SharkTeam: UniswapV4 フックのベスト セキュリティ プラクティス
SharkTeam
2023-08-08 03:59
本文约5316字,阅读全文需要约21分钟
最近、Uniswap Lab は次世代 AMM Uniswap V4 の開発進捗状況を正式に発表し、ホワイト ペーパーとコード ウェアハウスを公開しました。今回の V4 ホワイト ペーパーは 3 ページのみですが、その理由は、V4 は AMM のコア アルゴリズム ロジックにあまり多くの変更を加えず、より多くのシナリオのニーズを満たすために V3 をベースにいくつかの新機能を追加したためです。 SharkTeam は、現在オープン ソース コードに基づいて V4 によってもたらされる新機能を検討し、V4 によって開始された重要な機能フックのアプリケーションのベスト プラクティスを分析します。

最初のレベルのタイトル

副題


1.1 AMM

AMM アルゴリズム レベルでは、Uniswap V4 は V3 を変更せず、定数積 x*y=k に基づく流動性アルゴリズムを引き続き使用します。

Uniswap V3 では、各取引ペアに 4 つのプール (当初は 3 つで、後に新しい 1 bp プールが追加されました) を持つことができ、それぞれ 0.01%、0.05%、0.3%、1% のレートのプールを表します。プールを作成する場合、これら 4 つのタイプのうち 1 つだけを選択できます。

Uniswap V4 では、理論上、各取引ペアは任意の数のプールを持つことができ、各プールの手数料率も任意の値にすることができ、これらのプールのティック スペースも任意の値にすることができます。

副題

1.2 Hooks

フックは、サード パーティまたは Uniswap 公式によって開発されたコントラクトのセットです。プールを作成するとき、プールはフックをバインドすることを選択できます。その後、トランザクションの特定の段階で、プールはバインドされたフック コントラクトを自動的に呼び出します。 Uniswap V4 は、フック コントラクト コードを実行できる次のステージを定義します。


  • beforeInitialize

  • afterInitialize

  • beforeModifyPosition

  • afterModifyPosition

  • beforeSwap

  • afterSwap

  • beforeDonate

  • afterDonate


これは、プールの初期化、流動性の追加/削除、取引、寄付などの操作の前後にフック コントラクトを呼び出すことができることを意味します。

フック コントラクトでは、上記のどのステージを実行するかを明示的に指定する必要があり、プールは、対応するフックを特定のステージで実行する必要があるかどうかを知る必要があります。ガスを節約するために、これらのフラグはコントラクトには保存されませんが、フックがアドレスを示すために特定のを使用する必要があります。具体的な判定コードは以下の通りです。

フック アドレスの最初の 8 ビットは、フックを特定の段階で実行する必要があるかどうかをマークするために使用されていないことがわかります。

したがって、フックの開発者は、コントラクトをデプロイするときにプールの要件を満たすアドレスを生成する必要があります。これを達成するには、通常、Create 2 + ランダムなソルトの計算を使用する必要があります。

ホワイトペーパーのフック実行の例を次に示します。

副題

1.3 動的手数料率


フックは、特定の段階でコードを実行するだけでなく、特定のプールのスワップ手数料率と引き出し率を決定することもできます。引き出しレートとは、流動性を引き出す際にユーザーがフックに支払う必要があるレートを指します。さらに、フックはスワップ手数料の一部を自分自身に指定することもできます。

プールを作成するときは、手数料パラメータの最初の 4 ビット (uint 24) を使用して、プールが動的手数料を使用するかどうか、およびフック スワップ手数料と引き出し手数料を有効にするかどうかをマークする必要があります。

動的手数料が有効な場合、プールはフック コントラクトを呼び出して、各スワップの前に現在のスワップ手数料比率を取得します。フック コントラクトは、現在のスワップ手数料比率を返すために getFee() 関数を実装する必要があります。

副題

1.4 シングルトンコントラクト


Uniswap V3 で新しいプールが作成されるたびに、新しいコントラクトをデプロイする必要があり、大量のガスを消費しますが、実際には、これらのプールで使用されるコードは同じで、初期化パラメータのみが異なります。 Uniswap V4 では、すべてのプールを管理するための Singleton コントラクトが導入されているため、新しいプールを作成するときに新しいコントラクトをデプロイする必要がなくなり、コントラクトをデプロイするためのガスが節約されます。

さらに、シングルトン コントラクトを使用する利点は、すべてのプールが同じコントラクト内にあるため、トランザクション中のトークン転送を削減できることです。したがって、プール間のスワップはコントラクト内で直接完了でき、V3 では、クロスプールスワップ 異なるプール間でトークンを転送する必要があり、ガスが増加します。

副題

1.5 extload


副題

1.6 Flash Accounting


プール スワップ間のトークン転送を減らすために、V4 はフラッシュ アカウンティングと呼ばれる方法を使用してスワップのプロセスを標準化し、流動性/フラッシュ ローンをフラッシュ ローンのようなプロセスに追加/削除します。

(1) ユーザーがロックを取得する

(2) ユーザーは、複数のプールでのスワップ、流動性の追加/削除、フラッシュ ローンによるプールからのトークンの借用などの操作を実行します。

(3) ユーザーのすべての操作によって生成されたトークン転送はロックに記録されます。

(4) すべての操作が終了した後、ユーザーは取得したトークンを持ち帰ることができ、同時にロックに記録されている支払う必要のあるトークンを支払う必要があります。

これらのプロセスは 1 つのトランザクションで実行する必要があります。

副題

1.7 ERC 1155 mint/burn


Flash Accountingでは、同一トランザクション内のスワップのトークン転送を削減できますが、ERC 1155トークンを使用することで、複数のトランザクションのトークン転送をさらに削減できます。

V4 では、ERC 1155 mint を通じて V4 コントラクトにトークンを保存できるため、毎回トークンを V4 コントラクトに転送することなく、複数のトランザクションでこれらのトークンを使用できます。

V4 コントラクトに保存されているトークンは、ERC 1155 burn を使用して引き出すことができます。

最初のレベルのタイトル

副題


2.1 TWAMM (時間加重自動マーケットメーカー)


アリスはブロックチェーン上で 1 億ドル相当のイーサを購入したいと考えています。 Uniswap などの既存の自動マーケットメーカー (AMM) プラットフォームでこの規模の注文を実行すると、アリスがより良い価格を得るために内部情報を使用するのを防ぐために、これらのプラットフォームはアリスに法外な手数料を請求する可能性が高いため、法外なコストがかかります。

より良い価格を得るために、Alice の最善のオプションは、注文を手動でいくつかの小さなサブ注文に分割し、数時間かけて段階的に実行することです。その考えは、彼女が内部情報を持っていないことに気づき、より良い価格を付けるために市場に十分な時間を与えることです。ただし、たとえ彼女が複数のより大きなサブ注文を送信したとしても、各サブ注文は依然として価格に重大な影響を与える一方、敵対的なトレーダーによる「サンドイッチ攻撃」に対して脆弱でもあります。

TWAMM は、Alice に代わってトランザクションを実行することでこの問題を解決します。彼女の注文は無数の小さな仮想注文に分割され、時間内にスムーズな実行が保証されます。同時に、TWAMM は、組み込み AMM プロトコルの特別な数学的関係を使用して、これらの仮想注文間でガスコストを共有できるようにします。 TWAMM はブロック間のトランザクションを処理するため、「サンドイッチ攻撃」に対しても脆弱ではありません。

全体として、TWAMM は、アリスに大規模な取引を実行するためのより効率的な方法を提供し、高額な手数料や市場操作の可能性を回避します。

2.1.1 原則

TWAMM には他の AMM と同様に AMM が組み込まれており、ユーザーはこの AMM を通じてスポット取引を直接行ったり、AMM に流動性を追加したりすることができます。ただし、TWAMM には 2 つの TWAP 注文プールもあり、双方向で TWAP 注文を実行するために使用されます。ユーザーが注文を送信するときに、トークンの入力量とトランザクションの期間を指定すると、TWAMM は同じトランザクション方向の注文を発注します。対応するプールに転送され、指定されたトランザクション速度に従って自動的にトランザクションが実行されます。ユーザーの注文が完全に実行されると、ユーザーはトランザクションから取得したトークンを取り出すことができます。もちろん、ユーザーの注文が実行される前に、ユーザーは事前に注文をキャンセルしたり、注文で取引する必要があるトークンの数を変更したりすることもできます。

イーサリアムでは、スマート コントラクトは EOA アドレスによって開始されたトランザクションによってのみトリガーでき、自動的に実行することはできません。したがって、TWAMM は、注文プールで取引されるトークンを決済するために EOA アカウントから定期的にトランザクションを送信する必要があり、これらのトランザクションを実行するにはキーパー アカウントが必要です。

もちろん、TWAMMは、ユーザーが操作するたびに注文プールを自動的に決済することもできるため、キーパーのオーバーヘッドが節約されます。これは、DeFiプロトコルがストリーミングデータを処理する一般的な方法でもあります。

2.1.2 なぜこの取引モデルはサンドイッチ攻撃を受けにくいのでしょうか?

この種の攻撃は実装が難しく、ブロック内のタイムスタンプは変わらないため、攻撃者はブロックの最後のトランザクションでプール価格を引き上げる必要があり、その結果、次のブロックのTWAMM決済に影響が及びます。これにはサンドイッチ攻撃を複数のブロックで行う必要がありますが、他の裁定者が途中で介入して攻撃者が損失を被る可能性があるため、攻撃者に大きなリスクをもたらすことは間違いありません。

同時に、裁定業者の存在により、このような価格操作は持続不可能となる運命にあり、TWAP注文の特性上、短期間にあまり多くのトークンを取引することがないため、ほとんどの場合損失が発生します。制限する必要があります。

2.1.3 V4 の TWAMM ワークフロー

(1) このフックは、2 つのトランザクション方向の TWAP 注文をそれぞれ表す 2 つの TWAP 注文プールを維持します。

(2) ユーザーはこのフックを通じて TWAP 注文を送信でき、トランザクションのトークン、数量、時間の長さを指定する必要があります。

(3) このフックは beforeSwap と beforeModifyPosition を登録し、ユーザーがポジションを取引または調整するたびにこのフックがトリガーされます。

(4) トリガーされた後、フックは 2 つの TWAP 注文プールの決済を担当します。

(5) ユーザーはいつでも手動で決済をトリガーすることもできます

(6) ユーザーはTWAP注文のトークン数量をキャンセルまたは変更することができます

2.1.4 詳細な例

TWAMM は、フックのロジック呼び出しの 3 つのフェーズを登録し、プールの初期化前に TWAMM を初期化し、ユーザーがポジションを取引または調整するたびにこのフックをトリガーします。

ユーザーは、TWAMM の submitOrder 関数を手動で呼び出して、契約に実行する必要がある注文を送信できます。

ユーザーが実行する必要がある注文をコントラクトに追加すると、その注文はプールが swap およびmodifyPosition 操作を実行するたびに自動的に実行されます。

ユーザーが v4 のスワップ関数を呼び出して取引するか、modifyPosition 関数を呼び出してポジションを変更するたびに、TWAMM の実行関数がトリガーされ、その関数内で内部関数 _executeTWAMMOrders が呼び出され、以前に完了していない注文の実行を継続します。 。

_executeTWAMMOrders 関数

副題

2.2 Limit Order


直前の市場価格で即座に約定される成行注文とは異なり、指値注文は所定の価格に達するとすぐに約定されます。自動マーケットメーカー (AMM) に基づくほとんどの DEX は、デフォルトで成行注文システムを選択します。シンプルで初心者にもわかりやすい。成行注文は、最大価格への影響などのパラメーターにより、実行されるか失敗します。指値注文では、資産価格が指値価格に達した場合にのみ注文が約定され、それ以外の場合、注文はオープンされたままになります。

たとえば、ETH が現在 ETH/DAI プールで 1 ETH = 1500 DAI で取引されているとします。ユーザーは利益確定注文を出すことができます。主な内容は次のとおりです。"1 ETH = 2000 DAIの場合、私のETHをすべて売却します"。この価格に達すると、ユーザーの ETH は完全にオンチェーンで分散型の方法で自動的に DAI に交換されます。

Uniswap の以前のバージョンでは、指値注文は事実上不可能でした。ほとんどの AMM は市場での売買のみを許可します。 V4 バージョンでは、フックの強力な機能とスケーラビリティにより、v4 での指値注文の実装の基盤が確立されています。

2.2.1 原則

指値注文の設計原理はtwammに比べて単純であり、現在は流動性を追加するための指値注文が実装されており、取引のための指値注文の実装は容易になります。

v4にはtickLowerとtickUpperがあり、プールの取引条件の変化に応じて下限と上限が変わりますが、ユーザーが流動性を追加する際、現在の価格で追加したくなくても、現時点では追加することができます。制限注文フックを使用してこの要件を実装し、フックに対応する価格を設定します。各スワップの後、フックは現在のプール価格を判断します。設定された価格に達すると、対応する流動性が追加されて収入が得られます。

2.2.2 V4 の指値注文ワークフロー

1. Limit は、さまざまな下値および取引方向に対する指値注文として複数のエポックを維持します。

2. このフックを通じて、ユーザーは価格の引き下げと取引の方向を送信し、指値注文を契約に追加します。

3. このフックは afterSwap を登録します。これは、各スワップが終了した後に価格が変化した場合にのみトリガーされます。

4. トリガーされた後、フックは現在の価格範囲をチェックし、現在の価格で流動性を追加する必要がある指値注文があるかどうかをエポックからチェックします。

5. ユーザーはいつでも資金を引き出したり、流動性を直接追加したりできます

2.2.3 詳細な例

フックはコントラクト登録の 2 段階でトリガーされます。フックはプールが初期化された後に初期化され、フック ロジックは各交換の後にトリガーされます。

ユーザーは、place 関数を呼び出して、ユーザーが追加したい流動性の数量、価格、取引方向を渡します。フックは、ユーザーが追加したい流動性をまずストレージ用のプールに追加し、次に、ユーザーに対応する指値注文。

このフックは各スワップが終了した後にトリガーされ、現在の価格帯に応じた範囲価格に存在する指値注文に基づいて流動性を追加する操作が完了します。

指値注文が完了する前に、ユーザーは kill 関数を呼び出して指値注文をキャンセルし、今度は流動性を追加する利点を得ることができます。

ユーザーが流動性を削除したい場合は、引き出し関数を呼び出して、必要な流動性を引き出します。

一般に、この指値注文フックはユーザーにより便利な方法を提供します。ユーザーは流動性を追加したいときに価格を設定できます。プール内の価格範囲がその価格に達すると、フックは自動的にユーザーのプールに入ります。流動性を追加する操作が可能であり、ユーザーはいつでも流動性をキャンセルおよび撤回できます。

TWAMMや指値注文に加え、LP再投資や動的手数料変更などの機能もHookをベースに実現可能ですが、紙面の都合上、追跡分析で紹介します。

LP 再投資: ユーザーはフックを使用して流動性を追加、変更、削除できます。また、フックは呼び出すために afterSwap および afterModifyPosition を登録できます。ユーザーは一様にフックを使用して流動性を追加するため、poolManager に流動性を追加する唯一のアドレスはフックです。フックはトリガーされるたびに現在時刻を確認できます。一定の時間が経過した後、流動性報酬を引き出して LP を取得することを選択しますトークンはプールに流動性を再び追加し、ユーザーの収入を自動的に最適化します。

最初のレベルのタイトル

副題


require と revert の使用を減らす


フックを呼び出すプールの関数ロジックでは、ロールバック ステートメントの使用を最小限に抑えます。プール コントラクトとフック コントラクトは共通の関係にあるため、フックでトランザクションのロールバックが発生した後、プール内のトランザクションもロールバックされます。プール内の通常のトランザクションに関連しないフック内のロールバック ステートメントにより、ユーザーはプール内の関数を通常どおり使用できなくなる可能性があります。

自己破壊関数の使用を避ける

フック内で自己破壊関数を使用することは避けてください。フック内で自己破壊関数を呼び出すと、フック内のロジックに問題が発生するだけでなく、プール内の関数が失敗し、プール内のアセットが破損する可能性があります。プール全体が失われ、機能が失敗します。正常に動作します。

厳格なアクセス制御

フック コントラクト内のアクセス許可を厳密に制御して過剰なアクセス許可を持つロールを回避し、特権ロールに対してマルチシグネチャ管理を実行してシングルポイント攻撃を防ぎます。特権ロールがコントラクト状態変数を恣意的に変更できる状況を回避するために、ロジック エラーが発生してトランザクション全体がロールバックされ、プールの通常の使用に影響を与える可能性があります。最小特権の原則を検証するには、openzeppelin の AccessControl コントラクトを使用して、アクセスを制御するためのよりきめ細かいアクセス許可を実装する必要があります。これは、この方法では、各システム コンポーネントが最小特権の原則に従うように制限されるためです。

再入国制限はしっかりやれよ

プールの外部拡張コードとして、フックはコントラクト内のリエントリー攻撃の可能性にも注意を払う必要があります。たとえば、ネイティブ トークンを転送する際の指値注文でのリエントリー攻撃の可能性など、コントラクト資産の損失につながる可能性があります。外部コントラクトまたはいわゆる「check-validate-interact」パターンを呼び出す前に、すべての状態を確認して更新を試みます。この方法では、すべての状態更新が完了するため、再入可能であっても影響はありません。 。

契約アップグレード管理

最初のレベルのタイトル

About Us


公式ウェブサイト:

公式ウェブサイト:https://www.sharkteam.org

Twitter:https://twitter.com/sharkteamorg

Discord:https://discord.gg/jGH9xXCjDZ

Telegram:https://t.me/sharkteamorg


SharkTeam
作者文库