Before running through the walkthrough, make sure you have completed the prerequisites in the quickstart.
This page covers the setup of the two chains used in the demo. It walks you through what each one is, which modules the Cosmos chain needs for IBC v2 and IFT support, and what happens when you run the following command in the demo:
The logic for this command is in lib/chains.sh.
Everything else in the tutorial depends on both chains being up and producing blocks before it runs.
Cosmos: sandbox-ledger
The Cosmos chain in this demo is sandbox-ledger, a Cosmos SDK chain built specifically for IBC v2 interoperability. It runs as a single-validator proof-of-authority (POA) chain using CometBFT consensus.
EVM: Hyperledger Besu
The EVM chain is a single-validator Hyperledger Besu node running QBFT consensus. Unlike the Cosmos side, the EVM chain requires no custom chain-level modules: the IBC stack is deployed as Solidity contracts on top of a standard EVM node.
The demo uses:
- Chain ID:
32382
- Block period: 2 seconds
- Consensus: QBFT (single-validator, no peer discovery)
- Funded account:
0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 (this is a test key; do not use it with real funds).
Besu is configured via evm/besu.toml and evm/el-genesis.json.
What ./setup.sh chains does
Cosmos initialization
The lib/chains.sh script runs inside the sandbox-ledger container to initialize the chain, then patches the genesis before starting:
- Creates the host config directories (
cosmos/local/config/, cosmos/local/keyring-test/) so the bind mounts in docker-compose.yml resolve correctly.
- Runs
sandboxd init to generate the initial genesis and key files.
- Adds a
validator key.
- Adds a
relayer key and funds it in genesis.
- Reads the CometBFT consensus pubkey from
priv_validator_key.json and injects it into the POA validator set in genesis via patch-genesis.jq. POA requires at least one validator in genesis or it rejects on startup.
- Patches genesis denoms and sets the IFT module authority to the validator address.
- Copies the customized
app.toml and config.toml from cosmos/ into the config directory, overwriting the defaults written by init.
- Starts the
cosmos container.
Besu initialization
-
Starts the
besu container with the pre-existing evm/el-genesis.json and evm/key files.
-
Polls
http://localhost:8545 until the JSON-RPC endpoint is reachable.
Readiness check
After both containers start, the script polls each chain until it confirms blocks are being produced, then prints the endpoints and current block heights.
Cosmos (sandbox)
CometBFT RPC : http://localhost:26657
REST API : http://localhost:1317
gRPC : localhost:9090
Besu (Ethereum EL)
JSON-RPC HTTP : http://localhost:8545
WebSocket : ws://localhost:8546
Applying this to your own chains
The chain used in this demo illustrates how to use IBC modules on the Cosmos side, but you can also use the Solidity deployment on Cosmos chains with EVM capabilities.If you are operating a Cosmos EVM chain and need to access IBC through the EVM, you can skip the Cosmos-side wiring and use Solidity contract deployments for your chain.
For native Cosmos IBC module deployments, the Cosmos chain should have the IBC modules listed in the table below installed and wired.
| Module | Package | Purpose |
|---|
ibc (core) | ibc-go/v11 | Core IBC packet routing |
callbacks (v1 + v2) | ibc-go/v11 | Ack and timeout callbacks for GMP packets |
27-gmp | ibc-go/v11 | ICS-27 General Message Passing: carries cross-chain mint and burn instructions |
attestations light client | ibc-go/v11 | The only light client type registered on this chain: verifies packets via quorum-signed ECDSA attestations rather than Tendermint headers |
tokenfactory | ibc-go/v11 | Permissionless factory/<creator>/<subdenom> token creation with admin-gated mint and burn |
ift | ibc-go/v11 | The IFT bridge module: pairs a tokenfactory denom with a counterparty IFT contract and handles cross-chain burn/mint |
The tokenfactory and ift Cosmos modules used in this demo are provided as reference implementations only and are not intended for use in production as-is.
The IBC v2 port routing is set in app/app.go. The gmpport routes to the GMP module, wrapped in callbacks-v2 middleware so the IFT keeper receives ack and timeout callbacks.
You can refer to PR #1 in the sandbox-ledger repo as a reference of the changes needed to add IBC v2 and IFT support to an existing Cosmos SDK chain.
The full wiring, including keeper initialization, module manager registration, and begin/end blocker ordering, is in app/app.go.
On the EVM side, no chain modifications are needed. The IBC stack for EVM is entirely at the contract layer, which is covered in the next step.