# Makina: Curve spot-price oracle manipulation drains DUSD pool

Makina's Caliber/Machine oracle read Curve pool spot prices; attacker flash-loaned 280M USDC to skew DUSD and MIM pools, inflating DUSD, then drained ~5.1M USDC.

- Payout: Real-world hack
- Severity: critical
- Program: Makina
- Credited: DeFiHackLabs
- Disclosed: 2026-01-20
- Write-up quality: 7/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2026-01/makina_exp.sol
- Library page: https://bugbountylibrary.com/r/dhl%3A20260120-makina
- Tags: domain:web3 impact:funds-loss kind:incident platform:defihacklabs sev:critical tech:evm tech:solidity technique:chained vuln:flash-loan vuln:oracle-manipulation

**Target:** Caliber/Machine oracle + Curve DUSD/USDC and MIM/3Crv pools
**Root cause:** Makina's accountForPosition/updateTotalAum derived DUSD price from manipulable Curve pool spot reserves rather than a manipulation-resistant oracle.
**Steps:**
1. Flash-loan 280M USDC.
2. `add_liquidity` 100M USDC + `exchange(0,1,10M)` into DUSD/USDC Curve pool to pump DUSD price.
3. `add_liquidity` 170M USDC into 3Pool to get 3Crv.
4. Add 3Crv to MIM/3Crv pool and `exchange(1,0,120M)` to pump MIM.
5. Call Makina `accountForPosition` and `updateTotalAum` with crafted merkle-proof command payload to record inflated DUSD price.
6. Swap DUSD and LP back to USDC via `exchange(1,0)` and `remove_liquidity_one_coin`.
7. Unwind MIM/3Crv and 3Pool positions back to USDC; repeat run twice; repay flash loan.
**Exploitation:** Attacker flash-loaned 280M USDC, skewed two Curve pools to inflate DUSD and MIM, pushed the manipulated prices into Makina's accounting via accountForPosition/updateTotalAum, then redeemed inflated DUSD/LP for USDC, netting ~5.1M USDC. A MEV bot front-ran the real attacker's tx.
**Escalation:** Ran the exploit loop twice within one flash loan to compound profit.
**Insight:** When a protocol's AUM/position accounting calls Curve `get_dy`/reserves directly, a single large add_liquidity+exchange in that pool moves the recorded value; check whether updateTotalAum/accountForPosition can be permissionlessly re-poked after a pool skew.
