Custom Hooks Development for Uniswap v4

We design and develop full-cycle blockchain solutions: from smart contract architecture to launching DeFi protocols, NFT marketplaces and crypto exchanges. Security audits, tokenomics, integration with existing infrastructure.
Showing 1 of 1 servicesAll 1306 services
Custom Hooks Development for Uniswap v4
Complex
~1-2 weeks
FAQ
Blockchain Development Services
Blockchain Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1214
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    852
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1041
  • image_logo-advance_0.png
    B2B Advance company logo design
    561
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    823

Development of Custom Hooks for Uniswap v4

Uniswap v4 changed architecture radically: a single singleton contract PoolManager manages all pools, and logic extensions go through hooks. These aren't just callbacks. Hooks get control over critical points in a pool's lifecycle: before and after initialization, before and after swaps, before and after adding/removing liquidity. A correctly written hook enables limit orders, dynamic pricing, fee rebates, MEV-capture—without forking the protocol. An incorrect one blocks the pool or becomes an attack vector.

Hook Architecture: Critical Understanding Before Writing Code

Flags and Permissions

A hook's address encodes permissions in bits. Bits 0-7 determine which callbacks are active: BEFORE_SWAP_FLAG, AFTER_SWAP_FLAG, BEFORE_ADD_LIQUIDITY_FLAG, etc. If a hook declares getHookPermissions() with flag afterSwap: true, but the deployment address doesn't contain the corresponding bit, PoolManager reverts on pool initialization.

This means: the hook contract's address is not arbitrary. You need CREATE2 deployment with salt iteration until the correct bits in the address align. For a complex hook with 4-5 flags, salt hunting is a separate task solved with an off-chain script.

PoolKey and Pool Isolation

Each pool in v4 is identified by PoolKey: {currency0, currency1, fee, tickSpacing, hooks}. The hook address is part of the pool identifier. Two pools with identical tokens and fee but different hooks are different pools with different liquidity positions. This means: liquidity cannot be "migrated" between hooks without full withdrawal and re-entry.

Transient Storage and EIP-1153

V4 actively uses EIP-1153 transient storage—storage that clears at the end of a transaction. It's cheaper than SSTORE/SLOAD and ideal for temporary state within a transaction (e.g., a flag that "a swap is in progress"). Hooks can use transient storage for reentrancy protection without persistent storage overhead.

Typical Hook Use Cases and Complexities

Dynamic Fee Hook

The most popular request: fees that change based on volatility. Logic in afterSwap: calculate deviation from TWAP; if >threshold, raise the fee for the next swap via poolManager.updateDynamicLPFee().

Problem: TWAP must be stored in-hook. Using a Uniswap v3 TWAP oracle as reference means an external call from afterSwap, adding 3-5k gas to every swap. Alternative: your own rolling TWAP in hook storage, updated in afterSwap. Cheaper but requires bootstrap period and edge case handling for early swaps.

Second nuance: updateDynamicLPFee only works if the pool initialized with FEE_DYNAMIC_FLAG. This flag must be set in the fee field of PoolKey at pool creation. Miss it, and the contract deploys, the pool is created, but the hook doesn't work. You cannot replay it.

Limit Order Hook

beforeSwap checks if there are pending limit orders in the current tick range. If yes, executes them as part of the swap. Implementation: a mapping tick => orders[], traversal on tick crossing.

Main risk: unbounded loop over orders on a tick. If 500 orders accumulate on one tick, one swap crossing it costs >1M gas and hits block limit. Defense: order count limits per tick + batch execution via a separate keeper function for accumulated orders.

MEV Capture via AfterSwap Fee Redistribution

Idea: if a swap caused significant price movement (suspected MEV), redirect part of the fee to a compensation pool for LP. afterSwap calculates price impact; if above threshold, sends extra payment to a vault.

Technical complexity: afterSwap receives delta—balance changes. You must calculate price impact from delta and the pool's initial state. Capture that initial state in beforeSwap and store it in transient storage—so in afterSwap you can compare. This is a classic pattern for pairing beforeX/afterX hooks.

Development Tools

Foundry—the only reasonable choice for v4 hooks. The v4-core repository is written for Foundry; tests too. forge test --fork-url <mainnet> lets you test your hook against real PoolManager state.

v4-template from Uniswap—the starting point. Contains proper HookMiner setup for CREATE2 deployment, basic BaseHook abstractions, test examples.

Slither with custom detectors for v4—verify flag correctness, check for storage collisions with PoolManager slots.

Common Hook Development Mistakes

Mistake Consequence Solution
Incorrect bits in address Pool won't initialize CREATE2 + HookMiner before deployment
External call in beforeSwap without reentrancy guard Possible reentrancy via hook nonReentrant + transient storage lock
Unbounded loop in order book DoS via gas limit Limit orders per tick + keeper
Using SSTORE in hot path +20k gas per swap Transient storage (EIP-1153)
Mutating PoolKey in hook Impossible—PoolKey is immutable Design logic without changing key

Development Process

Specification (2-3 days). Formalize hook behavior at each lifecycle point. What invariants must hold? "Total fee always ≥ base fee," "limit order never executes at worse price than stated."

Development (5-7 days). Foundry + v4-template. CREATE2 deployment script with HookMiner. Property-based tests via Echidna on key invariants.

Fork Testing (2-3 days). Tests against real mainnet state: pool initialization, series of swaps, edge cases (empty pool, single-sided liquidity, large price impact).

Audit and Gas Profile. Slither + manual review. Gas snapshot via forge snapshot—compare gas cost of swap with and without hook. Acceptable overhead for most cases: <10k gas per swap.

Timeline Estimates

Simple hook (dynamic fee or whitelist): 1 week including tests. Medium-complexity hook (limit orders, MEV capture): 2-3 weeks. Complex system with several interacting hooks: 4+ weeks.

Pricing calculated individually after discussing required mechanics.