Skip to content

Instantly share code, notes, and snippets.

@beauwilliams
Created February 3, 2025 10:33
Show Gist options
  • Select an option

  • Save beauwilliams/14cd70a07d753a697911a64e1138a37d to your computer and use it in GitHub Desktop.

Select an option

Save beauwilliams/14cd70a07d753a697911a64e1138a37d to your computer and use it in GitHub Desktop.

Revisions

  1. beauwilliams created this gist Feb 3, 2025.
    92 changes: 92 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,92 @@
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.0;

    // Minimal interface for the Uniswap V2 Router.
    interface IUniswapV2Router {
    function swapExactTokensForTokens(
    uint amountIn, // amount of input tokens to send.
    uint amountOutMin, // minimum amount of output tokens that must be received for the transaction not to revert.
    address[] calldata path,// an array of token addresses. path.length must be >= 2. Pools for each consecutive pair must exist.
    address to, // recipient of the output tokens.
    uint deadline // Unix timestamp after which the transaction will revert.
    ) external returns (uint[] memory amounts);

    // Added function to fetch expected output amounts for a given input.
    function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
    }

    // Minimal ERC20 interface needed for token transfers and approvals.
    interface IERC20 {
    function transferFrom(
    address sender,
    address recipient,
    uint256 amount
    ) external returns (bool);

    function approve(
    address spender,
    uint256 amount
    ) external returns (bool);
    }

    contract SimpleSwap {
    // Instance of the Uniswap V2 Router.
    IUniswapV2Router public immutable uniswapRouter;

    // Set the router address upon deployment.
    constructor(address _router) {
    uniswapRouter = IUniswapV2Router(_router);
    }

    /**
    * @notice Swap a given amount of tokenIn for tokenOut using Uniswap.
    * Slippage is hardcoded to 10% and the deadline is set to 15 minutes from now.
    * @param tokenIn The address of the ERC20 token to swap from.
    * @param tokenOut The address of the ERC20 token to swap to.
    * @param amountIn The exact amount of tokenIn to swap.
    */
    function swapTokens(
    address tokenIn,
    address tokenOut,
    uint amountIn
    ) external {
    // 1. Transfer tokenIn from the caller to this contract.
    // The user must have approved this contract to spend tokenIn.
    require(
    IERC20(tokenIn).transferFrom(msg.sender, address(this), amountIn),
    "Transfer of tokenIn failed"
    );

    // 2. Approve the Uniswap router to spend the tokenIn held by this contract.
    require(
    IERC20(tokenIn).approve(address(uniswapRouter), amountIn),
    "Approval failed"
    );

    // 3. Define the swap path: from tokenIn directly to tokenOut.
    address[] memory path = new address[](2);
    path[0] = tokenIn;
    path[1] = tokenOut;

    // 4. Get the expected output amount using Uniswap's pricing.
    uint[] memory amountsOut = uniswapRouter.getAmountsOut(amountIn, path);
    uint expectedOut = amountsOut[amountsOut.length - 1];

    // 5. Calculate the minimum acceptable output accounting for a 10% slippage tolerance.
    // For example, if expectedOut is 100 tokens, minAmountOut will be 90 tokens.
    uint minAmountOut = (expectedOut * 90) / 100;

    // 6. Set deadline as 15 minutes from the current block timestamp.
    uint deadline = block.timestamp + 15 minutes;

    // 7. Perform the swap on Uniswap.
    // The output tokens will be sent directly to the caller.
    uniswapRouter.swapExactTokensForTokens(
    amountIn,
    minAmountOut,
    path,
    msg.sender,
    deadline
    );
    }
    }