Helpful?
PoolManager
In Uniswap V3, each liquidity pool was represented by a separate smart contract deployed through the UniswapV3Factory contract. While this approach provided flexibility, it also led to increased gas costs for pool creation and multi-hop swaps.
Uniswap V4 addresses this issue by introducing the Singleton design pattern. The PoolManager contract now serves as a single entry point for all liquidity pools. Instead of deploying separate contracts for each pool, the pool state and logic are encapsulated within the PoolManager itself.
Purpose
The primary purpose of the PoolManager is to:
- Efficiently manage liquidity pools
 - Facilitate token swaps
 - Reduce gas costs compared to the factory-based approach in Uniswap V3
 - Enable extensibility through hooks
 
Architecture
Singleton Design
- Uniswap V4 uses a Singleton design pattern for the 
PoolManager - All pool state and logic are encapsulated within the 
PoolManagercontract 
Locking Mechanism
- The 
PoolManageruses a locking mechanism to allow for flash accounting (also known as deferred balance accounting) - When unlocked, the calling contract can perform various operations and zero-out outstanding balances before returning control to the 
PoolManagerfor final solvency checks 
Pool State
- The 
Pool.Statestruct contains information such as:- Current price
 - Liquidity
 - Tick bitmap
 - Fee growth
 - Position information
 
 
Libraries
- The pool logic is implemented using Solidity libraries to keep the 
PoolManagercontract modular and gas-efficient - These libraries are:
Pool: Contains core pool functionality, such as swaps and liquidity managementHooks: Handles the execution of hook functionsPosition: Manages liquidity positions within a pool
 
Core Functionality
Pool Creation
- New pools are created by calling the 
initializefunction on thePoolManager - The pool creator specifies the token pair, fee tier, tick spacing, and optional hook contract address
 - The 
PoolManagerinitializes the pool state and associates it with a uniquePoolId 
Swaps
- Swaps are initiated through the 
swapfunction on thePoolManager, typically via a swap router contract - The 
PoolManagerexecutes the following steps:- Checks if the pool is valid and initialized
 - Executes the 
beforeSwaphook, if applicable - Performs the actual swap, updating the pool state and charging fees
 - Executes the 
afterSwaphook, if applicable - Calculates the net token amounts owed to the user and the pool, represented by the 
BalanceDeltastruct 
 - Swaps utilize flash accounting, where tokens are moved into the 
PoolManager, and only the final output tokens are withdrawn 
Liquidity Management
- Liquidity providers can add or remove liquidity using the 
modifyLiquidityfunction on thePoolManager. However, you wouldn't call this directly from your application, you would call this from a periphery contract to handle the locking & unlocking a particular pool. - The 
PoolManagerexecutes the following steps:- Checks if the pool is valid and initialized
 - Determines if the modification is an addition or removal of liquidity
 - Executes the appropriate 
beforeAddLiquidityorbeforeRemoveLiquidityhook, if applicable - Performs the actual liquidity modification and updates the pool state
 - Emits the 
ModifyLiquidityevent - Executes the appropriate 
afterAddLiquidityorafterRemoveLiquidityhook, if applicable - Calculates the balance delta and returns it to the caller
 
 
Flash Accounting
- The 
PoolManageremploys flash accounting to reduce gas costs and simplify multi-hop swaps - Tokens are moved into the 
PoolManagercontract, and all subsequent actions are performed within the contract's context - Only the final output tokens are withdrawn from the 
PoolManagerat the end of the transaction 
Transient Storage
- The 
PoolManagerutilizes transient storage (EIP-1153) to store temporary data during complex operations - Transient storage reduces gas costs by avoiding regular storage operations for data only needed within a single transaction