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

feat: enable Ethereum native restaking for Bootstrap #121

Merged
merged 8 commits into from
Nov 4, 2024

Conversation

adu-web3
Copy link
Collaborator

@adu-web3 adu-web3 commented Oct 29, 2024

Description

As we need to support Ethereum native restaking during bootstrap, we should allow the stakers to deposit staked ETH of beacon chain to Exocore, by pointing withdrawal credentials to capsule contract the staker creates and owns.

TODO:

  • let Bootstrap inherit INativeRestakingController and implement relative functions
  • move ownerToCapsule state from ClientChainGatewayStorage to BootstrapStorage
  • refactor BootstrapStorage constructor function by using ImmutableConfig struct to work around stack too deep compilation error
  • add unit tests in Bootstrap.t.sol and integration test in BootstrapDepositNSTTest.t.sol
  • add comments and docs

Summary by CodeRabbit

  • New Features

    • Introduced a new verifyAndDepositNativeStake function for enhanced deposit verification and processing.
    • Added withdrawNonBeaconChainETHFromCapsule function for ETH withdrawals from ExoCapsule.
    • New ImmutableConfig struct consolidates configuration parameters for improved contract initialization.
  • Bug Fixes

    • Enhanced error handling across various functions to manage invalid states and conditions.
    • Added InvalidImmutableConfig error for better error management in configuration.
  • Tests

    • Expanded testing coverage for staking and deposit functionalities, including new test cases for capsule creation and deposit verification.
  • Documentation

    • Updated comments and event emissions for clarity in deposit and withdrawal processes.

Copy link
Contributor

coderabbitai bot commented Oct 29, 2024

Walkthrough

This pull request introduces significant changes to the staking and deposit functionality within the Ethereum ecosystem. Key modifications include renaming the depositBeaconChainValidator method to verifyAndDepositNativeStake, reflecting a shift towards enhanced verification processes. The implementation of an ImmutableConfig struct across various contracts simplifies parameter management during contract initialization. Additionally, new validation checks and error handling mechanisms are introduced to ensure the integrity of deposit operations. Overall, these changes streamline the deposit process and improve the organization of code across multiple contracts.

Changes

File Path Change Summary
docs/native_deposit_workflow.wsd Renamed method: depositBeaconChainValidatorverifyAndDepositNativeStake in NativeRestakingController.
script/12_RedeployClientChainGateway.s.sol Added import for BootstrapStorage. Updated run function to use ImmutableConfig struct for ClientChainGateway instantiation.
script/13_DepositValidator.s.sol Updated method call from clientGateway.depositBeaconChainValidator to clientGateway.verifyAndDepositNativeStake.
script/14_CorrectBootstrapErrors.s.sol Added import for BootstrapStorage. Updated setUp function with additional address checks. Replaced individual parameters with ImmutableConfig struct in Bootstrap instantiation.
script/2_DeployBoth.s.sol Added import for BootstrapStorage. Updated run function to utilize ImmutableConfig struct for ClientChainGateway instantiation.
script/7_DeployBootstrap.s.sol Added import for BootstrapStorage. Updated run function to deploy Bootstrap using ImmutableConfig struct.
script/integration/1_DeployBootstrap.s.sol Added imports for EigenLayerBeaconOracle, BootstrapStorage, and ExoCapsule. Updated deployContract to use ImmutableConfig struct for Bootstrap initialization.
src/core/Bootstrap.sol Added new methods for native restaking. Updated constructor to accept ImmutableConfig struct.
src/core/ClientChainGateway.sol Updated constructor to accept ImmutableConfig struct.
src/core/NativeRestakingController.sol Renamed function depositBeaconChainValidator to verifyAndDepositNativeStake. Removed nativeRestakingEnabled modifier.
src/interfaces/INativeRestakingController.sol Renamed function depositBeaconChainValidator to verifyAndDepositNativeStake. Added new function withdrawNonBeaconChainETHFromCapsule.
src/storage/BootstrapStorage.sol Added new mapping ownerToCapsule and ImmutableConfig struct. Updated constructor to accept ImmutableConfig.
src/storage/ClientChainGatewayStorage.sol Removed ownerToCapsule mapping. Updated constructor to accept ImmutableConfig and simplified state management.
test/foundry/BootstrapDepositNST.t.sol Introduced a new test contract for Bootstrap functionality, including various test cases for deposit processes and event emissions.
test/foundry/DepositWithdrawPrinciple.t.sol Updated test cases to reflect the new method name verifyAndDepositNativeStake. Enhanced event emissions for deposit and withdrawal workflows.
test/foundry/ExocoreDeployer.t.sol Added import for BootstrapStorage. Updated ClientChainGateway instantiation to use ImmutableConfig struct.
test/foundry/Governance.t.sol Added import for BootstrapStorage. Updated ClientChainGateway constructor to use ImmutableConfig.
test/foundry/unit/Bootstrap.t.sol Added tests for staking functionality and updated initialization to use ImmutableConfig.
test/foundry/unit/ClientChainGateway.t.sol Modified test setup to use ImmutableConfig for ClientChainGateway initialization.

Possibly related PRs

Suggested reviewers

  • cloud8little
  • leonz789
  • bwhour

Poem

🐇 In the meadow where the stakes are high,
A rabbit hops beneath the sky.
With deposits verified, oh what a sight,
New structures in place, everything feels right!
So let us cheer for the code that's neat,
For every hop, a new feature's sweet! 🌼


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 or @coderabbitai title anywhere in the PR title to generate the title automatically.

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

Linting failed. Please check the logs.

Copy link

The tests have failed. Please check the logs.

Copy link

Storage layout compatibility check failed. This could be due to a mismatch between Bootstrap and ClientChainGateway, or incompatibility with deployed contracts on Sepolia. Please check the logs for details.

1 similar comment
Copy link

Storage layout compatibility check failed. This could be due to a mismatch between Bootstrap and ClientChainGateway, or incompatibility with deployed contracts on Sepolia. Please check the logs for details.

Copy link

Storage layout compatibility check failed. This could be due to a mismatch between Bootstrap and ClientChainGateway, or incompatibility with deployed contracts on Sepolia. Please check the logs for details.

1 similar comment
Copy link

Storage layout compatibility check failed. This could be due to a mismatch between Bootstrap and ClientChainGateway, or incompatibility with deployed contracts on Sepolia. Please check the logs for details.

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

🧹 Outside diff range and nitpick comments (18)
src/interfaces/INativeRestakingController.sol (2)

59-63: Consider enhancing documentation and security specifications.

A few suggestions for improvement:

  1. Consider adding an @notice comment to explain the purpose more clearly.
  2. Move the parameter constraint from @dev to @param amountToWithdraw.
  3. Consider adding @return documentation.
  4. Consider specifying access control requirements in the interface documentation.

Apply this documentation improvement:

-    /// @notice Withdraws the nonBeaconChainETHBalance from the ExoCapsule contract.
-    /// @dev @param amountToWithdraw can not be greater than the available nonBeaconChainETHBalance.
-    /// @param recipient The payable destination address to which the ETH are sent.
-    /// @param amountToWithdraw The amount to withdraw.
+    /// @notice Withdraws non-beacon chain ETH balance from the ExoCapsule contract
+    /// @dev Only callable by authorized roles (implementation should enforce access control)
+    /// @param recipient The payable destination address to receive the ETH
+    /// @param amountToWithdraw The amount of ETH to withdraw (must not exceed available non-beacon chain balance)
+    /// @return success Boolean indicating whether the withdrawal was successful

Line range hint 1-64: Interface design aligns well with native restaking requirements.

The interface provides a complete set of operations needed for Ethereum native restaking:

  1. Staking via stake()
  2. ExoCapsule creation via createExoCapsule()
  3. Deposit verification via verifyAndDepositNativeStake()
  4. Withdrawal processing via processBeaconChainWithdrawal()
  5. Non-beacon chain ETH withdrawal via withdrawNonBeaconChainETHFromCapsule()

This design effectively supports the workflow where stakers can deposit their beacon chain ETH into Exocore through their capsule contracts.

script/13_DepositValidator.s.sol (1)

Line range hint 83-87: Improve error handling in deployment script.

The current error handling is insufficient for a deployment script:

  1. The catch block silently continues with "fire anyway"
  2. No error details are logged
  3. No deployment status is tracked

Consider implementing more robust error handling:

-        try clientGateway.verifyAndDepositNativeStake{value: nativeFee}(validatorContainer, validatorProof) {
-            console.log("finish");
-        } catch {
-            console.log("fire anyway");
-        }
+        try clientGateway.verifyAndDepositNativeStake{value: nativeFee}(validatorContainer, validatorProof) {
+            console.log("Successfully deposited native stake");
+            return true;
+        } catch Error(string memory reason) {
+            console.log("Deposit failed with reason:", reason);
+            return false;
+        } catch Panic(uint errorCode) {
+            console.log("Deposit failed with panic code:", errorCode);
+            return false;
+        } catch (bytes memory lowLevelData) {
+            console.log("Deposit failed with low level error:", vm.toString(lowLevelData));
+            return false;
+        }
src/core/NativeRestakingController.sol (4)

Line range hint 61-89: Fix potential reentrancy vulnerability in createExoCapsule.

The function writes to state (ownerToCapsule) before making an external call to capsule.initialize(), which violates the checks-effects-interactions pattern. Additionally, there's no check if a contract already exists at the computed Create2 address.

Suggested fix:

 function createExoCapsule() public whenNotPaused nativeRestakingEnabled returns (address) {
     if (address(ownerToCapsule[msg.sender]) != address(0)) {
         revert Errors.NativeRestakingControllerCapsuleAlreadyCreated();
     }
+    address computedAddress = Create2.computeAddress(
+        bytes32(uint256(uint160(msg.sender))),
+        keccak256(abi.encodePacked(
+            BEACON_PROXY_BYTECODE.getBytecode(),
+            abi.encode(address(EXO_CAPSULE_BEACON), "")
+        ))
+    );
+    if (computedAddress.code.length > 0) {
+        revert Errors.NativeRestakingControllerCapsuleAlreadyExists();
+    }
     IExoCapsule capsule = IExoCapsule(
         Create2.deploy(
             0,
             bytes32(uint256(uint160(msg.sender))),
             abi.encodePacked(BEACON_PROXY_BYTECODE.getBytecode(), abi.encode(address(EXO_CAPSULE_BEACON), ""))
         )
     );
+    capsule.initialize(address(this), payable(msg.sender), BEACON_ORACLE_ADDRESS);
     ownerToCapsule[msg.sender] = capsule;
-    capsule.initialize(address(this), payable(msg.sender), BEACON_ORACLE_ADDRESS);
     emit CapsuleCreated(msg.sender, address(capsule));
     return address(capsule);
 }

Line range hint 105-134: Add event emission for partial withdrawals and amount validation.

The function handles partial withdrawals silently without emitting events, making it difficult to track these operations off-chain. Additionally, there's no minimum withdrawal amount validation.

Consider these improvements:

 function processBeaconChainWithdrawal(
     bytes32[] calldata validatorContainer,
     BeaconChainProofs.ValidatorContainerProof calldata validatorProof,
     bytes32[] calldata withdrawalContainer,
     BeaconChainProofs.WithdrawalProof calldata withdrawalProof
 ) external payable whenNotPaused nonReentrant nativeRestakingEnabled {
     IExoCapsule capsule = _getCapsule(msg.sender);
     (bool partialWithdrawal, uint256 withdrawalAmount) =
         capsule.verifyWithdrawalProof(validatorContainer, validatorProof, withdrawalContainer, withdrawalProof);
+    if (withdrawalAmount == 0) {
+        revert Errors.NativeRestakingControllerInvalidWithdrawalAmount();
+    }
     if (!partialWithdrawal) {
         // request full withdraw
         bytes32 validatorPubkey = validatorContainer.getPubkey();
         bytes memory actionArgs = abi.encodePacked(validatorPubkey, bytes32(bytes20(msg.sender)), withdrawalAmount);
         bytes memory encodedRequest = abi.encode(VIRTUAL_NST_ADDRESS, msg.sender, withdrawalAmount);
         _processRequest(Action.REQUEST_WITHDRAW_NST, actionArgs, encodedRequest);
+    } else {
+        emit PartialWithdrawalProcessed(msg.sender, withdrawalAmount);
     }
 }

Line range hint 135-150: Add recipient and amount validation for withdrawals.

The function should validate the recipient address and withdrawal amount before proceeding with the withdrawal.

Consider adding these validations:

 function withdrawNonBeaconChainETHFromCapsule(address payable recipient, uint256 amountToWithdraw)
     external
     whenNotPaused
     nonReentrant
     nativeRestakingEnabled
 {
+    if (recipient == address(0)) {
+        revert Errors.NativeRestakingControllerInvalidRecipient();
+    }
+    if (amountToWithdraw == 0) {
+        revert Errors.NativeRestakingControllerInvalidWithdrawalAmount();
+    }
     IExoCapsule capsule = _getCapsule(msg.sender);
     capsule.withdrawNonBeaconChainETHBalance(recipient, amountToWithdraw);
 }

Line range hint 1-150: Verify security measures for critical operations.

This contract handles significant ETH amounts and critical validator operations. Please ensure:

  1. Comprehensive test coverage for all edge cases
  2. Emergency pause mechanisms are properly tested
  3. Access control for admin functions is adequately restricted

Consider:

  1. Adding circuit breaker patterns for large withdrawals
  2. Implementing withdrawal limits
  3. Adding delay periods for significant operations
test/foundry/unit/ClientChainGateway.t.sol (1)

125-131: Consider adding address validation for config parameters

While the ImmutableConfig initialization is well-structured and consolidates the configuration parameters effectively, consider adding validation to ensure none of the addresses are zero addresses before initialization.

 BootstrapStorage.ImmutableConfig memory config = BootstrapStorage.ImmutableConfig({
     exocoreChainId: exocoreChainId,
     beaconOracleAddress: address(beaconOracle),
     vaultBeacon: address(vaultBeacon),
     exoCapsuleBeacon: address(capsuleBeacon),
     beaconProxyBytecode: address(beaconProxyBytecode)
 });
+require(address(beaconOracle) != address(0), "Invalid beaconOracle address");
+require(address(vaultBeacon) != address(0), "Invalid vaultBeacon address");
+require(address(capsuleBeacon) != address(0), "Invalid capsuleBeacon address");
+require(address(beaconProxyBytecode) != address(0), "Invalid beaconProxyBytecode address");
docs/native_deposit_workflow.wsd (1)

Line range hint 55-98: Align flowchart conditions with actual function logic

In the flowchart for verifyAndDepositNativeStake(), some conditional branches may not accurately reflect the implemented logic. Specifically:

  • The check if (msg.sender != gateway) should occur before interacting with the ExoCapsule, as permission checks are typically done upfront.
  • The use of fork may be unnecessary if the branches are not truly parallel processes.

Apply this diff to correct the flowchart:

 start

+:Check if caller is gateway;
 if (msg.sender != gateway) then (yes)
-    :Revert with "ExoCapsule: only client chain gateway could call this function";
+    :Revert with UnauthorizedCaller error;
     stop
 endif

 :Get the capsule associated with the message sender;
 if (capsule == address(0)) then (yes)
     :Revert with CapsuleDoesNotExist error;
     stop
 endif

-:Call capsule.verifyDepositProof(validatorContainer, proof);
-fork
 :Call capsule.verifyDepositProof(validatorContainer, proof);

This revision ensures the flowchart mirrors the function's actual control flow, improving maintainability and readability.

script/7_DeployBootstrap.s.sol (2)

67-68: Fix comment formatting for clarity

There is an extra /// on line 68~, which may be unintended. Adjusting the comment formatting will improve code readability.

Apply this diff to correct the comment:

-/// deploy vault implementation contract, capsule implementation contract, reward vault implementation contract
-///
+// Deploy vault, capsule, and reward vault implementation contracts

72-72: Adjust comment for consistency and clarity

Ensure that the comment on line 72~ accurately describes the subsequent code and follows consistent formatting.

Apply this diff:

-/// deploy the vault beacon, capsule beacon, reward vault beacon that store the implementation contract address
+// Deploy the vault and capsule beacons that store the implementation contract addresses
test/foundry/BootstrapDepositNST.t.sol (1)

145-168: Add error handling for file operations

When reading the validator data from a JSON file, the code does not handle potential errors such as the file not existing or the data being malformed. Adding error handling will make the tests more robust and prevent unexpected failures.

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

304-304: Improve comment clarity and grammar

Consider rephrasing the comment for better readability:

-// 1. next depositor call clientGateway.verifyAndDepositNativeStake to deposit into Exocore from client chain through layerzero
+// 1. Depositor calls clientGateway.verifyAndDepositNativeStake to deposit into Exocore from client chain through LayerZero

334-334: Improve comment clarity and grammar

Consider rephrasing the comment for clarity:

-/// call verifyAndDepositNativeStake to see if these events are emitted as expected
+/// Call verifyAndDepositNativeStake to confirm that the expected events are emitted as expected
src/core/Bootstrap.sol (2)

442-454: Placeholder Functions for Future Reward Mechanisms

The functions submitReward, claimRewardFromExocore, and withdrawReward currently revert with Errors.NotYetSupported(). This indicates that reward mechanisms are planned for future implementation.

Would you like assistance in outlining or implementing these reward functions?


788-796: Implement processBeaconChainWithdrawal Functionality

The processBeaconChainWithdrawal function currently reverts with Errors.NotYetSupported(). Implementing this function is crucial for handling withdrawal proofs from the beacon chain.

Would you like assistance in drafting the implementation for this function?

test/foundry/unit/Bootstrap.t.sol (2)

32-33: Remove duplicate import of Create2.

There is a duplicate import of Create2 at lines 32 and 33. Removing the redundant import will clean up the code.

Apply this diff to remove the duplicate import:

-import {Create2} from "@openzeppelin/contracts/utils/Create2.sol";

1671-1680: Use assertEq instead of assertTrue for value comparisons.

Using assertEq in your assertions provides clearer output when tests fail by displaying the expected and actual values. Consider replacing assertTrue with assertEq for better test diagnostics.

Apply this diff to improve the assertions:

- assertTrue(
-     bootstrap.totalDepositAmounts(addrs[0], VIRTUAL_STAKED_ETH_ADDRESS) == initialDeposit + expectedDepositValue
- );
+ assertEq(
+     bootstrap.totalDepositAmounts(addrs[0], VIRTUAL_STAKED_ETH_ADDRESS),
+     initialDeposit + expectedDepositValue,
+     "Total deposit amount mismatch after verifying and depositing native stake."
+ );

- assertTrue(
-     bootstrap.withdrawableAmounts(addrs[0], VIRTUAL_STAKED_ETH_ADDRESS)
-         == initialWithdrawable + expectedDepositValue
- );
+ assertEq(
+     bootstrap.withdrawableAmounts(addrs[0], VIRTUAL_STAKED_ETH_ADDRESS),
+     initialWithdrawable + expectedDepositValue,
+     "Withdrawable amount mismatch after verifying and depositing native stake."
+ );

- assertTrue(
-     bootstrap.depositsByToken(VIRTUAL_STAKED_ETH_ADDRESS) == initialDepositsByToken + expectedDepositValue
- );
+ assertEq(
+     bootstrap.depositsByToken(VIRTUAL_STAKED_ETH_ADDRESS),
+     initialDepositsByToken + expectedDepositValue,
+     "Deposits by token mismatch after verifying and depositing native stake."
+ );
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 54cb293 and 4bb7cea.

📒 Files selected for processing (19)
  • docs/native_deposit_workflow.wsd (2 hunks)
  • script/12_RedeployClientChainGateway.s.sol (2 hunks)
  • script/13_DepositValidator.s.sol (1 hunks)
  • script/14_CorrectBootstrapErrors.s.sol (3 hunks)
  • script/2_DeployBoth.s.sol (2 hunks)
  • script/7_DeployBootstrap.s.sol (3 hunks)
  • script/integration/1_DeployBootstrap.s.sol (5 hunks)
  • src/core/Bootstrap.sol (5 hunks)
  • src/core/ClientChainGateway.sol (1 hunks)
  • src/core/NativeRestakingController.sol (1 hunks)
  • src/interfaces/INativeRestakingController.sol (2 hunks)
  • src/storage/BootstrapStorage.sol (6 hunks)
  • src/storage/ClientChainGatewayStorage.sol (1 hunks)
  • test/foundry/BootstrapDepositNST.t.sol (1 hunks)
  • test/foundry/DepositWithdrawPrinciple.t.sol (2 hunks)
  • test/foundry/ExocoreDeployer.t.sol (2 hunks)
  • test/foundry/Governance.t.sol (2 hunks)
  • test/foundry/unit/Bootstrap.t.sol (15 hunks)
  • test/foundry/unit/ClientChainGateway.t.sol (2 hunks)
🧰 Additional context used
📓 Learnings (1)
test/foundry/unit/ClientChainGateway.t.sol (1)
Learnt from: MaxMustermann2
PR: ExocoreNetwork/exocore-contracts#16
File: test/foundry/Bootstrap.t.sol:156-156
Timestamp: 2024-10-09T01:26:20.424Z
Learning: The `setClientChainGatewayLogic` method in `src/core/Bootstrap.sol` now includes checks to ensure the address is non-zero and the initialization data is at least 4 bytes long to include the function selector.
🔇 Additional comments (43)
src/interfaces/INativeRestakingController.sol (1)

Line range hint 35-39: LGTM! Function rename improves clarity.

The renaming from depositBeaconChainValidator to verifyAndDepositNativeStake better reflects the function's dual responsibility of verification and deposit handling.

script/12_RedeployClientChainGateway.s.sol (2)

7-7: LGTM! Import changes are well-organized.

The new BootstrapStorage import is properly placed with other core imports and is necessary for the ImmutableConfig struct usage.

Also applies to: 9-9


61-73: Well-structured configuration changes, verify constructor parameters.

The refactoring to use ImmutableConfig improves code organization and maintainability. The struct encapsulates related parameters logically, aligning with the PR's architectural changes.

Let's verify the constructor parameter alignment:

✅ Verification successful

Constructor parameters match the deployment script correctly

The verification confirms that the constructor parameters in the deployment script match the implementation:

  1. The ClientChainGateway constructor signature matches exactly:
constructor(address endpoint_, ImmutableConfig memory params_, address rewardVaultBeacon_)
  1. The ImmutableConfig struct in BootstrapStorage.sol contains all the expected fields in the correct order:
struct ImmutableConfig {
    uint32 exocoreChainId;
    address beaconOracleAddress;
    address vaultBeacon;
    address exoCapsuleBeacon;
    address beaconProxyBytecode;
}

The deployment script correctly provides all required parameters in the proper order:

  • address(clientChainLzEndpoint) for endpoint_
  • config struct with all required fields for params_
  • address(rewardVaultBeacon) for rewardVaultBeacon_
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify ClientChainGateway constructor signature matches the deployment script

# Test: Search for ClientChainGateway constructor definition
ast-grep --pattern 'contract ClientChainGateway {
  $$$
  constructor($$$) {
    $$$
  }
  $$$
}'

Length of output: 99


Script:

#!/bin/bash
# Let's try a different approach to find the ClientChainGateway constructor

# First, let's find the file containing ClientChainGateway
fd "ClientChainGateway" --type f

# Then use ripgrep to search for constructor with context
rg "constructor.*ClientChainGateway" -A 10

Length of output: 315


Script:

#!/bin/bash
# Let's examine the ClientChainGateway.sol file directly
cat src/core/ClientChainGateway.sol | rg "constructor" -A 10 -B 2

# Also check the storage contract for the ImmutableConfig struct definition
cat src/storage/ClientChainGatewayStorage.sol | rg "struct ImmutableConfig" -A 10

Length of output: 1066


Script:

#!/bin/bash
# Let's check the storage contract directly since grep didn't find the struct
cat src/storage/ClientChainGatewayStorage.sol

Length of output: 3786


Script:

#!/bin/bash
# Let's check the BootstrapStorage.sol since it contains the ImmutableConfig struct
cat src/storage/BootstrapStorage.sol

Length of output: 23424

src/core/NativeRestakingController.sol (2)

Line range hint 90-104: Add validation and error handling for deposit verification.

The function needs additional safeguards and clarification:

  1. No validation of validatorContainer format/length
  2. No minimum deposit value check
  3. Comment states "_processRequest is a must-succeed action" but no explanation of failure handling

Please clarify:

  1. What happens if _processRequest fails?
  2. Are there any recovery mechanisms?
#!/bin/bash
# Search for _processRequest implementation and error handling
rg -A 10 "_processRequest.*Action\.REQUEST_DEPOSIT_NST"

Line range hint 38-60: Add input validation for BLS public key and signature.

While the function correctly validates the ETH amount and follows the checks-effects-interactions pattern, it lacks validation for the BLS public key and signature format. This could lead to failed deposits if malformed data is provided.

Consider adding these validations:

  1. Verify pubkey length (48 bytes for BLS12-381)
  2. Verify signature length (96 bytes for BLS12-381)
  3. Check if validator already exists to prevent duplicate deposits
script/14_CorrectBootstrapErrors.s.sol (5)

22-22: LGTM: Import aligns with new configuration structure.

The addition of BootstrapStorage import supports the new configuration management approach using ImmutableConfig.


76-81: LGTM: Enhanced validation for critical components.

The additional checks for beaconOracle and capsuleBeacon addresses ensure all required components for native restaking are properly configured.


93-101: LGTM: Well-structured configuration management.

The ImmutableConfig struct provides a clean and organized way to manage configuration parameters, improving code maintainability and reducing the risk of initialization errors.


102-103: Verify upgrade compatibility.

The upgrade process involves both a new implementation and initialization. Please ensure:

  1. The new Bootstrap implementation is backward compatible with existing state
  2. The reinitializer version (2) mentioned in the comment is correctly set in the Bootstrap contract
#!/bin/bash
# Check reinitializer version in Bootstrap contract
ast-grep --pattern 'function initialize($$$) $_ {
  $$$
  reinitializer(2)
  $$$
}'

Also applies to: 116-117


102-102: Verify Bootstrap constructor parameters.

While the configuration looks correct, please ensure that the clientChainLzEndpoint and config parameters are properly validated in the Bootstrap contract's constructor.

✅ Verification successful

Based on the code examination, I can now generate the final response:

Constructor parameters are properly validated in Bootstrap contract

The constructor parameters are properly validated through multiple mechanisms:

  • The endpoint_ parameter is validated in the parent OAppCoreUpgradeable constructor
  • The params struct is validated in the parent BootstrapStorage constructor
  • The constructor immediately disables initializers as a security measure

Additionally, from the learnings, we know that setClientChainGatewayLogic method (which is part of the initialization flow) includes checks to ensure addresses are non-zero and initialization data is valid.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check Bootstrap contract's constructor validation
ast-grep --pattern 'contract Bootstrap {
  $$$
  constructor(address $_endpoint, $_ memory $_config) {
    $$$
    require($_endpoint != address(0), $_);
    $$$
  }
}'

Length of output: 241


Script:

#!/bin/bash
# Let's try to find and examine the Bootstrap contract's constructor
rg "constructor.*Bootstrap" -A 10

Length of output: 767


Script:

#!/bin/bash
# Let's try to find the Bootstrap contract file first and then examine its contents
fd Bootstrap.sol --type f --exec cat {}

Length of output: 35626

script/2_DeployBoth.s.sol (3)

13-13: LGTM: Import statement is correctly placed and necessary.

The addition of BootstrapStorage import aligns with the new ImmutableConfig struct usage.


63-74: LGTM: Implementation and beacon deployments follow best practices.

The deployment sequence is well-structured with each implementation paired with its corresponding beacon. The simplified comment style maintains clarity while being more concise.


75-87: Verify parameter validation in ClientChainGateway constructor.

While grouping configuration parameters into an ImmutableConfig struct improves code organization, we should ensure proper validation of these parameters in the ClientChainGateway constructor to prevent initialization with zero addresses.

Let's verify the parameter validation in the ClientChainGateway constructor:

✅ Verification successful

Parameter validation is properly implemented in parent contracts

The validation concern is addressed through proper inheritance chain:

  • ClientChainGateway inherits from ClientChainGatewayStorage and OAppCoreUpgradeable
  • ClientChainGatewayStorage inherits from BootstrapStorage
  • BootstrapStorage implements comprehensive validation for all ImmutableConfig parameters:
    • Validates exocoreChainId is not zero
    • Validates beaconOracleAddress is not zero address
    • Validates vaultBeacon is not zero address
  • Additionally, ClientChainGatewayStorage validates the rewardVaultBeacon parameter
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if ClientChainGateway validates ImmutableConfig parameters

# Test: Search for parameter validation in the constructor
ast-grep --pattern 'constructor($config, $_) {
  $$$
  require($config.$_ != address(0), $_);
  $$$
}'

# Test: Search for any other validation patterns
rg -A 3 'require.*config\.' src/

Length of output: 139


Script:

#!/bin/bash
# Let's try a broader search to find the ClientChainGateway constructor implementation

# Search for ClientChainGateway constructor
ast-grep --pattern 'contract ClientChainGateway {
  $$$
  constructor($$$) {
    $$$
  }
  $$$
}'

# Also search for any require statements in ClientChainGateway
rg -B 2 -A 5 'ClientChainGateway' --type sol

Length of output: 172


Script:

#!/bin/bash
# Let's try finding the file first and then examine its contents
fd ClientChainGateway

# Then search for constructor implementation
rg -B 2 -A 10 "constructor.*ImmutableConfig"

Length of output: 4412

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

38-38: LGTM: Import statement is correctly placed and necessary.

The import of BootstrapStorage is required for using the ImmutableConfig struct in the test file.


155-162: LGTM: ImmutableConfig struct is properly initialized with all required parameters.

The configuration includes all necessary components for the native restaking functionality, with proper initialization of beacon addresses and chain configuration.


164-165: LGTM: ClientChainGateway constructor updated correctly with new parameter structure.

The constructor call properly uses the new ImmutableConfig struct along with the required endpoint and reward vault beacon addresses.


154-166: Verify test coverage for native restaking functionality.

While the configuration changes are properly implemented, consider adding specific test cases for:

  1. Native restaking initialization
  2. Validation of ImmutableConfig parameters
  3. Integration with beacon chain withdrawal credentials
test/foundry/unit/ClientChainGateway.t.sol (2)

24-24: LGTM: Import statement properly added

The import for BootstrapStorage is correctly placed and necessary for the ImmutableConfig struct usage.


133-133: LGTM: ClientChainGateway initialization updated correctly

The initialization is properly updated to use the new ImmutableConfig struct and includes the rewardVaultBeacon parameter. The change is well-tested through the existing test cases in the Initialize contract.

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

47-47: LGTM: Import statement is correctly placed.

The import for BootstrapStorage is appropriately placed with other storage-related imports.


366-366: Verify ClientChainGateway initialization.

The constructor call includes critical components for the system's functionality. Let's verify the initialization is properly tested.

✅ Verification successful

ClientChainGateway initialization is properly tested

The initialization is thoroughly verified in the Initialize contract within ClientChainGateway.t.sol. The test suite includes comprehensive checks for:

  • Exocore chain ID initialization
  • LayerZero endpoint initialization
  • Vault beacon initialization
  • Beacon proxy bytecode initialization
  • Beacon oracle initialization
  • ExoCapsule beacon initialization
  • Owner initialization
  • Initial pause state
  • Bootstrap state
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for tests that verify the initialization of ClientChainGateway
rg -A 5 "new ClientChainGateway.*config" --type sol

Length of output: 81


Script:

#!/bin/bash
# Search for tests that verify the initialization of ClientChainGateway
rg -A 5 "new ClientChainGateway"

Length of output: 4352


Script:

#!/bin/bash
# Let's check the test file content to verify initialization tests
cat test/foundry/unit/ClientChainGateway.t.sol

Length of output: 16222

script/7_DeployBootstrap.s.sol (5)

21-21: Ensure new imports are necessary and correctly used

The imports BootstrapStorage and EigenLayerBeaconOracle have been added. Verify that these contracts are required and are correctly utilized in the script.


65-65: Verify implementation of _deployBeaconOracle()

The function _deployBeaconOracle() is called to deploy beaconOracle, but its implementation is not shown here. Ensure that this function is properly defined, perhaps in the inherited BaseScript contract, and that it correctly deploys and returns an instance of EigenLayerBeaconOracle.


76-83: Verify the initialization of ImmutableConfig struct

Confirm that all parameters passed into the ImmutableConfig struct are correct and correspond to the expected values. Double-check that the addresses assigned to beaconOracleAddress, vaultBeacon, exoCapsuleBeacon, and beaconProxyBytecode are accurate and necessary for initializing the Bootstrap and ClientChainGateway contracts.


86-86: Confirm instantiation of Bootstrap with ImmutableConfig

The Bootstrap contract is instantiated using the config struct. This should align with the updated constructor in the Bootstrap contract. Ensure that all required parameters are included and correctly referenced.


91-93: Ensure correct instantiation of ClientChainGateway

The ClientChainGateway is instantiated with the config struct and the rewardVaultBeacon address. Verify that these parameters match the updated constructor of ClientChainGateway and that the initialization logic is correctly implemented.

script/integration/1_DeployBootstrap.s.sol (4)

7-19: Imports are appropriately added

The new import statements for EigenLayerBeaconOracle, BootstrapStorage, ExoCapsule, and IExoCapsule are necessary for the added functionalities and are correctly referenced.


59-63: New state variables introduced correctly

The introduction of state variables beaconOracle, capsuleImplementation, vaultBeacon, and capsuleBeacon is appropriate for managing the new oracle and capsule implementations.


117-119: Beacon oracle deployment is correctly implemented

The deployment of the EigenLayerBeaconOracle using the _deployBeaconOracle() function is properly integrated into the deployContract function.


134-143: ImmutableConfig struct initialization enhances configuration management

The creation and initialization of the ImmutableConfig struct consolidates configuration parameters, improving code organization and maintainability.

test/foundry/BootstrapDepositNST.t.sol (2)

274-282: Ensure correct mocking of external contract calls

When mocking the call to ETH_POS.deposit, verify that the mock accurately reflects the expected behavior of the deposit function. Misconfigured mocks can cause the test to pass or fail incorrectly.

Confirm that the deposit function in IETHPOSDeposit does not return a value, and adjust the mock accordingly:

-vm.mockCall(address(ETH_POS), abi.encodeWithSelector(ETH_POS.deposit.selector), abi.encode(true));
+vm.mockCall(address(ETH_POS), abi.encodeWithSelector(ETH_POS.deposit.selector), "");

185-189: Verify event emission expectations

The test expects certain events to be emitted using vm.expectEmit. Ensure that the events are correctly defined and that the expectEmit parameters match the event signatures. Incorrect configurations may cause the test to pass or fail incorrectly.

src/storage/BootstrapStorage.sol (2)

320-326: Ensure Modifier is Applied to Relevant Functions

Please verify that the nativeRestakingEnabled modifier is applied to all functions that require native restaking to be enabled. This ensures that any functions dependent on native restaking are correctly restricted when the feature is disabled.


146-148: Verify ETH_POS Deposit Contract Address

Confirm that the address 0x00000000219ab540356cBB839Cbe05303d7705Fa assigned to ETH_POS is correct and corresponds to the official ETH2.0 deposit contract. Using the correct contract address is crucial for the security and functionality of deposit operations.

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

336-336: Update reflects correct method usage

The method clientGateway.verifyAndDepositNativeStake is correctly called with the appropriate parameters, aligning with the updated functionality.

src/core/Bootstrap.sol (7)

9-9: Addition of Create2 Import

The import of Create2 is appropriate for deploying contracts with deterministic addresses, which is essential for the capsule creation functionality.


20-20: Adding Necessary Interfaces and Libraries

The imports of INativeRestakingController, IExoCapsule, and BeaconChainProofs are necessary for implementing the native restaking features.

Also applies to: 23-23, 27-27


47-47: Implementing INativeRestakingController Interface

Including INativeRestakingController in the list of implemented interfaces correctly extends the contract to support native restaking functionalities.


52-54: Updating Constructor to Use ImmutableConfig Struct

The constructor now accepts an ImmutableConfig struct, streamlining the initialization process and enhancing code maintainability.


709-727: Proper Handling of 32 ETH Stake in stake Function

The stake function correctly ensures that exactly 32 ETH is staked, aligning with Ethereum's validator requirements. The creation of a capsule if it doesn't exist enhances user experience.


735-755: Secure Implementation of createExoCapsule Function

The createExoCapsule function uses Create2 for deterministic deployment and correctly prevents multiple capsules per user. The use of the checks-effects-interactions pattern enhances security by updating state before external calls.


802-810: Access Control Verification in withdrawNonBeaconChainETHFromCapsule

The function withdrawNonBeaconChainETHFromCapsule allows users to withdraw ETH from their capsule. Ensure that access control is correctly enforced so only the capsule owner can perform withdrawals.

You can verify the access control with the following script:

✅ Verification successful

Let me try a different pattern to locate the _getCapsule function implementation.


Let me check the mapping between owners and capsules to verify the access control.


Based on the gathered information, I can now provide the final response:

Access Control is Properly Implemented in withdrawNonBeaconChainETHFromCapsule

The function correctly enforces access control through:

  1. The _getCapsule function which verifies capsule ownership by checking ownerToCapsule[msg.sender]
  2. Reverts with CapsuleDoesNotExist if the caller doesn't own a capsule
  3. The mapping ownerToCapsule can only be modified during capsule creation and is properly validated
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that only the capsule owner can call `withdrawNonBeaconChainETHFromCapsule`.

# Expected result: The function should only be callable by the owner of the capsule.

# Command to search for the `_getCapsule` function and its usage.
ast-grep --pattern $'function _getCapsule($_) {
    $$ body
}' --json

# Check that `_getCapsule` retrieves the capsule based on `msg.sender` and that there are no alternate ways to access capsules.

Length of output: 73


Script:

#!/bin/bash
# Search for _getCapsule function with a more flexible pattern
ast-grep --pattern '_getCapsule'

# Also search using ripgrep for better context
rg "_getCapsule" -A 5

Length of output: 8282


Script:

#!/bin/bash
# Search for ownerToCapsule mapping and its usage
rg "ownerToCapsule" -A 5

# Also search for any other functions that might modify this mapping
ast-grep --pattern 'ownerToCapsule[$_] = $_'

Length of output: 7115

test/foundry/unit/Bootstrap.t.sol (1)

1556-1823: Comprehensive test cases for native restaking functionality.

The added test functions thoroughly cover various scenarios for Ethereum native restaking, including positive and negative test cases. This significantly enhances the test coverage and ensures the robustness of the new features.

script/13_DepositValidator.s.sol Outdated Show resolved Hide resolved
test/foundry/ExocoreDeployer.t.sol Show resolved Hide resolved
docs/native_deposit_workflow.wsd Show resolved Hide resolved
src/core/ClientChainGateway.sol Outdated Show resolved Hide resolved
script/integration/1_DeployBootstrap.s.sol Show resolved Hide resolved
test/foundry/BootstrapDepositNST.t.sol Show resolved Hide resolved
src/storage/BootstrapStorage.sol Outdated Show resolved Hide resolved
src/storage/BootstrapStorage.sol Outdated Show resolved Hide resolved
src/storage/BootstrapStorage.sol Outdated Show resolved Hide resolved
src/core/Bootstrap.sol 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: 3

🧹 Outside diff range and nitpick comments (7)
src/core/ClientChainGateway.sol (1)

45-46: Enhance NatSpec documentation for better clarity.

Consider expanding the parameter documentation to include:

  • The purpose and structure of the ImmutableConfig struct
  • The relationship between these parameters and the contract's functionality

Apply this diff to improve the documentation:

-    /// @param config is the struct containing the immutable state variables
+    /// @param config The configuration struct containing immutable state variables:
+    ///        - exocoreChainId: The chain ID of the Exocore network
+    ///        - beaconOracleAddress: The address of the beacon chain oracle
+    ///        - vaultBeacon: The beacon contract address for Vault proxies
+    ///        - exoCapsuleBeacon: The beacon contract address for ExoCapsule proxies
src/libraries/Errors.sol (1)

63-64: LGTM! Consider enhancing the error documentation.

The new error is well-placed and aligns with the PR's objectives of supporting Ethereum native restaking. The error will help validate immutable configurations during contract initialization.

Consider expanding the documentation to list specific validation criteria:

-    /// @dev Bootstrap: invalid immutable config, typically due to zero address or zero value
+    /// @dev Bootstrap: invalid immutable config
+    /// @dev Thrown when the immutable config validation fails due to:
+    /// @dev - Zero addresses in required address fields
+    /// @dev - Zero values in required numeric fields
+    /// @dev - Invalid ranges or relationships between config parameters
src/storage/BootstrapStorage.sol (1)

146-147: Consider making ETH_POS address configurable.

The ETH_POS deposit contract address is hardcoded to the Ethereum mainnet address. This could make testing difficult and might not work on other networks.

Consider making this address configurable through the constructor or a setter function, especially for testing environments.

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

Line range hint 304-336: Consider enhancing test coverage and consistency.

  1. The comment style is inconsistent (mixing // and ///). Consider standardizing to one style.
  2. Consider adding assertions to verify the capsule state after deposit.
-        /// client chain layerzero endpoint should emit the message packet including deposit payload.
+        // client chain layerzero endpoint should emit the message packet including deposit payload.

         // Add capsule state verification
+        assertEq(capsule.owner(), depositor.addr);
+        assertEq(capsule.gateway(), address(clientGateway));
src/core/Bootstrap.sol (3)

442-454: Stub Implementations for Reward Functions

The functions submitReward, claimRewardFromExocore, and withdrawReward currently revert with Errors.NotYetSupported(). Ensure these functions are implemented when reward functionality is added.


762-786: Ensure Capsule Existence Before Verification in verifyAndDepositNativeStake

While _getCapsule(msg.sender) reverts if the capsule does not exist, consider adding a clear error message to improve code readability and provide better feedback to users.

Apply this diff to add an explicit require statement:

IExoCapsule capsule = _getCapsule(msg.sender);
+ // Explicit check for capsule existence
+ require(address(capsule) != address(0), "Capsule does not exist for caller");
uint256 depositValue = capsule.verifyDepositProof(validatorContainer, proof);

788-798: Clarify Comments in processBeaconChainWithdrawal Function

The comment mentions that this function is not yet supported but suggests that stakers could call it after bootstrapping. To avoid confusion, update the comment to clearly state when this function will be available.

Apply this diff to update the comment:

/// @notice Verifies a withdrawal proof from the beacon chain and forwards the information to Exocore.
/// @notice This function is not yet supported. It will be available after bootstrapping is complete,
-/// but staker could call this function after bootstrapping to withdraw their stake.
+/// allowing stakers to withdraw their stake.
function processBeaconChainWithdrawal(
    bytes32[] calldata,
    BeaconChainProofs.ValidatorContainerProof calldata,
    bytes32[] calldata,
    BeaconChainProofs.WithdrawalProof calldata
) external payable whenNotPaused nativeRestakingEnabled {
    revert Errors.NotYetSupported();
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 4bb7cea and cc4f3cf.

📒 Files selected for processing (8)
  • script/13_DepositValidator.s.sol (1 hunks)
  • src/core/Bootstrap.sol (5 hunks)
  • src/core/ClientChainGateway.sol (1 hunks)
  • src/libraries/Errors.sol (1 hunks)
  • src/storage/BootstrapStorage.sol (6 hunks)
  • src/storage/ClientChainGatewayStorage.sol (2 hunks)
  • test/foundry/BootstrapDepositNST.t.sol (1 hunks)
  • test/foundry/DepositWithdrawPrinciple.t.sol (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/foundry/BootstrapDepositNST.t.sol
🧰 Additional context used
📓 Learnings (1)
src/core/Bootstrap.sol (2)
Learnt from: adu-web3
PR: ExocoreNetwork/exocore-contracts#121
File: docs/native_deposit_workflow.wsd:23-23
Timestamp: 2024-10-31T01:55:53.516Z
Learning: In the `verifyAndDepositNativeStake(validatorContainer, proof)` function of `NativeStakingController` in `docs/native_deposit_workflow.wsd`, the verification work is performed by calling `ExoCapsule`, so internal validations within `NativeStakingController` are minimal or handled by `ExoCapsule`.
Learnt from: bwhour
PR: ExocoreNetwork/exocore-contracts#121
File: src/core/Bootstrap.sol:762-786
Timestamp: 2024-10-30T11:22:55.750Z
Learning: In the Solidity contract `src/core/Bootstrap.sol`, within the `verifyAndDepositNativeStake` function, there is no need to check if the capsule exists before calling `_getCapsule(msg.sender)` because `_getCapsule` already reverts if the capsule does not exist.
🔇 Additional comments (13)
src/storage/ClientChainGatewayStorage.sol (2)

6-6: LGTM: Import organization.

The added empty line improves code organization by grouping related imports together.


72-78: Constructor refactoring looks good but verify storage layout.

The constructor changes appropriately consolidate parameters using ImmutableConfig and include proper validation. However, the removal of state variables raises concerns about storage layout compatibility.

Let's analyze the storage layout impact:

✅ Verification successful

Storage layout changes are safely handled with storage gaps

The storage layout changes in ClientChainGatewayStorage are safe because:

  1. The contract maintains a storage gap of 40 slots (uint256[40] private __gap)
  2. The inheritance chain (ClientChainGatewayStorage -> BootstrapStorage -> GatewayStorage) each have their own storage gaps
  3. The removed state variables (ownerToCapsule, BEACON_ORACLE_ADDRESS, EXO_CAPSULE_BEACON) are being compensated by the existing storage gaps
  4. The contract is part of an upgradeable contract system as evidenced by the presence of proxy patterns and upgrade scripts
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for potential storage layout incompatibilities
# Test 1: Look for deployed addresses or deployment scripts
echo "Checking for deployment references..."
rg -l "ClientChainGatewayStorage" | grep -iE "deploy|address|migration"

# Test 2: Check if there are existing storage layout artifacts
echo "Checking for storage layout artifacts..."
fd -g "*storage*layout*.json"

# Test 3: Look for upgrade references
echo "Looking for upgrade patterns..."
rg "function upgrade" -A 5
rg "function implementation" -A 5

Length of output: 711


Script:

#!/bin/bash
# Let's try a different approach to analyze storage layout concerns

# Check for storage inheritance hierarchy
echo "Checking storage inheritance..."
ast-grep --pattern 'contract ClientChainGatewayStorage is $$$'

# Look for storage slots and variables in parent contracts
echo "Checking BootstrapStorage..."
rg -A 20 "contract BootstrapStorage"

# Check for storage gaps
echo "Looking for storage gaps..."
rg "__gap" -B 5 -A 5

# Check for upgrade related contracts/interfaces
echo "Checking for upgrade patterns..."
rg -l "Upgradeable|UUPS|Proxy|Beacon"

Length of output: 11061

script/13_DepositValidator.s.sol (1)

83-83: ⚠️ Potential issue

Critical operation requires proper error handling and validation.

The current implementation has several concerns:

  1. The removal of error handling makes the script less robust for this critical operation
  2. The nativeFee value is used without validation
  3. As a must-succeed operation for validator deposits, failure handling is essential

Apply this diff to add proper error handling and validation:

+        require(nativeFee > 0, "Invalid native fee");
+        try clientGateway.verifyAndDepositNativeStake{value: nativeFee}(validatorContainer, validatorProof) {
+            console.log("Validator deposit successful");
+        } catch Error(string memory reason) {
+            console.log("Validator deposit failed:", reason);
+            revert("Validator deposit failed - must succeed operation");
+        } catch (bytes memory /*lowLevelData*/) {
+            console.log("Validator deposit failed with low-level error");
+            revert("Validator deposit failed - must succeed operation");
+        }
-        clientGateway.verifyAndDepositNativeStake{value: nativeFee}(validatorContainer, validatorProof);

Let's verify the implementation of verifyAndDepositNativeStake to ensure our error handling aligns with the contract's expectations:

src/core/ClientChainGateway.sol (1)

47-49: LGTM! Verify ImmutableConfig validation.

The refactoring to use ImmutableConfig improves code organization. However, we should verify that the struct parameters are properly validated.

Let's check the validation in the base contracts:

✅ Verification successful

ImmutableConfig parameters are properly validated

The validation is implemented in BootstrapStorage.sol with proper zero-address checks for all config parameters:

require(!(
    config.exocoreChainId == 0 || 
    config.beaconOracleAddress == address(0) || 
    config.vaultBeacon == address(0) ||
    config.exoCapsuleBeacon == address(0) || 
    config.beaconProxyBytecode == address(0)
), "Bootstrap: invalid config");
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for ImmutableConfig validation in base contracts
rg -A 10 "ImmutableConfig.*{" 

Length of output: 131


Script:

#!/bin/bash
# Search for ImmutableConfig struct definition and usage
rg -A 5 "struct ImmutableConfig"

# Search for validation of ImmutableConfig parameters
rg -A 10 "function.*ImmutableConfig.*memory.*config"

Length of output: 484


Script:

#!/bin/bash
# Search for ClientChainGatewayStorage constructor and initialization
rg -A 10 "contract ClientChainGatewayStorage"

# Search for any validation or require statements related to config parameters
rg -A 3 "require\(.*config\." 
rg -A 3 "if.*config\." 

# Search for usage of these config parameters
rg "beaconOracleAddress|vaultBeacon|exoCapsuleBeacon|beaconProxyBytecode"

Length of output: 15396

src/storage/BootstrapStorage.sol (4)

275-284: LGTM! Well-structured events with proper indexing.

The new events are well-designed with:

  • Clear naming that reflects their purpose
  • Proper use of indexing for efficient filtering
  • Comprehensive documentation

301-315: LGTM! Well-structured configuration struct.

The ImmutableConfig struct is a good solution that:

  • Avoids "stack too deep" errors in the constructor
  • Improves code organization
  • Has comprehensive documentation for each field

320-326: LGTM! Well-implemented modifier.

The nativeRestakingEnabled modifier properly checks if native restaking is enabled through the whitelist mechanism.


378-386: LGTM! Consistent internal helper function.

The _getCapsule function follows the same pattern as _getVault:

  • Proper error handling for non-existent capsules
  • Consistent with the codebase's style
  • Well-documented
test/foundry/DepositWithdrawPrinciple.t.sol (2)

30-31: LGTM: Well-structured event declarations.

The events are properly defined with indexed parameters, following Solidity best practices and providing clear tracking for capsule creation and staking operations.


Line range hint 304-336: LGTM: Native deposit test updated correctly.

The test has been properly updated to use the new verifyAndDepositNativeStake function name, maintaining test coverage for the native staking functionality.

src/core/Bootstrap.sol (3)

Line range hint 9-32: Imports and Inheritance Updated for Native Restaking Support

The added imports and inheritance correctly integrate INativeRestakingController, IExoCapsule, BeaconChainProofs, and BootstrapLzReceiver to support Ethereum native restaking functionality.


52-56: Constructor Updated with Immutable Configuration

The constructor now accepts an ImmutableConfig struct and properly initializes the base contracts OAppCoreUpgradeable and BootstrapStorage with the provided parameters.


800-812: Access Control in withdrawNonBeaconChainETHFromCapsule

Ensure that the withdrawNonBeaconChainETHFromCapsule function properly restricts withdrawals to authorized users to prevent unauthorized access to funds.

Run the following script to verify access control:

src/storage/BootstrapStorage.sol Show resolved Hide resolved
src/core/Bootstrap.sol Show resolved Hide resolved
src/core/Bootstrap.sol Show resolved Hide resolved
Copy link

Storage layout compatibility check failed. This could be due to a mismatch between Bootstrap and ClientChainGateway, or incompatibility with deployed contracts on Sepolia. Please check the logs for details.

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 looks good.

@adu-web3
Copy link
Collaborator Author

adu-web3 commented Nov 1, 2024

This PR would lead to failure of upgrading the current ClientChainGateway, since it has changed some state slots(#121 (comment)). @cloud8little do you think this is acceptable? If acceptable, I would disable the compare-storage-layout job to make this PR able to merge

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (1)
src/storage/BootstrapStorage.sol (1)

353-360: Constructor validation logic can be refined

While the validation checks are comprehensive, consider separating zero address checks and the chain ID check for more precise error handling. This can improve clarity on which parameter caused the failure.

Apply this diff to refine the validation logic:

 constructor(ImmutableConfig memory config) {
-    if (
-        config.exocoreChainId == 0 || config.beaconOracleAddress == address(0) || config.vaultBeacon == address(0)
-            || config.exoCapsuleBeacon == address(0) || config.beaconProxyBytecode == address(0)
-    ) {
-        revert Errors.InvalidImmutableConfig();
-    }
+    if (config.exocoreChainId == 0) {
+        revert Errors.InvalidExocoreChainId();
+    }
+    if (
+        config.beaconOracleAddress == address(0) ||
+        config.vaultBeacon == address(0) ||
+        config.exoCapsuleBeacon == address(0) ||
+        config.beaconProxyBytecode == address(0)
+    ) {
+        revert Errors.ZeroAddress();
+    }

This change provides more specific error messages, helping users identify configuration issues more easily.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between cc4f3cf and 2a5480c.

📒 Files selected for processing (1)
  • src/storage/BootstrapStorage.sol (7 hunks)
🔇 Additional comments (10)
src/storage/BootstrapStorage.sol (10)

6-7: Imports are properly added for new interfaces

The added imports for IETHPOSDeposit and IExoCapsule correctly bring in the necessary interfaces for the new functionalities.


133-135: Immutable ExoCapsule Beacon is correctly declared

The declaration of the immutable EXO_CAPSULE_BEACON variable ensures that the ExoCapsule implementation remains consistent throughout the contract's lifecycle.


136-138: Immutable Beacon Oracle Address is correctly declared

The BEACON_ORACLE_ADDRESS is properly set as an immutable variable, which aligns with its intended unchangeable nature.


142-144: ETH_POS deposit contract address is accurately defined

The ETH_POS constant is correctly set to the official ETH2.0 deposit contract address.


167-170: Storage gap is appropriately defined for future upgrades

Defining the storage gap after existing variables helps maintain storage layout compatibility and allows for future contract upgrades.


171-176: Mapping ownerToCapsule is correctly moved and declared

The ownerToCapsule mapping has been moved appropriately to maintain storage layout compatibility. Including parameter names enhances readability, which is preferred in this codebase.


281-291: Events for native restaking are well-defined and indexed

The CapsuleCreated and StakedWithCapsule events are correctly defined with indexed parameters, facilitating efficient event filtering and log queries.


307-322: ImmutableConfig struct enhances constructor parameter management

Introducing the ImmutableConfig struct simplifies the constructor and avoids the stack too deep error. This approach improves code maintainability and clarity.


323-329: nativeRestakingEnabled modifier is correctly implemented

The modifier properly checks if native restaking is enabled by verifying the whitelisting of VIRTUAL_NST_ADDRESS. The revert uses an appropriate custom error.


381-390: _getCapsule function is properly implemented

The internal function _getCapsule correctly retrieves the ExoCapsule for a given owner and handles the case where it does not exist by reverting with an appropriate error.

@adu-web3 adu-web3 added this pull request to the merge queue Nov 4, 2024
Merged via the queue into main with commit 46f9927 Nov 4, 2024
7 checks passed
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.

3 participants