DEV Community

Cover image for Uniswap V4 Security Guide: Hooks, Pools, and New Attack Vectors You Need to Know Before Deploying
Duron Epps
Duron Epps

Posted on Originally published at smartcontractauditor.ai

Uniswap V4 Security Guide: Hooks, Pools, and New Attack Vectors You Need to Know Before Deploying

Uniswap V4 hooks are the most powerful primitive ever shipped in AMM design — and the most dangerous. One misconfigured hook can drain an entire pool in a single transaction, and with over $1B in TVL migrated from V3 within weeks of launch, there's a lot of money sitting behind code most people haven't audited.

I've gone through the V4 architecture, the PoolManager contract, and a stack of early hook implementations. The vulnerability surface isn't just new — it's fundamentally different from anything that came before.

How Hooks Change the V4 Security Model

Uniswap V4 moves all pools into a single singleton contract called PoolManager. Instead of deploying a new pair contract per token pair (V2/V3 style), every pool lives in one contract and is identified by a PoolKey struct. Lower gas, but a bug in one pool's hook now has implications for shared singleton state.

Hooks are external contracts that PoolManager calls at defined lifecycle points:

  • beforeInitialize / afterInitialize
  • beforeAddLiquidity / afterAddLiquidity
  • beforeRemoveLiquidity / afterRemoveLiquidity
  • beforeSwap / afterSwap
  • beforeDonate / afterDonate

The hook's address determines which callbacks it implements — encoded in the address via CREATE2 mining. Clever design. But it introduces a critical trust assumption: the hook is trusted by the pool unconditionally. PoolManager calls your hook contract and expects it to behave. There is no sandbox.

The Four Real Attack Vectors

Everyone focuses on reentrancy because it's the classic AMM boogeyman. Fair — but the real killers in V4 are subtler.

1. Hook-Level Reentrancy via Delta Accounting

V4 uses a flash accounting model — balances are tracked as deltas, settled by end of transaction. The lock mechanism in PoolManager is meant to prevent reentrant calls. But if your hook calls back into PoolManager through a different code path during a callback, you can manipulate intermediate state before deltas settle.

Reentrancy-adjacent vulnerabilities have drained over $2.3B from DeFi protocols since 2020 (Rekt News). V4's accounting model doesn't eliminate this class — it reshapes it.

2. Malicious Hooks as Backdoors

This one targets traders and LPs directly. If you're interacting with a V4 pool, you are implicitly trusting its hook. A malicious afterSwap hook can redirect funds, inflate prices, or call back into your wallet if approvals exist. Venom Protocol used exactly this social engineering pattern against NFT traders in 2022 — embedding malicious logic in what looked like a standard marketplace contract, draining $1.8M. V4 hooks create the same attack surface with a technical wrapper that looks legitimate.

3. Missing Access Control on Admin Functions

Access control failures account for 3x more total DeFi losses than reentrancy — and almost nobody builds their hook audit checklist around it. Most hook developers add admin functions for fee updates, oracle configs, or whitelist management. If those aren't properly gated, you've shipped a god-mode backdoor.

4. Price Oracle Manipulation Through Hook Logic

Hooks that read or write price data mid-swap create new TWAP manipulation surfaces. If your hook reads slot0 (spot price, not TWAP) during a beforeSwap callback — say, for a dynamic fee calculation — an attacker can sandwich that logic with a flash loan. Mango Markets lost $117M to oracle price manipulation. V4 hooks give attackers a new insertion point for the same playbook.

What a Vulnerable Hook Looks Like

Here's a realistic dynamic fee hook with two critical vulnerabilities. This pattern shows up constantly in early implementations.

// ❌ VULNERABLE PATTERN
contract VulnerableFeeHook is BaseHook {
    uint24 public dynamicFee;

    // ❌ No access control — anyone can call this
    function setFee(uint24 newFee) external {
        dynamicFee = newFee;
    }

    // ❌ Reads slot0 (spot price) — flash loan bait
    function beforeSwap(
        address,
        PoolKey calldata key,
        IPoolManager.SwapParams calldata params,
        bytes calldata
    ) external override returns (bytes4, BeforeSwapDelta, uint24) {
        (uint160 sqrtPriceX96,,,) = poolManager.getSlot0(key.toId());
        uint24 fee = sqrtPriceX96 > 1e18 ? 500 : dynamicFee;
        return (BaseHook.beforeSwap.selector, BeforeSwapDeltaLibrary.ZERO_DELTA, fee);
    }
}
Enter fullscreen mode Exit fullscreen mode

Two problems: setFee has zero access control — any wallet can set the fee to the maximum, bricking the pool or extracting value from traders. And reading slot0 in beforeSwap to drive fee logic means a flash loan attacker can manipulate that price in the same block.

The fix requires two changes: gate admin functions behind ownership, and replace spot price reads with TWAP data that can't be manipulated within a single block.

// ✅ SECURE PATTERN
contract SecureFeeHook is BaseHook, Ownable {
    uint24 public dynamicFee;

    // ✅ Only owner can update fee
    function setFee(uint24 newFee) external onlyOwner {
        require(newFee <= 100_000, "Fee too high");
        dynamicFee = newFee;
        emit FeeUpdated(newFee);
    }

    // ✅ Use TWAP — not spot price — for fee decisions
    function beforeSwap(
        address,
        PoolKey calldata key,
        IPoolManager.SwapParams calldata params,
        bytes calldata
    ) external override returns (bytes4, BeforeSwapDelta, uint24) {
        // Reference TWAP oracle instead of slot0
        uint24 fee = _getTWAPBasedFee(key);
        return (BaseHook.beforeSwap.selector, BeforeSwapDeltaLibrary.ZERO_DELTA, fee);
    }
}
Enter fullscreen mode Exit fullscreen mode

Pre-Deployment Checklist

Before you touch a V4 pool — as a developer or an LP — run through this:

  • Access control: Every admin function gated. No unprotected setFee, setOracle, or whitelist functions
  • Oracle source: TWAP over multiple blocks, never slot0 for decision logic
  • Reentrancy: Trace every external call inside hook callbacks; check for cross-function reentrance paths through the delta accounting system
  • Hook trust model: If you're an LP or trader, verify the hook's source code is published and audited — the pool's safety is entirely dependent on it
  • Singleton implications: Understand that any hook interacting with shared PoolManager state can have cross-pool effects
  • Delta settlement: Ensure all currency deltas are properly settled before transaction end; unsettled deltas are a vector for fund extraction

The V4 architecture is a genuine leap forward in AMM design. The hooks primitive enables things that simply weren't possible before — dynamic fees, custom order types, on-chain limit orders, protocol-owned liquidity management. But every one of

Top comments (0)