根據審計公司Certik的分析,黑客通過利用 KyberSwap 部分借貸池哪怕是最小的漏洞,成功挖礦交叉互換手段竊取了借貸池。
11 月 22 日, KyberNetwork多個鏈遭受閃貸攻擊,造成約 4700 萬美元的損失。根據 Certik 的說法,使用這種技術,瞭解中心化流動性生成器的工作原理非常重要。
自動LP本質上是在所有交易發生的地方部署標準恆定乘積曲線 (x*y=k)。
Certik 發現,如果製作的資金池具有更嚴格的價格曲線上限,則可以更好地利用流動性。在狹窄的價格區間內擁有大量流動性支持也可以有效下降價格滑落的風險,因為交易規模必須與借貸池比例上漲才能產生相同的價格影響。

中心化流動性提供者模型由Uniswap v3 普及,允許LP(LP) 為其首選價格區間添加流動性。
Certik 指出,這種設計的結果是,每個流動性供應頭寸 (LP) 必須單獨跟蹤,因為池中的流動性變得不匹配。價格範圍可以分為Chia的“報價點”,允許有限合夥人在任意兩個“報價點”之間提供流動性。價格變動指數(表示為 i)定義為相應價格的對數。

流動性提供者的淨流動性等參數存儲在鏈表數據結構中。

實際上,這些頭寸中的每一個都製作了用戶定義的價格曲線。通過將所有不同的頭寸聚合到一條價格曲線中,它允許單個池支持流動性提供者(LP)偏好的多樣性。

當在某個價格變動範圍內添加或減少流動性時,借貸池必須記錄在這些價格變動範圍超越時添加或釋放的虛擬流動性數量,以及在該保證金範圍內使用了多少籌碼來觸發流動性。代幣置換籌碼1 會導致當前池價格和當前“報價”向下移動,而代幣置換籌碼0 會導致當前池價格和當前“報價”上漲。執行交換時,當“tick”超越此邊際左右移動時,流動性總量會增加或減少,這就是發生攻擊的 KyberSwap 中的漏洞。
漏洞
簡而言之,該漏洞存在於 KyberSwap Elastic 的computeSwapStep()實現中。該函數負責計算需要相減或相加的交易實際輸入輸出金額、需要收取的掉期費用,以及得到的平方根值作為sqrtP函數。

該函數最初被稱為calcReachAmount()函數,並認為黑客的交易不會超越刻度保證金,但由於製作了一個大於targetSqrtP 的虛擬價格(通過調用函數“calcFinalPrice”計算),因此出現了錯誤。因此,流動性不會被消除並導致下一次攻擊。
攻擊流程
此示例基於以太坊交易,其 txhash 為: 0x396a83df7361519416a6dc960d394e689dd0f158095cbc6a6c387640716f5475 。
該交易代表了六次攻擊,均使用相同的方法。因此,Certik 以針對 USDC-ETHX 貨幣對的攻擊為例。
1.首先,黑客從Uniswap閃貸 500 ETHx,並通過交換過量的 ETHx 來操縱只有 2.8 ETHx 的 KS2-RT 池((KyberSwap v2 Reinvestment 籌碼)。黑客將 246,754 ETHx 兌換成 32389.63 USDC,耗盡了資金池流動性並將currentTick上漲至 305,000。

交換後,池中還剩下 249.5 ETHX 和 13.2 USDC。

可以看到,黑客最初想用 500 ETHX 兌換 USDC,但 246,754 ETHx 足以獲得 32,389.63 USDC,並將currentTick上漲305,000。這意味著當時沒有超過 305,000 點保證金的流動性可供黑客進行交換,因此被認為是真空。

2. 然後,黑客從 KyberSwap: Elastic Anti-Snippingposition Manager合約中調用mint()函數,以製作一個包含 16 USDC 和 5.87e-3 ETHX 的新借貸池。 “蜱”被放置在 305,000 到 305,408 的狹窄範圍內,這意味著黑客創建了自己的借貸池來跟蹤 305,000 的“蜱”。

隨後,黑客刪除了部分流動性,但在 305,000 至 305,408 的刻度範圍內留下了一些流動性。

3. 黑客進行第二次從 ETHX 到 USDC 的兌換。他們以 305,000 的價格變動保證金兌換了 244.08 ETHX,獲得了 13.6 USDC,並將價格變動保證金上漲至 305,408。

從表面上看,這似乎是一次奇怪的交換,因為黑客是唯一提供 305,000 到 305,408 之間流動性的人,但這是下一步的前提。
4. KyberSwap 使用compute SwapStep()函數來確定交易是否超過了tick間隔。部分功能如下圖所示:

這裡,重點關注calcReachAmount()函數。如果currentSqrtP (當前平方根價格)達到targetSqrtP ,此函數計算交易所需的籌碼數量。
Cerik表示,在這筆交易中, usedAmount的值為244080034447360000000,而黑客輸入兌換的ETHx數量為244080034447359999999,比usedAmount的值少了1。 computeSwapStep()函數確定此交易不足以耗盡當前報價範圍內的流動性,不需要更改為另一個報價範圍。意味著nextSqrtP不會更新為targetSqrtP 。

然後調用calcFinalPrice函數來計算下一個nextSqrtP值。這裡重要的部分是,在計算過程中,掉期費用被計入流動性中。導致nextSqrtP的最終價格實際上高於最初預期,特別是高於“tick”範圍內的價格305,408。


回到上面的交換函數,Certik 說通過比較sqrtP和nextSqrtP的值來確定刻度幅度是否需要交換。這裡的條件僅確定sqrtP是否等於nextSqrtP ,並且只有在等於時,才會調用下層函數updateLiquidityAndCrossTick()來增加或減少流動性( swapData.baseL )並超越保證金“tick”。
此時, sqrtP現在大於nextSqrtP 。這意味著黑客製作了一種當前價格已經超越了tick範圍上限的其中,但卻沒有觸發updateLiquidityAndCrossTick()函數來減少流動性,從而導致仿盤流動性的存在。


5. 最後,黑客進行了反向交易,將 USDC 換成 ETHx,將價格下降到略高於“tick”範圍 305,408——黑客提供的流動性範圍上限(從 305,000 到 305,408),略低於價格在“tick”範圍內 304,982。

當價格從略高於 305,408 的價格進入 305,000 – 305,408 的“tick”範圍(黑客提供流動性的範圍)時,就會調用updateLiquidityAndCrossTick()函數。仿盤流動性被添加到305,000 – 305,408“tick”範圍內的流動性中,與實際流動性相比,上漲了“tick”範圍內值之間的流動性。隨後,黑客在此價格範圍內將 493,638 個 ETHx 兌換為 27,517 USDC(包括未包含在 305,000 – 305,408 報價範圍內的約 250 個 ETHx)。 Certik 總結道,結果是,之前的成本得到了恢復,同時借貸池失去了所有 USDC。

6、閃電貸,完成攻擊。

對跨多個區塊鏈的KyberSwap 協議上的多個交易對對重複此過程,導致以下損失。
保利:1,180,097 美元;以太:7,486,868 美元; OP:15,504,542 美元;基礎:318,413 美元; ARB:16,833,861美元; AVAX:23,526 美元。
Certik確認的攻擊來自三個不同的以太坊地址(EOA),其中地址0x502佔大部分資產。最初,地址0x502聯繫了項目方,告知他們休息一段時間後進行談判。 KyberSwap團隊隨後提出了 10% 的獎勵,截止日期為 UTC 時間 11 月 25 日早上 6 點。




