Reproduced Exploit
Canto — native gas tokens stuck in `ASDRouter` on successful redemption
1. Successful lzCompose → _sendASD on same-chain delivery uses 0 of msg.value. 2. Error paths refund fully; success paths do not refund the remainder. 3. Protocol invariant: ASDRouter native balance should always be zero. 4. HARM in the PoC: 1 ETH stuck on the router after a successful on-Canto sen…
Chain
Other
Category
fee
Date
Mar 2024
Source
AuditVault
EVM Playground
Source-level debugger — step opcodes and Solidity in sync
The attack is replayed in an in-browser EVM preloaded with the exact dumped fork state. The execution tree shows every call; step by Solidity line or by opcode across all depths — source, Stack, Memory, Storage, Balances (native / ERC-20 / NFT), Transient storage and Return value stay in sync. Click a tree node, opcode, or source line to jump. No backend, no live RPC.
Source & credit. Reproduction of a public audit finding curated by AuditVault — the original finding: 32129-h-01-native-gas-tokens-can-become-stuck-in-asdrouter-contrac. Standalone Foundry PoC and full write-up: 32129-h-01-native-gas-tokens-can-become-stuck-in-asdrouter-contrac_exp in the
evm-hack-registrymirror.
Vulnerability classes: vuln/fee/missing-refund · vuln/bridge/stuck-asset · genome: frozen-funds · locked-funds · bridge-stuck-asset
Reproduction: a self-contained Foundry PoC that compiles & runs in an isolated project with only
forge-std— no fork, no RPC, noanvil_state. Full trace: output.txt. PoC: test/32129-h-01-native-gas-tokens-can-become-stuck-in-asdrouter-contrac_exp.sol.
AuditVault taxonomy: lang/solidity · platform/code4rena · has/github · has/poc · severity/high · sector/insurance · genome: frozen-funds · locked-funds · bridge-stuck-asset
Key info#
| Impact | HIGH — excess msg.value permanently stuck on ASDRouter (no recovery path) |
| Protocol | Canto asD / ASDRouter |
| Vulnerable code | ASDRouter._sendASD — success path never refunds leftover native value |
| Bug class | Missing native refund / stuck ETH |
| Finding | Code4rena 2024-03-canto · H-01 · #32129 |
| Report | code4rena.com/reports/2024-03-canto |
| Source | AuditVault |
| Status | Confirmed (Canto). Reproduced as standalone local PoC. |
| Compiler | ^0.8.24 (PoC) |
TL;DR#
- Successful
lzCompose→_sendASDon same-chain delivery uses 0 ofmsg.value. - Error paths refund fully; success paths do not refund the remainder.
- Protocol invariant:
ASDRouternative balance should always be zero. - HARM in the PoC: 1 ETH stuck on the router after a successful on-Canto send.
The vulnerable code#
if (_payload._dstLzEid == cantoLzEID) {
// just transfer the ASD tokens to the destination receiver
ASDOFT(_payload._cantoAsdAddress).transfer(_payload._dstReceiver, _amount); // @> VULN: 0 of msg.value used; remainder never refunded
} else {
// … only _feeForSend of msg.value used on cross-chain success …
}
// missing: refund address(this).balance to _cantoRefundAddress
Fix: after success, refund remaining native balance to _cantoRefundAddress.
Root cause#
Refunds exist only on failure (_refundToken). Success paths assume callers send exact value, but the contract neither requires nor refunds overpayment — so leftover CANTO/ETH is trapped with no owner recovery.
Preconditions#
- A successful asD redemption/compose path runs with non-zero
msg.value(same-chain) ormsg.value > _feeForSend(cross-chain).
Attack walkthrough#
- Compose path delivers ASD on Canto with
msg.value = 1 ETH. _sendASDtransfers ASD; uses none of the attached value.- HARM: router balance is 1 ETH; refund address receives 0.
Diagrams#
Impact#
Native gas tokens are irrecoverably stuck on ASDRouter, breaking the documented zero-balance invariant. Severity raised to High because there is no safe recovery path once success returns.
How to reproduce#
cd evm-hack-registry/32129-h-01-native-gas-tokens-can-become-stuck-in-asdrouter-contrac_exp
forge test -vvv
Sources#
- AuditVault finding #32129
- Code4rena report 2024-03-canto
- Reduced from code-423n4/2024-03-canto@15160280
_sendASD
Sources & further analysis#
Reproductions & code
- Standalone PoC + full trace: 32129-h-01-native-gas-tokens-can-become-stuck-in-asdrouter-contrac_exp (evm-hack-registry mirror).
- AuditVault finding: 32129-h-01-native-gas-tokens-can-become-stuck-in-asdrouter-contrac.
Alerts & third-party analyses
These dashboards index community alerts tweets, post-mortems, and independent write-ups. Reach them through the protocol name above to cross-check this reproduction against other analyses.