Last month I spent an afternoon looping on eleven characters of a hex address: 0x7a3F...4bC8. In Uniswap V4, the trailing fourteen bits of a hook contract's address are not vanity mining. They are a capability manifest. 0xC8 decodes to 1100 1000; set against V4's flag table, that single byte declares BEFORE_SWAP_FLAG, AFTER_SWAP_FLAG, and BEFORE_SWAP_RETURNS_DELTA_FLAG simultaneously. The last of those is the one that matters. It means the hook returns a BeforeSwapDelta, which means the hook — not the PoolManager's curve math — decides how much of the trade actually settles against the AMM. Tracing the gas trail back to the genesis block is trivial in this case, because the genesis is the CREATE2 salt. The problem is that almost nobody reads it. An address does not look like code, and reviewers do not treat it as one.
V4 collapsed V3's per-pool architecture into a singleton PoolManager holding every pool, with flash accounting replacing per-swap token transfers. Rather than moving ERC-20s on each hop, V4 records deltas — BalanceDelta — and only requires that they net to zero when the lock closes. The upside is real: multi-hop routing without intermediate transfers, meaningful gas savings on concentrated routes, and fourteen defined intervention points spanning pool initialization, liquidity modification, swaps, and donations.
The design choice that deserves more scrutiny is how V4 determines which of those points a hook actually implements. It does not introspect. It does not check ERC165. It reads the low fourteen bits of the hook contract's address, pre-mined via CREATE2 so that the bits match the callbacks the developer intends to expose. This is a gas decision — an in-memory mask comparison costs far less than storage reads or external calls on the swap hot path. It is also a coupling decision. Your deployment salt is now part of your security model.
The flag mechanism itself predates the code. V3's periphery used hardcoded callback interfaces. V4's authors wanted a dispatch layer that could scale to arbitrary hook types without grafting a selector table onto the singleton. Encoding capability into the address was elegant, cheap, and — critically — verifiable at zero runtime cost. Every one of those properties describes the PoolManager's gas profile. None of them describes the integrator's.
Seventeen months after mainnet, hook deployment counts keep climbing, and audit coverage of the hooks themselves has kept pace. Coverage of the binding between address bits and runtime bytecode has not. Attention, meanwhile, sits on ETF flow tables and L2 incentive programs — a sideways market rewards nobody's curiosity.

Here is the invariant V4 actually enforces, stated precisely: at the close of an unlock cycle, the sum of all currency deltas for the locker must equal zero. That is it. The PoolManager does not verify that the curve was consulted, that price moved consistently with the input, or that a delta-returning hook computed anything correctly. It verifies solvency, not semantics.
That distinction is tolerable when the hook is a fee splitter. It becomes load-bearing when the hook holds BEFORE_SWAP_RETURNS_DELTA_FLAG. A delta-returning pre-swap hook can, legitimately, reroute an order to an RFQ desk, fill it against a limit book, or net it against an internal TWAMM. In each case the user receives tokens the curve never priced. The curve becomes one venue among several, and the hook becomes the pricing authority. That is not a defect; it is the explicit thesis of V4. It is also a trust-boundary expansion most integrators have not internalized.
The second-order problem is rounding. BeforeSwapDelta is a packed pair of signed values representing specified and unspecified currency amounts. Hooks computing that delta in fixed-point arithmetic will, at some frequency, round toward their own reserve rather than the pool. One wei per call is statistically invisible in a test suite and monotonically extractive in production. I have filed this finding three times in the past year against three different hook designs, and each team's answer was identical: the delta nets to zero at settlement. It does. The extraction happens across cycles, not within them.
Consider a boundary case. A hook quotes a swap at exactly the tick where its internal reserve model brackets the AMM price. The returned delta is valid, the trade settles, the user is filled, no revert fires. Repeat across ten thousand swaps with a slow drift in the hook's reserve ratio, and the pool's effective price diverges from the curve without a single failed transaction ever hitting a monitoring dashboard.

Then there is deployment, and here the audit culture has a genuine hole. V4 routes callbacks by address bitmask. Inherit BaseHook and the constructor calls Hooks.validateHookPermissions, comparing address(this) & ALL_HOOK_MASK against your getHookPermissions() override and reverting on mismatch. Do not inherit BaseHook — nothing compels you — and you may deploy at any address you like. The PoolManager dispatches by bits regardless, never by ABI. A hook whose address advertises beforeSwap while its code exposes a different signature does not fail at review. It fails at swap time, for the first user, with a selector mismatch.
Add a proxy and the hole deepens. A proxy-based hook passes the constructor check against the implementation's declared permissions, then executes arbitrary logic after an upgrade. The address bits are immutable; the bytecode behind them is not. I have yet to see that combination flagged in a public audit report.
The counter-intuitive part is where attention went instead. Eighteen months of V4 security discourse has centered on hook logic — fee-on-transfer edge cases, donation griefing, liquidity-callback reentrancy. That work is competent and largely correct. It also misses the pattern. Smart contracts don't fail where the documentation points; they fail where two systems disagree about a shared assumption. V4 has two such seams: address bits versus runtime bytecode, and delta-netting versus per-cycle economic correctness. Both are invisible to a line-by-line review of a single .sol file, which is precisely how most audits are scoped and billed. The uncomfortable implication is that hook audits priced per line of Solidity systematically underprice risk living in deployment scripts and arithmetic edge cases — which is to say, the risk that actually materializes.
My forecast is specific. The first material V4 hook exploit will not be a reentrancy bug. It will be a delta hook that was arithmetically correct on every individual call and economically wrong in aggregate — or a proxy upgrade that silently changed behavior behind a permission bit nobody re-checked. Entropy increases, but the invariant holds; the question is whether the invariant is the one you believe you are relying on.
That complexity is not incidental. It is why the hook ecosystem will consolidate around a dozen audited templates and a long tail of abandoned experiments — the shape V3 fee tiers took, compressed into eighteen months rather than four years. In the absence of trust, verify everything twice. Then verify the salt.