Skip to content

IFT transfer demo#1

Merged
dianab-cl merged 30 commits into
mainfrom
diana/plat-998-ibcevm-interop-demo-spec
May 8, 2026
Merged

IFT transfer demo#1
dianab-cl merged 30 commits into
mainfrom
diana/plat-998-ibcevm-interop-demo-spec

Conversation

@dianab-cl
Copy link
Copy Markdown
Contributor

No description provided.

@linear
Copy link
Copy Markdown

linear Bot commented Apr 24, 2026

PLAT-998 IBC<>EVM Interop Demo Spec

Summary

Reference demo for IBC↔EVM interop:

  1. a single make command spins up:
  • a Cosmos chain (PoA + EVM + IBC-go + IFT),
  • an EVM chain,
  • the relayer, attestor, and proof API;
  • deploys IBC contracts;
  1. and a second command runs bidirectional IFT transfers (Cosmos→EVM and EVM→Cosmos) with live status via the relayer API.

Context

Background / link to PRD:

Persona / use case:

  • Developer building a new Cosmos chain who wants to add IBC↔EVM connectivity.
  • Developer integrating IFT (tokenfactory-based) cross-chain transfers.
  • DevOps team operating a production relayer who needs to understand the
    monitoring and observability surface.

User stories

Asset issuer

  1. As an asset issuer, I can transfer my token between my Cosmos chain and EVM chains (Ethereum, Base) using mint/burn semantics — tokens burned on source, minted on destination, in both directions.
  2. As an asset issuer, transfers that fail (timeout, error ack, network issue) surface clearly through the relayer status API and are retryable; transfers never get permanently stuck.
  3. As an asset issuer, my users can directly move between all chains in my issuance network; they do not need to go through an intermediate chain.
  4. As an asset issuer, I want a connectivity offering that works on my Cosmos chain even without an EVM module installed; I will have built out my own issuance / tokenfactory module.

DevOps team

  1. As a DevOps team, I can submit a source transaction hash to the relayer and track the status of each packet in real time (pending/complete/failed, with tx hashes for each leg).
  2. As a DevOps team, I can monitor the relayer and attestor via Prometheus metrics: service liveness, relay latency, gas balance, transfer volume, retry counts, and external request latency. Documentation exists for alerts that fire on excessive latency and low gas balance.
  3. As a DevOps team, the relayer and attestor emit structured JSON logs. The attestor emits OpenTelemetry-compatible spans with per-request trace IDs so I can plug into my existing logging and observability stack.

Problem to solve:

  • No self-contained local demo existed for the Cosmos↔EVM IBC path that covers the full stack (chain setup, contract deployment, relaying, observability).
  • Developers and DevOps teams had no single reference to understand how all components wire together.

Scope

In

  • Cosmos chain (sandbox ledger / wfchain-derived):
    - PoA module
    - EVM module
    - IBC-go (no transfer module or Tendermint LC — not needed)
    - IFT module (tokenfactory-based, wfchain reference)
  • EVM chain:
    - Local EVM node (currently Besu + Teku as CL)
    - solidity-ibc-eureka contracts deployed: ICS26Router, attestor light client,
    IFT solidity contracts
  • Relaying stack:
    - Relayer (cosmos/ibc-relayer)
    - Attestor (cosmos/ibc-attestor)
    - Proof API (cosmos/solidity-ibc-eureka/programs/relayer)
  • Deploy script (single make command):
    - Spins up both chains, relayer, attestor, and proof API
    - Deploys IBC contracts to EVM chain
    - Creates attestation light clients on both chains
    - Registers counterparties (Cosmos: MsgCreateClient/MsgRegisterCounterparty;
    EVM: ICS26Router contract call)
    - Links IFT bridges on both chains (tokenfactory denom ↔ EVM IFT contract)
  • Transfer script (single command):
    - IFT transfer Cosmos → EVM (mint/burn)
    - IFT transfer EVM → Cosmos (mint/burn)
    - Polls relayer status API for both transfers; prints per-leg tx hashes
  • Observability:
    - Relayer + attestor Prometheus metrics endpoint
    - Structured JSON logs from both services
    - OTel-compatible spans with trace IDs from attestor
  • Documentation (developer-facing):
    - How to wire IBC-go + GMP + IFT + attestations into app.go alongside EVM
    and PoA modules
    - Deploy script walkthrough (ICS26Router, ICS20Transfer, IFT contracts)
    - Setup script walkthrough: attestation LC creation, counterparty registration,
    IFT bridge linking
    - Relayer, attestor, and proof API config walkthroughs
    - Transfer script: submit tx, poll relayer status API

Acceptance criteria + success metric

  • make deploy completes without errors: both chains produce blocks, all contracts deployed, attestation light clients created on both chains, IFT bridges registered on both chains.
  • make transfer completes: IFT transfer Cosmos→EVM accepted and relayed; IFT transfer EVM→Cosmos accepted and relayed; relayer status API returns "complete" with tx hashes for each leg of both transfers.
  • Tokens are minted on destination and burned on source for both directions (confirmed via chain state query after transfer).
  • Transfers that time out or error are surfaced in the relayer status API as "failed" (not silently dropped); a retry mechanism exists.
  • Prometheus /metrics endpoint on relayer and attestor returns liveness, relay latency, gas balance, transfer volume, retry counts, and external request latency metrics.
  • Relayer and attestor produce structured JSON logs; attestor spans include per-request trace IDs compatible with OTel collectors.
  • make clean leaves no Docker volumes, containers, or generated files.
  • A developer reading the docs can answer all six questions listed in the spec's Documentation Scope section.

Success metric(s):

  • make deploy completes in under 10 minutes on a developer laptop.
  • make transfer completes in under 2 minutes (both directions confirmed).

Approach (lightweight)

Implementation notes / proposed steps:

  • docker-compose setup for Cosmos chain
  • docker-compose setup for EVM chain
  • Makefile or sh script for chains setup, IBC setup and automated configuration
  • Makefile or sh script for running the user stories

Open questions / decisions:

  • Can the sandbox ledger / wfchain image be reused as-is, or does it need to be built from source? Who owns publishing a Docker image for it?
    • We should be using the sandbox ledger and we will likely need to add the ibc dependencies to it. Coordinate with vlad and eric on this.
  • SP1ICS07Tendermint: confirm whether the relayer (cosmos/ibc-relayer)
    deploys it on create-client or requires it pre-deployed. If pre-deployed,
    a Phase 4A1 forge-create step is needed.
    • We should be using the attestor light clients, not this client
  • Relayer config schema for cosmos/ibc-relayer — does it differ from
    the current solidity-ibc-eureka relayer config format?
    • These are different services. The relayer in the solidity-ibc-eureka repo is actually something we are referring to as the proof api now and it only helps to form transactions for the relayer.
  • Attestor: what config does it need, and does it share a keyring with
    the relayer or require its own funded key?
    • The attestor should use it's own signing key, it does not sign transactions so it does not need funds.
  • IFT bridge registration — is this a single tx or a multi-step flow?
    Confirm the exact Cosmos message(s) and EVM contract call(s).
    • This is multiple transactions, you'll have to deploy the send call constructor on the evm side and then perform ift bridge registration on both chains.

Definition of Ready (DoR) checklist

  • PRD/context + persona/use case present
  • Acceptance criteria + success metric(s) defined
  • Dependencies identified + owners known
  • Scope boundaries (in/out) clear
  • Approach agreed (or explicitly deferred)
  • Security/compliance notes captured if relevant

Definition of Done (DoD) checklist

  • Custom Cosmos chain image (PoA + EVM + IBC-go + IFT) boots and produces blocks; all module queries respond correctly
  • IFT Solidity contracts deployed alongside ICS26Router + ICS20Transfer
  • Attestor service starts and creates attestation LCs on both chains
  • Proof API service starts and relayer config references it correctly
  • Counterparty and IFT bridge registered on both chains
  • make transfer succeeds: both directions confirmed, relayer status API returns "complete" with tx hashes for all legs
  • cosmos/ibc-relayer image replaces solidity-ibc-eureka-relayer
  • Prometheus /metrics, JSON logs, and OTel spans verified; alert docs written
  • make deploy and make transfer targets work; make clean is complete
  • Open questions Q1–Q5 resolved
  • All 8 ACs met
  • Docs cover all 6 developer goals from spec's Documentation Scope
  • README updated (auto-download, make commands, no manual artifact steps)

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 24, 2026

Greptile Summary

This PR introduces a full Cosmos ↔ EVM IBC demo (demo/cosmos-evm/) covering chain initialization, solidity-ibc-eureka contract deployment, attestation light-client wiring, relayer/attestor setup, and four user-story demonstrations (Cosmos→EVM transfer, EVM→Cosmos transfer, packet tracking, failure/retry). The shell library is well-structured with state persistence and idempotency guards throughout.

  • P1 – tokenfactory denom check never matches (lib/ibc.sh:735): the select(. == \"uift\") filter compares the bare subdenom against full factory/<addr>/uift paths returned by the chain; on any re-run where the bridge must be recreated create-denom is resubmitted, the chain rejects it, and cosmos_tx_and_wait calls die, aborting setup.
  • Several pre-existing issues from earlier review rounds remain open (timeout units in seconds vs nanoseconds, cast to-check-sum-address typo, CI timeout-minutes: 20 too short).

Confidence Score: 3/5

Not ready to merge without fixing the tokenfactory denom idempotency bug; several pre-existing issues from prior review rounds also remain open.

One confirmed P1 (tokenfactory select never matches full factory paths, causing die on re-runs); multiple carry-over P1s from previous review rounds still unresolved (timeout units, cast to-check-sum-address typo, CI timeout). Score capped at 4 by the single new P1 and pulled down further by the accumulated open issues.

demo/cosmos-evm/lib/ibc.sh (denom check, checksum typo), demo/cosmos-evm/lib/demo.sh (timeout units), .github/workflows/demo-ift.yml (CI timeout)

Security Review

  • render_template in lib/common.sh uses eval with a heredoc, which will execute any $(...) or backtick expressions present in template content or in the values of shell variables expanded inside templates. A user-supplied DEVNET_MNEMONIC (environment-overridable) that contains command-substitution syntax would execute arbitrary commands at render time.
  • Hardcoded EVM private key (0xac0974bec…) and DEVNET mnemonic in setup.sh are well-known Foundry/Hardhat devnet credentials; clearly labeled devnet-only and not a concern for production, but GitHub secret scanning may flag them.

Important Files Changed

Filename Overview
demo/cosmos-evm/lib/ibc.sh Core IBC setup orchestrator: generally well-structured with idempotency guards, but the tokenfactory denom check (line 735) silently fails because it compares a bare subdenom against full factory paths; cast to-check-sum-address typo (line 713, 820) silently falls back to unchecksummed address
demo/cosmos-evm/lib/demo.sh User-story demos; timeout_ts for both cosmos_ibc_transfer and iftTransfer uses $(date +%s) + N in seconds — IBC standard expects nanoseconds, which would cause packets to appear immediately timed-out
demo/cosmos-evm/lib/common.sh render_template uses eval + heredoc to expand templates, executing any $(...) in template content or in expanded variables; state_set is correct but subtly relies on `
demo/cosmos-evm/setup.sh Top-level orchestrator; clean subcommand routing with state.env sourcing; SOLIDITY_IBC_TAG="main" is a known-deferred mutable ref that makes CI non-reproducible; COSMOS_IFT_MODULE_ADDR not included in default variable initializations
.github/workflows/demo-ift.yml timeout-minutes: 20 is insufficient for the full end-to-end run including demo_failure_and_retry plus EVM→Cosmos finality waits on cold ubuntu-latest; CI will be cancelled before teardown
demo/cosmos-evm/lib/chains.sh Chain init (Cosmos + Ethereum Besu/Teku) with correct idempotency guards for validator key, JWT secret, and CL genesis; ownership fix for Linux CI hosts is well-handled
demo/cosmos-evm/ibc/scripts/MinimalDeploy.s.sol Minimal forge deploy script for ICS26Router + ICS27GMP + TestIFT; returns a JSON label map consumed by _forge_return_addr; auth model (deployer = AccessManager admin) is appropriate for single-validator devnet

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[./setup.sh] --> B[cmd_chains]
    B --> B1[init_cosmos]
    B --> B2[init_ethereum / Besu+Teku]
    B --> B3[wait_for_services]
    A --> C[setup_ibc / cmd_ibc]
    C --> C1[4A0 fetch solidity-ibc-eureka]
    C1 --> C2[4A deploy IBC contracts on Besu]
    C2 --> C3[4A1 resolve IFT_CONTRACT_ADDR]
    C3 --> C4[4B fetch + checksum ethereum-lc.wasm]
    C4 --> C5[4C setup relayer key]
    C5 --> C6[4B5 reconcile IBC client pair]
    C6 --> C7[4B5 create attestation client on Cosmos]
    C7 --> C8[4D generate relayer + attestor configs]
    C8 --> C9[4E start postgres + relayer + attestors + proof-api]
    C9 --> C10[4E3 deploy AttestationLightClient on EVM]
    C10 --> C11[4F wait for clients on both sides]
    C11 --> C12[4F2 register counterparty on Cosmos]
    C12 --> C13[4F3 register IFT bridge on Cosmos]
    C13 --> C14[4F3a register IFT bridge on EVM]
    C14 --> C15[4F4 finalize relayer config + restart]
    C15 --> D[demo_all]
    D --> D1[Cosmos to EVM IFT transfer]
    D --> D2[EVM to Cosmos IFT transfer]
    D --> D3[track packet status]
    D --> D4[failure + retry demo]
    D --> D5[observability / Prometheus]
Loading

Reviews (7): Last reviewed commit: "After code review" | Re-trigger Greptile

Comment thread demo/cosmos-evm/lib/ibc.sh Outdated
Comment thread demo/cosmos-evm/setup.sh
Comment thread demo/cosmos-evm/ibc/relayer.yaml Outdated
Comment thread demo/cosmos-evm/lib/demo.sh
Comment thread demo/cosmos-evm/lib/ibc.sh
Comment thread demo/cosmos-evm/lib/ibc.sh
@dianab-cl dianab-cl marked this pull request as draft April 24, 2026 14:39
@dianab-cl
Copy link
Copy Markdown
Contributor Author

@greptile review

Comment thread demo/cosmos-evm/lib/ibc.sh
@dianab-cl
Copy link
Copy Markdown
Contributor Author

@greptile review

Comment thread .github/workflows/demo-ift.yml
@dianab-cl dianab-cl marked this pull request as ready for review April 25, 2026 09:57
Comment thread demo/cosmos-evm/lib/ibc.sh
@dianab-cl
Copy link
Copy Markdown
Contributor Author

@greptile review

@dianab-cl
Copy link
Copy Markdown
Contributor Author

@greptile review

Comment thread demo/cosmos-evm/lib/ibc.sh Outdated
@dianab-cl dianab-cl requested review from dhfang April 27, 2026 12:52
@dianab-cl dianab-cl requested review from evanorti and srdtrk April 27, 2026 12:52
Copy link
Copy Markdown
Member

@srdtrk srdtrk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My initial review is pointing out two high level issues.

  1. We want to demo against a besu + qbft chain rather than besu + teku. Teku is a beacon consensus implementation for Ethereum Mainnet only. So we should not be using it.
  2. I noticed that you are using the 08-wasm beacon light client rather than attestation. This is only possible because you're using teku as your consensus. We don't want to do this in this demo.

Comment thread demo/cosmos-evm/cosmos/inject-wasm-lc.jq Outdated
Comment thread demo/cosmos-evm/cosmos/patch-genesis.jq Outdated
Comment thread demo/cosmos-evm/evm/cl-config.yaml Outdated
Comment thread demo/cosmos-evm/evm/teku.yaml Outdated
return _toJson(d);
}

function _deploy() internal returns (Deployed memory d) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This script does not configure the access manager. This means that the roles have not yet been setup. And also, the only role granted is ADMIN_ROLE.

The access manager setup can also be done during the runtime or by using another script. So, this is not a big issue

Comment on lines +22 to +40
{
"name": "eth_to_cosmos",
"src_chain": "${ETH_CHAIN_ID}",
"dst_chain": "${COSMOS_CHAIN_ID}",
"config": {
"tm_rpc_url": "http://cosmos:26657",
"ics26_address": "${ICS26_ROUTER_ADDR}",
"eth_rpc_url": "http://besu:8545",
"eth_beacon_api_url": "http://teku:5051",
"signer_address": "${RELAYER_ADDR}",
"mode": {"attested": {
"attestor": {
"quorum_threshold": 1,
"attestor_endpoints": ["http://attestor:9101"],
"attestor_query_timeout_ms": 10000
}
}}
}
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't want to use this since this is only meant to be used for eth mainnet

Comment thread demo/cosmos-evm/README.md Outdated
Comment thread demo/cosmos-evm/README.md Outdated
@dianab-cl
Copy link
Copy Markdown
Contributor Author

My initial review is pointing out two high level issues.

  1. We want to demo against a besu + qbft chain rather than besu + teku. Teku is a beacon consensus implementation for Ethereum Mainnet only. So we should not be using it.
  2. I noticed that you are using the 08-wasm beacon light client rather than attestation. This is only possible because you're using teku as your consensus. We don't want to do this in this demo.

points addressed and resolved, removed wasm clients and teku-> qbft

@dianab-cl dianab-cl merged commit cb3dfd2 into main May 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants