Learn / Secure hooks
last updated 2026-08-27
Secure Uniswap v4 hooks
PoolManager enforces pool math and end-of-session settlement. Your hook owns authorization, which pools are legitimate, how deltas and fees are accounted for, and whether external calls can brick swaps or exits.
Cork and Bunni-scale losses came from application and hook code, not from a broken PoolManager. Agents implementing a listing from this site should run this checklist before treating an excerpt as production-ready.
Builder checklist
- Gate every callback and unlock path. Hook callbacks are external. Without onlyPoolManager (or equivalent), anyone can call them with crafted PoolKey data. Use BaseHook for entrypoints and SafeCallback for unlockCallback; add caller checks on any path those bases do not cover.
- Allowlist pools, not just tokens. Pool creation is permissionless. Unless beforeInitialize restricts who can attach your hook, an attacker can create a pool with currencies they control. Bind to known PoolKey values or re-check PoolId on every user-controlled path.
- Custom accounting can leak even when settlement passes. PoolManager only checks that session deltas settle to zero. It does not validate your internal balances, fee buckets, or rounding. Keep LP funds, fees, and incentives in separate buckets. For NoOp / beforeSwapReturnDelta hooks, treat the hook as a custom AMM and test conservation.
- Put logic in the right callback. beforeSwap sees pre-swap state; afterSwap sees post-swap state. Fee or JIT penalties that need final results must run after the action. Wrong timing looks correct in isolation and fails in production.
- Address bits are part of the API. The hook address encodes which callbacks PoolManager will call. Bit set + function missing reverts; function implemented + bit missing means silent skip; return-delta bit missing means your returned delta is treated as zero. Keep getHookPermissions in sync and validate at deploy.
- Hook failures can brick exits. Callbacks share the user’s transaction. Optional reward, oracle, or cleanup code that reverts inside afterRemoveLiquidity or afterSwap can trap LPs. Keep non-essential work out of the critical path; use try/catch or a separate claim function.
- State can change between before and after. One hook can serve many pools. Nested unlocks and external calls can mutate shared storage before afterSwap runs. Key temporary state by PoolId and caller, reject overlapping ops, and clear after use.
Quick fuzz targets
- Direct calls to every external callback with a malicious
PoolKey. - Fee extremes, NoOp / return-delta paths, and same-tx round trips that should not mint value.
- Nested swaps across multiple pools that share the hook.
- Fee-on-transfer, rebasing, and callback tokens if you claim to support them.
- Oracle / reward failure during
afterRemoveLiquidity— exits must still work.
Start from known-good bases
Prefer OpenZeppelin BaseHook (or Uniswap’s BaseHook) so onlyPoolManager and permission validation are not reinvented. See Build with OpenZeppelin hooks for modular fee and MEV patterns.
Sources
This page summarizes public guidance for agents and SEO; read the originals for full examples and audit questions:
- Trail of Bits — Building secure Uniswap v4 hooks
- Hacken — Auditing Uniswap v4 hooks
- OpenZeppelin/uniswap-hooks
- Uniswap docs — Hooks
- Templates and tools
v4hooks is not an auditor. A listing here is not a security review. For the full catalog see https://v4hooks.com.