Reproduced Exploit
Barter DAO: A malicious taker re-enters swap() for a second same-maker order sharing the same takerTok
Chain
Other
Category
untagged
Date
Jan 1970
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: 63500-double-order-attack-via-callback-mechanism-mixbytes-none-bar. The historical source/toolchain is unavailable; this entry is documentation only and claims no executable Forge PoC.
Vulnerability classes: vuln/theft
Reproduction: a faithful minimal reproduction of the vulnerable finding — the vulnerable function is reproduced verbatim (marked
@>) with faithful minimal doubles; local deploy, no fork.
Root cause#
A malicious taker re-enters swap() for a second same-maker order sharing the same takerToken during the callback; that single payment satisfies the first order's post-callback balance-delta check too, so the taker collects makerToken from both orders while paying takerToken for only one — netting 100 STOLEN-MAKER (order #1's makerToken) for free while the maker is robbed of one full order.
order.takerToken.balanceOf(address(order.maker));
// Check that callback provided enough tokens
if (balanceAfter < balanceBefore + actualTakerAmount) { // @> post-callback balance-delta check with NO reentrancy guard: a concurrent same-maker order paying the SHARED takerToken satisfies this order's check too
revert ReceivedLessThanMinReturn(
balanceAfter,
Why it's exploitable here#
A malicious taker re-enters swap() for a second same-maker order sharing the same takerToken during the callback; that single payment satisfies the first order's post-callback balance-delta check too, so the taker collects makerToken from both orders while paying takerToken for only one — netting 100 STOLEN-MAKER (order #1's makerToken) for free while the maker is robbed of one full order.
Attack path#
Marked-line walkthrough (Playground)#
The EVM Playground pins each step to the exact executed source line in 0xe3a787a4e4…:
- L119 — Pay maker token to taker: Sends the maker's tokens to the taker up front, before the taker callback — so both orders pay out before payment is checked.
- L124 — Determine taker amount owed: Selects what the taker must pay for this order — the partial
filledtakerAmountor the fulltakerAmount. - L136 — Contract-wide balance-delta check: Root cause: payment is verified by a whole-contract balance delta, not per order, so one re-entrant deposit satisfies two orders' checks at once.
- L137 — Revert on underpayment: Reverts if the measured balance increase falls short — but one shared payment passes both orders, so this never fires.
- L139 — Expected post-swap balance: The threshold the contract balance must reach; being a global snapshot, the double-order payment gets double-counted against it.
- L147 — Minimal reentrancy guard: Setup: a stripped reentrancy guard is defined, yet the taker re-enters
swap()on a DIFFERENT order, a path this guard does not cover. - L155 — Guard status check: The guard requires
_status == 1; the double-order attack succeeds through the balance-delta flaw, not by evading this check.
PoC#
Registry (Foundry, local deploy — verbatim vulnerable source + harm-asserting test + negative control):
cd 63500-double-order-attack-via-callback-mechanism-mixbytes-none-bar_exp
forge test -vvv
The browser Playground replays the same synthetic opcode-for-opcode and measures the harm: A malicious taker re-enters swap() for a second same-maker order sharing the same takerToken during the callback; that single payment satisf. Both gates are green (registry forge test PASS + Playground _verify-poc VERDICT: PASS).
Sources & further analysis#
Reproductions & code
- No executable Forge reproduction is claimed; the historical source/toolchain was unavailable for this finding.
- AuditVault finding: 63500-double-order-attack-via-callback-mechanism-mixbytes-none-bar.
- Upstream DeFiHackLabs PoC directory: src/test.
Alerts & third-party analyses
- DeFiHackLabs incident explorer: search "Barter DAO: A malicious taker re-enters swap() for a second same-maker order sharing the same takerTok".
- 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.