In Uniswap V4, the default position manager rigidly defines a "position" by its tick boundaries. This creates friction when you want to:
- Rebalance liquidity to a different price range without burning/minting new tokens
- Split a range (e.g., remove liquidity from the middle of a wide position)
- Merge adjacent ranges to consolidate fragmented positions
A declarative position manager that stores multiple conventional liquidity ranges within a single NFT position. Users manage fragmented, non-contiguous, or overlapping liquidity ranges through one NFT interface, eliminating the overhead of managing complex strategies across multiple positions.
sequenceDiagram
participant User
participant YogaManager
participant RBTree as Red-Black Tree
participant PoolManager as Uniswap Pool Manager
User->>YogaManager: Modify liquidity [A, B]
YogaManager->>RBTree: Query existing ranges
RBTree-->>YogaManager: Current boundaries
YogaManager->>YogaManager: Detect gaps/overlaps/merges
YogaManager->>YogaManager: Compile action list
YogaManager->>PoolManager: unlock()
PoolManager->>YogaManager: unlockCallback()
loop For each action
YogaManager->>PoolManager: modifyLiquidity()
end
YogaManager->>RBTree: Update boundaries
YogaManager->>User: Settle tokens
The contract logic:
- Tree Lookup: Check the NFT's Red-Black Tree for existing ranges
- Gap Detection: If [A, B] is disconnected, mark as new insert
- Overlap Detection: If [A, B] intersects existing ranges, calculate splits
- Merge Check: If new liquidity matches a neighbor's level, fuse them
- Action Compilation: Build list of raw Uniswap operations
- Execution: Unlock pool, execute actions via callback, update tree, settle tokens
By abstracting positions into trees of ranges, Yoga enables:
- Dynamic Rebalancing: Shift liquidity without minting new positions
- Range Orders: Efficiently manage single-sided positions across price levels
- Advanced Strategies: Build sophisticated protocols (e.g., LVR mitigation hooks) requiring granular liquidity management without NFT overhead
- MultiCall mode to create arbitrary liquidity distributions in a single transaction
- Flag to settle in ERC6909 or ERC20 tokens
- ERC721 enumerability
- Support for hooks that require hookData
- Clean up
_populateActions - Stateful invariant testing
burn(with pagination for gas limits)- Fancy
tokenURIimages - Permit2 support
- Easy function for collecting/compounding swap fees
- Allow creation of non-adjacent liquidity ranges
- Pool initialization on
mint