Protocol Uniswap V4

Protocol

Uniswap V4.

Ladders built inside the V4 singleton with unlock callbacks, flash accounting and native ETH.

V4 keeps every pool inside a single PoolManager. ObolLadderManagerV4 adds and removes liquidity inside an unlock callback and settles once per currency.

Ladder manager
0x761F…Fe05
PoolManager
0x8366…0951
StateView
0xF333…673b
Positions per ladder
One position per bin, owner = the manager, salt = keccak256(ladderId, bin)
Native ETH
Supported (currency0 = address(0)); send ETH as msg.value

Pools are identified by a PoolKey

A V4 pool is defined by its PoolKey: both currencies (sorted), fee, tick spacing and hooks contract. Its id is keccak256(abi.encode(key)). The app resolves the key of each pool from the PoolManager's Initialize event.

PoolKey
struct PoolKey {
Currency currency0; // address(0) = native ETH
Currency currency1;
uint24 fee; // hundredths of a bip, 0x800000 = dynamic
int24 tickSpacing;
address hooks;
}

Unlock and flash accounting

  1. unlock

    The manager calls poolManager.unlock(data); the PoolManager calls back unlockCallback, which only accepts calls from the PoolManager.

  2. modifyLiquidity per bin

    Each bin is a modifyLiquidity call. The resulting deltas are summed per currency.

  3. settle or take

    Negative deltas are paid (sync → transfer → settle, or settle with ETH for the native currency); positive deltas are withdrawn with take. The pool must end fully settled.

Read more: flash accounting.

Fees on V4

modifyLiquidity returns both callerDelta (principal + fees) and feesAccrued, so the manager knows exactly which part is fees and applies the 7.5% only to it. pendingFees is computed from StateView.getFeeGrowthInside and each position's last fee growth.

Hooks

Pools with hooks are accepted. The manager only ever pays what the pool asks for, capped by what you deposited, so a hook that charges extra makes the open revert rather than spending more of your funds. See Uniswap: hooks.

Learn more