// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "../interfaces/IERC20.sol"; interface ISwapRouter { struct ExactInputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; uint160 sqrtPriceLimitX96; } function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut); } /** * @title UniswapV3Swap * @notice Example contract for swapping tokens on Uniswap v3 */ contract UniswapV3Swap { ISwapRouter public immutable swapRouter; constructor(address swapRouter_) { swapRouter = ISwapRouter(swapRouter_); } /** * @notice Swap tokens using Uniswap v3 * @param tokenIn The input token * @param tokenOut The output token * @param fee The fee tier (100, 500, 3000, 10000) * @param amountIn The input amount * @param amountOutMinimum The minimum output amount (slippage protection) * @param deadline The transaction deadline */ function swapExactInputSingle( address tokenIn, address tokenOut, uint24 fee, uint256 amountIn, uint256 amountOutMinimum, uint256 deadline ) external returns (uint256 amountOut) { // Transfer tokens from user IERC20(tokenIn).transferFrom(msg.sender, address(this), amountIn); // Approve router IERC20(tokenIn).approve(address(swapRouter), amountIn); // Execute swap ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({ tokenIn: tokenIn, tokenOut: tokenOut, fee: fee, recipient: msg.sender, deadline: deadline, amountIn: amountIn, amountOutMinimum: amountOutMinimum, sqrtPriceLimitX96: 0 }); amountOut = swapRouter.exactInputSingle(params); } }