Back to Blog

#3 Balancer V2 事件:捨入不一致導致不變量失效並在多鏈間傳播

Code Auditing
February 10, 2026
5 min read

#3 Balancer V2 事件:捨入不一致破壞不變量並跨鏈傳播

2025 年 11 月 3 日,Balancer V2 的可組合穩定池(Composable Stable Pools)以及跨多個鏈的多個分叉項目遭受協同攻擊,導致總損失超過 1.25 億美元,據報導約 4,500 萬美元已追回。其根本原因是不變量計算中的精度損失導致了價格操縱,這種精度損失源於放大(upscaling)和縮小(downscaling)操作之間的不一致捨入,最終扭曲了 BPT(Balancer Pool Token)的定價邏輯。

此事件之所以成為 2025 年十大安全事件之一,不僅是因為損失規模巨大,還因為其底層漏洞的隱蔽性。此外,該漏洞攻擊迅速跨多個鏈傳播,同時影響了 Balancer 及其分叉項目,凸顯了共享代碼庫和可組合 DeFi 基礎設施如何顯著放大系統性風險。

我們發布了一份詳盡的報告——"深入分析:Balancer V2 漏洞攻擊" [1],其中提供了詳細的技術分解。以下我們對該事件進行簡潔的說明。

背景

Balancer V2 的可組合穩定池(Composable Stable Pool)

此次攻擊中受影響的組件是 Balancer V2 協議的「可組合穩定池」[2]。這些資金池專為預期保持近 1:1 平價(或按已知匯率交易)的資產而設計,並允許在大額交易時將價格影響降至最低,從而顯著提高了同類或相關資產之間的資本效率。每個資金池都有其專屬的 Balancer 池代幣(BPT),代表流動性提供者在池中的份額以及相應的底層資產。

  • 此資金池採用穩定數學模型(基於 Curve 的 StableSwap 模型),其中不變量 D 代表資金池的虛擬總價值。

  • BPT 價格可近似為:

Price(BPT)DtotalSupplyPrice(BPT) \approx \frac{D}{totalSupply}

根據上述公式,如果 D 在賬面上變小(即使沒有任何實際的資金損失),BPT 的價格就會顯得更便宜。

batchSwap()onSwap()

Balancer V2 提供了 batchSwap() 函數,可以在 Vault [3] 內實現多跳交換。該函數接收一個參數以確定兩種交換類型:

  • GIVEN_IN(給定輸入):調用者指定精確的輸入代幣數量,資金池計算相應的輸出數量。
  • GIVEN_OUT(給定輸出):調用者指定期望的輸出數量,資金池計算所需的輸入數量。

通常,batchSwap() 由通過 onSwap() 函數執行的多個代幣間交換組成。這個過程不可避免地涉及與不變量 D 相關的數值計算 [1]。

縮放與捨入

為了統一不同代幣餘額的計算,Balancer 執行以下兩項操作:

  • 放大(Upscaling):在進行計算之前,將餘額和金額放大到統一的內部精度。
  • 縮小(Downscaling):將結果轉換回其原生精度,並應用定向捨入(例如,輸入金額通常向上捨入以確保資金池不會收費不足,而輸出金額通常向下捨入)。

從理論上講,放大和縮小是成對的操作:分別對應乘法和除法。然而,這兩項操作的實現存在不一致性。 具體而言,縮小操作有兩種變體或方向:divUpdivDown。相比之下,放大操作只有一個方向,即 mulDown

漏洞分析

根本問題在於 BaseGeneralPool._swapGivenOut() 函數在放大過程中執行的向下捨入操作。特別是 _swapGivenOut() 通過 _upscale() 函數錯誤地將 swapRequest.amount 向下捨入。由此產生的捨入值隨後在通過 _onSwapGivenOut() 計算 amountIn 時被用作 amountOut這種行為違背了標準慣例,即捨入應以有利於協議的方式應用。

因此,對於給定的資金池(wstETH/rETH/cbETH),計算出的 amountIn 低估了實際所需的輸入。這允許用戶用較少數量的某種底層資產(例如 wstETH)換取另一種資產(例如 cbETH),從而因有效流動性減少而導致不變量 D 減小。因此,對應的 BPT (wstETH/rETH/cbETH) 價格就會因 BPT 價格 = D / totalSupply 而變得貶值。

攻擊分析

攻擊者執行了兩階段攻擊,這很可能是為了將檢測風險降至最低:

  • 在第一階段,核心漏洞利用在單筆交易中執行,沒有產生即時利潤。
  • 在第二階段,攻擊者在單獨的交易中提取資產實現獲利。

第一階段可進一步分為兩個步驟:參數計算批量交換(Batch Swap)。以下我們以 Arbitrum 上的一個攻擊交易範例(TX)來說明這些步驟。

參數計算階段

在此階段,攻擊者結合鏈下計算和鏈上模擬,根據可組合穩定池的當前狀態(包括縮放因子、放大係數、BPT 費率、交換手續費及其他參數),精確調整接下來(批量交換)階段中每一跳的參數。攻擊者還部署了一個輔助合約來協助這些計算,這可能旨在減少暴露於搶先交易(front-running)的風險。詳情請參閱 [1]。

批量交換階段

batchSwap() 操作可細分為三個步驟:

步驟 1:攻擊者將 BPT (wstETH/rETH/cbETH) 交換為底層資產,精確調整其中一種代幣 (cbETH) 的餘額至捨入邊界(數量 = 9)。這為下一步的精度損失創造了條件。

步驟 2:攻擊者隨後使用精心構造的數量(= 8)在另一種底層資產 (wstETH) 和 cbETH 之間進行交換。由於在縮放代幣數量時進行了向下捨入,計算出的 Δx 變得略小(從 8.918 變為 8),導致 Δy 被低估,從而使不變量(根據 Curve 的 StableSwap 模型得出 D)變小。由於 BPT 價格 = D / totalSupply,BPT 價格被人為壓低。

步驟 3:攻擊者將底層資產反向交換回 BPT,在恢復餘額的同時從被壓低的 BPT 價格中獲利。

總結

此次事件涉及一系列針對 Balancer V2 可組合穩定池以及跨多個鏈部署的分叉版本的協同漏洞利用交易,導致了巨大的損失。在首次攻擊後,模仿交易迅速出現,顯示了攻擊模式一旦暴露後傳播速度之快。

關鍵教訓:

  • 捨入與精度處理:所有關於代幣數量的縮放和精度操作都應朝著有利於協議的方向進行捨入。_upscale()(僅向下捨入)與縮小操作(定向捨入)之間存在的單一不一致性,就足以製造出可被利用的價格扭曲。
  • 安全軍備競賽:攻擊者將操縱和利潤提取分開在不同的交易中進行,以規避檢測。檢測系統應關聯相關交易,而不僅僅是標記單個交易。
  • 運營安全:一旦漏洞利用模式公開,模仿者在幾分鐘內就跨鏈複製了攻擊。共享代碼庫的協議需要協同監控和快速的跨鏈暫停能力。

參考文獻

  1. https://blocksec.com/blog/in-depth-analysis-the-balancer-v2-exploit

  2. https://docs-v2.balancer.fi/concepts/pools/composable-stable.html

  3. https://docs-v2.balancer.fi/reference/swaps/batch-swaps.html


關於 BlockSec

BlockSec 是一家全棧區塊鏈安全與加密合規服務提供商。我們構建的產品與服務可幫助客戶在協議及平台的整個生命週期中,執行代碼審計(包括智能合約、區塊鏈和錢包)、實時攔截攻擊、分析事件、追蹤違法資金,並滿足 AML/CFT 合規義務。

BlockSec 已在知名會議上發表多篇區塊鏈安全論文,報告了多個 DeFi 應用程式的零日漏洞,攔截了多次駭客攻擊並挽回了超過 2,000 萬美元的資金,並保障了價值數十億美元的加密資產安全。

Best Security Auditor for Web3

Validate design, code, and business logic before launch. Aligned with the highest industry security standards.

BlockSec Audit