Debug
cross-L1 apps
on Avalanche ICM.
A source transaction succeeding doesn't mean the operation did. ICM Trace follows the messageID across chains and reconstructs the full execution trace — including the exact Solidity error when the destination contract reverts.
source Game L1 tx 0xab12…ef45 ✓
event SendCrossChainMessage
──────────────────────────────
relay ICM relayer · delivered
──────────────────────────────
dest Rewards L1 tx 0xcd34…gh67 ✗
event MessageExecutionFailed
──────────────────────────────
TeleporterMessenger
└─ RewardController.processReward
└─ PlayerRegistry.getPlayer
└─ REVERT
──────────────────────────────
error PlayerNotRegistered(address player)The problem
A successful source transaction doesn't mean the operation succeeded.
The source tx confirms. The relayer delivers. But the destination contract reverts — and you're left manually correlating two chains, parsing raw call trees, and decoding revert bytes by hand.
Three systems. No shared view. No automatic correlation.
How it works
One messageID. One trace.
Teleporter emits a deterministic messageID on the source chain that also appears in the destination execution event. ICM Trace uses it as the correlation key.
// source
SendCrossChainMessage
messageID: 0x9f2a…c31b
// destination
MessageExecutionFailed
messageID: 0x9f2a…c31bMulti-chain event ingestion
Subscribes to Teleporter event logs on both source and destination L1s.
messageID correlation
Links SendCrossChainMessage on the source to MessageExecuted or MessageExecutionFailed on the destination using the shared messageID.
Lifecycle reconstruction
Assembles all events — Send, Receive, Execute/Fail, Receipt — into one ordered trace.
Destination trace analysis
On failure, calls debug_traceTransaction and reconstructs the internal EVM call tree.
Solidity error decoding
Extracts the revert bytes from the failing call and ABI-decodes them using the contract interface.
Retry history
Tracks retry attempts and links them under the same messageID.
Trace example
From a vague failure to a precise error.
A game on Game L1 sends a reward message to Rewards L1. The destination contract reverts with a custom Solidity error.
messageID 0x9f2a…c31b
────────────────────────────────────────
source Game L1 0xab12…ef45 success
event SendCrossChainMessage
────────────────────────────────────────
relay ICM relayer · delivered
────────────────────────────────────────
dest Rewards L1 0xcd34…gh67 reverted
event MessageExecutionFailed
────────────────────────────────────────
call tree
TeleporterMessenger
└─ RewardController.receiveTeleporterMessage
└─ RewardController.processReward
└─ PlayerRegistry.getPlayer(0xA82…)
└─ REVERT
────────────────────────────────────────
error PlayerNotRegistered(address 0xA82f…3c91)Message lifecycle
Five Teleporter events. One trace.
ICM Trace tracks these events across both chains, correlated by messageID.
Fired when an application sends a cross-chain message. Contains the messageID and encoded payload.
Fired by the destination TeleporterMessenger when the relayer delivers the Warp message.
Fired when the destination contract handles the message successfully.
Fired when the destination contract reverts. Triggers EVM trace analysis in ICM Trace.
Delivery receipt sent back to the source chain. Closes the lifecycle loop.
MVP scope
What the initial MVP includes.
EVM-based Avalanche L1s using Teleporter. No speculative items.
Proof of concept
Validating the core technical assumption.
Can a complete cross-L1 execution trace be reconstructed using messageID as the correlation key? The PoC answers this with an intentionally broken destination contract and a custom Solidity error.
PoC steps
- 01Deploy two local Avalanche L1s
- 02Send an ICM message from the first L1
- 03Intentionally revert the destination contract with a custom Solidity error
- 04Capture the source SendCrossChainMessage event and extract the messageID
- 05Correlate the destination execution failure using the same messageID
- 06Trace the destination transaction and find the reverting call
- 07Decode the custom Solidity error
- 08Produce one structured cross-L1 execution trace
Open source
Built in public. MIT license.
Currently in technical validation — proving the core mechanism works before building the full tool. Honest work on a real problem.
Ecosystem