v4-hook-generator
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesev4 Hook Generator
v4 Hook生成器
Generate Uniswap v4 hook contracts via the OpenZeppelin Contracts Wizard MCP tool. This skill
guides you through selecting the right hook type, configuring permissions and utilities, assembling
the canonical MCP JSON, and invoking the MCP tool to produce ready-to-compile Solidity code.
Security companion: Generated hook code touches fund-handling contracts. Always apply theskill immediately after generation to audit permissions, delta accounting, and access control before deploying to any network.v4-security-foundations
通过OpenZeppelin合约向导MCP工具生成Uniswap v4 hook合约。本技能会引导你选择合适的hook类型、配置权限和工具库、组装标准MCP JSON,再调用MCP工具生成可直接编译的Solidity代码。
安全提示:生成的hook代码涉及资金处理合约,在部署到任何网络之前,务必在生成代码后立即使用技能审计权限、delta记账和访问控制。v4-security-foundations
When to Use This Skill
何时使用本技能
Use this skill when you need to:
- Scaffold a new Uniswap v4 hook contract from scratch
- Select the right base hook type for a specific use case (fees, MEV protection, oracles, etc.)
- Configure hook permissions, utility libraries, shares, and access control
- Produce the canonical MCP tool call JSON to invoke the OpenZeppelin Contracts Wizard
- Understand trade-offs between hook configuration options before committing to an implementation
Prerequisite / companion skill: — run it before writing custom logic
and again before deployment. Hook misconfiguration can drain user funds.
v4-security-foundations当你需要完成以下操作时使用本技能:
- 从零搭建新的Uniswap v4 hook合约脚手架
- 为特定使用场景选择合适的基础hook类型(手续费、MEV防护、预言机等)
- 配置hook权限、工具库、份额和访问控制
- 生成标准MCP工具调用JSON来调用OpenZeppelin合约向导
- 在确定实现方案前了解不同hook配置选项的权衡
前置/配套技能: —— 在编写自定义逻辑前和部署前都需要运行该技能。hook配置错误可能导致用户资金被盗。
v4-security-foundationsHook Type Decision Table
Hook类型决策表
Choose the base hook type that matches your primary goal. If your hook has multiple goals, choose
the type that covers the most critical concern and layer additional logic on top.
| Goal | Use Hook |
|---|---|
| Custom swap logic | |
| Async/delayed swaps | |
| Hook-owned liquidity | |
| Custom curve | |
| Dynamic LP fees | |
| Dynamic swap fees | |
| Post-swap fees | |
| Fixed hook fees | |
| MEV protection | |
| JIT protection | |
| Limit orders | |
| Yield on idle | |
| Oracle | |
| V3-compatible oracle | |
Selection tips:
- is the general-purpose starting point — choose a specialized type only when the built-in logic provides concrete value.
BaseHook - replaces the entire AMM math; only use it if you are implementing a novel pricing algorithm.
BaseCustomCurve - and
AntiSandwichHookboth address MEV but target different actors (traders vs. JIT LPs). Clarify which attack vector you are mitigating.LiquidityPenaltyHook - is appropriate when downstream integrations expect a Uniswap v3
OracleHookWithV3Adapters-compatible oracle interface.IUniswapV3Pool
选择匹配你核心目标的基础hook类型。如果你的hook有多个目标,选择覆盖最核心需求的类型,再在其基础上叠加其他逻辑。
| 目标 | 使用的Hook |
|---|---|
| 自定义兑换逻辑 | |
| 异步/延迟兑换 | |
| Hook所有的流动性 | |
| 自定义曲线 | |
| 动态LP手续费 | |
| 动态兑换手续费 | |
| 兑换后手续费 | |
| 固定hook手续费 | |
| MEV防护 | |
| JIT防护 | |
| 限价单 | |
| 闲置资金收益 | |
| 预言机 | |
| 兼容V3的预言机 | |
选择提示:
- 是通用的开发起点——只有当特定类型的内置逻辑能提供明确价值时再选择专用类型。
BaseHook - 会替换整套AMM计算逻辑;只有当你要实现全新的定价算法时再使用它。
BaseCustomCurve - 和
AntiSandwichHook都用于解决MEV问题,但针对的是不同的参与方(交易者vs JIT LP),你需要明确要缓解的攻击向量。LiquidityPenaltyHook - 当下游集成需要兼容Uniswap v3 预言机接口时,适合使用
IUniswapV3Pool。OracleHookWithV3Adapters
Minimal Decision Checklist
最低决策检查清单
Before calling the MCP tool, confirm all six decisions:
- Hook type — chosen from the decision table above
- Permissions to enable — only the callbacks your logic actually uses (,
beforeSwap, etc.)afterSwap - Utility libraries — ,
currencySettler,safeCastas neededtransientStorage - Shares — ,
false,ERC20, orERC6909ERC1155 - Access control — ,
ownable, orrolesmanaged - Hook inputs — ,
blockNumberOffset(only for hook types that use them)maxAbsTickDelta
调用MCP工具前,确认以下6项决策都已完成:
- Hook类型 —— 从上方决策表中选择
- 要启用的权限 —— 仅开启你的逻辑实际需要的回调(、
beforeSwap等)afterSwap - 工具库 —— 根据需要选择、
currencySettler、safeCasttransientStorage - 份额 —— 、
false、ERC20或ERC6909ERC1155 - 访问控制 —— 、
ownable或rolesmanaged - Hook入参 —— 、
blockNumberOffset(仅对应类型的hook需要)maxAbsTickDelta
Permission Configuration
权限配置
All 14 permission flags with guidance on when to enable each. Start with all flags and
enable only what your hook logic requires. Every enabled permission increases the hook's attack
surface and requires a specific bit to be set in the hook's deployed address (see address encoding
note below).
false| Permission Flag | Enable When | Risk |
|---|---|---|
| You need to validate or restrict pool creation params | LOW |
| You need to set up state after a pool is created | LOW |
| You need to gate or transform LP deposits | MEDIUM |
| You track LP positions or distribute rewards | LOW |
| You need lock-up periods or fee-on-exit logic | HIGH |
| You track position removals for accounting | LOW |
| You modify swap behavior, apply dynamic fees, or block | HIGH |
| You observe final swap state for oracles or accounting | MEDIUM |
| You restrict who may donate to the pool | LOW |
| You track donation events | LOW |
| You implement custom AMM curves or JIT liquidity (CRITICAL: NoOp attack vector — see | CRITICAL |
| You extract a hook fee from swap output | HIGH |
| You adjust LP token amounts on deposit | HIGH |
| You adjust withdrawal amounts | HIGH |
Address encoding note: Permissions are encoded as bits in the hook contract's deployed address.
The address must have the correct bits set at deployment time or the PoolManager will revert. Use
(from ) to mine a salt that produces an address with the correct bit
pattern. Never change permissions after deployment — the address is immutable.
HookMinerv4-periphery以下是全部14个权限标记,以及启用时机的指引。初始时所有标记都设为,仅启用你的hook逻辑需要的权限。每多启用一个权限都会扩大hook的攻击面,且需要在hook的部署地址中设置对应的位(见下方地址编码说明)。
false| 权限标记 | 启用时机 | 风险等级 |
|---|---|---|
| 你需要验证或限制池子创建参数 | 低 |
| 你需要在池子创建后设置状态 | 低 |
| 你需要限制或转换LP存款 | 中 |
| 你需要跟踪LP头寸或分发奖励 | 低 |
| 你需要实现锁定期或退出收费逻辑 | 高 |
| 你需要跟踪头寸移除操作用于记账 | 低 |
| 你需要修改兑换行为、应用动态手续费或拦截兑换 | 高 |
| 你需要获取最终兑换状态用于预言机或记账 | 中 |
| 你需要限制谁可以向池子捐款 | 低 |
| 你需要跟踪捐款事件 | 低 |
| 你要实现自定义AMM曲线或JIT流动性(CRITICAL:存在NoOp攻击向量——参考 | 极高 |
| 你要从兑换输出中提取hook手续费 | 高 |
| 你要在存款时调整LP token数量 | 高 |
| 你要调整提现金额 | 高 |
地址编码说明:权限会被编码为hook合约部署地址中的比特位。部署时地址必须设置正确的比特位,否则PoolManager会回滚交易。使用中的来生成盐值,从而得到比特位符合要求的地址。部署后永远不要修改权限——地址是不可变的。
v4-peripheryHookMinerUtility Library Selection
工具库选择
Three optional utility libraries can be included in the generated hook. Include only what your
hook logic uses.
| Library | Include When |
|---|---|
| Your hook moves tokens between itself and the PoolManager (e.g., custom accounting, fee collection) |
| Your hook performs arithmetic that could overflow when casting between integer types |
| Your hook needs to pass data between callbacks within a single transaction without persisting to storage (requires EVM Cancun or later, Solidity >= 0.8.24) |
Guidance:
- is almost always needed when
currencySettler,beforeSwapReturnDelta,afterSwapReturnDelta, orafterAddLiquidityReturnDeltaare enabled — it providesafterRemoveLiquidityReturnDeltaandsettlehelpers that implement the correcttakesequence.sync → transfer → settle - is a gas-efficient alternative to storage slots for intra-transaction state. Use it to pass a flag or value from
transientStoragetobeforeSwapwithout paying 20k gas for a cold SSTORE.afterSwap - is advisable whenever you compute amounts derived from
safeCast/int256conversions, especially for fee calculations.uint256
生成hook时可以引入三个可选的工具库,仅引入你的hook逻辑需要的库即可。
| 库名称 | 引入时机 |
|---|---|
| 你的hook需要在自身和PoolManager之间转移token(例如自定义记账、手续费收取) |
| 你的hook需要执行整数类型转换,可能存在溢出风险 |
| 你的hook需要在同一笔交易的多个回调之间传递数据,且不需要持久化存储(要求EVM Cancun及以上版本,Solidity >= 0.8.24) |
指引:
- 当启用了、
beforeSwapReturnDelta、afterSwapReturnDelta或afterAddLiquidityReturnDelta时,几乎都需要引入afterRemoveLiquidityReturnDelta——它提供了currencySettler和settle辅助方法,实现了正确的take流程。sync → transfer → settle - 对于交易内的状态传递,是比存储槽更省gas的方案。你可以用它在
transientStorage和beforeSwap之间传递标记或数值,不需要为冷SSTORE支付20k gas。afterSwap - 当你需要基于/
int256转换计算金额,尤其是手续费计算时,建议使用uint256。safeCast
Shares Configuration
份额配置
The option controls whether the generated hook issues a token representing user shares
(e.g., LP positions in hook-owned liquidity pools).
shares| Option | Description | Use When |
|---|---|---|
| No share token — hook does not track ownership of deposited assets | Simple hooks that do not hold user funds |
| Fungible share token — one token represents proportional ownership of all hook-held assets | Hook-managed liquidity pools with interchangeable shares |
| Multi-token (minimal) — one contract manages many token IDs with lower overhead than ERC1155 | Hook manages multiple distinct asset classes efficiently |
| Multi-token (standard) — full ERC1155 with metadata URI support | Hook needs broad wallet and marketplace compatibility |
Trade-offs:
- : smallest bytecode, no share accounting overhead; appropriate for fee hooks and oracles.
false - : simplest fungible share; good DeFi composability (e.g., used as collateral).
ERC20 - : gas-efficient multi-token with a minimal interface; preferred for new protocol designs.
ERC6909 - : widest ecosystem support (wallets, explorers, NFT marketplaces); higher gas cost per transfer than ERC6909.
ERC1155
shares| 选项 | 说明 | 使用场景 |
|---|---|---|
| 无份额token —— hook不跟踪存入资产的所有权 | 不持有用户资金的简单hook |
| 同质化份额token —— 一枚token代表对hook持有所有资产的比例所有权 | hook管理的流动性池,份额可互换 |
| 极简多token标准 —— 单个合约管理多个token ID,开销比ERC1155更低 | hook需要高效管理多个不同的资产类别 |
| 标准多token标准 —— 完整的ERC1155实现,支持metadata URI | hook需要兼容广泛的钱包和市场 |
权衡:
- :字节码最小,无份额记账开销;适合手续费hook和预言机。
false - :最简单的同质化份额实现;DeFi composability好(例如可作为抵押品)。
ERC20 - :省gas的多token实现,接口极简;新协议设计的首选。
ERC6909 - :生态支持最广泛(钱包、浏览器、NFT市场);转账gas成本比ERC6909高。
ERC1155
Access Control Options
访问控制选项
The option shapes the constructor and administrative interface of the generated hook.
access| Option | Constructor Shape | Use When |
|---|---|---|
| | Single owner controls all admin functions |
| | Multiple roles with granular permissions (OpenZeppelin AccessControl) |
| | External authority contract governs permissions (OpenZeppelin AccessManaged) |
Guidance:
- is the simplest — one address can perform all privileged operations. Suitable for early-stage hooks and personal tools.
ownable - adds
roles,ADMIN_ROLE, etc. via OpenZeppelinPAUSER_ROLE. Use when different team members need different privileges (e.g., a keeper bot that can update fees but cannot upgrade the contract).AccessControl - delegates all permission checks to a separate
managedcontract. Use when you need a unified governance layer across multiple contracts or want timelocked admin actions.AccessManager
Note: Changing theoption changes the constructor signature. Update deployment scripts and initialization logic accordingly. When usingaccess, ensure theownableis not the zero address — OpenZeppelin'sinitialOwnerreverts on zero address since v5.Ownable
access| 选项 | 构造函数结构 | 使用场景 |
|---|---|---|
| | 单个所有者控制所有管理功能 |
| | 多角色粒度权限控制(基于OpenZeppelin AccessControl) |
| | 外部权限合约管理权限(基于OpenZeppelin AccessManaged) |
指引:
- 是最简单的方案——单个地址可执行所有特权操作。适合早期阶段的hook和个人工具。
ownable - 基于OpenZeppelin
roles实现,提供AccessControl、ADMIN_ROLE等角色。当不同团队成员需要不同权限时使用(例如运维机器人可以更新手续费,但不能升级合约)。PAUSER_ROLE - 将所有权限校验委托给独立的
managed合约。当你需要在多个合约之间使用统一的治理层,或者需要管理员操作带时间锁时使用。AccessManager
注意:修改选项会改变构造函数签名,请相应更新部署脚本和初始化逻辑。使用access时,确保ownable不是零地址——OpenZeppelin的initialOwner从v5开始遇到零地址会回滚。Ownable
Hook Inputs Reference
Hook入参参考
Some hook types accept numeric configuration inputs that tune behavior. These are passed as the
object in the MCP tool call.
inputs| Input | Type | Used By | Description |
|---|---|---|---|
| | | Number of blocks before sandwich/JIT detection window opens |
| | | Maximum tick movement allowed per block before MEV protection triggers |
For hook types that do not use these inputs, omit the field or pass an empty object .
Passing unsupported inputs to the MCP tool will not cause an error but the values will be ignored.
inputs{}部分hook类型支持数值配置入参来调整行为,这些参数会作为MCP工具调用的对象传递。
inputs| 入参 | 类型 | 被哪些hook使用 | 说明 |
|---|---|---|---|
| | | 三明治/JIT检测窗口开启前的区块数 |
| | | 触发MEV防护前每个区块允许的最大tick变动 |
对于不需要这些入参的hook类型,省略字段或者传入空对象即可。向MCP工具传递不支持的入参不会导致错误,但参数值会被忽略。
inputs{}MCP Tool Call (Canonical)
MCP工具调用(标准格式)
The OpenZeppelin Contracts Wizard exposes a MCP tool. The following is the
canonical JSON schema — populate each field according to your decisions from the sections above,
then pass this object as the tool's argument.
generate_hookjson
{
"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" }
}Field notes:
- : string — one of the 14 hook types from the decision table
hook - : string — the Solidity contract name (PascalCase, no spaces)
name - : boolean — wraps the hook in OpenZeppelin
pausable; addsPausable/pause()admin functionsunpause() - :
shares.options|false|"ERC20"|"ERC6909""ERC1155" - :
access|"ownable"|"roles""managed" - : SPDX license identifier — use
info.licensefor open-source hooks"MIT" - : omit or pass
inputsfor hook types that do not use{}/blockNumberOffsetmaxAbsTickDelta
OpenZeppelin合约向导提供了 MCP工具,以下是标准JSON schema——根据你在上文各节的决策填充每个字段,然后将该对象作为工具的入参传递。
generate_hookjson
{
"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" }
}字段说明:
- :字符串 —— 决策表中14种hook类型之一
hook - :字符串 —— Solidity合约名称(大驼峰命名,无空格)
name - :布尔值 —— 为hook添加OpenZeppelin
pausable能力;新增Pausable/pause()管理功能unpause() - :
shares.options|false|"ERC20"|"ERC6909""ERC1155" - :
access|"ownable"|"roles""managed" - :SPDX许可证标识符 —— 开源hook使用
info.license"MIT" - :如果hook类型不需要
inputs/blockNumberOffset则省略或传入maxAbsTickDelta{}
Workflow: Gather → Configure → Generate → Secure
工作流:需求收集 → 配置 → 生成 → 安全审计
Follow these steps in order every time you use this skill.
每次使用本技能时都按顺序执行以下步骤:
Step 1: Gather Requirements
步骤1:收集需求
Ask the user (or infer from context):
- What is the hook's primary goal? (Map to the decision table.)
- Which lifecycle events does the hook need to intercept? (Map to permissions.)
- Does the hook hold or move user funds? (Determines and
currencySettler.)shares - Who administers the hook? (Single owner, role-based team, or external governance?)
- Does the hook need to pass state between callbacks within a single transaction?
- Is this for a chain with EVM Cancun support? (Required for .)
transientStorage
询问用户(或从上下文推断):
- Hook的核心目标是什么?(匹配决策表)
- Hook需要拦截哪些生命周期事件?(匹配权限)
- Hook是否持有或转移用户资金?(决定和
currencySettler配置)shares - 谁来管理hook?(单个所有者、基于角色的团队、还是外部治理?)
- Hook是否需要在同一笔交易的多个回调之间传递状态?
- 部署的链是否支持EVM Cancun?(使用的必要条件)
transientStorage
Step 2: Select Hook Type
步骤2:选择Hook类型
Using the decision table, identify the single best hook type. If the user's goal maps to multiple
types, explain the trade-offs and ask them to confirm. Document the chosen type and the reasoning.
使用决策表确定最合适的单一hook类型。如果用户的目标对应多个类型,说明不同方案的权衡并请用户确认。记录选择的类型和理由。
Step 3: Configure All Six Decisions
步骤3:完成全部6项决策配置
Work through the minimal decision checklist:
- Set to the chosen type.
hook - Set each permission flag — default , enable only what the logic requires.
false - Set ,
currencySettler,safeCastbased on utility library guidance.transientStorage - Set based on shares guidance.
shares.options - Set based on access control guidance.
access - Set only if the hook type uses
inputsorblockNumberOffset.maxAbsTickDelta
对照最低决策检查清单完成配置:
- 将设为选择的类型。
hook - 设置每个权限标记 —— 默认,仅启用逻辑需要的权限。
false - 根据工具库指引设置、
currencySettler、safeCast。transientStorage - 根据份额指引设置。
shares.options - 根据访问控制指引设置。
access - 仅当hook类型需要时设置或
blockNumberOffset。maxAbsTickDelta
Step 4: Assemble and Call the MCP Tool
步骤4:组装并调用MCP工具
Construct the JSON object from Step 3 and call the OpenZeppelin Contracts Wizard MCP tool with it.
The tool returns Solidity source code — it does not write files automatically.
After receiving the generated code:
- Display the code to the user.
- Explain the key generated sections (constructor, , enabled callbacks).
getHookPermissions - Note any manual steps required (HookMiner for address mining, deployment script updates for
constructor args if is
accessorroles).managed
基于步骤3的配置构建JSON对象,用它调用OpenZeppelin合约向导MCP工具。工具会返回Solidity源代码——不会自动写入文件。
收到生成的代码后:
-
向用户展示代码。
-
说明生成的核心部分(构造函数、、启用的回调)。
getHookPermissions -
说明需要手动完成的步骤(用HookMiner生成地址、如果是
access或roles需要更新部署脚本的构造函数参数)。managed
Step 5: Apply Security Foundations
步骤5:应用安全基础检查
Always remind the user — and invoke — before the code is deployed:
v4-security-foundations- Verify all enabled callbacks check .
msg.sender == address(poolManager) - Review any enabled permissions for NoOp attack exposure.
*ReturnDelta - Confirm delta accounting sums to zero for every execution path.
- Run the full pre-deployment audit checklist from .
v4-security-foundations
务必提醒用户——代码部署前调用:
v4-security-foundations- 验证所有启用的回调都检查。
msg.sender == address(poolManager) - 检查所有启用的权限是否存在NoOp攻击风险。
*ReturnDelta - 确认所有执行路径的delta记账总和为0。
- 执行中的完整部署前审计检查清单。
v4-security-foundations
Important Notes
重要说明
- Access control changes constructor shape: Choosing adds an
ownableparameter;initialOwneradds anrolesparameter;adminadds anmanagedparameter. Update deployment scripts and factory contracts accordingly.authority - Permissions encode in the hook address: Each enabled permission flag corresponds to a specific
bit in the lower bytes of the hook's deployed address. The PoolManager validates these bits on
every callback. Use from
HookMinerto mine a deployment salt that produces a matching address.v4-periphery - MCP returns code only — it does not write files: The generated Solidity is returned as a
string. You must write it to disk yourself (e.g., ).
packages/contracts/src/hooks/MyHook.sol
- 访问控制会修改构造函数结构:选择会新增
ownable参数;initialOwner会新增roles参数;admin会新增managed参数。请相应更新部署脚本和工厂合约。authority - 权限编码在hook地址中:每个启用的权限标记对应hook部署地址低字节中的特定比特位。PoolManager会在每次回调时校验这些比特位。使用中的
v4-periphery生成部署盐值,得到匹配的地址。HookMiner - MCP仅返回代码——不会写入文件:生成的Solidity代码以字符串形式返回,你需要手动写入磁盘(例如)。
packages/contracts/src/hooks/MyHook.sol
Related Skills
相关技能
- — Run this after generation. Security audit for Uniswap v4 hooks: permission risk matrix, NoOp attack patterns, delta accounting, access control verification, and the full pre-deployment audit checklist. Generated hook code should never be deployed without completing this review.
v4-security-foundations - — Deploy generated hook contracts and interact with them using viem/wagmi
viem-integration - — Interact with deployed hooks via the Uniswap v4 SDK
v4-sdk-integration
- —— 生成代码后务必运行。Uniswap v4 hook安全审计工具:包含权限风险矩阵、NoOp攻击模式、delta记账、访问控制验证和完整的部署前审计检查清单。生成的hook代码必须完成该审查才能部署。
v4-security-foundations - —— 部署生成的hook合约,使用viem/wagmi与合约交互
viem-integration - —— 通过Uniswap v4 SDK与部署的hook交互
v4-sdk-integration