mcpField
V
v4-hook-generator

v4-hook-generator

github.com/uniswap開発236692 回インストール2 日前に更新
リポジトリ

v4-hook-generator について

v4-hook-generatorは、OpenZeppelin Contracts Wizardを使ってUniswap v4のhookコントラクトを設定・生成するスキルです。Solidity開発者がhookの種類や設定を選び、MCPリクエストを組み立てて、生成後のセキュリティ確認につなげます。

主な機能

  1. 01目的に応じた14種類のhookを比較
  2. 02権限、ユーティリティ、シェア、アクセス制御の設定
  3. 03標準的なMCPツール呼び出しJSONの組み立て
  4. 04hook固有の数値入力の選択
  5. 05生成からセキュリティ確認までの手順

活用シーン

  1. 01手数料、オラクル、MEV対策hookの雛形作成
  2. 02カスタムhookの権限選定
  3. 03generate_hookリクエストの準備
  4. 04実装前の設定選択肢の比較

MCP 対応

OpenZeppelin Contracts WizardのMCPツール`generate_hook`に渡すリクエストの作成を案内し、Solidityのhookコード生成につなげます。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/uniswap/uniswap-ai --skill v4-hook-generator

インストール後、Claude Code で/v4-hook-generatorを入力して読み込まれたか確認します。

詳細

v4 Hook Generator

OpenZeppelin Contracts Wizard MCP ツールを使って Uniswap v4 のフックコントラクトを生成します。このスキルでは、適切なフックタイプの選択、権限とユーティリティの設定、標準的な MCP JSON の組み立て、MCP ツールの呼び出しによるコンパイル可能な Solidity コードの生成について説明します。

セキュリティ関連スキル:生成されたフックコードは、資金を扱うコントラクトに関わります。デプロイ前に必ず生成直後に v4-security-foundations スキルを適用し、権限、デルタの計算、アクセス制御を監査してください。

このスキルを使用する場面

次のような場合に、このスキルを使用します。

  • Uniswap v4 の新しいフックコントラクトを一から作成する
  • 特定のユースケース(手数料、MEV 対策、オラクルなど)に適したベースフックタイプを選択する
  • フックの権限、ユーティリティライブラリ、シェア、アクセス制御を設定する
  • OpenZeppelin Contracts Wizard を呼び出すための標準的な MCP ツール呼び出し JSON を作成する
  • 実装を確定する前に、フック設定の選択肢ごとのトレードオフを理解する

前提条件/関連スキル:v4-security-foundations — カスタムロジックを書く前と、デプロイ前に再度実行してください。フックの設定を誤ると、ユーザーの資金が流出するおそれがあります。

フックタイプの選択表

主な目的に合ったベースフックタイプを選択します。フックに複数の目的がある場合は、最も重要な懸念に対応するタイプを選び、その上に追加のロジックを重ねてください。

目的使用するフック
カスタムスワップロジックBaseHook
非同期/遅延スワップBaseAsyncSwap
フック所有の流動性BaseCustomAccounting
カスタムカーブBaseCustomCurve
動的 LP 手数料BaseDynamicFee
動的スワップ手数料BaseOverrideFee
スワップ後の手数料BaseDynamicAfterFee
固定フック手数料BaseHookFee
MEV 対策AntiSandwichHook
JIT 対策LiquidityPenaltyHook
指値注文LimitOrderHook
待機中の利回りReHypothecationHook
オラクルBaseOracleHook
V3 互換オラクルOracleHookWithV3Adapters

選択のヒント:

  • BaseHook は汎用的な出発点です。組み込みロジックに具体的な利点がある場合に限り、特殊なタイプを選択してください。
  • BaseCustomCurve は AMM の計算全体を置き換えます。新しい価格設定アルゴリズムを実装する場合に限り使用してください。
  • AntiSandwichHook と LiquidityPenaltyHook はどちらも MEV に対処しますが、対象となるアクター(トレーダーと JIT LP)は異なります。どの攻撃ベクトルを軽減するのかを明確にしてください。
  • 下流の統合先で Uniswap v3 の IUniswapV3Pool 互換オラクルインターフェースが必要な場合は、OracleHookWithV3Adapters が適しています。

最小限の選択チェックリスト

MCP ツールを呼び出す前に、次の 6 項目をすべて決定してください。

  1. フックタイプ — 上の選択表から選択します
  2. 有効にする権限 — ロジックで実際に使用するコールバックのみ(beforeSwap、afterSwap など)
  3. ユーティリティライブラリ — 必要に応じて currencySettler、safeCast、transientStorage
  4. シェア — false、ERC20、ERC6909、ERC1155 のいずれか
  5. アクセス制御 — ownable、roles、managed のいずれか
  6. フックの入力値 — blockNumberOffset、maxAbsTickDelta(これらを使用するフックタイプのみ)

権限の設定

14 個すべての権限フラグと、それぞれを有効にするタイミングに関するガイダンスです。すべてのフラグを false にした状態から始め、フックのロジックで必要なものだけを有効にしてください。有効にする権限が増えるたびにフックの攻撃対象領域が広がり、デプロイ済みアドレスに特定のビットを設定する必要があります(下記のアドレスエンコーディングに関する注記を参照)。

権限フラグ有効にするタイミングリスク
beforeInitializeプール作成時のパラメーターを検証または制限する必要がある場合低
afterInitializeプール作成後に状態を設定する必要がある場合低
beforeAddLiquidityLP の預け入れを制限または変更する必要がある場合中
afterAddLiquidityLP のポジションを追跡したり、報酬を分配したりする場合低
beforeRemoveLiquidityロックアップ期間や退出時の手数料ロジックが必要な場合高
afterRemoveLiquidity会計処理のためにポジションの削除を追跡する場合低
beforeSwapスワップの動作を変更したり、動的手数料を適用したり、スワップをブロックしたりする場合高
afterSwapオラクルや会計処理のために、スワップ後の最終状態を観測する場合中
beforeDonateプールへの寄付を許可するユーザーを制限する場合低
afterDonate寄付イベントを追跡する場合低
beforeSwapReturnDeltaカスタム AMM カーブまたは JIT 流動性を実装する場合(重大:NoOp 攻撃ベクトル — v4-security-foundations を参照)重大
afterSwapReturnDeltaスワップの出力からフック手数料を徴収する場合高
afterAddLiquidityReturnDelta預け入れ時に LP トークンの数量を調整する場合高
afterRemoveLiquidityReturnDelta引き出し額を調整する場合高

アドレスエンコーディングに関する注記:権限はフックコントラクトのデプロイ済みアドレスのビットとしてエンコードされます。デプロイ時にアドレスに正しいビットが設定されていないと、PoolManager によってリバートされます。HookMiner(v4-periphery のもの)を使用し、正しいビットパターンを持つアドレスが生成されるソルトをマイニングしてください。デプロイ後に権限を変更してはいけません。アドレスは不変です。

ユーティリティライブラリの選択

生成されるフックには、3つのオプションのユーティリティライブラリを含めることができます。フックのロジックで使用するものだけを含めてください。

ライブラリ含める場合
currencySettlerフックが自身と PoolManager の間でトークンを移動する場合(例:カスタム会計、手数料の徴収)
safeCastフックで整数型間のキャスト時にオーバーフローする可能性がある演算を行う場合
transientStorageストレージに永続化せずに、単一トランザクション内のコールバック間でデータを渡す必要がある場合(EVM Cancun 以降、Solidity >= 0.8.24 が必要)

ガイダンス:

  • beforeSwapReturnDelta、 afterSwapReturnDelta、afterAddLiquidityReturnDelta、または afterRemoveLiquidityReturnDelta が有効な場合、ほぼ常に currencySettler が必要です。正しい sync → transfer → settle の順序を実装する settle および take ヘルパーを提供します。
  • transientStorage は、トランザクション内の状態を保存するためのストレージスロットに代わる、ガス効率の高い方法です。 コールド SSTORE に 20k gas を費やさずに、beforeSwap から afterSwap にフラグや値を渡すために使用します。
  • safeCast は、int256/uint256 の変換から導出される金額を計算する場合、特に手数料の計算での使用を推奨します。

シェアの設定

shares オプションは、生成されるフックがユーザーのシェアを表すトークンを発行するかどうかを制御します (例:フックが所有する流動性プール内の LP ポジション)。

オプション説明使用する場合
falseシェアトークンなし — フックは預け入れられた資産の所有権を追跡しませんユーザー資金を保有しないシンプルなフック
ERC20代替可能なシェアトークン — 1つのトークンがフック保有資産全体に対する比例所有権を表します交換可能なシェアを持つ、フックが管理する流動性プール
ERC6909マルチトークン(最小構成)— 1つのコントラクトで、ERC1155 より低いオーバーヘッドで複数のトークン ID を管理しますフックが複数の異なる資産クラスを効率的に管理する場合
ERC1155マルチトークン(標準)— メタデータ URI に対応した完全な ERC1155幅広いウォレットやマーケットプレイスとの互換性が必要な場合

トレードオフ:

  • false:バイトコードが最小で、シェア会計のオーバーヘッドもありません。手数料フックやオラクルに適しています。
  • ERC20:最もシンプルな代替可能シェアです。DeFi とのコンポーザビリティに優れています(例:担保として使用)。
  • ERC6909:最小限のインターフェースを備えた、ガス効率の高いマルチトークンです。新しいプロトコルの設計に適しています。
  • ERC1155:エコシステムで最も幅広くサポートされています(ウォレット、エクスプローラー、NFT マーケットプレイス)。転送時のガスコストは ERC6909 より高くなります。

アクセス制御のオプション

access オプションは、生成されるフックのコンストラクターと管理インターフェースの形式を決定します。

オプションコンストラクターの形式用途
ownableconstructor(IPoolManager, address initialOwner)1 人のオーナーがすべての管理機能を制御する場合
rolesconstructor(IPoolManager, address admin)細分化された権限を持つ複数のロールを使用する場合(OpenZeppelin AccessControl)
managedconstructor(IPoolManager, address authority)外部の権限コントラクトがアクセス許可を管理する場合(OpenZeppelin AccessManaged)

ガイダンス:

  • ownable は最もシンプルです。1 つのアドレスですべての特権操作を実行できます。初期段階のフックや個人用ツールに適しています。
  • roles は OpenZeppelin AccessControl を通じて ADMIN_ROLE、PAUSER_ROLE などを追加します。チームメンバーごとに異なる権限が必要な場合に使用してください(例:手数料は更新できるが、コントラクトはアップグレードできないキーパーボット)。
  • managed は、すべてのアクセス許可チェックを別個の AccessManager コントラクトに委譲します。複数のコントラクトにまたがる統一的なガバナンスレイヤーが必要な場合や、管理操作にタイムロックを設ける場合に使用してください。

注:access オプションを変更すると、コンストラクターのシグネチャも変わります。それに応じてデプロイスクリプトと初期化ロジックを更新してください。ownable を使用する場合は、initialOwner がゼロアドレスでないことを確認してください。OpenZeppelin の Ownable は v5 以降、ゼロアドレスを指定するとリバートします。

フック入力のリファレンス

一部のフックタイプでは、動作を調整する数値の設定入力を受け付けます。これらは MCP ツール呼び出しの inputs オブジェクトとして渡します。

入力型使用するフック説明
blockNumberOffsetuint256AntiSandwichHook、LiquidityPenaltyHookサンドイッチ/JIT 検出ウィンドウが開くまでのブロック数
maxAbsTickDeltaint24AntiSandwichHookMEV 保護が作動するまでに許容される、ブロックごとの最大ティック変動幅

これらの入力を使用しないフックタイプでは、inputs フィールドを省略するか、空のオブジェクト {} を渡してください。 サポートされていない入力を MCP ツールに渡してもエラーにはなりませんが、値は無視されます。

MCP ツール呼び出し(標準形式)

OpenZeppelin Contracts Wizard は generate_hook MCP ツールを公開しています。以下は標準的な JSON スキーマです。上のセクションで決めた内容に従って各フィールドを設定し、このオブジェクトをツールの引数として渡してください。

{
  "hook": "BaseHook",
  "name": "MyHook",
  "pausable": false,
  "currencySettler": true,
  "safeCast": true,
  "transientStorage": false,
  "shares": { "options": false },
  "permissions": {
    "beforeInitialize": false,
    "afterInitialize": false,
    "beforeAddLiquidity": false,
    "beforeRemoveLiquidity": false,
    "afterAddLiquidity": false,
    "afterRemoveLiquidity": false,
    "beforeSwap": true,
    "afterSwap": false,
    "beforeDonate": false,
    "afterDonate": false,
    "beforeSwapReturnDelta": false,
    "afterSwapReturnDelta": false,
    "afterAddLiquidityReturnDelta": false,
    "afterRemoveLiquidityReturnDelta": false
  },
  "inputs": {
    "blockNumberOffset": 1,
    "maxAbsTickDelta": 100
  },
  "access": "ownable",
  "info": { "license": "MIT" }
}

フィールドの説明:

  • hook:文字列 — 選択表にある 14 種類のフックのいずれか
  • name:文字列 — Solidity コントラクト名(パスカルケース、スペースなし)
  • pausable:ブール値 — フックを OpenZeppelin Pausable でラップし、管理機能として pause()/unpause() を追加します
  • shares.options:false | "ERC20" | "ERC6909" | "ERC1155"
  • access:"ownable" | "roles" | "managed"
  • info.license:SPDX ライセンス識別子 — オープンソースのフックには "MIT" を使用してください
  • inputs:blockNumberOffset/maxAbsTickDelta を使用しないフックタイプでは、省略するか {} を渡します

ワークフロー:収集 → 設定 → 生成 → セキュリティ確保

このスキルを使用する際は、毎回以下の手順に従ってください。

ステップ 1:要件を収集する

ユーザーに質問するか、コンテキストから推測します。

  1. フックの主な目的は何ですか?(判定表に照らし合わせます。)
  2. フックがインターセプトする必要があるライフサイクルイベントはどれですか?(権限に照らし合わせます。)
  3. フックはユーザーの資金を保持または移動しますか?(currencySettler と shares を決定します。)
  4. フックの管理者は誰ですか?(単一のオーナー、ロールベースのチーム、外部ガバナンスのいずれですか?)
  5. フックは、1 回のトランザクション内でコールバック間の状態を受け渡す必要がありますか?
  6. EVM Cancun に対応するチェーンで使用しますか?(transientStorage に必要です。)
ステップ 2:フックの種類を選択する

判定表を使って、最適なフックの種類を 1 つ特定します。ユーザーの目的が複数の種類に該当する場合は、トレードオフを説明して確認を求めます。選択した種類と、その理由を記録します。

ステップ 3:6 つすべての設定を決定する

最小限の判断チェックリストに沿って進めます。

  1. hook を選択した種類に設定します。
  2. 各権限フラグを設定します。デフォルトは false とし、ロジックで必要なものだけを有効にします。
  3. ユーティリティライブラリのガイダンスに基づいて、currencySettler、safeCast、transientStorage を設定します。
  4. shares のガイダンスに基づいて、shares.options を設定します。
  5. アクセス制御のガイダンスに基づいて、access を設定します。
  6. フックの種類で blockNumberOffset または maxAbsTickDelta を使用する場合に限り、inputs を設定します。
ステップ 4:MCP ツールを組み立てて呼び出す

ステップ 3 の設定から JSON オブジェクトを構成し、それを指定して OpenZeppelin Contracts Wizard MCP ツールを呼び出します。ツールは Solidity ソースコードを返します。ファイルを自動的に書き込むことはありません。

生成されたコードを受け取った後:

  1. コードをユーザーに表示します。
  2. 生成された主要なセクション(コンストラクター、getHookPermissions、有効化されたコールバック)を説明します。
  3. 必要な手動作業(アドレスのマイニングに HookMiner を使うこと、access が roles または managed の場合はコンストラクター引数に合わせてデプロイスクリプトを更新すること)を伝えます。
ステップ 5:セキュリティの基盤を適用する

コードをデプロイする前に、必ずユーザーに注意を促し、v4-security-foundations を実行します。

  • 有効化されたすべてのコールバックで msg.sender == address(poolManager) を確認していることを検証します。
  • 有効化された *ReturnDelta 権限について、NoOp 攻撃にさらされるリスクを確認します。
  • すべての実行パスでデルタの合計がゼロになることを確認します。
  • v4-security-foundations にあるデプロイ前監査チェックリストをすべて実行します。

重要な注意事項

  • アクセス制御によってコンストラクターの形式が変わります:ownable を選ぶと initialOwner パラメーターが追加されます。roles では admin パラメーターが、managed では authority パラメーターが追加されます。それに応じて、デプロイスクリプトとファクトリーコントラクトを更新してください。
  • 権限はフックのアドレスにエンコードされます:有効化された各権限フラグは、デプロイされたフックアドレスの下位バイトの特定のビットに対応します。PoolManager は、コールバックのたびにこれらのビットを検証します。一致するアドレスを生成するデプロイ用ソルトをマイニングするには、v4-periphery の HookMiner を使用します。
  • MCP が返すのはコードのみです。ファイルは書き込みません:生成された Solidity は文字列として返されます。自分でディスクに書き込む必要があります(例:packages/contracts/src/hooks/MyHook.sol)。

関連スキル

  • v4-security-foundations — 生成後に実行してください。 Uniswap v4 フックのセキュリティ監査:権限リスクマトリックス、NoOp 攻撃パターン、デルタ会計、アクセス制御の検証、デプロイ前監査チェックリスト全体が含まれます。このレビューを完了せずに、生成されたフックコードをデプロイしてはいけません。
  • viem-integration — 生成されたフックコントラクトをデプロイし、viem/wagmi を使って操作します
  • v4-sdk-integration — Uniswap v4 SDK を使ってデプロイ済みフックを操作します

コメント