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.
- 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.
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
unlock
The manager calls
poolManager.unlock(data); the PoolManager calls backunlockCallback, which only accepts calls from the PoolManager.modifyLiquidity per bin
Each bin is a
modifyLiquiditycall. The resulting deltas are summed per currency.settle or take
Negative deltas are paid (
sync→ transfer →settle, orsettlewith ETH for the native currency); positive deltas are withdrawn withtake. 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