
Yearn Finance 攻擊事件分析
TechFlow Selected深潮精選

Yearn Finance 攻擊事件分析
本文將分析Yearn Finance攻擊事件的攻擊過程以及漏洞產生的原因。
概述
2023 年 4 月 13 日,Yearn Finance 遭到黑客攻擊,導致損失了大約 1000 萬美元。本文將分析攻擊過程以及漏洞產生的原因。
攻擊分析
這是一筆攻擊交易:
https://etherscan.io/tx/0xd55e43c1602b28d4fd4667ee445d570c8f298f5401cf04e62ec329759ecda95d
攻擊者從 Balancer 發起了閃電貸,借了 500 萬 DAI、500 萬 USDC 和 200 萬 USDT:

然後,在 Curve 上,攻擊者將 500 萬 DAI 兌換成了 695,000 USDT,並將 350 萬 USDC 兌換成 151 USDT:

攻擊者調用 IEarnAPRWithPool 的 recommend 函數來檢查當前的 APR。此時,只有 Aave 的 APR 不等於 0:

接下來,攻擊者將 800,000 USDT 轉移到了攻擊合約 0x9fcc1409b56cf235d9cdbbb86b6ad5089fa0eb0f 中。在該合約中,攻擊者多次調用了 Aave:Lending Pool V1 的 repay 函數,幫助其他人償還債務,以使 Aave 的 APR 等於 0:

攻擊者調用了 yUSDT 的 deposit 函數,抵押了 900,000 USDT,並獲得了 820,000 yUSDT:

接下來,攻擊者調用了 bZx iUSDC 的 mint 函數,使用 156,000 USDC 鑄造了 152,000 bZx iUSDC,並將其轉移到了 Yearn yUSDT:

攻擊者調用 Yearn:yUSDT 的 withdraw 函數,將 820,000 yUSDT 兌換成 1,030,000 USDT。此時,合約中只剩下攻擊者轉移的 bZx iUSDC:

接下來,攻擊者調用 Yearn:yUSDT 的 rebalance 函數,銷燬 bZx iUSDC:

然後,攻擊者向 yUSDT 合約轉移了 1/e6 個 USDT,並調用了 deposit 函數,抵押了 10,000 USDT,獲得了 1,252,660,242,850,000 yUSDT:

然後,在 Curve 上,攻擊者將 70,000 yUSDT 兌換成 5,990,000 yDAI,將 4 億 yUSDT 兌換成 4,490,000 yUSDC,將 1,240,133,244,352,200 yUSDT 兌換成 1,360,000 yTUSD:

然後在 yearn: yDAI 和 yearn: yUSDC 中分別調用 withdraw ,提取 678 萬 個 DAI 和 562w 萬個 USDC,並歸還閃電貸:

漏洞分析
這次攻擊中最關鍵的一點,是攻擊者使用 100,000 USDT 鑄造了 1,252,660,242,850,000 個 yUSDT。查看 deposit 函數的實現:

可以看到 share 的數量和變量 pool 相關,pool 越小,share 越大,而 pool 的值由 _calcPoolValueInToken 獲得:

攻擊者在調用 rebalance 函數 後,合約中只存在了 USDC,但是 _balance() 獲取的是 USDT 的餘額,USDC 的餘額並不計入其中,因此此時的 pool 為 1(攻擊者轉入的) :



這裡顯然是項目方的配置錯誤,yUSDT 合約中 應當都是 USDT 類的代幣,但是其 fulcrum 變量卻是 USDC 相關的 bZx IUSDC 代幣,因此 yUSDT 中的 USDC 不計入 balance 中:


攻擊者為什麼能調用 rebalance 函數來 burn 掉 bZx iUSDC 代幣呢?查看 rebalance 函數的實現:



可以看到在 _withdrawFulcrum() 中會 存在 redeem 和 burn 操作,因此我們需要讓 "newProvider != provider" 成立 , 其中 recommend() 的實現:

攻擊者通過控制 IIEarnManager(apr).recommend(token) 的返回值,使其為都為 0 來操控 newProvider:

如何讓其都為 0 呢,該函數的返回值和計算出的各個 DeFi 中的 APR 相關,由於 Compound,bZx,dydx 中沒有池子,因此只需要控制 Aave ( Aave: Lending Pool Core V1) 即可:

要使其值返回為 0 ,需要讓 apr.calculateInterestRates 函數的第一個返回值為 0 :

即讓 currentLiquidityRate 為 0 ,該值和 _totalBorrowsStable、_totalBorrowsVariable 相關,當這兩個個值都為 0 時,currentLiquidityRate 為 0:


_totalBorrowsVariable 為 0 ,即 Aave: Lending Pool Core V1 此時沒有人存在債務,為了達成這個條件,攻擊者將池中所有人的債務進行了 repay :

最後,攻擊者讓 _totalBorrowsVariable 變為 0,所以它能夠調用 rebalance 函數 burn 掉 bZx iUSDC 代幣:

總結
此次 Yearn Finance 攻擊事件的根本原因是項目方合約的配置錯誤。攻擊者通過一系列精妙的手法利用了該漏洞,最終獲利大約 1000 萬美元。
歡迎加入深潮 TechFlow 官方社群
Telegram 訂閱群:https://t.me/TechFlowDaily
Twitter 官方帳號:https://x.com/TechFlowPost
Twitter 英文帳號:https://x.com/BlockFlow_News














