2023年4月16日、Compound V2のフォークであるHundred Financeが攻撃を受け、約740万ドルの損失が発生しました。この攻撃には、主に以下の2つの問題が関与していました。
- 精度損失の問題(不正確な丸め処理の問題)
- 空の市場により、ハッカーがexchangeRateを操作できるようになったこと。
DeFiLlamaによると、最も多くフォークされているレンディングプロトコルであるCompound V2は、100以上のフォークを誇っています。OpenZeppelinによって監査され、実戦で証明されたそのコントラクトは安全と見なされています。しかし、Hundred Financeの攻撃は、特に流動性が低い状況での精度損失がDeFiプロトコルのセキュリティに致命的な影響を与える可能性があり、MidasやRadiantなどの著名なフォークでも同様のエクスプロイトが連鎖的に発生するきっかけとなりました。
より深く理解するためには、完全な分析を参照することをお勧めします。以下では、このインシデントの簡潔な紹介を提供し、2023年のトップ10セキュリティインシデントの1つとして強調します。
背景
Hundred Financeの概要
Hundred Financeは、Chainlinkオラクルを利用して複数のメインネットで動作するCompound v2のフォークです。従来の金融レンディングとは異なり、CompoundやAaveのようなDeFiレンディングプロトコルでは、過剰担保での借り入れは許可されていません。 簡単に言うと、トークンAで100ドル相当を預け入れた場合、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と基盤資産(例:daiとhDai、ethとhEth)の間のexchangeRateは0.020から始まり、複利市場金利に等しいレートで増加します。
清算
不良債権を防ぐため、レンディングプロトコルはどのユーザーでも他のユーザーの債務を清算できるようにしています。以下の例で説明します。
- アリスが100ドル相当のBTCを預け入れ、70ドル相当のETHを借ります。
- ETHの価格が上昇したり、BTCの価格が下落したりすると、アリスの資産が清算閾値に達する可能性があります。
- ボブは、一定量のETHを使用してアリスのBTCを清算し、アリスの債務を健全なレベルに戻すことで、プロトコルの資金の安全を確保します(プロトコルは清算を開始したユーザーに報酬を与えます)。
清算はこの攻撃の焦点ではありませんが、攻撃には関与していました。 ここで知っておくべきことは、どのユーザーでも1種類のトークンで他のユーザーの債務を清算でき、それにより対応するhTokenが減少するということです。
脆弱性
精度損失の問題
ハッカーは、redeem()を介して担保を引き出す際に、控除されるhTokenの量を計算すると1.99999992(2に非常に近いが2未満)になるようにしました。truncate()で整数に変換する際に、切り捨てを使用するため、最終結果は1になります。

exchangeRate
前述のように、exchangeRateの計算にはgetCash()が含まれており、これはhTokenコントラクトが保有する基盤残高を指します。基盤トークンを直接コントラクトに転送すること(mintなしで、単に転送すること)により、ハッカーはexchangeRateを操作できます。
しかし、このexchangeRateの問題だけではプロトコルのセキュリティは侵害されないことに注意することが重要です。ハッカーは単独でこれを利用して利益を得ることはできません。 この攻撃の文脈では、主にハッカーの利益を増幅するために悪用され、プールを急速に枯渇させることができました。そうでなければ、攻撃は単一の決定的な一撃から多数の小さな刺し傷に移行し、大きな影響を与えるには多数の繰り返しが必要になります。
簡潔に言うと、精度損失はこの攻撃における主要な問題です。
攻撃プロセス
以下は攻撃トランザクションであり、Phalcon Explorerを使用してこの複雑なトランザクションを分析します。
トランザクション:0x6e9ebcdebbabda04fa9f2e3bc21ea8b2e4fb4bf4f4670cb8483e2f0b2604f451
-
Flashloanを介してAave V3から500 WBTCを借入します。
-
以前に取得したhWBTCをすべて
Redeemし、hWBTCのtotalSupplyを0にリセットします。
ここでの目的は、flashloanを使用して準備金を用意し、hWBTCを新しい市場としてリセットすることです。
-
2番目の攻撃コントラクト(以下、Attack Contract 2と呼ぶ)を
Createし、すべてのWBTC(500.30063816 WBTC)をAttack Contract 2に転送します。
-
4 WBTCを使用してhWBTCを
Mint()し、200 hWBTCを生成します。 -
199.99999998 hWBTCを
Redeem()し、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を借入します。
-
50030063815 WBTCを
Redeem()しますが、計算後、1.9999992 hBTCが控除されるはずですが、精度損失により、1 hBTCのみが控除され、大幅な精度損失(約50%)が発生します。
この時点で、ハッカーは500 WBTC + 1021 Etherを保有しており、1021 Etherの利益を上げています。 -
攻撃者は残りのhWBTCを
liquidate()し、そのtotalSupplyを0にリセットして、他の市場への攻撃を継続する準備をします。 hWBTC内のWBTCはほぼすべて引き出されているため、ハッカーはわずか0.000002 Etherでこれを管理します。
-
他の市場への攻撃を継続し、プロトコル全体を枯渇させます。
-
AaveへのFlashloanを返済します。
セキュリティ勧告
レンディングプロトコルのための緩和策
この問題は、特にCompoundやAaveのフォークで顕著です。プロアクティブなアプローチとしては、新しい市場を立ち上げる際に、totalSupplyが決して0にならないように、会計トークンをいくつかミントすることが含まれます。
精度損失問題のための緩和策
精度損失に起因する一連の問題をより効果的に回避するために、実践においては最小値を設定することが有効な方法です。 この戦略は、非常に小さい値を扱う際の精度損失による重大な影響を回避するのに役立ちます。
このシリーズの他の記事を読む:
- リードイン:2023年のトップ10「素晴らしい」セキュリティインシデント
- #1:Flashbots Relayの脆弱性を悪用したMEVボットの収穫
- #2:Euler Financeインシデント:2023年最大のハック
- #3:KyberSwapインシデント:極めて微妙な計算による丸め誤差の巧妙な悪用
- #4:Curveインシデント:コンパイラエラーが意図しないソースコードから不正なバイトコードを生成
- #5:Platypus Finance:幸運により3回の攻撃を生き延びる
- #7:ParaSpaceインシデント:業界で最も重大な攻撃を阻止するための時間との戦い
- #8:SushiSwapインシデント:不器用な救出試みが一連のコピーキャット攻撃を招く
- #9:MEV Bot 0xd61492:巧妙なエクスプロイトで捕食者から獲物へ
- #10:ThirdWebインシデント:信頼されたモジュール間の非互換性が脆弱性を露呈



