
開発者ノート:Aggregator Hookの誕生
TechFlow厳選深潮セレクト

開発者ノート:Aggregator Hookの誕生
本稿では、Aggregator Hookの起源や運用メカニズム、およびUniswapやより広範なDEXエコシステムに与える深远な影響について考察する。
執筆:Attens & Bruce
編集:Lisa,DODO Research
これは(Aggregator Hook)他のDEXにとって非常に良いことだ。コードをわずかに追加するだけで「スーパー・アグリゲーター」としてもう一つの取引所に接続できるのだから、やらない手はない。もちろんUniswapにとっても良いことであり、他DEXの流動性をシームレスかつコストゼロで自らのプラットフォームに取り込むことができる。
— Attens, DODO DEV Leader
Uniswap V4のリリースは開発者の間で瞬く間に大きな波紋を広げた。Hook構造は、従来の固定化されたテンプレート型プール契約に豊かな拡張性をもたらしたのだ。Uniswap V4のHookインターフェースは、プールと資金のやり取りの全ライフサイクルをほぼ網羅しており、開発者たちの「頭脳戦」に肥沃な土壌を提供している。時間加重オラクルを導入して価格操作から守るTWAMM Hookのような比較的シンプルなものから、LimitOrder Hookによるより強力な可能性の提示、あるいはハッカソン中に生まれたクロスチェーン取引Hookまで、さまざまなHookが雨後の筍のように次々と登場している。
DeFiの実務者として、私たちも傍観しているわけにはいかない。11月に行われたETH Globalでは、私たちは新たなHook設計を提案し、「Best of Use Hook」賞を受賞する幸運にも恵まれた。この設計は汎用性が非常に高く、さまざまな流動性プール契約にコンポーネントとして搭載可能であるため、Aggregator Hookと名付けた。
Aggregator Hookは「橋渡し」の役割を果たすことを目的としており、市場の流動性を直接Uniswap V4のプールに接続することを可能にする。また「直前原則(JIT: Just-In-Time)」を利用して流動性資金を動的に管理し、取引前に流動性を注入し、取引後に撤退することで、元のプールに対する影響を最小限に抑える。この統合により、LPはこれまでにないほど容易に資金を管理でき、Uniswapの堅牢なインフラを利用しながら、さらに広範なDEXエコシステム内の流動性を活用することが可能になる。
本稿では、Aggregator Hookの起源、動作メカニズム、そしてUniswapおよびより広いDEXエコシステムに与える深远な影響について探っていく。
I. Aggregator Hookの誕生
当初、このアイデアは単純なニーズから生まれたものだった。つまり、効率の高い価格提示を行うDODO V3のプールがあり、これをHook経由でUni V4に移植できないかという問いかけから始まった。
LimitOrderHookの調査を通じて、私たちは重要な着想を得た。「Hookは一部の資金を託管できる」という事実だ。一見地味な発見だが、これがまさしくウサギ小屋への入り口となった。「Hookは独立したコントラクトである」という点と「Hookは資金を管理できる」という点を組み合わせると、そもそもHook自体がプールになり得るのではないか? さらに言えば、あるコントラクトがUniswap V4のHook要件を満たし、対応する関数を持っているならば、それが他のDEXのプールであっても、あるいは共同購入プールや取引マネージャーのような別のロジックを持っていても、同時にHookとして機能できるのではないか?
こうして初期の構想が生まれた:Aggregator Hookとは、プール中心のHookであり、DODO V3のプールでもありながら、Uniswap V4のHookとしても機能するもの。つまり、価格提示システムをHookの関数内に移行し、JITを活用して、ユーザーがUniswap V4で取引する際にDODO V3と同じ価格を得られるようにする。当初の案は極めて自然だった。各トークンの価格上限・下限、販売数量を持ち、価格上下限をtickに変換し、数量に応じて流動性を配置。ユーザーが取引し、成功。完璧……と思われたが、ここで大きな価格差に直面した。
さまざまなtickSpacingとFeeの組み合わせを試し、複数の価格上下限に対応するtickのパターンを適用しても、最良の結果でも元のDODO V3と比べて0.2%の価格差が生じてしまった。これはユーザー体験に十分影響を及ぼすレベルだ。明らかに、DODO V3とUni V4のアルゴリズムの違いが原因だった。この価格差を解消するために、二つの道が眼前に現れた。
-
正門:Uni V4とDODO V3のアルゴリズム差を徹底的に考慮し、流動性の再マッピング式を導出する
-
裏口:fromAmountを使ってDODO V3から価格を取得し、その価格に基づいて流動性配置パラメータを直接決定することで価格差を排除する
短い検討の末、私たちは迷わず裏口を選んだ! 正門のアプローチが解析解を導ければ、優雅な論文が書けるだろうとは信じているが、残念ながら我々は数学者ではない。一方、裏口のアプローチには明らかな欠点がある:問い合わせが一回増えるため、ガス消費が必然的に増える。しかし利点も同様に明確だ。fromAmountから価格を得る関数はDODO V3特有のものではなく、すべてのDEXプールに類似の関数が存在する——getAmountsOut、get_dy、querySellTokens… 関数名は異なっても、何らかの方法で価格情報を取得できる。つまりこのHookコンポーネントはDODO V3だけでなく、任意のDEXプールに統合可能であり、さらにはプールでなくても、Solverによる価格提示モジュールとしても利用できる。流動性を持ち、その流動性に対して価格提示ができるコントラクトであれば、このHookコードを追加するだけで、元の独立したロジックを損なうことなく同時にHookとなり、Hook-Poolとして正式なUniswap V4プールを構成できる。理想を言えば、Uniswap V4のルーティングは従来のV4プールだけでなく、我々が生み出したこのようなトリックプールにも対応できるようになるはずだ。
私たちは興奮した――これは他のDEXにとっても良いことだ。コードをわずかに追加するだけで「スーパー・アグリゲーター」として接続できるのだから、やらない理由はない。Uniswapにとっても当然良いことだ。他DEXの流動性をシームレスかつコストゼロで自らに取り込むことができる。
もちろん、この壮大なビジョンが実現するかどうかは、最終的にUniswap V4がどのようなルーティングアルゴリズムを採用し、これらのプールをどのように優先順位づけするかにかかっている。それはまた別の話題であり、別途記事を書くべきテーマかもしれない。しかしHookの特殊性から言えるのは、どのようなルーティングアルゴリズムを採用しても、Hookの影響を無視することはできないということだ。なぜなら、Hook内の処理はユーザーが得る最終的な価格に直接関係するからである。
ここで読者の皆さんは、私たちの壮大な仮定の基本前提を思い出しているだろうか? 私たちはある価格を得て、それをUniswap V4内で再現するような流動性配置方法を見つける。その結果、ユーザーがUniswap V4を通じて取引する価格と、Hook-Poolに直接取引する価格が一致するようにする。
最終的に、私たちはそれを達成した。だからこそ私たちはこれを正式に「Aggregator Hook」と呼ぶのである。
II. Aggregator Hookの操作フロー
実際にAggregator Hookの具体的な実装を語るとき、その魔法は実はマジシャンの袖に隠された、気づきにくい一枚の硬貨に過ぎない。
-
ユーザーがswapコールを発行
-
beforeSwapHookが発火し、Hook内で以下の3つの操作を実行
-
プールに残っているすべての流動性を撤去(Hush! これが鍵です)
-
ユーザーのfromAmountを使ってHook-Pool本来の取引価格を取得
-
その取引価格からmodifyPositionのパラメータを計算し、流動性を注入
-
swapコール終了
-
外部のRouterがユーザーのtransferInおよびtransferOutを処理
下図の通り:

ユーザーの注文が近づくと、BeforeSwapフックが起動し、流動性提供者(LP)がUniswap V4のプールに流動性を投入する。追加された流動性は、まもなく到着する注文に適応し、取引の成功を促進する。しかし、取引終了時に即座に流動性を撤去するのではなく、そのままプールに残しておく。これにより、最初の取引の完全なライフサイクルが成立する。
革新は次の取引の処理にある。次の取引開始前に、BeforeSwapフックが再び発動する。その最初の任務は、前回の取引で残された余分な流動性をすべて削除することである。
残存する流動性が撤去されると、LPは初期ステップを繰り返す。新しい取引のニーズを分析し、2つの価格帯に正確な量の流動性を追加する。この細心の追加により、流動性は最適化され、最も効率的な位置に配置されるため、スリッページが減少し、Uniswapエコシステム全体の取引執行が改善される。
III. メカニズムとコードの詳細分析
最高潮は最後に取っておこう。
流動性をいつ撤去すべきか
まず、なぜ流動性を撤去する必要があるのか説明しよう。これは以下の2点に基づいている。
-
このHookにおいて、Hook-Poolが主体であり、流動性は可能な限りHook-Poolに集中させるべきである。
-
プールに余計な流動性がない状態では、価格のremapping計算が簡単になる。
JITでは通常、ユーザーのswap前に流動性を注入し、swap後に撤去するのが一般的だ。当初私たちもそう考えていた。beforeSwapHookで流動性を追加し、afterSwapHookで撤去する。論理的にはスムーズだ――しかし、Hookは常に驚きを提供する。現在のUniswap V4の最新testRouterの構造を見てみよう。



わかるだろうか? 我々の壮大な計画を阻んでいる核心は、ユーザーがmanager.swapを完了した後でなければ、poolManagerとのトークン交換が行われないという点にある。つまり、afterSwapHookは文字通り「swap後」には発火せず、afterSwapHook内で流動性の撤去処理を行うことはできないのだ。removeLiquidity関数は最適なタイミングを失い、テスト内ではswap関数呼び出しの直後に孤独に一行だけ立つ、滑稽な小人となってしまう。行き詰まり、swap関数のhookDataを改造し、testRouterの改修を模索し始めた矢先、Uniswapの創造者の一人ken氏と開発者のsaucepoint氏が決定的な助言を与えてくれた。「次の取引開始時に流動性を撤去すればよい」と。
この案は私たちにとって間違いなく最善だった。第一に、コードへの変更が極めて小さい。当時、ハッカソンのプレゼンまであと7時間しかなかった。第二に、不安定なtestRouterに依存せずに自動化された流動性撤去が可能になる。少し待つだけで、次のユーザーが来れば、前の取引の未処理分はそのまま返却される。
もちろん、Hook-Poolのオーナーは任意のタイミングでUniswap V4の流動性を引き出すことができ、次の取引ユーザーを待つ必要はない。以下のremove関数はpublicである。


また、資金保護のため、beforeModifyPosition Hookで流動性変更のmsg.senderを検証している。

流動性の注入方法
Uniswap V4とV3の計算式は同一である(V4のプールがライブラリになった点を除けば)。ここでは極めて狭いtick間隔に片側流動性を注入することのみを考える。例えば、tick -46874 と tick -46873 の間に流動性を配置し、跨tick消費を最小限に抑える。コードと関連解析記事を読むことで、Uniswapのアルゴリズムから以下の公式が得られる。

対応するコード:

しかし、ここが終わりではない。Uniswap V3/V4の流動性分布を観察すると、以下のようなことがわかる。

流動性を注入した後、その価格帯のうち実際には50%の範囲しか片方向取引のニーズを満たさない。token0をtoken1に売る場合、選択したtick区間[tickLower, tickUpper]に対応する価格区間[priceLower, priceUpper]において、期待される価格変動はpriceから目標価格まで下落することだが、その目標価格が(priceLower + priceUpper) / 2より低くなってはならない。もし下回ると、price_nextが価格下限を越えてしまい、tick下限の補正が必要になる。反対側の取引でも同様に補正が必要となる。例を示そう。

この補正に対応するコード:

価格バランス
ここまで、私たちが描いた夢はほぼすべて実現できた。Aggregator Hookは優れているが、完璧ではない。最大の制限は取引方向にある。この制限は以下の通り。
-
現在、V4プールの価格がtick 0に対応する価格にあるとする(currentPrice)
-
targetPrice > currentPriceのとき、V4プールはswap 1 to 0のみ実行可能
-
targetPrice < currentPriceのとき、V4プールはswap 0 to 1のみ実行可能
この制限は直感的にも理解しやすい。targetPriceを市場価格、currentPriceを古いDEXプールの取引によって形成された価格と考える。DEXプールの価格が市場価格より低い場合、ユーザーがtoken0を購入して価格を上げることで均衡を保つ。逆にDEXプールの価格が高い場合は、ユーザーがtoken1を購入して価格を下げることで均衡を保つ。
この制限条件のコード表現:

IV. 深層的な考察と展望
私たちは、Aggregator Hookの最大の意義は、Hook設計の視点を刷新したことにあると考えている。
従来、Hook設計を考える際は常にUniswap V4プール本位の視点から、「取引」に何を新しい機能を加えられるかを考えてきた。しかしAggregator Hookはまったく新しい視点を提示した。Hookの独立性ゆえに、このコントラクトは必ずしも「Hook専業」である必要はなく、Hookはその一部の機能にすぎない。つまり、Uniswap V4プールとの「橋渡し」を作る機能でありながら、それ自体はどんな処理でも実行可能なコントラクトであり、「取引」とUniswap V4がその機能の一部となる。
簡単な例を挙げよう。小さなプロジェクトチームが、トークンのクラウドセール後に一定比率の資金をUniswapに流動性として追加すると宣言することがある。Uniswap V3の時代では、クラウドセールコントラクトとUniswap V3コントラクトの操作は非同期であり、ユーザーはプロジェクトチームによる資金移転に依存せざるを得なかった。しかしUniswap V4のHookがあれば、なぜHookの独立性を活かして、流動性追加操作を同じコントラクトに直接統合しないのか? さらにはユーザーの入金時に即座に流動性を追加する(もちろんガス消費は高くなるが、透明性を求めるユーザーにとっては価値がある)ことも可能になる。これは狂気のように思えるが、Hookが持つ無限の可能性を予兆している。
Aggregator Hookの最大の制限は、取引時のガス消費にある。通常のUniswap V3のガス消費は約12万程度だが、各種流動性の追加・撤去操作を含むため、単一取引のガスはforge snapshotで測定すると42〜55万程度と、通常のswapよりもはるかに高い。このため、このような統合プール方式はストレージガスに鈍感なL2や、ガス価格の低いチェーンでのみ使用可能となる。トリックにはトリックの代償が伴う。これは合理的だ。
もちろん改善の余地はある。特に流動性の追加・撤去部分に集中している。二つの方向性がある。一つは簡単、もう一つは複雑だ。まずは簡単な方から。
-
「価格バランス」の節で取引方向の問題を議論したが、流動性撤去方式を維持する限り、targetPriceとcurrentPriceのルールは変えられない。しかし、tick0とlimitTickが等しくない必要もない。limitTick = tick0の場合、流動性注入は両方向になるため、計算式の修正が必要だが、これにより取引方向の制限をわずかに緩和できる。tick一つ分の緩和だ。
より複雑なのは:
-
すでに両方向流動性の可能性を考慮しているのなら、なぜ徹底的に貫かないのか? 流動性の撤去を強制せず、Hook-Pool管理者が必要と判断したときだけremoveLiquidityを行うようにすれば、user swap時のガス消費をさらに削減でき、Aggregator Hookをより「実用的」にできる。もちろん、これには前述の簡易案よりも複雑な流動性注入アルゴリズムが求められるだろう。
現在のAggregator Hookプールのソースコードは以下の通り。
https://github.com/Attens1423/Aggregator-Hook
取引結果を直感的に確認できるよう、afterSwap Hookの呼び出し結果を出力するようにしているが、これは必須ではない。内部には多くの中間値出力があり、forge testを使用してAggregator Hookの「パフォーマンス」を確認できる。
DODO V3が最初のパイオニアになるかもしれない。今後の計画として、Aggregator HookをDODO V3プールに統合することを目指している。そのためにはプールリザーブやプールステートの更新作業が必要だが、すべてのテストを終えた後、オープンソース化し、当初のHook-Pool構想を実現する予定だ。
TechFlow公式コミュニティへようこそ
Telegram購読グループ:https://t.me/TechFlowDaily
Twitter公式アカウント:https://x.com/TechFlowPost
Twitter英語アカウント:https://x.com/BlockFlow_News














