Skip to Content
Advanced Mini CoursesUniswap IntroductionInitializing a Uniswap v3 Pool

Initializing a Uniswap v3 Pool

Creating a new Uniswap v3 pool is the first step if you want to enable trading for a token pair that doesn’t have a pool yet. Let’s walk through the process step by step.

Prerequisites

Before initializing a pool, you need:

  1. Two ERC-20 tokens (or one token and ETH/WETH)
  2. A fee tier (0.05%, 0.3%, or 1%)
  3. An initial price for the token pair

Understanding Pool Initialization

When you initialize a Uniswap v3 pool, you’re:

  1. Creating a new pool contract for the token pair
  2. Setting the initial price (as sqrtPriceX96)
  3. Preparing the pool to accept liquidity

However, the pool won’t be usable until someone adds liquidity to it.

Code Example: Initializing a Pool

Here’s a simplified example of how to initialize a Uniswap v3 pool using Solidity:

// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol"; import "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol"; contract PoolInitializer { address public factory; constructor(address _factory) { factory = _factory; } function createAndInitializePool( address tokenA, address tokenB, uint24 fee, uint160 sqrtPriceX96 ) external returns (address pool) { // Create the pool pool = IUniswapV3Factory(factory).createPool(tokenA, tokenB, fee); // Initialize the pool with the starting price IUniswapV3Pool(pool).initialize(sqrtPriceX96); return pool; } }

Calculating the Initial sqrtPriceX96

The trickiest part is calculating the correct sqrtPriceX96 value for your initial price. Here’s a helper function:

function calculateSqrtPriceX96(uint256 price, uint8 decimals0, uint8 decimals1) public pure returns (uint160) { // Adjust for decimal differences between tokens uint256 adjustedPrice = price * 10**(decimals0 - decimals1); // Calculate square root uint256 sqrtPrice = sqrt(adjustedPrice * 10**18); // Scale by 2^96 return uint160((sqrtPrice * (2**96)) / 10**9); } // Helper function to calculate square root function sqrt(uint256 x) internal pure returns (uint256) { if (x == 0) return 0; uint256 z = (x + 1) / 2; uint256 y = x; while (z < y) { y = z; z = (x / z + z) / 2; } return y; }

Example: Initializing an ETH/USDC Pool

Let’s say we want to create an ETH/USDC pool with a 0.3% fee, and the initial price is 2000 USDC per ETH:

// Addresses for Ethereum mainnet address WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; address USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; uint24 fee = 3000; // 0.3% // Calculate sqrtPriceX96 for 2000 USDC per ETH // WETH has 18 decimals, USDC has 6 decimals uint256 price = 2000 * 10**6; // 2000 with USDC's 6 decimals uint160 sqrtPriceX96 = calculateSqrtPriceX96(price, 6, 18); // Create and initialize the pool address pool = createAndInitializePool(USDC, WETH, fee, sqrtPriceX96);
Token Order Matters

In Uniswap v3, the token with the lower address value is considered token0, and the other is token1. The price is always expressed as the amount of token1 per token0.

What Happens After Initialization?

After initialization, the pool exists but has no liquidity. It’s like an empty marketplace with a price tag but no goods to trade.

The pool will remain in this state until someone adds liquidity. The initial price you set is important because:

  1. It determines the starting point for liquidity provision
  2. It affects how tokens need to be provided when adding the first liquidity
  3. If set incorrectly, it can make the pool less efficient or harder to use

In the next section, we’ll learn how to add liquidity to our newly created pool.

Last updated on