2023 年 4 月 16 日,Compound V2 的分支協議 Hundred Finance 遭到攻擊,導致約 740 萬美元的損失。此次攻擊涉及兩個主要問題:
- 精度丟失問題(導致錯誤捨入);
- 空市場問題(允許駭客操縱 exchangeRate)。
根據 DeFiLlama 的數據,Compound V2 是被分叉次數最多的借貸協議,擁有超過 100 個分叉版本。其合約經過 OpenZeppelin 審計並經過實戰驗證,被認為是安全的。然而,Hundred Finance 的攻擊事件突顯了精度丟失(尤其是在低流動性情況下)如何嚴重影響 DeFi 協議的安全性,並隨後在 Midas 和 Radiant 等眾多著名分叉項目中引發了一系列類似的攻擊。
為了深入了解,建議您參考完整分析。以下我們對該事件進行簡要介紹,並將其列為 2023 年十大安全事件之一。
背景
Hundred Finance 概述
Hundred Finance 是 Compound v2 的一個分叉,在多個主網上運行,並使用 Chainlink 預言機。與傳統金融借貸做法不同,像 Compound 和 Aave 這樣的 DeFi 借貸協議不允許超額抵押借貸。 簡單來說,如果您存入價值 100 美元的代幣 A,您只能借出價值低於 100 美元的資產。根據大多數協議的風險控制係數,該比例通常在 50% 到 80% 之間。
對於借貸協議,常見的攻擊方法包括價格操縱和重入攻擊。有趣的是,Hundred Finance 此前曾遭受過 2022 年 3 月的重入攻擊,但這次事件產生了一個新的攻擊向量。
hToken
從 Compound 和 Aave 分叉出來的借貸協議會為每個基礎代幣(抵押品)創建相應的會計代幣。對於 Hundred Finance 而言:
- USDC 對應 hUSDC
- WBTC 對應 hWBTC
基礎代幣與 hToken 之間的匯率稱為 exchangeRate。
- 當存入資產時,用戶需呼叫 hToken 的
mint()。 - 當提取資產時,用戶需呼叫 hToken 的
redeem()。
exchangeRate
以下是計算 exchangeRate 的公式:

其中:
getCash():此 hToken 合約所擁有的基礎代幣餘額數量。這是一個可以被操縱的關鍵參數,請記住這一點。totalBorrows():市場當前借出的基礎代幣總量,也是市場供應商獲得利息累計的基礎。totalReserves():準備金是每個 hToken 合約中的會計條目,代表歷史利息中撥出的一部分現金,可通過協議治理進行提取或轉移。totalSupply():目前在該 hToken 市場流通的代幣數量。
注意:hToken 與基礎資產之間的 exchangeRate(例如 dai vs hDai 或 eth vs hEth)始於 0.020,並以等於複利市場利率的速度增長。
清算 (Liquidation)
為了防止壞賬,借貸協議允許任何用戶清算他人的債務。我們用以下例子來說明:
- Alice 存入價值 100 美元的 BTC,並借出價值 70 美元的 ETH。
- 如果 ETH 價格上漲或 BTC 價格下跌,Alice 的資產可能會達到清算閾值。
- Bob 可以使用一定數量的 ETH 來清算 Alice 的 BTC,使 Alice 的債務回到健康水平,從而確保協議資金的安全(協議會獎勵發起清算的用戶)。
清算並非本次攻擊的重點,但它參與了攻擊過程。在此,我們只需知道任何用戶都可以用一種代幣來清算他人的債務,這會減少相應的 hToken。
漏洞分析
精度丟失問題
駭客在通過 redeem() 提取抵押品時,計算需扣除的 hToken 數量結果為 1.99999992(非常接近 2 但小於 2)。在 truncate() 中轉換為整數時,向下捨入導致最終結果為 1。

exchangeRate
如前所述,exchangeRate 的計算涉及 getCash(),即 hToken 合約所擁有的基礎餘額數量。通過直接將基礎代幣轉入合約(不通過 mint,僅轉帳),駭客可以操縱 exchangeRate。
然而,值得注意的是,僅憑這個匯率問題並不會危及協議的安全性;駭客無法單獨從中獲利。 在本次攻擊的背景下,它主要被用來放大駭客的收益,使其能夠迅速耗盡資金池。否則,攻擊將從單次決定性的打擊變為一連串的小規模攻擊,需要多次迭代才能產生顯著影響。
總而言之,精度丟失是此次攻擊的關鍵問題。
攻擊流程
這是攻擊交易,我們將使用 Phalcon Explorer 來分析這一複雜的交易。
交易:0x6e9ebcdebbabda04fa9f2e3bc21ea8b2e4fb4bf4f4670cb8483e2f0b2604f451
-
通過閃電貸(Flashloan)從 Aave V3 借入 500 WBTC。
-
Redeem所有先前獲取的 hWBTC,將 hWBTC 的totalSupply重置為 0。
之前的目標是利用閃電貸準備儲備資金,並將 hWBTC 重置為一個新市場。
-
Create第二個攻擊合約(以下稱為攻擊合約 2),並將所有 WBTC(500.30063816 WBTC)轉移到攻擊合約 2。
-
使用 4 WBTC 進行
Mint()以產生 200 hWBTC。 -
Redeem()199.99999998 hWBTC,使 hWBTC 總量剩下 0.00000002(2 wei hWBTC)。 -
將所有 WBTC(500.30063816 WBTC)轉入 hWBTC。注意,直接轉帳不會增加 hWBTC;這可以看作是向資金池捐贈 WBTC。此步驟的主要目的是操縱前述的
exchangeRate。此時,hWBTC 的totalSupply保持在 2 wei hWBTC,但現在有 500.30064194 WBTC,使得exchangeRate比初始值高出數百倍。

-
從 hETH 市場借入 1021 Ether。
-
Redeem()50030063815 WBTC,經計算理應扣除 1.9999992 hBTC,但由於精度丟失,僅扣除了 1 hBTC,產生了巨大的精度丟失(近 50%)。
此時,駭客擁有 500 WBTC + 1021 Ether,成功獲利 1021 Ether。 -
攻擊者
liquidate()剩餘的 hWBTC,將其totalSupply重置為 0,為後續對其他市場的攻擊做準備。鑑於 hWBTC 內幾乎所有的 WBTC 都已被提取,駭客僅用 0.000002 Ether 就完成了此操作。
-
繼續攻擊其他市場,耗盡整個協議。
-
歸還 Aave 的閃電貸。
安全建議
對借貸協議的緩解措施
此問題非常普遍,特別是在 Compound 和 Aave 的分叉中。一種主動的方法是:在啟動新市場時,鑄造少量會計代幣以確保 totalSupply 永遠不會變為 0。
對精度丟失問題的緩解措施
為了更好地規避因精度丟失導致的一系列問題,在實踐中設置最小值是一個有效的方法。 該策略有助於避免在處理極小值時,由精度丟失帶來的重大影響。
閱讀本系列的其他文章:
- 導讀:2023 年十大「精彩」安全事件
- #1:利用 Flashbots Relay 中的漏洞掠奪 MEV 機器人
- #2:Euler Finance 事件:2023 年最大的駭客攻擊
- #3:KyberSwap 事件:通過極其細微的計算實現對捨入錯誤的精妙利用
- #4:Curve 事件:編譯器錯誤導致無害源代碼產生錯誤字節碼
- #5:Platypus Finance:憑藉運氣倖存的三次攻擊
- #7:ParaSpace 事件:與時間賽跑,挫敗行業有史以來最關鍵的攻擊
- #8:SushiSwap 事件:笨拙的救援嘗試引發了一系列模仿攻擊
- #9:MEV 機器人 0xd61492:在一場天才般的攻擊中從掠食者變為獵物
- #10:ThirdWeb 事件:受信任模塊之間的不兼容性暴露了漏洞



