SimpleSwap

There are two things to consider when you swap in a pair without router:

  1. which token is token0 and which token is token1

  2. what is the optimal amountOut (considering the 0.3% swap fee)

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import "./interfaces/IUniswapV2Pair.sol";
import "./interfaces/IERC20.sol";

contract SimpleSwap {
    /**
     *  PERFORM A SIMPLE SWAP WITHOUT ROUTER EXERCISE
     *
     *  The contract has an initial balance of 1 WETH.
     *  The challenge is to swap any amount of WETH for USDC token using the `swap` function
     *  from USDC/WETH pool.
     *
     */
    function performSwap(address pool, address weth, address usdc) public {
        /**
         *     swap(uint256 amount0Out, uint256 amount1Out, address to, bytes calldata data);
         *
         *     amount0Out: the amount of USDC to receive from swap.
         *     amount1Out: the amount of WETH to receive from swap.
         *     to: recipient address to receive the USDC tokens.
         *     data: leave it empty.
         */

        // Get current reserves
        IUniswapV2Pair pair = IUniswapV2Pair(pool);
        (uint112 reserve0, uint112 reserve1,) = pair.getReserves();
        
        // Get token order
        address token0 = pair.token0();
        address token1 = pair.token1();
        
        // Determine which token is USDC and which is WETH
        bool wethIsToken0 = token0 == weth;
        
        // Get WETH balance to swap
        uint256 wethBalance = IERC20(weth).balanceOf(address(this));
        
        // Transfer WETH to pool
        IERC20(weth).transfer(pool, wethBalance);
        
        // Calculate output amount using constant product formula
        // We need to account for the 0.3% fee
        uint256 amountInWithFee = wethBalance * 997;
        uint256 numerator;
        uint256 denominator;
        
        if (wethIsToken0) {
            numerator = amountInWithFee * reserve1;
            denominator = reserve0 * 1000 + amountInWithFee;
        } else {
            numerator = amountInWithFee * reserve0;
            denominator = reserve1 * 1000 + amountInWithFee;
        }
        
        uint256 amountOut = numerator / denominator;
        
        // Perform swap
        if (wethIsToken0) {
            // WETH is token0, USDC is token1, so we want amount0Out = 0, amount1Out = amountOut
            pair.swap(0, amountOut, address(this), "");
        } else {
            // WETH is token1, USDC is token0, so we want amount0Out = amountOut, amount1Out = 0
            pair.swap(amountOut, 0, address(this), "");
        }
    }
}

Last updated