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

test(contracts-rfq): gas bench for TokenZapV1 #3406

Merged
merged 2 commits into from
Nov 22, 2024

Conversation

ChiTimesChi
Copy link
Collaborator

@ChiTimesChi ChiTimesChi commented Nov 22, 2024

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 SimpleVaultMock for testing deposit functionality.
    • Added VaultManyArguments for enhanced error handling and deposit methods.
    • Created TokenZapV1GasBenchmarkTest for gas benchmarking of token deposits.
  • Bug Fixes

    • Improved validation and error handling in deposit functions.
  • Documentation

    • Included notices indicating the mock contracts are for testing only.

Copy link
Contributor

coderabbitai bot commented Nov 22, 2024

Walkthrough

The changes introduce three new Solidity contracts aimed at enhancing testing capabilities for the vault system. The SimpleVaultMock contract serves as a mock implementation for testing deposit functionality, while the VaultManyArguments contract extends VaultMock with additional error handling and deposit functions. Additionally, the TokenZapV1.GasBench.t.sol contract is created for gas benchmarking of token deposits, ensuring accurate performance metrics for both ERC20 and native token transactions.

Changes

File Path Change Summary
packages/contracts-rfq/test/mocks/SimpleVaultMock.sol Added contract SimpleVaultMock with methods testSimpleVaultMock() and deposit(address, uint256, address).
packages/contracts-rfq/test/mocks/VaultManyArguments.sol Added contract VaultManyArguments with error VaultManyArguments__SomeError and method testSimpleVaultMock(). Retained existing deposit functionality.
packages/contracts-rfq/test/zaps/TokenZapV1.GasBench.t.sol Introduced contract TokenZapV1GasBenchmarkTest for gas benchmarking with methods test_deposit_erc20 and test_deposit_native.

Possibly related PRs

Suggested labels

size/l, needs-go-generate-services/rfq

Suggested reviewers

  • aureliusbtc
  • parodime
  • trajan0x

Poem

In the land of code where bunnies play,
New mocks and tests come out to stay.
With deposits and gas, we leap with cheer,
For vaults and tokens, the path is clear!
Hopping through functions, oh what a sight,
Testing our contracts, all day and night! 🐇✨


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

🧹 Outside diff range and nitpick comments (4)
packages/contracts-rfq/test/mocks/VaultManyArguments.sol (3)

11-12: Consider renaming the test exclusion function

While the empty function pattern for coverage exclusion is good, the name testSimpleVaultMock might be misleading as it's not actually testing anything related to SimpleVaultMock. Consider a more generic name like excludeFromCoverage.

-    function testSimpleVaultMock() external {}
+    function excludeFromCoverage() external {}

Line range hint 14-27: Add NatSpec documentation for function parameters

The deposit function lacks parameter documentation. Consider adding @param descriptions to clarify the purpose of each parameter, especially for the encoded parameters.

+    /// @param token The token address to deposit
+    /// @param encodedToken The ABI encoded token address for validation
+    /// @param amount The amount to deposit
+    /// @param user The user address for the deposit
+    /// @param encodedUser The ABI encoded user address for validation
     function deposit(
         address token,
         bytes memory encodedToken,
         uint256 amount,
         address user,
         bytes memory encodedUser
     )

Line range hint 29-42: Consider adding events and optimizing validation

  1. Consider emitting events in the deposit functions to track state changes, even in test contracts.
  2. The _validateBytes function uses keccak256 for comparison which is gas intensive. For testing purposes, consider using a simpler validation method.
+    event Deposit(address indexed user, address indexed token, uint256 amount);

     function depositNoAmount(address user) external payable {
         _deposit(user, NATIVE_GAS_TOKEN, msg.value);
+        emit Deposit(user, NATIVE_GAS_TOKEN, msg.value);
     }

     function _validateBytes(address addr, bytes memory encoded) internal pure {
-        if (keccak256(abi.encode(addr)) != keccak256(encoded)) revert VaultManyArguments__SomeError();
+        // For test contracts, we can use a simpler comparison
+        if (abi.encode(addr) != encoded) revert VaultManyArguments__SomeError();
     }
packages/contracts-rfq/test/zaps/TokenZapV1.GasBench.t.sol (1)

13-20: Consider documenting constants and using representative test amounts.

Two suggestions for improvement:

  1. Add a comment explaining the significance of the nativeGasToken address (0xEeee...)
  2. Consider if 0.1337 ether is a representative amount for gas benchmarking - you might want to test with different amounts to measure gas scaling.
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 24a88dc and 55329da.

📒 Files selected for processing (3)
  • packages/contracts-rfq/test/mocks/SimpleVaultMock.sol (1 hunks)
  • packages/contracts-rfq/test/mocks/VaultManyArguments.sol (1 hunks)
  • packages/contracts-rfq/test/zaps/TokenZapV1.GasBench.t.sol (1 hunks)
🔇 Additional comments (7)
packages/contracts-rfq/test/mocks/SimpleVaultMock.sol (4)

1-4: LGTM! Appropriate license and modern Solidity version

The file uses a secure Solidity version and has proper licensing.


9-10: LGTM! Well-documented test exclusion pattern

The empty test function is properly documented and serves its purpose for coverage exclusion.


6-8: Verify the VaultMock implementation

The inheritance looks correct, but let's verify the base contract implementation to ensure proper integration.

✅ Verification successful

Base contract implementation is appropriate for testing purposes

The VaultMock implementation is a well-structured abstract contract that:

  • Clearly documents its test-only purpose
  • Implements basic vault functionality with deposit and balance tracking
  • Uses SafeERC20 for secure token transfers
  • Handles both ERC20 and native gas token deposits
  • Has proper error handling

The inheritance in SimpleVaultMock is correct and safe to use for testing purposes.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check VaultMock implementation and its inheritance chain

# Find and display VaultMock contract content
rg -p "contract VaultMock" --type sol
ast-grep --pattern 'contract VaultMock {
  $$$
}'

Length of output: 119


Script:

#!/bin/bash
# Search for VaultMock contract definition using ripgrep without file type filter
rg -p "contract VaultMock"

# Find all Solidity files that might contain VaultMock
fd -e sol

# Search for imports of VaultMock to trace its location
rg "import.*VaultMock"

Length of output: 18975


Script:

#!/bin/bash
# Get the content of VaultMock.sol
cat "packages/contracts-rfq/test/mocks/VaultMock.sol"

Length of output: 910


12-14: Verify native token handling in deposit function

The function is marked as payable but delegates to _deposit without explicit ETH value handling. Please ensure:

  1. The parent's _deposit function properly handles native token deposits
  2. Input validation is sufficient
  3. The msg.value is properly handled when token is the native token address
✅ Verification successful

Native token handling is properly implemented in deposit function

The internal _deposit function correctly handles native token deposits by:

  1. Checking if the token is NATIVE_GAS_TOKEN (0xEeeee...)
  2. Validating that msg.value matches the amount parameter when depositing native tokens
  3. Using ERC20 transfer for non-native tokens
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check _deposit implementation in VaultMock for native token handling

# Find _deposit function implementation
ast-grep --pattern 'function _deposit(address $_, address $_, uint256 $_) {
  $$$
}'

# Check for native token handling patterns
rg -p "msg.value" --type sol

Length of output: 143


Script:

#!/bin/bash
# Search for _deposit implementation and native token handling with correct file extension
ast-grep --pattern 'function _deposit(address $_, address $_, uint256 $_) {
  $$$
}'

# Find files with .sol extension
fd -e sol

# Search for msg.value in .sol files
rg "msg.value" -A 3 $(fd -e sol)

# Look for native token handling patterns
rg "native|eth|weth" -i $(fd -e sol)

Length of output: 139251


Script:

#!/bin/bash
# Look for _deposit implementation in VaultMock
rg "_deposit" packages/contracts-rfq/test/mocks/VaultMock.sol -A 5

# Look for native token handling in VaultMock
rg "NATIVE|ETH|GAS_TOKEN" packages/contracts-rfq/test/mocks/VaultMock.sol

Length of output: 575

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

6-9: Well-structured contract declaration with clear documentation!

The contract follows good practices:

  • Clear documentation about test-only usage
  • Proper error naming convention with contract prefix
  • Appropriate inheritance structure
packages/contracts-rfq/test/zaps/TokenZapV1.GasBench.t.sol (2)

1-12: LGTM! Contract setup and imports are well-structured.

The file uses the latest Solidity version and includes all necessary imports for testing.


22-37: Verify infinite approval simulation necessity.

While the infinite approval setup simulates a real-world scenario, consider adding a test case without infinite approval to benchmark the gas cost difference of the first deposit.

Comment on lines +39 to +46
function getVaultPayload(address token, uint256 amount) public view returns (bytes memory) {
return abi.encodeCall(vault.deposit, (token, amount, user));
}

function getZapData(bytes memory originalPayload) public view returns (bytes memory) {
// Amount is the second argument of the deposit function.
return tokenZap.encodeZapData(address(vault), originalPayload, 4 + 32);
}
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

Replace hardcoded offset with a calculated value.

The hardcoded offset 4 + 32 in getZapData is brittle and could break if the function signature changes. Consider:

  1. Adding a comment explaining the offset calculation
  2. Using ABI encoding utilities to calculate the offset dynamically

Comment on lines +48 to +64
function test_deposit_erc20() public {
bytes memory depositPayload = getVaultPayload(address(erc20), AMOUNT);
bytes memory zapData = getZapData(depositPayload);
// Transfer tokens to the zap contract first.
erc20.transfer(address(tokenZap), AMOUNT);
tokenZap.zap(address(erc20), AMOUNT, zapData);
// Check that the vault registered the deposit.
assertEq(vault.balanceOf(user, address(erc20)), AMOUNT);
}

function test_deposit_native() public {
bytes memory depositPayload = getVaultPayload(nativeGasToken, AMOUNT);
bytes memory zapData = getZapData(depositPayload);
tokenZap.zap{value: AMOUNT}(nativeGasToken, AMOUNT, zapData);
// Check that the vault registered the deposit.
assertEq(vault.balanceOf(user, nativeGasToken), AMOUNT);
}
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

Add explicit gas measurements for benchmarking.

For a gas benchmarking test suite, consider:

  1. Adding explicit gas measurement assertions
  2. Testing with different deposit amounts to understand gas scaling
  3. Adding comparison benchmarks against direct vault deposits

Example improvement:

 function test_deposit_erc20() public {
+    uint256 gasStart = gasleft();
     bytes memory depositPayload = getVaultPayload(address(erc20), AMOUNT);
     bytes memory zapData = getZapData(depositPayload);
     erc20.transfer(address(tokenZap), AMOUNT);
     tokenZap.zap(address(erc20), AMOUNT, zapData);
+    uint256 gasUsed = gasStart - gasleft();
+    assertLt(gasUsed, MAX_EXPECTED_GAS);
     assertEq(vault.balanceOf(user, address(erc20)), AMOUNT);
 }

Committable suggestion skipped: line range outside the PR's diff.

Copy link

Deploying sanguine-fe with  Cloudflare Pages  Cloudflare Pages

Latest commit: 55329da
Status: ✅  Deploy successful!
Preview URL: https://8442555e.sanguine-fe.pages.dev
Branch Preview URL: https://feat-token-zap-gas-bench.sanguine-fe.pages.dev

View logs

Copy link

codecov bot commented Nov 22, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 42.36502%. Comparing base (601922b) to head (55329da).
Report is 2 commits behind head on master.

Additional details and impacted files
@@              Coverage Diff              @@
##              master       #3406   +/-   ##
=============================================
  Coverage   42.36502%   42.36502%           
=============================================
  Files             87          87           
  Lines           3019        3019           
  Branches          82          82           
=============================================
  Hits            1279        1279           
  Misses          1737        1737           
  Partials           3           3           
Flag Coverage Δ
packages 90.44834% <ø> (ø)
solidity 98.86364% <ø> (ø)

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.


🚨 Try these New Features:

@ChiTimesChi ChiTimesChi merged commit 31997a8 into master Nov 22, 2024
52 checks passed
@ChiTimesChi ChiTimesChi deleted the feat/token-zap-gas-bench branch November 22, 2024 19:16
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.

1 participant