On March 9, 2021, the DODO decentralised exchange suffered an exploit affecting four V2 Crowdpools — total losses initially around $3.8 million, of which approximately $1.9M was front-run by MEV arbitrage bots (some of whom returned funds). The root cause: the Crowdpool's init() function could be called again on already-initialized pools, with no re-initialization guard.
What happened
DODO's V2 Crowdpools were liquidity pools initialized via an init() function that set the pool's parameters — including which tokens the pool traded and the price relationship between them. As is standard for initialization functions, init() was supposed to be called exactly once, at pool creation.
The fatal flaw: DODO's Crowdpool contract did not guard against init() being called a second time. An attacker could:
- Call
init()again on an existing, funded Crowdpool, passing in a fake token they controlled as one of the pool's assets and setting an arbitrary price relationship. - The pool now believed it was trading the real asset against the attacker's worthless fake token at an attacker-chosen rate.
- Use a flash loan to "trade" the fake token into the pool, extracting the pool's real assets at the manipulated rate.
- Repeat across the four affected Crowdpools.
The total extractable was around $3.8M. But the attacker's transactions were visible in the public mempool, and MEV arbitrage bots front-ran approximately $1.9M of the exploit — replaying the attack to extract funds before the original attacker could. Some of these front-running bots were operated by white-hats who returned the funds; others kept them.
Aftermath
- DODO paused the affected Crowdpools and shipped a fixed contract with proper re-initialization guards.
- DODO published a resolution post and worked to recover and return front-run funds; a meaningful portion was recovered through MEV-bot operators returning funds and through negotiation.
- The protocol's core AMM was unaffected — only the Crowdpool feature.
Why it matters
The DODO incident is one of the earliest re-invokable-initializer exploits in DeFi history, predating the better-known Audius (2022) and continuing the lineage from Parity Multisig (2017). The bug class — an init() or initialize() function with no guard against being called twice — is one of the most-documented in Solidity, and one of the most-repeated.
The structural lessons:
-
Every initialization function needs an explicit one-shot guard — OpenZeppelin's
initializermodifier, aninitializedboolean, or equivalent. The pattern is one line of code. -
The public mempool turns every exploit into a race. DODO's incident is one of the earliest clear demonstrations that MEV bots front-running an attacker is now part of the incident dynamics — sometimes for the worse (the bots keep the funds), sometimes for the better (white-hat bots return them). The protocol that gets exploited often has the least control over where the funds end up.
-
Feature-level isolation limits blast radius. DODO's core AMM was unaffected because the bug was confined to the Crowdpool feature. Protocols that isolate new features behind separate contracts (rather than expanding monolithic core contracts) contain the damage when a new feature ships with a bug.
DODO recovered and continued as a meaningful DEX — one of the relatively few protocols from the 2021 exploit wave that survived its incident with reputation largely intact, in part because of the transparent resolution process and the fortuitous (if chaotic) MEV-bot partial recovery.
Sources & on-chain evidence
- [01]halborn.comhttps://halborn.com/explained-the-dodo-dex-hack-march-2021/
- [02]coindesk.comhttps://www.coindesk.com/tech/2021/03/09/dodo-dex-drained-of-38m-in-defi-exploit
- [03]dodoexchange.medium.comhttps://dodoexchange.medium.com/dodo-incident-which-affected-4-crowdpools-and-our-resolution-9da0298c2b65