
overview
first level title
overview
On April 13, 2023, Yearn Finance was hacked, resulting in a loss of approximately $10 million. This article will analyze the attack process and the cause of the vulnerability.
https://etherscan.io/tx/0xd55e43c1602b28d4fd4667ee445d570c8f298f5401cf04e62ec329759ecda95d
attack analysis
Here's an attack transaction:
The attacker initiated a flash loan from Balancer, borrowing 5 million DAI, 5 million USDC, and 2 million USDT:
Then on Curve, the attacker exchanged 5 million DAI for 695,000 USDT and 3.5 million USDC for 151 USDT:
The attacker calls the recommend function of IEarnAPRWithPool to check the current APR. At this point, only Aave's APR is not equal to 0:
Next, the attacker transferred 800,000 USDT to the attack contract 0x9fcc1409b56cf235d9cdbbb86b6ad5089fa0eb0f. In this contract, the attacker called the repay function of Aave: Lending Pool V1 several times to help others repay their debts, so that Aave's APR is equal to 0:
The attacker called the deposit function of yUSDT, mortgaged 900,000 USDT, and obtained 820,000 yUSDT:
Next, the attacker called the mint function of bZx iUSDC, used 156,000 USDC to mint 152,000 bZx iUSDC, and transferred it to Yearn yUSDT:
The attacker calls the withdraw function of Yearn:yUSDT to convert 820,000 yUSDT into 1,030,000 USDT. At this point, only the bZx iUSDC transferred by the attacker remains in the contract:
Next, the attacker calls the rebalance function of Yearn:yUSDT to destroy bZx iUSDC:
Then on Curve, the attacker exchanged 70,000 yUSDT for 5,990,000 yDAI, 400 million yUSDT for 4,490,000 yUSDC, and 1,240,133,244,352,200 yUSDT for 1 , 360,000 yTUSD:
Vulnerability analysis
Then call withdraw in yearn: yDAI and yearn: yUSDC respectively, withdraw 6.78 million DAI and 5.62 million USDC, and return the flash loan:
Vulnerability analysis
The most critical point in this attack is that the attacker used 100,000 USDT to mint 1,252,660,242,850,000 yUSDT. Check out the implementation of the deposit function:
It can be seen that the number of shares is related to the variable pool, the smaller the pool, the larger the share, and the value of the pool is obtained by _calcPoolValueInToken:
After the attacker calls the rebalance function, only USDC exists in the contract, but _balance() obtains the balance of USDT, and the balance of USDC is not included in it, so the pool at this time is 1 (transferred by the attacker) :
This is obviously a configuration error by the project side. The yUSDT contract should be all USDT tokens, but its fulcrum variable is the bZx IUSDC token related to USDC, so the USDC in yUSDT is not included in the balance:"newProvider != provider"Why can the attacker call the rebalance function to burn bZx iUSDC tokens? Check out the implementation of the rebalance function:
It can be seen that there will be redeem and burn operations in _withdrawFulcrum(), so we need to let
is established, where the implementation of recommend():
The attacker manipulates newProvider by controlling the return value of IIEarnManager(apr).recommend(token) to be 0:
How to make them all 0? The return value of this function is related to the calculated APR in each DeFi. Since there is no pool in Compound, bZx, and dydx, you only need to control Aave (Aave: Lending Pool Core V1):
To make it return a value of 0, the first return value of the apr.calculateInterestRates function needs to be 0:
_totalBorrowsVariable is 0, that is, Aave: Lending Pool Core V1 has no debts at this time. In order to achieve this condition, the attacker repays the debts of everyone in the pool:
Summarize
The root cause of the Yearn attack incident was a configuration error by the project party. The attackers exploited the vulnerability in a series of subtle ways, and ended up making approximately $10 million in profits.
about Us
At Eocene Research, we provide the insights of intentions and security behind everything you know or don't know of blockchain, and empower every individual and organization to answer complex questions we hadn't even dreamed of back then.