IBC in Solidity Full Actions Minimal Actions Foundry License: MIT Code Coverage

IBC in Solidity

This is an implementation of IBC v2 in Solidity and Solana. IBC v2 is a simplified version of the IBC protocol that is encoding agnostic. This enables a trust-minimized IBC connection between Ethereum and a Cosmos SDK chain.

Overview

solidity-ibc-eureka is an implementation of IBC in Solidity.

Project Structure

This project is structured as a foundry project with the following directories:

Solidity Contracts

Contracts Description Status
ICS26Router.sol IBC router handles sequencing, replay protection, and timeout checks. Passes proofs to light clients for verification, and resolves portId for app callbacks. Provable IBC storage is stored in this contract.
ICS20Transfer.sol IBC transfer application to send and receive tokens to/from another IBC transfer implementation.
SP1ICS07Tendermint.sol Tendermint light client powered by SP1. The entry point for SP1 proofs.
ICS27GMP.sol IBC General Message Passing via Interchain Accounts.
AttestationLightClient.sol The multisig contract implementing IBC Light Client specs.
utils/IFTBaseUpgradeable.sol Interchain Fungible Token standard. Mint and burn alternative to ICS-20.

SP1 Programs for the Light Client

Programs Description Status
update-client Once the initial client state and consensus state are submitted, future consensus states can be added to the client by submitting IBC Headers. These headers contain all necessary information to run the Comet BFT Light Client protocol. Also supports partial misbehavior check.
membership As consensus states are added to the client, they can be used for proof verification by relayers wishing to prove packet flow messages against a particular height on the counterparty. This uses the verify_membership and verify_non_membership methods on the tendermint client.
uc-and-membership This is a program that combines update-client and membership to update the client, and prove membership of packet flow messages against the new consensus state.
misbehaviour In case, the malicious subset of the validators exceeds the trust level of the client; then the client can be deceived into accepting invalid blocks and the connection is no longer secure. The tendermint client has some mitigations in place to prevent this.

Solana Programs

Programs Description Status
access-manager A central contract to store the permissions of a system.
attestation The multisig contract implementing IBC Light Client specs.
ics07-tendermint ICS-07 tendermint light client, powered by tendermint-rs
ics26-router IBC router handles sequencing, replay protection, and timeout checks. Passes proofs to light clients for verification, and resolves portId for app callbacks. Provable IBC storage is stored in this contract.
ics27-gmp IBC General Message Passing via Interchain Accounts.
ift Interchain Fungible Token standard. Mint and burn alternative to ICS-20.

Build Requirements

Ethereum Requirements

Foundry typically uses git submodules to manage contract dependencies, but this repository uses Node.js packages (via Bun) because submodules don't scale. You can install the contracts dependencies by running the following command:

bun install

You also need to have the operator and proof API binaries installed on your machine to run some of the end-to-end tests. You can install them by running the following commands:

just install-operator
just install-proof-api

[!TIP] Nix users can enter a development shell with all the necessary dependencies by running:

nix develop

Solana Requirements

If you have Anchor installed locally, you can use the standard commands:

just build-solana-programs
just test-solana

Or directly:

cd programs/solana
anchor build
anchor test
anchor deploy

[!TIP] Nix users can enter a solana development shell with all the necessary dependencies by running:

nix develop .#solana

Then navigate to the Solana programs directory and use anchor-nix commands:

cd programs/solana
anchor-nix build
anchor-nix test
anchor-nix deploy

Solana Programs

For detailed information about Solana IBC programs including deployment, key generation, access control, and upgradability, see the Solana Programs README.

Unit Testing

There are multiple unit tests for the solidity contracts located in the test/ directory. The tests are written in Solidity using foundry/forge.

To run all the tests, run the following command:

just test-foundry

The recipe also accepts a testname argument that will only run the test with the given name. For example:

just test-foundry test_success_sendTransfer

End to End Testing

There are several end-to-end tests in the e2e/interchaintestv8 directory. These tests are written in Go and use the interchaintest library. It spins up a local Ethereum and a Tendermint network and runs the tests found in e2e/interchaintestv8/ibc_eureka_test.go. Some of the tests use the prover network to generate the proofs, so you need to provide your SP1 network private key to .env for these tests to pass.

Requirements

To prepare for running the e2e tests, you need to make sure you have done the following:

[!NOTE] If you are running on a Mac with an M chip, you will need to do the following:

Running the tests

There are five test suites in the e2e/interchaintestv8 directory:

Development

You may need these additional tools to develop on this project:

Before committing, you should lint your code to ensure it follows the style guide. You can do this by running the following command:

just lint

End to End Benchmarks

The contracts in this repository are benchmarked end-to-end using foundry. The following benchmarks were ran with the underlying sp1-ics07-tendermint. About ~230,000 gas is used for each light client verification (groth16), and this is included in the gas costs below for recvPacket, timeoutPacket and ackPacket. At the time of writing, proof generation takes around 25 seconds. More granular and in-depth benchmarks are planned for the future.

Single Packet Benchmarks

The following benchmarks are for a single packet transfer without aggregation.

Contract Method Description Gas (groth16) Gas (plonk)
ICS26Router.sol sendPacket Initiating an IBC transfer with an ERC20. ~165,000 ~165,000
ICS26Router.sol recvPacket Receiving back an ERC20 token. ~524,474 ~608,862
ICS26Router.sol recvPacket Receiving a new Cosmos token for the first time. (Deploying an ERC20 contract) ~1,072,445 ~1,156,233
ICS26Router.sol ackPacket Acknowledging an ICS20 packet. ~399,576 ~483,375
ICS26Router.sol timeoutPacket Timing out an ICS20 packet ~473,505 ~556,640

Aggregated Packet Benchmarks

The gas costs are substantially lower when aggregating multiple packets into a single proof, as long as the packets are submitted in the same tx. Since there is no meaningful difference in gas costs between plonk and groth16 in the aggregated case, they are not separated in the table below.

ICS26Router Method Description Avg Gas (25 packets) Avg Gas (50 packets) Calldata size (25 packets) Calldata size (50 packets)
multicall/recvPacket Receiving back an ERC20 token. ~179,471 ~172,804 ~51,172B ~100,772B
multicall/ackPacket Acknowledging an ICS20 packet. ~92,621 ~88,485 ~53,572B ~105,572B

Note: These gas benchmarks are with Groth16.

Security Assumptions

IBC is a peer-to-peer, light-client-based interoperability protocol. This repository contains the following light clients:

The security of an IBC connection depends on the integrity of these light clients and the validator sets of the respective chains. However, IBC light clients can become frozen under certain conditions, such as:

Handling Frozen Light Clients

When a light client freezes, Cosmos SDK chains rely on governance to restart the client. However, Ethereum and Solana lack a native governance mechanism for this purpose. To address this, the Solidity and Solana implementations of IBC requires a timelocked Security Council to restart the light client in case of a freeze.

Additionally, the Security Council is responsible for:

Ideally, the Security Council should mirror the validators of the counterparty Cosmos SDK chain for better decentralization. In the future, a mechanism called govAdmin will allow the Cosmos SDK chain’s governance to directly control Ethereum contract upgrades via IBC (tracked in #278).

Security Council and Governance Admin

Although govAdmin is not yet implemented, the contract tracking both admins is AccessManager. We require that the both admins are granted the admin role on AccessManager.sol:

Other IBC contracts that require access control or upgradability should reference AccessManager.

Admin Powers and Restrictions

Until govAdmin is implemented, the Security Council remains the sole administrator. Under the AccessManager contract, all admins have equal authority, including the ability to:

Key Distinction Between Admins

The Security Council must apply a timelock to itself. This ensures that after delegation, the Security Council only retains power in cases where IBC light clients are frozen—effectively making govAdmin the primary administrator in normal conditions.

[!WARNING]

Roles and Permissions

The IBC solidity contracts use AccessManager to manage roles and permissions and allow the admins to reassign roles. All the roles are defined in IBCRolesLib.sol:

Role Name Role Id Description
ADMIN_ROLE 0 Can grant and set target functions for all roles.
RELAYER_ROLE 1 Whitelisted relayer addresses.
PAUSER_ROLE 2 Can pause the IBC application contracts.
UNPAUSER_ROLE 3 Can unpause the IBC application contract.
DELEGATE_SENDER_ROLE 4 Has permission to call sendTransferWithSender.
RATE_LIMITER_ROLE 5 Can set withdrawal rate limits per ERC20 token.
ID_CUSTOMIZER_ROLE 6 Can set custom client and port ids for applications.
ERC20_CUSTOMIZER_ROLE 7 Can set custom ERC20 contracts for non-native tokens instead of the default IBCERC20.
PUBLIC_ROLE type(uint64).max A role that everyone has by default.

Releases

The release lines currently supported are: solidity-v2.0.x, cw-ics08-wasm-eth-v1.3.x, and proof-api-v0.7.x. Please refer to our versioning guide for more information on how to understand our release versioning.

License

This project is licensed under MIT.

Acknowledgements

This project was bootstrapped with this template. Implementations of IBC specifications in solidity, CosmWasm, golang, and rust were used as references. We are also grateful to unionlabs for their 08-wasm Ethereum light client implementation for ibc-go which our own implementation is based on.