Skip to Content
Advanced Mini CoursesUniswap IntroductionSwapping Tokens in Uniswap v3

Swapping Tokens in Uniswap v3

Now that we understand how pools are created and liquidity is provided, let’s look at how swaps work in Uniswap v3.

Understanding Swaps in Uniswap v3

When you swap tokens in Uniswap v3:

  1. The swap moves along the bonding curve, potentially crossing multiple tick boundaries
  2. The price changes according to the constant product formula within each price range
  3. The swap might use liquidity from multiple providers who have positions in different price ranges
  4. The swap incurs a fee based on the pool’s fee tier (0.05%, 0.3%, or 1%)

The SwapRouter Contract

Uniswap v3 uses a contract called SwapRouter to handle swaps. This contract:

  1. Routes your swap through the appropriate pool(s)
  2. Handles the complex logic of crossing tick boundaries
  3. Ensures you receive at least your specified minimum output amount

Code Example: Performing a Swap

Here’s how to perform a swap in Uniswap v3:

// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; contract TokenSwapper { ISwapRouter public swapRouter; constructor(address _swapRouter) { swapRouter = ISwapRouter(_swapRouter); } function swapExactInputSingle( address tokenIn, address tokenOut, uint24 fee, uint256 amountIn, uint256 amountOutMinimum ) external returns (uint256 amountOut) { // Approve the router to spend the token IERC20(tokenIn).approve(address(swapRouter), amountIn); // Create the params for the swap ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({ tokenIn: tokenIn, tokenOut: tokenOut, fee: fee, recipient: address(this), deadline: block.timestamp + 15 minutes, amountIn: amountIn, amountOutMinimum: amountOutMinimum, sqrtPriceLimitX96: 0 // No price limit }); // Execute the swap amountOut = swapRouter.exactInputSingle(params); return amountOut; } function swapExactOutputSingle( address tokenIn, address tokenOut, uint24 fee, uint256 amountOut, uint256 amountInMaximum ) external returns (uint256 amountIn) { // Approve the router to spend the token IERC20(tokenIn).approve(address(swapRouter), amountInMaximum); // Create the params for the swap ISwapRouter.ExactOutputSingleParams memory params = ISwapRouter.ExactOutputSingleParams({ tokenIn: tokenIn, tokenOut: tokenOut, fee: fee, recipient: address(this), deadline: block.timestamp + 15 minutes, amountOut: amountOut, amountInMaximum: amountInMaximum, sqrtPriceLimitX96: 0 // No price limit }); // Execute the swap amountIn = swapRouter.exactOutputSingle(params); // Refund any unused input tokens if (amountIn < amountInMaximum) { IERC20(tokenIn).approve(address(swapRouter), 0); } return amountIn; } }

Types of Swaps

Uniswap v3 supports several types of swaps:

1. Exact Input Single

You specify exactly how much of token A you want to swap, and get at least a minimum amount of token B.

2. Exact Output Single

You specify exactly how much of token B you want to receive, and spend at most a maximum amount of token A.

3. Exact Input (Multi-hop)

Swap a fixed amount of one token for another through multiple pools (e.g., A → B → C).

4. Exact Output (Multi-hop)

Receive a fixed amount of one token by spending another through multiple pools.

Example: Swapping ETH for USDC

Let’s say we want to swap 1 ETH for at least 1,950 USDC:

// Addresses for Ethereum mainnet address WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; address USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; uint24 fee = 3000; // 0.3% // Amount to swap uint256 amountIn = 1 ether; uint256 amountOutMinimum = 1950 * 10**6; // 1,950 USDC // Execute the swap uint256 amountOut = swapExactInputSingle( WETH, USDC, fee, amountIn, amountOutMinimum );

Understanding Price Impact and Slippage

When performing swaps, two important concepts to understand are:

Price Impact

The effect your trade has on the market price. Larger trades relative to pool size have higher price impact.

Slippage

The difference between the expected price and the executed price. To protect against slippage, you set:

  • amountOutMinimum for exact input swaps
  • amountInMaximum for exact output swaps

What Happens During a Swap?

During a swap, several things happen:

  1. The pool calculates the output amount based on the constant product formula
  2. The price moves along the bonding curve
  3. If the price crosses tick boundaries, liquidity is added or removed as needed
  4. Fees are collected and distributed to liquidity providers
  5. The tokens are transferred between the user and the pool

In the next section, we’ll explore the differences between Uniswap v3 and v4, and how v4 improves upon v3’s design.

Last updated on