// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;

import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";
import "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol";
import "@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol";

struct StructUser {
    address user;
    mapping(address => mapping(address => StructTokenConfig)) swappedConfig;
    mapping(address => StructPerWithDivision) perToTrade;
}

struct StructAnalytics {
    address[] users;
    address[] tokens;
}

struct StructPerWithDivision {
    uint256 per;
    uint256 division;
}

struct StructTokenConfig {
    address token;
    address pair;
    uint256 lastPrice;
}

contract SwapRouter is
    Initializable,
    PausableUpgradeable,
    OwnableUpgradeable,
    UUPSUpgradeable
{
    using SafeERC20 for IERC20;

    struct TokenConfig {
        address token;
        address pair;
        uint256 lastPrice;
    }

    mapping(address => StructUser) private _mappingStructUser;
    receive() external payable {}

    event TokenSwapped(
        address indexed user,
        address indexed token,
        uint256 amountIn,
        uint256 amountOut,
        uint256 price
    );

    /// @custom:oz-upgrades-unsafe-allow constructor
    constructor() {
        _disableInitializers();
    }

    function initialize(
        address initialOwner,
        address _uniswapV3Router
    ) public initializer {
        __Pausable_init();
        __Ownable_init(initialOwner);
        __UUPSUpgradeable_init();
    }

    function swapTokensV2(
        address user_,
        address router,
        address tokenIn,
        uint256 amountIn,
        address tokenOut
    ) external whenNotPaused {
        StructUser storage userAccount = _mappingStructUser[user_];

        require(
            tokenConfigs[tokenIn].token != address(0),
            "Token not configured"
        );

        IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);
        IERC20(tokenIn).approve(router, amountIn);

        IUniswapV2Router02 uniswapV2Router = IUniswapV2Router02(router);

        address[] memory path = new address[](2);
        path[0] = tokenIn;
        path[1] = tokenOut;

        uint256 balanceBefore = IERC20(tokenIn).balanceOf(address(this));

        uint256[] memory amounts = uniswapV2Router.swapExactTokensForTokens(
            amountIn,
            0,
            path,
            msg.sender,
            block.timestamp + 60
        );

        uint256 balanceAfter = IERC20(tokenIn).balanceOf(address(this));
        uint256 leftover = balanceAfter - balanceBefore;

        if (leftover > 0) {
            IERC20(tokenIn).safeTransfer(msg.sender, leftover);
        }

        uint256 newPrice = calculateCurrentPrice(tokenIn, amounts[0]);
        emit TokenSwapped(msg.sender, tokenIn, amountIn, amounts[1], newPrice);
    }

    function swapTokensV3(
        address uniswapV3Router_,
        address tokenIn,
        uint256 amountIn,
        address tokenOut,
        uint24 fee
    ) external whenNotPaused {
        require(
            tokenConfigs[tokenIn].token != address(0),
            "Token not configured"
        );

        ISwapRouter iUniswapRouter = ISwapRouter(uniswapV3Router_);

        IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);
        IERC20(tokenIn).approve(uniswapV3Router_, amountIn);

        uint256 balanceBefore = IERC20(tokenIn).balanceOf(address(this));

        ISwapRouter.ExactInputSingleParams memory params = ISwapRouter
            .ExactInputSingleParams({
                tokenIn: tokenIn,
                tokenOut: tokenOut,
                fee: fee,
                recipient: msg.sender,
                deadline: block.timestamp + 60,
                amountIn: amountIn,
                amountOutMinimum: 0,
                sqrtPriceLimitX96: 0
            });

        iUniswapRouter.exactInputSingle(params);

        uint256 balanceAfter = IERC20(tokenIn).balanceOf(address(this));
        uint256 leftover = balanceAfter - balanceBefore;

        if (leftover > 0) {
            IERC20(tokenIn).safeTransfer(msg.sender, leftover);
        }

        uint256 newPrice = calculateCurrentPrice(tokenIn, amountIn);
        emit TokenSwapped(msg.sender, tokenIn, amountIn, amountIn, newPrice);
    }

    function calculateCurrentPrice(
        address token,
        uint256 amount
    ) internal view returns (uint256) {
        // Placeholder function for real price calculation.
        return amount;
    }

    function getCurrentTokenPrice(
        address token,
        address tokenOut,
        uint24 fee
    ) public view returns (uint256 price) {
        address pair = tokenConfigs[token].pair;
        require(pair != address(0), "Token pair not configured");

        uint256 price = fetchPriceFromReserves(pair, token);

        return price;
    }

    function fetchPriceFromReserves(
        address pair,
        address token
    ) internal view returns (uint256) {
        (uint256 reserve0, uint256 reserve1, ) = IUniswapV2Pair(pair)
            .getReserves();
        if (IUniswapV2Pair(pair).token0() == token) {
            return (reserve1 * 1e18) / reserve0;
        } else {
            return (reserve0 * 1e18) / reserve1;
        }
    }

    function pause() public onlyOwner {
        _pause();
    }

    function unpause() public onlyOwner {
        _unpause();
    }

    function _authorizeUpgrade(
        address newImplementation
    ) internal override onlyOwner {}
}


how do i verify that uniswaprouter address is correct?