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

status/proof mapping packing [SLT-186] #3173

Merged
merged 13 commits into from
Sep 27, 2024
Merged

Conversation

parodime
Copy link
Collaborator

@parodime parodime commented Sep 23, 2024

Description

A lot of functions are reading/writing from/to both bridgeStatuses and bridgeProofs, wasting more gas than necessary.

  • Pack these into a new internal mapping to take a single storage slot
  • Expose backwards-compatible views bridgeStatuses(bytes32) and bridgeProofs(bytes32)

Summary by CodeRabbit

  • New Features

    • Introduced a new structure for managing bridge transaction details, enhancing clarity and organization.
    • Added functions to retrieve transaction status and proof using transaction IDs.
  • Bug Fixes

    • Updated references in tests to align with the new interface, ensuring consistent functionality.
  • Documentation

    • Enhanced interface with new enumerations and structures for better tracking of bridge transaction statuses.
  • Tests

    • Updated test files to incorporate the new interface and ensure proper functionality across the board.

Copy link
Contributor

coderabbitai bot commented Sep 23, 2024

Walkthrough

The changes in this pull request focus on the FastBridgeV2 contract, specifically its state management for bridge transactions. The BridgeStatus enum has been removed, and its functionality has been integrated into a new structure called BridgeTxDetails, which consolidates transaction status and proof. New functions for retrieving transaction details have been introduced, and existing functions have been updated to utilize this new structure. The test files have also been modified to reference the updated interface, ensuring consistent functionality across the contract and its tests.

Changes

Files Change Summary
packages/contracts-rfq/contracts/FastBridgeV2.sol Removed BridgeStatus enum; introduced BridgeTxDetails structure; updated functions to use new mapping.
packages/contracts-rfq/test/FastBridgeV2.Src.t.sol Updated references to BridgeStatus to use IFastBridgeV2 interface; modified assertions accordingly.

Possibly related PRs

  • prove w/ tx id [SLT-181] #3169: The modifications to the prove function in this PR directly relate to the changes in the main PR, which also updates the prove function to handle transaction IDs more effectively.
  • rearrange refund validation checks [SLT-185] #3172: The updates to the refund function in the main PR, which include checks for transaction status, are relevant to the changes made in this PR that also modify the refund validation checks.
  • store relayer on relay [SLT-182] #3170: This PR introduces a new mapping for relay details in the FastBridgeV2 contract, which is related to the overall state management changes in the main PR that reorganizes transaction details.
  • reduce solhint warnings on FbV2 #3189: The changes in this PR regarding the reduction of solhint warnings include modifications to the FastBridgeV2 contract, which may relate to the overall code quality improvements seen in the main PR.
  • fix(contracts-rfq): gas estimation tests [SLT-275] #3204: This PR focuses on gas estimation tests for the RFQ contracts, which are relevant to the overall functionality and performance of the FastBridgeV2 contract as described in the main PR.

Suggested labels

size/m, Sol, Typescript

Suggested reviewers

  • trajan0x
  • ChiTimesChi
  • bigboydiamonds

Poem

🐰 In the meadow where bridges flow,
A contract changed, with a new status to show.
Tx details now, all neatly aligned,
With proofs and statuses, perfectly designed.
Hops of joy for the code so bright,
In the world of contracts, everything feels right! 🌼


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.

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: 10

Outside diff range and nitpick comments (2)
packages/contracts-rfq/test/FastBridgeV2.Src.t.sol (2)

312-314: LGTM: bridgeProofs access updated correctly.

The bridgeProofs access has been properly updated to use a struct-like syntax, which is consistent with the PR objectives of consolidating mappings. This change improves the code structure and readability.

Consider using destructuring assignment for better readability:

-(uint96 timestamp, address relayer) = (fastBridge.bridgeProofs(txId).timestamp, fastBridge.bridgeProofs(txId).relayer);
+var (timestamp, relayer) = (fastBridge.bridgeProofs(txId).timestamp, fastBridge.bridgeProofs(txId).relayer);

326-328: LGTM: bridgeProofs access updated correctly for eth test.

The bridgeProofs access has been properly updated to use a struct-like syntax in the eth test, which is consistent with the previous update for token tests and the PR objectives of consolidating mappings.

Consider using destructuring assignment for better readability:

-(uint96 timestamp, address relayer) = (fastBridge.bridgeProofs(txId).timestamp, fastBridge.bridgeProofs(txId).relayer);
+var (timestamp, relayer) = (fastBridge.bridgeProofs(txId).timestamp, fastBridge.bridgeProofs(txId).relayer);
Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 1eb6fa0 and 1348e63.

Files selected for processing (4)
  • packages/contracts-rfq/contracts/FastBridgeV2.sol (9 hunks)
  • packages/contracts-rfq/contracts/interfaces/IFastBridgeV2.sol (1 hunks)
  • packages/contracts-rfq/test/FastBridgeV2.Src.t.sol (30 hunks)
  • packages/contracts-rfq/test/FastBridgeV2.t.sol (1 hunks)
Additional comments not posted (24)
packages/contracts-rfq/test/FastBridgeV2.t.sol (1)

5-5: Approve new import, but verify its usage

The addition of the IFastBridgeV2 import is appropriate, likely reflecting updates to the FastBridge contract. However, I noticed that the test file doesn't explicitly use this new interface yet.

To ensure proper test coverage for the new interface:

  1. Verify if any test cases need updating to use IFastBridgeV2.
  2. Check if new test cases are required for any new functionality in IFastBridgeV2.

Run the following script to check for usage of IFastBridgeV2 in this test file:

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

17-17: LGTM: Import statement updated correctly.

The addition of IFastBridgeV2 to the import statement is consistent with the changes in the contract, allowing the use of IFastBridgeV2.BridgeStatus instead of FastBridgeV2.BridgeStatus.


170-172: LGTM: assertEq function signature updated correctly.

The assertEq function signature has been properly updated to use IFastBridgeV2.BridgeStatus instead of FastBridgeV2.BridgeStatus. This change is consistent with the updated import statement and ensures that the test cases use the correct BridgeStatus enum from the interface.


186-186: LGTM: assertEq call updated correctly.

The assertEq call has been properly updated to use IFastBridgeV2.BridgeStatus.REQUESTED. This change is consistent with the previous updates and ensures that the test case checks for the correct bridge status using the interface enum.


194-194: LGTM: assertEq call updated correctly.

The assertEq call has been properly updated to use IFastBridgeV2.BridgeStatus.REQUESTED. This change is consistent with the previous updates and ensures that the test case checks for the correct bridge status using the interface enum.


211-211: LGTM: assertEq call updated correctly for eth test.

The assertEq call has been properly updated to use IFastBridgeV2.BridgeStatus.REQUESTED in the eth test. This change is consistent with the previous updates and ensures that the test case checks for the correct bridge status using the interface enum for eth transactions.


221-221: LGTM: assertEq call updated correctly for eth test.

The assertEq call has been properly updated to use IFastBridgeV2.BridgeStatus.REQUESTED in the eth test. This change is consistent with the previous updates and ensures that the test case checks for the correct bridge status using the interface enum for eth transactions.


236-236: LGTM: assertEq call updated correctly for user-specific nonce test.

The assertEq call has been properly updated to use IFastBridgeV2.BridgeStatus.REQUESTED in the user-specific nonce test. This change is consistent with the previous updates and ensures that the test case checks for the correct bridge status using the interface enum for user-specific nonce transactions.


385-385: LGTM: assertEq call updated correctly for claim token test.

The assertEq call has been properly updated to use IFastBridgeV2.BridgeStatus.RELAYER_CLAIMED. This change is consistent with the previous updates and ensures that the test case checks for the correct bridge status using the interface enum for claimed transactions.


397-397: LGTM: assertEq call updated correctly for permissionless claim token test.

The assertEq call has been properly updated to use IFastBridgeV2.BridgeStatus.RELAYER_CLAIMED. This change is consistent with the previous updates and ensures that the test case checks for the correct bridge status using the interface enum for permissionless claimed transactions.


409-409: LGTM: assertEq call updated correctly for permissionless claim token test with zero address.

The assertEq call has been properly updated to use IFastBridgeV2.BridgeStatus.RELAYER_CLAIMED. This change is consistent with the previous updates and ensures that the test case checks for the correct bridge status using the interface enum for permissionless claimed transactions with zero address.


420-420: LGTM: assertEq call updated correctly for claim token test with different address.

The assertEq call has been properly updated to use IFastBridgeV2.BridgeStatus.RELAYER_CLAIMED. This change is consistent with the previous updates and ensures that the test case checks for the correct bridge status using the interface enum for claimed transactions with a different address.


432-432: LGTM: assertEq call updated correctly for claim token test with long delay.

The assertEq call has been properly updated to use IFastBridgeV2.BridgeStatus.RELAYER_CLAIMED. This change is consistent with the previous updates and ensures that the test case checks for the correct bridge status using the interface enum for claimed transactions with a long delay.


451-451: LGTM: assertEq call updated correctly for claim eth test.

The assertEq call has been properly updated to use IFastBridgeV2.BridgeStatus.RELAYER_CLAIMED. This change is consistent with the previous updates and ensures that the test case checks for the correct bridge status using the interface enum for claimed eth transactions.


464-464: LGTM: assertEq call updated correctly for permissionless claim eth test.

The assertEq call has been properly updated to use IFastBridgeV2.BridgeStatus.RELAYER_CLAIMED. This change is consistent with the previous updates and ensures that the test case checks for the correct bridge status using the interface enum for permissionless claimed eth transactions.


477-477: LGTM: assertEq call updated correctly for permissionless claim eth test with zero address.

The assertEq call has been properly updated to use IFastBridgeV2.BridgeStatus.RELAYER_CLAIMED. This change is consistent with the previous updates and ensures that the test case checks for the correct bridge status using the interface enum for permissionless claimed eth transactions with zero address.


489-489: LGTM: assertEq call updated correctly for claim eth test with different address.

The assertEq call has been properly updated to use IFastBridgeV2.BridgeStatus.RELAYER_CLAIMED. This change is consistent with the previous updates and ensures that the test case checks for the correct bridge status using the interface enum for claimed eth transactions with a different address.


501-501: LGTM: assertEq call updated correctly for claim eth test with long delay.

The assertEq call has been properly updated to use IFastBridgeV2.BridgeStatus.RELAYER_CLAIMED. This change is consistent with the previous updates and ensures that the test case checks for the correct bridge status using the interface enum for claimed eth transactions with a long delay.


581-581: LGTM: assertEq calls updated correctly for dispute tests.

The assertEq calls have been properly updated to use IFastBridgeV2.BridgeStatus.REQUESTED in the dispute tests. These changes are consistent with the previous updates and ensure that the test cases check for the correct bridge status using the interface enum for disputed transactions.

Also applies to: 593-593, 605-605, 618-618

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

43-46: bridgeStatuses function correctly provides bridge transaction status

The bridgeStatuses function is appropriately defined to return the BridgeStatus for a given transactionId. This matches the intended functionality and complies with interface design.


48-51: bridgeProofs function correctly returns proof details

The bridgeProofs function is correctly defined to return the timestamp and relayer address associated with a bridge transaction. This aligns with the intended interface functionality.

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

225-225: Consistent Status Verification in Claim Function

In the claim function, you check if the status is RELAYER_PROVED. Ensure that no other statuses (e.g., REFUNDED, DISPUTED) could lead to unintended access to this function.


253-254: Ensure Safe Time Calculations in Dispute Function

In the dispute function, the _timeSince calculation might be susceptible to unexpected behavior if block timestamps are manipulated. Ensure that the function is secure against such scenarios.


257-258: Confirm Complete Reset of Proof Data

When calling delete bridgeTxDetails[transactionId].proof;, verify that all fields within the BridgeProof struct are reset to their default values, and that no residual data remains.

Comment on lines 37 to 40
struct BridgeTxDetails {
BridgeStatus status;
BridgeProof proof;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Ensure BridgeProof type is properly defined or imported

The BridgeProof type used in the BridgeTxDetails struct is not defined within this interface. Please verify that BridgeProof is properly defined or imported from another contract or interface to prevent compilation errors.

Comment on lines 37 to 40
function bridgeStatuses(bytes32 transactionId) public view returns (BridgeStatus status)
{
return bridgeTxDetails[transactionId].status;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Optimize Getter Function Return Type

In the bridgeStatuses function, you're returning a BridgeStatus enum. While enums are convenient, returning them can be less gas-efficient. Consider returning a uint8 instead, which represents the underlying value of the enum and reduces gas consumption.

Consider this change:

-function bridgeStatuses(bytes32 transactionId) public view returns (BridgeStatus status)
+function bridgeStatuses(bytes32 transactionId) public view returns (uint8 status)
{
-    return bridgeTxDetails[transactionId].status;
+    return uint8(bridgeTxDetails[transactionId].status);
}
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 bridgeStatuses(bytes32 transactionId) public view returns (BridgeStatus status)
{
return bridgeTxDetails[transactionId].status;
}
function bridgeStatuses(bytes32 transactionId) public view returns (uint8 status)
{
return uint8(bridgeTxDetails[transactionId].status);
}

Comment on lines 208 to 209
if (bridgeTxDetails[transactionId].status != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();
BridgeProof memory proof = bridgeTxDetails[transactionId].proof;
Copy link
Contributor

Choose a reason for hiding this comment

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

Check for Uninitialized Proof Before Access

When accessing bridgeTxDetails[transactionId].proof, ensure that the proof exists to prevent accessing uninitialized memory, which could lead to incorrect data retrieval.

Add a check for proof initialization:

 BridgeProof memory proof = bridgeTxDetails[transactionId].proof;
+if (proof.relayer == address(0)) revert ProofNotInitialized();
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
if (bridgeTxDetails[transactionId].status != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();
BridgeProof memory proof = bridgeTxDetails[transactionId].proof;
if (bridgeTxDetails[transactionId].status != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();
BridgeProof memory proof = bridgeTxDetails[transactionId].proof;
if (proof.relayer == address(0)) revert ProofNotInitialized();

Comment on lines 42 to 45
function bridgeProofs(bytes32 transactionId) public view returns (BridgeProof memory proof)
{
return bridgeTxDetails[transactionId].proof;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Avoid Returning Structs Directly from Public Functions

The bridgeProofs function returns a BridgeProof struct. Returning structs can be expensive in terms of gas and may expose internal implementation details. Instead, consider returning individual fields of the struct.

Refactor the function to return individual fields:

-function bridgeProofs(bytes32 transactionId) public view returns (BridgeProof memory proof)
+function bridgeProofs(bytes32 transactionId) public view returns (uint96 timestamp, address relayer)
{
-    return bridgeTxDetails[transactionId].proof;
+    BridgeProof memory proof = bridgeTxDetails[transactionId].proof;
+    return (proof.timestamp, proof.relayer);
}

Committable suggestion was skipped due to low confidence.

Comment on lines 187 to 189
if (bridgeTxDetails[transactionId].status != BridgeStatus.REQUESTED) revert StatusIncorrect();
bridgeTxDetails[transactionId].status = BridgeStatus.RELAYER_PROVED;
bridgeTxDetails[transactionId].proof = BridgeProof({timestamp: uint96(block.timestamp), relayer: relayer}); // overflow ok
Copy link
Contributor

Choose a reason for hiding this comment

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

Tip

Codebase Verification

❗ Unexpected Status Transition Detected

The status transition from REQUESTED to REFUNDED is not defined in the expected state machine (REQUESTEDRELAYER_PROVEDRELAYER_CLAIMED). Please review the state transitions to ensure they adhere to the intended workflow.

Analysis chain

Confirm Proper Status Transition and Proof Assignment

Before updating the status to RELAYER_PROVED and assigning the proof, ensure that the transition from REQUESTED to RELAYER_PROVED is valid according to your state machine. This prevents invalid status transitions.

Run the following script to verify status transitions:

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that all status transitions in the code follow the defined state machine.

# Expected statuses in order: REQUESTED -> RELAYER_PROVED -> RELAYER_CLAIMED

# Search for all status updates
rg --type solidity 'bridgeTxDetails\[.*\].status = BridgeStatus\.\w+' -A 2

Length of output: 109


Script:

#!/bin/bash
# Description: Verify that all status transitions in the Solidity code follow the defined state machine.

# Expected statuses in order: REQUESTED -> RELAYER_PROVED -> RELAYER_CLAIMED

# Search for all status updates in .sol files
rg --glob '*.sol' 'bridgeTxDetails\[.*\].status\s*=\s*BridgeStatus\.\w+' -A 2

Length of output: 1552

Copy link

cloudflare-workers-and-pages bot commented Sep 23, 2024

Deploying sanguine-fe with  Cloudflare Pages  Cloudflare Pages

Latest commit: 78c84a8
Status: ✅  Deploy successful!
Preview URL: https://389f6a87.sanguine-fe.pages.dev
Branch Preview URL: https://feat-fbv2-storagepacking.sanguine-fe.pages.dev

View logs

Copy link

codecov bot commented Sep 23, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 38.45965%. Comparing base (f0b13bc) to head (78c84a8).
Report is 12 commits behind head on master.

Additional details and impacted files
@@                 Coverage Diff                 @@
##              master       #3173         +/-   ##
===================================================
- Coverage   40.97804%   38.45965%   -2.51839%     
===================================================
  Files            459         424         -35     
  Lines          25643       24462       -1181     
  Branches         343         148        -195     
===================================================
- Hits           10508        9408       -1100     
+ Misses         14383       14314         -69     
+ Partials         752         740         -12     
Flag Coverage Δ
packages 90.56974% <ø> (ø)
solidity 93.36283% <100.00000%> (-1.34390%) ⬇️

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.

Comment on lines 37 to 40
struct BridgeTxDetails {
BridgeStatus status;
BridgeProof proof;
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

This will not have a desired effect of saving the gas on reads and writes, as the internal composition of the struct takes more than a single storage slot (256 bits). We don't export a gas report as of now, but in this case it's possible to generate using forge t --mc FastBridgeV2SrcTest --nmt revert --gas-report.

  • Using FastBridgeV2SrcTest test contract gives us the overview for the source chain-related functions
  • --nmt revert excludes test functions having a word "revert" in the name, which makes the report more useful (revert cases in general consume less gas, and thus need to be filtered)

Copy link
Collaborator

Choose a reason for hiding this comment

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

This are the results when run on master, prior to this PR
image

Copy link
Collaborator

Choose a reason for hiding this comment

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

And this are the results after this PR changes:
image

Copy link
Collaborator

Choose a reason for hiding this comment

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

To gain the performance in gas consumption, the BridgeTxDetails needs to fit within 256 bits:

  • BridgeStatus enum is equivalent to uint8
  • address relayer takes 160 bits
  • which leaves up to 88 bits for the proof's timestamp

This is an opportunity to follow the suit of #3170 and also store the block number, when the prove happened. This could be useful for some of the Relayer implementations. This will require using up to 88 bits for both block number and timestamp, which is more than enough for practical purposes.

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: 3

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 1c5dd7d and 5045835.

📒 Files selected for processing (3)
  • packages/contracts-rfq/contracts/FastBridgeV2.sol (9 hunks)
  • packages/contracts-rfq/contracts/interfaces/IFastBridgeV2.sol (1 hunks)
  • packages/contracts-rfq/test/FastBridgeV2.Src.t.sol (30 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/contracts-rfq/contracts/interfaces/IFastBridgeV2.sol
  • packages/contracts-rfq/test/FastBridgeV2.Src.t.sol
🔇 Additional comments not posted (5)
packages/contracts-rfq/contracts/FastBridgeV2.sol (5)

187-190: LGTM: Proper status check and proof update

The changes in the prove function correctly update the status and proof details in the bridgeTxDetails mapping. The status check ensures that only transactions in the REQUESTED state can be proved, maintaining the expected state machine flow.


209-210: LGTM: Correct status check and proof retrieval

The canClaim function has been properly updated to use the new bridgeTxDetails mapping. It correctly checks the status and retrieves the proof, maintaining the existing logic while using the new data structure.


226-226: LGTM: Proper status handling and proof retrieval in claim function

The claim function has been correctly updated to use the new bridgeTxDetails mapping. It properly checks and updates the transaction status, and correctly retrieves the proof details. The changes maintain the existing logic while utilizing the new data structure effectively.

Also applies to: 228-228, 239-239


27-27: 🛠️ Refactor suggestion

Consider changing bridgeTxDetails visibility to private

The bridgeTxDetails mapping is declared as public, which allows direct access to the internal data structure. To improve encapsulation and control access to this data, consider changing the visibility to private and using the newly added getter functions bridgeStatuses and bridgeProofs for external access.

Apply this change:

-    mapping(bytes32 => BridgeTxDetails) public bridgeTxDetails;
+    mapping(bytes32 => BridgeTxDetails) private bridgeTxDetails;

Likely invalid or redundant comment.


113-113: ⚠️ Potential issue

Ensure transaction ID uniqueness before setting status

When setting the status to REQUESTED, it's important to verify that the transactionId is unique and hasn't been used in a previous transaction. This prevents overwriting existing transaction details.

Consider adding a check:

+if (bridgeTxDetails[transactionId].status != BridgeStatus.NONE) revert TransactionAlreadyExists();
 bridgeTxDetails[transactionId].status = BridgeStatus.REQUESTED;

Don't forget to define the TransactionAlreadyExists error in your Errors.sol file.

Likely invalid or redundant comment.

packages/contracts-rfq/contracts/FastBridgeV2.sol Outdated Show resolved Hide resolved
packages/contracts-rfq/contracts/FastBridgeV2.sol Outdated Show resolved Hide resolved
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 (5)
packages/contracts-rfq/test/FastBridgeV2.Parity.t.sol (3)

15-28: LGTM! Consider adding a comment for clarity.

The assertCorrectProof function is well-implemented and consistent with the stated purpose. It correctly retrieves and verifies the proof details.

Consider adding a brief comment explaining the purpose of this function, e.g.:

/// @dev Verifies that the proof for a given transaction matches the expected timestamp and relayer

Line range hint 30-38: Skipped tests are well-documented. Consider future test updates.

The decision to skip test_failedRelayNotRelayer and test_failedClaimNotRelayer is well-justified and clearly explained in the comments.

While skipping these tests is appropriate for now, consider replacing them with new tests that verify the updated permission model in FastBridgeV2. This will ensure that the new behavior is properly tested.


Line range hint 40-55: Modified test correctly reflects updated permission model.

The test_failedClaimNotOldRelayer function has been appropriately updated to align with the new permission model in FastBridgeV2.

To improve clarity, consider renaming the test function to better reflect its current purpose, e.g., test_failedClaimNotProvenRelayer. This would more accurately describe what the test is now verifying.

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

1725-1725: Good use of assertCorrectProof in dispute test!

The replacement of direct assertions with assertCorrectProof in this dispute test case maintains consistency with other changes and improves readability.

Consider adding a comment or updating the test name to clarify that this assertion is checking for reset proof details after a successful dispute. For example:

- assertCorrectProof(transactionId, 0, address(0));
+ // Assert that the proof details are reset after a successful dispute
+ assertCorrectProof(transactionId, 0, address(0));

1749-1749: Consistent use of assertCorrectProof in overflow dispute test!

The use of assertCorrectProof in this overflow dispute test case maintains consistency with other changes and improves the overall structure of the test suite.

Similar to the previous suggestion, consider adding a comment to clarify that this assertion is checking for reset proof details after a successful dispute in an overflow scenario. For example:

- assertCorrectProof(transactionId, 0, address(0));
+ // Assert that the proof details are reset after a successful dispute, even in an overflow scenario
+ assertCorrectProof(transactionId, 0, address(0));
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 5045835 and 7f5c260.

📒 Files selected for processing (2)
  • packages/contracts-rfq/test/FastBridge.t.sol (7 hunks)
  • packages/contracts-rfq/test/FastBridgeV2.Parity.t.sol (1 hunks)
🔇 Additional comments not posted (5)
packages/contracts-rfq/test/FastBridge.t.sol (5)

55-66: Great addition of the assertCorrectProof helper function!

This new function encapsulates the logic for asserting the correctness of bridge transaction proofs, which will help reduce code duplication and improve the maintainability of the test suite. It's a good practice to create such helper functions for commonly used assertions.


1366-1366: Good use of the new assertCorrectProof function!

Replacing the direct assertions with a call to assertCorrectProof improves the readability and consistency of the test case. This change will make it easier to maintain and update these assertions in the future if needed.


1398-1398: Consistent use of assertCorrectProof in overflow test!

The replacement of direct assertions with assertCorrectProof in this overflow test case maintains consistency with other similar changes. This consistency improves the overall structure and readability of the test suite.


1427-1427: Consistent application of assertCorrectProof in delay test!

The use of assertCorrectProof in this test case with a huge delay maintains the consistent structure across different scenarios. This consistency in test structure will make it easier for developers to understand and maintain the test suite in the future.


Line range hint 1-1749: Overall improvement in test structure and readability!

The introduction of the assertCorrectProof helper function and its consistent application across various test cases significantly enhances the structure and readability of the test suite. This refactoring reduces code duplication and improves maintainability, making it easier for developers to understand and update the tests in the future.

The consistent use of this new function across different scenarios (normal operations, overflow conditions, and disputes) ensures a uniform approach to asserting proof correctness throughout the test suite.

These changes represent a positive step in improving the quality and maintainability of the test code for the FastBridge contract.

@parodime
Copy link
Collaborator Author

gas report after BridgeTxDetails refactor
2024-09-25 14_41_56-FastBridgeV2 sol - contracts-rfq  WSL_ Ubuntu  - SYNAPSE - Cursor

Copy link

codecov bot commented Sep 25, 2024

Bundle Report

Changes will decrease total bundle size by 157.85kB (-0.44%) ⬇️. This is within the configured threshold ✅

Detailed changes
Bundle name Size Change
synapse-interface-server-cjs 1.47MB 147.19kB (-9.11%) ⬇️
widget-esm-cjs 273.3kB 10.65kB (-3.75%) ⬇️

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)
packages/contracts-rfq/contracts/FastBridgeV2.sol (2)

Line range hint 225-249: Emit event for status change to RELAYER_CLAIMED

After updating the status to RELAYER_CLAIMED, consider emitting an event to log this state change. This improves transparency and facilitates off-chain tracking of transaction statuses.

Add an event emission:

 _thisBridgeTxDetails.status = BridgeStatus.RELAYER_CLAIMED;
+emit BridgeStatusUpdated(transactionId, BridgeStatus.RELAYER_CLAIMED);

Ensure you've defined the BridgeStatusUpdated event as suggested in a previous comment. This addition would enhance the contract's observability and make it easier to track the complete lifecycle of bridge transactions.


Line range hint 273-285: Emit event for status change to REFUNDED

After updating the status to REFUNDED, it would be beneficial to emit an event logging this state change. This improves transparency and aids in off-chain tracking of transaction statuses.

Add an event emission:

 bridgeTxDetails[transactionId].status = BridgeStatus.REFUNDED;
+emit BridgeStatusUpdated(transactionId, BridgeStatus.REFUNDED);

Ensure you've defined the BridgeStatusUpdated event as suggested in previous comments. This addition would further enhance the contract's observability and provide a complete picture of the bridge transaction lifecycle.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 7f5c260 and dc2dab5.

📒 Files selected for processing (2)
  • packages/contracts-rfq/contracts/FastBridgeV2.sol (8 hunks)
  • packages/contracts-rfq/contracts/interfaces/IFastBridgeV2.sol (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/contracts-rfq/contracts/interfaces/IFastBridgeV2.sol
🔇 Additional comments not posted (5)
packages/contracts-rfq/contracts/FastBridgeV2.sol (5)

196-203: LGTM: Efficient timestamp calculation

The _timeSince function has been optimized to use uint40 for timestamp calculations, which aligns well with the storage optimization in BridgeTxDetails. The unchecked block correctly handles potential overflow scenarios. This implementation is both gas-efficient and functionally correct.


209-212: LGTM: Correct usage of consolidated mapping

The canClaim function has been successfully updated to use the new bridgeTxDetails mapping. It correctly accesses the relevant fields from the BridgeTxDetails struct while maintaining the original logic. This change aligns well with the optimization goals of the PR.


36-38: 🛠️ Refactor suggestion

Optimize bridgeStatuses return type for gas efficiency

The bridgeStatuses function returns a BridgeStatus enum. While enums are convenient for readability, returning them can be less gas-efficient. Consider returning a uint8 instead, which represents the underlying value of the enum.

-function bridgeStatuses(bytes32 transactionId) public view returns (BridgeStatus status) {
+function bridgeStatuses(bytes32 transactionId) public view returns (uint8 status) {
-    return bridgeTxDetails[transactionId].status;
+    return uint8(bridgeTxDetails[transactionId].status);
}

This change would maintain backwards compatibility while potentially reducing gas costs for callers.

Likely invalid or redundant comment.


27-27: 🛠️ Refactor suggestion

Consider making bridgeTxDetails mapping private

While the new bridgeTxDetails mapping effectively consolidates bridgeStatuses and bridgeProofs, making it public allows direct access to the entire BridgeTxDetails struct. Consider making this mapping private and relying on specific getter functions for better encapsulation and potential gas savings.

-    mapping(bytes32 => BridgeTxDetails) public bridgeTxDetails;
+    mapping(bytes32 => BridgeTxDetails) private bridgeTxDetails;

This change would align with the principle of minimal exposure and could potentially save gas by preventing unnecessary SLOAD operations when only specific fields are needed.

Likely invalid or redundant comment.


111-111: ⚠️ Potential issue

Add check for existing transactions before setting status

When setting the status to REQUESTED, it's important to ensure that the transactionId doesn't already exist in the bridgeTxDetails mapping. This prevents accidentally overwriting an existing transaction.

Consider adding a check:

+   if (bridgeTxDetails[transactionId].status != BridgeStatus.NONE) revert TransactionAlreadyExists();
    bridgeTxDetails[transactionId].status = BridgeStatus.REQUESTED;

This addition would prevent potential issues with duplicate transaction IDs and improve the contract's robustness.

Likely invalid or redundant comment.

Comment on lines 185 to 190
if (bridgeTxDetails[transactionId].status != BridgeStatus.REQUESTED) revert StatusIncorrect();
BridgeTxDetails storage _thisBridgeTxDetails = bridgeTxDetails[transactionId];
_thisBridgeTxDetails.status = BridgeStatus.RELAYER_PROVED;
_thisBridgeTxDetails.proofBlockTimestamp = uint40(block.timestamp);
_thisBridgeTxDetails.proofBlockNumber = uint48(block.number);
_thisBridgeTxDetails.proofRelayer = relayer;
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

Emit event for status change to RELAYER_PROVED

After updating the status to RELAYER_PROVED, consider emitting an event to log this state change. This aids in transparency and off-chain tracking of transaction statuses.

Add an event emission:

 _thisBridgeTxDetails.status = BridgeStatus.RELAYER_PROVED;
 _thisBridgeTxDetails.proofBlockTimestamp = uint40(block.timestamp);
 _thisBridgeTxDetails.proofBlockNumber = uint48(block.number);
 _thisBridgeTxDetails.proofRelayer = relayer;
+emit BridgeStatusUpdated(transactionId, BridgeStatus.RELAYER_PROVED);

Don't forget to define the event:

event BridgeStatusUpdated(bytes32 indexed transactionId, BridgeStatus status);

This addition would improve the contract's observability and make it easier to track the lifecycle of bridge transactions.

Comment on lines 40 to 43
function bridgeProofs(bytes32 transactionId) public view returns (BridgeProof memory) {
BridgeTxDetails storage _thisBridgeTxDetails = bridgeTxDetails[transactionId];
return BridgeProof(_thisBridgeTxDetails.proofBlockTimestamp, _thisBridgeTxDetails.proofRelayer);
}
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 returning individual values instead of BridgeProof struct

The bridgeProofs function returns a BridgeProof struct. Returning structs can be gas-inefficient and may expose internal implementation details. Consider returning individual fields of the struct instead.

-function bridgeProofs(bytes32 transactionId) public view returns (BridgeProof memory) {
+function bridgeProofs(bytes32 transactionId) public view returns (uint40 timestamp, address relayer) {
     BridgeTxDetails storage _thisBridgeTxDetails = bridgeTxDetails[transactionId];
-    return BridgeProof(_thisBridgeTxDetails.proofBlockTimestamp, _thisBridgeTxDetails.proofRelayer);
+    return (_thisBridgeTxDetails.proofBlockTimestamp, _thisBridgeTxDetails.proofRelayer);
}

This change would maintain backwards compatibility while potentially reducing gas costs and limiting exposure of internal structures.

📝 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 bridgeProofs(bytes32 transactionId) public view returns (BridgeProof memory) {
BridgeTxDetails storage _thisBridgeTxDetails = bridgeTxDetails[transactionId];
return BridgeProof(_thisBridgeTxDetails.proofBlockTimestamp, _thisBridgeTxDetails.proofRelayer);
}
function bridgeProofs(bytes32 transactionId) public view returns (uint40 timestamp, address relayer) {
BridgeTxDetails storage _thisBridgeTxDetails = bridgeTxDetails[transactionId];
return (_thisBridgeTxDetails.proofBlockTimestamp, _thisBridgeTxDetails.proofRelayer);
}

Copy link
Collaborator

@ChiTimesChi ChiTimesChi left a comment

Choose a reason for hiding this comment

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

Not a fan of storage approach (see the comments) + needs merge conflicts to be resolved.

packages/contracts-rfq/contracts/FastBridgeV2.sol Outdated Show resolved Hide resolved
packages/contracts-rfq/contracts/FastBridgeV2.sol Outdated Show resolved Hide resolved
packages/contracts-rfq/contracts/FastBridgeV2.sol Outdated Show resolved Hide resolved
packages/contracts-rfq/contracts/FastBridgeV2.sol Outdated Show resolved Hide resolved
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: 1

🧹 Outside diff range and nitpick comments (1)
packages/contracts-rfq/contracts/interfaces/IFastBridgeV2.sol (1)

7-13: Consider renaming the NULL state for improved clarity

The BridgeStatus enum provides a clear representation of the possible states of a bridge transaction. However, the NULL state could be renamed to improve clarity and avoid potential confusion with null values in other programming contexts.

Consider renaming NULL to a more descriptive term such as NOT_INITIATED or UNINITIALIZED. For example:

enum BridgeStatus {
-    NULL, // doesn't exist yet
+    NOT_INITIATED, // doesn't exist yet
    REQUESTED,
    RELAYER_PROVED,
    RELAYER_CLAIMED,
    REFUNDED
}

The rest of the enum looks good and follows a logical order of states for a bridge transaction.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between dc2dab5 and ddc1f1f.

📒 Files selected for processing (4)
  • packages/contracts-rfq/contracts/FastBridgeV2.sol (8 hunks)
  • packages/contracts-rfq/contracts/interfaces/IFastBridgeV2.sol (2 hunks)
  • packages/contracts-rfq/test/FastBridgeV2.Parity.t.sol (1 hunks)
  • packages/contracts-rfq/test/FastBridgeV2.Src.t.sol (28 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/contracts-rfq/contracts/FastBridgeV2.sol
  • packages/contracts-rfq/test/FastBridgeV2.Parity.t.sol
  • packages/contracts-rfq/test/FastBridgeV2.Src.t.sol
🔇 Additional comments (1)
packages/contracts-rfq/contracts/interfaces/IFastBridgeV2.sol (1)

15-20: Efficient struct packing for gas optimization

The BridgeTxDetails struct is well-designed for gas efficiency:

  1. It uses smaller uint types (uint40 and uint48) for timestamp and block number, which are sufficient for their purposes.
  2. The struct is packed into a single 256-bit storage slot:
    • BridgeStatus enum (8 bits)
    • uint40 proofBlockTimestamp (40 bits)
    • uint48 proofBlockNumber (48 bits)
    • address proofRelayer (160 bits)
      Total: 256 bits

This efficient packing addresses the gas optimization concerns raised in previous comments and will lead to reduced gas costs for storage operations.

@parodime parodime merged commit 0240714 into master Sep 27, 2024
64 checks passed
@parodime parodime deleted the feat/FbV2-storagePacking branch September 27, 2024 23:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants