💥 Gate 廣場活動:#发帖赢代币TRUST 💥
在 Gate 廣場發布與 TRUST 或 CandyDrop 活動相關的原創內容,即有機會瓜分 13,333 枚 TRUST 獎勵!
📅 活動時間:2025年11月6日 – 11月16日 24:00(UTC+8)
📌 相關詳情:
CandyDrop 👉 https://www.gate.com/zh/announcements/article/47990
📌 參與方式:
1️⃣ 在 Gate 廣場發布原創內容,主題需與 TRUST 或 CandyDrop 活動相關;
2️⃣ 內容不少於 80 字;
3️⃣ 貼文添加話題: #发帖赢代币TRUST
4️⃣ 附上任意 CandyDrop 活動參與截圖。
🏆 獎勵設定(總獎池:13,333 TRUST)
🥇 一等獎(1名):3,833 TRUST / 人
🥈 二等獎(3名):1,500 TRUST / 人
🥉 三等獎(10名):500 TRUST / 人
📄 注意事項:
內容必須原創,禁止抄襲或灌水;
得獎者需完成 Gate 廣場身份認證;
活動最終解釋權歸 Gate 所有。
價格操縱的黑魔法:Balancer V2 不變量計算漏洞剖析
編譯:白話區塊鏈
2025 年 11 月 3 日,Balancer V2 的組合型穩定池(Composable Stable Pools)以及多個鏈上的幾個分叉項目遭受了一次協同攻擊,導致總損失超過 1.25 億美元。BlockSec 在第一時間發出了警報,並隨後發布了初步分析。
這是一次高度復雜的攻擊。我們的調查顯示,根本原因是不變量(invariant)計算中的精度損失導致的價格操縱,進而扭曲了 BPT(Balancer 池Token)的價格計算。這種不變量操縱允許攻擊者通過單次批量交換(batch swap)從一個特定的穩定池中獲利。盡管一些研究人員提供了富有洞察力的分析,但某些解讀存在誤導性,其根本原因和攻擊過程尚未完全闡明。本博客旨在對該事件進行全面而準確的技術分析。
關鍵要點 (TL;DR)
根本原因:舍入不一致和精度損失
攻擊執行
運營影響與放大
在以下部分中,我們將首先提供有關 Balancer V2 的關鍵背景信息,然後深入分析已發現的問題和相關攻擊。
0x1 背景
1. Balancer V2 的組合型穩定池
本次攻擊中受影響的組件是 Balancer V2 協議的組合型穩定池。這些池專爲預期保持接近 1:1 錨定(或以已知匯率交易)的資產而設計,並允許以最小的價格影響進行大額交換,從而顯著提高同類或相關資產之間的資本效率。每個池都有自己的 Balancer 池Token (BPT),代表流動性提供者在池中的份額,以及相應的底層資產。
該池採用了 Stable Math(基於 Curve 的 StableSwap 模型),其中不變量 D 代表了池的虛擬總價值。
BPT 價格可以近似爲:
2. batchSwap() 和 onSwap()
Balancer V2 提供了 batchSwap() 函數,該函數支持在 Vault內進行多跳交換(multi-hop swaps)。根據傳遞給此函數的參數,有兩種交換類型:
通常,batchSwap() 由多個通過 onSwap() 函數執行的Token間交換組成。以下概述了當一個 SwapRequest被分配爲 GIVEN_OUT 交換類型時的執行路徑(請注意 ComposableStablePool 繼承自 BaseGeneralPool):
以下顯示了 GIVEN_OUT 交換類型中 amount_in 的計算,這涉及不變量 D。
// inGivenOut token x for y - polynomial equation to solve // ax = amount in to calculate
// bx = balance token in
// x = bx + ax (finalBalanceIn)
// D = invariant // A = amplification coefficient // n = number of tokens // S = sum of final balances but x
// P = product of final balances but x
x^2 + ( S - ---------- - D) * x - ------------- = 0
(A * n^n) A * n^2n * P
3. 縮放與舍入
爲了在不同Token餘額之間規範化計算,Balancer 執行以下兩個操作:
顯然,放大和縮小在理論上是成對的操作——分別是乘法和除法。然而,這兩種操作的實現中存在不一致。具體來說,縮小操作有兩個變體或方向:divUp 和 divDown。相比之下,放大操作只有一個方向,即 mulDown。
這種不一致的原因尚不清楚。根據 _upscale() 函數中的注釋,開發人員認爲單向舍入的影響是微乎其微的。
0x2 漏洞分析
根本問題源於在 BaseGeneralPool._swapGivenOut() 函數中執行放大(upscaling)操作時所執行的向下舍入操作。特別是,_swapGivenOut() 通過 _upscale() 函數錯誤地將 swapRequest.amount 向下舍入。這個舍入後的值隨後被用作 amountOut,在通過 _onSwapGivenOut() 計算 amountIn 時使用。這種行爲與“舍入應以有利於協議的方式應用”的標準實踐相矛盾。
因此,對於給定的池(wstETH/rETH/cbETH),計算出的 amountIn 低估了實際所需的輸入。這允許用戶以較少數量的一種底層資產(例如 wstETH)交換另一種資產(例如 cbETH),從而由於有效流動性減少而導致不變量 D 減少。因此,相應的 BPT(wstETH/rETH/cbETH)的價格變得被人爲壓低(deflated),因爲 $\text{BPT price} = \frac{D}{\text{totalSupply}}$。
0x3 攻擊分析
攻擊者執行了
兩階段攻擊,可能是爲了最小化被檢測的風險:
第一階段可以進一步分爲兩個階段:參數計算和批量交換。下面,我們使用 Arbitrum 上的一個攻擊交易(TX)示例(來說明這些階段。
參數計算階段
在此階段,攻擊者將鏈下計算與鏈上模擬相結合,根據組合型穩定池的當前狀態(包括縮放因子、放大系數、BPT 匯率、交換費用和其他參數),精確調整下一階段(批量交換)中每一跳的參數。有趣的是,攻擊者還部署了一個輔助合約來協助這些計算,這可能是爲了減少被“搶跑”(front-running)的風險。
首先,攻擊者收集目標池的基本信息,包括每個Token的縮放因子、放大參數、BPT 匯率和交換費百分比。然後他們計算一個關鍵值 trickAmt,這是用於引發精度損失的被操縱的目標Token數量。
將目標Token的縮放因子(scaling factor)記爲 sF,計算如下:
uint256[] balances; // 池Token的餘額(不包括 BPT) uint256[] scalingFactors; // 每個池Token的縮放因子 uint tokenIn; // 此跳模擬的輸入Token索引 uint tokenOut; // 此跳模擬的輸出Token索引 uint256 amountOut; // 期望的輸出Token數量 uint256 amp; // 池的放大參數 uint256 fee; // 池交換費百分比
返回數據爲:
uint256[] balances; // 交換後池Token的餘額(不包括 BPT)
具體來說,初始餘額和迭代循環次數是鏈下計算的,並作爲參數傳遞給攻擊者的合約(報告分別爲 100,000,000,000 和 25)。每次迭代執行三次交換:
請注意,由於 StableMath 計算中使用了牛頓-拉弗森(Newton–Raphson)方法,此步驟可能偶爾會失敗。爲了緩解這種情況,攻擊者實現了兩次重試嘗試,每次使用原始值的 9/10 作爲備用值。
攻擊者的輔助合約派生自 Balancer V2 的 StableMath 庫,這一點可以通過其包含“BAL”風格的自定義錯誤消息來證明。
批量交換階段
然後,batchSwap() 操作可以分解爲三個步驟:
0x4: 攻擊與損失
我們在下表中總結了這些攻擊及其相應的損失,總損失超過 1.25 億美元。
0x5 結論
該事件涉及一系列針對 Balancer V2 協議及其分叉項目的攻擊交易,導致了重大的財務損失。在最初的攻擊之後,在多個鏈上觀察到了大量後續和模仿交易。這次事件凸顯了 DeFi 協議設計和安全的幾個關鍵教訓:
在保持運營和業務連續性的同時,行業參與者可以利用 BlockSec Phalcon 作爲最後一道防線來保護他們的資產。BlockSec 專家團隊隨時準備爲您的項目進行全面的安全評估。
本文連結:
來源: