Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DNM] test #3238 #3240

Closed
wants to merge 8 commits into from
Closed

[DNM] test #3238 #3240

wants to merge 8 commits into from

Conversation

trajan0x
Copy link
Contributor

@trajan0x trajan0x commented Oct 5, 2024

  • add fe-release label

  • fix label


Description
A clear and concise description of the features you're adding in this pull request.

Additional context
Add any other context about the problem you're solving.

Metadata

  • Fixes #[Link to Issue]

Summary by CodeRabbit

  • New Features
    • Introduced an automated labeling system for pull requests targeting the 'fe-release' branch, enhancing organization and visibility.
    • Added new API endpoints for retrieving active disputes and pending transactions that exceed a specified deadline.
    • Expanded GraphQL schema with new types and queries to support dispute handling.
    • Introduced a new event type for bridge proof disputes, enhancing event handling capabilities.
  • Documentation
    • Updated README for improved clarity and organization, including a new section on environment variables.
    • Enhanced OpenAPI documentation for new endpoints, detailing expected responses and usage.
    • Added a new section in the documentation for supported tokens organized by blockchain chain.
  • Bug Fixes
    • Improved data retrieval logic to ensure accurate responses for active proofs and disputes.
  • Chores
    • Updated changelog and package versioning for the @synapsecns/rfq-indexer-api and @synapsecns/bridge-docs packages.
    • Configured Renovate to ignore specific paths in dependency management.

698ba5b: docs preview link
aec7fa4: docs preview link

* add fe-release label

* fix label

---------

Co-authored-by: Trajan0x <trajan0x@users.noreply.github.com>
Copy link
Contributor

coderabbitai bot commented Oct 5, 2024

Walkthrough

The pull request modifies the workflow file .github/workflows/labeler.yml by adding a new step to the existing job pr-labeler. This step checks if the base reference of a pull request is 'fe-release' and, if true, applies the 'fe-release' label using the actions-ecosystem/action-add-labels@v1 action. The integration maintains the overall structure of the workflow. Additionally, updates are made to the changelog, README, and various controllers and queries within the @synapsecns/rfq-indexer-api package, enhancing functionality and documentation.

Changes

File Path Change Summary
.github/workflows/labeler.yml Added a new step to check for 'fe-release' base reference and apply 'fe-release' label.
packages/rfq-indexer/api/CHANGELOG.md Updated to include version 1.0.6 entry, indicating a version bump only.
packages/rfq-indexer/api/README.md Restructured API calls section for clarity, added "Env Vars" section.
packages/rfq-indexer/api/package.json Incremented version from 1.0.5 to 1.0.6.
packages/rfq-indexer/api/src/controllers/conflictingProofsController.ts Modified to filter for active proofs.
packages/rfq-indexer/api/src/controllers/disputesController.ts Added new controller for handling disputes.
packages/rfq-indexer/api/src/controllers/pendingTransactionsController.ts Enhanced existing controllers and added new ones for pending transactions.
packages/rfq-indexer/api/src/controllers/transactionIdController.ts Updated to include disputes in transaction queries.
packages/rfq-indexer/api/src/db/index.ts Added new event type BridgeProofDisputedEvents to the Database interface.
packages/rfq-indexer/api/src/graphql/queries/queries.graphql Added new type DisputedRelay and new query pendingTransactionsMissingRelayExceedDeadline.
packages/rfq-indexer/api/src/graphql/resolvers.ts Introduced new query function qDisputes and added disputedRelays resolver.
packages/rfq-indexer/api/src/graphql/types/events.graphql Added new type BridgeProofDisputedEvent.
packages/rfq-indexer/api/src/queries/disputesQueries.ts Introduced qDisputes function for querying disputes.
packages/rfq-indexer/api/src/queries/index.ts Added export for qDisputes.
packages/rfq-indexer/api/src/queries/proofsQueries.ts Modified qProofs to include activeOnly parameter.
packages/rfq-indexer/api/src/routes/disputesRoute.ts Added new route for handling disputes.
packages/rfq-indexer/api/src/routes/index.ts Registered new disputes route in the main router.
packages/rfq-indexer/api/src/routes/pendingTransactionsRoute.ts Added new route for transactions exceeding deadline.
packages/rfq-indexer/api/src/types/index.ts Introduced BridgeProofDisputedEvents interface and updated EventType.

Possibly related PRs

Suggested labels

size/xs

Suggested reviewers

  • trajan0x
  • ChiTimesChi

Poem

In the land of code, where rabbits play,
A label's added to brighten the day.
With branches checked, and tokens in hand,
The 'fe-release' label now takes a stand.
Hopping along in the workflow's embrace,
A joyful update in our coding space! 🐇✨


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions github-actions bot added M-ci Module: CI size/xs labels Oct 5, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (1)
.github/workflows/labeler.yml (1)

35-40: LGTM! Consider adding a comment for clarity.

The new step correctly implements the addition of the 'fe-release' label for pull requests targeting the 'fe-release' branch. This aligns well with the PR objective and enhances the automated labeling process.

For improved readability, consider adding a brief comment explaining the purpose of this step. For example:

      # Add 'fe-release' label for pull requests targeting the fe-release branch
      - name: Add 'fe-release' label
        if: github.event.pull_request.base.ref == 'fe-release'
        uses: actions-ecosystem/action-add-labels@v1
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          labels: 'fe-release'
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 4c073ff and 5c3686c.

📒 Files selected for processing (1)
  • .github/workflows/labeler.yml (1 hunks)

* fixing terminology

* rfq-indexer-docs

* Update RFQ Indexer API Readme (#3221)

* adding dispute events to ponder and linting

* numbering typo

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* small fixes

* sync with master

* API changes for disputes

* fixing pending txs missing proofs

* proof/dispute active & other tweaks/suggs

* dispute col rename originChain prefix

---------

Co-authored-by: defi-moses <jakedinero@protonmail.com>
Co-authored-by: Moses <103143573+Defi-Moses@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link

cloudflare-workers-and-pages bot commented Oct 7, 2024

Deploying sanguine-fe with  Cloudflare Pages  Cloudflare Pages

Latest commit: 4b49879
Status: ✅  Deploy successful!
Preview URL: https://e84a2524.sanguine-fe.pages.dev
Branch Preview URL: https://master.sanguine-fe.pages.dev

View logs

 - @synapsecns/rfq-indexer-api@1.0.6
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

🧹 Outside diff range and nitpick comments (11)
packages/rfq-indexer/api/src/controllers/disputesController.ts (2)

7-8: Consider enhancing error logging for better debugging.

The function declaration and overall error handling structure are good. However, to improve debugging and error tracing, consider logging more details about the error.

Here's a suggested improvement for error logging:

-    console.error('Error fetching active disputes:', error)
+    console.error('Error fetching active disputes:', error.message, '\nStack:', error.stack)

This change will provide more context about the error, including the error message and stack trace, which can be crucial for debugging in production environments.

Also applies to: 23-27


15-16: Add type annotation to improve type safety.

The query execution and result processing look good. However, adding a type annotation to the disputes variable would improve type safety and code readability.

Consider modifying the code as follows:

const results = await query.execute()
const disputes: Dispute[] = nest_results(results)

This assumes there's a Dispute interface or type defined elsewhere in your project. If not, you should create one to represent the structure of a dispute object.

packages/rfq-indexer/api/src/queries/disputesQueries.ts (2)

4-19: LGTM: Query construction is well-structured.

The query construction is logically sound and well-implemented. The left join effectively filters out stale or invalid disputes, and the field selection is clear with consistent aliasing.

Consider adding a brief comment explaining the purpose of the left join and field selection for improved code documentation.


1-26: Overall implementation is well-designed and efficient.

The qDisputes function provides a flexible and efficient way to query dispute events. The implementation is logically sound, with clear query construction and appropriate use of joins and filters.

Consider adding a brief function-level JSDoc comment to describe the purpose of qDisputes, its parameters, and return value. This would enhance code documentation and improve maintainability. For example:

/**
 * Constructs a query to fetch dispute events from the database.
 * @param {Object} options - Query options
 * @param {boolean} [options.activeOnly=false] - If true, only active disputes are returned
 * @returns {SelectQueryBuilder} A query builder object for further chaining or execution
 */
export const qDisputes = ({ activeOnly }: { activeOnly: boolean } = { activeOnly: false }) => {
  // ... existing implementation ...
}
packages/rfq-indexer/api/README.md (1)

10-32: Improved structure and clarity of API documentation.

The restructuring of the API calls section enhances readability and consistency. The new introductory text directing users to Swagger documentation is helpful.

Consider adding language specifications to the fenced code blocks for improved syntax highlighting. For example:

-     ```
+     ```bash
      curl http://localhost:3001/api/pending-transactions/missing-relay
      ```
🧰 Tools
🪛 Markdownlint

17-17: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


24-24: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


31-31: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

packages/rfq-indexer/api/src/routes/disputesRoute.ts (1)

7-62: Great job on the comprehensive OpenAPI documentation!

The documentation is thorough and follows OpenAPI standards, providing clear information about the endpoint's functionality and possible responses. The detailed schema for the successful response is particularly helpful for API consumers.

One minor suggestion:

Consider updating the description for the 404 response to match the endpoint's functionality. Currently, it says "No disputes found", but it might be more accurate to say "No active disputes found" to align with the endpoint's summary ("Get all active disputes").

-         description: No disputes found
+         description: No active disputes found
packages/rfq-indexer/api/src/graphql/queries/queries.graphql (2)

122-122: Approved: New query added, but consider improvements

The new pendingTransactionsMissingRelayExceedDeadline query is a valuable addition. However, consider the following suggestions to enhance its usability and clarity:

  1. Add a comment or description to explain the specific use case and criteria for "exceeding deadline".
  2. Consider adding optional arguments (e.g., deadline: Int) to make the query more flexible and reusable.

Example with improvements:

"""
Retrieves pending transactions missing a relay that have exceeded a specified deadline.
If no deadline is provided, a default value is used.
"""
pendingTransactionsMissingRelayExceedDeadline(deadline: Int): [PendingTransactionMissingRelay!]!

129-129: Approved: New disputedRelays query added, consider enhancements

The new disputedRelays query is a good addition that complements the newly introduced DisputedRelay type. To improve its usability and clarity, consider the following suggestions:

  1. Add a comment or description to explain what constitutes a disputed relay and how they are determined.
  2. Consider adding optional arguments (e.g., limit: Int, offset: Int) for pagination, or filter for more targeted queries.

Example with improvements:

"""
Retrieves a list of disputed relays. A relay is considered disputed when [explain criteria here].
"""
disputedRelays(limit: Int, offset: Int, filter: DisputedRelayFilter): [DisputedRelay!]!

Don't forget to define the DisputedRelayFilter input type if you choose to add filtering capabilities.

packages/rfq-indexer/api/src/types/index.ts (1)

84-92: LGTM! Consider aligning property names with other interfaces.

The new BridgeProofDisputedEvents interface looks good and follows the structure of other event interfaces in the file. It captures essential information for a disputed event.

For consistency with other interfaces, consider renaming chainId to originChainId and chain to originChain.

 export interface BridgeProofDisputedEvents {
   id: ColumnType<string>
   transactionId: ColumnType<string>
   blockNumber: ColumnType<bigint>
   blockTimestamp: ColumnType<number>
   transactionHash: ColumnType<string>
-  chainId: ColumnType<number>
-  chain: ColumnType<string>
+  originChainId: ColumnType<number>
+  originChain: ColumnType<string>
 }
packages/rfq-indexer/api/src/routes/pendingTransactionsRoute.ts (1)

150-190: LGTM: New route added correctly, with a minor suggestion

The new route for transactions that exceed the deadline has been added correctly. It follows the existing pattern for route definitions and includes comprehensive OpenAPI annotations. The route handler correctly uses the newly imported controller.

However, there's a minor typo in the 404 response description:

- *         description: No pending transactionst that exceed the deadline found
+ *         description: No pending transactions that exceed the deadline found
packages/rfq-indexer/api/src/queries/proofsQueries.ts (1)

9-10: Ensure database indexes exist on joined and filtered columns

For optimal query performance, please verify that indexes exist on the transactionId and blockTimestamp columns in both BridgeProofProvidedEvents and BridgeProofDisputedEvents tables. This will improve the efficiency of the join and filter operations.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 5c3686c and 327a3a4.

📒 Files selected for processing (18)
  • packages/rfq-indexer/api/CHANGELOG.md (1 hunks)
  • packages/rfq-indexer/api/README.md (1 hunks)
  • packages/rfq-indexer/api/package.json (1 hunks)
  • packages/rfq-indexer/api/src/controllers/conflictingProofsController.ts (2 hunks)
  • packages/rfq-indexer/api/src/controllers/disputesController.ts (1 hunks)
  • packages/rfq-indexer/api/src/controllers/pendingTransactionsController.ts (4 hunks)
  • packages/rfq-indexer/api/src/controllers/transactionIdController.ts (2 hunks)
  • packages/rfq-indexer/api/src/db/index.ts (2 hunks)
  • packages/rfq-indexer/api/src/graphql/queries/queries.graphql (1 hunks)
  • packages/rfq-indexer/api/src/graphql/resolvers.ts (3 hunks)
  • packages/rfq-indexer/api/src/graphql/types/events.graphql (5 hunks)
  • packages/rfq-indexer/api/src/queries/disputesQueries.ts (1 hunks)
  • packages/rfq-indexer/api/src/queries/index.ts (1 hunks)
  • packages/rfq-indexer/api/src/queries/proofsQueries.ts (1 hunks)
  • packages/rfq-indexer/api/src/routes/disputesRoute.ts (1 hunks)
  • packages/rfq-indexer/api/src/routes/index.ts (2 hunks)
  • packages/rfq-indexer/api/src/routes/pendingTransactionsRoute.ts (2 hunks)
  • packages/rfq-indexer/api/src/types/index.ts (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • packages/rfq-indexer/api/CHANGELOG.md
  • packages/rfq-indexer/api/package.json
🧰 Additional context used
🪛 Markdownlint
packages/rfq-indexer/api/README.md

17-17: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


24-24: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


31-31: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🔇 Additional comments (31)
packages/rfq-indexer/api/src/queries/index.ts (1)

3-3: LGTM! The new export is consistent with the file's structure.

The addition of the qDisputes export from ./disputesQueries aligns well with the existing pattern in this index file. This change appears to introduce a new query related to disputes, which could be part of a larger feature addition.

Let's verify the existence of the disputesQueries file and the qDisputes export:

packages/rfq-indexer/api/src/routes/index.ts (2)

8-8: LGTM: Import statement for disputesRoute

The import statement for disputesRoute is correctly added and follows the existing pattern in the file. It maintains consistency with other route imports in terms of naming convention and relative path usage.


17-17: LGTM: Route registration for disputes

The route registration for /disputes is correctly added and follows the existing pattern in the file. It maintains consistency with other route registrations and adheres to RESTful naming conventions.

To ensure the completeness of this change, please verify the implementation of disputesRoute. Run the following script to check its contents:

packages/rfq-indexer/api/src/db/index.ts (2)

25-25: LGTM! Verify the database schema.

The addition of BridgeProofDisputedEvents to the Database interface is consistent with the existing pattern and corresponds to the new import. This expands the database interface to include the new event type.

To ensure the database schema has been updated accordingly, run the following script:

✅ Verification successful

Database schema includes BridgeProofDisputedEvents as expected.

The search results confirm that BridgeProofDisputedEvents is properly integrated into the database schema across relevant migration and TypeScript files.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the database schema includes the new event type

# Test: Search for database migration files that might include the new event type
fd -e sql -e ts 'migration' | xargs rg 'BridgeProofDisputedEvents'

Length of output: 4021


10-10: LGTM! Verify the imported type.

The addition of BridgeProofDisputedEvents to the import statement is consistent with the existing pattern. This suggests a new event type is being introduced to the system.

To ensure the imported type is correctly defined, run the following script:

✅ Verification successful

Verify that BridgeProofDisputedEvents is defined as an interface.

The initial script searched for a type definition, but an interface was found instead. To confirm the definition, please run the following script:


Verification Successful: BridgeProofDisputedEvents is correctly defined as an interface.

The BridgeProofDisputedEvents interface is properly defined in packages/rfq-indexer/api/src/types/index.ts and is consistently utilized across the codebase without any issues.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the definition of BridgeProofDisputedEvents type

# Test: Search for the type definition in the types file
ast-grep --lang typescript --pattern 'export type BridgeProofDisputedEvents = $_'

Length of output: 4021


Script:

#!/bin/bash
# Description: Verify the definition of BridgeProofDisputedEvents as an interface

# Test: Search for the interface definition in the types file
ast-grep --lang typescript --pattern 'export interface BridgeProofDisputedEvents {'

Length of output: 783

packages/rfq-indexer/api/src/controllers/disputesController.ts (1)

1-5: Imports look good and follow best practices.

The necessary dependencies are imported correctly, including Express types, database connection, queries, and utility functions. The imports are concise and follow the best practice of destructuring specific imports.

packages/rfq-indexer/api/src/queries/disputesQueries.ts (3)

1-3: LGTM: Function signature and import look good.

The import statement and function signature are well-defined. The optional parameter activeOnly with a default value of false provides flexibility in query execution.


21-23: LGTM: Active disputes filter is correctly implemented.

The additional where clause for active disputes is logically sound. It effectively filters for disputes that don't have a corresponding entry in the BridgeProofProvidedEvents table when activeOnly is set to true.


25-26: LGTM: Query return is appropriate.

Returning the constructed query object is a good practice. It allows for further modifications or immediate execution by the caller, providing flexibility in query usage.

packages/rfq-indexer/api/src/controllers/conflictingProofsController.ts (3)

44-44: LGTM: Updated response message.

The response message has been appropriately updated to reflect that no active conflicting proofs were found. This change is consistent with the new focus on active proofs and provides clear feedback to the client.


47-47: LGTM: Updated error logging message.

The error logging message has been appropriately updated to reflect that the error occurs while fetching active conflicting proofs. This change is consistent with the new focus on active proofs and provides clear context for debugging.


16-16: LGTM: Filtering for active proofs.

The change to filter only active proofs is consistent with the updated functionality. This should improve the relevance of the data returned by the controller.

Let's verify if the qProofs function supports the activeOnly parameter:

packages/rfq-indexer/api/README.md (2)

38-42: Valuable addition of environment variables documentation.

The new "Env Vars" section provides crucial information for local testing and database connection. This addition enhances the README's usefulness for developers setting up the project.


Line range hint 1-42: Overall improvement in README structure and clarity.

The changes to this README file significantly enhance its usability:

  1. The API Calls section is now more consistently formatted and easier to read.
  2. The addition of the Env Vars section provides crucial setup information.
  3. The overall structure is more logical and user-friendly.

These improvements will help developers better understand and use the RFQ Indexer API.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~45-~45: Loose punctuation mark.
Context: ...## Important Scripts - yarn dev:local: Runs the API in development mode using ...

(UNLIKELY_OPENING_PUNCTUATION)

🪛 Markdownlint

17-17: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


24-24: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


31-31: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

packages/rfq-indexer/api/src/graphql/types/events.graphql (3)

Line range hint 1-1: LGTM: Addition of BigInt scalar type

The introduction of the BigInt scalar type is appropriate for handling large integer values commonly found in blockchain data. Its consistent usage across various event types (e.g., blockNumber, originAmount, destAmount) ensures proper representation of numerical data.


Line range hint 1-91: LGTM: Overall structure and consistency

The addition of BridgeProofDisputedEvent maintains the file's overall structure and naming conventions. The use of the BigInt scalar is consistent across all relevant fields, and the file structure remains clear and easy to understand. The new event type integrates well with the existing types, preserving the file's coherence.


83-91: Verify completeness of BridgeProofDisputedEvent fields

The new BridgeProofDisputedEvent type has been added successfully and follows the naming convention of other event types. It includes common fields such as id, transactionId, blockNumber, etc.

However, please verify if additional fields are needed for this event type. Other event types in this file often include fields like relayer, to, token, and amount. If these are relevant for a proof dispute event, consider adding them for consistency.

To help verify the completeness of the BridgeProofDisputedEvent fields, please run the following script:

This script will help us understand how BridgeProofDisputedEvent is used in the codebase and if there are any proof dispute-related operations that might require additional fields in the event type.

packages/rfq-indexer/api/src/routes/disputesRoute.ts (2)

1-5: LGTM: Imports and router setup are correct.

The imports and router setup follow best practices. The use of a separate controller file (disputesController) promotes good code organization and separation of concerns.


65-65: LGTM: Router export is correct.

The default export of the router is the standard way to make it available for use in other parts of the Express application.

packages/rfq-indexer/api/src/graphql/queries/queries.graphql (1)

115-118: LGTM: New type DisputedRelay added

The new DisputedRelay type is well-structured and consistent with the existing schema. It appropriately uses non-nullable fields for required information and references existing types.

packages/rfq-indexer/api/src/types/index.ts (1)

100-100: LGTM! EventType updated correctly.

The addition of 'DISPUTE' to the EventType union is consistent with the new BridgeProofDisputedEvents interface. This update allows the system to recognize and handle dispute events properly.

packages/rfq-indexer/api/src/routes/pendingTransactionsRoute.ts (2)

6-7: LGTM: Import statement updated correctly

The import statement has been updated to include the new controller pendingTransactionsMissingRelayExceedDeadlineController. This change is consistent with the new route being added and follows the existing naming convention.


Line range hint 1-191: Summary: Successful implementation of new 'exceed-deadline' route

The changes in this file successfully implement a new route for handling transactions that exceed a specified deadline. The modifications include:

  1. Adding a new import for the pendingTransactionsMissingRelayExceedDeadlineController.
  2. Implementing a new GET route at '/exceed-deadline' with appropriate OpenAPI annotations.

These changes enhance the API's functionality by providing a way to retrieve transactions that have exceeded their deadline, which aligns with the PR objectives. The implementation is consistent with the existing code structure and follows best practices.

packages/rfq-indexer/api/src/queries/proofsQueries.ts (1)

20-22: Conditional filtering based on activeOnly is correctly implemented

The logic for filtering proofs when activeOnly is true is implemented correctly and functions as expected.

packages/rfq-indexer/api/src/controllers/transactionIdController.ts (3)

4-4: Importing qDisputes is Appropriate

The addition of qDisputes to the import statement correctly incorporates dispute-related queries needed for the new functionality.


16-17: Verify Inconsistency in Active Status Filters for Proofs and Disputes

The query includes all proofs by setting activeOnly: false, thus displaying both active and inactive proofs. In contrast, it includes only active disputes by setting activeOnly: true. Please verify if this is intentional, as displaying inactive proofs but excluding inactive disputes might lead to inconsistent data representation.


26-26: Confirm Join Condition with the disputes Table

The addition of the left join with the disputes table using .leftJoin('disputes', 'transactionId_deposit', 'transactionId_dispute') should be verified to ensure that it correctly associates disputes with the corresponding deposits. Please confirm that the join keys are accurate and that this join will function as expected.

packages/rfq-indexer/api/src/controllers/pendingTransactionsController.ts (4)

4-11: Imports are updated with necessary query modules.

The additional imports (qDisputes, etc.) are appropriate and necessary for the controllers.


24-24: Ensure the 'activeOnly' parameter is handled correctly in qProofs.

Adding { activeOnly: true } to qProofs modifies its behavior to include only active proofs. Verify that the qProofs function supports this parameter and that this change aligns with the intended functionality.


65-65: Ensure the 'activeOnly' parameter is handled correctly in qProofs.

Similar to the previous controller, confirm that the qProofs function properly handles the { activeOnly: true } parameter and behaves as expected.


122-123: Confirm that filtering deposits to the last 7 days meets business requirements.

The added filter .where('blockTimestamp_deposit', '>', sevenDaysAgo) limits results to deposits from the last seven days. Ensure this aligns with business requirements and that older pending transactions are addressed appropriately elsewhere.

Comment on lines +9 to +13
const query = db
.with('disputes', () => qDisputes({activeOnly: true}))
.selectFrom('disputes')
.selectAll()
.orderBy('blockTimestamp_dispute', 'desc')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider optimizing the query by selecting only necessary columns.

The query construction looks good overall, using a CTE and proper ordering. However, selecting all columns (selectAll()) might not be the most efficient approach, especially if the client doesn't need all the data.

Consider modifying the query to select only the columns that are actually needed by the client. This can improve query performance and reduce data transfer. For example:

.selectFrom('disputes')
.select(['id', 'status', 'blockTimestamp_dispute', /* other necessary columns */])

This change would require knowing which specific columns are needed for the disputes data in your application.

Comment on lines +18 to +22
if (disputes && disputes.length > 0) {
res.json(disputes)
} else {
res.status(200).json({ message: 'No active disputes found' })
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider making the response structure consistent for both cases.

The response handling covers both cases (disputes found and not found) appropriately. However, the response structure is inconsistent between the two cases.

To improve API consistency, consider using the same structure for both cases. Here's a suggested modification:

if (disputes && disputes.length > 0) {
  res.json({ disputes })
} else {
  res.json({ disputes: [], message: 'No active disputes found' })
}

This change ensures that the client always receives an object with a disputes property (an array, which may be empty) and optionally a message property. This consistency can make it easier for clients to handle the response.

* message:
* type: string
*/
router.get('/', disputesController)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

LGTM: Route definition is correct and concise.

The route definition matches the OpenAPI documentation and uses the imported disputesController as the handler, which is a good practice for separation of concerns.

Consider adding error handling middleware to catch any errors thrown by the controller:

import { ErrorRequestHandler } from 'express';

const errorHandler: ErrorRequestHandler = (err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({ message: 'An unexpected error occurred' });
};

router.get('/', disputesController);
router.use(errorHandler);

This would ensure that any unhandled errors in the controller are caught and returned as a 500 response, improving the robustness of the API.

@@ -1,15 +1,25 @@
import { db } from '../db'

// typical fields to return for a BridgeProofProvided event when it is joined to a BridgeRequest
export const qProofs = () => {
return db
export const qProofs = ({ activeOnly}: { activeOnly: boolean} = { activeOnly: false}) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Simplify the function signature for better readability

The current function signature can be simplified by setting the default value directly in the destructured parameter and making the type optional. This enhances readability.

Here is a suggested change:

-export const qProofs = ({ activeOnly}: { activeOnly: boolean} = { activeOnly: false}) => {
+export const qProofs = ({ activeOnly = false }: { activeOnly?: boolean } = {}) => {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const qProofs = ({ activeOnly}: { activeOnly: boolean} = { activeOnly: false}) => {
export const qProofs = ({ activeOnly = false }: { activeOnly?: boolean } = {}) => {

.leftJoin('claims', 'transactionId_deposit', 'transactionId_claim')
.leftJoin('refunds', 'transactionId_deposit', 'transactionId_refund')
.selectAll('deposits')
.selectAll('relays')
.selectAll('proofs')
.selectAll('disputes')
.selectAll('claims')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Specify Fields When Selecting from disputes to Prevent Sensitive Data Exposure

Using .selectAll('disputes') selects all columns from the disputes table, which may inadvertently include sensitive or unnecessary data in the API response. Consider specifying only the required fields to ensure that sensitive information is not exposed.

Apply this diff to specify the fields to select from the disputes table:

-              .selectAll('disputes')
+              .selectFrom('disputes').select(['field1', 'field2', 'field3'])

Replace ['field1', 'field2', 'field3'] with the specific fields that should be included in the response.

Committable suggestion was skipped due to low confidence.

Comment on lines +140 to +167
export const pendingTransactionsMissingRelayExceedDeadlineController = async (
req: Request,
res: Response
) => {
try {
const query = db
.with('deposits', () => qDeposits())
.with('relays', () => qRelays())
.with('refunds', () => qRefunds())
.with(
'combined',
(qb) =>
qb
.selectFrom('deposits')
.selectAll('deposits')
.leftJoin('relays', 'transactionId_deposit', 'transactionId_relay')
.leftJoin(
'refunds',
'transactionId_deposit',
'transactionId_refund'
)
.where('transactionId_relay', 'is', null) // is not relayed
.where('transactionId_refund', 'is', null) // is not refunded
)
.selectFrom('combined')
.selectAll()
.orderBy('blockTimestamp_deposit', 'desc')
.where('blockTimestamp_deposit', '<=', sevenDaysAgo)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider refactoring to reduce code duplication between controllers.

The pendingTransactionsMissingRelayController and pendingTransactionsMissingRelayExceedDeadlineController have similar structures with differences in the where clauses. Refactoring common logic into shared functions can improve maintainability and reduce redundancy.

Comment on lines +135 to +137
console.error('Error fetching pending transactions missing relay:', error)
res.status(500).json({ message: 'Internal server error' })
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Differentiate error messages for clearer debugging.

The error messages in the catch blocks are identical across controllers. To facilitate easier debugging, update the error messages to reflect the specific controller's context.

Suggested changes:

In pendingTransactionsMissingRelayExceedDeadlineController, update the error logging:

- console.error('Error fetching pending transactions missing relay:', error)
+ console.error('Error fetching pending transactions missing relay exceeding deadline:', error)

And update the response message in the else block:

- .json({ message: 'No pending transactions missing relay found' })
+ .json({ message: 'No pending transactions missing relay exceeding deadline found' })

Also applies to: 166-167

Comment on lines +91 to +103
// typical fields to return for a BridgeProofDisputed event when it is joined to a BridgeRequest
const qDisputes = () => {
return db
.selectFrom('BridgeProofDisputedEvents')
.select([
'BridgeProofDisputedEvents.transactionId as transactionId_dispute',
'BridgeProofDisputedEvents.blockNumber as blockNumber_dispute',
'BridgeProofDisputedEvents.blockTimestamp as blockTimestamp_dispute',
'BridgeProofDisputedEvents.transactionHash as transactionHash_dispute',
'BridgeProofDisputedEvents.originChainId as originChainId_dispute',
'BridgeProofDisputedEvents.originChain as originChain_dispute',
])
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Include the relayer field in qDisputes for consistency

The qDisputes function is missing the relayer field, which is present in similar query functions like qProofs. Including the relayer field ensures consistency across queries and provides complete data for downstream processes.

Apply this diff to include the relayer field:

 const qDisputes = () => {
   return db
     .selectFrom('BridgeProofDisputedEvents')
     .select([
       'BridgeProofDisputedEvents.transactionId as transactionId_dispute',
       'BridgeProofDisputedEvents.blockNumber as blockNumber_dispute',
       'BridgeProofDisputedEvents.blockTimestamp as blockTimestamp_dispute',
       'BridgeProofDisputedEvents.transactionHash as transactionHash_dispute',
+      'BridgeProofDisputedEvents.relayer as relayer_dispute',
       'BridgeProofDisputedEvents.originChainId as originChainId_dispute',
       'BridgeProofDisputedEvents.originChain as originChain_dispute',
     ])
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// typical fields to return for a BridgeProofDisputed event when it is joined to a BridgeRequest
const qDisputes = () => {
return db
.selectFrom('BridgeProofDisputedEvents')
.select([
'BridgeProofDisputedEvents.transactionId as transactionId_dispute',
'BridgeProofDisputedEvents.blockNumber as blockNumber_dispute',
'BridgeProofDisputedEvents.blockTimestamp as blockTimestamp_dispute',
'BridgeProofDisputedEvents.transactionHash as transactionHash_dispute',
'BridgeProofDisputedEvents.originChainId as originChainId_dispute',
'BridgeProofDisputedEvents.originChain as originChain_dispute',
])
}
// typical fields to return for a BridgeProofDisputed event when it is joined to a BridgeRequest
const qDisputes = () => {
return db
.selectFrom('BridgeProofDisputedEvents')
.select([
'BridgeProofDisputedEvents.transactionId as transactionId_dispute',
'BridgeProofDisputedEvents.blockNumber as blockNumber_dispute',
'BridgeProofDisputedEvents.blockTimestamp as blockTimestamp_dispute',
'BridgeProofDisputedEvents.transactionHash as transactionHash_dispute',
'BridgeProofDisputedEvents.relayer as relayer_dispute',
'BridgeProofDisputedEvents.originChainId as originChainId_dispute',
'BridgeProofDisputedEvents.originChain as originChain_dispute',
])
}

Comment on lines +496 to +518
disputedRelays: async () => {
const query = db
.with('deposits', () => qDeposits())
.with('relays', () => qRelays())
.with('proofs', () => qProofs())
.with('disputes', () => qDisputes())
.with('combined', (qb) =>
qb
.selectFrom('proofs')
.leftJoin(
'disputes',
'transactionId_proof',
'transactionId_dispute'
)
.selectAll('proofs')
.selectAll('disputes')
)
.selectFrom('combined')
.selectAll()
.orderBy('blockTimestamp_proof', 'desc')

return nest_results(await query.execute())
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

⚠️ Potential issue

Join deposits and relays in disputedRelays for comprehensive data

The disputedRelays resolver currently joins proofs with disputes but does not include data from deposits and relays. Joining these tables provides a complete view of the transactions and ensures all relevant data is available for the nested results.

Apply this diff to include deposits and relays in the query:

 const query = db
   .with('deposits', () => qDeposits())
   .with('relays', () => qRelays())
   .with('proofs', () => qProofs())
   .with('disputes', () => qDisputes())
   .with('combined', (qb) =>
     qb
-      .selectFrom('proofs')
+      .selectFrom('deposits')
+      .innerJoin('proofs', 'transactionId_deposit', 'transactionId_proof')
+      .leftJoin('relays', 'transactionId_deposit', 'transactionId_relay')
       .leftJoin('disputes', 'transactionId_proof', 'transactionId_dispute')
       .selectAll('deposits')
       .selectAll('proofs')
+      .selectAll('relays')
       .selectAll('disputes')
   )

This change ensures that data from deposits and relays are included, providing a more complete dataset.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
disputedRelays: async () => {
const query = db
.with('deposits', () => qDeposits())
.with('relays', () => qRelays())
.with('proofs', () => qProofs())
.with('disputes', () => qDisputes())
.with('combined', (qb) =>
qb
.selectFrom('proofs')
.leftJoin(
'disputes',
'transactionId_proof',
'transactionId_dispute'
)
.selectAll('proofs')
.selectAll('disputes')
)
.selectFrom('combined')
.selectAll()
.orderBy('blockTimestamp_proof', 'desc')
return nest_results(await query.execute())
},
disputedRelays: async () => {
const query = db
.with('deposits', () => qDeposits())
.with('relays', () => qRelays())
.with('proofs', () => qProofs())
.with('disputes', () => qDisputes())
.with('combined', (qb) =>
qb
.selectFrom('deposits')
.innerJoin('proofs', 'transactionId_deposit', 'transactionId_proof')
.leftJoin('relays', 'transactionId_deposit', 'transactionId_relay')
.leftJoin(
'disputes',
'transactionId_proof',
'transactionId_dispute'
)
.selectAll('deposits')
.selectAll('proofs')
.selectAll('relays')
.selectAll('disputes')
)
.selectFrom('combined')
.selectAll()
.orderBy('blockTimestamp_proof', 'desc')
return nest_results(await query.execute())
},

Comment on lines +237 to +249
.unionAll(
db
.selectFrom('BridgeProofDisputedEvents')
.select([
'BridgeProofDisputedEvents.id',
'BridgeProofDisputedEvents.transactionId',
'BridgeProofDisputedEvents.blockNumber',
'BridgeProofDisputedEvents.blockTimestamp',
'BridgeProofDisputedEvents.transactionHash',
'BridgeProofDisputedEvents.originChainId',
'BridgeProofDisputedEvents.originChain',
])
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

⚠️ Potential issue

Inconsistent Field Selection Detected in Unified Event Queries

The selected fields in the unioned event queries do not match the expected fields based on BridgeRequestEvents. Specifically:

  • BridgeProofDisputedEvents

    • Extra fields:
      • blockNumberasblockNumber_dispute
      • blockTimestampasblockTimestamp_dispute
      • originChainIdasoriginChainId_dispute
      • originChainasoriginChain_dispute
      • transactionHashastransactionHash_dispute
      • transactionIdastransactionId_dispute
  • BridgeRelayedEvents

    • Extra fields:
      • blockNumberasblockNumber_relay
      • blockTimestampasblockTimestamp_relay
      • relayerasrelayer_relay
      • toasto_relay
      • transactionHashastransactionHash_relay
      • transactionIdastransactionId_relay
  • BridgeProofProvidedEvents

    • Extra fields:
      • blockNumberasblockNumber_proof
      • blockTimestampasblockTimestamp_proof
      • relayerasrelayer_proof
      • transactionHashastransactionHash_proof
      • transactionIdastransactionId_proof
  • BridgeDepositClaimedEvents

    • Extra fields:
      • amountFormattedasamountFormatted_claim
      • blockNumberasblockNumber_claim
      • blockTimestampasblockTimestamp_claim
      • relayerasrelayer_claim
      • toasto_claim
      • transactionHashastransactionHash_claim
      • transactionIdastransactionId_claim
  • BridgeDepositRefundedEvents

    • Extra fields:
      • amountFormattedasamountFormatted_refund
      • blockNumberasblockNumber_refund
      • blockTimestampasblockTimestamp_refund
      • toasto_refund
      • transactionHashastransactionHash_refund
      • transactionIdastransactionId_refund

Action Required:

  • Align the field selections in all unioned event queries to match the expected fields from BridgeRequestEvents.
  • Remove any extra or inconsistently aliased fields.
  • Ensure that all event queries maintain schema consistency to prevent processing issues.
🔗 Analysis chain

Ensure consistent field selection in unified event queries

When adding BridgeProofDisputedEvents to the events query, verify that the selected fields match those of the other event queries to maintain schema consistency. Inconsistent fields can lead to issues when processing the unified results.

Run the following script to compare the selected fields across all event queries:

This script will highlight any discrepancies in the selected fields.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that all unioned queries in the 'events' query select consistent fields.

# Expected fields based on 'BridgeRequestEvents' selection
expected_fields=$(cat <<EOF
BridgeRequestEvents.id
BridgeRequestEvents.transactionId
BridgeRequestEvents.blockNumber
BridgeRequestEvents.blockTimestamp
BridgeRequestEvents.transactionHash
BridgeRequestEvents.originChainId
BridgeRequestEvents.originChain
EOF
)

# Function to extract selected fields from a query
extract_fields() {
  rg -A 10 "$1" packages/rfq-indexer/api/src/graphql/resolvers.ts | \
  rg "select(\[|\()" -A 10 | \
  sed -n '/select/,$p' | \
  tr -d ' \t' | \
  grep -v '^$' | \
  grep -v 'select' | \
  grep -v '\[' | \
  grep -v '\]' | \
  grep -v '),' | \
  sed 's/,$//' | \
  sort
}

# Extract fields from each event query
fields_disputed=$(extract_fields "selectFrom.*BridgeProofDisputedEvents")
fields_relays=$(extract_fields "selectFrom.*BridgeRelayedEvents")
fields_proofs=$(extract_fields "selectFrom.*BridgeProofProvidedEvents")
fields_claims=$(extract_fields "selectFrom.*BridgeDepositClaimedEvents")
fields_refunds=$(extract_fields "selectFrom.*BridgeDepositRefundedEvents")

# Compare fields
echo "Comparing selected fields in 'BridgeProofDisputedEvents' to expected fields:"
diff <(echo "$expected_fields" | sort) <(echo "$fields_disputed")

echo "Ensure other event queries also match the expected fields."

Length of output: 7234


Script:

#!/bin/bash
# Description: Verify that all unioned queries in the 'events' query select consistent fields without using process substitution.

# Expected fields based on 'BridgeRequestEvents' selection
cat <<EOF > expected_fields.txt
BridgeRequestEvents.id
BridgeRequestEvents.transactionId
BridgeRequestEvents.blockNumber
BridgeRequestEvents.blockTimestamp
BridgeRequestEvents.transactionHash
BridgeRequestEvents.originChainId
BridgeRequestEvents.originChain
EOF

# Function to extract selected fields from a query
extract_fields() {
  local query_pattern="$1"
  rg -A 10 "$query_pattern" packages/rfq-indexer/api/src/graphql/resolvers.ts | \
  rg "select(\[|\()" -A 10 | \
  sed -n '/select/,$p' | \
  tr -d ' \t' | \
  grep -v '^$' | \
  grep -v 'select' | \
  grep -v '\[' | \
  grep -v '\]' | \
  grep -v '),' | \
  sed 's/,$//' | \
  sort > "$2"
}

# Extract fields from each event query
extract_fields "selectFrom.*BridgeProofDisputedEvents" fields_disputed.txt
extract_fields "selectFrom.*BridgeRelayedEvents" fields_relays.txt
extract_fields "selectFrom.*BridgeProofProvidedEvents" fields_proofs.txt
extract_fields "selectFrom.*BridgeDepositClaimedEvents" fields_claims.txt
extract_fields "selectFrom.*BridgeDepositRefundedEvents" fields_refunds.txt

# Compare fields for BridgeProofDisputedEvents
diff expected_fields.txt fields_disputed.txt > diff_disputed.txt
echo "Comparing selected fields in 'BridgeProofDisputedEvents' to expected fields:"
cat diff_disputed.txt

# Compare fields for BridgeRelayedEvents
diff expected_fields.txt fields_relays.txt > diff_relays.txt
echo "Comparing selected fields in 'BridgeRelayedEvents' to expected fields:"
cat diff_relays.txt

# Compare fields for BridgeProofProvidedEvents
diff expected_fields.txt fields_proofs.txt > diff_proofs.txt
echo "Comparing selected fields in 'BridgeProofProvidedEvents' to expected fields:"
cat diff_proofs.txt

# Compare fields for BridgeDepositClaimedEvents
diff expected_fields.txt fields_claims.txt > diff_claims.txt
echo "Comparing selected fields in 'BridgeDepositClaimedEvents' to expected fields:"
cat diff_claims.txt

# Compare fields for BridgeDepositRefundedEvents
diff expected_fields.txt fields_refunds.txt > diff_refunds.txt
echo "Comparing selected fields in 'BridgeDepositRefundedEvents' to expected fields:"
cat diff_refunds.txt

echo "Ensure other event queries also match the expected fields."

Length of output: 8147

Copy link

codecov bot commented Oct 7, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Please upload report for BASE (fe-release@b2dae77). Learn more about missing BASE report.
Report is 2 commits behind head on fe-release.

Additional details and impacted files
@@               Coverage Diff                @@
##             fe-release       #3240   +/-   ##
================================================
  Coverage              ?   90.43902%           
================================================
  Files                 ?          54           
  Lines                 ?        1025           
  Branches              ?          82           
================================================
  Hits                  ?         927           
  Misses                ?          95           
  Partials              ?           3           
Flag Coverage Δ
packages 90.43902% <ø> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

* Revert "Hide Routes component (#3225)"

This reverts commit b93ba4b.

* Fixes img height width bug

* Refactor for checks, already imported value

---------

Co-authored-by: Trajan0x <trajan0x@users.noreply.github.com>
Co-authored-by: abtestingalpha <abtestingalpha@gmail.com>
 - @synapsecns/bridge-docs@0.3.8
Copy link

codecov bot commented Oct 7, 2024

Bundle Report

Changes will decrease total bundle size by 4.15MB (-11.65%) ⬇️. This is within the configured threshold ✅

Detailed changes
Bundle name Size Change
sdk-router-@synapsecns/sdk-router-esm* 255.08kB 426 bytes (0.17%) ⬆️
sdk-router-@synapsecns/sdk-router-cjs* 117.47kB 234 bytes (0.2%) ⬆️
explorer-ui-server-cjs* 708.77kB 157.29kB (-18.16%) ⬇️
explorer-ui-client-array-push* 2.15MB 162.81kB (-7.04%) ⬇️
synapse-interface-client-array-push* 7.38MB 100.07kB (1.38%) ⬆️
synapse-interface-server-cjs* 1.65MB 150.9kB (10.1%) ⬆️
widget-cjs-esm* 271.27kB 2.03kB (-0.74%) ⬇️
docs-bridge-client-array-push 7.18MB 724.77kB (-9.17%) ⬇️
docs-bridge-server-cjs 11.17MB 3.71MB (-24.92%) ⬇️
synapse-constants-esm-cjs* 174.63kB 174.63kB (100%) ⬆️
synapse-constants-cjs-esm* 174.18kB 174.18kB (100%) ⬆️

ℹ️ *Bundle size includes cached data from a previous commit

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (2)
docs/bridge/src/components/Routes.tsx (2)

6-6: Improved chain image rendering

The change to use an <img> tag for rendering the chain image is a good improvement. It simplifies the code and makes it more consistent with standard HTML practices.

Consider adding error handling for cases where chainImg might be undefined:

-<img width="28" height="28" src={chainImg} alt={chain.name} />
+{chainImg && <img width="28" height="28" src={chainImg} alt={chain.name} />}

This will prevent rendering an empty image if chainImg is not available for some reason.

Also applies to: 18-18


32-33: Improved token image rendering

The change to use an <img> tag for rendering the token image is a good improvement. It simplifies the code and makes it more consistent with the chain image rendering approach.

Consider adding error handling for cases where token.icon might be undefined:

-<img width="16" height="16" src={token.icon} alt={token.symbol} />{' '}
+{token.icon && <img width="16" height="16" src={token.icon} alt={token.symbol} />}{' '}

This will prevent rendering an empty image if token.icon is not available for some reason.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between aab8e56 and 8311329.

📒 Files selected for processing (8)
  • docs/bridge/CHANGELOG.md (1 hunks)
  • docs/bridge/docs/01-About/03-Routes.md (1 hunks)
  • docs/bridge/docs/02-Bridge/04-Code-Examples.md (1 hunks)
  • docs/bridge/docs/02-Bridge/05-Supported-Routes.md (0 hunks)
  • docs/bridge/docs/02-Bridge/_05-Supported-Routes.md (0 hunks)
  • docs/bridge/docs/02-Bridge/index.md (1 hunks)
  • docs/bridge/package.json (1 hunks)
  • docs/bridge/src/components/Routes.tsx (3 hunks)
💤 Files with no reviewable changes (2)
  • docs/bridge/docs/02-Bridge/05-Supported-Routes.md
  • docs/bridge/docs/02-Bridge/_05-Supported-Routes.md
✅ Files skipped from review due to trivial changes (3)
  • docs/bridge/CHANGELOG.md
  • docs/bridge/docs/02-Bridge/04-Code-Examples.md
  • docs/bridge/package.json
🧰 Additional context used
🔇 Additional comments (3)
docs/bridge/docs/01-About/03-Routes.md (3)

3-5: LGTM! Clear and informative content.

The markdown content is well-structured and provides clear information about the purpose of the page. The link to the Synapse Bridge is correctly formatted.


7-7: LGTM! Verify the Routes component output.

The Routes component is correctly rendered using JSX syntax. Ensure that the markdown processor used in this project supports JSX syntax.

To verify the component's functionality and output, please manually check the rendered page in the development environment or staging site. Confirm that:

  1. The component renders without errors.
  2. It displays the expected list of supported tokens organized by blockchain chain.
  3. The information presented is accurate and up-to-date.

1-1: LGTM! Verify the imported component.

The import statement looks correct. However, it's important to ensure that the Routes component exists at the specified path.

Run the following script to verify the existence of the Routes component:

✅ Verification successful

Verified: The Routes component exists at docs/bridge/src/components/Routes.tsx.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the existence of the Routes component

# Test: Check if the Routes component file exists
fd --type f --full-path '.*src/components/Routes.(js|jsx|ts|tsx)$'

Length of output: 106

export default () =>
Object.entries(BRIDGABLE_TOKENS).map(([id, tokens]) => {
const chain = CHAINS_BY_ID[id]
const chainImg = chain.chainImg({ width: 28, height: 28 })
const chain = CHAINS.CHAINS_BY_ID[id]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

⚠️ Potential issue

Incorrect usage of CHAINS_BY_ID

The CHAINS object does not contain a CHAINS_BY_ID property. You should reference CHAINS_BY_ID directly instead of accessing it via CHAINS.

  • Suggested change in docs/bridge/src/components/Routes.tsx:

    - const chain = CHAINS.CHAINS_BY_ID[id]
    + const chain = CHAINS_BY_ID[id]
🔗 Analysis chain

Incorrect chain access method

The current implementation attempts to access CHAINS.CHAINS_BY_ID[id], which is likely incorrect. Based on the previous implementation and the typical structure of such constants, it's probable that CHAINS_BY_ID is a separate object, not a property of CHAINS.

Consider reverting to the previous access method or ensure that the CHAINS object has the correct structure. If CHAINS_BY_ID is a separate export from the constants file, you should use:

-const chain = CHAINS.CHAINS_BY_ID[id]
+const chain = CHAINS_BY_ID[id]

If CHAINS_BY_ID is no longer available, please provide more context on how chain information should be accessed.

To verify the correct structure, we can check the contents of the constants file:


Constants file not found

The shell script did not locate a constants file containing synapse-constants. To verify the structure of CHAINS, we need to identify where it is defined in the codebase.


Failed to locate CHAINS definitions

The previous shell script failed to recognize the tsx file type. To locate the definitions of CHAINS and CHAINS_BY_ID, we need to adjust the search parameters.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check the structure of CHAINS in the constants file

# Find the constants file
constants_file=$(fd -e ts -e js -e tsx -e jsx -t f synapse-constants)

if [ -n "$constants_file" ]; then
    echo "Contents of the constants file:"
    cat "$constants_file"
else
    echo "Constants file not found."
fi

Length of output: 149


Script:

#!/bin/bash
# Description: Find the definition of CHAINS and CHAINS_BY_ID in the codebase

# Search for CHAINS definition
echo "Searching for 'CHAINS' definition:"
rg 'CHAINS\s*=' --type ts --type tsx --type js --type jsx

# Search for 'CHAINS_BY_ID' definition
echo "Searching for 'CHAINS_BY_ID' definition:"
rg 'CHAINS_BY_ID\s*=' --type ts --type tsx --type js --type jsx

Length of output: 363


Script:

#!/bin/bash
# Description: Find the definition of CHAINS and CHAINS_BY_ID in the codebase without specifying file types

# Search for CHAINS definition
echo "Searching for 'CHAINS' definition:"
rg 'CHAINS\s*='

# Search for 'CHAINS_BY_ID' definition:
rg 'CHAINS_BY_ID\s*='

Length of output: 1524

@@ -7,7 +7,7 @@ import SVGBridge from '@site/src/components/SVGBridge'

# Synapse Bridge

The [Synapse Bridge](https://synapseprotocol.com) and [Solana Bridge](https://solana.synapseprotocol.com/) seamlessly swap on-chain assets between [20+ EVM and non-EVM blockchains](./Supported-Routes) in a safe and secure manner.
The [Synapse Bridge](https://synapseprotocol.com) and [Solana Bridge](https://solana.synapseprotocol.com/) seamlessly swap on-chain assets between [20+ EVM and non-EVM blockchains](/docs/About/Routes) in a safe and secure manner.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Invalid link detected in documentation.

The link /docs/About/Routes in docs/bridge/docs/02-Bridge/index.md does not point to an existing documentation page. Please update the link to docs/bridge/docs/01-About/03-Routes.md to ensure it directs to the correct location.

🔗 Analysis chain

Approve link update with verification request.

The update to the documentation link appears to be an improvement in the overall structure. However, please ensure that the new link '/docs/About/Routes' is valid and leads to the correct page containing information about the supported blockchains.

To verify the existence of the new documentation page, please run the following script:

If the script doesn't find the file, please create it or update the link to the correct location.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if the new Routes documentation file exists

# Test: Search for the Routes documentation file
fd -t f 'Routes.md' docs/About

Length of output: 128


Script:

#!/bin/bash
# Description: Search for Routes.md in the entire repository to verify its existence and correct path.

fd -t f 'Routes.md'

Length of output: 58

…[SLT-233] (#3215)

* feat: add `callParams`

* feat: scaffold `IFastBridgeRecipient`

* feat: add `callParams` to `BridgeTransactionV2`

* test: skip `getBridgeTransaction` V2 test for now

* test: add coverage for SRC arbitrary calls

* feat: check callParams length when bridging

* test: non-payable ETH recipient

* test: no-op contract recipient

* test: incorrect recipients cases (does not affect base tests)

* test: define cases for arbitrary call

* feat: update relay logic with arbitrary calls

* feat: checked call of the recipient hook function

* test: refactor state setup

* refactor: better comments in `relay`

* docs: add a TODO note wrt encoding changes
 - @synapsecns/contracts-rfq@0.7.0
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 14

🧹 Outside diff range and nitpick comments (30)
packages/contracts-rfq/test/mocks/NoOpContract.sol (1)

4-8: LGTM: Well-structured mock contract with a minor suggestion.

The NoOpContract is well-implemented for its purpose as a mock that can receive ETH. The receive function is correctly defined, and the comment explains its purpose clearly.

Consider adding a @dev tag to the comment to follow common Solidity documentation practices:

-    /// @notice Mock needs to accept ETH
+    /// @dev Mock contract that can receive ETH
+    /// @notice Allows the contract to receive ETH
     receive() external payable {}
packages/contracts-rfq/contracts/interfaces/IFastBridgeRecipient.sol (1)

4-12: Approve interface and function declaration, suggest adding NatSpec comments.

The interface IFastBridgeRecipient and its function fastBridgeTransferReceived are well-defined. The function is correctly marked as external and payable, which allows it to be called from other contracts and receive Ether. The bytes4 return type is appropriate for returning a function selector or acknowledging successful execution.

Consider adding NatSpec comments to provide more context about the interface and function's purpose, parameters, and return value. This would improve the contract's documentation and make it more developer-friendly. For example:

/// @title IFastBridgeRecipient
/// @notice Interface for contracts that can receive tokens via a fast bridge
interface IFastBridgeRecipient {
    /// @notice Called when tokens are received via a fast bridge
    /// @param token The address of the token being transferred
    /// @param amount The amount of tokens being transferred
    /// @param callParams Additional parameters for the transfer
    /// @return bytes4 A function selector or acknowledgment of the transfer
    function fastBridgeTransferReceived(
        address token,
        uint256 amount,
        bytes memory callParams
    )
        external
        payable
        returns (bytes4);
}
packages/contracts-rfq/test/mocks/NonPayableRecipient.sol (2)

4-5: LGTM: Clear documentation and appropriate naming.

The contract is well-documented, clearly stating its purpose as a mock for testing and warning against production use. The name NonPayableRecipient accurately reflects its nature.

Consider adding a brief explanation of why this implementation is incorrect, to further clarify its purpose in testing scenarios.


6-9: LGTM: Function implementation serves its purpose as a mock.

The fastBridgeTransferReceived function is correctly implemented for its purpose as a mock:

  • It matches the expected interface.
  • The pure modifier is appropriate.
  • Returning the function selector is a common pattern for interface implementations.

The comment about incorrect implementation is crucial for understanding the mock's purpose.

Consider adding a @dev comment explaining why returning the function selector is the expected behavior for this mock. This would provide more context for developers unfamiliar with this pattern.

packages/contracts-rfq/test/mocks/NoReturnValueRecipient.sol (2)

4-4: Consider using a more specific solhint-disable directive.

The current solhint-disable directive disables all linter rules for the entire file. It's generally better to disable only specific rules that are necessary to ignore. If you need to disable multiple rules, you can list them explicitly.

For example:

// solhint-disable-next-line no-empty-blocks, avoid-low-level-calls

Or for multiple lines:

/* solhint-disable no-empty-blocks, avoid-low-level-calls */
// ... code ...
/* solhint-enable no-empty-blocks, avoid-low-level-calls */

11-12: The fastBridgeTransferReceived function is correctly implemented for its intended testing purpose.

The function is correctly set up as an external, payable function with the appropriate parameters. The empty implementation is intentional, as stated in the comment, to simulate an incorrect implementation for testing purposes.

A minor suggestion to improve the NatSpec comment:

- /// @notice Incorrectly implemented - method does not return anything.
+ /// @notice Incorrectly implemented - method does not return anything, simulating a contract that fails to implement the expected interface.

This provides more context about why the lack of a return value is considered "incorrect" in this mock.

packages/contracts-rfq/test/FastBridgeV2.GasBench.Dst.Excl.t.sol (1)

Line range hint 11-14: Consider adding an explanatory comment for the setUp function

While the setUp function implementation looks good, it might be beneficial to add a comment explaining why you're skipping half of the EXCLUSIVITY_PERIOD. This would enhance the readability and maintainability of the test, making it easier for other developers to understand the test setup and its purpose.

Example comment:

function setUp() public virtual override {
    super.setUp();
    // Skip half of the exclusivity period to test behavior in the middle of the exclusivity window
    skip({time: EXCLUSIVITY_PERIOD / 2});
}
packages/contracts-rfq/contracts/interfaces/IFastBridgeV2Errors.sol (2)

6-6: LGTM! Consider adding parameters for improved debugging.

The CallParamsLengthAboveMax error is a good addition for handling cases where call parameters exceed a maximum length.

Consider adding parameters to provide more context, such as:

error CallParamsLengthAboveMax(uint256 actualLength, uint256 maxLength);

This would make debugging easier by providing specific information about the violation.


14-14: LGTM! Consider adding parameters for more detailed error reporting.

The RecipientIncorrectReturnValue error is a valuable addition for handling cases where a recipient returns an incorrect value.

To enhance debugging capabilities, consider adding parameters to provide more context:

error RecipientIncorrectReturnValue(bytes expectedValue, bytes actualValue);

This would allow for more precise error reporting and easier troubleshooting.

packages/contracts-rfq/test/mocks/RecipientMock.sol (2)

6-9: LGTM: Well-structured contract declaration with appropriate warning.

The contract declaration and receive function are correctly implemented. The warning comment about not using in production is a good practice for test contracts.

Consider adding a more detailed comment explaining the purpose of this mock contract and how it's intended to be used in tests. This can help other developers understand its role in the testing suite more quickly.


11-14: LGTM: Correct implementation of fastBridgeTransferReceived.

The fastBridgeTransferReceived function is correctly implemented according to the IFastBridgeRecipient interface. The minimal implementation is appropriate for a mock contract used in testing.

Consider adding a comment explaining why the function parameters are not used in this mock implementation. This can help prevent confusion for developers who might expect these parameters to be utilized.

packages/contracts-rfq/test/mocks/IncorrectReturnValueRecipient.sol (3)

6-7: LGTM: Well-documented contract declaration.

The contract declaration and documentation are clear and follow best practices. The warning against production use is particularly important for this mock contract.

Consider adding a brief explanation of why this mock is needed in the testing context. For example:

/// @notice Incorrectly implemented recipient mock for testing purposes. DO NOT USE IN PRODUCTION.
/// @dev This mock is used to test the behavior of the system when a recipient returns an incorrect value.

11-15: LGTM: Well-implemented mock function with intentional error.

The fastBridgeTransferReceived() function is correctly implemented to return an intentionally incorrect value. The use of XOR to flip the last bit of the selector is a clever approach.

Consider adding more detailed documentation to explain the specific test scenarios this mock is designed for. For example:

/// @notice Incorrectly implemented - method returns incorrect value.
/// @dev This function intentionally returns an incorrect selector to test error handling in the main contract.
/// @return A bytes4 value that is the original selector with its last bit flipped.

1-16: Overall: Well-implemented mock contract for testing purposes.

This mock contract is well-structured, clearly documented, and serves its purpose of providing an incorrect implementation for testing. The intentional error in the fastBridgeTransferReceived() function is cleverly implemented and well-commented. The contract follows Solidity best practices and includes appropriate warnings against production use.

Ensure that the test suite using this mock covers various scenarios, including:

  1. Verifying that the main contract correctly handles the incorrect return value.
  2. Testing error messages or events emitted when dealing with this incorrect implementation.
  3. Checking that the system's overall integrity is maintained when interacting with this mock.
packages/contracts-rfq/test/FastBridgeV2.Src.Exclusivity.t.sol (1)

11-12: Approve refactoring with a suggestion for improved clarity

The refactoring of createFixturesV2() improves code maintainability by encapsulating the logic for setting exclusivity parameters. The use of separate methods for token and ETH params with different relayers allows for more flexible and thorough testing scenarios.

Consider adding a brief comment explaining the purpose of using different relayers for token and ETH tests, as it might not be immediately clear to other developers why this distinction is made. For example:

// Use different relayers for token and ETH tests to ensure proper handling of distinct relayers
setTokenTestExclusivityParams(relayerA, EXCLUSIVITY_PERIOD);
setEthTestExclusivityParams(relayerB, EXCLUSIVITY_PERIOD);
packages/contracts-rfq/test/FastBridgeV2.Src.Exclusivity.Negative.t.sol (3)

11-13: Approve changes with a minor suggestion.

The modifications to createFixturesV2 improve code maintainability by using the EXCLUSIVITY_PERIOD_ABS constant. The negative exclusivity periods are correctly set for negative testing scenarios.

Consider adding a brief comment explaining the purpose of setting negative exclusivity periods for clarity:

 // Populate the fields using the absolute exclusivity period
 setTokenTestExclusivityParams(relayerA, EXCLUSIVITY_PERIOD_ABS);
 setEthTestExclusivityParams(relayB, EXCLUSIVITY_PERIOD_ABS);
+// Set negative exclusivity periods for negative testing scenarios
 // Override with negative exclusivity period
 tokenParamsV2.quoteExclusivitySeconds = -int256(EXCLUSIVITY_PERIOD_ABS);
 ethParamsV2.quoteExclusivitySeconds = -int256(EXCLUSIVITY_PERIOD_ABS);

Line range hint 36-40: LGTM: Good test for zero exclusivity end time in ETH transactions.

This test function effectively checks that the contract reverts with ExclusivityParamsIncorrect when the exclusivity end time would be zero for ETH transactions. The use of vm.expectRevert is appropriate.

For consistency with the token test, consider renaming the function to test_bridge_eth_revert_exclusivityEndTimeZero:

-function test_bridge_eth_revert_exclusivityEndTimeZero() public {
+function test_bridge_eth_revert_exclusivityEndTimeZero() public {

Line range hint 42-46: LGTM: Effective test for exclusivity period underflow in ETH transactions.

This test function properly verifies that the contract reverts with ExclusivityParamsIncorrect when the exclusivity period would underflow for ETH transactions. The use of vm.expectRevert is correct for this scenario.

For consistency with the token test, consider renaming the function to test_bridge_eth_revert_exclusivityPeriodUnderflow:

-function test_bridge_eth_revert_exclusivityPeriodUnderflow() public {
+function test_bridge_eth_revert_exclusivityPeriodUnderflow() public {
packages/contracts-rfq/contracts/interfaces/IFastBridgeV2.sol (3)

36-41: LGTM! Consider enhancing the comment for clarity.

The addition of callParams to the BridgeParamsV2 struct enhances the flexibility of the bridge transaction process by allowing arbitrary call parameters to be passed to the destination recipient. This is a valuable improvement.

Consider slightly modifying the comment for callParams to provide more context:

-    /// @param callParams               Parameters for the arbitrary call to the destination recipient (if any)
+    /// @param callParams               Optional parameters for an arbitrary call to be executed on the destination chain (if any)

This change clarifies that the parameters are for an optional call that will be executed on the destination chain, which might be more informative for developers using this interface.


62-62: LGTM! Consider adding a comment for the new field.

The addition of callParams to the BridgeTransactionV2 struct is consistent with its addition to BridgeParamsV2 and enhances the functionality of the bridge transaction process.

To improve code readability and maintainability, consider adding a comment for the new callParams field:

        uint256 exclusivityEndTime;
+       /// @dev Optional parameters for an arbitrary call to be executed on the destination chain
        bytes callParams;

This comment will provide context for the purpose of callParams within the BridgeTransactionV2 struct, making it easier for developers to understand its role in the bridging process.


Line range hint 1-124: Summary: Enhancements to bridge transaction flexibility

The changes to IFastBridgeV2 interface improve the flexibility of the bridge transaction process by introducing the callParams field to both BridgeParamsV2 and BridgeTransactionV2 structs. This addition allows for arbitrary call parameters to be passed to the destination recipient, enhancing the capabilities of the bridge.

Key points:

  1. No breaking changes were introduced to the interface.
  2. The bridge function signature remains unchanged but now accepts the updated BridgeParamsV2 struct with the new field.
  3. These changes provide a more versatile bridging mechanism that can accommodate a wider range of use cases.

As the project evolves, consider the following:

  1. Ensure that all implementations of this interface properly handle the new callParams field.
  2. Update any related documentation or integration guides to reflect these new capabilities.
  3. Consider adding validation mechanisms for callParams to prevent potential security risks associated with arbitrary calls.
packages/contracts-rfq/test/FastBridgeV2.Dst.Exclusivity.t.sol (1)

20-21: LGTM. Consider using a constant for empty string initialization.

The addition of the callParams field to ethParamsV2 is consistent with the changes made to tokenParamsV2. To improve maintainability, consider defining a constant for the empty string initialization used in both tokenParamsV2 and ethParamsV2.

Example:

string constant EMPTY_CALL_PARAMS = "";

Then use EMPTY_CALL_PARAMS instead of "" in both initializations.

packages/contracts-rfq/test/FastBridgeV2.Src.ArbitraryCall.t.sol (1)

6-6: Specify the reason for disabling solhint rules

It's good practice to provide a comment explaining why specific Solhint rules are being disabled. This improves code readability and helps other developers understand the rationale behind these exceptions.

packages/contracts-rfq/test/FastBridgeV2.Encoding.t.sol (1)

56-56: Address the TODO comment: Reevaluate test necessity

There's a TODO comment indicating the need to reevaluate the necessity of this test if or when the encoding scheme changes. Would you like assistance in addressing this, or should I open a GitHub issue to track this task?

packages/contracts-rfq/test/FastBridgeV2.Dst.t.sol (6)

159-163: Inconsistent test naming: Function name suggests different behavior

The test function test_relay_token_excessiveReturnValueRecipient_revertWhenCallParamsPresent implies it tests a scenario where callParams are present and expects a revert. However, it asserts that callParams are empty and proceeds without expecting a revert. This may cause confusion.

Consider renaming the function to reflect its current behavior or adding comments to clarify that it is intended to be overridden in derived classes where callParams are present.


165-172: Inconsistent test naming: Function name implies different scenario

Similarly, the function test_relay_token_withRelayerAddress_excessiveReturnValueRecipient_revertWhenCallParamsPresent suggests testing a revert when callParams are present, but it asserts that callParams are empty.

Recommend clarifying the function name or adding comments to explain its purpose in the current context.


174-178: Inconsistent test naming in ETH relay test

The test function test_relay_eth_excessiveReturnValueRecipient_revertWhenCallParamsPresent implies a revert when callParams are present, but it asserts that callParams are empty.

Consider adjusting the function name or adding clarifying comments for better readability.


191-223: Inconsistent test naming in Incorrect Return Value Recipient tests

The test functions for the incorrect return value recipient also exhibit similar inconsistencies between their names and behavior. They assert that callParams are empty while the function names suggest testing with callParams present.

Suggest renaming the functions or enhancing comments to make the intended usage clearer.


254-276: Inconsistent test naming in No-Op Recipient tests

The test functions like test_relay_token_noOpRecipient_revertWhenCallParamsPresent imply they are testing with callParams present and expecting a revert, but they assert that callParams are empty.

Recommend adjusting the function names or adding explanatory comments to clarify the intended test scenarios.


283-305: Inconsistent test naming in No Return Value Recipient tests

The test functions for the no return value recipient suggest they are testing scenarios with callParams present, yet they assert that callParams are empty.

Consider renaming these functions or adding comments to better reflect their current behavior and future overriding intentions.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 8311329 and 4b49879.

📒 Files selected for processing (22)
  • packages/contracts-rfq/CHANGELOG.md (1 hunks)
  • packages/contracts-rfq/contracts/FastBridgeV2.sol (9 hunks)
  • packages/contracts-rfq/contracts/interfaces/IFastBridgeRecipient.sol (1 hunks)
  • packages/contracts-rfq/contracts/interfaces/IFastBridgeV2.sol (2 hunks)
  • packages/contracts-rfq/contracts/interfaces/IFastBridgeV2Errors.sol (1 hunks)
  • packages/contracts-rfq/package.json (1 hunks)
  • packages/contracts-rfq/test/FastBridgeV2.Dst.ArbitraryCall.t.sol (1 hunks)
  • packages/contracts-rfq/test/FastBridgeV2.Dst.Exclusivity.t.sol (1 hunks)
  • packages/contracts-rfq/test/FastBridgeV2.Dst.t.sol (3 hunks)
  • packages/contracts-rfq/test/FastBridgeV2.Encoding.t.sol (1 hunks)
  • packages/contracts-rfq/test/FastBridgeV2.GasBench.Dst.Excl.t.sol (1 hunks)
  • packages/contracts-rfq/test/FastBridgeV2.GasBench.Src.t.sol (2 hunks)
  • packages/contracts-rfq/test/FastBridgeV2.Src.ArbitraryCall.t.sol (1 hunks)
  • packages/contracts-rfq/test/FastBridgeV2.Src.Exclusivity.Negative.t.sol (1 hunks)
  • packages/contracts-rfq/test/FastBridgeV2.Src.Exclusivity.t.sol (1 hunks)
  • packages/contracts-rfq/test/FastBridgeV2.t.sol (3 hunks)
  • packages/contracts-rfq/test/mocks/ExcessiveReturnValueRecipient.sol (1 hunks)
  • packages/contracts-rfq/test/mocks/IncorrectReturnValueRecipient.sol (1 hunks)
  • packages/contracts-rfq/test/mocks/NoOpContract.sol (1 hunks)
  • packages/contracts-rfq/test/mocks/NoReturnValueRecipient.sol (1 hunks)
  • packages/contracts-rfq/test/mocks/NonPayableRecipient.sol (1 hunks)
  • packages/contracts-rfq/test/mocks/RecipientMock.sol (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • packages/contracts-rfq/package.json
🧰 Additional context used
🪛 Markdownlint
packages/contracts-rfq/CHANGELOG.md

9-9: Expected: h2; Actual: h3
Heading levels should only increment by one level at a time

(MD001, heading-increment)

🔇 Additional comments (42)
packages/contracts-rfq/test/mocks/NoOpContract.sol (1)

1-2: LGTM: Appropriate license and Solidity version.

The MIT license is suitable for open-source projects, and the Solidity version (^0.8.0) is recent and includes important security features.

packages/contracts-rfq/contracts/interfaces/IFastBridgeRecipient.sol (1)

1-2: LGTM: License and Solidity version are appropriate.

The MIT license is suitable for open-source projects, and the Solidity version (^0.8.0) is recent and allows for minor version updates, which is a good practice.

packages/contracts-rfq/test/mocks/NonPayableRecipient.sol (1)

1-2: LGTM: Appropriate license and Solidity version.

The MIT license is suitable for open-source projects, and the Solidity version (^0.8.0) is recent and allows for minor updates.

packages/contracts-rfq/test/mocks/NoReturnValueRecipient.sol (2)

6-7: Contract declaration and documentation look good.

The contract name NoReturnValueRecipient is clear and descriptive. The NatSpec comment provides important information about the contract's purpose and usage, explicitly stating that it's for testing purposes and should not be used in production. This is good practice for mock contracts.


8-9: The receive function is correctly implemented for a mock contract.

The receive function allows the contract to accept ETH payments, which is necessary for a mock contract that might need to simulate receiving ETH. The empty function body is appropriate for this purpose. The NatSpec comment clearly explains the function's purpose.

packages/contracts-rfq/test/FastBridgeV2.GasBench.Dst.Excl.t.sol (1)

16-17: Excellent refactoring of createFixturesV2!

The changes improve code readability and maintainability by consolidating multiple parameter assignments into two function calls: setTokenTestExclusivityParams and setEthTestExclusivityParams. This approach ensures consistency by using the EXCLUSIVITY_PERIOD constant and relayerA across both token and ETH test setups.

packages/contracts-rfq/contracts/interfaces/IFastBridgeV2Errors.sol (2)

15-15: LGTM! Clear and concise error definition.

The RecipientNoReturnValue error is a good addition for handling cases where a recipient doesn't return a value when one was expected. The error is self-explanatory and doesn't require additional parameters.


6-15: Overall improvement in error handling granularity.

The addition of these three new errors (CallParamsLengthAboveMax, RecipientIncorrectReturnValue, and RecipientNoReturnValue) enhances the error handling capabilities of the FastBridgeV2 contract. These errors provide more specific reporting related to call parameters and recipient return values, which will likely improve debugging and error handling in the contract implementation.

packages/contracts-rfq/test/mocks/RecipientMock.sol (2)

1-2: LGTM: Appropriate license and Solidity version.

The file structure starts correctly with the SPDX license identifier and an appropriate Solidity version declaration.


4-4: LGTM: Correct import statement.

The import statement for the IFastBridgeRecipient interface is correctly formatted and uses an appropriate relative path.

packages/contracts-rfq/test/mocks/ExcessiveReturnValueRecipient.sol (4)

1-4: LGTM: Appropriate license and import.

The contract uses the MIT license, a recent Solidity version (^0.8.0), and correctly imports the IFastBridgeRecipient interface. These choices align with best practices for Solidity development.


6-7: Excellent use of documentation for this mock contract.

The contract name is descriptive and follows naming conventions. The comment explicitly stating that this is a mock for testing purposes and should not be used in production is crucial. This helps prevent potential misuse and clearly communicates the contract's intended purpose.


8-9: LGTM: Correctly implemented receive function with clear documentation.

The receive function is properly implemented to accept ETH, which is necessary for this mock contract's testing purposes. The accompanying comment clearly explains the function's purpose, enhancing code readability and maintainability.


11-14: LGTM: Well-implemented mock function for testing edge cases.

The fastBridgeTransferReceived function is correctly implemented as a mock for testing purposes. It intentionally returns an excessive number of bytes, which is useful for testing error handling in the actual implementation. The use of the interface selector and a hardcoded value (1337) is a good practice for verifying that this mock is indeed called in tests.

Remember that this implementation is specifically designed for testing and should never be used in a production environment.

packages/contracts-rfq/test/mocks/IncorrectReturnValueRecipient.sol (3)

1-2: LGTM: Appropriate license and Solidity version.

The SPDX-License-Identifier is correctly specified, and the Solidity version is appropriately set to ^0.8.0, allowing for minor updates while ensuring compatibility.


4-4: LGTM: Correct import statement.

The import statement for the IFastBridgeRecipient interface is correctly implemented and follows best practices.


8-9: LGTM: Correctly implemented receive() function.

The receive() function is properly implemented as external and payable. The NatSpec comment clearly explains its purpose in the context of this mock contract.

packages/contracts-rfq/test/FastBridgeV2.Src.Exclusivity.t.sol (1)

11-12: Verify impact of changes on contract behavior

The refactoring of createFixturesV2() appears to maintain the existing behavior of the contract. The bridge() function and test functions remain unchanged and should still work as expected with the new parameter setting methods.

To ensure that the refactoring hasn't introduced any unintended side effects, please run the following verification:

These checks will help confirm that the refactoring is complete and consistent throughout the contract.

✅ Verification successful

Retry verifying the parameter setting methods with adjusted search criteria

The initial search failed because rg does not recognize the solidity file type. Let's attempt to search within .sol files without specifying the file type.


Parameter Setting Methods Verified Successfully

The new parameter setting methods are correctly defined and utilized. Both tokenParamsV2 and ethParamsV2 are actively used across the contract without any references to the old parameter setting logic.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that the new parameter setting methods are called correctly and that they set the expected values.

# Test 1: Check if the new methods are defined in the parent class or in this contract
rg --type solidity -e "function setTokenTestExclusivityParams" -e "function setEthTestExclusivityParams"

# Test 2: Verify that tokenParamsV2 and ethParamsV2 are still being used in the contract
rg --type solidity -e "tokenParamsV2" -e "ethParamsV2" packages/contracts-rfq/test/FastBridgeV2.Src.Exclusivity.t.sol

# Test 3: Check for any references to the old parameter setting logic that might have been missed
rg --type solidity -e "quoteRelayer" -e "quoteExclusivitySeconds" -e "quoteId" packages/contracts-rfq/test/FastBridgeV2.Src.Exclusivity.t.sol

Length of output: 459


Script:

#!/bin/bash
# Description: Retry verifying that the new parameter setting methods are called correctly and that they set the expected values.

# Find all Solidity files and search for the new parameter setting methods
fd --extension sol | xargs rg "function setTokenTestExclusivityParams"
fd --extension sol | xargs rg "function setEthTestExclusivityParams"

# Verify that tokenParamsV2 and ethParamsV2 are still being used in the contract
fd --extension sol | xargs rg "tokenParamsV2"
fd --extension sol | xargs rg "ethParamsV2"

# Check for any references to the old parameter setting logic that might have been missed
fd --extension sol | xargs rg "quoteRelayer"
fd --extension sol | xargs rg "quoteExclusivitySeconds"
fd --extension sol | xargs rg "quoteId"

Length of output: 12107

packages/contracts-rfq/test/FastBridgeV2.Src.Exclusivity.Negative.t.sol (3)

Line range hint 24-28: LGTM: Well-structured test for zero exclusivity end time.

This test function effectively checks that the contract reverts with ExclusivityParamsIncorrect when the exclusivity end time would be zero. The use of vm.expectRevert is appropriate for testing this scenario.


Line range hint 30-34: LGTM: Effective test for exclusivity period underflow.

This test function properly verifies that the contract reverts with ExclusivityParamsIncorrect when the exclusivity period would underflow. The use of vm.expectRevert is correct for this scenario.


Line range hint 1-48: Overall assessment: Improved test coverage for exclusivity parameters.

The changes in this file significantly enhance the test coverage for negative scenarios related to exclusivity parameters in the FastBridgeV2 contract. The new tests effectively cover important edge cases, such as zero exclusivity end time and exclusivity period underflow, for both token and ETH transactions. These additions contribute to a more robust test suite, helping to prevent potential vulnerabilities in the contract's handling of exclusivity parameters.

packages/contracts-rfq/test/FastBridgeV2.Dst.Exclusivity.t.sol (2)

14-15: LGTM. Please clarify the purpose of callParams.

The addition of the callParams field to tokenParamsV2 is consistent with the changes mentioned in the summary. However, could you provide more context on the intended use of this new field? Understanding its purpose would help ensure that it's being used correctly in the tests.


Line range hint 1-180: Consider adding test cases for the new callParams field.

While the addition of the callParams field to both tokenParamsV2 and ethParamsV2 is implemented correctly, there are no test cases that specifically validate this new field. To ensure comprehensive test coverage, consider adding test cases that:

  1. Verify that callParams is correctly set and retrieved.
  2. Test the behavior of the system with non-empty callParams values.
  3. Ensure that the callParams field doesn't interfere with existing functionality.

This will help maintain the robustness of the test suite and validate the new feature.

Would you like assistance in drafting these additional test cases?

packages/contracts-rfq/CHANGELOG.md (2)

6-16: LGTM: New changelog entry is well-formatted and informative.

The new entry for version 0.7.0 follows the established format and provides clear information about the release. It includes:

  • The correct version number and release date
  • A link to compare with the previous version
  • A concise description of the new feature
  • References to the related issue and pull request
  • The commit hash for traceability

This entry maintains the quality and consistency of the changelog.

🧰 Tools
🪛 Markdownlint

9-9: Expected: h2; Actual: h3
Heading levels should only increment by one level at a time

(MD001, heading-increment)


9-9: Note on heading format: Consistent with existing structure.

The static analysis tool flagged the use of an h3 heading ("### Features") as a potential issue. However, this format is consistent with the rest of the changelog and appears to be intentional. Changing this would require updating the entire document structure, which is beyond the scope of this single entry. The current format is clear and functional for a changelog.

🧰 Tools
🪛 Markdownlint

9-9: Expected: h2; Actual: h3
Heading levels should only increment by one level at a time

(MD001, heading-increment)

packages/contracts-rfq/test/FastBridgeV2.GasBench.Src.t.sol (3)

107-107: Summary: Improved test structure with new helper functions

The changes in this file introduce two new helper functions, setTokenTestExclusivityParams and setEthTestExclusivityParams, which are used in the test_bridge_token_withExclusivity and test_bridge_eth_withExclusivity tests respectively. These changes improve code readability and maintainability by encapsulating the setup of exclusivity parameters.

However, the implementations of these new helper functions are not visible in the provided code. To ensure the correctness and completeness of these changes, please provide the implementations of both setTokenTestExclusivityParams and setEthTestExclusivityParams functions.

Please provide the implementations of the new helper functions:

#!/bin/bash
echo "Implementation of setTokenTestExclusivityParams:"
rg -U "function setTokenTestExclusivityParams\(.*?\)" -A 10
echo "Implementation of setEthTestExclusivityParams:"
rg -U "function setEthTestExclusivityParams\(.*?\)" -A 10

If these functions are implemented in a different file, please provide the file name and the implementations.

Also applies to: 188-188


188-188: Refactor: New helper function used for ETH exclusivity test

The setEthTestExclusivityParams function has been introduced to set up exclusivity parameters for the ETH test. This refactoring is consistent with the changes made to the token test, improving code readability and maintainability.

To ensure the correctness of this change, please provide the implementation of the setEthTestExclusivityParams function:

#!/bin/bash
rg -U "function setEthTestExclusivityParams\(.*?\)" -A 10

107-107: Refactor: New helper function used for token exclusivity test

The setTokenTestExclusivityParams function has been introduced to set up exclusivity parameters for the token test. This refactoring improves code readability and maintainability by encapsulating the parameter setup logic.

To ensure the correctness of this change, please provide the implementation of the setTokenTestExclusivityParams function:

packages/contracts-rfq/test/FastBridgeV2.t.sol (4)

127-138: Initialization of tokenParamsV2 and ethParamsV2 in createFixturesV2

The default initialization of tokenParamsV2 and ethParamsV2 with zero values is appropriate for the test setup and ensures that the parameters are reset before each test.


166-169: setTokenTestCallParams function is correctly implemented

The function correctly sets the callParams for both tokenParamsV2 and tokenTx, ensuring consistency between the parameters and the transaction.


180-183: setEthTestCallParams function is correctly implemented

The function properly sets the callParams for both ethParamsV2 and ethTx, maintaining consistency between the parameters and the transaction.


213-221: getMockQuoteId function is correctly implemented

The function appropriately returns different mock quote IDs based on the provided relayer address, which is suitable for testing purposes.

packages/contracts-rfq/test/FastBridgeV2.Dst.t.sol (7)

6-10: Approved: Importing required mock contracts

The import statements for mock contracts are correct and necessary for the added test cases.


26-30: Approved: Declaration of recipient address variables

The public address variables for the mock recipients are appropriately declared.


32-44: Setup function initializes mock recipients correctly

The setUp function properly instantiates the mock recipient contracts and labels them for easier identification during testing.


46-50: Approved: setTokenTestRecipient function implementation

The helper function correctly sets the recipient addresses for token tests.


52-56: Approved: setEthTestRecipient function implementation

The helper function appropriately updates the recipient addresses for ETH tests.


58-60: Approved: assertEmptyCallParams function validates call parameters

The function accurately asserts that callParams are empty, ensuring correct test setup.


224-248: Approved: Non-payable recipient tests are correctly implemented

The tests correctly verify that ERC20 transfers continue unaffected to a non-payable recipient and appropriately expect reverts when attempting to transfer ETH to a non-payable recipient.

packages/contracts-rfq/contracts/FastBridgeV2.sol (3)

29-31: Validate the appropriateness of MAX_CALL_PARAMS_LENGTH

The constant MAX_CALL_PARAMS_LENGTH is set to 2 ** 16 - 1 (65535). Ensure this value aligns with the expected maximum size of callParams to prevent potential issues with gas limits or unexpected input sizes.


232-257: Verify reentrancy safety in external calls

The relay function has been refactored to include external calls to _checkedCallRecipient. While the comments mention adherence to the checks-effects-interactions pattern, please double-check that all state changes occur before any external calls to prevent potential reentrancy attacks.


360-383: Review the implementation of _checkedCallRecipient for security

The _checkedCallRecipient function uses Address.functionCallWithValue to invoke the recipient's hook function. Ensure that:

  • The recipient contract complies with the IFastBridgeRecipient interface.
  • The call correctly handles the transfer of msgValue, especially when dealing with ETH transfers.
  • There are appropriate checks and error handling to prevent security vulnerabilities.

Comment on lines +5 to +12
function fastBridgeTransferReceived(
address token,
uint256 amount,
bytes memory callParams
)
external
payable
returns (bytes4);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Issues Found with IFastBridgeRecipient Implementations

Several implementations of the IFastBridgeRecipient interface do not adhere to the defined function signature of fastBridgeTransferReceived:

  • NoReturnValueRecipient.sol

    • Issue: Missing return value.
    • Details: The function does not return the required bytes4 value.
  • ExcessiveReturnValueRecipient.sol

    • Issue: Additional return value.
    • Details: The function returns both bytes4 and uint256, deviating from the interface specification.
  • Other Implementations (IncorrectReturnValueRecipient.sol, RecipientMock.sol, NonPayableRecipient.sol)

    • Review Needed: Ensure these implementations correctly handle return values and access controls as per the interface.

Recommendations:

  1. Standardize Return Values:

    • Ensure all implementations of fastBridgeTransferReceived return only the bytes4 value as defined in the IFastBridgeRecipient interface.
  2. Implement Access Controls:

    • Review and enforce appropriate access controls in each implementation to restrict function calls to authorized entities.
  3. Conduct Comprehensive Testing:

    • Perform thorough testing on all implementations to validate compliance with the interface and to identify any potential security vulnerabilities.
🔗 Analysis chain

Consider security implications and potential improvements.

While the function signature is well-structured, there are some security considerations and potential improvements to consider:

  1. Access Control: There's no explicit check for who can call this function. Consider adding a modifier or check to ensure only authorized addresses (e.g., the bridge contract) can call this function.

  2. Payable Function: The function is marked as payable, allowing it to receive Ether. Ensure this is intentional and necessary for all cases. If not always needed, consider creating separate functions for Ether and non-Ether transfers.

  3. Return Value: The bytes4 return type is common, but consider using a more specific return value or enum to indicate different states of the transfer (e.g., success, failure due to insufficient balance, etc.).

  4. Parameter Validation: Add input validation for the amount parameter to prevent potential overflow issues.

  5. Reentrancy: If this function performs state changes or transfers, ensure it's protected against reentrancy attacks.

To verify the usage and implementation of this interface across the project, you can run the following script:

This will help ensure consistent implementation and usage across the project.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for implementations and usages of IFastBridgeRecipient

echo "Searching for implementations of IFastBridgeRecipient:"
rg --type solidity "contract.*is.*IFastBridgeRecipient"

echo "\nSearching for usages of fastBridgeTransferReceived function:"
rg --type solidity "fastBridgeTransferReceived\("

Length of output: 429


Script:

#!/bin/bash
# Searching for implementations of IFastBridgeRecipient:
rg -g '*.sol' "contract\s+.*\s+is\s+.*IFastBridgeRecipient"

# Searching for usages of fastBridgeTransferReceived function:
rg -g '*.sol' "fastBridgeTransferReceived\("

Length of output: 1419

Comment on lines +31 to +36
function test_bridge_token_revert_callParamsLengthAboveMax() public {
bytes memory callParams = new bytes(2 ** 16);
setTokenTestCallParams(callParams);
vm.expectRevert(CallParamsLengthAboveMax.selector);
bridge({caller: userA, msgValue: 0, params: tokenParams, paramsV2: tokenParamsV2});
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consolidate revert tests to improve test suite efficiency

The functions test_bridge_token_revert_callParamsLengthAboveMax and test_bridge_eth_revert_callParamsLengthAboveMax are nearly identical. Combining them into a single function can simplify the test code and make future maintenance easier.

Here's how you might refactor these tests:

-function test_bridge_token_revert_callParamsLengthAboveMax() public {
-    bytes memory callParams = new bytes(2 ** 16);
-    setTokenTestCallParams(callParams);
-    vm.expectRevert(CallParamsLengthAboveMax.selector);
-    bridge({caller: userA, msgValue: 0, params: tokenParams, paramsV2: tokenParamsV2});
-}
-
-function test_bridge_eth_revert_callParamsLengthAboveMax() public {
-    bytes memory callParams = new bytes(2 ** 16);
-    setEthTestCallParams(callParams);
-    vm.expectRevert(CallParamsLengthAboveMax.selector);
-    bridge({caller: userA, msgValue: ethParams.originAmount, params: ethParams, paramsV2: ethParamsV2});
-}
+function test_bridge_revert_callParamsLengthAboveMax(bool isToken) public {
+    bytes memory callParams = new bytes(2 ** 16);
+    if (isToken) {
+        setTokenTestCallParams(callParams);
+        vm.expectRevert(CallParamsLengthAboveMax.selector);
+        bridge({caller: userA, msgValue: 0, params: tokenParams, paramsV2: tokenParamsV2});
+    } else {
+        setEthTestCallParams(callParams);
+        vm.expectRevert(CallParamsLengthAboveMax.selector);
+        bridge({caller: userA, msgValue: ethParams.originAmount, params: ethParams, paramsV2: ethParamsV2});
+    }
+}

Also applies to: 38-43

Comment on lines +19 to +23
function test_bridge_token_callParamsLengthMax() public {
bytes memory callParams = new bytes(2 ** 16 - 1);
setTokenTestCallParams(callParams);
test_bridge_token();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Refactor similar test functions to reduce code duplication

The functions test_bridge_token_callParamsLengthMax and test_bridge_eth_callParamsLengthMax have similar implementations. Consider refactoring them into a single parameterized function to enhance maintainability and reduce redundancy.

Apply this diff to refactor the tests:

-function test_bridge_token_callParamsLengthMax() public {
-    bytes memory callParams = new bytes(2 ** 16 - 1);
-    setTokenTestCallParams(callParams);
-    test_bridge_token();
-}
-
-function test_bridge_eth_callParamsLengthMax() public {
-    bytes memory callParams = new bytes(2 ** 16 - 1);
-    setEthTestCallParams(callParams);
-    test_bridge_eth();
-}
+function test_bridge_callParamsLengthMax(bool isToken) public {
+    bytes memory callParams = new bytes(2 ** 16 - 1);
+    if (isToken) {
+        setTokenTestCallParams(callParams);
+        test_bridge_token();
+    } else {
+        setEthTestCallParams(callParams);
+        test_bridge_eth();
+    }
+}

Committable suggestion was skipped due to low confidence.

Comment on lines +55 to +57
function test_getBridgeTransaction_supportsV2(IFastBridgeV2.BridgeTransactionV2 memory bridgeTxV2) public {
// TODO: reevaluate the necessity of this test if/when the encoding scheme is changed
vm.skip(true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Consider addressing the skipped test in test_getBridgeTransaction_supportsV2

The test function test_getBridgeTransaction_supportsV2 is currently being skipped using vm.skip(true);. Skipping tests can lead to reduced test coverage and potential issues might go unnoticed. Please consider implementing this test or, if it's no longer necessary due to the encoding compatibility issues, removing it to maintain a clean codebase.

Comment on lines +166 to +192
function setTokenTestCallParams(bytes memory callParams) public {
tokenParamsV2.callParams = callParams;
tokenTx.callParams = callParams;
}

function setTokenTestExclusivityParams(address relayer, uint256 exclusivitySeconds) public {
tokenParamsV2.quoteRelayer = relayer;
tokenParamsV2.quoteExclusivitySeconds = int256(exclusivitySeconds);
tokenParamsV2.quoteId = bytes.concat("Token:", getMockQuoteId(relayer));

tokenTx.exclusivityRelayer = relayer;
tokenTx.exclusivityEndTime = block.timestamp + exclusivitySeconds;
}

function setEthTestCallParams(bytes memory callParams) public {
ethParamsV2.callParams = callParams;
ethTx.callParams = callParams;
}

function setEthTestExclusivityParams(address relayer, uint256 exclusivitySeconds) public {
ethParamsV2.quoteRelayer = relayer;
ethParamsV2.quoteExclusivitySeconds = int256(exclusivitySeconds);
ethParamsV2.quoteId = bytes.concat("ETH:", getMockQuoteId(relayer));

ethTx.exclusivityRelayer = relayer;
ethTx.exclusivityEndTime = block.timestamp + exclusivitySeconds;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider refactoring to reduce code duplication

The functions setTokenTestCallParams, setEthTestCallParams, setTokenTestExclusivityParams, and setEthTestExclusivityParams have similar logic. Consider creating generic helper functions to reduce code duplication and improve maintainability.

Here's how you could refactor the code:

  1. Create internal helper functions:
function _setTestCallParams(
    IFastBridgeV2.BridgeParamsV2 storage paramsV2,
    IFastBridgeV2.BridgeTransactionV2 storage tx,
    bytes memory callParams
) internal {
    paramsV2.callParams = callParams;
    tx.callParams = callParams;
}

function _setTestExclusivityParams(
    IFastBridgeV2.BridgeParamsV2 storage paramsV2,
    IFastBridgeV2.BridgeTransactionV2 storage tx,
    string memory prefix,
    address relayer,
    uint256 exclusivitySeconds
) internal {
    paramsV2.quoteRelayer = relayer;
    paramsV2.quoteExclusivitySeconds = int256(exclusivitySeconds);
    paramsV2.quoteId = bytes.concat(bytes(prefix), getMockQuoteId(relayer));

    tx.exclusivityRelayer = relayer;
    tx.exclusivityEndTime = block.timestamp + exclusivitySeconds;
}
  1. Refactor the existing functions to use the helpers:
 function setTokenTestCallParams(bytes memory callParams) public {
-    tokenParamsV2.callParams = callParams;
-    tokenTx.callParams = callParams;
+    _setTestCallParams(tokenParamsV2, tokenTx, callParams);
 }

 function setEthTestCallParams(bytes memory callParams) public {
-    ethParamsV2.callParams = callParams;
-    ethTx.callParams = callParams;
+    _setTestCallParams(ethParamsV2, ethTx, callParams);
 }

 function setTokenTestExclusivityParams(address relayer, uint256 exclusivitySeconds) public {
-    tokenParamsV2.quoteRelayer = relayer;
-    tokenParamsV2.quoteExclusivitySeconds = int256(exclusivitySeconds);
-    tokenParamsV2.quoteId = bytes.concat("Token:", getMockQuoteId(relayer));

-    tokenTx.exclusivityRelayer = relayer;
-    tokenTx.exclusivityEndTime = block.timestamp + exclusivitySeconds;
+    _setTestExclusivityParams(tokenParamsV2, tokenTx, "Token:", relayer, exclusivitySeconds);
 }

 function setEthTestExclusivityParams(address relayer, uint256 exclusivitySeconds) public {
-    ethParamsV2.quoteRelayer = relayer;
-    ethParamsV2.quoteExclusivitySeconds = int256(exclusivitySeconds);
-    ethParamsV2.quoteId = bytes.concat("ETH:", getMockQuoteId(relayer));

-    ethTx.exclusivityRelayer = relayer;
-    ethTx.exclusivityEndTime = block.timestamp + exclusivitySeconds;
+    _setTestExclusivityParams(ethParamsV2, ethTx, "ETH:", relayer, exclusivitySeconds);
 }

// solhint-disable func-name-mixedcase, ordering
contract FastBridgeV2DstArbitraryCallTest is FastBridgeV2DstExclusivityTest {
bytes public constant CALL_PARAMS = abi.encode("Hello, world!");
bytes public constant REVERT_MSG = "GM, this is a revert";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Incorrect declaration of 'REVERT_MSG'

At line 12, REVERT_MSG is declared as bytes but assigned a string literal. In Solidity, string literals are of type string, and assigning them directly to a bytes variable can cause a type mismatch.

Suggested Fix:

Declare REVERT_MSG as a string:

- bytes public constant REVERT_MSG = "GM, this is a revert";
+ string public constant REVERT_MSG = "GM, this is a revert";
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
bytes public constant REVERT_MSG = "GM, this is a revert";
string public constant REVERT_MSG = "GM, this is a revert";

}

function mockRecipientRevert(IFastBridgeV2.BridgeTransactionV2 memory bridgeTx) public {
vm.mockCallRevert({callee: userB, data: getExpectedCalldata(bridgeTx), revertData: bytes(REVERT_MSG)});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Unnecessary casting of 'REVERT_MSG' to bytes

In line 43, bytes(REVERT_MSG) is used to cast REVERT_MSG to bytes. Since REVERT_MSG should be declared as a string (as per the previous suggestion), casting it to bytes here is appropriate. However, if REVERT_MSG remains as bytes, the cast is redundant.

Suggested Fix (if REVERT_MSG is a string):

No change needed in line 43 if REVERT_MSG is declared as a string.

Suggested Fix (if REVERT_MSG is kept as bytes):

Remove the redundant cast:

- vm.mockCallRevert({callee: userB, data: getExpectedCalldata(bridgeTx), revertData: bytes(REVERT_MSG)});
+ vm.mockCallRevert({callee: userB, data: getExpectedCalldata(bridgeTx), revertData: REVERT_MSG});

Committable suggestion was skipped due to low confidence.

Comment on lines +159 to +305
test_relay_token_withRelayerAddress();
}

function test_relay_eth_incorrectReturnValueRecipient_revertWhenCallParamsPresent() public virtual {
assertEmptyCallParams(ethTx.callParams);
setEthTestRecipient(incorrectReturnValueRecipient);
test_relay_eth();
}

function test_relay_eth_withRelayerAddress_incorrectReturnValueRecipient_revertWhenCallParamsPresent()
public
virtual
{
assertEmptyCallParams(ethTx.callParams);
setEthTestRecipient(incorrectReturnValueRecipient);
test_relay_eth_withRelayerAddress();
}

// ═══════════════════════════════════════════ NON PAYABLE RECIPIENT ═══════════════════════════════════════════════

/// @notice Should not affect the ERC20 transfer
function test_relay_token_nonPayableRecipient() public {
setTokenTestRecipient(nonPayableRecipient);
test_relay_token();
}

function test_relay_token_withRelayerAddress_nonPayableRecipient() public {
setTokenTestRecipient(nonPayableRecipient);
test_relay_token_withRelayerAddress();
}

function test_relay_eth_revert_nonPayableRecipient() public {
setEthTestRecipient(nonPayableRecipient);
vm.expectRevert();
relay({caller: relayerB, msgValue: ethParams.destAmount, bridgeTx: ethTx});
}

function test_relay_eth_withRelayerAddress_revert_nonPayableRecipient() public {
setEthTestRecipient(nonPayableRecipient);
vm.expectRevert();
relayWithAddress({caller: relayerA, relayer: relayerB, msgValue: ethParams.destAmount, bridgeTx: ethTx});
}

// ══════════════════════════════════════════════ NO-OP RECIPIENT ══════════════════════════════════════════════════

// Note: in this test, the callParams are not present, and the below test functions succeed.
// Override them in the derived tests where callParams are present to check for a revert.

function test_relay_token_noOpRecipient_revertWhenCallParamsPresent() public virtual {
assertEmptyCallParams(tokenTx.callParams);
setTokenTestRecipient(noOpRecipient);
test_relay_token();
}

function test_relay_token_withRelayerAddress_noOpRecipient_revertWhenCallParamsPresent() public virtual {
assertEmptyCallParams(tokenTx.callParams);
setTokenTestRecipient(noOpRecipient);
test_relay_token_withRelayerAddress();
}

function test_relay_eth_noOpRecipient_revertWhenCallParamsPresent() public virtual {
assertEmptyCallParams(ethTx.callParams);
setEthTestRecipient(noOpRecipient);
test_relay_eth();
}

function test_relay_eth_withRelayerAddress_noOpRecipient_revertWhenCallParamsPresent() public virtual {
assertEmptyCallParams(ethTx.callParams);
setEthTestRecipient(noOpRecipient);
test_relay_eth_withRelayerAddress();
}

// ═════════════════════════════════════════ NO RETURN VALUE RECIPIENT ═════════════════════════════════════════════

// Note: in this test, the callParams are not present, and the below test functions succeed.
// Override them in the derived tests where callParams are present to check for a revert.

function test_relay_token_noReturnValueRecipient_revertWhenCallParamsPresent() public virtual {
assertEmptyCallParams(tokenTx.callParams);
setTokenTestRecipient(noReturnValueRecipient);
test_relay_token();
}

function test_relay_token_withRelayerAddress_noReturnValueRecipient_revertWhenCallParamsPresent() public virtual {
assertEmptyCallParams(tokenTx.callParams);
setTokenTestRecipient(noReturnValueRecipient);
test_relay_token_withRelayerAddress();
}

function test_relay_eth_noReturnValueRecipient_revertWhenCallParamsPresent() public virtual {
assertEmptyCallParams(ethTx.callParams);
setEthTestRecipient(noReturnValueRecipient);
test_relay_eth();
}

function test_relay_eth_withRelayerAddress_noReturnValueRecipient_revertWhenCallParamsPresent() public virtual {
assertEmptyCallParams(ethTx.callParams);
setEthTestRecipient(noReturnValueRecipient);
test_relay_eth_withRelayerAddress();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider refactoring repetitive test functions to reduce duplication

Many test functions between lines 159-305 share similar structures, differing mainly in the recipient type and the specific test function called. Refactoring these tests using helper functions or parameterized tests could reduce code duplication and enhance maintainability.

For example, you could implement a generic test function that accepts parameters for the recipient address and the expected behavior, which can be reused for different scenarios.

Comment on lines +130 to +132
// TODO: the note below isn't true anymore with the BridgeTransactionV2 struct
// since the variable length `callParams` was added. This needs to be fixed/acknowledged.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Update the outdated comment regarding BridgeTransactionV2

The TODO comment indicates that the note about decoding V1 fields is no longer accurate due to the addition of variable-length callParams. Please revise or remove this comment to reflect the current implementation.

Would you like assistance in updating this comment to accurately describe the current behavior?

@@ -132,6 +145,7 @@ contract FastBridgeV2 is Admin, IFastBridgeV2, IFastBridgeV2Errors {
if (params.sender == address(0) || params.to == address(0)) revert ZeroAddress();
if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();
if (params.deadline < block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();
if (paramsV2.callParams.length > MAX_CALL_PARAMS_LENGTH) revert CallParamsLengthAboveMax();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Ensure CallParamsLengthAboveMax error is defined

The code uses revert CallParamsLengthAboveMax();, but there is no visible definition of the CallParamsLengthAboveMax error. Make sure this custom error is declared appropriately in the contract or imported from the correct interface.

Add the error definition to the contract:

+ error CallParamsLengthAboveMax();

Committable suggestion was skipped due to low confidence.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 26

🧹 Outside diff range and nitpick comments (24)
packages/contracts-rfq/test/mocks/NoOpContract.sol (1)

4-4: Consider adding a brief explanation for disabling the Solhint rule.

While disabling the no-empty-blocks rule is appropriate for this mock contract, it's beneficial to provide a brief explanation in the comment. This helps other developers understand the intention behind disabling the rule.

Consider updating the comment as follows:

-// solhint-disable-next-line no-empty-blocks
+// solhint-disable-next-line no-empty-blocks -- Intentionally empty mock contract
packages/contracts-rfq/contracts/interfaces/IFastBridgeRecipient.sol (2)

1-2: LGTM! Consider specifying a more precise Solidity version.

The SPDX license identifier and pragma solidity version are correctly placed. However, for better version control and to avoid potential future incompatibilities, consider specifying a more precise Solidity version range.

You might want to update the pragma statement to a more specific version range, for example:

pragma solidity >=0.8.0 <0.9.0;

This ensures compatibility with Solidity 0.8.x versions while preventing potential issues with future major releases.


4-13: LGTM! Consider adding NatSpec documentation.

The interface and function declarations are well-structured and follow Solidity conventions. The function modifiers (external, payable) are appropriate for the intended use.

To improve code readability and provide better documentation, consider adding NatSpec comments to the interface and function. For example:

/// @title IFastBridgeRecipient
/// @notice Interface for contracts that can receive tokens via a fast bridge
interface IFastBridgeRecipient {
    /// @notice Handles the receipt of tokens transferred via a fast bridge
    /// @param token The address of the token being transferred
    /// @param amount The amount of tokens being transferred
    /// @param callParams Additional parameters for the transfer
    /// @return A bytes4 value indicating the result of the operation
    function fastBridgeTransferReceived(
        address token,
        uint256 amount,
        bytes memory callParams
    )
        external
        payable
        returns (bytes4);
}
packages/contracts-rfq/test/mocks/NonPayableRecipient.sol (1)

6-9: LGTM: Function implementation is correct for testing purposes.

The fastBridgeTransferReceived function is correctly implemented as a mock. A few observations:

  1. The function is properly marked as external and pure.
  2. Returning the function selector is a common pattern for interface implementations.
  3. The notice comment clearly states that the function is incorrectly implemented (not payable) for testing purposes.

Minor suggestion: Consider naming the function parameters for improved readability, even in test contracts.

packages/contracts-rfq/test/mocks/NoReturnValueRecipient.sol (2)

4-4: Consider using more specific linter rule disables.

The solhint-disable directive is currently disabling all linter rules for the entire file. It's generally better to disable only specific rules that are necessary, and preferably only for the relevant code sections. This helps maintain code quality and catch potential issues early.

Consider replacing the global disable with specific rule disables as needed, or add a comment explaining why all rules need to be disabled for this file.


11-12: LGTM: Correctly implemented mock function with a minor suggestion.

The fastBridgeTransferReceived() function is correctly implemented as a mock that doesn't return any value, which aligns with the contract's purpose. The natspec comment clearly indicates that this is an incorrect implementation, which is crucial for testing purposes.

Consider adding a comment within the function body to explain why it's intentionally left empty. For example:

function fastBridgeTransferReceived(address, uint256, bytes memory) external payable {
    // Intentionally left empty for testing purposes
}

This can help prevent confusion for developers who might come across this code in the future.

packages/contracts-rfq/contracts/interfaces/IFastBridgeV2Errors.sol (3)

6-6: LGTM. Consider adding parameters for more informative errors.

The new CallParamsLengthAboveMax error is a good addition for handling cases where call parameters exceed a maximum length.

Consider adding parameters to provide more context, such as:

error CallParamsLengthAboveMax(uint256 actualLength, uint256 maxLength);

This would make debugging easier by providing specific information about the error condition.


14-14: LGTM. Consider adding parameters for more detailed error reporting.

The new RecipientIncorrectReturnValue error is a good addition for handling cases where a recipient returns an incorrect value.

To enhance debugging capabilities, consider adding parameters to provide more context:

error RecipientIncorrectReturnValue(bytes expectedValue, bytes actualValue);

This would allow for more precise error reporting and easier troubleshooting.


6-16: Consider reorganizing errors for better readability.

While the new errors are good additions, their placement within the interface could be improved for better readability and maintainability.

Consider the following suggestions:

  1. Group related errors together. For example, place RecipientIncorrectReturnValue and RecipientNoReturnValue next to each other.
  2. Consider organizing all errors alphabetically for easier lookup.
  3. Remove the empty line (line 16) to maintain consistent spacing throughout the interface.

These changes would enhance the overall structure and make it easier to navigate the interface as it grows.

packages/contracts-rfq/test/mocks/ExcessiveReturnValueRecipient.sol (3)

6-7: LGTM: Clear contract declaration and documentation.

The contract name is descriptive and the documentation clearly states its purpose as a mock for testing. The warning against production use is crucial.

Consider adding a brief explanation of why this mock is "incorrectly implemented" in the comment to provide more context for other developers.


11-14: LGTM: Correctly implemented mock function with intentional error.

The fastBridgeTransferReceived function is implemented as intended for testing purposes, returning excessive data. The comment clearly indicates that this is an incorrect implementation.

Consider adding a comment explaining the specific way in which this implementation is incorrect (i.e., returning an additional uint256 value that's not part of the interface). This would provide more clarity for developers using this mock.


1-15: Overall: Well-implemented mock contract for testing purposes.

This mock contract is well-structured, properly documented, and serves its intended purpose for testing. The intentional errors are clearly marked, and the contract adheres to Solidity best practices. The warnings against production use are appropriately placed.

Ensure that the tests using this mock contract explicitly check for the excessive return value to validate error handling in the main contract. This will help maintain the robustness of your testing suite.

packages/contracts-rfq/test/FastBridgeV2.Src.Exclusivity.t.sol (2)

11-12: Improved test setup with dedicated functions

The changes in createFixturesV2() enhance the code structure by introducing dedicated functions for setting up token and ETH exclusivity parameters. This approach improves readability and maintainability of the test setup.

Consider adding comments to explain the purpose of setTokenTestExclusivityParams and setEthTestExclusivityParams functions if they are not already documented in the parent class.


Line range hint 15-18: Improved flexibility in bridge parameter handling

The changes in the bridge() function enhance its flexibility by allowing different parameters to be used based on the origin token type. This is a good improvement in terms of functionality.

Consider adding a brief comment explaining the difference between ethParamsV2 and tokenParamsV2 for improved clarity. Also, you might want to split the ternary operator into an if-else statement for better readability, especially if more complex logic might be added in the future.

packages/contracts-rfq/test/FastBridgeV2.Dst.Exclusivity.t.sol (1)

Line range hint 1-180: Consider adding tests for the new callParams functionality

While the existing tests remain valid after the addition of the callParams field, it's important to ensure that this new functionality is properly tested. Consider adding new test cases that:

  1. Verify the correct handling of non-empty callParams in both token and ETH relay operations.
  2. Test edge cases related to callParams, such as very long strings or special characters.
  3. Ensure that the callParams field is correctly passed through the entire bridge process.

These additional tests will help maintain the robustness of the FastBridgeV2 contract and prevent potential issues related to the new field.

Would you like assistance in drafting these additional test cases?

packages/contracts-rfq/CHANGELOG.md (1)

6-11: LGTM! Consider adding more detail to the feature description.

The new version entry (0.7.0) is well-formatted and follows the conventional commit guidelines. The link to compare versions and the issue reference are correctly included.

To improve clarity for users and developers, consider expanding on the feature description. For example:
"Added support for arbitrary calls without requiring additional native value, enhancing flexibility in contract interactions."

🧰 Tools
🪛 Markdownlint

9-9: Expected: h2; Actual: h3
Heading levels should only increment by one level at a time

(MD001, heading-increment)

packages/contracts-rfq/test/FastBridgeV2.GasBench.Src.t.sol (3)

Line range hint 107-112: LGTM! Consider adding a comment for clarity.

The refactoring improves the readability of the test by using the setTokenTestExclusivityParams helper function. This change encapsulates the exclusivity parameter setup, making the test more maintainable.

Consider adding a brief comment explaining the purpose of setTokenTestExclusivityParams for better documentation:

+        // Set up exclusivity parameters for the token bridge test
         setTokenTestExclusivityParams(relayerA, EXCLUSIVITY_PERIOD);

Line range hint 188-193: LGTM! Consider adding a comment for consistency.

The refactoring improves the readability of the ETH bridging test by using the setEthTestExclusivityParams helper function. This change is consistent with the token bridging test and enhances maintainability.

For consistency with the token bridging test, consider adding a brief comment explaining the purpose of setEthTestExclusivityParams:

+        // Set up exclusivity parameters for the ETH bridge test
         setEthTestExclusivityParams(relayerA, EXCLUSIVITY_PERIOD);

Line range hint 1-265: Consider further test structure improvements in the future.

The recent changes to test_bridge_token_withExclusivity and test_bridge_eth_withExclusivity have improved the code's readability and maintainability. To build on this improvement, consider the following suggestions for future refactoring:

  1. Implement a beforeEach or similar setup function to reduce duplication in test setups.
  2. Group related tests using describe blocks (if supported by your testing framework) to improve organization.
  3. Consider parameterizing tests for different scenarios to reduce code duplication further.

These suggestions aim to enhance the overall structure and maintainability of the test suite in the long term.

packages/contracts-rfq/test/FastBridgeV2.Encoding.t.sol (2)

50-55: Consider rephrasing comments for clarity and professionalism

The comments contain informal language ("This is weird, but it is what it is.") which can be rephrased to maintain a formal tone and enhance clarity.

Suggested change:

-// which is ALWAYS equal to 32 (data starts right after the offset). This is weird, but it is what it is.
+// which is always equal to 32 (data starts immediately after the offset). This behavior is due to Solidity's encoding of dynamic types.

Line range hint 56-62: Reevaluate or remove the skipped test

The test test_getBridgeTransaction_supportsV2 is currently skipped using vm.skip(true); and contains a TODO note to reevaluate its necessity. Keeping skipped tests can clutter the test suite and may lead to confusion.

Consider the following actions:

  • If the test is no longer needed, remove it to keep the codebase clean.
  • If the test is important for future changes, consider implementing it or creating an issue to track this task.
packages/contracts-rfq/contracts/interfaces/IFastBridgeV2.sol (1)

Line range hint 46-62: Address the TODO regarding encoding scheme to optimize gas costs

The TODO comment suggests considering changes to the encoding scheme to prevent extra gas consumption during decoding. With the addition of callParams, revisiting the encoding strategy for BridgeTransactionV2 could improve gas efficiency.

Would you like assistance in proposing an optimized encoding scheme that could reduce gas costs?

packages/contracts-rfq/test/FastBridgeV2.Dst.ArbitraryCall.t.sol (2)

14-19: Add NatSpec documentation to createFixtures()

Consider adding NatSpec comments to the createFixtures() function to improve code readability and provide clarity on its purpose in the test setup.


21-25: Add NatSpec documentation to createFixturesV2()

Adding NatSpec comments to the createFixturesV2() function would enhance maintainability by explaining its role in initializing test parameters.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 8311329 and 4b49879.

📒 Files selected for processing (22)
  • packages/contracts-rfq/CHANGELOG.md (1 hunks)
  • packages/contracts-rfq/contracts/FastBridgeV2.sol (9 hunks)
  • packages/contracts-rfq/contracts/interfaces/IFastBridgeRecipient.sol (1 hunks)
  • packages/contracts-rfq/contracts/interfaces/IFastBridgeV2.sol (2 hunks)
  • packages/contracts-rfq/contracts/interfaces/IFastBridgeV2Errors.sol (1 hunks)
  • packages/contracts-rfq/package.json (1 hunks)
  • packages/contracts-rfq/test/FastBridgeV2.Dst.ArbitraryCall.t.sol (1 hunks)
  • packages/contracts-rfq/test/FastBridgeV2.Dst.Exclusivity.t.sol (1 hunks)
  • packages/contracts-rfq/test/FastBridgeV2.Dst.t.sol (3 hunks)
  • packages/contracts-rfq/test/FastBridgeV2.Encoding.t.sol (1 hunks)
  • packages/contracts-rfq/test/FastBridgeV2.GasBench.Dst.Excl.t.sol (1 hunks)
  • packages/contracts-rfq/test/FastBridgeV2.GasBench.Src.t.sol (2 hunks)
  • packages/contracts-rfq/test/FastBridgeV2.Src.ArbitraryCall.t.sol (1 hunks)
  • packages/contracts-rfq/test/FastBridgeV2.Src.Exclusivity.Negative.t.sol (1 hunks)
  • packages/contracts-rfq/test/FastBridgeV2.Src.Exclusivity.t.sol (1 hunks)
  • packages/contracts-rfq/test/FastBridgeV2.t.sol (3 hunks)
  • packages/contracts-rfq/test/mocks/ExcessiveReturnValueRecipient.sol (1 hunks)
  • packages/contracts-rfq/test/mocks/IncorrectReturnValueRecipient.sol (1 hunks)
  • packages/contracts-rfq/test/mocks/NoOpContract.sol (1 hunks)
  • packages/contracts-rfq/test/mocks/NoReturnValueRecipient.sol (1 hunks)
  • packages/contracts-rfq/test/mocks/NonPayableRecipient.sol (1 hunks)
  • packages/contracts-rfq/test/mocks/RecipientMock.sol (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • packages/contracts-rfq/package.json
🧰 Additional context used
🪛 Markdownlint
packages/contracts-rfq/CHANGELOG.md

9-9: Expected: h2; Actual: h3
Heading levels should only increment by one level at a time

(MD001, heading-increment)

🔇 Additional comments (32)
packages/contracts-rfq/test/mocks/NoOpContract.sol (3)

1-2: LGTM: Appropriate license and Solidity version.

The MIT license is suitable for open-source projects, and the Solidity version (^0.8.0) is recent and allows for minor updates.


5-6: LGTM: Clear contract name and purpose.

The contract name NoOpContract clearly indicates its purpose, and the docstring provides a concise explanation of why the contract needs to accept ETH. This is helpful for developers who might use this mock contract in tests.


7-7: LGTM: Correctly implemented receive function.

The receive function is properly implemented as an external payable function with an empty body. This allows the mock contract to accept ETH transactions without performing any operations, which is the intended behavior.

packages/contracts-rfq/test/mocks/NonPayableRecipient.sol (2)

4-5: LGTM: Contract declaration is clear and well-documented.

The contract name NonPayableRecipient clearly indicates its purpose, and the notice comment explicitly states it's for testing purposes only. This is good practice for mock contracts.


1-10: LGTM: Well-structured mock contract for testing purposes.

This NonPayableRecipient contract is well-designed for its intended use as a test mock:

  1. It's concise and focused on a single purpose.
  2. The contract and its function are clearly documented as test-only and intentionally incorrect.
  3. The implementation serves its purpose for testing scenarios where a non-payable recipient is needed.

The contract is suitable for its intended use in testing and poses no risk as long as it's not used in production environments.

packages/contracts-rfq/test/mocks/NoReturnValueRecipient.sol (2)

6-7: LGTM: Clear contract naming and documentation.

The contract name NoReturnValueRecipient is descriptive, and the natspec comment provides crucial information about its purpose and limitations. The explicit warning against production use is an important safeguard.


8-9: LGTM: Correctly implemented receive() function.

The receive() function is properly implemented to accept ETH payments, which is necessary for this mock contract. The natspec comment provides clear context for its purpose.

packages/contracts-rfq/test/FastBridgeV2.GasBench.Dst.Excl.t.sol (1)

16-17: Excellent refactoring of exclusivity parameter setup!

The changes improve code readability and maintainability by consolidating the logic for setting exclusivity parameters into dedicated functions. Using the EXCLUSIVITY_PERIOD constant ensures consistency across the contract.

packages/contracts-rfq/contracts/interfaces/IFastBridgeV2Errors.sol (1)

15-15: LGTM. Clear and concise error definition.

The new RecipientNoReturnValue error is a good addition for handling cases where a recipient doesn't return a value when one was expected. The error is self-explanatory and doesn't require additional parameters.

packages/contracts-rfq/test/mocks/RecipientMock.sol (4)

1-7: LGTM: Contract structure and interface implementation are well-defined.

The contract structure follows Solidity best practices, including proper SPDX license identifier, pragma statement, and clear import of the interface. The contract name and purpose are explicitly stated, which is good for maintainability.


8-9: LGTM: Receive function is correctly implemented.

The receive() function is properly implemented as external payable, allowing the contract to accept ETH. The accompanying comment clearly explains its purpose in the context of this mock contract.


11-14: LGTM: fastBridgeTransferReceived function is correctly implemented for a mock.

The fastBridgeTransferReceived function is properly implemented as external payable and matches the interface signature. The minimal implementation, which returns the function selector, is sufficient for testing purposes and ensures interface compliance.


1-15: Overall, the RecipientMock contract is well-implemented for testing purposes.

The contract successfully implements the IFastBridgeRecipient interface with minimal, but sufficient implementations for testing. It's clearly marked as a mock for testing, which is good practice. The code is clean, well-commented, and follows Solidity best practices.

packages/contracts-rfq/test/mocks/ExcessiveReturnValueRecipient.sol (2)

1-4: LGTM: Appropriate license, Solidity version, and import statement.

The contract header is well-structured with the correct license identifier and Solidity version. The import statement for the IFastBridgeRecipient interface is correctly implemented.


8-9: LGTM: Correctly implemented receive function with clear documentation.

The receive() function is properly implemented to allow the contract to accept ETH. The comment clearly explains the purpose of this function in the context of the mock contract.

packages/contracts-rfq/test/mocks/IncorrectReturnValueRecipient.sol (3)

1-7: LGTM: Clear contract purpose and implementation.

The contract declaration and purpose are well-defined. The explicit warning about not using this mock in production is a good practice to prevent misuse.


8-9: LGTM: Correctly implemented receive function.

The receive function is properly implemented to allow the contract to accept ETH, which is necessary for testing scenarios.


11-15: LGTM: Correctly implemented mock function for testing.

The fastBridgeTransferReceived function is intentionally implemented to return an incorrect value by flipping the last bit of the selector. This aligns with the contract's purpose as a mock for testing incorrect implementations.

To ensure this mock is only used in test files, run the following script:

packages/contracts-rfq/test/FastBridgeV2.Dst.Exclusivity.t.sol (1)

14-15: Update to BridgeParamsV2 structure: Added callParams field

The createFixturesV2 function has been updated to include a new callParams field in both tokenParamsV2 and ethParamsV2 structures. Additionally, the quoteId field is now explicitly set to an empty string.

These changes suggest an update to the BridgeParamsV2 structure in the main contract. While they don't affect the logic of the existing tests, please ensure that:

  1. The main FastBridgeV2 contract has been updated to include the callParams field in its BridgeParamsV2 structure.
  2. Any functions or logic depending on the BridgeParamsV2 structure in the main contract have been adjusted to handle the new callParams field.
  3. The explicit setting of quoteId to an empty string aligns with the expected behavior in the main contract.

To verify these changes, please run the following script:

Also applies to: 20-21

✅ Verification successful

Verification Successful: callParams Field Properly Added and Utilized

The BridgeParamsV2 structure in IFastBridgeV2.sol has been successfully updated to include the callParams field. Additionally, this field is correctly utilized across multiple test files within the packages/contracts-rfq/test/ directory.

  • Struct Update:

    • callParams has been added to the BridgeParamsV2 structure in contracts/interfaces/IFastBridgeV2.sol.
  • Test Coverage:

    • The callParams field is appropriately set and tested in various test cases, ensuring alignment with the updated contract structure.

No issues were found regarding the absence of removed or replaced code in the specified lines of FastBridgeV2.Dst.Exclusivity.t.sol.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the changes in the FastBridgeV2 contract and related files

# Check for the updated BridgeParamsV2 structure in the main contract
echo "Checking for updated BridgeParamsV2 structure:"
rg --type solidity -A 10 "struct BridgeParamsV2" packages/contracts-rfq/src/

# Check for any usage of callParams in the main contract
echo "\nChecking for usage of callParams:"
rg --type solidity "callParams" packages/contracts-rfq/src/

# Check for any other test files that might need similar updates
echo "\nChecking for other test files that might need updates:"
rg --type solidity "BridgeParamsV2" packages/contracts-rfq/test/

Length of output: 609


Script:

#!/bin/bash
# Description: Verify the changes in the FastBridgeV2 contract and related files

# Check for the updated BridgeParamsV2 structure in the main contract
echo "Checking for updated BridgeParamsV2 structure:"
rg -g "*.sol" -A 10 "struct BridgeParamsV2" packages/contracts-rfq/src/

# Check for any usage of callParams in the main contract
echo "\nChecking for usage of callParams:"
rg -g "*.sol" "callParams" packages/contracts-rfq/src/

# Check for any other test files that might need similar updates
echo "\nChecking for other test files that might need updates:"
rg -g "*.sol" "BridgeParamsV2" packages/contracts-rfq/test/

Length of output: 1757


Script:

#!/bin/bash
# Description: Verify the changes in the FastBridgeV2 contract and related files by searching the entire repository.

# Check for the updated BridgeParamsV2 structure in the main contract
echo "Checking for updated BridgeParamsV2 structure across the repository:"
rg -g "*.sol" -A 10 "struct BridgeParamsV2"

# Check for any usage of callParams in the repository
echo "\nChecking for usage of callParams across the repository:"
rg -g "*.sol" "callParams"

# Check for any other test files that might need similar updates
echo "\nChecking for other test files that might need updates:"
rg -g "*.sol" "BridgeParamsV2" packages/contracts-rfq/test/

Length of output: 10513

packages/contracts-rfq/test/FastBridgeV2.Src.ArbitraryCall.t.sol (1)

1-44: Tests are well-implemented

The tests correctly verify the bridge's behavior with call parameters at the boundary lengths, ensuring proper handling of maximum allowed sizes and correct reversion when exceeding limits.

packages/contracts-rfq/contracts/interfaces/IFastBridgeV2.sol (3)

36-41: Addition of callParams to BridgeParamsV2 enhances functionality

The inclusion of bytes callParams in BridgeParamsV2 allows passing arbitrary call parameters to the destination recipient, increasing flexibility and potential use cases.


39-39: Verify the need for int256 type for quoteExclusivitySeconds

The quoteExclusivitySeconds parameter is currently defined as int256. Since it represents a period of time (duration), should this be a uint256 to prevent negative values and align with typical usage of time intervals?


62-62: Inclusion of callParams in BridgeTransactionV2

Adding bytes callParams to BridgeTransactionV2 ensures that arbitrary call parameters are included in the bridge transaction, enhancing the functionality and flexibility of the bridge.

packages/contracts-rfq/test/FastBridgeV2.t.sol (1)

213-221: getMockQuoteId function is correctly implemented

The function appropriately returns mock quote IDs based on the provided relayer address.

packages/contracts-rfq/test/FastBridgeV2.Dst.ArbitraryCall.t.sol (8)

59-81: Comprehensive tests for recipient not being a contract

The test functions test_relay_token_revert_recipientNotContract() and test_relay_eth_revert_recipientNotContract() correctly verify that the relay function reverts when the recipient is not a contract, ensuring robust error handling.


85-116: Thorough testing of excessive return value recipients

The tests for handling recipients with excessive return values are well-designed, ensuring that the contract correctly reverts when unexpected return data is received.


119-150: Validating behavior with incorrect return value recipients

The test cases cover scenarios where recipients return incorrect values, which is crucial for ensuring that the relay function handles such cases appropriately.


153-176: Handling no-operation recipients

The tests effectively verify that the relay function reverts when interacting with recipients that perform no operation, ensuring consistent behavior.


179-210: Testing recipients with no return value

The included tests for recipients that do not return any value are important for verifying that the relay function handles these scenarios as expected.


213-235: Simulating recipient reverts

The test_relay_token_revert_recipientReverts() and related functions correctly mock recipient reverts and ensure that the relay function processes these reverts appropriately.


237-249: Consistent handling of no call parameters with recipient reverts

The tests for relaying ETH without call parameters and handling recipient reverts ensure that the relay function maintains consistent error handling in various scenarios.


38-40: Ensure expected call is properly configured in expectBridgeRelayed()

The overridden expectBridgeRelayed() function correctly adds an expectation for the arbitrary call to the recipient. Ensure that the getExpectedCalldata() function accurately reflects the intended calldata structure.

Run the following script to verify that getExpectedCalldata() matches the actual function signature:

Comment on lines +5 to +12
function fastBridgeTransferReceived(
address token,
uint256 amount,
bytes memory callParams
)
external
payable
returns (bytes4);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Inconsistent Implementations of fastBridgeTransferReceived Function

Several implementations of IFastBridgeRecipient exhibit inconsistencies in the fastBridgeTransferReceived function:

  • IncorrectReturnValueRecipient.sol: Returns a modified bytes4 selector.
  • NonPayableRecipient.sol: Declares the function as pure instead of payable and returns the selector.
  • ExcessiveReturnValueRecipient.sol: Returns both bytes4 and uint256, deviating from the expected return type.
  • NoReturnValueRecipient.sol: Does not return any value, contrary to the interface specification.

These discrepancies can lead to security vulnerabilities and unexpected behaviors within the contracts.

🔗 Analysis chain

Function parameters and return type look good. Consider access control implications.

The function parameters (token, amount, callParams) and return type (bytes4) are well-chosen for a flexible token transfer receipt mechanism. The use of a bytes parameter for callParams allows for extensibility.

However, there are some security considerations to keep in mind:

  1. Ensure that contracts implementing this interface include proper access control mechanisms to prevent unauthorized calls to fastBridgeTransferReceived.
  2. Validate and sanitize the callParams input in the implementing contract to prevent potential security vulnerabilities.
  3. Consider documenting the expected format and usage of the callParams parameter for implementers.
  4. Clarify the meaning of the bytes4 return value, possibly by defining specific return codes in the interface.

To verify the usage of this interface across the project, run the following script:

This will help ensure that the interface is being used correctly and securely throughout the project.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find implementations and usages of IFastBridgeRecipient

echo "Searching for implementations of IFastBridgeRecipient:"
ast-grep --lang solidity --pattern $'contract $_ is IFastBridgeRecipient'

echo "\nSearching for usages of fastBridgeTransferReceived:"
rg --type solidity -A 5 $'fastBridgeTransferReceived'

Length of output: 513


Script:

#!/bin/bash
# Description: Find implementations and usages of IFastBridgeRecipient in Solidity files

echo "Searching for implementations of IFastBridgeRecipient:"
rg --type-add 'solidity:*.sol' --type solidity 'contract\s+\w+\s+is\s+IFastBridgeRecipient' .

echo -e "\nSearching for usages of fastBridgeTransferReceived:"
rg --type-add 'solidity:*.sol' --type solidity -A 5 'fastBridgeTransferReceived' .

Length of output: 5718


Script:

#!/bin/bash
# Description: Extract fastBridgeTransferReceived function details from IFastBridgeRecipient implementations

# List of implementation files
files=(
  "./packages/contracts-rfq/test/mocks/IncorrectReturnValueRecipient.sol"
  "./packages/contracts-rfq/test/mocks/RecipientMock.sol"
  "./packages/contracts-rfq/test/mocks/NonPayableRecipient.sol"
  "./packages/contracts-rfq/test/mocks/NoReturnValueRecipient.sol"
  "./packages/contracts-rfq/test/mocks/ExcessiveReturnValueRecipient.sol"
)

for file in "${files[@]}"; do
  echo "Extracting from $file:"
  rg 'function fastBridgeTransferReceived' "$file" -A 5
  echo -e "\n---\n"
done

Length of output: 2917

# [0.7.0](https://github.com/synapsecns/sanguine/compare/@synapsecns/contracts-rfq@0.6.2...@synapsecns/contracts-rfq@0.7.0) (2024-10-07)


### Features
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Adjust heading level for consistency

The "Features" section is currently using an H3 heading (###). To maintain consistency with the Keep a Changelog format and address the static analysis hint, consider changing it to an H2 heading (##).

Apply this change:

-### Features
+## Features

This adjustment will improve the overall structure and readability of the changelog.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
### Features
## Features
🧰 Tools
🪛 Markdownlint

9-9: Expected: h2; Actual: h3
Heading levels should only increment by one level at a time

(MD001, heading-increment)

Comment on lines +19 to +43
function test_bridge_token_callParamsLengthMax() public {
bytes memory callParams = new bytes(2 ** 16 - 1);
setTokenTestCallParams(callParams);
test_bridge_token();
}

function test_bridge_eth_callParamsLengthMax() public {
bytes memory callParams = new bytes(2 ** 16 - 1);
setEthTestCallParams(callParams);
test_bridge_eth();
}

function test_bridge_token_revert_callParamsLengthAboveMax() public {
bytes memory callParams = new bytes(2 ** 16);
setTokenTestCallParams(callParams);
vm.expectRevert(CallParamsLengthAboveMax.selector);
bridge({caller: userA, msgValue: 0, params: tokenParams, paramsV2: tokenParamsV2});
}

function test_bridge_eth_revert_callParamsLengthAboveMax() public {
bytes memory callParams = new bytes(2 ** 16);
setEthTestCallParams(callParams);
vm.expectRevert(CallParamsLengthAboveMax.selector);
bridge({caller: userA, msgValue: ethParams.originAmount, params: ethParams, paramsV2: ethParamsV2});
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider defining constants for maximum call parameters lengths

To improve readability and maintainability, consider defining constants for the maximum call parameters length (2 ** 16 - 1) and the length exceeding the maximum (2 ** 16). This will make the purpose of these values clearer and avoid magic numbers.

Apply this diff:

+    uint256 constant MAX_CALL_PARAMS_LENGTH = 2 ** 16 - 1;
+    uint256 constant ABOVE_MAX_CALL_PARAMS_LENGTH = 2 ** 16;

     function test_bridge_token_callParamsLengthMax() public {
-        bytes memory callParams = new bytes(2 ** 16 -1);
+        bytes memory callParams = new bytes(MAX_CALL_PARAMS_LENGTH);
         setTokenTestCallParams(callParams);
         test_bridge_token();
     }

     function test_bridge_eth_callParamsLengthMax() public {
-        bytes memory callParams = new bytes(2 ** 16 -1);
+        bytes memory callParams = new bytes(MAX_CALL_PARAMS_LENGTH);
         setEthTestCallParams(callParams);
         test_bridge_eth();
     }

     function test_bridge_token_revert_callParamsLengthAboveMax() public {
-        bytes memory callParams = new bytes(2 ** 16);
+        bytes memory callParams = new bytes(ABOVE_MAX_CALL_PARAMS_LENGTH);
         setTokenTestCallParams(callParams);
         vm.expectRevert(CallParamsLengthAboveMax.selector);
         bridge({caller: userA, msgValue: 0, params: tokenParams, paramsV2: tokenParamsV2});
     }

     function test_bridge_eth_revert_callParamsLengthAboveMax() public {
-        bytes memory callParams = new bytes(2 ** 16);
+        bytes memory callParams = new bytes(ABOVE_MAX_CALL_PARAMS_LENGTH);
         setEthTestCallParams(callParams);
         vm.expectRevert(CallParamsLengthAboveMax.selector);
         bridge({caller: userA, msgValue: ethParams.originAmount, params: ethParams, paramsV2: ethParamsV2});
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function test_bridge_token_callParamsLengthMax() public {
bytes memory callParams = new bytes(2 ** 16 - 1);
setTokenTestCallParams(callParams);
test_bridge_token();
}
function test_bridge_eth_callParamsLengthMax() public {
bytes memory callParams = new bytes(2 ** 16 - 1);
setEthTestCallParams(callParams);
test_bridge_eth();
}
function test_bridge_token_revert_callParamsLengthAboveMax() public {
bytes memory callParams = new bytes(2 ** 16);
setTokenTestCallParams(callParams);
vm.expectRevert(CallParamsLengthAboveMax.selector);
bridge({caller: userA, msgValue: 0, params: tokenParams, paramsV2: tokenParamsV2});
}
function test_bridge_eth_revert_callParamsLengthAboveMax() public {
bytes memory callParams = new bytes(2 ** 16);
setEthTestCallParams(callParams);
vm.expectRevert(CallParamsLengthAboveMax.selector);
bridge({caller: userA, msgValue: ethParams.originAmount, params: ethParams, paramsV2: ethParamsV2});
}
uint256 constant MAX_CALL_PARAMS_LENGTH = 2 ** 16 - 1;
uint256 constant ABOVE_MAX_CALL_PARAMS_LENGTH = 2 ** 16;
function test_bridge_token_callParamsLengthMax() public {
bytes memory callParams = new bytes(MAX_CALL_PARAMS_LENGTH);
setTokenTestCallParams(callParams);
test_bridge_token();
}
function test_bridge_eth_callParamsLengthMax() public {
bytes memory callParams = new bytes(MAX_CALL_PARAMS_LENGTH);
setEthTestCallParams(callParams);
test_bridge_eth();
}
function test_bridge_token_revert_callParamsLengthAboveMax() public {
bytes memory callParams = new bytes(ABOVE_MAX_CALL_PARAMS_LENGTH);
setTokenTestCallParams(callParams);
vm.expectRevert(CallParamsLengthAboveMax.selector);
bridge({caller: userA, msgValue: 0, params: tokenParams, paramsV2: tokenParamsV2});
}
function test_bridge_eth_revert_callParamsLengthAboveMax() public {
bytes memory callParams = new bytes(ABOVE_MAX_CALL_PARAMS_LENGTH);
setEthTestCallParams(callParams);
vm.expectRevert(CallParamsLengthAboveMax.selector);
bridge({caller: userA, msgValue: ethParams.originAmount, params: ethParams, paramsV2: ethParamsV2});
}

Comment on lines +11 to +14
// Populate the fields using the absolute exclusivity period
setTokenTestExclusivityParams(relayerA, EXCLUSIVITY_PERIOD_ABS);
setEthTestExclusivityParams(relayerB, EXCLUSIVITY_PERIOD_ABS);
// Override with negative exclusivity period
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Optimize parameter initialization by passing negative exclusivity periods directly

Currently, the code initializes the exclusivity parameters with positive values and then immediately overrides them with negative values. To eliminate redundancy and improve code clarity, consider passing the negative exclusivity period directly to the initialization functions.

Apply this diff to pass negative exclusivity periods directly:

 function createFixturesV2() public virtual override {
-    // Populate the fields using the absolute exclusivity period
-    setTokenTestExclusivityParams(relayerA, EXCLUSIVITY_PERIOD_ABS);
-    setEthTestExclusivityParams(relayerB, EXCLUSIVITY_PERIOD_ABS);
-    // Override with negative exclusivity period
-    tokenParamsV2.quoteExclusivitySeconds = -int256(EXCLUSIVITY_PERIOD_ABS);
-    ethParamsV2.quoteExclusivitySeconds = -int256(EXCLUSIVITY_PERIOD_ABS);
+    // Populate the fields using the negative exclusivity period
+    setTokenTestExclusivityParams(relayerA, -int256(EXCLUSIVITY_PERIOD_ABS));
+    setEthTestExclusivityParams(relayerB, -int256(EXCLUSIVITY_PERIOD_ABS));
     tokenTx.exclusivityEndTime = block.timestamp - EXCLUSIVITY_PERIOD_ABS;
     ethTx.exclusivityEndTime = block.timestamp - EXCLUSIVITY_PERIOD_ABS;
 }

Committable suggestion was skipped due to low confidence.

Comment on lines +127 to +138
tokenParamsV2 = IFastBridgeV2.BridgeParamsV2({
quoteRelayer: address(0),
quoteExclusivitySeconds: 0,
quoteId: bytes(""),
callParams: bytes("")
});
ethParamsV2 = IFastBridgeV2.BridgeParamsV2({
quoteRelayer: address(0),
quoteExclusivitySeconds: 0,
quoteId: bytes(""),
callParams: bytes("")
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Refactor to eliminate code duplication in createFixturesV2

The initialization of tokenParamsV2 and ethParamsV2 is nearly identical. Consider creating a helper function to reduce code duplication and enhance maintainability.

Comment on lines +295 to +299
function test_relay_eth_noReturnValueRecipient_revertWhenCallParamsPresent() public virtual {
assertEmptyCallParams(ethTx.callParams);
setEthTestRecipient(noReturnValueRecipient);
test_relay_eth();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Test function may not be testing the intended scenario

The test function test_relay_eth_noReturnValueRecipient_revertWhenCallParamsPresent asserts that callParams are empty, which may not effectively test the scenario.

Assign a value to ethTx.callParams to accurately test the behavior when callParams are present.

Comment on lines +301 to +305
function test_relay_eth_withRelayerAddress_noReturnValueRecipient_revertWhenCallParamsPresent() public virtual {
assertEmptyCallParams(ethTx.callParams);
setEthTestRecipient(noReturnValueRecipient);
test_relay_eth_withRelayerAddress();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Test function may not be testing the intended scenario

test_relay_eth_withRelayerAddress_noReturnValueRecipient_revertWhenCallParamsPresent checks for empty callParams, which doesn't test the intended scenario suggested by the function name.

Modify ethTx.callParams to include data to properly test the expected revert behavior.

Comment on lines 145 to 150
if (params.sender == address(0) || params.to == address(0)) revert ZeroAddress();
if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();
if (params.deadline < block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();
if (paramsV2.callParams.length > MAX_CALL_PARAMS_LENGTH) revert CallParamsLengthAboveMax();
int256 exclusivityEndTime = int256(block.timestamp) + paramsV2.quoteExclusivitySeconds;
// exclusivityEndTime must be in range (0 .. params.deadline]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Refactor bridge function to reduce cyclomatic complexity.

The TODO comment suggests that the bridge function has a high cyclomatic complexity, which can make the code harder to understand and maintain. Consider refactoring the function by extracting portions of the logic into smaller, reusable functions to enhance readability and maintainability.

Comment on lines +130 to +132
// TODO: the note below isn't true anymore with the BridgeTransactionV2 struct
// since the variable length `callParams` was added. This needs to be fixed/acknowledged.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Update the outdated comment regarding getBridgeTransaction.

The TODO comment indicates that the note about decoding V1 fields is no longer accurate due to the addition of variable-length callParams in BridgeTransactionV2. Please update or remove the comment to reflect the current implementation to avoid confusion.

Comment on lines +371 to +382
bytes memory hookData =
abi.encodeCall(IFastBridgeRecipient.fastBridgeTransferReceived, (token, amount, callParams));
// This will bubble any revert messages from the hook function
bytes memory returnData = Address.functionCallWithValue({target: recipient, data: hookData, value: msgValue});
// Explicit revert if no return data at all
if (returnData.length == 0) revert RecipientNoReturnValue();
// Check that exactly a single return value was returned
if (returnData.length != 32) revert RecipientIncorrectReturnValue();
// Return value should be abi-encoded hook function selector
if (bytes32(returnData) != bytes32(IFastBridgeRecipient.fastBridgeTransferReceived.selector)) {
revert RecipientIncorrectReturnValue();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Correct the validation of the recipient's return value in _checkedCallRecipient.

In the _checkedCallRecipient function, the comparison between bytes32(returnData) and bytes32(IFastBridgeRecipient.fastBridgeTransferReceived.selector) may not work as intended because the function selector is 4 bytes, whereas the return data is 32 bytes. This could lead to incorrect validation results.

Apply this diff to fix the comparison by properly decoding the returned function selector:

        // Return value should be abi-encoded hook function selector
-       if (bytes32(returnData) != bytes32(IFastBridgeRecipient.fastBridgeTransferReceived.selector)) {
+       // Extract the returned selector from the return data
+       bytes4 returnedSelector = abi.decode(returnData, (bytes4));
+       if (returnedSelector != IFastBridgeRecipient.fastBridgeTransferReceived.selector) {
            revert RecipientIncorrectReturnValue();
        }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
bytes memory hookData =
abi.encodeCall(IFastBridgeRecipient.fastBridgeTransferReceived, (token, amount, callParams));
// This will bubble any revert messages from the hook function
bytes memory returnData = Address.functionCallWithValue({target: recipient, data: hookData, value: msgValue});
// Explicit revert if no return data at all
if (returnData.length == 0) revert RecipientNoReturnValue();
// Check that exactly a single return value was returned
if (returnData.length != 32) revert RecipientIncorrectReturnValue();
// Return value should be abi-encoded hook function selector
if (bytes32(returnData) != bytes32(IFastBridgeRecipient.fastBridgeTransferReceived.selector)) {
revert RecipientIncorrectReturnValue();
}
bytes memory hookData =
abi.encodeCall(IFastBridgeRecipient.fastBridgeTransferReceived, (token, amount, callParams));
// This will bubble any revert messages from the hook function
bytes memory returnData = Address.functionCallWithValue({target: recipient, data: hookData, value: msgValue});
// Explicit revert if no return data at all
if (returnData.length == 0) revert RecipientNoReturnValue();
// Check that exactly a single return value was returned
if (returnData.length != 32) revert RecipientIncorrectReturnValue();
// Return value should be abi-encoded hook function selector
// Extract the returned selector from the return data
bytes4 returnedSelector = abi.decode(returnData, (bytes4));
if (returnedSelector != IFastBridgeRecipient.fastBridgeTransferReceived.selector) {
revert RecipientIncorrectReturnValue();
}

@trajan0x trajan0x closed this Oct 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants