This is a work-in-progress implementation of IBC v1 for Cardano. It implements a Cardano-native realization of the IBC protocol semantics which allow trustless interop between Cardano and the Cosmos ecosystem. The bridge implements ICS-02 (clients), ICS-03 (connections), ICS-04 (channels and packets), ICS-20 (fungible token transfer), and the proof/path model of ICS-23 and ICS-24, while adapting Cardano to the IBC client model through the experimental 08-cardano-probabilistic light client.
The implementation adheres to the inter-blockchain communication protocol standards.
Caution
Disclaimer
Please be aware that this is an incubator project, and it is neither complete nor sufficiently tested at this time. The source code and software artifacts in this repository are subject to your own discretion and risk, and are not suggested as adequate for a production bridge deployment.
While we strive for high functionality and user satisfaction, unforeseen issues may arise due to the experimental nature of this project.
- Status
- Trust Model & Security Considerations
- Overview
- Architecture
- Getting Started
- Testing Against Cosmos Chains
- Demo: Direct Cosmos Routes
- Demo: Cross-chain Token Swap
- Additional Resources
- Contributing
| Area | Status | Notes |
|---|---|---|
| Local devnet stack | Active | Managed through caribic with Cardano, Hermes, Kupo, Ogmios, and Yaci-backed history services |
| Core IBC semantics | Active | Implements clients, connections, channels, packets, acknowledgements, and timeouts |
| ICS-20 transfer path | Active for local direct routes | Local Cardano-to-Osmosis and Cardano-to-Injective routes use direct channels; target chains still need the Cardano light client patched in locally |
| Historical query backend | Active | Uses Yaci Store + Bridge Projection rather than a generic db-sync query surface |
| Public network integrations | Pre-production | Select paths exist for public testnets and external Cardano services, but the operating model is still evolving |
| Mithril light client and local setup | Deprecated / disabled | Not maintained for new deployments; source is retained only for historical reference and type compatibility |
| Production deployment | Not recommended | This repository should be treated as pre-production software |
There are currently protocol-level constraints that prevent IBC-style state proofs of Cardano, for example UTxO inclusion proofs. A valuable conversation on that topic can be found here: CIP-0165 (Canonical Ledger State).
The maintained Cardano-native approach uses a proprietary STT architecture plus the experimental 08-cardano-probabilistic light client to attain an analogous IBC state machine in Cardano semantics. The STT architecture over the IBC host state keyspace functions as an authenticated mutex for IBC host state mutation, while the probabilistic light client authenticates accepted Cardano history through configured settlement heuristics. This model is documented in Probabilistic Light Client Design.
The older Mithril light client and local Mithril setup are deprecated, disabled, and not maintained. They remain in the repository only for historical design reference and protobuf/type compatibility.
This repository is divided into five main directories:
cardano: Contains all Cardano related source code that are part of the bridge as well as some facilities for bringing up a local Cardano blockchain for test and development purposes. It also contains the Aiken based Tendermint Light Client and IBC primitives implementation.cosmos: Contains all Cosmos SDK related source code including the Cardano light client (or thin client) implementation running on the Cosmos chain. The folder was scaffolded via Ignite CLI with Cosmos SDK 0.50.relayer: A fork of Hermes (Rust IBC relayer) with Cardano integration. This replaces the deprecated Go relayer and provides nativeChainEndpointimplementation for Cardano chains.caribic: A command-line tool responsible for starting and stopping all services, as well as providing a simple interface for users to interact with and configure the bridge services.
flowchart LR
subgraph Client["Client Layer"]
UI["Frontend UI"]
UW["User Wallet"]
end
subgraph Gateway["Cardano Gateway"]
TX["Tx Service"]
QUERY["Query Service"]
LUCID["Lucid Service"]
TRACE["Denom Trace Service"]
end
subgraph OnChain["On-Chain Validators"]
HOST["host_state_stt.ak"]
CH_SEND["spending_channel/<br/>send_packet.ak"]
CH_RECV["spending_channel/<br/>recv_packet.ak"]
CH_ACK["spending_channel/<br/>acknowledge_packet.ak"]
CH_TIMEOUT["spending_channel/<br/>timeout_packet.ak"]
TRANSFER["spending_transfer_module.ak"]
VOUCHER["minting_voucher.ak"]
end
subgraph CardanoInfra["Cardano Infrastructure"]
NODE["cardano-node"]
KUPO["Kupo"]
DBSYNC["db-sync + Postgres"]
HISTORY["Yaci / DB History<br/>+ Probabilistic Witnesses"]
end
subgraph Relay["Relay and Counterparty"]
HERMES["Hermes Relayer"]
COSMOS["Counterparty Chain"]
end
UI -->|"build unsigned transfer request"| TX
UW -->|"sign unsigned tx"| UI
TX -->|"assemble tx body"| LUCID
LUCID -->|"uses validators in tx scripts"| HOST
LUCID -->|"send-packet validation"| CH_SEND
LUCID -->|"recv-packet validation"| CH_RECV
LUCID -->|"ack-packet validation"| CH_ACK
LUCID -->|"timeout-packet validation"| CH_TIMEOUT
LUCID -->|"uses validators in tx scripts"| TRANSFER
LUCID -->|"uses validators in tx scripts"| VOUCHER
HERMES -->|"submit signed tx"| NODE
HERMES -->|"recv/ack/timeout calls"| TX
HERMES <-->|"IBC packets and proofs"| COSMOS
QUERY -->|"UTxO and datum reads"| KUPO
QUERY -->|"indexed tx/block queries"| DBSYNC
QUERY -->|"history and witness queries"| HISTORY
TX -->|"denom trace writes<br/>and updates"| TRACE
TRACE -->|"persist trace rows"| DBSYNC
NODE -->|"chain indexing feed"| KUPO
NODE -->|"chain indexing feed"| DBSYNC
NODE -->|"chain history feed"| HISTORY
classDef client fill:#e8f1ff,stroke:#2b5cab,color:#0f172a
classDef gateway fill:#e9f8ee,stroke:#2f7d4a,color:#0b1f14
classDef onchain fill:#fff4e5,stroke:#a05a00,color:#2b1a00
classDef infra fill:#f2f4f7,stroke:#4a5568,color:#111827
classDef relay fill:#fdecef,stroke:#b4233d,color:#3a0f16
class UI,UW client
class TX,QUERY,LUCID,TRACE gateway
class HOST,CH_SEND,CH_RECV,CH_ACK,CH_TIMEOUT,TRANSFER,VOUCHER onchain
class NODE,KUPO,DBSYNC,HISTORY infra
class HERMES,COSMOS relay
Additional architecture diagrams:
- Gateway escrow flow:
cardano/gateway/README.md#sendpacket-escrow-flow - Denom trace lifecycle:
docs/denom-trace-mapping.md - Probabilistic light client:
docs/probabilistic-light-client.md - Deprecated Mithril proof flow:
docs/mithril-light-client.md#mithril-proof-flow-for-relaying - Diagram index:
docs/architecture-overview.md
This project uses a fork of the Hermes IBC relayer with native Cardano support. The relayer is integrated as a git submodule pointing to:
Fork Repository: https://github.com/cardano-foundation/hermes-relayer
Branch: feat/cardano-integration
The Cardano implementation resides in relayer/crates/relayer/src/chain/cardano/ and includes:
ChainEndpointtrait implementation for Cardano- CIP-1852 hierarchical deterministic key derivation
- Ed25519 transaction signing using Pallas primitives
- Gateway gRPC client for blockchain interaction
- Cardano-specific IBC types (Header, ClientState, ConsensusState)
- Full async runtime integration with Hermes's message-passing architecture
- Complete protobuf generation for Gateway Query and Msg services
Caution
When configuring Hermes, ensure your ~/.hermes/config.toml has the correct key_store_folder path. Use absolute paths, not tilde (~) notation, as tilde expansion may not work correctly:
[[chains]]
type = 'Cardano'
id = 'cardano-devnet'
key_store_folder = '/Users/yourusername/.hermes/keys' # Absolute path requiredThe Hermes relayer implements Cardano transaction signing using Pallas, a pure Rust library for Cardano primitives. The architecture separates concerns between transaction building and signing:
- Gateway (NestJS/TypeScript) builds unsigned transactions using Lucid Evolution and handles all Cardano-specific domain logic (UTxO querying, fee calculation, and proof/header preparation)
- Hermes Relayer (Rust) signs pre-built transactions using CIP-1852 key derivation and Ed25519 signatures via the native
CardanoSigningKeyPairimplementation
This separation provides:
- Clean boundaries between chain-specific logic (Gateway) and generic IBC relaying (Hermes)
- Native integration with Hermes's keyring system following the same pattern as Cosmos SDK chains
- Easier testing and maintenance of cryptographic signing separate from transaction construction
The Cardano chain implementation in Hermes (relayer/crates/relayer/src/chain/cardano/) follows the same architectural patterns as other supported chains, ensuring consistent behavior across the IBC ecosystem.
The following components are required to run the project:
To check if you have all the necessary prerequisites installed:
cd caribic
cargo run checkThis project uses Docker containers that require platform-specific images depending on your operating system and CPU architecture. Some Docker images (such as Kupo) support multiple architectures (AMD64/x86_64 and ARM64), but Docker may not automatically select the correct one.
If you encounter issues with containers crashing immediately or OOM (Out-Of-Memory) errors, you may need to explicitly specify the platform in the Docker Compose configuration:
- ARM64 (Apple Silicon, M1/M2/M3 Macs): Ensure images specify
platform: linux/arm64 - AMD64/x86_64 (Intel/AMD processors): Use
platform: linux/amd64or omit the platform (defaults to AMD64)
The chains/cardano/docker-compose.yaml file includes platform specifications where needed. If you're running on a different architecture or encounter compatibility issues, you may need to adjust these platform settings accordingly.
To start the Cardano node, Ogmios, Kupo, and Yaci-backed history services locally, run the maintained default stack.
Warning
Mithril setup is deprecated, disabled, and not maintained. Do not use caribic start --with-mithril or caribic start mithril for new deployments. The Mithril sources and compose files remain only for historical reference and compatibility with old types.
Before using the CLI, build and install caribic locally:
cd caribic
cargo install --path . --force
cd ..To start the managed local Cardano devnet together with the bridge components, run:
caribic start --cleanIf you need to start components separately, use:
caribic start network
caribic start bridgeImportant
Cosmos chains must explicitly support the Cardano light client and allow it via ibc.core.client.v1.Params.allowed_clients (e.g., 08-cardano-probabilistic). If the client type is not registered/allowed on the Cosmos chain, creating the counterparty client will fail and IBC connection/channel handshakes cannot proceed. Also ensure the relayer key on those chains is funded; Cosmos SDK accounts can return NotFound until they receive tokens.
To stop the services:
caribic stopThe previous intermediary-chain topology has been phased out for production safety. Local and public-testnet flows should use direct Cardano-to-target routes instead.
Direct routes require explicit target-chain support:
- The target Cosmos chain must compile and register the Cardano light client module, and allow the relevant client type in IBC client parameters.
- Cardano must support the target chain client type, usually Tendermint/CometBFT for Cosmos SDK chains.
- Operators must create direct Cardano clients, connections, and channels for each target chain.
- ICQ flows require the target chain to enable the relevant ICQ host/query module.
The reusable transfer route setup command targets the selected chain directly:
caribic setup route --from cardano --to osmosis --to-network local
caribic setup route --from cardano --to injective --to-network localcaribic demo token-swap now uses direct Cardano-to-target channels. The local Osmosis demo provisions the swap pool/contracts and executes a direct Cardano-to-Osmosis wasm-hook swap with a direct return leg. The local Injective demo exercises the direct token-transfer legs used by the swap path.
For local Osmosis:
caribic start --clean
caribic chain start --chain osmosis --network local
caribic setup route --from cardano --to osmosis --to-network local
caribic demo token-swap --chain osmosis --network localFor local Injective:
caribic start --clean
caribic chain start --chain injective --network local
caribic setup route --from cardano --to injective --to-network local
caribic demo token-swap --chain injective --network localIf client creation fails with an unsupported client type, the selected target chain still needs the Cardano light client registered and allowed before direct routing can work.
caribic generates the local Cardano account material in config.json the first time it runs. By default, it can be found at <USER_HOME>/.caribic/config.json.
cd cardano/chains && ./regis-spo.sh <name>Example:
cd cardano/chains && ./regis-spo.sh aliceThis will sent a tx to retire your pool in the next epoch:
cd cardano/chains && ./deregis-spo.sh <name>Example:
cd cardano/chains && ./deregis-spo.sh aliceThis script will connect to your current docker and regis a new validator
Run this to check we only have 1 validator: curl -X GET "http://localhost:1317/cosmos/base/tendermint/v1beta1/validatorsets/latest" -H "accept: application/json"
Run this to regis new validator: cd cosmos/scripts/ && ./regis-spo.sh
Run this to check we now have 2 validators: curl -X GET "http://localhost:1317/cosmos/base/tendermint/v1beta1/validatorsets/latest" -H "accept: application/json"
Stop the running script above, then wait for about 100 blocks (~2 mins), then check we only have 1 validator:
curl -X GET "http://localhost:1317/cosmos/base/tendermint/v1beta1/validatorsets/latest" -H "accept: application/json"For current end-to-end timeout and packet lifecycle validation, use the maintained integration suite:
caribic start --clean
caribic --verbose 5 testIf you encounter an error like DiffusionError Network.Socket.bind: permission denied (Operation not permitted) when starting the Cardano node, see the Cardano Forum thread on this issue.
If this doesn't resolve the issue, this is typically related to Docker runtime configuration. If using Colima on macOS, ensure you're using VirtioFS mount type by recreating Colima with colima delete followed by colima start --vm-type=vz --mount-type=virtiofs --network-address, and verify the cardano-node is configured to bind to 0.0.0.0 rather than a specific IP address.
This project stands on the shoulders of some incredible frameworks and tools developed by the Cardano community. Huge thanks to the developers behind these services—projects like this wouldn’t be possible without their hard work and innovation:
All contributions are welcome! Please feel free to open a new thread on the issue tracker or submit a new pull request.
Please read Contributing in advance. Thank you for contributing!
This project is licensed under Apache 2.0.