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

Fix/native restaking withdraw in progress #52

Merged
merged 100 commits into from
Jul 17, 2024

Conversation

wewecalibrate
Copy link
Contributor

@wewecalibrate wewecalibrate commented Jul 17, 2024

  • Implement native restaking partial and full withdrawal workflow

Summary by CodeRabbit

  • New Features

    • Enhanced ClientGatewayLzReceiver and ExoCapsule contracts with new event handling for withdrawals.
    • Added new events and error handling in ExoCapsule for better transaction tracking.
    • Updated NativeRestakingController with improved withdrawal processing.
  • Improvements

    • Configured Solidity language formatter for consistent coding standards.
    • Increased maximum line length to 128 in Solidity linting rules.
    • Improved comment clarity and function naming in several interfaces and contracts.
  • Bug Fixes

    • Corrected formatting inconsistency in package.json.
  • Tests

    • Added structured JSON files for withdrawal proofs.
    • Introduced new unit tests for withdrawal proof verification in ExoCapsule.

adu-web3 and others added 30 commits May 13, 2024 14:31
Copy link
Contributor

coderabbitai bot commented Jul 17, 2024

Walkthrough

The updates encompass extensive enhancements across Solidity contracts and configuration files. Key changes include the addition of new event handling and withdrawal logic in ClientGatewayLzReceiver, comprehensive updates to the ExoCapsule contract for better handling of ETH deposits and withdrawal proofs, and adjustments to related interfaces and libraries. Configuration files were updated for Solidity formatting and linting, and new test data and functions were introduced for validating blockchain proofs.

Changes

File / Group Summary
.vscode/settings.json Added configurations for Solidity language formatter.
package.json Corrected formatting inconsistency in decimal.js dependency declaration.
src/.solhint.json Adjusted solhint.json rules, including max-line-length and added no-complex-fallback.
src/core/ClientGatewayLzReceiver.sol Updated event handling and withdrawal logic, adding new events and adjusting balance updates.
src/core/ExoCapsule.sol Major updates including new event handling, ETH deposits, and withdrawal proof verification.
src/core/NativeRestakingController.sol Updated import statements and modified withdrawal handling logic.
src/interfaces/IExoCapsule.sol Modified interface structure and refactored withdrawal proof functions.
src/interfaces/INativeRestakingController.sol Updated comments and renamed functions for clarity.
src/libraries/BeaconChainProofs.sol Added constants and functions for withdrawal proofs.
src/libraries/WithdrawalContainer.sol Added function to retrieve withdrawal amounts.
src/storage/ClientChainGatewayStorage.sol Removed GWEI_TO_WEI constant.
src/storage/ExoCapsuleStorage.sol Added new constants and state variables for withdrawal handling.
test/foundry/DepositWithdrawPrinciple.t.sol Updated functions and added new ones for deposit and withdrawal simulations.
test/foundry/ExocoreDeployer.t.sol Added imports and functions related to withdrawal proof handling.
test/foundry/test-data/full_withdrawal_proof.json Introduced structured JSON object for withdrawal proof data.
test/foundry/test-data/partial_withdrawal_proof.json Introduced structured JSON object for partial withdrawal proof data.
test/foundry/unit/ExoCapsule.t.sol Renamed contracts, updated type conversions, and added functions for withdrawal proof verification.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ClientGatewayLzReceiver
    participant ExoCapsule
    participant NativeRestakingController

    User->>ClientGatewayLzReceiver: Initiate Withdrawal
    ClientGatewayLzReceiver->>ExoCapsule: Handle Withdrawal
    ExoCapsule->>ClientGatewayLzReceiver: Emit WithdrawFailedOnExocore (if fail)
    ExoCapsule->>ExoCapsule: Update Balances (if success)
    ExoCapsule->>NativeRestakingController: Process Withdrawal
    NativeRestakingController->>ExoCapsule: Verify Withdrawal Proof
    ExoCapsule->>User: Withdrawal Processed
Loading

Poem

In lines of code, new tales unfold,
Withdrawals now with care controlled.
Proofs and data, structured tight,
Ensuring balances are just right.
With every byte, our contracts grow,
Solidity's dance, a rhythmic flow.
🌟🎉🐰


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>.
    • 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 generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @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 as 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.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

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
Collaborator

@bwhour bwhour left a comment

Choose a reason for hiding this comment

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

it is the same with pr10.

@wewecalibrate wewecalibrate merged commit a6dfa2d into main Jul 17, 2024
12 checks passed
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, codebase verification and nitpick comments (3)
test/foundry/ExocoreDeployer.t.sol (1)

124-125: Update file paths for mock contracts

The paths for the mock contract files in the setUp function are incorrect. Please update the paths to reflect the correct locations:

  • AssetsMock.sol should be located at test/mocks/AssetsMock.sol
  • DelegationMock.sol should be located at test/mocks/DelegationMock.sol
  • ClaimRewardMock.sol should be located at test/mocks/ClaimRewardMock.sol
Analysis chain

Verify file paths and contract addresses.

Ensure that the file paths and contract addresses used in the setUp function are correct and accessible.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify if the file paths and contract addresses are correct and accessible.

# Test: Check if the file exists. Expect: File exists.
cat test/foundry/test-data/validator_container_proof_302913.json

# Test: Check if the mock contracts are deployed. Expect: Contracts are deployed.
echo "Checking AssetsMock.sol deployment"
cat src/mocks/AssetsMock.sol
echo "Checking DelegationMock.sol deployment"
cat src/mocks/DelegationMock.sol
echo "Checking ClaimRewardMock.sol deployment"
cat src/mocks/ClaimRewardMock.sol

Length of output: 8957


Script:

#!/bin/bash
# Description: Search for the mock contract files in the repository to verify their existence and correct paths.

# Search for AssetsMock.sol
echo "Searching for AssetsMock.sol"
fd -e sol AssetsMock.sol

# Search for DelegationMock.sol
echo "Searching for DelegationMock.sol"
fd -e sol DelegationMock.sol

# Search for ClaimRewardMock.sol
echo "Searching for ClaimRewardMock.sol"
fd -e sol ClaimRewardMock.sol

Length of output: 395

test/foundry/DepositWithdrawPrinciple.t.sol (1)

Line range hint 248-302: Function _testNativeDeposit handles deposit logic correctly but can be refactored for clarity.

The deposit logic, including the cap at 32 Ether, is correctly implemented. However, the function could benefit from separating concerns for better readability and maintainability.

- // Cap to 32 ether
- if (depositAmount >= 32 ether) {
-     depositAmount = 32 ether;
- }
+ depositAmount = min(depositAmount, 32 ether);
test/foundry/unit/ExoCapsule.t.sol (1)

Update references to SetUp contract

The following files still contain references to the SetUp contract. Please update these references to DepositSetup:

  • test/foundry/unit/ExocoreGateway.t.sol
    • Line: contract SetUp is Test {
    • Line: contract Pausable is SetUp {
    • Line: contract LzReceive is SetUp {
    • Line: contract RegisterOrUpdateClientChain is SetUp {
    • Line: contract SetPeer is SetUp {
    • Line: contract AddWhitelistTokens is SetUp {
    • Line: contract UpdateWhitelistTokens is SetUp {
  • test/foundry/unit/ClientChainGateway.t.sol
    • Line: contract SetUp is Test {
    • Line: contract Pausable is SetUp {
    • Line: contract Initialize is SetUp {
    • Line: contract AddWhitelistTokens is SetUp {

Please update these references to ensure consistency and correctness.

Analysis chain

Line range hint 16-79: Review of DepositSetup Contract

The DepositSetup contract appears to be well-structured with appropriate use of comments and structured data. However, the renaming of the contract from SetUp to DepositSetup needs to be verified across the codebase to ensure that all references are updated accordingly.

  • Correctness: The contract uses stdStorage and Endian utilities effectively. The setup function initializes various components and contracts which are crucial for the deposit workflow.
  • Security: The use of vm.etch to simulate contract code and stdstore to manipulate storage directly are powerful tools in a test environment but should be used carefully to avoid misleading test outcomes.
  • Maintainability: The separation of setup logic into DepositSetup enhances readability and reusability.
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify all references to the old `SetUp` contract are updated to `DepositSetup`.

# Test: Search for the old contract name usage. Expect: No occurrences of the old name.
rg --type solidity -A 5 $'SetUp'

Length of output: 64


Script:

#!/bin/bash
# Description: Verify all references to the old `SetUp` contract are updated to `DepositSetup`.

# Test: Search for the old contract name usage. Expect: No occurrences of the old name.
rg 'SetUp'

Length of output: 820

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between a809580 and be519f2.

Files selected for processing (17)
  • .vscode/settings.json (1 hunks)
  • package.json (1 hunks)
  • src/.solhint.json (2 hunks)
  • src/core/ClientGatewayLzReceiver.sol (2 hunks)
  • src/core/ExoCapsule.sol (7 hunks)
  • src/core/NativeRestakingController.sol (3 hunks)
  • src/interfaces/IExoCapsule.sol (2 hunks)
  • src/interfaces/INativeRestakingController.sol (5 hunks)
  • src/libraries/BeaconChainProofs.sol (6 hunks)
  • src/libraries/WithdrawalContainer.sol (1 hunks)
  • src/storage/ClientChainGatewayStorage.sol (1 hunks)
  • src/storage/ExoCapsuleStorage.sol (1 hunks)
  • test/foundry/DepositWithdrawPrinciple.t.sol (9 hunks)
  • test/foundry/ExocoreDeployer.t.sol (6 hunks)
  • test/foundry/test-data/full_withdrawal_proof.json (1 hunks)
  • test/foundry/test-data/partial_withdrawal_proof.json (1 hunks)
  • test/foundry/unit/ExoCapsule.t.sol (5 hunks)
Files skipped from review due to trivial changes (2)
  • .vscode/settings.json
  • package.json
Additional context used
Learnings (1)
src/core/ClientGatewayLzReceiver.sol (1)
Learnt from: adu-web3
PR: ExocoreNetwork/exocore-contracts#23
File: src/core/ClientGatewayLzReceiver.sol:163-164
Timestamp: 2024-06-17T08:20:03.376Z
Learning: If a call to the vault reverts in the `afterReceiveWithdrawRewardResponse` function within `ClientGatewayLzReceiver.sol`, the entire transaction is intended to be reverted. This is a design choice to ensure atomicity and integrity of operations.
Additional comments not posted (31)
src/.solhint.json (3)

4-4: Updated max-line-length to 128.

This change increases the maximum allowed line length. Ensure that this adjustment aligns with your team's code readability standards.


17-17: Added no-complex-fallback rule set to 'off'.

This rule has been disabled. Consider the implications of allowing complex fallback functions, especially in terms of security and maintainability.


6-6: Modified func-visibility rule.

The extra space in the configuration might be a typographical error. Verify this change to ensure it does not affect the linting process.

Verification successful

The func-visibility rule configuration is consistent within the codebase. The extra space in the configuration does not appear to affect the linting process as it is the only instance found.

  • src/.solhint.json: "func-visibility": ["warn", { "ignoreConstructors": true }],
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the `func-visibility` rule configuration in other JSON files for consistency.

# Test: Search for the `func-visibility` rule in other JSON configuration files. Expect: Consistent configuration without extra spaces.
rg --type json "func-visibility"

Length of output: 115

src/interfaces/IExoCapsule.sol (3)

3-3: Added import for BeaconChainProofs.

This import is necessary for the new withdrawal proof functionality. Ensure that the BeaconChainProofs.sol file exists and is accessible from this path.

Verification successful

Verification successful for the import of BeaconChainProofs.

The file BeaconChainProofs.sol exists at the specified path and is accessible.

  • src/libraries/BeaconChainProofs.sol
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the existence and accessibility of `BeaconChainProofs.sol`.

# Test: Search for the file `BeaconChainProofs.sol` in the repository. Expect: At least one occurrence.
fd "BeaconChainProofs.sol"

Length of output: 62


22-33: Refactored verifyWithdrawalProof function.

The function has been renamed and its parameters modified to include new proof types. This change is critical for the new withdrawal workflow. Ensure that all references to this function reflect the new signature.

Verification successful

Refactored verifyWithdrawalProof function.

The function has been renamed and its parameters modified to include new proof types. This change is critical for the new withdrawal workflow. Ensure that all references to this function reflect the new signature.

  • src/core/NativeRestakingController.sol
  • test/foundry/unit/ExoCapsule.t.sol
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of the new `verifyWithdrawalProof` function signature in the codebase.

# Test: Search for the function usage with the new parameters. Expect: Consistent usage across the codebase.
ast-grep --lang solidity --pattern $'interface IExoCapsule {
  $$$
  verifyWithdrawalProof($_, $_, $_, $_);
  $$$
}'

Length of output: 234


Script:

#!/bin/bash
# Description: Verify the usage of the new `verifyWithdrawalProof` function signature in the codebase.

# Test: Search for the function usage with the new parameters. Expect: Consistent usage across the codebase.
rg 'verifyWithdrawalProof' -A 3

Length of output: 2387


18-18: Modified WithdrawalContainerProof struct.

The struct now includes stateRoot instead of previous fields, aligning with the new proof requirements. Confirm that all usages of this struct have been updated accordingly.

src/libraries/WithdrawalContainer.sol (1)

35-37: Added getAmount function.

This new function correctly retrieves the withdrawal amount in gwei. It's a straightforward addition that enhances the library's functionality.

src/storage/ExoCapsuleStorage.sol (2)

32-33: Added new constants for balance conversions and limits.

These constants (GWEI_TO_WEI and MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR) are crucial for managing balances and should be used consistently throughout the contract.


36-49: Introduced new state variables for balance management.

The new variables (withdrawableBalance, nonBeaconChainETHBalance, and provenWithdrawal) are essential for the updated withdrawal functionality. Ensure that these variables are correctly initialized and used in the contract's logic.

src/storage/ClientChainGatewayStorage.sol (1)

Line range hint 1-40: Verify the usage of the removed constant GWEI_TO_WEI across the codebase.

The removal of the GWEI_TO_WEI constant could impact other parts of the codebase if it was used elsewhere.

Verification successful

Line range hint 1-40: The removal of the GWEI_TO_WEI constant from ClientChainGatewayStorage.sol does not impact the rest of the codebase. The constant is defined independently in other files where it is used.

  • src/storage/ExoCapsuleStorage.sol
  • script/13_DepositValidator.s.sol
  • src/core/ExoCapsule.sol
  • test/foundry/ExocoreDeployer.t.sol
  • test/foundry/DepositWithdrawPrinciple.t.sol
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of the constant `GWEI_TO_WEI` across the codebase.

# Test: Search for the constant usage. Expect: No occurrences of the constant.
rg --type solidity $'GWEI_TO_WEI'

Length of output: 65


Script:

#!/bin/bash
# Description: Verify the usage of the constant `GWEI_TO_WEI` across the codebase.

# Test: Search for the constant usage in all files and filter to only include Solidity files.
rg 'GWEI_TO_WEI' | grep '\.sol'

Length of output: 1391

src/core/NativeRestakingController.sol (3)

5-5: Approved the addition of BeaconChainProofs import.

This import is necessary for the new withdrawal logic implemented in the contract.


55-55: Approved the change from ExoCapsule to IExoCapsule.

Using an interface (IExoCapsule) instead of a direct contract type promotes better decoupling and flexibility in the code.


86-104: Review the updated withdrawal logic in processBeaconChainWithdrawal.

The modifications in the processBeaconChainWithdrawal function to handle partial and full withdrawals need a detailed review to ensure they align with the intended functionality and security standards.

Verification successful

Verified the updated withdrawal logic in processBeaconChainWithdrawal.

The modifications in the processBeaconChainWithdrawal function to handle partial and full withdrawals align with the intended functionality and security standards, as evidenced by the comprehensive test cases in test/foundry/DepositWithdrawPrinciple.t.sol.

  • src/core/NativeRestakingController.sol
  • test/foundry/DepositWithdrawPrinciple.t.sol
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the correct handling of partial and full withdrawals.

# Test: Search for the function usage and review the logic. Expect: Correct implementation according to specifications.
rg --type solidity -A 10 $'processBeaconChainWithdrawal'

Length of output: 88


Script:

#!/bin/bash
# Description: Verify the correct handling of partial and full withdrawals.

# Test: Search for the function usage and review the logic. Expect: Correct implementation according to specifications.
rg 'processBeaconChainWithdrawal' --glob '*.sol' -A 10

Length of output: 4094


Script:

#!/bin/bash
# Description: Extract relevant test cases for processBeaconChainWithdrawal function.

# Extract the entire test function(s) containing processBeaconChainWithdrawal
rg 'processBeaconChainWithdrawal' --glob 'test/foundry/DepositWithdrawPrinciple.t.sol' -A 50

Length of output: 8474

src/interfaces/INativeRestakingController.sol (2)

3-3: Approved the addition of BeaconChainProofs import.

This import supports the updated withdrawal logic in the interface, aligning with changes in the implementation.


81-85: Verify the consistency of the parameter type change in processBeaconChainWithdrawal.

The change from IExoCapsule.WithdrawalContainerProof to BeaconChainProofs.WithdrawalProof should be consistent across all related contracts and interfaces.

Verification successful

The parameter type change in processBeaconChainWithdrawal from IExoCapsule.WithdrawalContainerProof to BeaconChainProofs.WithdrawalProof is consistent across the relevant contracts and interfaces.

  • src/interfaces/INativeRestakingController.sol
  • src/core/NativeRestakingController.sol
  • test/foundry/DepositWithdrawPrinciple.t.sol
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the consistency of the parameter type change across related contracts.

# Test: Search for the parameter type usage. Expect: Consistent usage across all related files.
rg --type solidity $'BeaconChainProofs.WithdrawalProof'

Length of output: 87


Script:

#!/bin/bash
# Description: Verify the consistency of the parameter type change across related contracts.

# Search for the definition and usage of the processBeaconChainWithdrawal function
rg 'processBeaconChainWithdrawal'

# Search for any remaining instances of the old type IExoCapsule.WithdrawalContainerProof
rg 'IExoCapsule.WithdrawalContainerProof'

Length of output: 537


Script:

#!/bin/bash
# Extract the definition of the processBeaconChainWithdrawal function from the identified files

# Extract from src/interfaces/INativeRestakingController.sol
rg -A 10 'function processBeaconChainWithdrawal' src/interfaces/INativeRestakingController.sol

# Extract from src/core/NativeRestakingController.sol
rg -A 10 'function processBeaconChainWithdrawal' src/core/NativeRestakingController.sol

# Extract from test/foundry/DepositWithdrawPrinciple.t.sol
rg -A 10 'clientGateway.processBeaconChainWithdrawal' test/foundry/DepositWithdrawPrinciple.t.sol

Length of output: 2553

src/core/ClientGatewayLzReceiver.sol (2)

18-18: Approved the addition of the WithdrawFailedOnExocore event.

This event enhances the transparency and traceability of failed withdrawal operations.


118-134: Review the updated withdrawal logic in afterReceiveWithdrawPrincipalResponse.

The modifications to handle different tokens during withdrawals need a detailed review to ensure they align with the intended functionality and security standards, especially considering the learning about transaction reversion on failures.

Verification successful

Review the updated withdrawal logic in afterReceiveWithdrawPrincipalResponse.

The modifications to handle different tokens during withdrawals align with the intended functionality and security standards. The function correctly distinguishes between VIRTUAL_STAKED_ETH_ADDRESS and other tokens, updates the relevant balances, and emits appropriate events.

  • The function decodes the payloads to extract necessary information.
  • It checks the success flag and updates balances using either IExoCapsule or IVault based on the token type.
  • Relevant events are emitted to signal the result of the withdrawal.
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the correct handling of different tokens during withdrawals.

# Test: Search for the function usage and review the logic. Expect: Correct implementation according to specifications.
rg --type solidity -A 10 $'afterReceiveWithdrawPrincipalResponse'

Length of output: 97


Script:

#!/bin/bash
# Description: Verify the correct handling of different tokens during withdrawals.

# Test: Search for the function definition and review the logic. Expect: Correct implementation according to specifications.
rg 'function afterReceiveWithdrawPrincipalResponse' -A 20 --glob '*.sol'

Length of output: 1758


Script:

#!/bin/bash
# Description: Verify the correct handling of different tokens during withdrawals.

# Test: Search for the complete implementation of the function. Expect: Correct implementation according to specifications.
rg 'function afterReceiveWithdrawPrincipalResponse' -A 50 --glob '*.sol'

Length of output: 4095

test/foundry/test-data/full_withdrawal_proof.json (1)

1-159: Review of Full Withdrawal Proof JSON:

The JSON structure appears well-formed and includes necessary cryptographic proofs and indices. The keys such as slot, validatorIndex, historicalSummaryIndex, etc., are consistent with blockchain-related data structures. Ensure that the values, especially the cryptographic hashes and indices, are validated against expected formats and ranges in the implementation.

test/foundry/test-data/partial_withdrawal_proof.json (1)

1-159: Review of Partial Withdrawal Proof JSON:

This JSON structure for the partial withdrawal proof mirrors the full withdrawal proof, containing all necessary cryptographic proofs and indices. It is well-formed and appears to adhere to expected blockchain data structures. Ensure that the values, especially cryptographic hashes and indices, are validated against expected formats and ranges in the implementation.

src/libraries/BeaconChainProofs.sol (1)

Line range hint 3-287: Review of BeaconChainProofs Solidity Library:

The BeaconChainProofs library is well-structured and includes a comprehensive set of functions and constants for handling beacon chain proofs. The use of external libraries like Endian and Merkle is appropriate. Ensure that the cryptographic operations, especially those involving Merkle proofs, are secure and efficient. The constants and indices should be double-checked for accuracy against the beacon chain specifications.

src/core/ExoCapsule.sol (1)

Line range hint 15-259: Review of ExoCapsule Contract:

The ExoCapsule contract is robust, with new functionalities for handling partial and full withdrawals, ETH transactions, and proof validations. The use of ReentrancyGuardUpgradeable is appropriate for preventing reentrancy attacks. The new events and error messages enhance the contract's usability and error handling. Ensure that all ETH transactions are secure, especially those in the _sendETH function, and that all withdrawal proofs are thoroughly validated before any state changes or ETH transfers are performed.

test/foundry/ExocoreDeployer.t.sol (4)

237-265: Improve error handling and verify JSON structure in _loadWithdrawalContainer.

Enhance error handling to gracefully handle potential issues with JSON parsing or data integrity in _loadWithdrawalContainer.

-        require(withdrawalContainer.length > 0, "validator container should not be empty");
+        if (withdrawalContainer.length == 0) {
+            revert("Withdrawal container is empty or not properly formatted.");
+        }
Verification successful

Improve error handling and verify JSON structure in _loadWithdrawalContainer.

Enhance error handling to gracefully handle potential issues with JSON parsing or data integrity in _loadWithdrawalContainer.

  • The JSON structure is correct and complete.
  • Consider improving error handling as suggested:
-        require(withdrawalContainer.length > 0, "validator container should not be empty");
+        if (withdrawalContainer.length == 0) {
+            revert("Withdrawal container is empty or not properly formatted.");
+        }
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the JSON structure and data integrity for withdrawal container.

# Test: Check JSON structure for completeness and correctness. Expect: JSON structure is correct and complete.
cat test/foundry/test-data/full_withdrawal_proof.json | jq .

Length of output: 10504


218-218: Optimize handling of native fees and verify event emissions.

Consider optimizing the handling of native fees to ensure efficiency. Also, verify that all expected events are emitted correctly during the execution of test_AddWhitelistTokens.

-        uint256 registerTokensRequestNativeFee = clientGateway.quote(registerTokensRequestPayload);
+        // Optimize fee calculation
+        uint256 registerTokensRequestNativeFee = clientGateway.estimateFee(registerTokensRequestPayload);
Verification successful

All expected events are emitted correctly.

The verification confirms that the events NewPacket, MessageSent, VaultCreated, and WhitelistTokenAdded are all emitted in the test/foundry/ExocoreDeployer.t.sol file.

  • emit NewPacket: Found at line 1.
  • emit MessageSent: Found at line 6.
  • emit VaultCreated: Found at line 11.
  • emit WhitelistTokenAdded: Found at lines 12 and 13.
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that all expected events are emitted correctly.

# Test: Search for event emissions in the function. Expect: All events are emitted.
rg --type solidity -A 5 $'emit NewPacket' test/foundry/ExocoreDeployer.t.sol
rg --type solidity -A 5 $'emit MessageSent' test/foundry/ExocoreDeployer.t.sol
rg --type solidity -A 5 $'emit VaultCreated' test/foundry/ExocoreDeployer.t.sol
rg --type solidity -A 5 $'emit WhitelistTokenAdded' test/foundry/ExocoreDeployer.t.sol

Length of output: 458


Script:

#!/bin/bash
# Description: Verify that all expected events are emitted correctly using ast-grep.

# Test: Search for event emissions in the function. Expect: All events are emitted.
ast-grep --lang solidity --pattern $'emit NewPacket($_, $_);' test/foundry/ExocoreDeployer.t.sol
ast-grep --lang solidity --pattern $'emit MessageSent($_, $_);' test/foundry/ExocoreDeployer.t.sol
ast-grep --lang solidity --pattern $'emit VaultCreated($_, $_);' test/foundry/ExocoreDeployer.t.sol
ast-grep --lang solidity --pattern $'emit WhitelistTokenAdded($_, $_);' test/foundry/ExocoreDeployer.t.sol

Length of output: 874


Script:

#!/bin/bash
# Description: Verify that all expected events are emitted correctly using grep.

# Test: Search for event emissions in the function. Expect: All events are emitted.
grep -E 'emit NewPacket\(' -A 5 test/foundry/ExocoreDeployer.t.sol
grep -E 'emit MessageSent\(' -A 5 test/foundry/ExocoreDeployer.t.sol
grep -E 'emit VaultCreated\(' -A 5 test/foundry/ExocoreDeployer.t.sol
grep -E 'emit WhitelistTokenAdded\(' -A 5 test/foundry/ExocoreDeployer.t.sol

Length of output: 1398


218-218: Improve error handling and verify JSON structure.

Enhance error handling in _loadValidatorContainer to gracefully handle potential issues with JSON parsing or data integrity.

-        require(validatorContainer.length > 0, "validator container should not be empty");
+        if (validatorContainer.length == 0) {
+            revert("Validator container is empty or not properly formatted.");
+        }
Verification successful

Improve error handling and verify JSON structure.

Enhance error handling in _loadValidatorContainer to gracefully handle potential issues with JSON parsing or data integrity.

-        require(validatorContainer.length > 0, "validator container should not be empty");
+        if (validatorContainer.length == 0) {
+            revert("Validator container is empty or not properly formatted.");
+        }

The JSON structure appears to be correct and complete based on the provided output.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the JSON structure and data integrity.

# Test: Check JSON structure for completeness and correctness. Expect: JSON structure is correct and complete.
cat test/foundry/test-data/validator_container_proof_302913.json | jq .

Length of output: 8000


266-266: Verify contract deployments and optimize the deployment process.

Ensure that all contracts are deployed correctly in the _deploy function. Consider optimizing the deployment process to enhance efficiency.

test/foundry/DepositWithdrawPrinciple.t.sol (3)

32-32: Constant for max restaked balance per validator is set correctly.

The value 32e9 aligns with typical staking limits in Ethereum, which is 32 Ether.


386-386: Function _simulateBlockEnvironmentForNativeDeposit is implemented correctly.

This function accurately sets up the block environment necessary for testing the deposit logic.


498-518: Function _simulateBlockEnvironmentForNativeWithdraw sets up the block environment accurately for withdrawal tests.

The function correctly adjusts timestamps and loads necessary data, ensuring accurate simulation for withdrawal operations.

test/foundry/unit/ExoCapsule.t.sol (3)

Line range hint 117-194: Review of VerifyDepositProof Contract

This contract extends DepositSetup and includes methods to verify deposit proofs. The implementation is detailed and includes various scenarios for proof verification.

  • Correctness: Methods like test_verifyDepositProof_success and test_verifyDepositProof_revert_validatorAlreadyDeposited correctly simulate different conditions and use the vm.expectRevert to handle expected failures.
  • Performance: Consider optimizing the repeated calculation of activationTimestamp by storing it once if it does not change during the tests.
  • Error Handling: The use of vm.expectRevert is appropriate for testing error conditions. However, ensure that all possible error codes are covered in tests.

299-468: Review of WithdrawalSetup Contract

The WithdrawalSetup contract is structured similarly to DepositSetup but focuses on withdrawal scenarios. It includes a setup function and methods to manipulate and verify withdrawal data.

  • Correctness: The contract setup and utility functions appear to handle the withdrawal data correctly.
  • Security: Ensure that the direct manipulation of contract storage (stdstore) is accurately representing the state changes that would occur in a live environment.
  • Maintainability: The clear separation of withdrawal logic into its own contract aids in understanding and maintaining the code.

472-540: Review of VerifyWithdrawalProof Contract

This contract extends WithdrawalSetup and introduces tests for both full and partial withdrawal scenarios using modifiers to set up the test environment.

  • Correctness: The implementation of test cases such as test_processFullWithdrawal_success and test_processPartialWithdrawal_success demonstrates a thorough approach to testing the withdrawal functionality.
  • Best Practices: The use of modifiers like setValidatorContainerAndTimestampForFullWithdrawal to prepare the test environment is a good practice, ensuring that each test runs in a correctly initialized state.
  • Security: The tests include checks for conditions that should cause reversions, which is crucial for ensuring the robustness of the withdrawal process.

Comment on lines +405 to +496
function _testNativeWithdraw(Player memory withdrawer, Player memory relayer, uint256 lastlyUpdatedPrincipalBalance)
internal
{
// before native withdraw, we simulate proper block environment states to make proof valid
_simulateBlockEnvironmentForNativeWithdraw();
deal(address(capsule), 1 ether); // Deposit 1 ether to handle excess amount withdraw

// 2. withdrawer will call clientGateway.processBeaconChainWithdrawal to withdraw from Exocore thru layerzero

/// client chain layerzero endpoint should emit the message packet including deposit payload.
uint64 withdrawRequestNonce = 2;
uint64 withdrawalAmountGwei = _getWithdrawalAmount(withdrawalContainer);
uint256 withdrawalAmount;
if (withdrawalAmountGwei > MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR) {
withdrawalAmount = MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR * GWEI_TO_WEI;
} else {
withdrawalAmount = withdrawalAmountGwei * GWEI_TO_WEI;
}
bytes memory withdrawRequestPayload = abi.encodePacked(
GatewayStorage.Action.REQUEST_WITHDRAW_PRINCIPAL_FROM_EXOCORE,
bytes32(bytes20(VIRTUAL_STAKED_ETH_ADDRESS)),
bytes32(bytes20(withdrawer.addr)),
withdrawalAmount
);
uint256 withdrawRequestNativeFee = clientGateway.quote(withdrawRequestPayload);
bytes32 withdrawRequestId = generateUID(withdrawRequestNonce, true);

// client chain layerzero endpoint should emit the message packet including withdraw payload.
vm.expectEmit(true, true, true, true, address(clientChainLzEndpoint));
emit NewPacket(
exocoreChainId,
address(clientGateway),
address(exocoreGateway).toBytes32(),
withdrawRequestNonce,
withdrawRequestPayload
);
// client chain gateway should emit MessageSent event
vm.expectEmit(true, true, true, true, address(clientGateway));
emit MessageSent(
GatewayStorage.Action.REQUEST_WITHDRAW_PRINCIPAL_FROM_EXOCORE,
withdrawRequestId,
withdrawRequestNonce,
withdrawRequestNativeFee
);

vm.startPrank(withdrawer.addr);
clientGateway.processBeaconChainWithdrawal{value: withdrawRequestNativeFee}(
validatorContainer, validatorProof, withdrawalContainer, withdrawalProof
);
vm.stopPrank();

/// exocore gateway should return response message to exocore network layerzero endpoint
uint64 withdrawResponseNonce = 3;
lastlyUpdatedPrincipalBalance -= withdrawalAmount;
bytes memory withdrawResponsePayload =
abi.encodePacked(GatewayStorage.Action.RESPOND, withdrawRequestNonce, true, lastlyUpdatedPrincipalBalance);
uint256 withdrawResponseNativeFee = exocoreGateway.quote(clientChainId, withdrawResponsePayload);
bytes32 withdrawResponseId = generateUID(withdrawResponseNonce, false);

// exocore gateway should return response message to exocore network layerzero endpoint
vm.expectEmit(true, true, true, true, address(exocoreLzEndpoint));
emit NewPacket(
clientChainId,
address(exocoreGateway),
address(clientGateway).toBytes32(),
withdrawResponseNonce,
withdrawResponsePayload
);
// exocore gateway should emit MessageSent event
vm.expectEmit(true, true, true, true, address(exocoreGateway));
emit MessageSent(
GatewayStorage.Action.RESPOND, withdrawResponseId, withdrawResponseNonce, withdrawResponseNativeFee
);
exocoreLzEndpoint.lzReceive(
Origin(clientChainId, address(clientGateway).toBytes32(), withdrawRequestNonce),
address(exocoreGateway),
withdrawRequestId,
withdrawRequestPayload,
bytes("")
);

// client chain gateway should execute the response hook and emit depositResult event
vm.expectEmit(true, true, true, true, address(clientGateway));
emit WithdrawPrincipalResult(true, address(VIRTUAL_STAKED_ETH_ADDRESS), withdrawer.addr, withdrawalAmount);
clientChainLzEndpoint.lzReceive(
Origin(exocoreChainId, address(exocoreGateway).toBytes32(), withdrawResponseNonce),
address(clientGateway),
withdrawResponseId,
withdrawResponsePayload,
bytes("")
);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Function _testNativeWithdraw correctly implements withdrawal logic with appropriate checks.

The function correctly caps the withdrawal amount based on the MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR constant. Consider refactoring the withdrawal amount calculation for clarity.

- if (withdrawalAmountGwei > MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR) {
-     withdrawalAmount = MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR * GWEI_TO_WEI;
- } else {
-     withdrawalAmount = withdrawalAmountGwei * GWEI_TO_WEI;
- }
+ withdrawalAmount = min(withdrawalAmountGwei, MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR) * GWEI_TO_WEI;
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 _testNativeWithdraw(Player memory withdrawer, Player memory relayer, uint256 lastlyUpdatedPrincipalBalance)
internal
{
// before native withdraw, we simulate proper block environment states to make proof valid
_simulateBlockEnvironmentForNativeWithdraw();
deal(address(capsule), 1 ether); // Deposit 1 ether to handle excess amount withdraw
// 2. withdrawer will call clientGateway.processBeaconChainWithdrawal to withdraw from Exocore thru layerzero
/// client chain layerzero endpoint should emit the message packet including deposit payload.
uint64 withdrawRequestNonce = 2;
uint64 withdrawalAmountGwei = _getWithdrawalAmount(withdrawalContainer);
uint256 withdrawalAmount;
if (withdrawalAmountGwei > MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR) {
withdrawalAmount = MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR * GWEI_TO_WEI;
} else {
withdrawalAmount = withdrawalAmountGwei * GWEI_TO_WEI;
}
bytes memory withdrawRequestPayload = abi.encodePacked(
GatewayStorage.Action.REQUEST_WITHDRAW_PRINCIPAL_FROM_EXOCORE,
bytes32(bytes20(VIRTUAL_STAKED_ETH_ADDRESS)),
bytes32(bytes20(withdrawer.addr)),
withdrawalAmount
);
uint256 withdrawRequestNativeFee = clientGateway.quote(withdrawRequestPayload);
bytes32 withdrawRequestId = generateUID(withdrawRequestNonce, true);
// client chain layerzero endpoint should emit the message packet including withdraw payload.
vm.expectEmit(true, true, true, true, address(clientChainLzEndpoint));
emit NewPacket(
exocoreChainId,
address(clientGateway),
address(exocoreGateway).toBytes32(),
withdrawRequestNonce,
withdrawRequestPayload
);
// client chain gateway should emit MessageSent event
vm.expectEmit(true, true, true, true, address(clientGateway));
emit MessageSent(
GatewayStorage.Action.REQUEST_WITHDRAW_PRINCIPAL_FROM_EXOCORE,
withdrawRequestId,
withdrawRequestNonce,
withdrawRequestNativeFee
);
vm.startPrank(withdrawer.addr);
clientGateway.processBeaconChainWithdrawal{value: withdrawRequestNativeFee}(
validatorContainer, validatorProof, withdrawalContainer, withdrawalProof
);
vm.stopPrank();
/// exocore gateway should return response message to exocore network layerzero endpoint
uint64 withdrawResponseNonce = 3;
lastlyUpdatedPrincipalBalance -= withdrawalAmount;
bytes memory withdrawResponsePayload =
abi.encodePacked(GatewayStorage.Action.RESPOND, withdrawRequestNonce, true, lastlyUpdatedPrincipalBalance);
uint256 withdrawResponseNativeFee = exocoreGateway.quote(clientChainId, withdrawResponsePayload);
bytes32 withdrawResponseId = generateUID(withdrawResponseNonce, false);
// exocore gateway should return response message to exocore network layerzero endpoint
vm.expectEmit(true, true, true, true, address(exocoreLzEndpoint));
emit NewPacket(
clientChainId,
address(exocoreGateway),
address(clientGateway).toBytes32(),
withdrawResponseNonce,
withdrawResponsePayload
);
// exocore gateway should emit MessageSent event
vm.expectEmit(true, true, true, true, address(exocoreGateway));
emit MessageSent(
GatewayStorage.Action.RESPOND, withdrawResponseId, withdrawResponseNonce, withdrawResponseNativeFee
);
exocoreLzEndpoint.lzReceive(
Origin(clientChainId, address(clientGateway).toBytes32(), withdrawRequestNonce),
address(exocoreGateway),
withdrawRequestId,
withdrawRequestPayload,
bytes("")
);
// client chain gateway should execute the response hook and emit depositResult event
vm.expectEmit(true, true, true, true, address(clientGateway));
emit WithdrawPrincipalResult(true, address(VIRTUAL_STAKED_ETH_ADDRESS), withdrawer.addr, withdrawalAmount);
clientChainLzEndpoint.lzReceive(
Origin(exocoreChainId, address(exocoreGateway).toBytes32(), withdrawResponseNonce),
address(clientGateway),
withdrawResponseId,
withdrawResponsePayload,
bytes("")
);
}
uint256 withdrawalAmount;
withdrawalAmount = min(withdrawalAmountGwei, MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR) * GWEI_TO_WEI;

@cloud8little cloud8little deleted the fix/native-restaking-withdraw-in-progress branch July 23, 2024 03:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants