Reproduced Exploit

Mute.Io — Bond max-buyer might end up buying the max buy of the next epoch

deposit(..., max_buy=true) ignores the caller's intended epoch and always takes the current epoch's remaining max. If the epoch rolls before inclusion, the buyer silently purchases the entire next epoch.

Mar 2023Otheruntagged2 min read

Chain

Other

Category

untagged

Date

Mar 2023

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: 16038-h-01-bond-max-buyer-might-end-up-buying-the-max-buy-of-the-n. Standalone Foundry PoC and full write-up: 16038-h-01-bond-max-buyer-might-end-up-buying-the-max-buy-of-the-n_exp in the evm-hack-registry mirror.


Reproduction: self-contained Foundry PoC (forge-std only) — no fork. Full trace: output.txt.

AuditVault taxonomy: lang/solidity · platform/code4rena · severity/high · sector/dex · genome: wrong-condition · direct-drain


Key info#

ImpactHIGH — max_buy after epoch flip purchases full next-epoch allocation at worse price
ProtocolMute.Io
Bug classmax_buy uses live maxPurchaseAmount() with no epoch pin
FindingCode4rena 2023-03-mute H-01 · #16038
Reporthttps://code4rena.com/reports/2023-03-mute
SourceAuditVault
StatusAudit finding — reproduced as a standalone local synthetic
Compiler^0.8.24 (PoC)

TL;DR#

deposit(..., max_buy=true) ignores the caller's intended epoch and always takes the current epoch's remaining max. If the epoch rolls before inclusion, the buyer silently purchases the entire next epoch.

HARM: victim intended 1 wad remainder, received full 100 wad next-epoch max payout.


Root cause#

No epoch-id check on the max_buy path.

Preconditions#

Near-exhausted epoch; concurrent fill or frontrun rolls epoch before victim's max_buy lands.

Attack walkthrough#

Seed 99% filled → attacker max_buy exhausts remainder → victim max_buy takes full next epoch.

Diagrams#

flowchart TD A["Epoch 0: 1 wad left"] --> B["Victim intends max_buy of 1"] A --> C["Attacker max_buy exhausts epoch"] C --> D["Epoch 1 starts full"] B --> E["Victim max_buy lands"] D --> E E --> F["Buys full 100 wad next epoch"]

Impact#

Users over-purchase bonds at worse pricing than intended when epochs roll mid-flight.

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.