// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../contracts/examples/UniswapV3Swap.sol"; import "../contracts/interfaces/IERC20.sol"; contract UniswapTest is Test { UniswapV3Swap public uniswapSwap; // Mainnet addresses address constant SWAP_ROUTER = 0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45; address constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; uint256 mainnetFork; function setUp() public { // Fork mainnet mainnetFork = vm.createFork(vm.envString("MAINNET_RPC_URL")); vm.selectFork(mainnetFork); // Deploy contract uniswapSwap = new UniswapV3Swap(SWAP_ROUTER); } function testSwapExactInputSingle() public { // Setup: Get some USDC from a whale address whale = 0x47ac0Fb4F2D84898e4D9E7b4DaB3C24507a6D503; // USDC whale uint256 amountIn = 1000 * 10**6; // 1000 USDC uint24 fee = 3000; // 0.3% fee tier uint256 deadline = block.timestamp + 600; // 10 minutes // Impersonate whale and transfer USDC to test contract vm.startPrank(whale); IERC20(USDC).transfer(address(this), amountIn); vm.stopPrank(); // Record initial WETH balance uint256 initialWETH = IERC20(WETH).balanceOf(address(this)); // Approve and swap IERC20(USDC).approve(address(uniswapSwap), amountIn); uint256 amountOut = uniswapSwap.swapExactInputSingle( USDC, WETH, fee, amountIn, 0, // No slippage protection for test deadline ); // Check that we received WETH uint256 finalWETH = IERC20(WETH).balanceOf(address(this)); assertGt(finalWETH, initialWETH, "Should have received WETH"); assertGt(amountOut, 0, "Should have output amount"); } }