昨天晚上(2024.2.23)uni瞬間拉盤,價格從7美元,一瞬間漲到了11美元。
compound這個借貸協議是允許用戶抵押其他幣(如usdc)借uni,就在這個uni瞬間拉盤之後的一小段時間裡,compound沒有及時更新uni的價格,導致在協議裡可以用低uni價值的抵押品去借走uni。
這被極少數幾個人發現後抵押usdc借走了大量的uni,然後賣掉uni變成usdc,然後你會發現,它獲得的usdc數量竟然多於他抵押進compound的數量。
我來認真分析這次對借貸協議的攻擊,資料來源https://bad-debt.riskdao.org/。
攻擊獲利的地址有以下四個
0x6980a47bee930a4584b09ee79ebe46484fbdbdd0
0x5968ada261a84e19a6c85830e655647752585ed4
0x49bc3cec1fb7978746f742a4e485d0d601831cea
0x2f99fb66ea797e7fa2d07262402ab38bd5e53b12
現在在debank上去查看這四個地址的餘額,你會發現在compound這個協議裡,這四個地址都有一筆債務,但抵押品幾乎為零,如下面:
這個截圖顯示,這個地址0x2f99fb66ea797e7fa2d07262402ab38bd5e53b12在compound抵押了1.1503Dai和0.051715usdc,但藉走了28702.7973uni 。
抵押品幾乎為0,但藉來的uni價值高達33萬U。這種情況下,這個地址一定是不會去還這筆uni債務的。
其他三個地址都一樣,使用了幾乎為零的抵押品,借走了十幾萬U的uni幣。
這四個地址累計借走了55,565.9001uni,目前以12U一個計算,總價值是55565.9*12=666790.8 usdt,66萬U虧損。
為什麼會發生可以使用幾乎為0抵押品,卻能藉賣幾十萬U的uni幣?
整個攻擊邏輯是下面這樣的:
1.假設現在是T0時間點,uni在市場上的價格是7U/uni,compound對uni的餵價正常,也是7U/uni
2.然後在T1時間點,uni在市場上的價格突然爆漲,瞬間漲到了11U/uni。但compound裡對uni的餵價出現錯誤,還是停留在7U/uni。
3.接著有人發現了compound對uni的餵價錯誤,立刻抵押了20萬usdc進去compound充當抵押品,並頂格借走了uni幣,按compound的餵價(7u/uni,和85%的借貸率),可以藉 20*0.85=17 萬U的uni,170000/7=24285.7143 uni,即可以藉走2.4萬uni。
4.然後將這2.4萬uni在市場上(如uniswap v3)賣掉換成usdc,因為市場上的價格是11U/uni,因此可以賣到2.4*11=26.4 wUsdc,比抵押品多了6.4萬Usdc,這就是利潤。
以下這筆交易https://etherscan.io/tx/0xaee0f8d1235584a3212f233b655f87b89f22f1d4890782447c4ef742b37af58d 可以非常清楚地看到上面的邏輯
它抵押了193020usdc,借出了19748uni,並且將uni賣出了ETH然後ETH又賣出了usdc,最終收到195461usdc,比抵押品多了195461-193020=2441 usdc。
5.等compound將正確的uni幣價格餵進協議後,那這些債務肯定要被清算,並且還清算不干淨,即使清算者拿走所有的抵押品,也還會留下大量的uni債務。這就是壞帳。
compound為什麼會出現uni價格餵價錯誤?
目前compound已經發起了修正這個bug的投票。
因為compound對uni幣的價格設定是採用了雙重保險,一個是採用chainlink的oracle餵價,另外同時也採用了Uniswap TWAP(時間加權平均價格)。但這兩個餵價具體是怎麼取捨我沒去查。但從目前的結果來看,這兩者必須同時正常,compound才能正常餵食價格。
當uni價格瞬間爆漲時,chainlink的餵食價格是正常的,但UniswapTWAP的價格出現了問題,compound的協議給了錯誤的價格。