Interchain Events: Cross-chain state verification on the Hub — working POC on mainnet
Hi everyone — I’ve been working on a cross-chain state verification primitive for the Hub and I’d love to get the community’s feedback on the approach, the architecture, and whether this is something that would be valuable for the ecosystem.
TL;DR
I built a CosmWasm contract on the Cosmos Hub that verifies the state of remote chains using ICS-23 Merkle proofs and triggers smart contract callbacks. It’s deployed on mainnet and works end-to-end today: write state on Neutron → watcher detects it → proof submitted to Hub → contract verifies proof → callback fires.
No oracle, no trusted third party. The proof is either mathematically valid or rejected.
The problem
IBC gives us trustless message passing between chains. ICS-20 lets us transfer tokens. But what about reacting to state changes on another chain without that chain’s cooperation?
Examples:
- An investor completes KYC on an identity chain → automatically whitelist them on a securities chain
- A settlement is finalized on Chain A → release escrowed payment on Chain B
- A certification is issued on an audit chain → unlock access on a service chain
Today, each of these requires building a custom bilateral IBC protocol on both sides. That’s months of development per integration, and it scales as N×N.
The solution: unilateral observation
Interchain Events flips the model. Instead of requiring both chains to cooperate, one chain observes another’s state unilaterally using cryptographic proofs:
Remote chain (e.g. Neutron): state changes
↓ watcher reads state + fetches Merkle proof
Cosmos Hub: interchain-events contract verifies ICS-23 proof
↓ condition met
callback contract executes business logic
Key properties:
- No changes needed on the observed chain — it doesn’t know or care it’s being watched
- Zero idle cost — no polling, no validator overhead. Gas is only spent when the event actually fires
- Trustless — watchers are transporters, not witnesses. They can’t forge proofs. A malicious watcher can only fail to submit, not lie
- Callback pattern — the proven value is passed to a subscriber contract that implements whatever logic it needs
The Hub is the natural place for this: it already maintains IBC light clients for dozens of chains.
What’s deployed right now
This is not a slide deck. It’s running on Cosmos Hub mainnet:
| Chain | Contract | Code ID | Address |
|---|---|---|---|
| Cosmos Hub | interchain-events v7 | 501 | cosmos1ul3v2sh4uqgvzr2c00dz2un6373hkunk0e0z9ay9x9td3uj7qdtqqggyqc |
| Cosmos Hub | proof-callback v2 | 502 | cosmos108u0auz26aqgulr5exh4h2gadqar7qedcjj9yx7da5ramn0hlnmqj5plp2 |
| Neutron | attestation-registry | 5237 | neutron1dhw2cyurukdvl9v36lkmd7p900u89cdalytv5a7tluzhkevd89wsda4wjl |
You can query them right now:
# See existing subscriptions
gaiad q wasm contract-state smart \
cosmos1ul3v2sh4uqgvzr2c00dz2un6373hkunk0e0z9ay9x9td3uj7qdtqqggyqc \
'{"list_subscriptions":{"limit":10}}' \
--node https://cosmos-rpc.polkachu.com:443
# See callback events
gaiad q wasm contract-state smart \
cosmos108u0auz26aqgulr5exh4h2gadqar7qedcjj9yx7da5ramn0hlnmqj5plp2 \
'{"events":{}}' \
--node https://cosmos-rpc.polkachu.com:443
What the POC demonstrates
- Writing an attestation (
{"status":"approved"}) on Neutron - Creating a subscription on the Hub: “watch this key on Neutron, call my callback when
status == approved” - An off-chain watcher detects the change and fetches an ICS-23 proof from Neutron
- The watcher submits the proof to the Hub
- The contract verifies the two-level Merkle proof (IAVL + SimpleTree) against the AppHash
- The callback contract receives the full proven value and executes its logic
Supported conditions: exists, equals, json_path_equals, greater_than, less_than. The callback receives the complete proven data, so it can implement arbitrarily complex logic on its own.
How the proof works
When you query a Cosmos chain with abci_query?prove=true, you get two Merkle proofs:
- IAVL proof — proves the key/value exists in the module’s tree (e.g.
wasm) - SimpleTree proof — proves the module’s root is included in the AppHash
The contract verifies both in pure Wasm. No external dependencies, no Stargate queries needed for the verification itself.
The one thing that would make it fully trustless
Right now, the AppHash is provided off-chain by the proof submitter. The verification is real — an invalid proof is rejected — but the AppHash itself is not read from the IBC light client.
Why? Because the Hub does not expose VerifyMembership to CosmWasm contracts. This is a Gaia configuration choice, not a technical limitation. The fix is literally 2 lines in app/keepers/keepers.go:
"/ibc.core.client.v1.Query/VerifyMembership": &ibcclienttypes.QueryVerifyMembershipResponse{},
"/ibc.core.client.v1.Query/VerifyNonMembership": &ibcclienttypes.QueryVerifyMembershipResponse{},
I’ve opened an issue: cosmos/gaia#4023
This is a read-only query with zero security risk. It would allow CosmWasm contracts to leverage the light clients the Hub already maintains, making this and any future cross-chain verification use case fully trustless.
What this enables
With VerifyMembership whitelisted, any developer could deploy a contract on the Hub that:
- Cross-chain compliance gates — KYC on chain A → whitelist on chain B, with no integration work on either chain
- Conditional escrow — release payment when a third-party certifier attests completion
- DVP for regulated assets — bonds that must stay on their issuance chain, settled against USDC on Noble
- Automated treasury management — rebalance across chains when a balance threshold is crossed
- Multi-hop verification — verify state on chain C through chain B, using the Hub as a trust relay
All of these work with zero changes on the observed chains. The Hub becomes a coordination layer, not just a routing layer.
Architecture choices
- One-shot subscriptions — a subscription triggers once and is consumed. For ongoing workflows, the callback contract re-subscribes in its callback. This keeps the protocol simple and the looping logic in user code.
- Watchers are incentive-compatible — the party who benefits from the event is naturally motivated to submit the proof. Watchers serve as a reliability backstop, not the primary mechanism.
- Full value passed to callback — the callback receives the complete proven data (subscription_id, proven_value, height, plus the subscriber’s custom callback_msg). The subscriber contract decides what to do with it.
What I’m looking for
- Feedback — Does this architecture make sense? What would you build with it?
- Support for
VerifyMembershipwhitelisting — If you’re a validator or Gaia contributor, please look at cosmos/gaia#4023. This 2-line change would unlock trustless cross-chain state verification for every CosmWasm contract on the Hub. - Collaborators — The repo is open source. I’m particularly interested in:
- Enterprise use cases (compliance, settlement, treasury)
- Watcher network design and incentives
- Frontend/UX for the State Explorer (browsing any chain’s state and subscribing in clicks)
Happy to answer any questions. The code is all there, the contracts are live, you can poke at them right now.