On November 30, 2021, the monox finance hack drained approximately $31 million from MonoX Finance — a decentralized exchange that had bet its entire architecture on a clever idea. Instead of requiring liquidity providers to deposit token pairs (like Uniswap), MonoX let them deposit a single token. One pool per token, with a virtual LP share. It saved capital. It also created a fatal loop: the price of MONO — the token at the heart of every swap — was calculated from the very pool an attacker could trade against. By pumping MONO from about $5 to over $8,000 inside that pool in a single transaction, the attacker convinced the protocol they had deposited $16 million worth of MONO. The protocol, trusting its own inflated math, handed over $16 million of real WETH and WBTC in return. No flash loan. No private key theft. Just circular pricing and atomic execution.
What MonoX Built and Why It Was a Juicy Target
MonoX Finance launched in 2021 as a "single-sided" automated market maker. On Uniswap, providing liquidity for WETH/WBTC requires depositing both tokens. On MonoX, you deposited just one — WETH into the WETH pool, WBTC into the WBTC pool, MONO into the MONO pool. Each pool tracked a token balance and a virtual LP token (vToken) supply. Swaps routed through MONO as intermediary: WETH → MONO → WBTC. The pitch was capital efficiency — LPs earned fees without impermanent loss from a paired asset.
By late November 2021, MonoX held roughly $64 million in total value locked across Ethereum and Polygon. Three properties made it unusually exploitable. First, it was single-pool priced — MONO's price was not set by an external oracle but derived internally as MONO pool balance / vToken total supply. Second, MONO had shallow liquidity — only ~$2 million in the MONO pool versus $60M+ in other pools, so a modest MONO trade moved the internal price violently. Third, the protocol was atomic — pump and drain executed in one transaction, so block-level price checks never saw the intermediate spike.
Timeline: Two Transactions, $31 Million, Zero Returns
The entire exploit — both chains, full drain — took about 30 minutes. No negotiation followed.
November 30, 2021, 08:43 UTC — The attacker executed the first exploit transaction on Ethereum (block 13702061). In one atomic call, they pumped MONO's internal price from ~$5 to ~$8,200 and withdrew 192 WETH and 36 WBTC — approximately $18.2 million at ETH ~$4,400 and BTC ~$57,000.
November 30, 2021, 09:15 UTC — A second exploit transaction on Polygon (block 21464005) repeated the same technique, draining WMATIC, WETH, WBTC, and USDC — approximately $12.8 million. The Polygon deployment held complementary pools; the attacker bridged proceeds to Ethereum within two hours via the Polygon PoS bridge.
November 30, 2021, ~10:00 UTC — MonoX team paused all contracts (pause() on Monoswap), confirmed the exploit, published the attacker address, and asked centralized exchanges and DEX aggregators to blacklist the tainted funds. The frontend TVL display froze at ~$32 million remaining — pools that did not contain MONO or had insufficient depth to exploit.
November 30, 2021, ~12:00 UTC — PeckShield and SlowMist published independent root-cause analyses, both pinpointing the circular getPrice() as the culprit. Community confirmed no funds had been returned.
November 30, 2021, +6 hours — The attacker began laundering: ~$2 million swapped to ETH via 1inch and deposited to Tornado Cash in 10 batches of 100 ETH each.
December 1, 2021 — MonoX published its official post-mortem, confirming the single-asset pool pricing flaw and announcing a reimbursement plan funded by treasury buyback, vesting team tokens, and a new MONO v2 token.
The Numbers: Where $31 Million Came From and Where It Went
At the time of the hack (ETH ~$4,400, BTC ~$57,000, MATIC ~$1.80), the $31 million broke down by chain in a pattern that reveals the attacker selected only pools where MONO was the counter-asset with sufficient depth:
| Chain | Stolen (approx) | Key tokens |
|---|---|---|
| Ethereum | ~$18.2M | WETH 192, WBTC 36, plus LINK/UNI/stable reserves |
| Polygon | ~$12.8M | WMATIC ~2.1M, WETH ~150, WBTC ~20, USDC ~$3M |
| Total | ~$31M | $30.8–31.4M depending on price snapshot |
Pre-hack TVL was ~$64 million. The attacker drained ~48% in two transactions. The remaining ~$32 million sat in pools that either did not use MONO as intermediary or had too little depth to absorb the inflated MONO deposit at a profitable ratio.
The attacker's economics tell a second story:
- Attacker EOA (Ethereum):
0xD5173Ba4a98BF67A665840c3fC1F5ad27e4cA1E5 - Seed capital: ~3,900 MONO (~$20K at pre-attack price), bought on Uniswap weeks before the exploit — no flash loan needed
- MONO inflated price: ~$8,200 per MONO (1,640x from ~$5) — observed inside the pool during the attack transaction
- Amplification: ~1,800x — $10K of real MONO valued as $16M+ by the protocol, enabling withdrawal of $16M in hard assets per loop
- Laundered quickly: ~$2M to Tornado Cash within 6 hours (10 × 100 ETH deposits); remainder held and slowly swapped via FixedFloat over weeks
- Returned: $0 — no negotiation, no white-hat claim, unlike Poly Network ($611M, 100% returned) or Euler ($197M, ~90% returned)
- Remaining TVL post-hack: ~$32M frozen/paused; by mid-2022, MonoX TVL had fallen below $2M as LPs withdrew
A useful contrast: the monox 31 million hack is small compared to 2021's Poly Network ($611M) or 2022's Ronin ($625M), but its technique-to-payout ratio is among the highest in DeFi — $10K in, $31M out, no flash loan, no brute force.
Root Cause: Circular Pricing — The Oracle That Priced Itself
The price manipulation defi flaw in MonoX was not a classic oracle manipulation. In most oracle attacks (Mango Markets $100M, Cream Finance $130M), the attacker manipulates an external price feed — a Chainlink price, a Uniswap TWAP, a Curve pool — and the victim protocol trusts that feed. MonoX had no external feed to manipulate. Its price was the pool.
The Single-AMM Pool Design
Each MonoX pool holds one token and a virtual LP token:
- WETH Pool: holds WETH balance + vWETH supply
- WBTC Pool: holds WBTC balance + vWBTC supply
- MONO Pool: holds MONO balance + vMONO supply
Swaps route through MONO: WETH → MONO → WBTC. The conversion rate for each leg depends on MONO's price, computed as:
` MONO price = MONO pool token balance / vMONO total supply `
Both the numerator and denominator live inside the MONO pool — the same pool the attacker can trade against. This is a circular oracle: the price is derived from the pool that the price is used to value.
The Two-Step Atomic Exploit
Step 1 — Pump MONO inside its own pool. The attacker swaps ~2,000 MONO into the MONO pool. Because the pool is shallow (~$2M depth), this large inflow spikes the MONO token balance relative to vToken supply. getPrice() reads the new balance and returns ~$8,200 per MONO — a 1,640x increase. This happens inside the same transaction; no block has passed, so no external observer or circuit breaker sees the spike yet.
Step 2 — Drain with inflated MONO. In the same transaction (atomic — either both steps succeed or both revert), the attacker calls swap or addLiquidity that deposits MONO and withdraws WETH/WBTC. The protocol values the deposited MONO at the inflated $8,200 price: 2,000 MONO × $8,200 = $16.4M of "value." It releases $16.4M worth of WETH/WBTC at real market prices. The attacker paid ~$10K for 2,000 MONO on Uniswap weeks earlier; the protocol treats it as $16M.
Repeating the loop once more per chain (the attacker ran it twice per chain) yielded the full $31M.
Why Existing Checks Failed
MonoX had a priceThreshold guard that compared the current MONO price to the previous block's price and would revert if the change exceeded a threshold. It failed for a structural reason:
The pump and drain are atomic within a single transaction. The threshold checks block N price vs block N-1 price. But the pump (MONO $5 → $8,200) and drain (withdraw WETH/WBTC) happen in internal calls within one transaction in block N. The threshold sees only the final state after the drain — MONO price has already been partially corrected by the withdrawal — not the intermediate $8,200 spike. Checking block-to-block change cannot catch intra-transaction manipulation.
This is the same atomicity bypass exploited in Harvest Finance ($24M, 2020) and understood since 2019 — yet MonoX shipped without an intra-transaction guard.
Why the Single-AMM Oracle Failed (and Why No Flash Loan Was Needed)
The single amm pool exploit pattern in MonoX differs from flash-loan price manipulation in a way that made it harder to detect and cheaper to execute.
In a typical flash-loan oracle attack, the attacker borrows millions, dumps them into a DEX pool to move the price, exploits a victim that reads that DEX price, then repays the loan — all in one transaction. The fingerprint is obvious: a huge borrow, a huge swap, a victim interaction, a repayment. Monitoring that flags flash loans catches it.
MonoX required none of that. The attacker already held MONO — bought cheaply on Uniswap weeks before, when MONO traded at $1–$5 as a low-cap governance token. The attack transaction looks like a normal large swap followed by a liquidity add — no borrow, no repay, no external pool. A flash-loan detector would see nothing anomalous.
Three design choices compounded the vulnerability:
- Shallow MONO pool vs deep victim pools. The MONO pool held ~$2M; the WETH and WBTC pools held $20M+ each. Pumping a shallow pool to inflate valuation of a deep pool is the highest-leverage configuration — small input, large output. The team held 60% of MONO supply but had not seeded the MONO pool proportionally.
- No external price anchor. Unlike Uniswap v3 (TWAP) or Curve (Chainlink), MonoX had no second price source to cross-check. The protocol trusted its own pool reserves as ground truth. When those reserves were manipulated, there was no dissenting oracle to say "MONO is not $8,200."
- Halborn flagged it as Low severity. The pre-hack audit by Halborn (September 2021) identified the vector: "Price calculation relies on internal pool state and could be manipulated if MONO liquidity is low." It was rated Low/Informational because MONO had deep liquidity on external DEXes at audit time. But external liquidity is irrelevant when the price is read from internal reserves — the attacker trades against the internal pool, not the external one. The severity model weighted "is there liquidity somewhere?" instead of "where is the price read from?"
The Attacker and the Laundering
Unlike Poly Network's gray-hat who returned $611M after 13 days of on-chain negotiation, the monox protocol hack attacker never engaged. No messages. No return. No white-hat claim.
On-chain forensics paint a picture of premeditation:
- Funding: The attacker EOA was funded via a Tornado Cash withdrawal approximately two weeks before the exploit — preserving anonymity of the seed capital.
- Accumulation: ~3,900 MONO were bought on Uniswap at $1–$5 over several days, then held. This was not opportunistic — the attacker waited for MONO to be cheap, accumulated, then struck when pool conditions were favorable.
- Simulation: The attacker drained only pools where the MONO-intermediated price gave profitable ratios. Pools with insufficient depth or non-MONO routing were untouched. This selectivity proves off-chain simulation — the attacker modeled the exploit against a forked mainnet before executing.
- Laundering: Within 6 hours, ~$2M was swapped to ETH via 1inch and deposited to Tornado Cash in 10 batches of 100 ETH. The remainder was held in the attacker EOA and slowly swapped via FixedFloat (a non-KYC instant exchange) over subsequent weeks. No centralized exchange was used directly — the addresses were blacklisted within hours.
- Identity: Unknown. Behavior suggests an experienced DeFi actor familiar with single-sided AMM math, atomic transaction construction, and AML evasion — but not a flash-loan specialist, since no flash loan was used.
Response and Aftermath
MonoX's response was fast on containment, slow on recovery.
Containment (hours): Contracts paused within ~75 minutes. Attacker addresses published. CEX/DEX blacklist requests sent. No further funds were lost — the pause was effective because the exploit required the Monoswap contract to be unpaused.
Post-mortem (24 hours): The team published a candid incident report confirming the circular pricing flaw, crediting PeckShield and SlowMist for root-cause analysis, and outlining a fix: replace getPrice() with Chainlink price feeds plus a TWAP guard, and remove the ability to price any asset from its own pool.
Reimbursement (weeks–months): MonoX announced a plan to reimburse LPs via treasury buyback (~$5M available immediately), vesting team tokens, and a new MONO v2 token. In practice, the treasury covered <20% of losses upfront; the remainder was a multi-month vesting schedule. Many LPs accepted partial compensation; some pursued legal claims. By mid-2022, MonoX TVL had fallen from $64M to <$2M as liquidity fled.
Redeployment: MonoX v2 launched on Polygon with Chainlink oracles and a Halborn re-audit. The Immunefi bug bounty was increased to $250K max. The protocol continued operating at small scale but never regained its pre-hack TVL — a common fate for DeFi protocols that lose ~50% of TVL in a single exploit.
Industry ripple: The hack became a staple in audit checklists. Trail of Bits, OpenZeppelin, and CertiK all added "never price an asset from the pool it trades in" as a critical finding. It directly influenced the adoption of TWAP and Chainlink as mandatory for any single-asset or concentrated liquidity design.
5 Defenses That Would Have Stopped the MonoX Hack
Every defense below was available before November 2021. Each alone would have prevented or contained the exploit.
1. Never price an asset from the pool it trades in — use an external oracle. MONO's price should have come from Chainlink, Uniswap TWAP, or a median of multiple sources — never from MONO pool balance / vToken supply. An external oracle cannot be pumped by trading against the victim pool. MonoX v2 adopted Chainlink; every audit since flags self-pricing as Critical.
2. Use TWAP or median price, not spot. Even with an external pool as oracle, spot price can be manipulated in one transaction. A time-weighted average price (TWAP) over 15–30 minutes requires the attacker to sustain the pump — which either costs enormously or is arbitraged away before the victim reads it. Uniswap v3's TWAP was designed precisely for this.
3. Intra-transaction circuit breaker. MonoX's block-level priceThreshold checked price change between blocks. It must also check within a transaction: if MONO's price moves >10% between internal calls in one tx, revert. This catches atomic pump-and-drain regardless of block timing. Harvest's post-mortem recommended the same fix in 2020.
4. Depth-proportional withdrawal limits. Cap any single transaction's withdrawal to a fraction of pool TVL (e.g., ≤5% per tx, ≤15% per block). Even if the price is manipulated, the attacker can only drain a small slice before the circuit breaker fires. Rate-limiting turns a $31M heist into a $1M anomaly that triggers investigation.
5. Audit severity: treat "price from own reserves" as Critical, not Low. Halborn correctly identified the vector but rated it Low because external MONO liquidity existed. The correct severity question is not "is there liquidity somewhere?" but "can the price source be manipulated through the victim contract itself?" If yes, it is Critical — shallow or deep external liquidity is irrelevant. Audit frameworks now explicitly score price source location.
Frequently Asked Questions
How much was stolen in the MonoX Finance hack? Approximately $31 million — ~$18.2M on Ethereum (WETH 192, WBTC 36, plus other reserves) and ~$12.8M on Polygon (WMATIC, WETH, WBTC, USDC). Pre-hack TVL was ~$64M, so the attacker drained ~48% in two transactions. The figure is consistently cited as $31M across MonoX's post-mortem, PeckShield, SlowMist, and Rekt.
How did the MonoX Finance hack work? The attacker exploited circular pricing in MonoX's single-asset pool design. MONO's price was calculated as MONO pool balance / vToken supply — both values inside the MONO pool itself. The attacker swapped ~2,000 MONO into the shallow MONO pool, inflating its internal price from ~$5 to ~$8,200 (1,640x). In the same atomic transaction, they deposited MONO valued at the inflated price and withdrew WETH/WBTC at real market prices. The protocol thought it received $16M of MONO and released $16M of hard assets; actual cost was ~$10K.
Did MonoX use an oracle? No — that was the problem. MonoX priced MONO from its own pool reserves (getPrice() reading MONO balance / vToken supply), not from an external oracle like Chainlink or a TWAP. There was no external feed to manipulate; the pool was the oracle. After the hack, MonoX v2 replaced this with Chainlink price feeds plus TWAP guards.
Was a flash loan used in the MonoX hack? No. Unlike most oracle manipulation attacks (Cream $130M, Mango $100M), the attacker did not use a flash loan. They had bought ~3,900 MONO on Uniswap weeks earlier at $1–$5 and used that pre-held balance to pump the pool. This made the attack cheaper and harder to detect — no large borrow/repay fingerprint, just a big swap that looked superficially normal.
Were the stolen funds recovered? No. Unlike Poly Network (100% of $611M returned) or Euler (~90% of $197M returned), $0 was returned in the MonoX hack. The attacker immediately laundered ~$2M via Tornado Cash and slowly swapped the remainder via FixedFloat. No negotiation occurred. MonoX reimbursed LPs partially from treasury (~$5M) plus vesting team tokens, but many LPs were not made whole.
Has anything like the MonoX hack happened since? Yes — the pattern of pricing an asset from its own pool recurs. Notable echoes include Inverse Finance ($15.6M, 2022 — TWAP manipulation on INV), Mango Markets ($100M, 2022 — oracle manipulation on MNGO perp), and Platypus Finance ($8.5M, 2023 — solvency check bypass with self-priced LP). All share MonoX's lesson: any time a protocol prices an asset from a pool it also trades against, the price is manipulable by definition.
Conclusion
The monox finance hack endures as DeFi's cleanest demonstration of circular pricing. The attacker did not need a flash loan, a private key, or a reentrancy bug. They needed $10K of MONO, a shallow pool, and the knowledge that price = pool balance / supply means the pool prices itself. One transaction pumped MONO 1,640x inside its own pool; the same transaction deposited that inflated MONO and withdrew $16M of WETH and WBTC at real prices. Two chains, two transactions, $31M, zero returned. The technical lesson is absolute: never price an asset from the pool it trades in, and never trust a spot price that can move 1,640x in one atomic call. The human lesson is quieter: Halborn found the bug, rated it Low, and the protocol shipped anyway. The difference between "known risk" and "patched risk" was $31 million.
