Harvest Finance Hack
The Story
On October 26, 2020, Harvest Finance, a yield farming aggregator protocol, suffered a devastating hack that resulted in the theft of approximately $34 million in USDC and USDT stablecoins. The attack took place in just 7 minutes through a series of complex transactions.
Harvest Finance offered yield farming strategies that relied on Curve Finance pools for stablecoin swaps. The attacker exploited this dependency by manipulating the price of stablecoins in the Curve y-pool, which was used by Harvest to determine the value of deposits and withdrawals.
In the aftermath, the Harvest team quickly worked to secure remaining funds and implemented changes to prevent similar attacks. They also offered a $100,000 bounty for information leading to the attacker, who later returned $2.5 million of the stolen funds. The incident led to a 65% crash in the FARM token price and significantly damaged user trust in the protocol.
This attack highlighted the risks of relying on external price calculations and the dangerous potential of flash loan attacks in interconnected DeFi systems.
Technical Analysis
The Harvest Finance attack was a flash loan price manipulation exploit that took advantage of how the protocol calculated the value of its stablecoin pools. Here's the technical breakdown:
- The attacker took out large flash loans from Uniswap (tens of millions in USDC)
- They used these funds to manipulate the price of stablecoins in the Curve y-pool by creating large imbalances
- During the price distortion, they deposited into and withdrew from Harvest's stablecoin (USDC, USDT) strategy vaults
- Due to the price manipulation, they were able to deposit at one price and withdraw at a more favorable price
- They repeated this process multiple times, draining approximately $34 million
The key vulnerability was in how Harvest calculated the share price for its vaults:
// Simplified representation of the vulnerable code
function getPricePerFullShare() public view returns (uint256) {
// Calculate total assets including those deployed in strategy
uint256 totalAssets = balance().add(
IStrategy(strategy).totalAssets()
);
// Calculate share price
uint256 totalShares = totalSupply();
if (totalShares == 0 || totalAssets == 0) {
return 1e18;
}
// Vulnerability: relies on external price that can be manipulated
return totalAssets.mul(1e18).div(totalShares);
}
The main issue was that totalAssets() called by the strategy was indirectly using Curve's stablecoin exchange rate, which could be manipulated by large trades. By creating artificial price differences in the Curve pool, the attacker could exploit these rate differences to extract value from the vault.
Lessons Learned
- DeFi protocols should implement time-weighted average price (TWAP) oracles to resist price manipulation
- Flash loan attack vectors should be rigorously tested in security audits
- Deposit and withdrawal limits can help mitigate the impact of market manipulation
- Economic security limits should be proportional to the TVL (total value locked) of the protocol
- Complex interdependencies between DeFi protocols create new attack surfaces that require careful analysis