Root Cause
Makina Finance's updateTotalAum() function suffered from three compounding design flaws that together allowed single-transaction oracle manipulation:
- No access control — the function was
externalwith no role restriction, allowing any caller to trigger an AUM recalculation - Synchronous spot-price reads — the function read Curve pool prices atomically within the same block, making it fully exploitable within a flash-loan transaction
- Pre-approved Weiroll execution paths — included price-sensitive functions with no time delay or sanity-check gate
// CVE-2026-0120 — CRITICAL (CVSS 9.8)
// Ethereum Mainnet, Block 19847623
function updateTotalAum() external {
// FLAW 1: No access control — any EOA or contract can call
uint256 totalValue = 0;
for (uint i = 0; i < positions.length; i++) {
// FLAW 2: Reads Curve spot price synchronously — same-block manipulation
totalValue += pool.calc_withdraw_one_coin(positions[i], 0);
}
// FLAW 3: No circuit breaker, no TWAP, no sanity check
totalAum = totalValue;
}
The Cantina CTF audit explicitly excluded the oracle update mechanism from scope; it became the sole exploited surface post-audit.
Attack Steps
| Step | Action | Detail |
|---|---|---|
| 1 | Flash-borrow 280M USDC from Morpho + Aave | Zero-collateral, same-transaction |
| 2 | Dump 170M USDC into DUSD/USDC Curve pool | Artificially inflates DUSD spot price |
| 3 | Call permissionless updateTotalAum() | Reads manipulated Curve price — AUM inflated 165× |
| 4 | Withdraw protocol assets at false valuations | $4.13M (1,299 ETH) extracted |
| 5 | Convert residual DUSD → USDC; repay flash loans | ~$970K in fees paid |
| MEV | Searcher decompiles, replicates, front-runs attacker | Bot captures ~$4.1M; original attacker nets minimal |
MEV note: An MEV searcher decompiled the attack contract in-block, replicated the strategy, and front-ran the original attacker — capturing approximately $4.1M. Makina sent an on-chain message offering a 10% whitehat bounty; the bot operator eventually returned 920.7 ETH, keeping 102.3 ETH.
Impact
- Protocol loss: $4.13M from the DUSD/USDC stablecoin pool
- Net attacker gain: Near-zero after MEV front-run
- Chain: Ethereum Mainnet (Block 19847623, January 20, 2026)
- CVE: CVE-2026-0120 (CVSS 9.8)
- Attack vector: Flash loan oracle manipulation via permissionless price feed
Lessons for Auditors
- Never exclude oracle update functions from audit scope — even if labeled "administrative," any permissionless function that affects price feeds or AUM is an attack surface.
- Spot AMM prices ≠ safe oracles —
calc_withdraw_one_coinand similar same-block reads from Curve, Uniswap V2, or Balancer pools are trivially manipulable with flash loans; require a TWAP with ≥6 observations and a ≥30-minute window. - Restrict every AUM/price-update path — gate behind an authorized keeper role (
AccessControl,Ownable) or a decentralized oracle network. - Implement circuit breakers — a 10% maximum AUM change per update would have blocked the 165× inflation with zero false positives under normal conditions.
- Audit scope exclusions are liability — any exclusion touching price-sensitive functions should be escalated to protocol risk, documented publicly, and prioritized in follow-up audits.