账户
0x3b...8aa3
0x3b...8Aa3

0x3b...8Aa3

US$0.00
此合同的源代码已经过验证!
合同元数据
编译器
0.8.26+commit.8a97fa7a
语言
Solidity
合同源代码
文件 1 的 1:IAMM_swapper.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// Interface for interacting with AMM pairs like UniswapV2 or similar
interface IAMMPair {
    function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
    function getReserves() external view returns (uint reserve0, uint reserve1, uint32 blockTimestampLast);
    function token0() external view returns (address);
    function token1() external view returns (address);
}

// Standard ERC20 interface for token interactions
interface IERC20 {
    function balanceOf(address account) external view returns (uint);
    function transferFrom(address sender, address recipient, uint amount) external returns (bool);
    function transfer(address recipient, uint amount) external returns (bool);
    function allowance(address owner, address spender) external view returns (uint);
}

// TokenSwapper contract that interacts with AMM pairs and ERC20 tokens
contract TokenSwapperV2 {
    address public owner;

    address constant TOKEN1 = 0x4200000000000000000000000000000000000006;
    address constant TOKEN2 = 0x0b3e328455c4059EEb9e3f84b5543F74E24e7E1b;

    event SwapExecuted(address indexed tokenIn, uint amountIn, uint amountOutMin, uint amountOut, address indexed recipient, bool success);

    constructor() {
        owner = msg.sender;
    }

    modifier onlyOwner() {
        require(msg.sender == owner, "Caller is not the owner");
        _;
    }

    // Function to calculate the output amount based on input, reserves, and an optional tax percentage
    function getAmountOut(
        uint amountIn,
        uint reserveIn,
        uint reserveOut,
        uint taxPercentIn,
        uint taxPercentOut
    ) public pure returns (uint amountOut) {
        require(amountIn > 0, "TokenSwapper: INSUFFICIENT_INPUT_AMOUNT");
        require(reserveIn > 0 && reserveOut > 0, "TokenSwapper: INSUFFICIENT_LIQUIDITY");

        // Calculate the amount in after applying input tax
        uint amountInAfterTax = amountIn * (100 - taxPercentIn) / 100;

        // Standard Uniswap V2 formula with fee
        uint amountInWithFee = amountInAfterTax * 997;
        uint numerator = amountInWithFee * reserveOut;
        uint denominator = reserveIn * 1000 + amountInWithFee;
        uint amountOutBeforeTax = numerator / denominator;

        // Apply output tax
        amountOut = amountOutBeforeTax * (100 - taxPercentOut) / 100;
    }

    // Function to get reserves for the swap
    function getReserves(IAMMPair ammPair, bool isToken0In) internal view returns (uint reserveIn, uint reserveOut) {
        (uint reserve0, uint reserve1,) = ammPair.getReserves();
        return isToken0In ? (reserve0, reserve1) : (reserve1, reserve0);
    }

    // Function to determine the input token based on the swap direction
    function getTokens(IAMMPair ammPair, bool isToken0In) internal view returns (address tokenIn) {
        return isToken0In ? ammPair.token0() : ammPair.token1();
    }

    // Function to execute the swap on the AMM pair
    function swap(
        address pair,
        uint amountIn,
        uint amountOutMin,
        bool isToken0In,
        uint taxPercent
    ) external {
        IAMMPair ammPair = IAMMPair(pair);

        // Determine the input and output tokens
        address tokenIn = getTokens(ammPair, isToken0In);

        uint taxPercentIn = 0;
        uint taxPercentOut = 0;

        if (tokenIn == TOKEN1 || tokenIn == TOKEN2) {
            // Apply tax on output token
            taxPercentOut = taxPercent;
        } else {
            // Apply tax on input token
            taxPercentIn = taxPercent;
        }

        // Get reserves
        (uint reserveIn, uint reserveOut) = getReserves(ammPair, isToken0In);

        // Calculate the expected output amount with the tax applied
        uint amountOut = getAmountOut(amountIn, reserveIn, reserveOut, taxPercentIn, taxPercentOut);
        require(amountOut >= amountOutMin, "TokenSwapper: INSUFFICIENT_OUTPUT_AMOUNT");

        // Transfer input tokens directly from the sender to the AMM pair
        require(IERC20(tokenIn).transferFrom(msg.sender, pair, amountIn), "TokenSwapper: TRANSFER_FAILED");

        // Execute the swap on the AMM pair
        ammPair.swap(
            isToken0In ? 0 : amountOut,
            isToken0In ? amountOut : 0,
            msg.sender, // Send output tokens directly to the user
            ""
        );

        // Emit the swap event
        emit SwapExecuted(tokenIn, amountIn, amountOutMin, amountOut, msg.sender, true);
    }

    // Function to rescue tokens accidentally sent to the contract
    function rescueTokens(address token, uint amount, address to) external onlyOwner {
        require(IERC20(token).transfer(to, amount), "TokenSwapper: TRANSFER_FAILED");
    }

    // Function to transfer ownership of the contract
    function transferOwnership(address newOwner) external onlyOwner {
        require(newOwner != address(0), "New owner cannot be the zero address");
        owner = newOwner;
    }
}
设置
{
  "compilationTarget": {
    "contracts/IAMM_swapper.sol": "TokenSwapperV2"
  },
  "evmVersion": "cancun",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "optimizer": {
    "enabled": false,
    "runs": 200
  },
  "remappings": []
}
ABI
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"tokenIn","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"bool","name":"success","type":"bool"}],"name":"SwapExecuted","type":"event"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"reserveIn","type":"uint256"},{"internalType":"uint256","name":"reserveOut","type":"uint256"},{"internalType":"uint256","name":"taxPercentIn","type":"uint256"},{"internalType":"uint256","name":"taxPercentOut","type":"uint256"}],"name":"getAmountOut","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"rescueTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pair","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"bool","name":"isToken0In","type":"bool"},{"internalType":"uint256","name":"taxPercent","type":"uint256"}],"name":"swap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]