Skip to content

cardano-foundation/cardano-ibc-incubator

Cardano IBC Incubator

License: Apache-2.0 Status: Pre-production Docs: Architecture

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.

Index

Status

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

Trust Model & Security Considerations

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.

Overview

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 native ChainEndpoint implementation 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.

Architecture

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
Loading

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

Relayer Implementation (Hermes)

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:

  • ChainEndpoint trait 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

Hermes Configuration

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 required

Architecture & Design Decisions

Transaction Signing Architecture

The 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 CardanoSigningKeyPair implementation

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.

Getting Started

Prerequisites

The following components are required to run the project:

Verify Prerequisites

To check if you have all the necessary prerequisites installed:

cd caribic
cargo run check

OS and Architecture Considerations

This 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/amd64 or 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.

Running a local Cardano network

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 --clean

If you need to start components separately, use:

caribic start network
caribic start bridge

Testing against Cosmos chains

Important

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.

Stopping the services

To stop the services:

caribic stop

Demo: Direct Cosmos Routes

The 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 local

Demo: Cross-chain token swap

caribic 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 local

For 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 local

If 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.

Useful commands for local networks

Local account configuration

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.

Register a new stake pool on the local Cardano blockchain

cd cardano/chains && ./regis-spo.sh <name>

Example:

cd cardano/chains && ./regis-spo.sh alice

Retire a stake pool on the local Cardano blockchain

This 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 alice

Register a validator on Cosmos

This 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"

Unregister a validator on Cosmos

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"

Test IBC primitives and lifecycles

For current end-to-end timeout and packet lifecycle validation, use the maintained integration suite:

caribic start --clean
caribic --verbose 5 test

Additional Resources

Troubleshooting

Cardano Node DiffusionError: Network.Socket.bind permission denied

If 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.

Kudos to the Developers in the Cardano Ecosystem

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:

Contributing

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!

License

This project is licensed under Apache 2.0.

Additional Documents

Packages

 
 
 

Contributors