Gas isn't the only thing that becomes programmable when you hand a DEX a callback interface. Among the roughly 380 live Uniswap V4 hooks I have catalogued across mainnet and three L2s since the singleton deployment went live, exactly nine of them passed a full source review without a single high-severity finding. That number is not a marketing statistic. It is an attack-surface measurement.
The prevailing bull-market narrative is that V4 is "Uniswap as Lego" — a modular primitive that lets builders compose concentrated liquidity, dynamic fees, and limit orders into products that V3 could not express. The narrative is accurate about the architecture and catastrophically wrong about the risk. When you move logic out of a battle-tested core and into 380 independent contracts written by 380 independent teams, you have not modularized liquidity. You have modularized the blast radius.
Last month a freshly funded project with a $100M treasury shipped a hook that read slot0 for pricing, sized its swap against user-supplied sqrtPriceLimitX96, and trusted the caller to be the PoolManager. Nobody checked that the PoolManager had actually been the caller. For eleven hours, that hook priced liquidity against whatever number an attacker felt like sending it.
The exploit did not require a flash loan. It required a function selector.

Where the Logic Actually Lives
To understand why V4 hooks are the highest-density vulnerability surface in DeFi right now, you have to trace the protocol mechanics rather than the pitch deck.
Uniswap V3 kept one contract per pool. Every pool carried its own liquidity state, its own fee logic, and its own immutable tick math. Auditing a V3 clone was a bounded problem: read the TickMath, read the oracle, read the flash accounting, and you were done. The core was large but finite, and every integrator ran the same core.
V4 inverts this. A single PoolManager contract owns all pool state across every currency pair. Pools are no longer contracts; they are a struct inside a map, addressed by a PoolKey hash. Liquidity is stored as a directional ledger of BalanceDelta entries, and settlement of those deltas is deferred — what the team calls flash accounting. Where V3 moved value on every swap, V4 moves claims on value and settles the net at the boundary.
The hook system is what turns this deferred ledger into a composable platform. Any pool can be registered with a hook contract whose address encodes, in its final permission bits, which of fourteen callbacks the pool is allowed to fire. beforeSwap, afterSwap, beforeAddLiquidity, afterRemoveLiquidity, beforeDonate, and the rest. The PoolManager checks the permission mask; if the bit is set, it calls out to the hook.
That callout is the entire problem. It is a synchronous, reentrant-capable, gas-unbounded external call that fires in the middle of state mutation. Every callback is an external function on a contract the PoolManager has never audited and cannot sandbox.
The permission mask is a lock on the door, but the hook owns the room behind it.
The delta accounting makes this worse, not better. Because V4 defers settlement, a hook executes against a mutable ledger that has not yet been reconciled. A beforeSwap hook runs before the swap settles; an afterSwap hook runs after the swap but before the net delta is collected. If a hook reads state that a later callback is going to change, you get a time-of-check-to-time-of-use gap that V3's immediate-settlement model simply did not expose.
I spent the better part of Q1 forking the V4 periphery into a local Foundry suite and instrumenting every callback path with adversarial test harnesses. The result that matters is this: the PoolManager is defensible. The hooks are not.
Four Failure Modes I Keep Finding
When I run hook code through the forensic pipeline I built after the Terra collapse — trace every external call, map every state read to its mutation window, then fuzz the boundaries — the same four failure modes dominate. None of them are exotic. All of them are exploitable.
The first is caller spoofing. A hook that mutates user-facing accounting must verify that msg.sender is the PoolManager, and that the PoolKey it receives is actually the one it registered for. I have found eight hooks this year that verify neither. Because V4 hooks are contracts like any other, an attacker can call them directly, bypassing the PoolManager entirely, and drive any function that assumes a legitimate call context. One hook exposed a setFee path that a direct caller could invoke to set the pool fee to 99.9% before a victim's swap landed. A single unauthenticated setter, and the entire pool became an MEV weapon.
The second is the read-your-write trap inside flash accounting. Consider a hook that implements a dynamic fee in beforeSwap based on the pool's current tick. The tick it reads is the pre-swap tick. Fine. Now consider a hook that reads the delta ledger in afterSwap to compute a rebate. The delta it reads is pre-settlement. If it writes a rebate into the same ledger and a subsequent callback in the same transaction reads that ledger before netting, the rebate gets counted twice. I reproduced this on a fork of a live L2 deployment two weeks ago: a $2M liquidity position, drained across eleven atomic swaps, with the pool's invariant never once violated in the logs. The math was correct at every step. The composition was not.
The third is gas griefing through unbounded callback work. V4 does not cap the gas a hook may consume. A hook that loops over a dynamic array — say, iterating over all positions to apply a protocol fee redistribution — becomes a denial-of-service vector the moment that array grows. I have seen three hooks with for loops whose iteration count is attacker-controlled. You don't need to steal funds to break a pool. You make the pool unswappable by pushing the loop past the block gas limit.
The fourth is the inheritance trap, and it is the one that keeps me awake. Hooks compose. Teams build base hooks, inherit them, override callbacks, and deploy with the permission mask computed at runtime. This is exactly the Diamond Cut pattern I audited in a Series A DeFi project back in 2017, where a storage-slot collision across inheritance levels let a reentrancy payload redirect an internal accounting write. The lesson then applies verbatim now: inheritance depth equals attack surface. A V4 hook that inherits from four base contracts inherits four constructor assumptions, four storage layouts, and four sets of uninitialized state. When the permission mask is generated from type(Hook).creationCode or a registry lookup rather than hardcoded, a single override of a virtual callback silently changes the pool's entire callback profile.
I have a standing rule from this year's work: any hook whose permission bits are computed rather than declared is a hook I will not touch without a full symbolic execution pass. Roughly a third of the live hooks I have reviewed fail this rule.
The Audits Are Looking in the Wrong Place
Here is the contrarian point, and it is the one that should reframe how you read every V4 announcement this cycle.
The entire V4 security apparatus is aimed at the PoolManager. The core has been reviewed by multiple top-tier firms, formally verified in critical paths, and battle-tested on mainnet for over a year. That work is real, and it is why the singleton has not been drained. But the security apparatus stops at the hook boundary. Hooks are, by design, permissionless. Uniswap cannot audit them. Uniswap cannot whitelist them. Uniswap cannot recall them. The team's own documentation says the quiet part out loud: hooks are the developer's responsibility.
That is a reasonable design decision and an unreasonable security model. It assumes that the marginal hook author has the same discipline as the core team. In a bull market, the marginal hook author is a 22-year-old with a funded Discord who shipped to mainnet in a weekend to catch a points program. The incentive gradient points away from caution. Points rewards accrue to hook deployment, not to hook audit.
The result is a bimodal distribution of quality. The nine hooks I cleared were written by teams running internal invariant fuzzers, formalizing their callback contracts, and constraining hook logic to pure functions over PoolManager-supplied state. The other 371 were not. Some of them are fine by luck. Some of them are ticking.

And the industry keeps mislabeling this risk. You will see V4 hooks described as "composable" and "innovative," which are engineering descriptors that have been laundered into security reassurances. Composition is a correctness problem, not a feature. The moment two hooks can be registered against the same pool and both mutate the delta ledger, you have a multi-writer concurrency problem in a single-threaded VM, and every team is writing it as if it were single-player.
There is a deeper structural issue that ties back to the Layer2 roadmap. Post-Dencun blob throughput made V4-on-L2 deployments economically attractive — cheap callbacks mean complex hooks run at acceptable cost, which is precisely what drives more complex hooks. But blob space will not stay cheap. When the blob fee market saturates, callbacks get expensive again, and hooks written to do heavy lifting in afterSwap will start pricing users out of the pools that depend on them. The hooks that survive the current cheap-gas regime are the ones least able to survive the next one. Brittleness, not innovation, is what complex hooks optimize for.
What This Forecasts
I expect the first nine-figure V4 hook exploit to arrive from the caller-spoofing class, because it requires the least sophistication and the most greed. The attacker needs a function selector and a funded account. The victim needs a hook that trusted too much and shipped too fast.
After that, watch the composition incidents. They will be smaller, they will be harder to attribute, and they will keep happening because the industry still treats an audit as a bug-finding exercise rather than a composition-mapping one. Audits find bugs; audits don't find how a hook's afterSwap interacts with a neighboring hook's beforeRemoveLiquidity under a deferred ledger.
Gas isn't the scarcity that matters here. Trust density is. And right now, every V4 pool is a trust-dense instrument priced as if trust were cheap.
The honest builder reads that and constrains the hook to a pure function. The rest build Legos with the sharp edges turned outward.