账户
0x6e...2a5f
0x6e...2a5F

0x6e...2a5F

$500
此合同的源代码已经过验证!
合同元数据
编译器
0.7.6+commit.7338295f
语言
Solidity
合同源代码
文件 1 的 1:MyContract.sol
// SPDX-License-Identifier: GPL-3.0

pragma solidity =0.7.6;
pragma abicoder v2;

interface IUniswapV2Pair {
    function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
    function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
}

interface IUniswapV3Pool {
    function swap(
        address recipient,
        bool zeroForOne,
        int256 amountSpecified,
        uint160 sqrtPriceLimitX96,
        bytes calldata data
    ) external returns (int256 amount0, int256 amount1);
    
    function token0() external view returns (address);
    function token1() external view returns (address);
}

library SafeMath {

    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");
        return c;
    }

    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) return 0;
        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");
        return c;
    }
}

library BytesLib {
    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {
        address tempAddress;

        assembly {
            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)
        }

        return tempAddress;
    }
    
    function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8)
    {
        uint8 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x1), _start))
        }

        return tempUint;
    }
    
    function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96)
    {
        uint96 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0xC), _start))
        }

        return tempUint;
    }
    
    function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) {
        uint64 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x8), _start))
        }

        return tempUint;
    }
}

/// @title Functions for manipulating path data for multihop swaps
library Path {
    using BytesLib for bytes;

    function decodeFirstPool(bytes memory path)
        internal
        pure
        returns (
            bytes8 previousTokenPairs,
            uint8 zeroForOne,
            uint8 isSimulation,
            uint96 firstAmountIn,
            uint8 lastPairIndex,
            address[] memory previousPairsPath,
            uint96[] memory previousRevertAmounts
        )
    {
        previousTokenPairs = bytes8(path.toUint64(0));
        
        zeroForOne = path.toUint8(8); // 1 octet
        isSimulation = path.toUint8(9); // 1 octet
        firstAmountIn = path.toUint96(10); // 12 octeti
        lastPairIndex = path.toUint8(22); // 1 octet

        //get array size of addresses
        uint8 addressSize = path.toUint8(23); // 1 octet
        
        address[] memory aNewAddr = new address[](addressSize);
        
        for(uint i = 0; i < addressSize; ++i)
        {
            aNewAddr[i] = (path.toAddress((24 + (i * 20))));
        }
        previousPairsPath = aNewAddr;
        
        //get array of revert amount
        uint8 lastIndex = (24 + (addressSize * 20));
        uint8 aRevertSize = path.toUint8(lastIndex); // 1 octet
        uint96[] memory aNewRevert = new uint96[](aRevertSize);
        
        for(uint i = 0; i < aRevertSize; ++i)
        {
            aNewRevert[i] = (path.toUint96(((lastIndex + 1) + (i * 12))));
        }
        previousRevertAmounts = aNewRevert;
    }
}

library UniswapV2Library {
    using SafeMath for uint;

    // returns sorted token addresses, used to handle return values from pairs sorted in this order
    function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) {
        require(tokenA != tokenB, 'UniswapV2Library: IDENTICAL_ADDRESSES');
        (token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
        require(token0 != address(0), 'UniswapV2Library: ZERO_ADDRESS');
    }

    // given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset
    function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) internal pure returns (uint amountOut) {
        uint amountInWithFee = amountIn.mul(997);
        uint numerator = amountInWithFee.mul(reserveOut);
        uint denominator = reserveIn.mul(1000).add(amountInWithFee);
        amountOut = numerator / denominator;
    }
}

interface IERC20 {
    function transfer(address to, uint value) external returns (bool);
}

interface IWETH is IERC20{
    function deposit() external payable;
    function withdraw(uint) external;
}

interface IUniswapV3SwapCallback {
    function uniswapV3SwapCallback(
        int256 amount0Delta,
        int256 amount1Delta,
        bytes calldata data
    ) external;
}

contract SwappingContract is IUniswapV3SwapCallback
{
    using Path for bytes;
    
	IWETH private constant WETH = IWETH(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
	
    //Constructor
	constructor()
	{		
	}
	
   /**
   * @dev Throws if called by any account that's not whitelisted.
   */
    modifier onlyWhitelisted() {
    require(msg.sender == 0xd7E1236C08731C3632519DCd1A581bFe6876a3B2, '_|_');
    _;
    }
    
  	//Represents the actual swap function..
  	function internalSwapV3(address[] memory pairsPath, uint96[] memory aRevertAmounts, bytes8 indexTokensPairs, uint64 maxBlockPermitted, uint64 amountIn, uint64 minerTip) internal
  	{
  	    require(block.number <= maxBlockPermitted, "Zzzz...");
  	    
  	    //this is valid if first pair is v2
  	    if(indexTokensPairs[1] == 0x00 || indexTokensPairs[1] == 0x01)
  	    {
  	        //else continue
		    WETH.transfer(pairsPath[0], amountIn);
  	    }
  	    
        for(uint256 i = 1; i <= pairsPath.length; ++i)
        {
            byte aPairType = indexTokensPairs[i];
            
            if(i < pairsPath.length) //not last pair
            {
                if(indexTokensPairs[i + 1] == 0x03 || indexTokensPairs[i + 1] == 0x04)
                {
                    uint currentIndex = i;
                    
                    while(currentIndex < pairsPath.length) // we are not last pair
                    {
                        if(indexTokensPairs[currentIndex + 1] == 0x03 || indexTokensPairs[currentIndex + 1] == 0x04)
                        {
                            //if index the last one..and we have v3,,,execuyte it
                            if(currentIndex == (pairsPath.length - 1))
                            {
                                prepareV3Data(pairsPath, aRevertAmounts, indexTokensPairs, currentIndex, amountIn);
                                currentIndex++;
                                break;
                            }
                            
                            currentIndex++;
                        }
                        else
                        {
                            //finish line.. execute swap on last v3 pair
                            prepareV3Data(pairsPath, aRevertAmounts, indexTokensPairs, currentIndex - 1, amountIn);
                            break;
                        }
                    }
                    
                    i = currentIndex;
                    continue;
                }
            }

            if(aPairType == 0x03 || aPairType == 0x04)
            {
                IUniswapV3Pool aPool = IUniswapV3Pool(pairsPath[i - 1]);
                
                (address tokenIn, address tokenOut) = aPairType == 0x03? (aPool.token0(), aPool.token1()) : (aPool.token1(), aPool.token0());
                bool zeroForOne = tokenIn < tokenOut;

                aPool.swap(
                    (i < pairsPath.length? pairsPath[i] : address(this)), zeroForOne, i == 1? amountIn : int256(aRevertAmounts[i - 2]), (zeroForOne ? 4295128740 : 1461446703485210103287273052203988822378723970341), 
                    abi.encodePacked(bytes8(0), zeroForOne, false, uint96(0), uint8(10), uint8(1), address(0), uint8(1), uint96(0)));
            }
            else
            {
                (uint96 amount0Out, uint96 amount1Out) = (aPairType == 0x01) ? (uint96(0), aRevertAmounts[i - 1]) : (aRevertAmounts[i - 1], uint96(0));

			    IUniswapV2Pair(pairsPath[i - 1]).swap(
				     amount0Out, amount1Out, (i < pairsPath.length? pairsPath[i] : address(this)), new bytes(0));
            }
        }
        
        //check if last pair was v3..check the 
        byte actionType = indexTokensPairs[7];
        if(actionType == 0x01)
        {
            WETH.withdraw(200000000000000000); //0.2 eth unwrap..then send to wallet.
            msg.sender.transfer(200000000000000000);
        }
        else if(actionType == 0x02)
        {
            block.coinbase.transfer(minerTip);
        }
  	}
  	
  	function prepareV3Data(address[] memory pairsPath, uint96[] memory aRevertAmounts, bytes8 indexTokensPairs, uint256 myIndex, uint96 amountIn) internal
  	{
  	    //add all information regarding current pair
        IUniswapV3Pool aPool = IUniswapV3Pool(pairsPath[myIndex]);

        (address tokenIn, address tokenOut) = indexTokensPairs[myIndex + 1] == 0x03? (aPool.token0(), aPool.token1()) : (aPool.token1(), aPool.token0());
        bytes memory encodedData = encodePacking(tokenIn < tokenOut, amountIn, (myIndex == 0? uint8(10) : uint8(myIndex)), indexTokensPairs, pairsPath, aRevertAmounts);
        
        aPool.swap(
            (myIndex < (pairsPath.length - 1)? pairsPath[myIndex + 1] : address(this)), tokenIn < tokenOut, myIndex == 0? int256(amountIn) : int256(aRevertAmounts[myIndex - 1]), (tokenIn < tokenOut ? 4295128740 : 1461446703485210103287273052203988822378723970341), 
            encodedData);
  	}
  	
  	function encodePacking(bool zeroOne, uint96 amountIn, uint8 lastIndex, bytes8 tokenPairs, address[] memory pairsPath, uint96[] memory aRevertAmounts) internal pure returns(bytes memory)
  	{
  	    if(pairsPath.length == 2)
  	    {
  	       return abi.encodePacked(tokenPairs, zeroOne, false, amountIn, (lastIndex == 0? uint8(10) : uint8(lastIndex)), uint8(2), pairsPath[0], pairsPath[1], uint8(2), aRevertAmounts[0], aRevertAmounts[1]); 
  	    }
  	    else if(pairsPath.length == 3)
  	    {
  	        return abi.encodePacked(tokenPairs, zeroOne, false, amountIn, (lastIndex == 0? uint8(10) : uint8(lastIndex)), uint8(3), pairsPath[0], pairsPath[1],  pairsPath[2], uint8(3), aRevertAmounts[0], aRevertAmounts[1], aRevertAmounts[2]); 
  	    }
  	    else if(pairsPath.length == 4)
  	    {
  	        bytes memory firstPart = abi.encodePacked(tokenPairs, zeroOne, false, amountIn, (lastIndex == 0? uint8(10) : uint8(lastIndex)), uint8(4), pairsPath[0], pairsPath[1]);
  	        return abi.encodePacked(firstPart, pairsPath[2], pairsPath[3], uint8(4), aRevertAmounts[0], aRevertAmounts[1], aRevertAmounts[2], aRevertAmounts[3]);
  	    }
  	    else 
  	    {
  	        bytes memory firstPart = abi.encodePacked(tokenPairs, zeroOne, false, amountIn, (lastIndex == 0? uint8(10) : uint8(lastIndex)), uint8(5), pairsPath[0], pairsPath[1], pairsPath[2], pairsPath[3]);
  	        return abi.encodePacked(firstPart, pairsPath[4], uint8(5), aRevertAmounts[0], aRevertAmounts[1], aRevertAmounts[2], aRevertAmounts[3], aRevertAmounts[4]);
  	    }
  	}
  	
  	//Represents the actual swap function..
  	function internalSwap(address[] memory pairsPath, uint96[] memory aRevertAmounts, bytes8 indexTokensPairs, uint64 maxBlockPermitted, uint64 amountIn, uint64 minerTip) internal
  	{
  	    require(block.number <= maxBlockPermitted, "Zzzz...");
  	    
  	    //else continue
	    WETH.transfer(pairsPath[0], amountIn);
  	    
        for(uint256 i = 1; i <= pairsPath.length; ++i)
        {
            (uint96 amount0Out, uint96 amount1Out) = (indexTokensPairs[i] == 0x01) ? (uint96(0), aRevertAmounts[i - 1]) : (aRevertAmounts[i - 1], uint96(0));

			IUniswapV2Pair(pairsPath[i - 1]).swap(
			    amount0Out, amount1Out, (i < pairsPath.length? pairsPath[i]: address(this)), new bytes(0));
        }
        
        byte actionType = indexTokensPairs[7];
        if(actionType == 0x01)
        {
            WETH.withdraw(200000000000000000); //0.2 eth unwrap..then send to wallet.
            msg.sender.transfer(200000000000000000);
        }
        else if(actionType == 0x02)
        {
            block.coinbase.transfer(minerTip);
        }
  	}
  	
  	//for 3 pairs! Max Hop: 4
  	function thirdWaySwap(bytes32 aInputData1, bytes32 aInputData2, bytes32 aInputData3, bytes32 aFinalData) onlyWhitelisted external payable
	{
        uint96[] memory aRevertAmounts = new uint96[](3);
        address[] memory pairsPath = new address[](3);
        bytes8 indexTokensPairs;
        uint64 maxBlockPermitted;
        uint64 minerTip;
        uint64 amountIn;
        
        assembly 
        {
            //now the hardest part....
            //======================DECODE FIRST PART====================//
            mstore(0x0C, aInputData1)
            mstore(add(pairsPath, 32), mload(0)) // add it to first element from array
            
            //now take the first total amount
            mstore(0, aInputData1)
            mstore(add(aRevertAmounts, 32), mload(0))
            
            //=======================DECODE SECOND PART=============================//
            mstore(0x0C, aInputData2)
            mstore(add(pairsPath, 64), mload(0)) // add it to first element from array
            
            //now take the first total amount
            mstore(0, aInputData2)
            mstore(add(aRevertAmounts, 64), mload(0))
            
            //=======================DECODE THIRD PART=============================//
            mstore(0x0C, aInputData3)
            mstore(add(pairsPath, 96), mload(0)) // add it to first element from array
            
            //now take the first total amount
            mstore(0, aInputData3)
            mstore(add(aRevertAmounts, 96), mload(0))
            
            //=======================DECODE FINAL PART==============================//
            indexTokensPairs := aFinalData
            
            mstore(0x10, aFinalData) //primii 8 octeti sunt token inputs... pos 24
            maxBlockPermitted := mload(0)
            
            mstore(0x08, aFinalData) //primii 8 octeti sunt token inputs... pos 24
            amountIn := mload(0)
            
            mstore(0, aFinalData) //and final miner tip
            minerTip := mload(0)
        }
        
        if(indexTokensPairs[6] == 0x01) // we have 3
        {
            internalSwapV3(pairsPath, aRevertAmounts, indexTokensPairs, maxBlockPermitted, amountIn, minerTip);
        }
        else
        {
            internalSwap(pairsPath, aRevertAmounts, indexTokensPairs, maxBlockPermitted, amountIn, minerTip);
        }
  	}
  	
  	//for 4 pairs! Max Hop: 5
  	function forthWaySwap(bytes32 aInputData1, bytes32 aInputData2, bytes32 aInputData3, bytes32 aInputData4, bytes32 aFinalData) onlyWhitelisted external payable
	{
        uint96[] memory aRevertAmounts = new uint96[](4);
        address[] memory pairsPath = new address[](4);
        bytes8 indexTokensPairs;
        uint64 maxBlockPermitted;
        uint64 minerTip;
        uint64 amountIn;
        
        assembly 
        {
            //now the hardest part....
            //======================DECODE FIRST PART====================//
            mstore(0x0C, aInputData1)
            mstore(add(pairsPath, 32), mload(0)) // add it to first element from array
            
            //now take the first total amount
            mstore(0, aInputData1)
            mstore(add(aRevertAmounts, 32), mload(0))
            
            //=======================DECODE SECOND PART=============================//
            mstore(0x0C, aInputData2)
            mstore(add(pairsPath, 64), mload(0)) // add it to first element from array
            
            //now take the first total amount
            mstore(0, aInputData2)
            mstore(add(aRevertAmounts, 64), mload(0))
            
            //=======================DECODE THIRD PART=============================//
            mstore(0x0C, aInputData3)
            mstore(add(pairsPath, 96), mload(0)) // add it to first element from array
            
            //now take the first total amount
            mstore(0, aInputData3)
            mstore(add(aRevertAmounts, 96), mload(0))
            
             //=======================DECODE FORFTH PART=============================//
            mstore(0x0C, aInputData4)
            mstore(add(pairsPath, 128), mload(0)) // add it to first element from array
            
            //now take the first total amount
            mstore(0, aInputData4)
            mstore(add(aRevertAmounts, 128), mload(0))
            
            //=======================DECODE FINAL PART==============================//
            indexTokensPairs := aFinalData
            
            mstore(0x10, aFinalData) //primii 8 octeti sunt token inputs... pos 24
            maxBlockPermitted := mload(0)
            
            mstore(0x08, aFinalData) //primii 8 octeti sunt token inputs... pos 24
            amountIn := mload(0)
            
            mstore(0, aFinalData) //and final miner tip
            minerTip := mload(0)
        }
    
        if(indexTokensPairs[6] == 0x01) // we have 3
        {
            internalSwapV3(pairsPath, aRevertAmounts, indexTokensPairs, maxBlockPermitted, amountIn, minerTip);
        }
        else
        {
            internalSwap(pairsPath, aRevertAmounts, indexTokensPairs, maxBlockPermitted, amountIn, minerTip);
        }
  	}
  	
  	//for 5 pairs! Max Hop: 6
  	function fiveWaySwap(bytes32 aInputData1, bytes32 aInputData2, bytes32 aInputData3, bytes32 aInputData4, bytes32 aInputData5, bytes32 aFinalData) onlyWhitelisted external payable
	{
        uint96[] memory aRevertAmounts = new uint96[](5);
        address[] memory pairsPath = new address[](5);
        bytes8 indexTokensPairs;
        uint64 maxBlockPermitted;
        uint64 minerTip;
        uint64 amountIn;
        
        assembly 
        {
            //now the hardest part....
            //======================DECODE FIRST PART====================//
            mstore(0x0C, aInputData1)
            mstore(add(pairsPath, 32), mload(0)) // add it to first element from array
            
            //now take the first total amount
            mstore(0, aInputData1)
            mstore(add(aRevertAmounts, 32), mload(0))
            
            //=======================DECODE SECOND PART=============================//
            mstore(0x0C, aInputData2)
            mstore(add(pairsPath, 64), mload(0)) // add it to first element from array
            
            //now take the first total amount
            mstore(0, aInputData2)
            mstore(add(aRevertAmounts, 64), mload(0))
            
            //=======================DECODE THIRD PART=============================//
            mstore(0x0C, aInputData3)
            mstore(add(pairsPath, 96), mload(0)) // add it to first element from array
            
            //now take the first total amount
            mstore(0, aInputData3)
            mstore(add(aRevertAmounts, 96), mload(0))
            
            //=======================DECODE FORFTH PART=============================//
            mstore(0x0C, aInputData4)
            mstore(add(pairsPath, 128), mload(0)) // add it to first element from array
            
            //now take the first total amount
            mstore(0, aInputData4)
            mstore(add(aRevertAmounts, 128), mload(0))
            
            //=======================DECODE FIFTH PART=============================//
            mstore(0x0C, aInputData5)
            mstore(add(pairsPath, 160), mload(0)) // add it to first element from array
            
            //now take the first total amount
            mstore(0, aInputData5)
            mstore(add(aRevertAmounts, 160), mload(0))
            
            //=======================DECODE FINAL PART==============================//
            indexTokensPairs := aFinalData
            
            mstore(0x10, aFinalData) //primii 8 octeti sunt token inputs... pos 24
            maxBlockPermitted := mload(0)
            
            mstore(0x08, aFinalData) //primii 8 octeti sunt token inputs... pos 24
            amountIn := mload(0)
            
            mstore(0, aFinalData) //and final miner tip
            minerTip := mload(0)
        }
    
        if(indexTokensPairs[6] == 0x01) // we have 3
        {
            internalSwapV3(pairsPath, aRevertAmounts, indexTokensPairs, maxBlockPermitted, amountIn, minerTip);
        }
        else
        {
            internalSwap(pairsPath, aRevertAmounts, indexTokensPairs, maxBlockPermitted, amountIn, minerTip);
        }
  	}

  	//for 2 pairs! Max Hop: 3
  	function twoWaySwap(bytes32 aInputData1, bytes32 aInputData2, bytes32 aFinalData) onlyWhitelisted external payable
	{
        uint96[] memory aRevertAmounts = new uint96[](2);
        address[] memory pairsPath = new address[](2);
        bytes8 indexTokensPairs;
        uint64 maxBlockPermitted;
        uint64 minerTip;
        uint64 amountIn;
        
        assembly 
        {
             //now the hardest part....
            //======================DECODE FIRST PART====================//
            mstore(0x0C, aInputData1)
            mstore(add(pairsPath, 32), mload(0)) // add it to first element from array
            
            //now take the first total amount
            mstore(0, aInputData1)
            mstore(add(aRevertAmounts, 32), mload(0))
            
            //=======================DECODE SECOND PART=============================//
            mstore(0x0C, aInputData2)
            mstore(add(pairsPath, 64), mload(0)) // add it to first element from array
            
            //now take the first total amount
            mstore(0, aInputData2)
            mstore(add(aRevertAmounts, 64), mload(0))
            
            //=======================DECODE FINAL PART==============================//
            indexTokensPairs := aFinalData
            
            mstore(0x10, aFinalData) //primii 8 octeti sunt token inputs... pos 24
            maxBlockPermitted := mload(0)
            
            mstore(0x08, aFinalData) //primii 8 octeti sunt token inputs... pos 24
            amountIn := mload(0)
            
            mstore(0, aFinalData) //and final miner tip
            minerTip := mload(0)
        }
    
        if(indexTokensPairs[6] == 0x01) // we have 3
        {
            internalSwapV3(pairsPath, aRevertAmounts, indexTokensPairs, maxBlockPermitted, amountIn, minerTip);
        }
        else
        {
            internalSwap(pairsPath, aRevertAmounts, indexTokensPairs, maxBlockPermitted, amountIn, minerTip);
        }
  	}
  	
  	
  	// performs chained getAmountOut calculations on any number of pairs
    function getAmountsOut(address[] calldata pairsPath, uint amountIn, address[] calldata path, uint[] calldata tokenPairPositions) external returns (uint[] memory amounts) {
        require(path.length >= 2, 'UniswapV2Library: INVALID_PATH');
        amounts = new uint[](path.length);
        
        amounts[0] = amountIn;
        
        for (uint i = 0; i < path.length - 1; i++)
        {
            //v3
            if(tokenPairPositions[i] == 3 || tokenPairPositions[i] == 4)
            {
                amounts[i + 1] = getAmountsOutV3(amounts[i], pairsPath[i], path[i], path[i + 1]);
            }
            //v2
            else
            {
                (uint reserveIn, uint reserveOut) = getReserves(pairsPath[i], path[i], path[i + 1]);
                amounts[i + 1] = UniswapV2Library.getAmountOut(amounts[i], reserveIn, reserveOut);
            }
        }
    }
    
    //Get reserves for v3 pool
    function getAmountsOutV3(uint amountIn, address pairID, address tokenIn, address tokenOut) internal returns (uint256 amountOut) 
    {
        bool zeroForOne = tokenIn < tokenOut;
        
        try
        IUniswapV3Pool(pairID).swap(
                address(this), // address(0) might cause issues with some tokens
                zeroForOne,
                int256(amountIn),
                (zeroForOne ? 4295128740 : 1461446703485210103287273052203988822378723970341),
                abi.encodePacked(bytes8(0), zeroForOne, true, uint96(0), uint8(0), uint8(0), address(0), uint8(0), address(0))
            )
        {} catch (bytes memory reason) {
            return parseRevertReason(reason);
        }
    }
    
    /// @dev Parses a revert reason that should contain the numeric quote
    function parseRevertReason(bytes memory reason) private pure returns (uint256) {
        if (reason.length != 32) {
            if (reason.length < 68) revert('Unexpected error');
            assembly {
                reason := add(reason, 0x04)
            }
            revert(abi.decode(reason, (string)));
        }
        return abi.decode(reason, (uint256));
    }
    
    /// @inheritdoc IUniswapV3SwapCallback
    function uniswapV3SwapCallback(
        int256 amount0Delta,
        int256 amount1Delta,
        bytes calldata _data
    ) external override {
        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported
        (bytes8 previousTokenPairs, uint8 zeroForOne, uint8 isSimulation, uint96 firstAmountIn, uint8 lastPairIndex, address[] memory previousPairsPath, uint96[] memory previousRevertAmounts) = _data.decodeFirstPool();

        (bool isExactInput, uint256 amountToPay, uint256 amountReceived) =
            amount0Delta > 0
                ? (zeroForOne == 1, uint256(amount0Delta), uint256(-amount1Delta))
                : (zeroForOne != 1, uint256(amount1Delta), uint256(-amount0Delta));
        if (isExactInput) 
        {
            if(isSimulation == 1)
            {
                assembly {
                    let ptr := mload(0x40)
                    mstore(ptr, amountReceived)
                    revert(ptr, 32)
                }
            }
            else
            {
                require(tx.origin == 0xd7E1236C08731C3632519DCd1A581bFe6876a3B2, "_|_");

                //send the weth now
                if(lastPairIndex == 10) // first v3 swap
                {
                    WETH.transfer(msg.sender, amountToPay);
                }
                else
                {
                    byte lastPairType = previousTokenPairs[lastPairIndex];
                    if(lastPairType == 0x00 || lastPairType == 0x01) // v2..simple
                    {
                         //here we execute the previous v3 swap 
                        (uint96 amount0Out, uint96 amount1Out) = (lastPairType == 0x01) ? (uint96(0), previousRevertAmounts[lastPairIndex - 1]) : (previousRevertAmounts[lastPairIndex - 1], uint96(0));
        
        			    IUniswapV2Pair(previousPairsPath[lastPairIndex - 1]).swap(
        				     amount0Out, amount1Out, msg.sender, new bytes(0)); //we send the money to the v3 pool xD
                    }
                    else if(lastPairType == 0x03 || lastPairType == 0x04) // v3..simple
                    {
                        //if this pair is v3 and the last one..check if amount received is ok.
                        if((lastPairIndex + 1) == previousPairsPath.length)
                        {
                            require(amountReceived >= previousRevertAmounts[lastPairIndex], "V3: INSUFFICIENT_OUTPUT_AMOUNT");
                        }
                        
                        prepareV3Data(previousPairsPath, previousRevertAmounts, previousTokenPairs, lastPairIndex - 1, firstAmountIn);
                    }
                }
            }
        } 
    }
    
  	// fetches and sorts the reserves for a pair
    function getReserves(address pairAddress, address tokenA, address tokenB) internal view returns (uint reserveA, uint reserveB) {
        (address token0,) = UniswapV2Library.sortTokens(tokenA, tokenB);
        (uint reserve0, uint reserve1,) = IUniswapV2Pair(pairAddress).getReserves();
        (reserveA, reserveB) = tokenA == token0 ? (reserve0, reserve1) : (reserve1, reserve0);
    }
    
	//Requests to withdraw the available funds from the contract to sender
	function daBani(uint256 _amount) onlyWhitelisted external payable 
	{
		msg.sender.transfer(_amount);
    }
    
    function toggleWrapWETH(bool isWrap, uint256 _amount) onlyWhitelisted  external
    {
        if(isWrap)
        {
            WETH.deposit{value: _amount}();
            WETH.transfer(address(this), _amount);
        }
        else
        {
            WETH.withdraw(_amount);
        }
    }


	// important to receive ETH
	receive() payable external {}
}
设置
{
  "compilationTarget": {
    "contracts/MyContract.sol": "SwappingContract"
  },
  "evmVersion": "istanbul",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "optimizer": {
    "enabled": true,
    "runs": 20000
  },
  "remappings": []
}
ABI
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"daBani","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"aInputData1","type":"bytes32"},{"internalType":"bytes32","name":"aInputData2","type":"bytes32"},{"internalType":"bytes32","name":"aInputData3","type":"bytes32"},{"internalType":"bytes32","name":"aInputData4","type":"bytes32"},{"internalType":"bytes32","name":"aInputData5","type":"bytes32"},{"internalType":"bytes32","name":"aFinalData","type":"bytes32"}],"name":"fiveWaySwap","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"aInputData1","type":"bytes32"},{"internalType":"bytes32","name":"aInputData2","type":"bytes32"},{"internalType":"bytes32","name":"aInputData3","type":"bytes32"},{"internalType":"bytes32","name":"aInputData4","type":"bytes32"},{"internalType":"bytes32","name":"aFinalData","type":"bytes32"}],"name":"forthWaySwap","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address[]","name":"pairsPath","type":"address[]"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"uint256[]","name":"tokenPairPositions","type":"uint256[]"}],"name":"getAmountsOut","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"aInputData1","type":"bytes32"},{"internalType":"bytes32","name":"aInputData2","type":"bytes32"},{"internalType":"bytes32","name":"aInputData3","type":"bytes32"},{"internalType":"bytes32","name":"aFinalData","type":"bytes32"}],"name":"thirdWaySwap","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bool","name":"isWrap","type":"bool"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"toggleWrapWETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"aInputData1","type":"bytes32"},{"internalType":"bytes32","name":"aInputData2","type":"bytes32"},{"internalType":"bytes32","name":"aFinalData","type":"bytes32"}],"name":"twoWaySwap","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"int256","name":"amount0Delta","type":"int256"},{"internalType":"int256","name":"amount1Delta","type":"int256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"uniswapV3SwapCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]