4 min read

PancakeBunny hacked for $40M+

PancakeBunny hacked for $40M+

It’s a nice feeling to finally go to sleep after a hard day and wake up to $40M+ gone from another Binance Smart Chain DeFi protocol…BSC DeFi doesn’t have an easy time right now. This hack’s a “nice” addition to the growing amount of already stolen funds from different DeFi Applications.

The title gave it away, but the DeFi App in question is PancakeBunny. $40M+ were stolen, around 114k of WBNB and 697k of Bunny tokens. Exploit was possible because of how the protocol uses PancakeSwap AMM for its asset price calculation. In bugs like this, flashloans are the go-to way to manipulate the price of AMM pools which affects the price oracle.

For those who don’t understand what I’m talking about,  flash loans, as the name suggests, is a way to borrow a large amount of money from a different protocol like Aave or DyDx or on BSC side, ForTube, or PancakeSwap.finance,  for a certain fee. The caveat is it needs to be returned within one transaction block. If not, the transaction will be reversed.

This could be used in several ways, but most people are using it for arbitrage. Second I think the most popular and notorious way of using them is to break some other protocols or manipulate the price of an Oracle, and that’s what has happened in the BunnyFinance case.

Using a FlashLoan, an attacker can swap any amount of token A for token B on different AMM pools, thus making it unbalanced. That will allow swapping Token A for Token B for a much lower price. More on this on Uniswap Docs.

Uniswap
Automated liquidity protocol on Ethereum

How the Attack was performed?

An attacker used eight flash loans to fuel his exploit. Seven flash loans were from the PancakeSwap WBNB pools and one from ForTube Bank for BUSDT.

Borrowed funds were put into the WBNB<>BUSDT pool (7,7K WBNB and 2.9M BUSDT) and ~144k of LP Tokens were minted.

Next, the 2.3M WBNB were swapped for 3.8 BUSDT through the above pool, making the pool unbalanced and raising the value of LP Tokens.

The attacker then called getReward() function from protocol and minting 6.9M Bunny Tokens through the higher valuation of LP Tokens previously minted. The Extra 1,045M Bunny tokens you see are a reward for the dev team (fee).

At the last step, the flash loans are returned and paid for.

The attacker even left a note in exploit TX.

Vulnerability

The issue was with how the PancakeBunny-Finance was calculating minting reward. getReward() calls _minter.mintFor()

https://github.com/PancakeBunny-finance/Bunny/blob/main/contracts/vaults/VaultFlipToFlip.sol#L249

mintFor() checks for a current price of an asset.

https://github.com/PancakeBunny-finance/Bunny/blob/main/contracts/bunny/BunnyMinterV2.sol#L191

If the asset pair is using WBNB, then it takes the current
totalSupply of LP Tokens of that pair and amount of WBNB in the pool, inflated by the large amount of WBNB because of the swap in WBNB<>BUSDT pool.

https://github.com/PancakeBunny-finance/Bunny/blob/main/contracts/dashboard/calculator/PriceCalculatorBSC.sol#L108-L109

Because of this, the value of LP Tokens is much increased, and an attacker can mint a higher amount of Bunny Tokens.

How to guard against price manipulation?

As the PancakeSwap is a direct fork of the UniswapV2, UniswapV2 offers an example of Time-Weighted Average Price (TWAP). As we can read from Uniswap docs:

The TWAP is constructed by reading the cumulative price from an ERC20 token pair at the beginning and at the end of the desired interval. The difference in this cumulative price can then be divided by the length of the interval to create a TWAP for that period.

More on that here. They even provide an example of how to use TWAP.

Uniswap/uniswap-v2-periphery
🎚 Peripheral smart contracts for interacting with Uniswap V2 - Uniswap/uniswap-v2-periphery
https://github.com/Uniswap/uniswap-v2-periphery/blob/master/contracts/examples/ExampleOracleSimple.sol

AMM-Based Price Oracle can lead to massive losses, as we learned during this hack and many other protocols in 2020 had learned. There are available solutions to this issue if someone wants to use on-chain oracle. Still, developers need to look actively for a solution for this problem and be aware of any vulnerabilities.


Big Thanks to FrankResarcher for the initial analysis of the exploit 👌