# PancakeBunny: LP price oracle manipulation mints 6.97M BUNNY

PancakeBunny's VaultFlipToFlip valued LP tokens via manipulable PancakeSwap spot reserves, letting an attacker flash-loan, skew the WBNB-USDT pool, and mint 6.97M BUNNY.

- Payout: Real-world hack
- Severity: critical
- Program: PancakeBunny
- Analysis by: DeFiHackLabs
- Disclosed: 2021-05-19
- Write-up quality: 8/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2021-05/PancakeBunny_exp.sol
- Library page: http://bugbountylibrary.com/r/dhl%3A20210519-pancakebunny
- Tags: area:web3 domain:web3 impact:funds-loss kind:incident platform:defihacklabs sev:critical tech:evm tech:solidity technique:chained vuln:flash-loan vuln:oracle-manipulation vuln:reward-distribution

**Target:** VaultFlipToFlip vault reward calculation using PancakeSwap LP reserves
**Root cause:** The vault computed LP token value from live PancakeSwap pool reserves (BNB-BUSDT/BNB-BUNNY), which are spot-manipulable within a single transaction. Inflated LP valuation yielded outsized BUNNY rewards.
**Steps:**
1. Flash-loan WBNB from 7 PancakeSwap pools (WBNB+CAKE, +BUSD, +ETH, +BTCB, +SAFEMOON, +BELT, +DOT) and 2.96M USDT from Fortube Bank.
2. Deposit 2.96M USDT + 7886 WBNB into WBNB+BUSDT pool, minting 144.45K LP tokens.
3. Swap 2.32M WBNB for 3.83M BUSDT via the WBNB+BUSDT pool to skew reserves and inflate LP token valuation.
4. Call `flip.getReward()` to claim rewards; inflated LP value yields 6.97M BUNNY.
5. Sell BUNNY, crashing price from $146 to $6, then repay all flash loans.
**How found:** Post-mortem analysis (Peckshield) identified that the vault's reward calculation read PancakeSwap LP reserves directly, making it flash-loan manipulable; Haechi noted their audit had warned the helper function was weak to flash loans but the exploited contracts were new and unaudited.
**Exploitation:** Attacker stacked 8 flash loans (~2.3M WBNB + 2.96M USDT), deposited into the vault, dumped WBNB into the WBNB-USDT pool to inflate the LP token price the vault used for reward math, claimed 6.97M BUNNY via getReward(), sold it, and repaid loans — netting ~$45M.
**Escalation:** Chained 7 PancakeSwap flash loans plus a Fortube Bank flash loan to accumulate enough capital to move the pool reserves far enough to skew the oracle.
**Insight:** When a vault prices LP tokens from live AMM reserves, a single-tx reserve skew inflates reward math — check whether reward/valuation functions read spot reserves rather than TWAP or a manipulation-resistant source.

## Proof of concept (copied exactly from the original report)

**Zap 1 WBNB into vault and trigger harvest**

```
zap.zapInToken(WBNB, 1e18, address(WBNBUSDTv2));
        uint256 lpamount = IERC20(address(WBNBUSDTv2)).balanceOf(address(this));
        flip.deposit(lpamount);

        emit log_string("After X blocks, the keeper of VaultFlipToFlip calls harvest()");

        cheat.warp(1_655_908_339);
        cheat.roll(7_556_391);

        // Keeper needs to call flip.harvest() so that flip.earned(address(this)) > 0
        cheat.prank(keeper);
        (bool success,) = address(flip).call(abi.encodeWithSignature("harvest()"));
        require(success, "flip.harvest() fails");
```

