This repository is the home of IBC contracts for Ethereum and Solana. The files include the Solidity contracts, the Solana programs, and the light clients.
The Inter-Blockchain Communication (IBC) Protocol is the open standard for secure interoperability between independent systems. Visit the IBC docs for more information.
Contributions are welcome. See CONTRIBUTING.md for contribution guidelines.
| Path | What it is |
|---|---|
ibc-solidity/contracts/ |
IBC core, applications, and light clients for EVM chains. |
ibc-solidity/programs/ |
The Rust programs maintained alongside the contracts: the SP1 programs, the CosmWasm Ethereum light client, and the SP1 fixture operator. |
ibc-solana/ |
IBC core, applications, and light clients implemented as Anchor programs, with shared crates and integration tests. |
programs/proof-api/ |
Serves the proofs a relayer submits. |
packages/ |
Shared Rust crates, including go-abigen/ for the Go bindings. |
e2e/ |
End-to-end tests, powered by interchaintest. |
docs/ |
Architecture decision records and audit reports. |
scripts/, tools/ |
Repository-wide scripts and test tooling. |
The published documentation for this repository lives at ibcprotocol.dev, and its source lives in cosmos/ibc. Documentation changes are tracked there.
- IBC Solidity contracts is the reference for each contract: what it does, its storage, events, and roles.
- Permissions and upgrades covers the roles, the proxies, and what each deployment fixes for good.
- Solana programs covers deployment, key generation, access control, and upgradability.
UPGRADEABILITY.mdis the procedure for upgrading a deployed contract.- Benchmarks covers SP1 Tendermint packet costs and Besu QBFT light-client operation costs.
See RELEASES.md for the versioning scheme, how to cut a release, and how to verify its signed files and image. Current versions are on the releases page.
| Contract | What it does | Released |
|---|---|---|
ICS26Router.sol |
Sequencing, replay protection, and timeout checks. Passes proofs to light clients and resolves portId for app callbacks. Holds the provable IBC store. |
✅ |
ICS20Transfer.sol |
Sends and receives tokens against another ICS-20 implementation. | ✅ |
ICS27GMP.sol |
General message passing, through per-sender interchain accounts. | ✅ |
SP1ICS07Tendermint.sol |
Tendermint light client powered by SP1. The entry point for SP1 proofs. | ✅ |
AttestationLightClient.sol |
Verifies state attestations signed by a quorum of attestors. | ✅ |
utils/IFTBaseUpgradeable.sol |
Interchain Fungible Tokens using mint and burn semantics. | ✅ |
BesuLightClient.sol |
Besu IBFT 2.0 and QBFT light client. | ✅ |
| Program | What it does | Released |
|---|---|---|
update-client |
Adds a consensus state from an IBC header, running the CometBFT light client protocol. Also supports a partial misbehaviour check. | ✅ |
membership |
Verifies verify_membership and verify_non_membership against a consensus state the client already holds. |
✅ |
uc-and-membership |
Updates the client and proves membership against the new consensus state, in one program. | ✅ |
misbehaviour |
Handles the case where a malicious subset of validators exceeds the client's trust level. | ✅ |
No Solana release line is tagged yet. The programs below are on main.
| Program | What it does |
|---|---|
ics26-router |
The router, matching the Solidity contract's responsibilities. |
ics27-gmp |
General message passing, through interchain accounts. |
ics07-tendermint |
Tendermint light client, powered by tendermint-rs. |
attestation |
The multisig light client. |
access-manager |
Stores the permissions for the whole system. |
ift |
Interchain Fungible Token. |
Install Rust, Foundry, Bun, Just, SP1, and the Protobuf compiler.
Note
A Homebrew installation of Rust can fail the SP1 step. Install Rust through rustup instead.
Foundry usually manages contract dependencies with git submodules. This repository uses Node.js packages through Bun, because submodules do not scale:
cd ibc-solidity && bun installSome end-to-end tests need the operator and proof API binaries:
just solidity::install-operator
just install-proof-apiTip
Nix users get every dependency with nix develop.
Install Rust, Anchor, Agave, and Just. ibc-solana/rust-toolchain.toml selects the Rust version.
just solana::build-solana-programs
just solana::test-solanaList every Solana recipe with just solana.
Tip
Nix users can run nix develop .#solana, then use anchor-nix in place of anchor from ibc-solana/.
The Solidity contracts compile for the Cancun EVM and use EIP-1153 transient storage at runtime, in ReentrancyGuardTransient and in the proof caches of the SP1 Tendermint and Besu light clients. Deploy them only to a chain with Cancun enabled. On a pre-Cancun chain, packet handling and proof verification revert with an invalid opcode.
See the contracts README and the Besu light client README.
Solidity tests live in ibc-solidity/test/ and are written with forge:
just solidity::test-foundryPass a test name to run one of them:
just solidity::test-foundry test_success_sendTransferCoverage is reported to Codecov from the Foundry and Rust unit tests, tracked per component:
codecov.yml has the full list.
The tests in e2e/interchaintestv8 are written in Go and use interchaintest. They spin up a local Ethereum network and a Tendermint network. Some generate proofs through the prover network, which needs an SP1 network private key in .env.
Install Go, Docker, and Kurtosis. Kurtosis must match the github.com/kurtosis-tech/kurtosis/api/golang version in the e2e go.mod.
Then set up .env as .env.example describes. After changing a contract interface or type, regenerate the ABIs with just solidity::generate-abi.
Note
On a Mac with an M chip: set up Rosetta, enable it for Docker under Settings → General, and pull the Foundry image with docker pull --platform=linux/amd64 ghcr.io/foundry-rs/foundry:latest.
Five suites are available, each taking a test name:
| Suite | Command | Needs |
|---|---|---|
| IBC contracts through the proof API | just test-e2e-eureka $TEST_NAME |
operator, proof API |
| The proof API itself | just test-e2e-proof-api $TEST_NAME |
operator, proof API |
| Cosmos-to-Cosmos connections | just test-e2e-cosmos-proof-api $TEST_NAME |
operator, proof API |
| SP1 ICS-07 Tendermint light client | just test-e2e-sp1-ics07 $TEST_NAME |
operator |
| Multichain transfers | just test-e2e-multichain $TEST_NAME |
operator, proof API |
Development also uses Natlint, Abigen, golangci-lint, jq, and GNU Parallel. Lint before committing:
just lintIBC is a peer-to-peer, light-client-based interoperability protocol. This repository contains the following light clients:
- SP1 Tendermint Light Client – Verifies the consensus state of a Cosmos SDK chain powered by SP1 and
tendermint-rs. (Solidity) - Besu IBFT 2.0 / QBFT Light Client – Verifies Besu BFT headers in header-validator mode, tracks the counterparty chain state root, and verifies EVM account/storage proofs for Eureka commitments. (Solidity)
- Ethereum Light Client – Verifies the consensus state of the Ethereum chain. (CosmWasm)
- Attestation Light Client – A multisig that can be used if the counterparty chain does not have a light client protocol. (Solidity and Solana)
- Solana Tendermint Light Client – Verifies the consensus state of a Cosmos SDK chain powered by
tendermint-rs. (Solana)
The security of an IBC connection depends on the integrity of its light clients and their underlying trust assumptions, including the relevant validator or attestor sets.
Depending on the implementation, a light client can become frozen after detecting misbehaviour, such as two conflicting valid headers. A client with a trusting period can instead expire if it is not updated before that period elapses. Freezing and expiration are distinct conditions; recovery procedures depend on the client implementation.
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 require a timelocked Security Council to restart the light client in case of a freeze.
Additionally, the Security Council is responsible for:
- Upgrading IBC contracts in the event of a security vulnerability.
- Introducing new features while balancing security and decentralization.
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).
Although govAdmin is not yet implemented, the contract tracking both admins is AccessManager. We require that both admins are granted the admin role on AccessManager.sol:
timelockedAdmin(Security Council)govAdmin(Governance Admin)
Other IBC contracts that require access control or upgradability should reference AccessManager.
Until govAdmin is implemented, the Security Council remains the sole administrator. Under the AccessManager contract, all admins have equal authority, including the ability to:
- Assign or modify the other admin.
- Manage roles on IBC contracts.
- Upgrade IBC contracts. Learn more about upgrading the Solidity contracts.
The Security Council must enforce its own timelock. After delegation, govAdmin is intended to handle routine administration, while the Security Council intervenes when a light client is frozen. Both retain equal administrative permissions under AccessManager.
Warning
- The timelock on the Security Council is not enforced within the IBC contracts but should be self-enforced.
- The timelock duration should be at least as long as:
- The
govAdmintimelock (if applicable). - The time required for governance proposals to pass.
- The
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 and app and client registration in the router. |
UNPAUSER_ROLE |
3 | Can unpause the IBC application contracts and app and client registration in the router. |
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. |
Apache License, Version 2.0. See LICENSE.md.
Bootstrapped from this Foundry template. The IBC implementations in Solidity, CosmWasm, Go, and Rust were used as references. The 08-wasm Ethereum light client from unionlabs is the basis for this repository's own.
