Eco Foundation

Eco PR 347

Cantina Security Report

Organization

@Eco-Inc

Engagement Type

Cantina Reviews

Period

-


Findings

Informational

5 findings

4 fixed

1 acknowledged


Informational5 findings

  1. No 0-checks on incoming message

    State

    Fixed

    PR #348

    Severity

    Severity: Informational

    Submitted by

    Rikard Hjort


    Description

    The existing provers perform 0-checks on incoming data from the bridges to catch blatant errors.

    For example, in handle() in HyperProver and MetaProver

    // Verify origin and sender are validif (origin == 0) revert ZeroDomainID();
    // Validate sender is not zeroif (sender == bytes32(0)) revert SenderCannotBeZeroAddress();

    ... and lzReceive() in LayerZeroProver:

    if (origin.sender == bytes32(0)) {    revert SenderCannotBeZeroAddress();}

    However, CCIPProver performs no such checks in ccipReceive.

    Recommendation

    For consistency, check for senderAddress == address(0) and message.sourceChainSelector == 0, and possibly also messageId == bytes32(0) in ccipReceive().

  2. Prover accepts too-large proof batch sizes

    State

    Acknowledged

    Severity

    Severity: Informational

    Submitted by

    Rikard Hjort


    Description

    The encodedProofs bytes array can be arbitrarily large. CCIP has a documented max data size (30 KB) and per‑lane execution gas ceilings. Currently, the Eco protocol relies on the prover to revert on too-large proof batches. With current router implementations, it would revert on the fee request:

    https://sepolia.etherscan.io/address/0x12492154714fBD28F28219f6fc4315d19de1025B#code:

    if (dataLength > maxDataBytes) revert MessageTooLarge(maxDataBytes, dataLength);

    Recommendation

    Best practice would be to pre‑check data sizes and reject oversized batches with a clear error.

    Status

    The limit has been documented and it's on callers to make sure they respect the limit, or face reverts.

  3. The sender of proofs must ensure that the allowOutOfOrderExecution flag respects chain restrictions

    State

    Fixed

    PR #351

    Severity

    Severity: Informational

    Submitted by

    Rikard Hjort


    Description

    According to the CCIP documentation:

    • Default value for allowOutOfOrderExecution varies by chain
    • Some chains enforce specific values and will revert if not set correctly

    It is on the caller of prove() to check that this is set correctly. Not all chains may guarantee that it can serve transactions in order. If the caller elects to try to enforce in-order execution, the EVM2EVMOnRamp contract, called by the router, may throw ExtraArgOutOfOrderExecutionMustBeTrue().

    Recommendation

    Document prominently.

    Alternatively, set allowOutOfOrderExecution to a static true value. This is more permissive, and does not revert on any chain according to official documentation. This could cause problems if fulfilled intents e.g. have non-standard behavior at the address that is being withdrawn to (e.g. the withdrawal is to a contract, and that contract expects a certain order of intent fulfilments).

  4. The provided gasLimit is not checked against MIN_GAS_LIMIT

    State

    Fixed

    PR #352

    Severity

    Severity: Informational

    Submitted by

    Rikard Hjort


    Description

    The caller of prove() on the Portal can set any gas limit they want for the CCIP call. However, like in LayerZeroProver, it should be checked that it is at least as large as MIN_GAS_LIMIT.

  5. Missing documentation for the new CCIP prover in various NatSpecs

    State

    Fixed

    PR #353

    Severity

    Severity: Informational

    Submitted by

    Rikard Hjort


    Summary

    There are NatSpec comments explaining the various schemes of chainId used for different provers, listing all (currently) available provers in Inbox.sol and IProver.sol. CCIPProver should be added to these lists.

    * @dev WARNING: sourceChainDomainID is NOT necessarily the same as chain ID.*      Each bridge provider uses their own domain ID mapping system:*      - Hyperlane: Uses custom domain IDs that may differ from chain IDs*      - LayerZero: Uses endpoint IDs that map to chains differently*      - Metalayer: Uses domain IDs specific to their routing system*      - Polymer: Uses chain IDs*      You MUST consult the specific bridge provider's documentation to determine*      the correct domain ID for the source chain.*/