バランサーの脆弱性分析

背景

8 月 22 日、Balancer は、複数の V2 Boost プールに影響を与える重大な脆弱性の報告を受けたことを正式に発表しました。影響を受けたのは TVL の 1.4% のみでした。複数のプールが停止され、ユーザーはできるだけ早く流動性 LP を引き出すよう通知されました。 [1] [2]

8 月 27 日、SlowMist MistEye システムは、Balancer の脆弱性を悪用した疑いのある攻撃トランザクションを発見しました。 [3]

プールを一時停止することはできず、一部のファンドはまだ攻撃の影響を受けているため、バランサー担当者はユーザーに対し、影響を受けたプール内のLPを取得するよう改めて注意を喚起している。 [4] その後、BalancerはMedium上で8月に公開された脆弱性の詳細を正式に公開した。 [5] 、SlowMist セキュリティ チームがレビューしたところ、詳細は次のとおりです。

## 導入

バランサー関係者は開示の中で、今回の問題は線形プールの下方丸めと結合可能なプールの仮想供給により bptSupply が 0 になったことであるとだけ指摘した。まず、この脆弱性に関連するバランサー プロトコルの内容を簡単に理解しましょう。

バランサー V2 ボールト

バランサーV2 [6] このプロトコルは、プログラム可能な流動性のための柔軟な構成要素を表す、イーサリアムに基づく分散型自動マーケット メーカー (AMM) プロトコルです。その中核となるコンポーネントは Vault コントラクトで、すべてのプールの記録を維持し、ネイティブ ETH のパッケージ化とアンパックを含むトークンのアカウンティングと転送を管理します。言い換えれば、Vault は、トークンのアカウンティングと管理をプール ロジックから分離するために実装されています。

Vault には、joinPool、exitPool、swap、batchSwap という 4 つのインターフェイスがあります (参加、終了、およびスワップは別の呼び出しであり、単一の呼び出しで組み合わせることはできません)。優れた機能の 1 つは、batchSwap です。これは、複数のプール間で複数のアトミック交換を実現し、1 つのプール交換の出力を別のプールの入力 (GiveIn および GiveOut) に接続できます。このシステムにはライトニングスワップも導入されています [7] 、社内フラッシュローンに似ています。

リニア プール リニア プール

LP の資本効率と高いワープおよびアンワープ オーバーヘッドの問題を改善するために、Balancer は V2 のソリューションとしてリニア プールを開始し、BPT (ERC20 Balancer Pool Token) トークンを導入しました。

リニアプール [8] メイントークン(原資産)、ラップトークン(ラップトークン)、BPTトークンを含め、資産とリターンのあるラップされた対応物は既知の為替レートで交換されます。ラップされたトークンの割合が高くなるほど、プールの利回りと資本効率が高くなります。ワープ プロセスでは、通常、異なるトークンが同じ精度で計算されることを保証するためにスケーリング係数が使用されます。

コンポーザブル プール コンポーザブル プール

すべてのバランサー プールは、他のトークンを含む構成可能なプールであり、プール自体にも独自のトークンがあります。このうち、BPT通貨とは、すべてのプールの基礎となるERC20バランスプールトークンを指します。ユーザーは他のプールの BPT トークンを自由に組み合わせて引き換えることができます。償還には常にプールと 2 つのトークン (GiveIn と GiveOut) が含まれます。 In はコンポーネント トークンの送信と BPT の受信を意味し、Out は BPT の送信とコンポーネント トークンの受信を意味します。 BPT 自体がコンポーネント トークンであれば、他のトークンと同様に交換できます。このような実装は、外部プール内の基礎となる資産とトークン間の単純なバッチスワップ パスを構成します。ユーザーは、BPT を使用して、線形プールの基礎となる資産を交換できます。これは、バランサー ブースト プールでもあります。 [9] 財団。

上記の組み合わせにより、Balancer の組み合わせ可能なプールが形成されます。 bb-a-USD のコンポーザブル ステーブル プールは 3 つの線形プールで構成され、アイドル状態の流動性を外部プロトコル (Aave) に送信します。たとえば、bb-a-DAI は、DAI と waDAI (ラップされた aDAI) を含む線形プールです。ユーザーがバッチスワップする必要がある場合 (USDT から DAI への変更など)、交換パスの例は次のとおりです。

  1. USDT 線形プールで、USDT を bb-a-USDT に交換します (USDT 線形プールに入る)。

  2. bb-a-USD では、bb-a-USDT が bb-a-DAI に交換されます (線形 BPT 間の交換)。

  3. DAI 線形プールでは、bb-a-DAI が DAI と交換されます (DAI 線形プールを終了します)。

上記の前提知識を簡単に理解した後、脆弱性分析リンクに入ります。

分析

8 月 27 日、SlowMist セキュリティ チームは、バランサーの脆弱性が実際に悪用された疑いがあるという情報を MistEye システムから受け取りました。貿易 [3] 次のように:

攻撃者は最初にフラッシュ ローンを通じて AAVE から 300,000 USDC を借りました。次に、Vault のバッチSwap 操作が呼び出され、結合可能な安定プール bb-a-USD プールを通じて BPT トークンの交換計算が実行され、最終的に、94,508 USDC が 59,964 bb-a-USDC、68,201 bb-a-DAI、および 74,280 に交換されます。 bb-a-USDT。最後に、取得した BPT トークンは、原資産と引き換えに Vault 契約の exitPool を介してプールから出て、フラッシュ ローンを返済し、約 108,843.7 米ドルの利益を残して市場から出ます。

この攻撃の鍵はbatchSwapにあることがわかりますが、batchSwapでは一体何が起こったのでしょうか?詳しく見てみましょう。

BatchSwap プロセス全体を通じて、攻撃者はまず bb-a-USDC プール内の USDC を引き換え、次に BPT トークンを交換して、bb-a-USDC を bb-a-DAI、bb-a-USDT、USDC と交換しました。最後に、基礎となるメイン トークン USDC が bb-a-USDT に交換されます。つまり、bb-a-USDC は、キー BPT トークンとして、GiveOut と GiveIn のコンポーネント トークンとして機能します。

最初のステップでは、攻撃者は固定スケーリング係数を使用して bb-a-USDC 線形プール内の USDC メイン トークンと BPT トークンを交換し、増加した量がプール内の bptBalance に記録されます。しかし、2 回目の onSwap 交換後、同じ交換プロセス中に交換された USDC の amountOut 値が 0 であることがわかりました。どうしてこれなの?

onSwap 関数をさらに詳しく調べると、このプロセスで精度が公称値に処理され、対応するトークンのスケーリング係数が計算されることがわかります。次に _downscaleDown 関数が呼び出されるとき、amountOut は切り捨てられます。 amountOut と scalingFactors の場合 [indexOut] 値の差が大きく、_downscaleDown の計算値はゼロになります。

つまり、BPT トークンを使用してメイン トークンを引き換える場合、amountOut が小さすぎる場合、戻り値はゼロに切り捨てられ、この値は scalingFactors によって計算された 1e12 より小さくなります。ただし、amountIn から入ってくる bb-a-USDC の量は引き続き bptBalance 仮想量に追加され、この操作により bb-a-USDC プールの残高が増加します。これは bb の一方的な追加とみなすことができます。 -a-USDC の流動性。

次に、結合可能なステーブルプールの特性を利用して、BPT トークン間の相互変換を通じて、まず bb-a-USDC を他の BPT トークンと交換します。この交換プロセスを実行するには、安定したプールの呼び出しパス bb-a-DAI onSwap -> _swapGivenIn -> _onSwapGivenIn を組み合わせます。まず、bb-a-USDC を bb-a-DAI および bb- に置き換えます。 a-USDT を順に実行します。オンライン線形プールとは異なり、コンポーザブル ステーブル プールでは、onSwap 操作の前に為替レートのキャッシュ更新が必要です。コードから、組み合わせプールでは、onSwap が最初にキャッシュされたトークンの交換レートを更新する必要があるかどうかを判断することがわかります。

前回の交換後、bb-a-USDC の量が変更され、_toNominal による名目化後の実質総額は totalBalance 994,010,000,000、BPT トークンの仮想供給量は 20,000,000,000 です。更新された交換レートは、以前の線形プールの元のキャッシュ交換レート 1,100,443,876,587,504,549 のほぼ 45 倍、つまり 49,700,500,000,000,000,000 であると計算できます。

その後、bb-a-USDC が線形プール内の USDC に交換されます。ただし、この交換は 2 番目の交換と同じであり、これにより、再び amountOut が 0 に切り捨てられ、交換パスは以前と同じになります。

次の交換は、USDC を bb-a-USDC に反転することであり、交換パスは onSwap -> onSwapGivenIn -> _swapGivenMainIn です。このプロセス中に、償還が必要な amountOut を計算する際、仮想供給量の計算は、償還された BPT トークンの総供給量とプール内の残りの量 (0) の差に基づいていることがわかりました。

これは、bptSupply が 0 であり、BPT Out を計算するときに _toNominal 関数が直接呼び出され、このパスの呼び出しによって USDC と bb-a-USDC の交換比率が 1:1 に近づくためです。

要約

batchSwap は、複数のプール間の複数のアトミック スワップを通じて、1 つのプールの交換の出力を別のプールの入力 (tokenIn および tokenOut) に接続し、USDC を BPT トークンに変換します。このバッチスワップでは、実際のトークンの送金は発生しませんが、送金量と送金量を記録することで最終的な交換金額が確認されます。また、線形プールは原資産トークンを通じて交換されるため、交換方法は仮想供給と固定アルゴリズムを通じてレートを計算することになります。したがって、batchSwap には 2 つのセキュリティ ホールが存在します。

1 つ目は線形プールの下方丸めの問題で、攻撃者は丸めによって一方的にメイン トークンをプールに追加し、キャッシュされたトークンの比率を高め、対応するコンポーザブル プール内のトークン交換レートを操作します。

第二に、結合可能なプールの仮想供給特性により、仮想供給は BPT トークンからプールの残高を差し引くことによって計算されます。GiveIn が引き換え時に BPT トークンである場合、この部分はその後のトークンから差し引かれます。の場合、攻撃者は BPT を GiveIn として交換し、その供給を 0 に操作してから逆スワップを実行するだけで済みます。つまり、BPT が GiveOut 側として使用されます。このとき、供給は 0 であるため、アルゴリズムは 1 に近くなります。1 の比率は、実際の償還における線形プールの償還率よりも低く、GiveOut の BPT トークンの数が間接的に操作されます。

脆弱性 1 では為替レートが上昇し、脆弱性 2 では為替レートが逆に下落していることがわかり、攻撃者は二重バフを利用して利益を得て立ち去ったことがわかります。

参考リンク:

[1]

[2]

[3]

[4]

[5]

[6]

[7]

[8]

[9]

原文表示
このページには第三者のコンテンツが含まれている場合があり、情報提供のみを目的としております(表明・保証をするものではありません)。Gateによる見解の支持や、金融・専門的な助言とみなされるべきものではありません。詳細については免責事項をご覧ください。
  • 報酬
  • コメント
  • 共有
コメント
0/400
コメントなし
いつでもどこでも暗号資産取引
qrCode
スキャンしてGateアプリをダウンロード
コミュニティ
日本語
  • 简体中文
  • English
  • Tiếng Việt
  • 繁體中文
  • Español
  • Русский
  • Français (Afrique)
  • Português (Portugal)
  • Bahasa Indonesia
  • 日本語
  • بالعربية
  • Українська
  • Português (Brasil)