// 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 ); } }