Skip to content

Conversation

@s2imonovic
Copy link
Collaborator

@s2imonovic s2imonovic commented Oct 23, 2025

Merging release/v15 to main

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced cross-action fee mechanism: first action in a transaction remains free; subsequent actions incur an additional fee.
    • Added administrative function to configure per-action fees.
    • Expanded deposit and call functions with explicit amount parameters.
  • Chores

    • Updated EVM version to Cancun.
    • Renamed module and package for improved clarity.
    • Updated community links and documentation references.

@s2imonovic s2imonovic requested review from a team as code owners October 23, 2025 14:57
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 23, 2025

Important

Review skipped

Review was skipped as selected files did not have any reviewable changes.

💤 Files selected but had no reviewable changes (1)
  • test/GatewayEVM.t.sol
⛔ Files ignored due to path filters (2)
  • pkg/gatewayevm.t.sol/gatewayevminboundtest.go is excluded by !pkg/**
  • pkg/gatewayevm.t.sol/gatewayevmtest.go is excluded by !pkg/**

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

📝 Walkthrough

Walkthrough

This PR renames the module from protocol-contracts to protocol-contracts-evm, updates compiler settings from london to cancun EVM version, introduces a cross-action fee mechanism in GatewayEVM with per-transaction action counting, adds multiple deposit/call function overloads, and refactors gas fee handling in GatewayZEVM.

Changes

Cohort / File(s) Summary
Package & Module Rename
go.mod, package.json
Updated module path from protocol-contracts to protocol-contracts-evm and npm package name accordingly.
Compiler Configuration Updates
foundry.toml, hardhat.config.ts
Updated EVM version from london to cancun; foundry.toml added dependencies to libs path.
Documentation
README.md
Updated X (Twitter) community link from /zetablockchain to /zetachain.
Interface Updates
contracts/Revert.sol
Removed payable modifier from Revertable.onRevert() function signature.
UniversalContract Interface
contracts/zevm/interfaces/UniversalContract.sol
Added imports: AbortContext, RevertOptions from Revert.sol, and new interface imports for IWZETA and IZRC20.
ZetaConnectorNative References
contracts/evm/ZetaConnectorNative.sol
Updated URL references in documentation from protocol-contracts/issues/398 to protocol-contracts-evm/issues/398.
Gateway EVM Interface
contracts/evm/interfaces/IGatewayEVM.sol
Added new events (UpdatedGatewayTSSAddress, UpdatedAdditionalActionFee) and errors (FeeTransferFailed, InsufficientFee, ExcessETHProvided, AdditionalActionDisabled, IncorrectValueProvided); added/updated multiple deposit, depositAndCall, and call overloads to be payable.
Gateway EVM Implementation
contracts/evm/GatewayEVM.sol
Introduced cross-action fee mechanism with per-transaction action counter; added additionalActionFeeWei state variable, updateAdditionalActionFee() setter; added multiple deposit/depositAndCall/call overloads with fee validation via _processFee(), _validateChargedFeeForERC20(), and _validateChargedFeeForETHWithAmount() internal helpers.
Gateway ZEVM Implementation
contracts/zevm/GatewayZEVM.sol
Added private _burnProtocolFees() helper to centralize gas fee withdrawal, transfer, and burning; refactored _withdrawZRC20WithGasLimit() and call paths to use this helper.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant GatewayEVM
    participant TSS Address
    participant ZEVM

    User->>GatewayEVM: First deposit() in transaction
    note over GatewayEVM: _getNextActionIndex() = 1
    note over GatewayEVM: First action: NO FEE
    GatewayEVM->>ZEVM: Execute deposit (no fee charged)

    User->>GatewayEVM: Second call() in same transaction
    note over GatewayEVM: _getNextActionIndex() = 2
    note over GatewayEVM: Subsequent action: CHARGE FEE
    GatewayEVM->>GatewayEVM: _processFee() validates and deducts additionalActionFeeWei
    GatewayEVM->>TSS Address: Transfer fee
    GatewayEVM->>ZEVM: Execute call (fee charged)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Rationale: The GatewayEVM.sol changes introduce substantial new logic including a transient per-transaction action counter, cross-action fee mechanism with multiple validation paths, and five new function overloads with varying signatures. This requires careful review of fee calculations, validation order, and interaction with both ETH and ERC20 deposit paths. IGatewayEVM interface changes are correspondingly extensive. GatewayZEVM refactoring centralizes gas fee handling into a new helper. Multiple heterogeneous changes across configuration, package metadata, and contract logic files compound review complexity.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title Check ❓ Inconclusive The PR title "chore: release v15" is technically related to the changeset as this is indeed a release PR being merged to main, but it is highly generic and non-descriptive. The title uses vague language that does not convey meaningful information about what v15 contains, similar to terms like "misc updates" or "stuff." The changeset includes significant modifications such as a new cross-action fee mechanism, breaking API changes (removed payable modifier, new function overloads), module path updates, EVM version changes, and configuration updates, none of which are reflected in or summarized by the title. A teammate scanning commit history would have no clarity about the primary nature or scope of these changes based solely on this title. Consider making the title more specific by either summarizing the primary change (e.g., "feat: add cross-action fee mechanism and API updates for v15") or including a brief descriptor of the release scope. If a generic release title is intentional, ensure the PR description clearly lists major changes and breaking changes so reviewers understand the scope of v15.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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.

# Conflicts:
#	contracts/evm/interfaces/IGatewayEVM.sol
#	contracts/zevm/GatewayZEVM.sol
#	docs/index.md
#	pkg/coreregistry.sol/coreregistry.go
#	pkg/coreregistry.t.sol/coreregistrytest.go
#	pkg/coreregistry.t.sol/mockgatewayzevm.go
#	pkg/erc20custody.sol/erc20custody.go
#	pkg/erc20custody.t.sol/erc20custodytest.go
#	pkg/erc20custodyupgradetest.sol/erc20custodyupgradetest.go
#	pkg/gatewayevm.sol/gatewayevm.go
#	pkg/gatewayevm.t.sol/gatewayevminboundtest.go
#	pkg/gatewayevm.t.sol/gatewayevmtest.go
#	pkg/gatewayevmupgradetest.sol/gatewayevmupgradetest.go
#	pkg/gatewayevmzevm.t.sol/gatewayevmzevmtest.go
#	pkg/gatewayzevm.sol/gatewayzevm.go
#	pkg/gatewayzevm.t.sol/gatewayzevminboundtest.go
#	pkg/gatewayzevm.t.sol/gatewayzevmoutboundtest.go
#	pkg/gatewayzevmupgradetest.sol/gatewayzevmupgradetest.go
#	pkg/receiverevm.sol/receiverevm.go
#	pkg/registry.sol/registry.go
#	pkg/registry.t.sol/mockgatewayevm.go
#	pkg/registry.t.sol/registrytest.go
#	pkg/senderzevm.sol/senderzevm.go
#	pkg/systemcontract.sol/systemcontract.go
#	pkg/systemcontractmock.sol/systemcontractmock.go
#	pkg/testuniversalcontract.sol/testuniversalcontract.go
#	pkg/zetaconnector.base.sol/zetaconnectorbase.go
#	pkg/zetaconnector.eth.sol/zetaconnectoreth.go
#	pkg/zetaconnector.non-eth.sol/zetaconnectornoneth.go
#	pkg/zetaconnectornative.sol/zetaconnectornative.go
#	pkg/zetaconnectornative.t.sol/zetaconnectornativetest.go
#	pkg/zetaconnectornativeupgradetest.sol/zetaconnectornativeupgradetest.go
#	pkg/zetaconnectornonnative.sol/zetaconnectornonnative.go
#	pkg/zetaconnectornonnative.t.sol/zetaconnectornonnativetest.go
#	pkg/zetaconnectornonnativeupgradetest.sol/zetaconnectornonnativeupgradetest.go
#	pkg/zetaconnectorzevm.sol/zetaconnectorzevm.go
#	pkg/zrc20.sol/zrc20.go
#	pkg/zrc20.t.sol/zrc20test.go
#	types/factories/CoreRegistry__factory.ts
#	types/factories/ERC20CustodyUpgradeTest__factory.ts
#	types/factories/ERC20Custody__factory.ts
#	types/factories/GatewayEVMUpgradeTest__factory.ts
#	types/factories/GatewayEVM__factory.ts
#	types/factories/GatewayZEVMUpgradeTest__factory.ts
#	types/factories/GatewayZEVM__factory.ts
#	types/factories/ReceiverEVM__factory.ts
#	types/factories/Registry__factory.ts
#	types/factories/SenderZEVM__factory.ts
#	types/factories/SystemContract.sol/SystemContract__factory.ts
#	types/factories/SystemContractMock.sol/SystemContractMock__factory.ts
#	types/factories/TestUniversalContract__factory.ts
#	types/factories/ZRC20.sol/ZRC20__factory.ts
#	types/factories/ZetaConnector.base.sol/ZetaConnectorBase__factory.ts
#	types/factories/ZetaConnector.eth.sol/ZetaConnectorEth__factory.ts
#	types/factories/ZetaConnector.non-eth.sol/ZetaConnectorNonEth__factory.ts
#	types/factories/ZetaConnectorNativeUpgradeTest__factory.ts
#	types/factories/ZetaConnectorNative__factory.ts
#	types/factories/ZetaConnectorNonNativeUpgradeTest__factory.ts
#	types/factories/ZetaConnectorNonNative__factory.ts
#	types/factories/ZetaConnectorZEVM.sol/ZetaConnectorZEVM__factory.ts
@github-actions github-actions bot added the chore label Oct 23, 2025
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 (1)
contracts/evm/GatewayEVM.sol (1)

526-531: Use SafeERC20.forceApprove for connector allowance.

Raw approve may fail for non‑standard tokens; SafeERC20 handles zero‑first semantics.

-            // approve connector to handle tokens depending on connector version (eg. lock or burn)
-            if (!IERC20(token).approve(zetaConnector, amount)) revert ApprovalFailed();
+            // approve connector to handle tokens depending on connector version (eg. lock or burn)
+            IERC20(token).forceApprove(zetaConnector, 0);
+            IERC20(token).forceApprove(zetaConnector, amount);
🧹 Nitpick comments (21)
contracts/zevm/interfaces/UniversalContract.sol (1)

4-7: Trim unused imports and simplify paths

AbortContext, RevertOptions, IWZETA, and IZRC20 aren’t used here; drop them to reduce compile surface. Also prefer absolute "contracts/Revert.sol" or "../../Revert.sol" for clarity over "../../../contracts/...".

-import { AbortContext, RevertContext, RevertOptions } from "../../../contracts/Revert.sol";
+import { RevertContext } from "contracts/Revert.sol";
-import "../interfaces/IWZETA.sol";
-import "../interfaces/IZRC20.sol";
contracts/zevm/GatewayZEVM.sol (1)

373-373: call(): consider surfacing paid gas fee for observability

Helper burns fees but Called event carries no gasFee. Optional: emit a separate GasFeePaid(zrc20, payer, gasFee) to aid off-chain accounting without breaking ABI.

contracts/evm/GatewayEVM.sol (13)

55-59: Use a namespaced transient slot to avoid collisions.

_TRANSACTION_ACTION_COUNT_KEY = 0x01 is terse and risks future clashes. Prefer a namespaced keccak-based key.

-uint256 private constant _TRANSACTION_ACTION_COUNT_KEY = 0x01;
+bytes32 private constant _TRANSACTION_ACTION_COUNT_KEY =
+    bytes32(uint256(uint160(uint256(keccak256("zeta.gateway.tx_action_count.v1"))))));

And update assembly to use the bytes32-typed constant (no functional change).


112-121: Admin fee update looks good; add bounds/emit already present.

Optionally clamp to a sane upper bound to prevent misconfig by ops; otherwise LGTM.

- function updateAdditionalActionFee(uint256 newFeeWei) external onlyRole(DEFAULT_ADMIN_ROLE) {
+ function updateAdditionalActionFee(uint256 newFeeWei) external onlyRole(DEFAULT_ADMIN_ROLE) {
+     // Optional: cap to 2 ether to prevent fat‑finger; tune as needed
+     if (newFeeWei > 2 ether) revert();
      uint256 oldFee = additionalActionFeeWei;
      additionalActionFeeWei = newFeeWei;
      emit UpdatedAdditionalActionFee(oldFee, newFeeWei);
   }

258-270: Legacy ETH deposit: reentrancy hardening.

This transfers ETH to tssAddress via call. While TSS is trusted, adding nonReentrant is a cheap defense-in-depth.

-function deposit(address receiver, RevertOptions calldata revertOptions) external payable whenNotPaused {
+function deposit(address receiver, RevertOptions calldata revertOptions)
+    external
+    payable
+    whenNotPaused
+    nonReentrant
+{

279-306: ETH deposit with amount: add nonReentrant.

Same rationale as above; fee path sends ETH to TSS.

-    {
+    nonReentrant {

318-328: ERC20 deposit: payable for fee is fine; doc the exact msg.value rule.

Implementation enforces exact fee (0 for first action). Add NatSpec comment to guide integrators.

-    function deposit(
+    /// @dev msg.value must equal the required fee (0 for first action; `additionalActionFeeWei` otherwise).
+    function deposit(

338-360: Legacy depositAndCall: add nonReentrant.

Transfers ETH to TSS; mirror the hardening.

-    {
+    nonReentrant {

367-395: ETH depositAndCall with amount: add nonReentrant.

Fee transfer + deposit transfer happen here.

-    {
+    nonReentrant {

411-420: ERC20 depositAndCall: payable for fee is fine; doc msg.value rule.

Mirror deposit(…asset…) NatSpec for consistency.

-    function depositAndCall(
+    /// @dev msg.value must equal the required fee (0 for first action; `additionalActionFeeWei` otherwise).
+    function depositAndCall(

436-445: Call without assets: consider nonReentrant or restrict TSS fallback.

_processFee transfers ETH to tssAddress which could reenter via fallback. Low risk, but guarding aligns all feeed entrypoints.

-    {
+    nonReentrant {

502-502: TODO/link note.

Once ZETA is re-enabled, remove the TODO and ensure unit/integration tests cover ZETA paths. Until then, consider a require with a clear message in public surfaces to fail fast.


585-616: Fee processing logic: OK; add config validation guardrail.

Consider reverting if additionalActionFeeWei is absurdly high to avoid accidental lockouts.

-        if (additionalActionFeeWei == 0) {
+        if (additionalActionFeeWei == 0) {
             revert AdditionalActionDisabled();
         }
+        if (additionalActionFeeWei > 2 ether) revert(); // optional: safety cap

617-626: ERC20 fee validation: matches processFee semantics.

Minor: rename error to mention “fee” vs “ETH” for clarity in logs, or add a dedicated IncorrectFeeProvided error.


41-45: Storage layout is sound; add storage gap for future extensibility.

The new additionalActionFeeWei (uint256) correctly appends at storage slot 4 after the four address variables (slots 0-3). No collision risk exists for deployed proxies. However, as a best practice for upgradeable contracts, add a storage gap array to prevent future slot conflicts during upgrades:

uint256[49] private __gap;

This follows OpenZeppelin's pattern and reserves space for future state variable additions without breaking compatibility.

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

119-140: New errors cover fee/amount invariants.

LGTM. Consider aligning names with implementation messages (e.g., “IncorrectValueProvided”) across docs.


208-213: ETH deposit with amount: payable signature OK.

Add NatSpec that msg.value == amount + fee and that first action has fee 0.

-    /// @param revertOptions Revert options.
+    /// @param revertOptions Revert options.
+    /// @dev msg.value must equal `amount + requiredFee` (requiredFee is 0 for the first action).

225-227: ERC20 deposit now payable for fee: clarify NatSpec.

State that msg.value must equal the required fee (0 or additionalActionFeeWei).


240-253: ETH depositAndCall with amount: payable OK; doc equality rule.

Mirror the deposit doc note.


267-269: ERC20 depositAndCall: payable for fee is consistent.

Doc the msg.value rule for integrators.


274-281: call(...) now payable for fee: ergonomic but consider overloading ergonomics.

Overloaded methods plus payable can be error‑prone in clients (ethers.js typing). Consider unique names or explicit structs in the next major.

📜 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 dbd47a3 and a920f13.

⛔ Files ignored due to path filters (134)
  • 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/revert.sol/revertable.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/Revert.sol/Revertable.ts is excluded by !types/**
  • types/TestUniversalContract.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/Revert.sol/Revertable__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 (11)
  • README.md (1 hunks)
  • contracts/Revert.sol (1 hunks)
  • contracts/evm/GatewayEVM.sol (11 hunks)
  • contracts/evm/ZetaConnectorNative.sol (3 hunks)
  • contracts/evm/interfaces/IGatewayEVM.sol (6 hunks)
  • contracts/zevm/GatewayZEVM.sol (5 hunks)
  • contracts/zevm/interfaces/UniversalContract.sol (1 hunks)
  • foundry.toml (2 hunks)
  • go.mod (1 hunks)
  • hardhat.config.ts (1 hunks)
  • package.json (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
contracts/**

⚙️ CodeRabbit configuration file

Review the Solidity contracts for security vulnerabilities and best practices.

Files:

  • contracts/zevm/GatewayZEVM.sol
  • contracts/evm/ZetaConnectorNative.sol
  • contracts/Revert.sol
  • contracts/evm/GatewayEVM.sol
  • contracts/evm/interfaces/IGatewayEVM.sol
  • contracts/zevm/interfaces/UniversalContract.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). (4)
  • GitHub Check: test
  • GitHub Check: slither
  • GitHub Check: generate
  • GitHub Check: semgrep/ci
🔇 Additional comments (15)
README.md (1)

73-73: LGTM!

The X social media link has been correctly updated to reflect the consolidated handle.

contracts/evm/ZetaConnectorNative.sol (1)

31-31: LGTM!

The GitHub issue references have been consistently updated across all three locations to reflect the repository rename from protocol-contracts to protocol-contracts-evm.

Also applies to: 54-54, 83-83

contracts/zevm/GatewayZEVM.sol (4)

134-134: _withdrawZRC20WithGasLimit now uses helper

LGTM. Centralization reduces duplication and error surface.


283-283: Updated issue link

LGTM.


326-326: Updated issue link

LGTM.


105-120: Add reentrancy protection to user-facing fee-charging functions

The review comment is correct. External functions withdraw() (lines 160, 196), withdrawAndCall() (line 233), and call() (line 346) that invoke _burnProtocolFees() lack nonReentrant guards. Since _burnProtocolFees() makes external calls to potentially malicious ZRC20 implementations (withdrawGasFeeWithGasLimit, transferFrom, burn), these functions are vulnerable to reentrancy attacks.

Additionally, _burnProtocolFees() should validate gasFee > 0 to fail fast on misconfigured tokens rather than silently succeeding with zero fees.

Recommendation: Apply nonReentrant modifier to the four external functions listed above, and add a guard clause if (gasFee == 0) revert InvalidGasFee(); in _burnProtocolFees().

foundry.toml (1)

4-4: Foundry config changes verified—no conflicts detected

The libs addition and evm_version "cancun" are consistent. Verification confirms only one evm_version setting exists (foundry.toml:26), with no conflicting profiles. Both changes are aligned with Hardhat and the intended Cancun target.

contracts/Revert.sol (1)

57-57: onRevert signature change verified—no breaking changes

Change from payable to non-payable is security-positive and safe. Verification confirms:

  • No implementations use payable modifier
  • All callers pass onRevert as a zero-value external call; value transfers occur separately (before the onRevert call)
  • All existing implementations (TestUniversalContract, ReceiverEVM, ZetaConnectorZEVM, etc.) are already compatible

The hardening is effective with no updates needed.

hardhat.config.ts (1)

15-15: evmVersion "cancun" configuration verified

The Solidity compiler configuration in hardhat.config.ts is consistent and compatible. Etherscan and Sourcify both support contracts compiled with Cancun EVM version, and the project uses Solidity 0.8.26, which includes Cancun support (available since 0.8.24). No configuration conflicts detected.

package.json (1)

2-2: Package rename verified: no internal breaking references found

Comprehensive verification confirms no references to the old package name @zetachain/protocol-contracts exist in docs, imports, scripts, or configuration files. The rename to @zetachain/protocol-contracts-evm is clean within the codebase.

go.mod (1)

1-1: Module rename verified—no stale imports found

The rename from github.com/zeta-chain/protocol-contracts to github.com/zeta-chain/protocol-contracts-evm is complete and clean. Verification confirms:

  • No stale imports of the old path in any of the 168 Go source files
  • go.mod correctly reflects the new module path
  • go.sum dependencies are clean and valid
contracts/evm/GatewayEVM.sol (2)

627-636: ETH amount validation: succinct and correct.

LGTM.


638-649: The verification confirms that the project properly targets Cancun for both build systems:

  • Hardhat (hardhat.config.ts:15): evmVersion: "cancun"
  • Foundry (foundry.toml:26): evm_version = "cancun"

This validates that the tload/tstore transient storage operations in _getNextActionIndex() are fully supported and the assembly implementation is appropriate.

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

69-73: Event for TSS updates: good addition.

LGTM.


74-78: Event for fee updates: good operational signal.

LGTM.

@sherlock-ai-beta
Copy link

Sherlock AI Findings

The automated tool completed its analysis of the codebase and found no potential security issues.

Next Steps: No immediate actions are required. Continue monitoring the codebase with future scans.

Full report available at: https://ai.sherlock.xyz/runs/cf177078-b894-4132-bb7b-f9674d878ebf

@s2imonovic s2imonovic merged commit 98b6687 into main Oct 24, 2025
15 checks passed
@s2imonovic s2imonovic deleted the release/v15 branch October 24, 2025 13:14
@s2imonovic s2imonovic restored the release/v15 branch October 30, 2025 18:21
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.

6 participants