合約安全(1):Balancer中通貨緊縮貨幣的套利攻擊詳解

Abstract

消息來源:2020.6.29 鏈聞看天下
當紅流動性挖礦 DeFi 項目 Balancer 如何被攻擊?官方這麼說
文中簡要描述了攻擊發生時間和危害,沒有詳細描述漏洞細節。

漏洞詳細介紹可參考文章《Balancer Pool with STA Deflationary Token Incident》

概念介紹

滑點 slippage

在買賣 token 時,期望的交易價格和實際支付的價格之間的差別,稱之爲交易滑點。

流通池

用戶將資產轉入交易平臺之中獲得收益,而在平臺中的總資產額度,就構成了流通池。
流通池中代幣總額越多,深度越好,大額交易帶來的影響也就更小,不至於因爲一筆幾十萬美元的交易就讓價格產生大幅波動。
Defi的一個風險點就是流通池不夠大,容易產生較大滑點。

流動性挖礦 liquidity mining

用戶將自己的token放到交易所的流通池中,交易所則將等值的交易所代幣發放給用戶。
這樣一來,用戶爲交易所提供了流通池的部分深度。同時,用戶可以享受交易所挖礦帶來的分紅。

自動化做市商 AMM

AMM是一種即時兌換模式。
通常的交易所(中心化/去中心化),需要買賣雙方對價格達成一致,才能完成交易;而AMM 只需買方認可流通池中的token價格即可完成交易。

類比到遊戲當中,就是玩家交易所 和 遊戲NPC商人的區別。
在玩家交易所中,需要買方玩家的出價 和 賣方的出價一致,才能達成交易。 這需要雙方的互動。
在遊戲NPC商人中,無論是買方還是賣方,玩家只需要認可NPC給出的一口價,就可以完成交易。(例如把打怪獲得的裝備賣給武器商人,多少錢武器商人說了算,沒有迴旋餘地)至於NPC給出的價格,則是按照遊戲中的規則,對武器進行估值(藍色裝備10金幣,紫色裝備100金幣等)
AMM就是這樣一個武器商人,他會按照既定規則對token進行估值,並跟用戶進行即時交易。

Uniswap

Uniswap 就是一個AMM實例,官網是 : https://uniswap.exchange
Uniswap 採取的算法爲固定乘積的方式 : 可以用方程式 X * Y= K 來表示。這裏,K 是個常數。
假設有這樣一個交易池,其中有 50 個以太坊,有 1 萬美元,而 K 的值恆定,爲 1 萬。
假設 X 表示以太坊的供應量 50, Y 是 ETH 交易時的價格。
在這種情況下,Y 的價格會是 10,000/50 = 200, 因爲 K = 10000 是個常數值。
如果有人購買了以太坊,交易池子中的以太坊會減少,而美元的總量會增加。

  • 假設用戶用 200 美元的價格,購買了 2 個以太坊。X 變爲 48,Y 變成 10000/48 = 208 元。
  • 假設用戶出售 7 個以太坊,X 變爲 55 。Y 變成 10000/55 = 181 美元。

通縮貨幣模型

即被設計成"越用越少"的token。
舉例如下

func token.Transfor(from,to,Amount):
	from.Amount -= Amount
	to.Amount += ( Amount - 1ETH )

當from把10000 ETH 轉給 to時,from雖然減少了10000 個 ETH,但是 to 只收到了9999個 ETH。這就導致token總量越來越少。
實現了貨幣的通縮。

攻擊過程

攻擊對應的transaction是https://etherscan.io/tx/0x013be97768b702fe8eccef1a40544d5ecb3c1961ad5f87fee4d16fdc08c78106

其中Token Transfer如下:
交易內容如下
etherscan自帶的explorer不太好看細節,這裏推薦使用OKO contract explorer
界面如下,可以看到函數調用順序
Call Tree

Step1 flash loan 借錢搞事

Defi相關攻擊中,有部分攻擊是需要資金成本的。閃電貸的出現,使這種資金成本不再是攻擊者的障礙。

  • 我們看到Transaction首先調用了兩次approve函數,來批准 WETH9和STA 代理用戶轉賬。
    approve
  • 接着是一記operate函數,從dYdX進行閃電貸。一共借了104331.302778 × 10¹⁸ WETH
    在這裏插入圖片描述

Step2 用WETH換STA,使STA數量減少,並升值。

  • 然後攻擊者分多次調用 swapExactAmountln函數,將借來的WETH換成STA。
    swapExactAmountln
    這裏注意,由於STA是通貨緊縮模型貨幣。上述swapExactAmountln函數發生時,流通池中的STA總數回減少,攻擊者得到的STA也減少了,收到的STA的總數量是小於WETH數量除以兩者價值比的。
    數量的下降,導致了STA單價上升(因爲Uniswap中的K值不變,數量少則單價升高)。

Step3 用STA換WETH,配合gulp函數,獲得額外WETH。

  • 最後,攻擊者多次先後調用 swapExactAmountln 和 gulp函數,將STA換回WETH。
    在這裏插入圖片描述
    這裏注意,如果沒有配合gulp使用,STA的單價會隨着swapExactAmountln的調用,越來越低。
    到最後STA單價會低到攻擊者無法獲利,不過是把WETH換成了STA,然後又換了回來。
    我們看一下gulp函數的定義。
function gulp(address token)
        external
        _logs_
        _lock_
    {
        require(_records[token].bound, "ERR_NOT_BOUND");
        _records[token].balance = IERC20(token).balanceOf(address(this));
    }

可見gulp是對STA單價進行一個校準,校準函數是ERC20的balanceOf。而不是用的當前流通池中預期的價格。
所以,這裏會產生一個偏差,STA的單價會被固定在高位。不會隨着swapExactAmountln的調用而減少。

Step4 還清flash loan貸款,套利離開

  • 最終,攻擊者得到了超量的WETH,並向dYdX歸還了借來的104331.302778 × 10¹⁸ WETH
    還錢
    並取出利潤。
    拿錢走人

Discussion

攻擊發生在2020年6月29日,造成了50w美元的損失。6月30日,balancer Labs宣佈已經獎勵了Bug finder Hex_Capital。並將會爲所有funder報銷整個攻擊事件中的所有損失。

References

  • 攻擊交易詳情 https://oko.palkeo.com/0x013be97768b702fe8eccef1a40544d5ecb3c1961ad5f87fee4d16fdc08c78106/
  • 攻擊事件記錄 https://medium.com/@1inch.exchange/balancer-hack-2020-a8f7131c980e
  • balancer 官方twitter https://twitter.com/BalancerLabs
  • ERC20智能合約實現代碼 https://zhuanlan.zhihu.com/p/104527883
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章