Reproduced Exploit

Toki Bridge — malformed recipient bytes silently burn tokens

The bridge accepts any non-empty recipient bytes, but the destination decoder accepts only 20-byte EVM addresses. Decode failure enters an unrecoverable branch without a retry/refund payload.

Jan 2025Otherinput-validation2 min read

Chain

Other

Category

input-validation

Date

Jan 2025

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: 64067-h-01-recipient-bytes-silent-burn-when-non-20-byte-payloads-p. Standalone Foundry PoC and full write-up: 64067-h-01-recipient-bytes-silent-burn-non-20-byte_exp in the evm-hack-registry mirror.


Vulnerability classes: vuln/input-validation/wrong-type · vuln/bridge/missing-validation · vuln/dos/frozen-funds

Reproduction: local synthetic Foundry reduction; the complete passing trace is in output.txt.

Key info#

FieldValue
LossA four-byte recipient burns 100 source units and credits no destination account.
Vulnerable contractTokiBridge.transfer / onRecv in test/64067-h-01-recipient-bytes-silent-burn-non-20-byte.sol
Attacker EOA0x1111111111111111111111111111111111111111
Attack contractExploit
Attack txLocal Foundry Exploit.run()
Chain · block · dateEthereum model · block 0 · synthetic
CompilerSolidity ^0.8.24
Bug classRecipient payload type/length validation failure

TL;DR#

The bridge accepts any non-empty recipient bytes, but the destination decoder accepts only 20-byte EVM addresses. Decode failure enters an unrecoverable branch without a retry/refund payload.

Background#

Bridge source accounting is debited before an IBC packet is delivered. Inputs that the destination cannot decode must be rejected at source or persisted for a recoverable refund.

The vulnerable code#

SOLIDITY
function transfer(bytes calldata to, uint256 amount) external {
    require(to.length > 0 && to.length <= 1024, "recipient length");
    // @> VULN: arbitrary non-empty bytes are debited as if an address.
    sourceBalance[msg.sender] -= amount;
}

Root cause#

_validateToLength checks only broad bounds while destination decodeAddress requires exactly 20 bytes. The failure path emits no recoverable transfer payload.

Preconditions#

  • A user submits a recipient payload of a length other than 20 bytes.
  • Source accounting is burned/escrowed before destination decoding.
  • Destination failure handling does not persist a refund.

Attack walkthrough#

  1. Seed the source account with 100 units and transfer to 0xdeadbeef.
  2. Destination onRecv returns false for the four-byte payload.
  3. Both balances are zero, proving silent loss at output.txt:4.

Diagrams#

flowchart LR U[User: 100] --> S[Source transfer accepts 4 bytes] S --> P[Packet arrives] P --> D[20-byte decode fails] D --> L[Unrecoverable; no refund]

Remediation#

Require to.length == 20 for EVM destinations (or decode to address at source). If arbitrary payloads are supported, persist a complete retry/refund message on failure.

How to reproduce#

BASH
cd evm-hack-registry/64067-h-01-recipient-bytes-silent-burn-non-20-byte_exp
forge test -vvvvv

Sources#

Reference: https://github.com/shieldify-security/audits-portfolio-md/blob/main/Toki-Bridge-Security-Review.md


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.