Skip to content

Instantly share code, notes, and snippets.

@beauwilliams
Created February 3, 2025 10:33
Show Gist options
  • Save beauwilliams/14cd70a07d753a697911a64e1138a37d to your computer and use it in GitHub Desktop.
Save beauwilliams/14cd70a07d753a697911a64e1138a37d to your computer and use it in GitHub Desktop.
SimpleSwapV2
// 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
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment