Uniswap V2/V3 Notes
Note: This is a curated educational resource combining information from official documentation, community resources, and AI assistance to provide a detailed learning guide and notes.
Uniswap revolutionized decentralized finance by creating an automated market maker (AMM) that allows anyone to trade tokens without traditional order books. As the protocol evolved from V2 to V3, significant improvements were made in capital efficiency and functionality. Let's dive deep into both versions to understand how they work and when to use each.
What is Uniswap and How Does it Work?
The AMM Revolution
Traditional exchanges use order books where buyers and sellers place orders at specific prices. Uniswap works completely differently - it uses liquidity pools where traders swap against pooled funds, with prices determined by mathematical formulas.
The Core Innovation: Instead of matching buyers with sellers, Uniswap matches traders with liquidity pools. When you want to trade ETH for USDC, you're not trading with another person - you're trading with a smart contract that holds both ETH and USDC.
Uniswap V2: Understanding the Foundation
What Does Uniswap V2 Swap Do?
Uniswap V2 swap allows you to exchange one token for another using the constant product formula: x * y = k
. Here's how it works:
- When you trade, you add Token A to the pool and remove Token B
- The product of both token amounts must always remain constant
- This automatically adjusts the price based on supply and demand
- The more you trade, the worse the price gets (this is called "slippage")
V2 Swap Features Explained
1. Exact Input Swaps ("Sell All")
- You specify exactly how much you want to sell
- You get whatever the market gives you (minus slippage)
- Perfect for: "I want to sell all my ETH for DAI"
- Use case: Converting your entire token balance
2. Exact Output Swaps ("Buy Specific")
- You specify exactly how much you want to buy
- You pay whatever it costs (up to your limit)
- Perfect for: "I need exactly 1000 DAI, whatever it costs"
- Use case: Paying for something that requires an exact amount
How V2 Routing Works
Sometimes there's no direct trading pair between two tokens. V2 solves this with multi-hop routing:
Single Hop: Direct swap between two tokens (WETH ↔ DAI)
- Cheaper gas costs
- Better for popular pairs
- Lower slippage
Multi-Hop: Route through an intermediary token (DAI → WETH → USDC)
- Necessary when no direct pair exists
- Higher gas costs (multiple swaps)
- More slippage (price impact compounds)
V2 Swap Code Example Explained
function swapExactETHForDAI(uint256 amountOutMin) external payable returns (uint256) {
// 1. Define the trading path
address[] memory path = new address[](2);
path[0] = WETH; // Start with WETH
path[1] = DAI; // End with DAI
// 2. Execute the swap
uint256[] memory amounts = router.swapExactETHForTokens{value: msg.value}(
amountOutMin, // Minimum DAI you're willing to accept
path, // The trading route
msg.sender, // Who receives the DAI
block.timestamp + 300 // Transaction must complete within 5 minutes
);
return amounts[1]; // Return actual DAI received
}
What this code does:
- Path Definition: Tells Uniswap the route (ETH → DAI)
- Slippage Protection:
amountOutMin
prevents bad trades - Deadline Protection: Prevents transactions from sitting in mempool too long
- Return Value: Shows exactly how much DAI you got
Uniswap V2 Liquidity: How Pool Creation Works
What Does V2 Liquidity Do?
V2 liquidity allows you to become a "market maker" by providing tokens to trading pools. Here's what happens:
- You deposit two tokens (e.g., ETH + USDC) into a pool
- You receive LP tokens representing your share of the pool
- Traders pay fees (0.3%) when they use your liquidity
- You earn those fees proportional to your share
- You can withdraw anytime by burning your LP tokens
V2 Pool Structure: The Math Behind It
Here's how a real V2 pool works with actual numbers:
Key Concepts Explained:
- Price Discovery: Price = Token B Reserve / Token A Reserve
- LP Token Formula: √(Reserve A × Reserve B) - this ensures fair distribution
- Constant Product: 1,000 × 3,000,000 = 3,000,000,000 (this never changes)
- Your Share: If you own 10% of LP tokens, you own 10% of both reserves
V2 Liquidity Features
Automatic Balancing: V2 always keeps your liquidity active across all possible prices
- ✅ Simple and passive
- ❌ Capital inefficient (most liquidity never used)
Auto-Compounding Fees: Trading fees automatically get added to the pool
- ✅ Your position grows automatically
- ❌ Fees are locked until you withdraw
Impermanent Loss: Your token ratio changes as prices move
- If ETH price doubles, you'll have less ETH and more USDC than if you just held
- You only "lose" compared to holding the tokens separately
V2 Liquidity Code Example Explained
function addLiquidity(
address tokenA,
address tokenB,
uint256 amountA,
uint256 amountB
) external returns (uint256 amountAUsed, uint256 amountBUsed, uint256 liquidity) {
// 1. Transfer tokens from user to this contract
IERC20(tokenA).transferFrom(msg.sender, address(this), amountA);
IERC20(tokenB).transferFrom(msg.sender, address(this), amountB);
// 2. Allow the router to spend our tokens
IERC20(tokenA).approve(ROUTER, amountA);
IERC20(tokenB).approve(ROUTER, amountB);
// 3. Add liquidity to the pool
(amountAUsed, amountBUsed, liquidity) = IUniswapV2Router(ROUTER).addLiquidity(
tokenA,
tokenB,
amountA, // How much Token A you want to add
amountB, // How much Token B you want to add
1, // Minimum Token A (slippage protection)
1, // Minimum Token B (slippage protection)
msg.sender, // Who receives the LP tokens
block.timestamp + 300
);
// 4. Refund any unused tokens
if (amountA > amountAUsed) {
IERC20(tokenA).transfer(msg.sender, amountA - amountAUsed);
}
if (amountB > amountBUsed) {
IERC20(tokenB).transfer(msg.sender, amountB - amountBUsed);
}
}
What this code does:
- Token Transfer: Moves your tokens into the contract
- Approval: Allows Uniswap to use your tokens
- Liquidity Addition: Creates or adds to a pool
- Ratio Adjustment: Uniswap adjusts your token amounts to match pool ratio
- Refund: Returns any tokens that couldn't be used
Uniswap V3: The Revolutionary Upgrade
What Does V3 Swap Do Differently?
V3 swaps work similarly to V2 but with major improvements:
- Multiple Fee Tiers: Choose the right fee for each pair type
- Concentrated Liquidity: More efficient routing through focused liquidity
- Advanced Routing: Better pathfinding through multiple fee tiers
V3 Fee Tier System Explained
V3's biggest improvement is multiple fee tiers for different asset types:
Fee Tier Guide:
- 0.01% (100): USDC/USDT, DAI/USDC (very stable, low risk)
- 0.05% (500): ETH/stETH, WBTC/BTC (correlated assets)
- 0.3% (3000): ETH/USDC, WBTC/ETH (standard volatile pairs)
- 1% (10000): New tokens, very volatile pairs
Why This Matters: Stable pairs need lower fees to compete, while volatile pairs can charge more because of higher risk.
V3 Swap Code Example Explained
function swapExactInputSingle(
address tokenIn,
address tokenOut,
uint24 fee, // NEW: Choose fee tier
uint256 amountIn,
uint256 amountOutMinimum
) external returns (uint256 amountOut) {
IERC20(tokenIn).transferFrom(msg.sender, address(this), amountIn);
IERC20(tokenIn).approve(SWAP_ROUTER, amountIn);
// V3 uses a struct for parameters (cleaner than V2's long parameter list)
ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({
tokenIn: tokenIn,
tokenOut: tokenOut,
fee: fee, // 100, 500, 3000, or 10000
recipient: msg.sender,
deadline: block.timestamp + 300,
amountIn: amountIn,
amountOutMinimum: amountOutMinimum,
sqrtPriceLimitX96: 0 // Advanced: price limit feature
});
amountOut = ISwapRouter(SWAP_ROUTER).exactInputSingle(params);
}
Key V3 Improvements:
- Fee Selection: You choose which pool to use
- Parameter Struct: Cleaner, more organized parameters
- Price Limits: Advanced feature to stop swaps at certain prices
- Better Gas: More efficient routing algorithms
Uniswap V3 Liquidity: Concentrated Liquidity Revolution
What Does V3 Concentrated Liquidity Do?
V3's concentrated liquidity is the biggest innovation in DeFi AMMs. Instead of spreading your liquidity across all possible prices (like V2), you can focus it in specific price ranges where trading actually happens.
V3 Concentrated Liquidity Features Explained
Capital Efficiency: Up to 4000x more efficient than V2
- V2: Your $1000 is spread from $0 to infinity
- V3: Your $1000 is focused on $2800-$3200 (where trading happens)
- Result: You earn the same fees with much less capital
Active Management Required: Your liquidity can go "out of range"
- If ETH price moves outside your range, you stop earning fees
- You need to rebalance or adjust your range
- More work, but much higher potential returns
NFT Positions: Each liquidity position is a unique NFT
- No fungible LP tokens like V2
- Each position has custom parameters
- Can't easily trade positions (they're unique)
Understanding V3's Tick System
V3 uses a tick system for precise price range definitions:
How Ticks Work:
- Each tick = 0.01% price change
- Tick spacing depends on fee tier (prevents too many small ranges)
- Your position = [tickLower, tickUpper]
- Example: ETH at $3000, you want $2800-$3200 range = specific tick numbers
Why Tick Spacing Matters:
- Prevents liquidity fragmentation
- Lower fees = tighter spacing (stable coins need precision)
- Higher fees = wider spacing (volatile pairs don't need as much precision)
V3 Liquidity Code Example Explained
function mintNewPosition(
address token0,
address token1,
uint24 fee,
int24 tickLower, // Price range start
int24 tickUpper, // Price range end
uint256 amount0Desired,
uint256 amount1Desired
) external returns (
uint256 tokenId, // Your NFT ID
uint128 liquidity, // Liquidity amount added
uint256 amount0, // Actual token0 used
uint256 amount1 // Actual token1 used
) {
// 1. Transfer tokens to contract
IERC20(token0).transferFrom(msg.sender, address(this), amount0Desired);
IERC20(token1).transferFrom(msg.sender, address(this), amount1Desired);
// 2. Approve position manager
IERC20(token0).approve(POSITION_MANAGER, amount0Desired);
IERC20(token1).approve(POSITION_MANAGER, amount1Desired);
// 3. Set up position parameters
INonfungiblePositionManager.MintParams memory params =
INonfungiblePositionManager.MintParams({
token0: token0,
token1: token1,
fee: fee, // Choose your fee tier
tickLower: tickLower, // Your range start
tickUpper: tickUpper, // Your range end
amount0Desired: amount0Desired,
amount1Desired: amount1Desired,
amount0Min: 0, // Slippage protection
amount1Min: 0, // Slippage protection
recipient: address(this), // Who owns the NFT
deadline: block.timestamp + 300
});
// 4. Mint the position NFT
(tokenId, liquidity, amount0, amount1) =
INonfungiblePositionManager(POSITION_MANAGER).mint(params);
// Note: Unlike V2, you need to manually collect fees later
}
What makes this different from V2:
- Tick Range: You specify exactly where your liquidity is active
- NFT Return: You get a unique NFT instead of fungible tokens
- Fee Tier Choice: You pick the appropriate fee level
- Manual Fee Collection: Fees don't auto-compound
V2 vs V3: The Complete Comparison
Architecture and Philosophy Differences
The fundamental differences between V2 and V3 affect every aspect of how they operate:
Detailed Feature Comparison
Liquidity Provision:
- V2: Spread across entire price curve (0 to ∞)
- V3: Concentrated in custom price ranges
- Impact: V3 can be 4000x more capital efficient
Position Management:
- V2: Set it and forget it (passive)
- V3: Active management required (rebalancing)
- Impact: V3 needs more attention but offers higher returns
Fee Structure:
- V2: Fixed 0.3% for all pairs
- V3: 0.01%, 0.05%, 0.3%, 1% based on asset type
- Impact: More appropriate pricing for different risk levels
Fee Collection:
- V2: Automatically reinvested (compounding)
- V3: Manual collection required
- Impact: V3 gives more control but requires action
Token Representation:
- V2: Fungible ERC20 LP tokens
- V3: Unique ERC721 NFTs
- Impact: V2 positions can be easily traded, V3 positions are unique
Gas Costs:
- V2: Lower (simpler calculations)
- V3: Higher (complex tick math)
- Impact: V3 trades cost ~15-20% more gas
Performance Comparison: Real Numbers
Capital Efficiency Example:
- V2: $10,000 spread across $0-∞, earns fees on ~5% of trades
- V3: $10,000 concentrated in $2800-$3200, earns fees on ~80% of trades
- Result: Same fees earned with much less capital
Risk vs Reward:
- V2: Lower risk, predictable returns, passive
- V3: Higher risk, higher potential returns, active management needed
Impermanent Loss:
- V2: Gradual across all price movements
- V3: More concentrated but can be mitigated with tight ranges
When to Use V2 vs V3: Decision Framework
Use Uniswap V2 When:
You Want Simplicity:
- Set it and forget it liquidity provision
- Don't want to actively manage positions
- Predictable behavior and returns
Gas Costs Matter:
- Frequent small trades
- Building applications where every gas unit counts
- Users are very price-sensitive
Token Characteristics:
- Long-tail tokens without V3 pools
- Very new tokens with uncertain price ranges
- Tokens with extreme volatility
Development Simplicity:
- Building simple DeFi protocols
- Need predictable AMM behavior
- Want to avoid complex tick calculations
Use Uniswap V3 When:
Capital Efficiency is Key:
- Limited capital but want maximum returns
- Professional liquidity provision
- Sophisticated DeFi strategies
You Can Actively Manage:
- Have time and tools for monitoring
- Can rebalance positions regularly
- Understand the risks of going out of range
Asset Characteristics:
- Stablecoin pairs (tight ranges work great)
- Well-established trading pairs
- Assets with predictable trading ranges
Advanced Features Needed:
- Multiple fee tiers
- Precise price range targeting
- Advanced trading strategies
Smart Contract Addresses Reference
For developers building on Uniswap, here are the key contract addresses on Ethereum mainnet:
V2 Contracts:
- Router: Handles all swaps and liquidity operations
- Factory: Creates new trading pairs
V3 Contracts:
- Router: Handles swaps with advanced features
- Factory: Creates pools with different fee tiers
- Position Manager: Manages NFT liquidity positions
- Quoter: Provides price quotes without executing trades