v4-security-foundations

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

v4 Hook Security Foundations

v4 Hook 安全基础

Security-first guide for building Uniswap v4 hooks. Hook vulnerabilities can drain user funds—understand these concepts before writing any hook code.
这是一份以安全为先的Uniswap v4 Hook开发指南。Hook漏洞可能导致用户资金被盗——在编写任何Hook代码前,请务必理解这些概念。

Threat Model

威胁模型

Before writing code, understand the v4 security context:
Threat AreaDescriptionMitigation
Caller VerificationOnly
PoolManager
should invoke hook functions
Verify
msg.sender == address(poolManager)
Sender Identity
msg.sender
always equals PoolManager, never the end user
Use
sender
parameter for user identity
Router ContextThe
sender
parameter identifies the router, not the user
Implement router allowlisting
State ExposureHook state is readable during mid-transaction executionAvoid storing sensitive data on-chain
Reentrancy SurfaceExternal calls from hooks can enable reentrancyUse reentrancy guards; minimize external calls
编写代码前,请先了解v4的安全背景:
威胁领域描述缓解措施
调用者验证
PoolManager
可调用Hook函数
验证
msg.sender == address(poolManager)
发送者身份
msg.sender
始终等于PoolManager,而非终端用户
使用
sender
参数获取用户身份
路由器上下文
sender
参数标识的是路由器,而非用户
实现路由器白名单机制
状态暴露Hook状态在交易执行过程中可被读取避免在链上存储敏感数据
重入攻击面Hook发起的外部调用可能引发重入攻击使用重入防护;尽量减少外部调用

Permission Flags Risk Matrix

权限标志风险矩阵

All 14 hook permissions with associated risk levels:
Permission FlagRisk LevelDescriptionSecurity Notes
beforeInitialize
LOWCalled before pool creationValidate pool parameters
afterInitialize
LOWCalled after pool creationSafe for state initialization
beforeAddLiquidity
MEDIUMBefore LP depositsCan block legitimate LPs
afterAddLiquidity
LOWAfter LP depositsSafe for tracking/rewards
beforeRemoveLiquidity
HIGHBefore LP withdrawalsCan trap user funds
afterRemoveLiquidity
LOWAfter LP withdrawalsSafe for tracking
beforeSwap
HIGHBefore swap executionCan manipulate prices
afterSwap
MEDIUMAfter swap executionCan observe final state
beforeDonate
LOWBefore donationsAccess control only
afterDonate
LOWAfter donationsSafe for tracking
beforeSwapReturnDelta
CRITICALReturns custom swap amountsNoOp attack vector
afterSwapReturnDelta
HIGHModifies post-swap amountsCan extract value
afterAddLiquidityReturnDelta
HIGHModifies LP token amountsCan shortchange LPs
afterRemoveLiquidityReturnDelta
HIGHModifies withdrawal amountsCan steal funds
所有14种Hook权限及其相关风险等级:
权限标志风险等级描述安全注意事项
beforeInitialize
池创建前调用验证池参数
afterInitialize
池创建后调用适合用于状态初始化
beforeAddLiquidity
流动性存入前可能阻止合法的流动性提供者操作
afterAddLiquidity
流动性存入后适合用于跟踪/奖励发放
beforeRemoveLiquidity
流动性提取前可能锁定用户资金
afterRemoveLiquidity
流动性提取后适合用于跟踪
beforeSwap
交易执行前可能操纵价格
afterSwap
交易执行后可观察最终状态
beforeDonate
捐赠前仅做访问控制
afterDonate
捐赠后适合用于跟踪
beforeSwapReturnDelta
关键返回自定义交易金额NoOp攻击向量
afterSwapReturnDelta
修改交易后金额可能窃取资产
afterAddLiquidityReturnDelta
修改LP代币数量可能少给流动性提供者发放代币
afterRemoveLiquidityReturnDelta
修改提取金额可能窃取资金

Risk Thresholds

风险阈值

  • LOW: Unlikely to cause fund loss
  • MEDIUM: Requires careful implementation
  • HIGH: Can cause fund loss if misimplemented
  • CRITICAL: Can enable complete fund theft
  • :不太可能造成资金损失
  • :需要谨慎实现
  • :若实现不当可能造成资金损失
  • 关键:可能导致资金全部被盗

CRITICAL: NoOp Rug Pull Attack

关键风险:NoOp 地毯式攻击

The
BEFORE_SWAP_RETURNS_DELTA
permission (bit 10) is the most dangerous hook permission. A malicious hook can:
  1. Return a delta claiming it handled the entire swap
  2. PoolManager accepts this and settles the trade
  3. Hook keeps all input tokens without providing output
  4. User loses entire swap amount
BEFORE_SWAP_RETURNS_DELTA
权限(第10位)是最危险的Hook权限。恶意Hook可通过以下方式攻击:
  1. 返回一个delta,声称已处理整个交易
  2. PoolManager接受该delta并完成交易结算
  3. Hook扣留所有输入代币,不提供输出
  4. 用户损失全部交易金额

Attack Pattern

攻击模式

solidity
// MALICIOUS - DO NOT USE
function beforeSwap(
    address,
    PoolKey calldata,
    IPoolManager.SwapParams calldata params,
    bytes calldata
) external override returns (bytes4, BeforeSwapDelta, uint24) {
    // Claim to handle the swap but steal tokens
    int128 amountSpecified = int128(params.amountSpecified);
    BeforeSwapDelta delta = toBeforeSwapDelta(amountSpecified, 0);
    return (BaseHook.beforeSwap.selector, delta, 0);
}
solidity
// MALICIOUS - DO NOT USE
function beforeSwap(
    address,
    PoolKey calldata,
    IPoolManager.SwapParams calldata params,
    bytes calldata
) external override returns (bytes4, BeforeSwapDelta, uint24) {
    // Claim to handle the swap but steal tokens
    int128 amountSpecified = int128(params.amountSpecified);
    BeforeSwapDelta delta = toBeforeSwapDelta(amountSpecified, 0);
    return (BaseHook.beforeSwap.selector, delta, 0);
}

Detection

检测方法

Before interacting with ANY hook that has
beforeSwapReturnDelta: true
:
  1. Audit the hook code - Verify legitimate use case
  2. Check ownership - Is it upgradeable? By whom?
  3. Verify track record - Has it been audited by reputable firms?
  4. Start small - Test with minimal amounts first
在与任何开启
beforeSwapReturnDelta: true
的Hook交互前:
  1. 审计Hook代码 - 验证其使用场景的合法性
  2. 检查所有权 - 它是否可升级?由谁控制?
  3. 验证过往记录 - 是否经过知名审计公司审计?
  4. 小额测试 - 先使用最小金额进行测试

Legitimate Uses

合法用途

NoOp patterns are valid for:
  • Just-in-time liquidity (JIT)
  • Custom AMM curves
  • Intent-based trading systems
  • RFQ/PMM integrations
But each requires careful implementation and audit.
NoOp模式的合法用途包括:
  • 即时流动性(JIT)
  • 自定义AMM曲线
  • 基于意图的交易系统
  • RFQ/PMM集成
但每种场景都需要谨慎实现并经过审计。

Delta Accounting Fundamentals

Delta 记账基础

v4 uses a credit/debit system through the PoolManager:
v4通过PoolManager使用借贷记账系统:

Core Invariant

核心不变量

text
For every transaction: sum(deltas) == 0
The PoolManager tracks what each address owes or is owed. At transaction end, all debts must be settled.
text
For every transaction: sum(deltas) == 0
PoolManager跟踪每个地址的欠款或应收款。交易结束时,所有债务必须结清。

Key Functions

核心函数

FunctionPurposeDirection
take(currency, to, amount)
Withdraw tokens from PoolManagerYou receive tokens
settle(currency)
Pay tokens to PoolManagerYou send tokens
sync(currency)
Update PoolManager balance trackingPreparation for settle
函数用途方向
take(currency, to, amount)
从PoolManager提取代币你接收代币
settle(currency)
向PoolManager支付代币你发送代币
sync(currency)
更新PoolManager余额跟踪为结算做准备

Settlement Pattern

结算模式

solidity
// Correct pattern: sync before settle
poolManager.sync(currency);
currency.transfer(address(poolManager), amount);
poolManager.settle(currency);
solidity
// Correct pattern: sync before settle
poolManager.sync(currency);
currency.transfer(address(poolManager), amount);
poolManager.settle(currency);

Common Mistakes

常见错误

  1. Forgetting sync: Settlement fails without sync
  2. Wrong order: Must sync → transfer → settle
  3. Partial settlement: Leaves transaction in invalid state
  4. Double settlement: Causes accounting errors
  1. 忘记sync:未执行sync会导致结算失败
  2. 顺序错误:必须遵循sync → transfer → settle的顺序
  3. 部分结算:会使交易处于无效状态
  4. 重复结算:会导致记账错误

Access Control Patterns

访问控制模式

PoolManager Verification

PoolManager 验证

Every hook callback MUST verify the caller:
solidity
modifier onlyPoolManager() {
    require(msg.sender == address(poolManager), "Not PoolManager");
    _;
}

function beforeSwap(
    address sender,
    PoolKey calldata key,
    IPoolManager.SwapParams calldata params,
    bytes calldata hookData
) external override onlyPoolManager returns (bytes4, BeforeSwapDelta, uint24) {
    // Safe to proceed
}
每个Hook回调必须验证调用者:
solidity
modifier onlyPoolManager() {
    require(msg.sender == address(poolManager), "Not PoolManager");
    _;
}

function beforeSwap(
    address sender,
    PoolKey calldata key,
    IPoolManager.SwapParams calldata params,
    bytes calldata hookData
) external override onlyPoolManager returns (bytes4, BeforeSwapDelta, uint24) {
    // Safe to proceed
}

Why This Matters

为什么这很重要

Without this check:
  • Anyone can call hook functions directly
  • Attackers can manipulate hook state
  • Funds can be drained through fake callbacks
如果没有此检查:
  • 任何人都可以直接调用Hook函数
  • 攻击者可操纵Hook状态
  • 可通过伪造回调窃取资金

Router Verification Patterns

路由器验证模式

The
sender
parameter is the router, not the end user. For hooks that need user identity:
sender
参数代表的是路由器,而非终端用户。对于需要获取用户身份的Hook:

Allowlisting Pattern

白名单模式

solidity
mapping(address => bool) public allowedRouters;

function beforeSwap(
    address sender,  // This is the router
    PoolKey calldata key,
    IPoolManager.SwapParams calldata params,
    bytes calldata hookData
) external override onlyPoolManager returns (bytes4, BeforeSwapDelta, uint24) {
    require(allowedRouters[sender], "Router not allowed");
    // Proceed with swap
}
solidity
mapping(address => bool) public allowedRouters;

function beforeSwap(
    address sender,  // This is the router
    PoolKey calldata key,
    IPoolManager.SwapParams calldata params,
    bytes calldata hookData
) external override onlyPoolManager returns (bytes4, BeforeSwapDelta, uint24) {
    require(allowedRouters[sender], "Router not allowed");
    // Proceed with swap
}

User Identity via hookData

通过hookData获取用户身份

solidity
function beforeSwap(
    address sender,
    PoolKey calldata key,
    IPoolManager.SwapParams calldata params,
    bytes calldata hookData
) external override onlyPoolManager returns (bytes4, BeforeSwapDelta, uint24) {
    // Decode user address from hookData (router must include it)
    address user = abi.decode(hookData, (address));
    // CAUTION: Router must be trusted to provide accurate user
}
solidity
function beforeSwap(
    address sender,
    PoolKey calldata key,
    IPoolManager.SwapParams calldata params,
    bytes calldata hookData
) external override onlyPoolManager returns (bytes4, BeforeSwapDelta, uint24) {
    // Decode user address from hookData (router must include it)
    address user = abi.decode(hookData, (address));
    // CAUTION: Router must be trusted to provide accurate user
}

msg.sender Trap

msg.sender 陷阱

solidity
// WRONG - msg.sender is always PoolManager in hooks
function beforeSwap(...) external {
    require(msg.sender == someUser); // Always fails or wrong
}

// CORRECT - Use sender parameter
function beforeSwap(address sender, ...) external {
    require(allowedRouters[sender], "Invalid router");
}
solidity
// WRONG - msg.sender is always PoolManager in hooks
function beforeSwap(...) external {
    require(msg.sender == someUser); // Always fails or wrong
}

// CORRECT - Use sender parameter
function beforeSwap(address sender, ...) external {
    require(allowedRouters[sender], "Invalid router");
}

Token Handling Hazards

代币处理风险

Not all tokens behave like standard ERC-20s:
Token TypeHazardMitigation
Fee-on-transferReceived amount < sent amountMeasure actual balance changes
RebasingBalance changes without transfersAvoid storing raw balances
ERC-777Transfer callbacks enable reentrancyUse reentrancy guards
PausableTransfers can be blockedHandle transfer failures gracefully
BlocklistSpecific addresses blockedTest with production addresses
Low decimalsPrecision loss in calculationsUse appropriate scaling
并非所有代币都表现得像标准ERC-20:
代币类型风险缓解措施
手续费代币实际收到的金额 < 发送金额测量实际余额变化
重基代币无需转账即可改变余额避免存储原始余额
ERC-777转账回调可能引发重入攻击使用重入防护
Pausable代币转账可能被阻止优雅处理转账失败情况
黑名单代币特定地址被禁止转账使用生产地址进行测试
低精度代币计算时可能丢失精度使用适当的缩放比例

Safe Balance Check Pattern

安全余额检查模式

solidity
function safeTransferIn(
    IERC20 token,
    address from,
    uint256 amount
) internal returns (uint256 received) {
    uint256 balanceBefore = token.balanceOf(address(this));
    token.safeTransferFrom(from, address(this), amount);
    received = token.balanceOf(address(this)) - balanceBefore;
}
solidity
function safeTransferIn(
    IERC20 token,
    address from,
    uint256 amount
) internal returns (uint256 received) {
    uint256 balanceBefore = token.balanceOf(address(this));
    token.safeTransferFrom(from, address(this), amount);
    received = token.balanceOf(address(this)) - balanceBefore;
}

Base Hook Template

基础Hook模板

Start with all permissions disabled. Enable only what you need:
solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import {BaseHook} from "v4-periphery/src/base/hooks/BaseHook.sol";
import {Hooks} from "v4-core/src/libraries/Hooks.sol";
import {IPoolManager} from "v4-core/src/interfaces/IPoolManager.sol";
import {PoolKey} from "v4-core/src/types/PoolKey.sol";
import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "v4-core/src/types/BeforeSwapDelta.sol";

contract SecureHook is BaseHook {
    constructor(IPoolManager _poolManager) BaseHook(_poolManager) {}

    function getHookPermissions() public pure override returns (Hooks.Permissions memory) {
        return Hooks.Permissions({
            beforeInitialize: false,
            afterInitialize: false,
            beforeAddLiquidity: false,
            afterAddLiquidity: false,
            beforeRemoveLiquidity: false,
            afterRemoveLiquidity: false,
            beforeSwap: false,           // Enable only if needed
            afterSwap: false,            // Enable only if needed
            beforeDonate: false,
            afterDonate: false,
            beforeSwapReturnDelta: false,      // DANGER: NoOp attack vector
            afterSwapReturnDelta: false,       // DANGER: Can extract value
            afterAddLiquidityReturnDelta: false,
            afterRemoveLiquidityReturnDelta: false
        });
    }

    // Implement only the callbacks you enabled above
}
See references/base-hook-template.md for a complete implementation template.
从禁用所有权限开始,仅启用你需要的权限:
solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import {BaseHook} from "v4-periphery/src/base/hooks/BaseHook.sol";
import {Hooks} from "v4-core/src/libraries/Hooks.sol";
import {IPoolManager} from "v4-core/src/interfaces/IPoolManager.sol";
import {PoolKey} from "v4-core/src/types/PoolKey.sol";
import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "v4-core/src/types/BeforeSwapDelta.sol";

contract SecureHook is BaseHook {
    constructor(IPoolManager _poolManager) BaseHook(_poolManager) {}

    function getHookPermissions() public pure override returns (Hooks.Permissions memory) {
        return Hooks.Permissions({
            beforeInitialize: false,
            afterInitialize: false,
            beforeAddLiquidity: false,
            afterAddLiquidity: false,
            beforeRemoveLiquidity: false,
            afterRemoveLiquidity: false,
            beforeSwap: false,           // Enable only if needed
            afterSwap: false,            // Enable only if needed
            beforeDonate: false,
            afterDonate: false,
            beforeSwapReturnDelta: false,      // DANGER: NoOp attack vector
            afterSwapReturnDelta: false,       // DANGER: Can extract value
            afterAddLiquidityReturnDelta: false,
            afterRemoveLiquidityReturnDelta: false
        });
    }

    // Implement only the callbacks you enabled above
}
完整的实现模板请参考references/base-hook-template.md

Security Checklist

安全检查清单

Before deploying any hook:
#CheckStatus
1All hook callbacks verify
msg.sender == poolManager
[ ]
2Router allowlisting implemented if needed[ ]
3No unbounded loops that can cause OOG[ ]
4Reentrancy guards on external calls[ ]
5Delta accounting sums to zero[ ]
6Fee-on-transfer tokens handled[ ]
7No hardcoded addresses[ ]
8Slippage parameters respected[ ]
9No sensitive data stored on-chain[ ]
10Upgrade mechanisms secured (if applicable)[ ]
11
beforeSwapReturnDelta
justified if enabled
[ ]
12Fuzz testing completed[ ]
13Invariant testing completed[ ]
部署任何Hook前,请完成以下检查:
#检查项状态
1所有Hook回调都验证
msg.sender == poolManager
[ ]
2已实现路由器白名单(若需要)[ ]
3无可能导致OOG的无界循环[ ]
4外部调用已添加重入防护[ ]
5Delta记账总和为零[ ]
6已处理手续费代币[ ]
7无硬编码地址[ ]
8已遵守滑点参数[ ]
9无敏感数据存储在链上[ ]
10升级机制已做安全防护(若适用)[ ]
11若启用
beforeSwapReturnDelta
,已证明其合理性
[ ]
12已完成模糊测试[ ]
13已完成不变量测试[ ]

Gas Budget Guidelines

燃气预算指南

Hook callbacks execute inside the PoolManager's transaction context. Excessive gas consumption can make swaps revert or become economically unviable.
Hook回调在PoolManager的交易上下文中执行,过高的燃气消耗可能导致交易回滚或在经济上不可行。

Gas Budgets by Callback

各回调的燃气预算

CallbackTarget BudgetHard CeilingNotes
beforeSwap
< 50,000 gas150,000 gasRuns on every swap; keep lean
afterSwap
< 30,000 gas100,000 gasAnalytics/tracking only
beforeAddLiquidity
< 50,000 gas200,000 gasMay include access control
afterAddLiquidity
< 30,000 gas100,000 gasReward tracking
beforeRemoveLiquidity
< 50,000 gas200,000 gasLock validation
afterRemoveLiquidity
< 30,000 gas100,000 gasTracking/accounting
Callbacks with external calls< 100,000 gas300,000 gasExternal DEX routing, oracles
回调目标预算硬上限说明
beforeSwap
< 50,000 gas150,000 gas每次交易都会执行;尽量精简
afterSwap
< 30,000 gas100,000 gas仅用于分析/跟踪
beforeAddLiquidity
< 50,000 gas200,000 gas可能包含访问控制
afterAddLiquidity
< 30,000 gas100,000 gas奖励跟踪
beforeRemoveLiquidity
< 50,000 gas200,000 gas锁定验证
afterRemoveLiquidity
< 30,000 gas100,000 gas跟踪/记账
带外部调用的回调< 100,000 gas300,000 gas外部DEX路由、预言机

Common Gas Pitfalls

常见燃气陷阱

  1. Unbounded loops: Iterating over dynamic arrays (e.g., all active positions) can exceed block gas limits. Cap array sizes or use pagination.
  2. SSTORE in hot paths: Each new storage slot costs ~20,000 gas. Prefer transient storage (
    tstore
    /
    tload
    ) for data that doesn't persist beyond the transaction. Requires Solidity >= 0.8.24 with EVM target set to
    cancun
    or later.
  3. External calls: Each cross-contract call adds ~2,600 gas base cost plus the callee's execution. Batch calls where possible.
  4. String operations: Avoid
    string
    manipulation in callbacks; use
    bytes32
    for identifiers.
  5. Redundant reads: Cache
    poolManager
    calls — repeated
    getSlot0()
    or
    getLiquidity()
    reads cost gas each time.
  1. 无界循环:遍历动态数组(如所有活跃仓位)可能超出区块燃气限制。限制数组大小或使用分页。
  2. 热点路径中的SSTORE:每个新存储槽消耗约20,000 gas。对于不需要跨交易持久化的数据,优先使用临时存储(
    tstore
    /
    tload
    )。要求Solidity >= 0.8.24,且EVM目标设置为
    cancun
    或更高版本。
  3. 外部调用:每次跨合约调用会增加约2,600 gas的基础成本加上被调用者的执行成本。尽可能批量调用。
  4. 字符串操作:避免在回调中进行
    string
    操作;使用
    bytes32
    作为标识符。
  5. 冗余读取:缓存
    poolManager
    调用——重复调用
    getSlot0()
    getLiquidity()
    每次都会消耗燃气。

Measuring Gas

测量燃气消耗

bash
undefined
bash
undefined

Profile a specific hook callback with Foundry

Profile a specific hook callback with Foundry

forge test --match-test test_beforeSwapGas --gas-report
forge test --match-test test_beforeSwapGas --gas-report

Snapshot gas usage across all tests

Snapshot gas usage across all tests

forge snapshot --match-contract MyHookTest

---
forge snapshot --match-contract MyHookTest

---

Risk Scoring System

风险评分系统

Calculate your hook's risk score (0-33):
CategoryPointsCriteria
Permissions0-14Sum of enabled permission risk levels
External Calls0-5Number and type of external interactions
State Complexity0-5Amount of mutable state
Upgrade Mechanism0-5Proxy, admin functions, etc.
Token Handling0-4Non-standard token support
计算你的Hook风险评分(0-33):
类别分值标准
权限0-14已启用权限的风险等级总和
外部调用0-5外部交互的数量和类型
状态复杂度0-5可变状态的数量
升级机制0-5代理、管理员函数等。
代币处理0-4非标准代币支持

Audit Tier Recommendations

审计等级建议

ScoreRisk LevelRecommendation
0-5LowSelf-audit + peer review
6-12MediumProfessional audit recommended
13-20HighProfessional audit required
21-33CriticalMultiple audits required
评分风险等级建议
0-5自审计 + 同行评审
6-12建议进行专业审计
13-20必须进行专业审计
21-33关键需要多次审计

Absolute Prohibitions

绝对禁止事项

Never do these things in a hook:
  1. Never trust
    msg.sender
    for user identity
    - It's always PoolManager
  2. Never enable
    beforeSwapReturnDelta
    without understanding NoOp attacks
  3. Never store passwords, keys, or PII on-chain
  4. Never use
    transfer()
    for ETH
    - Use
    call{value:}("")
  5. Never assume token decimals - Always query the token
  6. Never use
    block.timestamp
    for randomness
  7. Never hardcode gas limits in calls
  8. Never ignore return values from external calls
  9. Never use
    tx.origin
    for authorization
    - It's a phishing vector; malicious contracts can relay calls with the original user's
    tx.origin
在Hook中绝对不要做以下事情:
  1. 永远不要信任
    msg.sender
    作为用户身份
    - 它始终是PoolManager
  2. 永远不要在未理解NoOp攻击的情况下启用
    beforeSwapReturnDelta
  3. 永远不要在链上存储密码、密钥或PII
  4. 永远不要使用
    transfer()
    发送ETH
    - 使用
    call{value:}("")
  5. 永远不要假设代币的小数位数 - 始终查询代币的小数位数
  6. 永远不要使用
    block.timestamp
    生成随机数
  7. 永远不要在调用中硬编码燃气限制
  8. 永远不要忽略外部调用的返回值
  9. 永远不要使用
    tx.origin
    进行授权
    - 这是钓鱼攻击的载体;恶意合约可以通过原始用户的
    tx.origin
    中继调用

Pre-Deployment Audit Checklist

部署前审计检查清单

#ItemRequired For
1Code review by security-focused developerAll hooks
2Unit tests for all callbacksAll hooks
3Fuzz testing with FoundryAll hooks
4Invariant testingHooks with delta returns
5Fork testing on mainnetAll hooks
6Gas profilingAll hooks
7Formal verificationCritical hooks
8Slither/Mythril analysisAll hooks
9External auditMedium+ risk hooks
10Bug bounty programHigh+ risk hooks
11Monitoring/alerting setupAll production hooks
See references/audit-checklist.md for detailed audit requirements.
#适用场景
1由专注安全的开发者进行代码审查所有Hook
2为所有回调编写单元测试所有Hook
3使用Foundry进行模糊测试所有Hook
4不变量测试带有delta返回的Hook
5在主网分叉上进行测试所有Hook
6燃气分析所有Hook
7形式化验证关键Hook
8Slither/Mythril分析所有Hook
9外部审计中高风险Hook
10漏洞赏金计划高风险Hook
11监控/告警设置所有生产环境Hook
详细的审计要求请参考references/audit-checklist.md

Production Hook References

生产环境Hook参考

Learn from audited, production hooks:
ProjectDescriptionNotable Security Features
FlaunchToken launch platformMulti-sig admin, timelocks
EulerSwapLending integrationIsolated risk per market
Zaha TWAMMTime-weighted AMMGradual execution reduces MEV
BunniLP managementConcentrated liquidity guards
从已通过审计的生产环境Hook中学习:
项目描述值得注意的安全特性
Flaunch代币发行平台多签管理、时间锁
EulerSwap借贷集成按市场隔离风险
Zaha TWAMM时间加权AMM渐进式执行减少MEV
BunniLP管理集中式流动性防护

External Resources

外部资源

Official Documentation

官方文档

Security Resources

安全资源

Community

社区



Additional References

额外参考

  • Base Hook Template - Complete implementation starter
  • Vulnerabilities Catalog - Common patterns and mitigations
  • Audit Checklist - Detailed pre-deployment checklist
  • Base Hook模板 - 完整的实现入门模板
  • 漏洞目录 - 常见模式及缓解措施
  • 审计检查清单 - 详细的部署前检查清单