账户
0x92...e0e4
0x92...e0E4

0x92...e0E4

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

interface IERC20 {
    function balanceOf(address account) external view returns (uint256);
    function transfer(address recipient, uint256 amount) external returns (bool);
}

library TransferHelper {
    function safeTransfer(address token, address to, uint256 value) internal {
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20(token).transfer.selector, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED');
    }

    function safeTransferETH(address to, uint256 value) internal {
        (bool success, ) = to.call{value: value}(new bytes(0));
        require(success, 'TransferHelper: ETH_TRANSFER_FAILED');
    }
}



contract KaskadeRouterV1 {
    address private _owner;
    bool private _disabled;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

  event SwapSuccessful(
    address indexed user, 
    address tokenIn, 
    address tokenOut, 
    uint amountIn, 
    uint amountOut, 
    uint timestamp
);

    event Disabled();

     struct TokenAmount {
        address token;
        uint256 amount;
    }

    // Define a struct for whitelisted routers
struct RouterInfo {
    bool isWhitelisted;
    uint8 routerType;
}

// Mapping to store whitelisted routers
mapping(address => RouterInfo) public whitelistedRouters;


// Enum to represent different router types
enum RouterType {
    UniswapV2,
    UniswapV3,
    VelodromeV1,
    Ambient,
    Iziswap,
    Syncswap,
    DodoswapV2,
    Wombat
}


    constructor() {
        _transferOwnership(msg.sender);
    }

    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    function _checkOwner() internal view virtual {
        require(owner() == msg.sender, "Ownable: caller is not the owner");
    }

    function owner() public view virtual returns (address) {
        return _owner;
    }

    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }

    modifier ensure(uint deadline) {
        if (block.timestamp > deadline) {
            revert("Expired");
        }
        _;
    }

    modifier whenNotDisabled() {
        require(!_disabled, "Contract is disabled");
        _;
    }

    // Function to add or update whitelisted routers (should be called by owner)
function updateWhitelistedRouter(address router, bool isWhitelisted, uint8 routerType) external onlyOwner {
    whitelistedRouters[router] = RouterInfo(isWhitelisted, routerType);
}

 function swap(
    address router,
    address tokenIn,
    address tokenOut,
    uint amountIn,
    bytes calldata callData
) external payable whenNotDisabled ensure(block.timestamp + 300) returns (uint256 amountOut) {
    require(whitelistedRouters[router].isWhitelisted, "Router not whitelisted");

    // Delegate the call to the specified router
    (bool success, bytes memory result) = router.delegatecall(callData);
    
    // If the delegatecall failed, revert the transaction
    require(success, "Delegatecall to swap failed");

    // If the delegatecall was successful, try to decode the amountOut result
    RouterType routerType = RouterType(whitelistedRouters[router].routerType);

 
        if (routerType == RouterType.UniswapV2 || routerType == RouterType.VelodromeV1) {
            uint[] memory amounts = abi.decode(result, (uint[]));
            amountOut = amounts[amounts.length - 1];
        } else if (routerType == RouterType.UniswapV3 || routerType == RouterType.Iziswap || routerType == RouterType.DodoswapV2 || routerType == RouterType.Wombat) {
            amountOut = abi.decode(result, (uint256));
        } else if (routerType == RouterType.Ambient) {
            (int128 baseFlow, int128 quoteFlow) = abi.decode(result, (int128, int128));
            if (quoteFlow > 0) {
                amountOut = uint256(uint128(quoteFlow));
            } else {
                require(baseFlow < 0, "Unexpected Ambient flow values");
                amountOut = uint256(uint128(-baseFlow));
            }
        } else if (routerType == RouterType.Syncswap) {
            TokenAmount memory tokenAmount = abi.decode(result, (TokenAmount));
            amountOut = tokenAmount.amount;
        } else {
            // If we reach here, it's an unsupported router type
            amountOut = 0;
        }
   
    emit SwapSuccessful(msg.sender, tokenIn, tokenOut, amountIn, amountOut, block.timestamp);
}
    function disable() external onlyOwner {
        _disabled = true;
        emit Disabled();
    }

    function isDisabled() external view returns (bool) {
        return _disabled;
    }

    function rescueERC20(address token, address to, uint256 amount) external onlyOwner {
        require(to != address(0) && to != token, "Invalid to");

        uint balance = IERC20(token).balanceOf(address(this));

        if (amount == 0) {
            TransferHelper.safeTransfer(token, to, balance);
        } else {
            require(amount <= balance, "Exceeds balance");
            TransferHelper.safeTransfer(token, to, amount);
        }
    }

    function rescueETH(address payable to, uint256 amount) external onlyOwner {
        if (amount == 0) {
            amount = address(this).balance;
        }
        TransferHelper.safeTransferETH(to, amount);
    }

    receive() external payable {}
}
设置
{
  "compilationTarget": {
    "contracts/KaskadeRouterV1.sol": "KaskadeRouterV1"
  },
  "evmVersion": "paris",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "remappings": []
}
ABI
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[],"name":"Disabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"address","name":"tokenIn","type":"address"},{"indexed":false,"internalType":"address","name":"tokenOut","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"SwapSuccessful","type":"event"},{"inputs":[],"name":"disable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isDisabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"rescueERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"rescueETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"router","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"bytes","name":"callData","type":"bytes"}],"name":"swap","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"router","type":"address"},{"internalType":"bool","name":"isWhitelisted","type":"bool"},{"internalType":"uint8","name":"routerType","type":"uint8"}],"name":"updateWhitelistedRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whitelistedRouters","outputs":[{"internalType":"bool","name":"isWhitelisted","type":"bool"},{"internalType":"uint8","name":"routerType","type":"uint8"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]