- An attack vector in the GenLevComp strategy type was disclosed through Yearn's security process.
- Yearn's yvDAI vault had two potentially affected GenLevComp strategies attached.
- In the event of a successful exploit, an attacker would have been able to liquidate an affected strategy's entire debt position on Compound and potentially capture liquidation fees.
- No funds have been lost. The vulnerable strategies were successfully wound down, and are in process of being fixed.
- Yearn's security team has decided to award the disclosing security researcher, xyzaudits, with the maximum bounty reward of $200,000.
A security researcher, xyzaudits, contacts Yearn's security team through its vulnerability disclosure process about a possible exploit that can lead to significant loss of user funds.
Shortly thereafter, a secure line of communication is established and the details of the vulnerability are disclosed. The issue is related to GenLevComp, a strategy type that is in use in two strategies in the yvDAI 0.3.0 vault. A war room is created, with the priority to remove funds from the possibly affected contracts followed by verifying the exploit and creating a fix.
DAI GenLevComp[1], a.k.a StrategyGenericLevCompFarm, is a leveraged strategy that borrows and lends DAI repeatedly on Compound in order to farm Comp tokens. To get into this highly leveraged position it uses dYdX for flash loans.
To receive the flashloan, dYdX sends DAI to GenLevComp and then calls the function callFunction
. After the logic is complete, dYdX needs to receive back more DAI than was sent otherwise the transaction reverts.
GenLevComp lends out the amount
borrowed to Compound and borrows the repayAmount
(calculated as amount+2
) which it then returns to dYdX. The logic flow is that amount
and repayAmount
are passed to dYdX. dYdX send the DAI equivalent of amount
to the contract and executes callFunction
with input of amount
and repayAmount
. After callFunction
dYdX pulls the repayAmount
and verifies it has more funds than it started with.
If GenLevComp does not receive the expected amount from the loan, or if callFunction
is called by anyone other than dYdX's SOLO contract, or if dYdX does not receive its funds back, the transaction reverts. It was believed that the combination of these three safety features made the function safe.
The security researcher was able to effectively initiate a flashLoan of 0 amount
and inject their own value to repayAmount
. Because of this there was no loan, so dYdX did not expect any repayment and therefore did not revert. dYdX SOLO contract still called the callFunction
. And the function received the correct amount
: zero. Bypassing the three safety checks.
Then a loan of the injected repayAmount
was taken out from Compound. By calculating an exact number the exploiter would be able to force the strategy to borrow right up until it was 1 block away from liquidation. On the next block, liquidators would be able to liquidate the strategy and claim liquidation fees. By repeating this process again and again an exploiter would be able to completely liquidate the contract.
Two fixes were implemented[2]:
- A check was added to
callFunction
to make sure that only itself could initiate the dYdX call. Thereby stopping a third party from being able to intiate the flash loan. - The calculation for
repayAmount
was moved from functiondoDyDxFlashLoan
to functioncallFunction
. Thereby removing the opportunity to inject a false number.
June 29, 2021, 19:20 (UTC): Initial contact by xyzaudits.
20:15: Secure disclosure of vulnerability.
20:30: A war room is convened and the decision is made to remove all funds from the strategy before attempting to verify the exploit.
21:02: All funds are removed from DAI GenLevComp and returned to the yvDAI vault. Three more strategies which share the same code are identified, one of which is believed to be at risk: DAI IB GenLevComp[3]
21:09: All funds are removed from DAI IB GenLevComp and returned to the yvDAI vault.
21:53: As a precaution, all funds from the remaining two strategies are also removed and returned to yvUSDC.[4]
22:07: The exploit is verified.
22:25: Gro Protocol, who use a fork of the vulnerable contract and are deemed to potentially be at risk, are notified.
22:54: A fix is commited and ready for testing.
As per Yearn's security process document, the project does not currently have any established bilateral disclosure agreements.[5] However, in this case, due to the critical nature of the vulnerability, a disclosure was made to "Gro Protocol" prior to this publication.
- DAI GenLevComp: 0x55ec3771376b6E1E4cA88D0eEa5e42A448f51C7F
- https://github.com/Grandthrax/YearnV2-Generic-Lev-Comp-Farm/commit/a726df840ee7e51a6c84bf5115137560e9b9a3d3
- DAI IB GenLevComp: 0x77b7CD137Dd9d94e7056f78308D7F65D2Ce68910
- USDC GenLevComp: 0x339dc96a37Dba86008126B3391Db77af93cC0Bd9 USDC IB GenLevComp:0xE68A8565B4F837BDa10e2e917BFAaa562e1cD143
- https://github.com/yearn/yearn-security/blob/master/SECURITY.md#bilateral-responsible-disclosure-agreements