金色財經近期推出金色硬核(Hardcore)欄目,為讀者提供熱門項目介紹或者深度解讀。
2月16日,bZx被爆遭到「攻擊」,「攻擊者」操縱多個DeFi項目上的代幣價格,從而實現15秒內套利36萬美元。涉及多個DeFi明星項目如Compound,DyDx,Uniswap,kyber,bZx。這個「攻擊」利用了DeFi上最新的閃電貸(flashloans)功能。正如bZx所說,這種「攻擊」是所見過的最複雜的攻擊之一,只有對每種DeFi協議及其各種工具有非常深入的了解才有可能,傳統金融體系中沒有類似的東西。
什麼是閃電貸(flashloans)?怎麼利用閃電貸(flashloans)來套利?本期金色硬核(Hardcore)綜合編譯AbitrageDAO和PeckShield最早和最新的閃電貸套利研究。
AbitrageDAO是Stake資本團隊建立的一個DeFi套利基金,聯合鏈上流動性和鏈下機器人來尋求套利機會。PeckShield為區塊鏈安全公司。
最新進展:2月18日bZx發推宣布再次暫停,疑似再次被「攻擊」,「攻擊」者或獲利2388個ETH。
在交易世界中,套利是一種利用市場之間的價格差異來獲利的策略。套利機會在金融市場中以各種形式存在。加密貨幣也不例外,很多交易所之間有著套利機會。套利有助於減少資產在不同市場中的價格差異,它還有助於提高流動性。
我們(AbitrageDAO)專注於在以太坊上運行的具有合約可填充流動性(Contract Fillable Liquidity ,CFL)的去中心化交易所。有CFL的去中心化交易所包括Oasis,0x relayers,Uniswap,Bancor和Kyber。有CFL的交易所允許交易者在以太坊區塊鏈的一個區塊交易中利用套利機會。
什麼是閃電貸(flash loans)
閃電貸(flash loans)是為開發人員設計的,可以在無需提供任何抵押的情況下立即進行貸款。所有這些都要在一個交易(一個以太坊區塊)中完成。開發人員可以從Aave儲備池中借錢(註:flash loans最早討論來自Aave協議,第一筆flash loans也來自Aave),條件是在交易結束之前將流動資金返還到資金池中。如果這種流動性未能及時返回儲備庫,則交易將被撤回,從而確保儲備池的安全。
閃電貸有許多有趣的用例,包括:
這使得更多參與者可以在套利和清算間發揮作用,因為不需要任何資金就可以開始。套利機會通常不需要太多資金(在100-10000美元之間)。另一方面,清算需要大量資金來清算借款人頭寸。Compound或單抵押DAI(SAI)的許多清算需要ETH或DAI超過100萬美元。
ArbitrageDAO是低抵押/無抵押閃電貸的最佳用例。但我們相信,在未來幾個月中,將看到許多使用閃電貸的激動人心的項目。
第一筆閃電貸
ArbitrageDAO於2020年1月18日完成第一筆無抵押的閃電貸。見下圖Camilla Russo的報導。
為了證明閃電貸的巨大潛力,我們決定聚焦於特定的套利策略,但也可應用於許多其他方面。你可以在此處查看ArbitrageDAO從錢包發起的交易:https://etherscan.io/address/0x8645abffe4fad9e0c6c18afff30ef6aea438008c
https://etherscan.io/tx/0x4555a69b40fa465b60406c4d23e2eb98d8aee51def21faa28bb7d2b4a73ab1a9
在上述套利交易中,AbitrageDAO在Aave上借出超過3100個DAI。
更多交易:
截止2020年1月23日,AbitrageDAO總共從Aave借了大約9400個DAI,盈利33個DAI。
最新套利案例:bZx 2月15日閃電貸套利過程全披露
bZx 2月15日閃電貸套利過程來自安全公司派盾的分析。
這不是預言機攻擊。相反,這是一個非常聰明巧妙的套利,它確實利用了bZx智能合約中的一個錯誤,以允許本應鎖定的bZx資金流向Uniswap,並進一步將洩漏的資金吸收到Compound頭寸中。
套利五步驟
交易在這裡0xb5c8bd9430b6cc87a0e2fe110ece6bf527fa4f170a4bc8cd032f768fc5219838,它是在2020-02-15 01:38:57 + UTC的區塊高度9484688上。如上圖所示,此次「攻擊」可以分為五個不同的步驟:閃電貸借款、吸籌、槓桿拉盤、出貨、償還閃電貸(Flashloan Borrow, Hoard, Margin Pump, Dump, Flashloan Repay)。
1:閃電貸借款。這一步利用了dYdX的閃電貸功能借入10000個ETH。
執行此步驟後,「攻擊」者資產負債如下資產,無收益。
2:吸籌。利用借來的貸款,「攻擊」者將5500 ETH存入Compound作為抵押品,借入112 WBTC。這是正常的Compound操作,此吸籌的WBTC將在步驟4中出貨。
完成此步驟後,「攻擊」者的資產負債表如下,仍然無收益。
3:槓桿拉盤。吸籌之後,此步驟利用bZx保證金交易功能以賣空ETH兌得WBTC(即sETHwBTCx5)。具體來說,「攻擊」者存入1300 ETH並調用bZx保證金交易功能,即mintWithEther(連續調用marginTradeFromDeposit)。保證金交易功能利用KyberSwap將借入的5637.623762 ETH交換為51.345576 WBTC。請注意,5倍槓桿借入ETH。實質上將1 WBTC的兌換率提高到109.8 WETH,大約是正常兌換率(~38.5 WETH/WBTC)的三倍。
具體來說,為完成此交易,bZx將訂單轉發給KyberSwap,後者隨後會查詢其儲備金並找到最佳匯率,實際上KyberUniswap儲備庫。此步驟實質是將Uniswap中的WBTC價格提高了三倍。
此步驟應由內置的完整性檢查阻止,此操作可驗證掉期後頭寸不會變為默認值。但是,此攻擊發生時,沒有進行此檢查,我們稍後將在智能合約錯誤部分中檢查詳細信息。
完成此步驟後,「攻擊」者的資產負債表如下,仍然無收益。
4:出貨。隨著Uniswap中WBTC價格的飆升,「攻擊」者將Uniswap中從Compound中借來的112 WBTC賣出換成WETH。
此出貨步驟獲得6871.4127388702245 ETH的淨收益,平均兌換率為1 WBTC = 61.4 WETH。執行此步驟之後,攻擊者獲得可觀的利潤,資產負債表如下:
5:償還閃電貸。「攻擊」者使用從112 WBTC出貨中獲得的6871.4127388702245 ETH,將10000ETH的貸款償還給dYdX,從而完成閃電貸。
這一步後,可以重新計算一下資產負債。最終,「攻擊」者獲得71個ETH的套利,外加兩個頭寸,一個頭寸為Compound(+ 5500WETH / -112WBTC),另一個頭寸為bZx(-4337WETH / + 51WBTC)。當bZx頭寸處於預設狀態時,Compound頭寸非常有利可圖。在利用漏洞之後,「攻擊」者立即開始安排償還Compound債務(112BTC)來贖回抵押品(5500WETH)。對於bZx頭寸,「攻擊」者不再顯示任何興趣。
考慮到1 WBTC = 38.5WETH(或1 WETH = 0.025BTC)的市場均價,「攻擊」者可以獲得112 WBTC等價的4300 ETH。結果,「攻擊」者獲得了71 WETH + 5500 WETH -4300 ETH = 1271 ETH,大約35.59萬美元(假設ETH價格為280美元)。
bZx智能合約錯誤
這次「攻擊」背後的魔力是Uniswap WBTC/ETH是如何被操縱至高達61.4的利潤的。如第3步所述,當正常市場價格僅為38左右時,WBTC / ETH價格被拉升至109.8。換句話說,這一巨大價差是被有意操縱的。但是,如此巨大的價差會導致bZx頭寸處於抵押不足狀態。但是為什麼要允許抵押不足狀態存在,這自然導致在bZx智能合約實現中發現隱藏的錯誤。
保證金拉升功能從marginTradeFromDeposit()開始。
如上圖所示,marginTradeFromDeposit()在第840行將第四個參數設置為true的情況下調用_borrowTokenAndUse()
在_borrowTokenAndUse()內部,當amountIsADeposit為true時,在行1348中調用_getBorrowAmountAndRate()。返回的借款金額將存儲在sendAmounts [1]中。
同樣在_borrowTokenAndUse()中,在amountIsADeposit == true的情況下,在1355行中將sendAmounts [1]的值填充為sendAmounts [6](將在後面看到)。稍後,在第1370行中調用_borrowTokenAndUseFinal()。
在第1414行中,_borrowTokenAndUseFinal()通過IBZx接口調用takeOrderFromiToken(),以使交易流進入bZxContract。
下面有趣的部分到了。在第145–153行中,有一個require()調用以檢查該頭寸是否健康。不幸的是,在loadDataBytes.length == 0 && sentAmounts [6] == sentAmounts [1]的情況下,完整性檢查(sanity check)bZxOracle :: shoudLiquidate()被跳過了。這正是觸發漏洞以避免完整性檢查的條件。
如果我們看一下bZxOracle :: shouldLiquidate(),則第514行中的檢查getCurrentMarginAmount()<= loanOrder.maintenanceMarginAmount可以通過捕獲保證金提升步驟來完成這項工作,從而可以防止這種「攻擊」。
參考資料:
Flash Boys | Arbitrage DAO
https://medium.com/@bneiluj/flash-boys-arbitrage-dao-c0b96d094f93
bZx Hack Full Disclosure (With Detailed Profit Analysis)
https://medium.com/@peckshield/bzx-hack-full-disclosure-with-detailed-profit-analysis-e6b1fa9b18fc
聲明:本文系金色財經原創稿件,版權屬金色財經所有,未經授權不得轉載,已經協議授權的媒體下載使用時須註明"稿件來源:金色財經",違者將依法追究責任。
提示:投資有風險,入市須謹慎。本資訊不作為投資理財建議。