Uniswap v4 hook

The pool is sitting on money.

A Uniswap v4 hook that reclaims the mispricing a swap leaves behind, for the pool's own traders and LPs. It never runs the arbitrage and never fetches a price off-chain.

A pool quoting the wrong price is money on a table.

One ETH/USDC pool: 100 ETH, 300,000 USDC, price 3,000, Binance 3,000. Rohan buys 10 ETH and pays 33,333 USDC. That overpayment is price impact, the cost of consuming depth. Not a bug. But the pool now quotes 3,704 while the world still says 3,000. Vik the arb bot buys 10 ETH on Binance for 30,000, sells into the pool for 33,333, and hands most of the profit to a block builder for ordering.

Pool marked to truthETHUSDCValue at 3,000
Start100300,000600,000
After Rohan90333,333603,333
After Vik100300,000600,000

For one moment the pool was $3,333 richer. It held the value, then handed all of it back.

The surcharge is not a new charge on anyone. It is the pool declining to hand back what is already sitting in its own reserves.

Rohan cannot be charged. He already paid, and the payment landed in the pool. Backdraft keeps a slice of that value in escrow when a swap narrows the gap, then splits it at settlement.

Watch one gap live

The whole mechanism, in fifteen seconds.

Scrub through block time. White is the pool tick, grey is the reference. Inside the dashed band the gap is under 65 ticks and the hook is blind by design. Switch regimes: the code has no if for the exogenous case. An empty ledger is the attribution result.

Dormant
poolblock time →reference, v3 0.01% spot
blk +0
Contribution ledger

Empty. No gap yet.

Surcharge escrow, ERC-6909

Charged only on a narrowing swap, priced on the widest the gap ever reached, so splitting the close saves nothing.

Settlement

Runs when the gap closes. The trader pot scales by explained = min(ledger / peak gap, 1). A poisoning dust swap buys almost nothing.

Two regimes, one hook. The split falls out of the ledger.

Endogenous

A trade moved the pool.

Trigger
A swap knocks the pool off truth
Who pays
The originating traders
Ledger
Populated, explains the full gap
Settlement
Traders get alpha, pro rata on contribution
Exogenous, LVR

The world moved, the pool went stale.

Trigger
Information arrives, no trade does
Who pays
The LPs, loss versus rebalancing
Ledger
Empty, explained is 0
Settlement
100% to LPs, no branch

The earlier design used a binary empty ledger means exogenous. That was poisonable: one dust swap reclassifies a 200 tick gap as endogenous and claws the trader share back from LPs. Now the trader pot scales by explained = min(totalContribution / maxAbsGap, 1). Two manufactured ticks on a 200 tick gap buy 1% of the pot, less than the dust swap costs to make.

Architecture

All of it lives in pool state, never the mempool.

A gap opens, accrues a ledger, and settles across the swap and liquidity path. Drag it around, zoom in, or play the flow to walk one gap through the hook.

spot tickTWAP guardrefTick + ok + divTicksmint surchargeopen gapcredit + maxAbsGapescrowedgap closedledger + peaktraderPot / lpPot_payoutexternalv3 0.01%fast spotthe referenceexternalv3 0.05%deep spot + 30m TWAPthe guardexternalSplitV3ReferencegetRefTick → (tick, ok, divTicks)ok=false freezes · divTicks → graduated ×ignitionbeforeSwapclassify narrowingopen gap, mint surchargeignitionafterSwapdelta gap, credit via hookDataraise maxAbsGap, close gapstoragePoolManagerERC-6909 escrowBeforeSwapDelta from swapperstorageGap ledgercontribution, totalContributionmaxAbsGap, escrowedignitionsettle()explained = min(ledger / peak, 1)traderPot, lpPothookclaimTrader / claimLppro rata by liquidity, age gatesum claimable <= balancepayoutTraders + LPs_payoutIUnlockCallback

Drag to pan. Scroll to zoom. Drag any node to move it. Orange dots are the points where the hook acts.

100%

The reference price

Not the deepest pool, the most traded. The v3 0.01% ETH/USDC spot tick was the most corrected source across calm, volatile, USDT stressed, and one second truth conditions. An own pool EMA is 16.6 times worse: a pool cannot detect its own staleness from its own history.

Split from the guard

The fast pool is fresh but thin, 5% of pair liquidity would corrupt it. So the deep v3 0.05% pool guards it. If deep spot drifts from deep TWAP, or fast spot drifts from deep spot, by more than 50 ticks, the hook freezes. No credit, no surcharge. An unreliable reference produces inaction, not a wrong charge.

65gap threshold in ticks, from measured p100 error

50guard deviation in ticks, 6.6% to 10.1% freeze

74kreference gas, two stage read on the swap path

228 to 58worst case error in bps, cut by the guard

Everything else runs the arbitrage or fetches a price off-chain. Backdraft does neither.

i

Reference chosen by measured accuracy

Four market conditions, one consistent ordering. The source that gets corrected most often wins. We report the margin rather than claim a magnitude.

ii

Reference split from guard across fee tiers

Freshest source for the price, deepest source for manipulation detection. The only arrangement that gets both properties at once.

iii

Threshold derived from measured p100 error

65 ticks is the max of a 14,351 block window, with the honest note that a two day max is not a bound. Deployments must monitor realized error and version the threshold.

WhatTheHook

Runs the arb itself, needs two or more connected pools, no path for the exogenous case.

Detox Hook

Pyth to detect arb, capture, redirect. Fixed payee, no attribution, no trader leg.

ArbHook, Chainlink CRE

Off-chain compute, LPs only.

Truncated Oracle

Caps per block tick movement. Publishes a price, does not detect its own staleness.

am-AMM, LVR auctions

Auction the right to be the arbitrageur. Never touch the trader who created the opportunity.

Where we stand

The fee tier ordering is in the literature and reading external pools is not new. Doing all three at once has no precedent we can find.

The blind spot is exactly where the action is.

We will surcharge genuine traders

No on-chain signal separates a bot from someone who happened to sell into a stale quote. We frame it as a price on consuming a stale quote, not a penalty on intent, and it nets out over time.

Blind below 65 ticks, frozen in roughly 10% of volatile blocks

Plausibly the very blocks where dislocation value concentrates. The dollar weighted share lost to the blind spot is a never cut measurement and goes in the README either way.

Claim economics exclude small participants

Pull based, per gap, per address. A retail rebate is often smaller than the gas to claim it, so in practice the trader leg pays whales and bots.

tx.origin attribution

Works through the Universal Router, breaks for ERC-4337 and batched transactions. The demo uses direct swaps.

This is capture, not elimination

The arbitrage still happens and price discovery still works. We change who keeps the proceeds, from a block builder to the pool's own participants.