Harvest Flashloan Economic Attack Post-Mortem
- We take responsibility for this engineering error and are ensuring such incidents are mitigated in the future
- Formulating a remediation plan for affected users is the top priority for the coming week
- We humbly request that the funds are returned to the deployer so that it can be distributed back to the users
On October 26, 02:53:31 AM +UTC, an attacker executed a theft of funds from the USDC and USDT vaults of Harvest Finance. The attacker exploited an arbitrage and impermanent loss that influences the value of individual assets inside the Y pool of Curve.fi, which is where the funds of Harvest’s vaults were invested. The following mechanics of the protocol allowed for executing such an attack:
- Harvest’s investment strategies calculate the real-time value of assets invested in the underlying real-time protocols. The vaults use the value of the assets to calculate the number of shares to be issued to the user depositing the funds. They also use the value of the assets when users remove funds from the vaults to calculate the payout that a user should receive upon exit.
- The assets inside some of the vaults (including USDC and USDT) are deposited into shared pools of underlying DeFi protocols (such as the Y pool on Curve.fi). The assets inside such pools are subject to market effects such as impermanent loss, arbitrage, and slippage. Thus, their value can be manipulated via market trades with a large volume.
The attacker repeatedly exploited the effects of impermanent loss of USDC and USDT inside the Y pool on Curve.fi. They used the manipulated asset value to deposit funds into the Harvest’s vaults and obtain vault shares for a beneficial price, and later exit the vault at a regular share price generating a profit. The following chain of events tracks the attack:
- The attacker’s wallet address is 0xf224ab004461540778a914ea397c589b677e27bb. It deployed a contract 0xc6028a9fa486f52efd2b95b949ac630d287ce0af through which they carried out the entire attack on October 26, 2020, 02:53:31 AM +UTC. The 10 ETH for the attack was sourced through Tornado in transaction 0x4b7b9e387a79289720a0226f695913d1d11dbdc681b7218a432136cc089363c4.
- The attack itself initiated in transaction 0x35f8d2f572fceaac9288e5d462117850ef2694786992a8c3f6d02612277b0877. Within the context of a single transaction:
- The attacker sourced a large amount of USDT (18,308,555.417594) and USDC (50,000,000) from Uniswap into the attacking contract.
- The contract converted 17,222,012.640506 USDT into USDC via a swap inside Y pool. The effect of the swap was a higher value of USDC inside the Y pool as the other assets incurred impermanent loss. The smart contract obtained a roughly equivalent amount of 17,216,703.208672 USDC.
- The attacker deposited 49,977,468.555526 USDC into Harvest’s USDC vault, receiving the total of 51,456,280.788906 fUSDC at 0.97126080216 USDC per share. The price of a share before the attack was 0.980007 USDC, so the attacker decreased the value of the share by approximately 1%. The arbitrage check inside Harvest’s strategy did not exceed the threshold of 3% and thus did not revert the transaction.
- The attacker exchanged 17,239,234.653146 of USDC back into USDT via the Y pool. The result was obtaining the original lower value of USDC inside the Y pool due to reverting of the impermanent loss effect. The attacker received 17,230,747.185604 USDT back.
- The attacker withdrew from Harvest’s USDC vault trading all fUSDC shares back for 50,596,877.367825 USDC. The price of a share was 0.98329837664 USDC as the value of USDC inside the Y pool decreased. The USDC was paid entirely by the buffer of the Harvest’s USDC vault, not interacting with Y pool at all. The net profit (not accounting for the flash loan fees) was 619408.812299 USDC.The attacker repeated the process several times within the same transaction.
- After executing 17 attack transactions aimed at the USDC vault within 4 minutes, the attacker repeated the process in the analogous way for the USDT vault starting with transaction 0x0fc6d2ca064fc841bc9b1c1fad1fbb97bcea5c9a1b2b66ef837f1227e06519a6. They executed 13 transactions targeting the USDT vault within another 3 minutes.
- At the end of the process at October 26, 2020, 03:01:48 AM +UTC, the attacker transferred 13,000,000 USDC and 11,000,000 USDT from the attacking contract to address 0x3811765a53c3188c24d412daec3f60faad5f119b in transaction 0x53fae6f1d6b8a76a666a0bf7f9c724e6006465e544f89f1515b939d8911e8c58.
- The attacker transferred some funds back to the Harvest deployer in transaction 0x25119cd54a4562aa427d9770af383512f9cb5e8e4d17232ad96b69dc293a3510. This was 1,761,898.396474 USDC and 718,914.048541 USDT.
Harvest Finance acted and withdrew all the funds from the shared pools immediately after evaluating the attack and reconstructing its process. This includes DAI, USDC, USDT, TUSD as well as WBTC and renBTC. The funds are currently present in the vaults and cannot suffer from further market manipulation. The attack did not involve DAI, TUSD, WBTC and renBTC, and the depositors in these vaults were not affected.
The share price of the USDC vault decreased from 0.980007 to 0.834953, and the share price of the USDT vault dropped from 0.978874 to 0.844812, resulting in the decrease of 13.8% 13.7%, respectively. The value lost is about $33.8 million, which corresponded to approximately 3.2% of the total value locked in the protocol at the time before the attack.
The log of transactions pertaining to the attack is visible on the attacker’s address 0xf224ab004461540778a914ea397c589b677e27bb.
Immediate steps for continuity
The Harvest Finance protocol has a regular weekly schedule that needs to be maintained for the continuing benefit of all the farmers. The Harvest Finance team announced the mint of 19,637.46 FARM tokens according to the emission schedule for Tuesday October 27, 2020. The smart contract improvements requested by the community and scheduled to be released on Tuesday October 27 will be held back so that their security can be once again re-assessed in the context of the attack. The funds in the vaults that use the shared pools will remain withdrawn from the strategies until mitigation measures for this kind of an attack are in place (see the following section). Such measures, along with the infrastructure for providing remedy to the affected users, will be the focus of the next development sprint of the team. We take responsibility for this engineering error and are ensuring such incidents are mitigated in the future.
Possible mitigations in the future
The Harvest Finance team is committed to evaluating possible mitigation strategies and implementing them alongside with any necessary UX changes in the upcoming releases. We will use the upgradability feature of new vaults and timelock-based investment strategy replacement and communicate mitigation strategies well in advance of release.
The possible remediation techniques include the following options:
- Implementing a commit-and-reveal mechanism for deposits. This would remove the ability to perform deposits and withdrawals within a single transaction and therefore, make flash-loan based attacks infeasible. On users’ side, this would mean that during depositing, their tokens will be transferred into Harvest in one transaction. The users would subsequently claim their share in another transaction, ideally inside a different block. This would constitute a UX change and potentially incur a higher, yet still acceptable, gas cost for the depositors.
- A stricter configuration of the existing deposit arb check in the strategies. The current threshold was set to 3%, and it was not sufficient to protect the vault against such an attack. A stricter threshold can make such an attack economically infeasible, however, it may be limiting deposits in the case of a natural impermanent loss effects. Sunday’s events over 7 minutes show that this measure is not effective enough and thus should be seen as complementary to other ones.
- Withdrawals in an underlying asset. When users deposit into vaults that use share pools (such as the Y pool), they effectively trade their single asset for the pool asset (such as the yCurve). If the users withdrew only the underlying asset, they would be able to trade them for an asset combination as per the current market conditions. If the market was manipulated, the trade would be also subject to such manipulation, which would prevent the attacking entity from generating a profit. From a regular user’s perspective, withdrawing yCRV could be followed by conversion into a stablecoin in a separate transaction. While this requires a UX change, this could also address the social slippage problem, and thus could be beneficial for the protocol. The disadvantage of this approach is that it binds the vault withdrawal mechanism to the strategy that is currently being used: if a strategy is switched to another strategy that does not use the shared underlying pool, or uses a different pool, the asset produced by the withdrawal would change too.
- Using oracles for determining asset price. While an approximate asset price may be effectively determined from external oracles (provided by Chainlink or Maker), it would have a very loose connection to the real share price. If the value of assets inside the underlying DeFi protocol differed from the value reported by the oracle, the vault would be exposed to free arbitrage and a flashloan attack. This is not a solution for Harvest, however, oracles will be considered in the system design and possible mitigation strategies (as they have been considered up to this point).
Remediation methods for the users in USDC and USDT who lost funds
- Distribute the returned funds with a snapshot and the MerkleDistributor, we are in contact with the developers who helped to create these tools, and are actively working on building the infrastructure that can provide the remedy to the affected users. Distributing the funds is the top priority. More details on the distribution will be released once the tool is built.
- Additional remediation methods will be analyzed and voted on in governance
Attacker information and bounty
- The attacker used a fresh Ethereum address 0xf224ab004461540778a914ea397c589b677e27bb to carry out the attack
- Tornado TX 0x4b7b9e387a79289720a0226f695913d1d11dbdc681b7218a432136cc089363c4.
- Attack initiated in TX 0x35f8d2f572fceaac9288e5d462117850ef2694786992a8c3f6d02612277b0877
- The attacker transferred bitcoin to the following addresses via REN Protocol.
- The attacker then made several transactions into known Binance deposit addresses
- We are putting out a 100k bounty to the first person or team that helps to return the funds.
- If the return is done in the next 36 hours, the bounty will be 400k. Please do not doxx the attacker in the process. We strongly advise to focus all efforts on ensuring that user funds are successfully returned to the deployer.
Information about the flashloan attacker:
The attacker has proven their point. If they can return the funds to the users, it would be greatly appreciated by the community. Returning the funds to affected users is the focus.
We made an engineering mistake, we own up to it. Thousands of people are acting as collateral damage, so we humbly request the attacker to return funds to the deployer, where it will be distributed back to the users in its entirety.