
Yearn Finance Attack Incident Analysis
TechFlow Selected TechFlow Selected

Yearn Finance Attack Incident Analysis
This article will analyze the attack incident on Yearn Finance, including the attack process and the causes of the vulnerability.
Overview
On April 13, 2023, Yearn Finance was hacked, resulting in a loss of approximately $10 million. This article analyzes the attack process and the root cause of the vulnerability.
Attack Analysis
Below is the attack transaction:
https://etherscan.io/tx/0xd55e43c1602b28d4fd4667ee445d570c8f298f5401cf04e62ec329759ecda95d
The attacker initiated a flash loan from Balancer, borrowing 5 million DAI, 5 million USDC, and 2 million USDT:

Then, on Curve, the attacker swapped 5 million DAI for 695,000 USDT and 3.5 million USDC for 151 USDT:

The attacker called the recommend function of IEarnAPRWithPool to check the current APR. At this point, only Aave's APR was not equal to 0:

Next, the attacker transferred 800,000 USDT to the attack contract 0x9fcc1409b56cf235d9cdbbb86b6ad5089fa0eb0f. Within this contract, the attacker repeatedly called Aave Lending Pool V1’s repay function to repay others’ debts, causing Aave's APR to become 0:

The attacker called yUSDT’s deposit function, deposited 900,000 USDT, and received 820,000 yUSDT:

Next, the attacker called bZx iUSDC’s mint function, used 156,000 USDC to mint 152,000 bZx iUSDC, and transferred it into Yearn’s yUSDT vault:

The attacker called Yearn’s yUSDT withdraw function, exchanging 820,000 yUSDT for 1,030,000 USDT. At this point, only the attacker’s transferred bZx iUSDC remained in the contract:

Next, the attacker called Yearn’s yUSDT rebalance function to burn the bZx iUSDC tokens:

Then, the attacker transferred 1/e6 USDT to the yUSDT contract and called the deposit function, depositing 10,000 USDT and receiving 1,252,660,242,850,000 yUSDT:

Then, on Curve, the attacker swapped 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:

Then, by calling withdraw in yearn: yDAI and yearn: yUSDC respectively, the attacker withdrew 6.78 million DAI and 5.62 million USDC, and repaid the flash loan:

Vulnerability Analysis
The most critical part of this attack was when the attacker deposited 10,000 USDT and received 1,252,660,242,850,000 yUSDT. Examining the implementation of the deposit function:

We can see that the number of shares is related to the variable pool — the smaller the pool, the larger the shares. The value of pool is obtained via _calcPoolValueInToken:

After the attacker called the rebalance function, only USDC remained in the contract. However, _balance() retrieves the USDT balance, meaning USDC balances are not included. Therefore, at this moment, pool equaled 1 (the amount transferred by the attacker):



This was clearly a configuration error by the project team. The yUSDT contract should have contained only USDT-type tokens, but its fulcrum variable pointed to bZx iUSDC, a USDC-related token. As a result, USDC holdings in yUSDT were not counted toward the balance:


Why was the attacker able to call the rebalance function to burn the bZx iUSDC tokens? Let's examine the implementation of the rebalance function:



We can see that _withdrawFulcrum() contains redeem and burn operations, so we need "newProvider != provider" to be true. The recommend() function determines newProvider as follows:

The attacker manipulated newProvider by controlling the return value of IIEarnManager(apr).recommend(token) to make it zero:

How could they make it zero? The function’s return value depends on calculated APRs across various DeFi protocols. Since there were no pools in Compound, bZx, or dYdX, the attacker only needed to manipulate Aave (Aave: Lending Pool Core V1):

To make the return value zero, the first output of apr.calculateInterestRates must be zero:

That is, currentLiquidityRate must be zero. This value depends on _totalBorrowsStable and _totalBorrowsVariable; when both are zero, currentLiquidityRate becomes zero:


_totalBorrowsVariable being zero means no one had outstanding debt in Aave: Lending Pool Core V1. To achieve this, the attacker repaid all existing debts in the pool:

Finally, with _totalBorrowsVariable set to zero, the attacker was able to call the rebalance function and burn the bZx iUSDC tokens:

Summary
The root cause of this Yearn Finance attack was a configuration error in the project’s smart contract. The attacker exploited this flaw through a series of sophisticated maneuvers, ultimately profiting approximately $10 million.
Join TechFlow official community to stay tuned
Telegram:https://t.me/TechFlowDaily
X (Twitter):https://x.com/TechFlowPost
X (Twitter) EN:https://x.com/BlockFlow_News














