AttestationLightClient in the create-clients step once the attestor address is known, and CosmosIFTSendCallConstructor in wire once the client-derived account address is computed.
This command runs the deployment:
lib/ibc.sh.
What it does
The script uses the committed forge workspace atibc/forge/ and downloads prebuilt contract bytecode from the cosmos/solidity-ibc-eureka release bundle. Then the following runs inside a Foundry container:
AccessManager admin and the relayer EOA. OpenZeppelin AccessManager defaults unset restricted functions to ADMIN_ROLE, which the deployer holds, so addIBCApp, recvPacket, ackPacket, and timeoutPacket all work without additional role grants. This is sufficient for a single-validator devnet; production deployments need explicit role wiring (see Access control below).
See the table below for the full deploy order and constructor arguments.
Deployed Contracts
The following steps are run byMinimalDeploy.s.sol in order. Each contract’s constructor or initializer depends on addresses from the steps before it.
Two more contracts are deployed in later steps:
Resolving the IFT Contract Address
After the Forge script completes, the script reads the broadcast artifacts (broadcast/<script>/<chain-id>/run-latest.json) to extract the deployed IFTOwnable proxy address and persists it as IFT_CONTRACT_ADDR in ibc/state.env. This address is used in the wire step to register the EVM contract as the counterparty for the Cosmos-side uift denom.
Deployed Address Usage
The three core addresses produced by this step are used throughout the rest of the setup:ICS26Router: referenced by the attestor config (router_address), relayer config (ics_26_router_address), and proof API config (ics26_address)ICS27GMP: passed as an initializer argument toIFTOwnableat deploy timeIFTOwnable: registered in thewirestep as the EVM counterparty for the Cosmosuiftdenom
Applying this to your own chain
IBC Solidity Contracts
For a complete list of the IBC Solidity contracts, see the cosmos/solidity-ibc-eureka repository.EVM Deployments
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. Deploying IBC Solidity contracts to a Cosmos EVM chain is no different than deploying to any other EVM chain. If you are connecting two Solidity deployments (EVM on both sides), useEVMIFTSendCallConstructor instead of CosmosIFTSendCallConstructor when constructing IFT send calls.
Deploy order
The order is fixed because each contract’s initializer takes addresses from contracts deployed before it. The main constraints are:AccessManagerfirst: bothICS26RouterandICS27GMPtake its address ininitializeICS27AccountbeforeICS27GMP: GMP’s initializer takes the account implementation addressIFTOwnablelast: initialized with theICS27GMPaddress
Access control
TheAccessManager is initialized with the deployer address as admin. The admin can grant and revoke roles and configure which addresses are permitted to call restricted functions on ICS26Router and ICS27GMP. Use a secure address for this role. See the OpenZeppelin Access Control documentation for guidance on managing roles and permissions.
For permissioned relayers, the relayer address should hold a role that covers only recvPacket, ackPacket, and timeoutPacket on ICS26Router.
IFT contract
The demo deploysIFTOwnable, which uses OwnableUpgradeable for access control: a single owner address controls all privileged functions. IFTAccessManaged provides more fine-grained control, allowing each function to be restricted to a different role. For a fully custom implementation, extend IFTBaseUpgradeable and implement _onlyAuthority() with your own logic. The full interface is defined in IIFT.sol.