Assessment reports>IBC Eureka>Threat Model>Component: cs-ics08-wasm-eth

Component: cs-ics08-wasm-eth

Description

This is the CosmWasm implementation that can be used with ibc-go's 08-wasm light-client wrapper. It handles the client and consensus state and calls into packages/ethereum-light-client for all the light-client--related logic.

The packages/ethereum-light-client performs stateless verification. It contains all the core logic for verifying Ethereum consensus, proving state — verifying (non)membership — and the headers submitted to update the light client. The state is handled by the CosmWasm code.

The contract has three entry points:

  1. instantiate — This initializes the initial client_state and the consensus state.

  2. sudo — The sudo entry point could only be called via the trusted modules and are used for verification of membership/misbehavior and updating the state.

  3. query — This is used to query the state.

The packages/ethereum-light-client performs the following verifications:

  1. verify_membership, which is used to verify the membership of a key in the storage.

  2. verify_misbehaviour, which verifies if a consensus misbehavior is valid by checking if the two conflicting light-client updates are valid.

  3. verify_header, which verifies the header of the light client.

Invariants

  • During the SudoMsg::UpdateState message, the update_consensus_state function must be invoked with the current client state, current consensus state, and a new header, resulting in the updated consensus state being stored and, if required, the updated client state being stored as well.

  • The SudoMsg::UpdateStateOnMisbehaviour message should set the is_frozen variable to true in the ETH client state.

  • The SudoMsg::VerifyMembership should verify the membership proof at the given consensus height and the current client state. And the SudoMsg::VerifyNonMembership should perform similar actions but for nonmembership proofs.

  • The QueryMsg::VerifyClientMessage message should correctly verify the header that will be used for updating the state of the light client. The verification of the header is done in ethereum_light_client::verify::verify_header, which must verify the account_proof and that the update has been signed by at least two thirds of the sync committee. In the case the type of the client_message is of EthereumMisbehaviourMsg, it should verify the misbehavior via ethereum_light_client::misbehaviour::verify_misbehaviour.

  • The QueryMsg::CheckForMisbehaviour should return true if the provided client_message corresponds to two conflicting headers.

  • The validate_light_client_update function must perform the verification of the update as per the consensus specification.

  • The update_consensus_state should also update the consensus state as per the consensus specification.

Test coverage

Cases covered

  • Membership verification is working as expected.

  • Header verification is working as expected.

  • Updating consensus states via update_consensus_state returns the expected updated_slot, new_consensus_state, and new_client_state.

Cases not covered

  • Unit tests for misbehavior verification.

Attack surface

The ibc-go first performs the verification via the query message and then updates the states via the sudo message. It is crucial for the verification logic to be similar to the specification mentioned in the sync protocol docs. Any deviation from the proposed specification might lead to critical issues in the verification process. We verified the implementation against the specification and found several instances where the implementation did not follow the specification:

  • Finding ref: Merkle verification could be bypassed.

  • Finding ref: Attested header is stored instead of finalized header.

There were a few instances where the provided user input was used as trusted states, which might lead to issues as the user input is untrusted. The issue is discussed in detail in Finding ref.

Zellic © 2025Back to top ↑