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…

Mar 2024Otherfee3 min read

Chain

Other

Category

fee

Date

Mar 2024

Source

AuditVault

EVM Playground

Source-level debugger — step opcodes and Solidity in sync

evm-hack-analyzer

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.

Loading fork state…

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-registry mirror.


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, no anvil_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#

ImpactHIGH — excess msg.value permanently stuck on ASDRouter (no recovery path)
ProtocolCanto asD / ASDRouter
Vulnerable codeASDRouter._sendASD — success path never refunds leftover native value
Bug classMissing native refund / stuck ETH
FindingCode4rena 2024-03-canto · H-01 · #32129
Reportcode4rena.com/reports/2024-03-canto
SourceAuditVault
StatusConfirmed (Canto). Reproduced as standalone local PoC.
Compiler^0.8.24 (PoC)

TL;DR#

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

The vulnerable code#

SOLIDITY
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) or msg.value > _feeForSend (cross-chain).

Attack walkthrough#

  1. Compose path delivers ASD on Canto with msg.value = 1 ETH.
  2. _sendASD transfers ASD; uses none of the attached value.
  3. HARM: router balance is 1 ETH; refund address receives 0.

Diagrams#

sequenceDiagram participant Caller participant Router as ASDRouter participant ASD as MockASD participant Receiver Caller->>Router: sendOnCanto{value: 1 ETH} Router->>ASD: transfer(receiver, amount) ASD-->>Receiver: amount ASD Note over Router: 1 ETH stuck #59; no refund to cantoRefundAddress

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#

BASH
cd evm-hack-registry/32129-h-01-native-gas-tokens-can-become-stuck-in-asdrouter-contrac_exp
forge test -vvv

Sources#


Sources & further analysis#

Reproductions & code

Alerts & third-party analyses

  • Web3Sec X hacked database: search.
  • Rekt leaderboard: search.
  • Solodit incident search: search.

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.