Turnkey Uniswap v4 Hooks Development
Uniswap v3 limits pool customization: for dynamic fees, you had to fork the pool contract. v4 flips the architecture — instead of thousands of separate pool contracts, a single singleton PoolManager and 14 callback functions implemented via hooks. But each hook requires a deep understanding of flash accounting and address configuration. We specialize in these tasks: we develop production-ready hooks with full test coverage and audit-prep documentation.
We have developed hooks for 30+ DeFi projects, including dynamic fees for major DEXes. Our experience: 10+ years in blockchain, certified Solidity auditors. We guarantee code quality and security.
Why the Hook Address Is Its Configuration
In v4, the hook address is its configuration. The last 14 bits of the address encode which callback functions the hook implements: beforeSwap, afterSwap, beforeAddLiquidity, afterAddLiquidity — 14 flags in total. When registering a pool, PoolManager reads the hook address and knows which callbacks to call without additional on-chain queries.
Consequence: You can't just deploy a contract and get the desired address. Mining is required — brute-forcing the salt in CREATE2 until the address contains the correct bits. Foundry automates this:
bytes32 salt = HookMiner.find(deployer, flags, creationCode, constructorArgs); If the flags are wrong, PoolManager.initialize reverts with HookAddressNotValid. This is the first stumbling block when migrating from v3.
BeforeSwap and AfterSwap: Asymmetric Control
beforeSwap can return (bytes4 selector, BeforeSwapDelta delta, uint24 lpFeeOverride). Through delta, the hook can modify the token amounts involved in the swap — effectively intercepting part of the flow. Through lpFeeOverride, it can set a dynamic fee for a specific hop instead of the static fee set during pool initialization.
afterSwap receives BalanceDelta — the swap result — and can add custom logic on top. A typical use case is a rebate hook that returns part of the fees to active LPs in the form of tokens.
Important nuance: Hooks operate within PoolManager's transaction context. All token operations go through flash accounting — actual ERC-20 transfers only happen at the end via settle/take. If a hook attempts a direct transfer inside a callback, it breaks flash accounting and causes a revert or, worse, an incorrect balance state.
Reentrancy in v4: New Rules
PoolManager is protected by a Lock modifier — only one lock call is active at a time. A hook trying to call PoolManager.swap inside beforeSwap will get a revert. This means architectures where the hook needs to initiate a secondary swap (e.g., automatic rebalancing) require deferred execution — via a queue in an external contract or through afterSwap with a subsequent separate call.
How a Hook Can Implement Dynamic Fees
Case from our practice. We implemented a hook that reads the TWAP from its own accumulator (updated in afterSwap), computes σ over the last N blocks, and maps σ to a fee tier: low volatility → 0.01%, high volatility → 1%.lpFeeOverride is returned in beforeSwap. LPs automatically get protection during sharp market movements without manual intervention.
Other typical use cases:
- Whitelist hook for permissioned pools: checks
merkleProofor ERC-721 balance of the swapper inbeforeSwap/beforeAddLiquidity. - LVR mitigation via auction: before-swap hook implements a commit-reveal scheme where MEV bots bid for the right to the first swap. Proceeds go to LPs.
Stack and Tools
Development: Foundry with the v4-template from Uniswap. Tests: fork on Ethereum Sepolia (v4 already deployed on testnet). The HookTest base contract provides deployFreshManagerAndRouters — no need to manually configure a mock PoolManager.
For hook address mining: HookMiner from v4-periphery. In CI, this appears as a step before tests: mine the salt, pass it to the deployment script.
Flag correctness verification is a separate test:
assertEq(uint160(address(hook)) & HookFlags.ALL_FLAGS, expectedFlags); A failing test immediately shows that the address was mined incorrectly.
Audit Specifics for Hooks
Standard Slither detectors don't know about v4 callback contracts. We write custom detectors for specific patterns:
- Direct ERC-20 transfer inside a callback (violates flash accounting)
- Reading
slot0directly instead of through PoolManager (obsolete v3 pattern) - Missing
msg.sender == address(poolManager)check in callback functions
The last point is critical: if a hook doesn't check who is calling beforeSwap, anyone can call it directly with arbitrary parameters. Depending on the logic, this could lead to state manipulation without an actual swap.
Comparison: Uniswap v3 vs Uniswap v4 with Hooks
| Parameter | Uniswap v3 | Uniswap v4 with Hooks |
|---|---|---|
| Pool architecture | Separate contract per pool | Singleton PoolManager + hooks |
| Fee customization | Fixed at initialization | Dynamic via lpFeeOverride |
| Gas for pool creation | ~500k gas | ~50k gas (10x less) |
| Whitelist capability | No (only fork) | Built-in via beforeSwap |
| Test framework | Hardhat/Foundry | Foundry + HookTest |
What's Included in the Work
| Stage | Deliverable | Timeline |
|---|---|---|
| Analysis | Technical specification, interaction diagram | 2-3 days |
| Design | Storage layout, owner function interface | 2-3 days |
| Development | Code for all callbacks, Sepolia tests, fuzzing | 1-2 weeks |
| Audit | Custom Slither detectors, manual review | 1 week |
| Deployment | HookMiner CI, deployment script, monitoring | 2 days |
| Team training | Documentation, architectural recommendations | 1 day |
Process
- Analysis (2-3 days). We formalize the hook logic: which callbacks are needed, whether there is custom storage, need for oracle access. We check compatibility with the existing pool architecture.
- Design (2-3 days). Interaction diagram between hook and PoolManager, storage layout definition (minimizing SLOAD in hot paths), owner configuration interface.
- Development (1-2 weeks). Implementation of callback functions, Sepolia fork tests, fuzz tests for edge case input values.
-
Audit (1 week). Custom Slither detectors + manual review of all paths where the hook modifies
BeforeSwapDelta. Documentation of invariants for an external auditor. - Deployment (2 days). HookMiner in CI, deployment script via Foundry with flag verification. Monitoring via PoolManager event log for the first 72 hours after deployment.
Timeline Estimates
Simple hook (single callback, read-only) — 4-6 days. Hook with dynamic fees and custom oracle — 1-2 weeks. Complex hook with auction mechanics or custom LP position accounting — 3-4 weeks. The cost is calculated after analyzing the technical specification.
Refer to the official Uniswap v4 documentation for an in-depth understanding of the specification.
Get a Consultation for Your Project
Order hook development — we'll evaluate your task within 24 hours. Contact us to discuss architecture and timelines.







