# Oracle price can be manipulated

MagicLpAggregator derives LP token price from manipulable DODO pool reserves, letting a flash-loan attacker inflate DAI/USDT pair price from $2 to $67.

- Payout: Contest reward
- Severity: high
- Program: Abracadabra Money
- Credited: SpicyMeatball
- Disclosed: 2024-05-03
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2024-03-abracadabra-money-findings/issues/75
- Library page: https://bugbountylibrary.com/r/c4%3A2024-03-abracadabra-money%3AH-04
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:chained technique:source-review vuln:flash-loan vuln:oracle-manipulation

**Target:** MagicLpAggregator price oracle over DODO MagicLP pair
**Root cause:** latestAnswer() computes price from pair.getReserves() (spot reserves) instead of a manipulation-resistant source, so reserves can be skewed within a single transaction.
**Steps:**
1. Fork mainnet at block 19365773; deploy MagicLpAggregatorExt overriding _getReserves to call IDodo(pair).getVaultReserve() on DODO_POOL 0x3058...5D73.
2. Confirm baseline latestAnswer() ~ 2000502847471294054 (~$2).
3. Flash-borrow 100,000,000 DAI via DAI flash minter 0x6074...04FA.
4. In onFlashLoan, transfer borrowed DAI into the DODO pool and call `dodoPool.sellBase(address(this))` to skew reserves.
5. Read `oracle.latestAnswer()` — now ~$67 (BAD ANSWER).
6. Swap back via `sellQuote`, repay flash loan plus fee.
**How found:** Code review of latestAnswer(): noticed price is computed from pair.getReserves()/totalSupply, i.e. spot reserves, which are flash-loan manipulable; validated with a Foundry fork PoC.
**Exploitation:** Attacker flash-loans DAI, dumps it into the DODO DAI/USDT pool to shift reserves, reads the inflated MagicLpAggregator price, then uses that mispriced LP as collateral or in downstream logic before unwinding the swap and repaying the loan in the same tx.
**Insight:** When an LP-token oracle multiplies a Chainlink min-price by pool reserves/totalSupply, the reserve term is spot-manipulable — check whether reserves come from a DODO-style pool whose getVaultReserve can be skewed in one tx, and test with a flash-loan fork PoC.
