Lately, we’ve been having some not quite interesting hacks that really haven’t pushed me to make in-depth research. That was until yesterday, the 17th of April 2022. This hack was quite sophisticated. It was done by flash-loaning enough collateral to become a supermajority voter and create a proposal (BIP) to effectively rug the protocol in a single tx. The hacker managed to execute this by combining some known techniques along with sneaking in some malicious changes into governance. This hack was so complex that at first, CT was quiet about it.
But as usual, you know your boy got your back right??
Trust me, I’ve got all the juice you need. Sit back and read.
Today, I’m going to be making a post-mortem analysis explaining how the protocol got hacked, and what takeaways we have from this.
So, without further ado,…
To those of you who might not be aware, Beanstalk is a credit-based stablecoin protocol that uses a combination of a decentralized price oracle, a decentralized governance mechanism, and a decentralized credit facility to incentivize a peg to 1 USD. But by now, you probably know that a lot of these projects have a lot of hidden vulnerabilities and with the right amount of incentives, hackers would find them. If a black hat hacker finds it first, the money goes poof!!!
That is exactly what happened. Beanstalk had a voting mechanism vulnerability. The emergencyCommit() requirement bipVotePercent is based on balance.
In this case, if a person has 2/3rds of the vote, that person can actually stop the protocol and can also pass any Beanstalk Improvement Proposal (BIP) at any time.
This allows anyone to pass any proposals if they could flashloan just enough collateral to become a supermajority. This was what the hackers exploited. With a flashloan of $1b, they were able to become a supermajority, pass a BIP, and rug liquidity.
In this hack, users lost:
36M BEAN (36M)
0.54 ETH-BEAN UNI-v2 LP tokens ($33M in ETH and $32M in BEAN)
79.2M BEAN3CRV-f Curve LP tokens
1.6M BEAN-LUSD Curve LP tokens
Of course, by now, you should know how these hacks all begin. The hackers’ wallet was funded via Tornado Cash.
After being funded, they created a BIP-18 proposal to donate 250k BEAN to Ukraine.
Then, they used a flash loan to get:
350M DAI, 500M USDC, and 150M USDT from Aave
32M BEAN from Uniswap v2
11.6M LUSd from Sushiswap
These tokens were used to add liquidity to curve pools with BEAN for the governance voting. The borrowed DAI/USDC/USDT was used as collateral in the Curve 3Pool to obtain 3Crv, and some of the 3Crv was exchanged for LUSD. Next, the attacker deposited the $3Crv tokens into another contract in order to generate another token called BEAN3CRV-f. This was followed by a deposit of the 32m $BEAN tokens and the 25m $LUSD into yet another contract to generate a different token called BEAN3LUSD-f.
At this point, the attacker only really had two token stacks left: BEAN3CRV-f and BEAN3LUSD-f. But why does the attacker want these obscure tokens?
The attacker wants it because they're the key to controlling $BEAN itself. Like I said earlier, $BEAN is designed to have a governing system on Ethereum. In this system, users can get access to a special type of asset called "Seeds" which acts like voting power in the system. The more Seeds you have, the more voting power you have. Users with Seeds can vote on proposals that do pretty much anything. This is intended to give the system a way to evolve. Users with the most invested in the system are supposed to get control over the way that the system can change. In hindsight, that was a flaw.
BEAN3CRV-f and BEAN3LUSD-f can be converted directly into Seeds, giving the attacker a huge amount of voting power. In fact, the flash loan and $BEAN stew allowed the attacker to control more than 70% of the total number of Seeds. This was more than the 66% threshold required to execute an "emergency" governance action. With more than 2/3rds of the voting power, the attacker was able to siphon absolutely everything from the $BEAN contract, about $180m worth of assets.
The 3Crv/BEAN/LUSD was added to BEAN3CRV-f and BEANLUSD-f, respectively to get the corresponding BEAN3CRV-f and BEANLUSD-f certificates.
Then, they deployed and voted for a fake BIP-18 that moved the BEAN/WETH-BEAN LP/BEAN3CRV-f/BEANLUSD-f tokens from the contract to the exploiter. After removing liquidity, they repaid the flashloans, and were left with 24.8 wETH at a value of close to $76m which went straight to tornado cash.
The leading cause of this incident was the fact that there was no time interval between the voting and execution of the proposal. The attacker could directly execute the malicious proposal without community review after voting. The first proposal (proposal #18) steals all the money in the contract. The next proposal (proposal #19) sends $250k worth of $BEAN to the Ukraine donation address.
BeanstalkFarms says it paid 250k $USDC to be "continuously audited" by @Omniscia_sec. But the auditor says that the exploited code was not audited by them. They claim that their SOWs clearly specified the exact commits that were audited. They also released their own post-mortem analysis and claims that they were not auditing every new BIP after the retainer. They only audited the initial implementation of the protocol. The problem here is that the audit was completed only 15 days before the exploit and they passed a governance system that, in their words, “allows the caller to circumvent the usual lifecycles of a proposal and immediately execute it” -“The voting system of Beanstalk by design permitted votes to be cast retroactively on any active BIPs”.
So, who should we believe?
My recommendations:
The right to vote needs to be locked in a governance process. With all the hacks we’ve been seeing recently, it is important to have a “time-locked” wait time in between proposals/voting/execution so the community can strictly review it.
Never have more than 2% of your net worth in a protocol. Especially these smaller protocols and farms that are much more dangerous. Never go far out on the risk curve with a large % of your stack as it’s not worth the additional APY.
Special thanks go to:
https://etherscan.io
https://tenderly.co
https://ethtx.info
They made this piece possible.
Thanks for the recommendation