Skip to content

Conversation

@s2imonovic
Copy link
Collaborator

@s2imonovic s2imonovic commented Oct 22, 2025

Summary by CodeRabbit

Release Notes

  • New Features

    • Per-transaction action fees: additional actions beyond the first incur a configurable fee
    • Enhanced deposit and call functionality with direct amount parameters for ETH and ERC20 assets
    • New administrative control to update additional action fees
  • Chores

    • Updated EVM version to support latest protocol features

@s2imonovic s2imonovic requested review from a team as code owners October 22, 2025 12:07
@github-actions github-actions bot added the feat label Oct 22, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 22, 2025

📝 Walkthrough

Walkthrough

A per-transaction fee mechanism is introduced for cross-chain actions in EVM gateways. The first action in a transaction is free; subsequent actions incur a configurable fee transferred to the TSS address. Multiple deposit and depositAndCall function overloads are added to support amount-based ETH and ERC20 transfers with integrated fee validation. Interface definitions are updated with new events and custom errors, and the EVM version is upgraded to cancun.

Changes

Cohort / File(s) Summary
Fee Mechanism Core Implementation
contracts/evm/GatewayEVM.sol, test/utils/upgrades/GatewayEVMUpgradeTest.sol
Added public state variable additionalActionFeeWei and external function updateAdditionalActionFee() for fee configuration. Implemented internal fee processing via _processFee(), with transient storage key _TRANSACTION_ACTION_COUNT_KEY to track action index per transaction. Added validation helpers _validateChargedFeeForERC20() and _validateChargedFeeForETHWithAmount(). Multiple new/overloaded deposit and depositAndCall signatures now support amount parameters and fee enforcement; call function updated for fee processing.
Interface and Event Definitions
contracts/evm/interfaces/IGatewayEVM.sol
Added events UpdatedAdditionalActionFee and UpdatedGatewayTSSAddress. Expanded error definitions: FeeTransferFailed, InsufficientFee, ExcessETHProvided, AdditionalActionDisabled, IncorrectValueProvided. Updated and added multiple function signatures to IGatewayEVM: deposit variants with amount and asset parameters, depositAndCall overloads, and call function, all marked external payable.
Build Configuration
foundry.toml, hardhat.config.ts
EVM version upgraded from "london" to "cancun" in both Foundry and Hardhat configs.
Test Coverage
test/GatewayEVM.t.sol
Added public constant ADDITIONAL_ACTION_FEE_WEI = 2e5 and increased ownerAmount to 10_000 ether. Comprehensive test suite added covering fee enforcement on second actions, ETH and ERC20 deposit flows, payload size validation, zero-address checks, fee update authorization, disabled fee scenario, and edge cases across single and multi-action transactions.

Sequence Diagram

sequenceDiagram
    actor User
    participant Gateway as GatewayEVM
    participant Storage as Transient Storage
    participant TSS as TSS Address
    
    rect rgb(240, 248, 255)
    Note over User,TSS: Multi-Action Transaction
    end
    
    rect rgb(200, 220, 240)
    Note over Gateway,Storage: Action 1 (First Action - Free)
    User->>Gateway: deposit/call (action 1)
    Gateway->>Storage: _getNextActionIndex() → index=0
    Storage-->>Gateway: return 0, increment to 1
    Gateway->>Gateway: _processFee() → first action free
    end
    
    rect rgb(220, 240, 200)
    Note over Gateway,Storage: Action 2+ (Subsequent Actions - Fee Required)
    User->>Gateway: deposit/call (action 2, with ETH fee)
    Gateway->>Storage: _getNextActionIndex() → index=1
    Storage-->>Gateway: return 1, increment to 2
    Gateway->>Gateway: _processFee() checks:<br/>- additionalActionFeeWei > 0?<br/>- msg.value >= fee?
    Gateway->>Gateway: _validate...Fee() verifies amount
    Gateway->>TSS: transfer(additionalActionFeeWei)
    TSS-->>Gateway: ✓ fee received
    end
    
    rect rgb(255, 230, 200)
    Note over Gateway: Disabled Fee Scenario
    Gateway->>Gateway: if additionalActionFeeWei == 0<br/>→ revert AdditionalActionDisabled()
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

The changes involve multiple interconnected components: transient storage usage for action tracking, per-transaction fee state management, multiple fee validation and transfer paths for ETH and ERC20 assets, and numerous overloaded function signatures requiring careful review of parameter handling and backwards compatibility. The logic is distributed across core implementation, interfaces, and comprehensive test coverage, requiring separate reasoning for ETH vs. ERC20 flows and fee edge cases.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The pull request title "feat: multiple evm calls in single tx" directly and accurately summarizes the primary feature being introduced. The changeset implements a per-transaction fee mechanism that enables multiple actions (deposits, calls, and deposit-and-call combinations) to be executed within a single transaction, with the first action free and subsequent actions charged a fee. The title clearly conveys this core capability from the developer's perspective without being vague or misleading. While the fee mechanism is an implementation detail enabling this feature, the title appropriately focuses on the user-facing capability (multiple calls) rather than the internal mechanism, which is appropriate for concise PR titles.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/multiple-evm-calls

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

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

🧹 Nitpick comments (13)
contracts/zevm/interfaces/UniversalContract.sol (1)

4-7: Remove unused imports (or reference them) to avoid warnings.

IWZETA and IZRC20 are imported but unused here. Drop them unless needed.

-import "../interfaces/IWZETA.sol";
-import "../interfaces/IZRC20.sol";
test/GatewayEVM.t.sol (1)

457-508: Strong coverage; add two small scenarios to close gaps.

  • Add “transaction boundary” test: perform second action with fee, then start a new tx and ensure index resets (first action free again).
  • Add “third action” test: perform three actions in one tx and assert fees charged exactly twice (actions 2 and 3).

I can draft both tests if helpful.

Also applies to: 611-661, 762-819, 851-996, 997-1034, 1036-1169, 1171-1190, 1192-1250, 1252-1273

test/utils/upgrades/GatewayEVMUpgradeTest.sol (2)

59-63: Use a namespaced bytes32 key for transient storage to avoid future collisions.

A literal 0x01 can collide across upgrades/merges. Prefer a hashed, self‑documented slot.

-uint256 private constant _TRANSACTION_ACTION_COUNT_KEY = 0x01;
+bytes32 private constant _TRANSACTION_ACTION_COUNT_KEY =
+    keccak256("zeta.gatewayEVM.txActionCount.v1");
...
 function _getNextActionIndex() internal returns (uint256 currentIndex) {
     assembly {
-        // Load current count from transient storage
-        currentIndex := tload(_TRANSACTION_ACTION_COUNT_KEY)
-        // Increment and store back to transient storage
-        tstore(_TRANSACTION_ACTION_COUNT_KEY, add(currentIndex, 1))
+        currentIndex := tload(_TRANSACTION_ACTION_COUNT_KEY)
+        tstore(_TRANSACTION_ACTION_COUNT_KEY, add(currentIndex, 1))
     }
 }

Also applies to: 633-644


579-611: Optional: validate before fee transfer for clearer CEI flow.

Semantics are correct (reverts unwind), but moving validations ahead of the transfer clarifies intent.

-        // Subsequent actions require fee payment
-        feeCharged = additionalActionFeeWei;
-        if (msg.value < feeCharged) {
-            revert InsufficientFee(feeCharged, msg.value);
-        }
-
-        // Transfer fee to TSS address
+        // Subsequent actions require exact/adequate fee
+        feeCharged = additionalActionFeeWei;
+        if (msg.value < feeCharged) revert InsufficientFee(feeCharged, msg.value);
+        // Transfer fee to TSS address
         (bool success,) = tssAddress.call{ value: feeCharged }("");
         if (!success) {
             revert FeeTransferFailed();
         }

Also applies to: 615-631

contracts/evm/interfaces/IGatewayEVM.sol (6)

116-137: Error set looks good; minor doc/naming nits only.

The new custom errors cover all fee/ETH-mismatch paths. Consider clarifying in NatSpec that AdditionalActionDisabled is triggered when fee is 0 and actionIndex > 0, and that ExcessETHProvided/IncorrectValueProvided are used in ERC20 and ETH-with-amount contexts respectively.


205-210: Document msg.value semantics for ETH-with-amount deposit.

Add a NatSpec note: “msg.value must equal amount for the first action; for subsequent actions it must equal amount + additionalActionFeeWei.”

Please confirm the implementation in GatewayEVM.deposit(receiver, amount, revertOptions) enforces this invariant (it currently does via _processFee + _validateChargedFeeForETHWithAmount).


222-224: Clarify payable usage for ERC20 deposit.

Add a NatSpec note: “For first action, msg.value must be 0; for subsequent actions, msg.value must equal additionalActionFeeWei (fee only).”


237-250: Clarify msg.value rules for ETH depositAndCall with amount.

Same as deposit with amount: “msg.value == amount on first action; == amount + fee on subsequent.”


264-266: Clarify payable usage for ERC20 depositAndCall.

Document that msg.value is fee-only (0 for first action, fee for subsequent).


271-278: call(...) now payable: document zero-ETH first action rule.

Add NatSpec: “No asset transfer. msg.value must be 0 on the first action; equals fee on subsequent.”

contracts/evm/GatewayEVM.sol (3)

55-59: Cancun/EIP‑1153 dependency and transient slot hygiene.

  • Using tload/tstore ties this to Cancun-enabled chains. Confirm deployment networks have EIP‑1153 active in toolchain/runtime.
  • Slot 0x01 works but is fragile for future transient usage. Consider a unique slot like bytes32(uint256(keccak256("zeta.gateway.tx.action.count"))) to avoid accidental collisions in future refactors.

Also applies to: 639-649


585-616: Fee processing logic is clear; consider pulling fee-to-TSS into a small internal “_transferETHToTSS” helper.

Improves reuse and makes applying a reentrancy guard decision obvious in one place. Optional.


618-626: Doc/code mismatch: enforce equality for ERC20 fee payment.

NatSpec says msg.value equals required fee, but code only rejects the “greater than” case (underpayment is caught in _processFee). Make the invariant explicit for maintainability.

Apply this diff:

 function _validateChargedFeeForERC20(uint256 feeCharged) internal view {
-    // For ERC20 operations, msg.value must equal the required fee
-    if (msg.value > feeCharged) {
-        revert ExcessETHProvided(feeCharged, msg.value);
-    }
+    // For ERC20 operations, msg.value must equal the required fee (0 on first action)
+    if (msg.value != feeCharged) {
+        if (msg.value > feeCharged) revert ExcessETHProvided(feeCharged, msg.value);
+        revert IncorrectValueProvided(feeCharged, msg.value);
+    }
 }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 51631dc and 81291c9.

📒 Files selected for processing (9)
  • contracts/Revert.sol (1 hunks)
  • contracts/evm/GatewayEVM.sol (10 hunks)
  • contracts/evm/interfaces/IGatewayEVM.sol (6 hunks)
  • contracts/zevm/interfaces/UniversalContract.sol (1 hunks)
  • foundry.toml (1 hunks)
  • hardhat.config.ts (1 hunks)
  • test/GatewayEVM.t.sol (5 hunks)
  • test/utils/TestUniversalContract.sol (1 hunks)
  • test/utils/upgrades/GatewayEVMUpgradeTest.sol (10 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
test/**

⚙️ CodeRabbit configuration file

Review the test files for proper coverage, edge cases, and best practices.

Files:

  • test/utils/TestUniversalContract.sol
  • test/GatewayEVM.t.sol
  • test/utils/upgrades/GatewayEVMUpgradeTest.sol
contracts/**

⚙️ CodeRabbit configuration file

Review the Solidity contracts for security vulnerabilities and best practices.

Files:

  • contracts/zevm/interfaces/UniversalContract.sol
  • contracts/evm/interfaces/IGatewayEVM.sol
  • contracts/Revert.sol
  • contracts/evm/GatewayEVM.sol
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: generate
  • GitHub Check: test
  • GitHub Check: slither
🔇 Additional comments (8)
foundry.toml (1)

26-26: Good alignment with transient storage.

Foundry set to evm_version="cancun" matches contract/tests using TSTORE/TLOAD.

test/utils/upgrades/GatewayEVMUpgradeTest.sol (1)

121-130: Event + access control LGTM.

Admin‑only fee update with event emission is sound; tests cover role constraints.

contracts/Revert.sol (1)

57-58: ****

The interface change to non-payable onRevert() is correct. Call sites in both GatewayEVM and GatewayZEVM follow the proper pattern: transfer value/tokens first, then invoke onRevert() without forwarding ETH. No refactoring needed.

test/utils/TestUniversalContract.sol (1)

53-55: Verification confirms signature is consistent across all implementations.

All onRevert implementations matching the Revertable interface are non-payable:

  • TestUniversalContract.sol:53 uses external override (correct)
  • ReceiverEVM.sol:72 uses external (correct)
  • Interface definition in Revert.sol:57 is non-payable
  • All call sites use non-payable calls (no value forwarding)

The legacy ZetaConnector variants implement a different interface with different parameters, so they are not relevant to this change.

contracts/evm/interfaces/IGatewayEVM.sol (1)

74-75: Event addition aligns with admin control of fee.

UpdatedAdditionalActionFee is appropriate and matches GatewayEVM.updateAdditionalActionFee emission. No issues.

contracts/evm/GatewayEVM.sol (3)

112-122: Admin setter is fine; emits event.

Implementation looks good. Consider emitting the event before updating state only if you prefer old/new in logs before mutation; current pattern (emit after assign with cached oldFee) is correct.


627-637: ETH-with-amount validation looks solid.

Exact equality check prevents dust retention and overpayment. LGTM.


41-45: Verify storage layout compatibility before deployment using forge inspect.

This is a new storage variable added to an upgradeable contract. While the placement appears correct (appended after existing state variables custody, tssAddress, zetaConnector, and zetaToken, before constants), you must verify the actual storage slot layout to ensure:

  1. No conflicts with any previously deployed versions
  2. No unintended overwrites of inherited storage gaps from OpenZeppelin base contracts
  3. Compatibility with the upgrade path

Follow the review comment's recommendation: run forge inspect contracts/evm/GatewayEVM.sol:GatewayEVM storage-layout and compare against the currently deployed implementation's layout.

Copy link
Member

@lumtis lumtis left a comment

Choose a reason for hiding this comment

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

Might be great to get a review from @skosito since he worked on this feature

Copy link
Contributor

@skosito skosito left a comment

Choose a reason for hiding this comment

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

approved but there are some changes that are not from original PR, please check before merging if these should be in separate PR so it is not missed in changelog

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
contracts/evm/interfaces/IGatewayEVM.sol (2)

219-226: Document the fee payment requirement for ERC20 deposits.

Making the ERC20 deposit function payable is a significant behavioral change. Users will need to send ETH (via msg.value) to cover potential additional action fees, even when depositing ERC20 tokens. This could be confusing without clear documentation.

Consider enhancing the function documentation:

     /// @notice Deposits ERC20 tokens to the custody or connector contract.
+    /// @dev If this is not the first action in the transaction, msg.value must include the additional action fee.
     /// @param receiver Address of the receiver.
     /// @param amount Amount of tokens to deposit.
     /// @param asset Address of the ERC20 token.
     /// @param revertOptions Revert options.
     function deposit(

260-268: Document the fee payment requirement for ERC20 depositAndCall.

Similar to the deposit function, this ERC20 depositAndCall is now payable to support fee payments. Consider adding documentation to clarify when ETH must be sent alongside ERC20 token approvals.

Apply similar documentation enhancement:

     /// @notice Deposits ERC20 tokens to the custody or connector contract and calls an omnichain smart contract.
+    /// @dev If this is not the first action in the transaction, msg.value must include the additional action fee.
     /// @param receiver Address of the receiver.
     /// @param amount Amount of tokens to deposit.
     /// @param asset Address of the ERC20 token.
     /// @param payload Calldata to pass to the call.
     /// @param revertOptions Revert options.
🧹 Nitpick comments (2)
contracts/evm/interfaces/IGatewayEVM.sol (2)

74-77: Add explanatory documentation for the additional action fee mechanism.

The past review comment requested additional documentation here. Consider expanding the NatSpec to explain what "additional action" means in this context (e.g., "subsequent actions after the first free action in a transaction").

Apply this diff to enhance the documentation:

-    /// @notice Emitted when additional action fee is updated.
-    /// @param oldFeeWei old fee value.
-    /// @param newFeeWei new fee value.
+    /// @notice Emitted when the additional action fee is updated.
+    /// @dev The first action in a transaction is free; subsequent actions incur this fee.
+    /// @param oldFeeWei Old fee value in wei.
+    /// @param newFeeWei New fee value in wei.
     event UpdatedAdditionalActionFee(uint256 oldFeeWei, uint256 newFeeWei);

274-280: Document the fee payment requirement for the call function.

The call function is now payable, likely to support the additional action fee mechanism. Consider documenting when msg.value must be provided.

Enhance the documentation:

     /// @notice Calls an omnichain smart contract without asset transfer.
+    /// @dev If this is not the first action in the transaction, msg.value must include the additional action fee.
     /// @param receiver Address of the receiver.
     /// @param payload Calldata to pass to the call.
     /// @param revertOptions Revert options.
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 81291c9 and bd96420.

⛔ Files ignored due to path filters (130)
  • docs/index.md is excluded by !docs/**
  • pkg/address.sol/address.go is excluded by !pkg/**
  • pkg/beaconproxy.sol/beaconproxy.go is excluded by !pkg/**
  • pkg/console.sol/console.go is excluded by !pkg/**
  • pkg/core.sol/core.go is excluded by !pkg/**
  • pkg/coreregistry.sol/coreregistry.go is excluded by !pkg/**
  • pkg/coreregistry.t.sol/coreregistrytest.go is excluded by !pkg/**
  • pkg/coreregistry.t.sol/mockgatewayzevm.go is excluded by !pkg/**
  • pkg/defender.sol/defender.go is excluded by !pkg/**
  • pkg/defenderdeploy.sol/defenderdeploy.go is excluded by !pkg/**
  • pkg/erc1967proxy.sol/erc1967proxy.go is excluded by !pkg/**
  • pkg/erc1967utils.sol/erc1967utils.go is excluded by !pkg/**
  • pkg/erc20custody.sol/erc20custody.go is excluded by !pkg/**
  • pkg/erc20custody.t.sol/erc20custodytest.go is excluded by !pkg/**
  • pkg/erc20custodyupgradetest.sol/erc20custodyupgradetest.go is excluded by !pkg/**
  • pkg/gatewayevm.sol/gatewayevm.go is excluded by !pkg/**
  • pkg/gatewayevm.t.sol/gatewayevminboundtest.go is excluded by !pkg/**
  • pkg/gatewayevm.t.sol/gatewayevmtest.go is excluded by !pkg/**
  • pkg/gatewayevmupgradetest.sol/gatewayevmupgradetest.go is excluded by !pkg/**
  • pkg/gatewayevmzevm.t.sol/gatewayevmzevmtest.go is excluded by !pkg/**
  • pkg/gatewayzevm.sol/gatewayzevm.go is excluded by !pkg/**
  • pkg/gatewayzevm.t.sol/gatewayzevminboundtest.go is excluded by !pkg/**
  • pkg/gatewayzevm.t.sol/gatewayzevmoutboundtest.go is excluded by !pkg/**
  • pkg/gatewayzevmupgradetest.sol/gatewayzevmupgradetest.go is excluded by !pkg/**
  • pkg/igatewayevm.sol/igatewayevm.go is excluded by !pkg/**
  • pkg/igatewayevm.sol/igatewayevmerrors.go is excluded by !pkg/**
  • pkg/igatewayevm.sol/igatewayevmevents.go is excluded by !pkg/**
  • pkg/math.sol/math.go is excluded by !pkg/**
  • pkg/mockerc20.sol/mockerc20.go is excluded by !pkg/**
  • pkg/mockerc721.sol/mockerc721.go is excluded by !pkg/**
  • pkg/nonreturnapprovaltoken.sol/nonreturnapprovaltoken.go is excluded by !pkg/**
  • pkg/proxyadmin.sol/proxyadmin.go is excluded by !pkg/**
  • pkg/receiverevm.sol/receiverevm.go is excluded by !pkg/**
  • pkg/registry.sol/registry.go is excluded by !pkg/**
  • pkg/registry.t.sol/mockgatewayevm.go is excluded by !pkg/**
  • pkg/registry.t.sol/registrytest.go is excluded by !pkg/**
  • pkg/revertonzeroapprovaltoken.sol/revertonzeroapprovaltoken.go is excluded by !pkg/**
  • pkg/safeconsole.sol/safeconsole.go is excluded by !pkg/**
  • pkg/safeerc20.sol/safeerc20.go is excluded by !pkg/**
  • pkg/senderzevm.sol/senderzevm.go is excluded by !pkg/**
  • pkg/signedmath.sol/signedmath.go is excluded by !pkg/**
  • pkg/src/strings.sol/strings.go is excluded by !pkg/**
  • pkg/stderror.sol/stderror.go is excluded by !pkg/**
  • pkg/stdjson.sol/stdjson.go is excluded by !pkg/**
  • pkg/stdmath.sol/stdmath.go is excluded by !pkg/**
  • pkg/stdstorage.sol/stdstorage.go is excluded by !pkg/**
  • pkg/stdstorage.sol/stdstoragesafe.go is excluded by !pkg/**
  • pkg/stdstyle.sol/stdstyle.go is excluded by !pkg/**
  • pkg/stdtoml.sol/stdtoml.go is excluded by !pkg/**
  • pkg/storageslot.sol/storageslot.go is excluded by !pkg/**
  • pkg/strings.sol/strings.go is excluded by !pkg/**
  • pkg/systemcontract.sol/systemcontract.go is excluded by !pkg/**
  • pkg/systemcontractmock.sol/systemcontractmock.go is excluded by !pkg/**
  • pkg/testerc20.sol/testerc20.go is excluded by !pkg/**
  • pkg/testuniversalcontract.sol/testuniversalcontract.go is excluded by !pkg/**
  • pkg/transparentupgradeableproxy.sol/transparentupgradeableproxy.go is excluded by !pkg/**
  • pkg/upgradeablebeacon.sol/upgradeablebeacon.go is excluded by !pkg/**
  • pkg/upgrades.sol/unsafeupgrades.go is excluded by !pkg/**
  • pkg/upgrades.sol/upgrades.go is excluded by !pkg/**
  • pkg/utils.sol/utils.go is excluded by !pkg/**
  • pkg/utils/wzeta.sol/weth9.go is excluded by !pkg/**
  • pkg/versions.sol/versions.go is excluded by !pkg/**
  • pkg/wzeta.sol/weth9.go is excluded by !pkg/**
  • pkg/wzeta.t.sol/wzetatest.go is excluded by !pkg/**
  • pkg/zeta.non-eth.sol/zetanoneth.go is excluded by !pkg/**
  • pkg/zetaconnector.base.sol/zetaconnectorbase.go is excluded by !pkg/**
  • pkg/zetaconnector.eth.sol/zetaconnectoreth.go is excluded by !pkg/**
  • pkg/zetaconnector.non-eth.sol/zetaconnectornoneth.go is excluded by !pkg/**
  • pkg/zetaconnectornative.sol/zetaconnectornative.go is excluded by !pkg/**
  • pkg/zetaconnectornative.t.sol/zetaconnectornativetest.go is excluded by !pkg/**
  • pkg/zetaconnectornativeupgradetest.sol/zetaconnectornativeupgradetest.go is excluded by !pkg/**
  • pkg/zetaconnectornonnative.sol/zetaconnectornonnative.go is excluded by !pkg/**
  • pkg/zetaconnectornonnative.t.sol/zetaconnectornonnativetest.go is excluded by !pkg/**
  • pkg/zetaconnectornonnativeupgradetest.sol/zetaconnectornonnativeupgradetest.go is excluded by !pkg/**
  • pkg/zetaconnectorzevm.sol/zetaconnectorzevm.go is excluded by !pkg/**
  • pkg/zetaeth.sol/zetaeth.go is excluded by !pkg/**
  • pkg/zetanoneth.sol/zetanoneth.go is excluded by !pkg/**
  • pkg/zrc20.sol/zrc20.go is excluded by !pkg/**
  • pkg/zrc20.t.sol/zrc20test.go is excluded by !pkg/**
  • types/GatewayEVM.ts is excluded by !types/**
  • types/GatewayEVMUpgradeTest.ts is excluded by !types/**
  • types/IGatewayEVM.sol/IGatewayEVM.ts is excluded by !types/**
  • types/IGatewayEVM.sol/IGatewayEVMEvents.ts is excluded by !types/**
  • types/factories/Address__factory.ts is excluded by !types/**
  • types/factories/BeaconProxy__factory.ts is excluded by !types/**
  • types/factories/CoreRegistry__factory.ts is excluded by !types/**
  • types/factories/ERC1967Proxy__factory.ts is excluded by !types/**
  • types/factories/ERC1967Utils__factory.ts is excluded by !types/**
  • types/factories/ERC20CustodyUpgradeTest__factory.ts is excluded by !types/**
  • types/factories/ERC20Custody__factory.ts is excluded by !types/**
  • types/factories/GatewayEVMUpgradeTest__factory.ts is excluded by !types/**
  • types/factories/GatewayEVM__factory.ts is excluded by !types/**
  • types/factories/GatewayZEVMUpgradeTest__factory.ts is excluded by !types/**
  • types/factories/GatewayZEVM__factory.ts is excluded by !types/**
  • types/factories/IGatewayEVM.sol/IGatewayEVMErrors__factory.ts is excluded by !types/**
  • types/factories/IGatewayEVM.sol/IGatewayEVMEvents__factory.ts is excluded by !types/**
  • types/factories/IGatewayEVM.sol/IGatewayEVM__factory.ts is excluded by !types/**
  • types/factories/Math__factory.ts is excluded by !types/**
  • types/factories/MockERC20__factory.ts is excluded by !types/**
  • types/factories/MockERC721__factory.ts is excluded by !types/**
  • types/factories/NonReturnApprovalToken__factory.ts is excluded by !types/**
  • types/factories/ProxyAdmin__factory.ts is excluded by !types/**
  • types/factories/ReceiverEVM__factory.ts is excluded by !types/**
  • types/factories/Registry__factory.ts is excluded by !types/**
  • types/factories/RevertOnZeroApprovalToken__factory.ts is excluded by !types/**
  • types/factories/SafeERC20__factory.ts is excluded by !types/**
  • types/factories/SenderZEVM__factory.ts is excluded by !types/**
  • types/factories/StdError.sol/StdError__factory.ts is excluded by !types/**
  • types/factories/StdStorage.sol/StdStorageSafe__factory.ts is excluded by !types/**
  • types/factories/Strings__factory.ts is excluded by !types/**
  • types/factories/SystemContract.sol/SystemContract__factory.ts is excluded by !types/**
  • types/factories/SystemContractMock.sol/SystemContractMock__factory.ts is excluded by !types/**
  • types/factories/TestERC20__factory.ts is excluded by !types/**
  • types/factories/TestUniversalContract__factory.ts is excluded by !types/**
  • types/factories/TransparentUpgradeableProxy.sol/TransparentUpgradeableProxy__factory.ts is excluded by !types/**
  • types/factories/UpgradeableBeacon__factory.ts is excluded by !types/**
  • types/factories/WZETA.sol/WETH9__factory.ts is excluded by !types/**
  • types/factories/ZRC20.sol/ZRC20__factory.ts is excluded by !types/**
  • types/factories/Zeta.non-eth.sol/ZetaNonEth__factory.ts is excluded by !types/**
  • types/factories/ZetaConnector.base.sol/ZetaConnectorBase__factory.ts is excluded by !types/**
  • types/factories/ZetaConnector.eth.sol/ZetaConnectorEth__factory.ts is excluded by !types/**
  • types/factories/ZetaConnector.non-eth.sol/ZetaConnectorNonEth__factory.ts is excluded by !types/**
  • types/factories/ZetaConnectorNativeUpgradeTest__factory.ts is excluded by !types/**
  • types/factories/ZetaConnectorNative__factory.ts is excluded by !types/**
  • types/factories/ZetaConnectorNonNativeUpgradeTest__factory.ts is excluded by !types/**
  • types/factories/ZetaConnectorNonNative__factory.ts is excluded by !types/**
  • types/factories/ZetaConnectorZEVM.sol/ZetaConnectorZEVM__factory.ts is excluded by !types/**
  • types/factories/ZetaEth__factory.ts is excluded by !types/**
  • types/factories/ZetaNonEth__factory.ts is excluded by !types/**
  • types/factories/utils/WZETA.sol/WETH9__factory.ts is excluded by !types/**
📒 Files selected for processing (2)
  • contracts/evm/interfaces/IGatewayEVM.sol (6 hunks)
  • foundry.toml (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • foundry.toml
🧰 Additional context used
📓 Path-based instructions (1)
contracts/**

⚙️ CodeRabbit configuration file

Review the Solidity contracts for security vulnerabilities and best practices.

Files:

  • contracts/evm/interfaces/IGatewayEVM.sol
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: generate
  • GitHub Check: semgrep/ci
  • GitHub Check: test
  • GitHub Check: slither
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (3)
contracts/evm/interfaces/IGatewayEVM.sol (3)

119-139: LGTM! Comprehensive error definitions.

The new custom errors are well-documented and provide detailed context with parameters for debugging fee-related issues. This follows Solidity best practices for gas-efficient error handling.


240-252: LGTM! Consistent with the new deposit pattern.

This overload follows the same pattern as the new deposit function with explicit amount. The documentation is clear and the signature is well-formatted.


208-212: Implementation correctly validates msg.value relationship.

The deposit(address receiver, uint256 amount, RevertOptions) function at lines 284-311 properly validates that msg.value equals amount + feeCharged. The validation function _validateChargedFeeForETHWithAmount (lines 631-635) enforces this with the check if (msg.value != expectedValue) revert IncorrectValueProvided(expectedValue, msg.value), providing clear error messages that show both expected and provided values. The documentation accurately reflects this requirement.

@s2imonovic s2imonovic merged commit 1ef5a5b into develop Oct 22, 2025
17 checks passed
@s2imonovic s2imonovic deleted the feat/multiple-evm-calls branch October 22, 2025 14:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants