ETH Price: $2,885.59 (-10.96%)
Gas: 19 Gwei

Contract

0xdf01Af7E93453C081408921742043df8C8F8c039
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Value
Multicall166938982023-02-23 21:55:11497 days ago1677189311IN
Endaoment: Swap Wrapper (Auto Router V2)
0.001 ETH0.0007702632.27039128
0x60c06040165207842023-01-30 16:17:59521 days ago1675095479IN
 Create: AutoRouterWrapper
0 ETH0.0382634522.01183121

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To Value
202360462024-07-04 22:12:236 hrs ago1720131143
Endaoment: Swap Wrapper (Auto Router V2)
0.0092 ETH
202360462024-07-04 22:12:236 hrs ago1720131143
Endaoment: Swap Wrapper (Auto Router V2)
0.0092 ETH
202065672024-06-30 19:23:234 days ago1719775403
Endaoment: Swap Wrapper (Auto Router V2)
0.03 ETH
202065672024-06-30 19:23:234 days ago1719775403
Endaoment: Swap Wrapper (Auto Router V2)
0.03 ETH
201640132024-06-24 20:45:3510 days ago1719261935
Endaoment: Swap Wrapper (Auto Router V2)
0.2898 ETH
201640132024-06-24 20:45:3510 days ago1719261935
Endaoment: Swap Wrapper (Auto Router V2)
0.2898 ETH
201640002024-06-24 20:42:5910 days ago1719261779
Endaoment: Swap Wrapper (Auto Router V2)
1.17076634 ETH
201640002024-06-24 20:42:5910 days ago1719261779
Endaoment: Swap Wrapper (Auto Router V2)
1.17076634 ETH
201639862024-06-24 20:40:1110 days ago1719261611
Endaoment: Swap Wrapper (Auto Router V2)
2.0655 ETH
201639862024-06-24 20:40:1110 days ago1719261611
Endaoment: Swap Wrapper (Auto Router V2)
2.0655 ETH
201639412024-06-24 20:31:1110 days ago1719261071
Endaoment: Swap Wrapper (Auto Router V2)
24.75693698 ETH
201639412024-06-24 20:31:1110 days ago1719261071
Endaoment: Swap Wrapper (Auto Router V2)
24.75693698 ETH
201639172024-06-24 20:26:2310 days ago1719260783
Endaoment: Swap Wrapper (Auto Router V2)
31.24341286 ETH
201639172024-06-24 20:26:2310 days ago1719260783
Endaoment: Swap Wrapper (Auto Router V2)
31.24341286 ETH
201639032024-06-24 20:23:2310 days ago1719260603
Endaoment: Swap Wrapper (Auto Router V2)
36.9239695 ETH
201639032024-06-24 20:23:2310 days ago1719260603
Endaoment: Swap Wrapper (Auto Router V2)
36.9239695 ETH
201261332024-06-19 13:38:2315 days ago1718804303
Endaoment: Swap Wrapper (Auto Router V2)
1.00018499 ETH
201261332024-06-19 13:38:2315 days ago1718804303
Endaoment: Swap Wrapper (Auto Router V2)
1.00018499 ETH
200912202024-06-14 16:24:2320 days ago1718382263
Endaoment: Swap Wrapper (Auto Router V2)
2.3 ETH
200912202024-06-14 16:24:2320 days ago1718382263
Endaoment: Swap Wrapper (Auto Router V2)
2.3 ETH
200360022024-06-06 23:14:5928 days ago1717715699
Endaoment: Swap Wrapper (Auto Router V2)
1 ETH
200360022024-06-06 23:14:5928 days ago1717715699
Endaoment: Swap Wrapper (Auto Router V2)
1 ETH
199792772024-05-30 1:06:3536 days ago1717031195
Endaoment: Swap Wrapper (Auto Router V2)
5 ETH
199792772024-05-30 1:06:3536 days ago1717031195
Endaoment: Swap Wrapper (Auto Router V2)
5 ETH
199785282024-05-29 22:35:3536 days ago1717022135
Endaoment: Swap Wrapper (Auto Router V2)
0.001 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
AutoRouterWrapper

Compiler Version
v0.8.13+commit.abaa5c0e

Optimization Enabled:
Yes with 9999999 runs

Other Settings:
default evmVersion
File 1 of 9 : AutoRouterWrapper.sol
//SPDX-License-Identifier: BSD 3-Clause
pragma solidity 0.8.13;

import {ISwapWrapper} from "../interfaces/ISwapWrapper.sol";
import {ISwapRouter} from "../lib/ISwapRouter02.sol";
import {ERC20} from "solmate/tokens/ERC20.sol";
import {IWETH9} from "../lib/IWETH9.sol";
import {SafeTransferLib} from "solmate/utils/SafeTransferLib.sol";
import "../lib/uniswap/Path.sol";

contract AutoRouterWrapper is ISwapWrapper {
    using SafeTransferLib for ERC20;
    using BytesLib for bytes;

    /// @notice A deployed SwapRouter02(1.1.0). See https://docs.uniswap.org/protocol/reference/deployments.
    ISwapRouter public immutable swapRouter;

    /// @notice WETH contract.
    IWETH9 public immutable weth;

    /// @notice SwapWrapper name.
    string public name;

    /// @dev Address we use to represent ETH.
    address internal constant eth = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;

    error TxFailed();
    error OnlyMulticallsAllowed();
    error PathMismatch();
    error UnhandledFunction(bytes4 selector);
    error ETHAmountInMismatch();
    error TotalAmountMismatch();
    error RecipientMismatch(bytes4 selector);
    error TokenInMismatch(bytes4 selector);
    error TokenOutMismatch(bytes4 selector);

    /**
     * @param _name SwapWrapper name.
     * @param _uniV3SwapRouter Deployed Uniswap v3 SwapRouter.
     */
    constructor(string memory _name, address _uniV3SwapRouter) {
        name = _name;
        swapRouter = ISwapRouter(_uniV3SwapRouter);
        weth = IWETH9(swapRouter.WETH9());
    }

    function swap(address _tokenIn, address _tokenOut, address _recipient, uint256 _amount, bytes calldata _data)
        external
        payable
        returns (uint256)
    {
        // If token is ETH and value was sent, ensure the value matches the swap input amount.
        bool _isInputEth = _tokenIn == eth;
        if ((_isInputEth && msg.value != _amount) || (!_isInputEth && msg.value > 0)) {
            revert ETHAmountInMismatch();
        }
        uint256 _prevBalance = getBalance(_tokenOut, _recipient);

        if (!_isInputEth) {
            // If caller isn't sending ETH, we need to transfer in tokens...
            ERC20(_tokenIn).safeTransferFrom(msg.sender, address(this), _amount);
            ERC20(_tokenIn).safeApprove(address(swapRouter), 0);
            ERC20(_tokenIn).safeApprove(address(swapRouter), _amount);
        }

        uint256 _totalAmountIn = _validateData(_tokenIn, _tokenOut, _recipient, _data);
        // _totalAmountIn has been modified by the various `check...()` methods, and should now sum to _amount
        if (_totalAmountIn != _amount) revert TotalAmountMismatch();

        (bool _success,) = address(swapRouter).call{value: _isInputEth ? _amount : 0}(_data);
        if (!_success) revert TxFailed();

        uint256 _amountOut = getBalance(_tokenOut, _recipient) - _prevBalance;
        emit WrapperSwapExecuted(_tokenIn, _tokenOut, msg.sender, _recipient, _totalAmountIn, _amountOut);
        return _amountOut;
    }

    function _validateData(address _tokenIn, address _tokenOut, address _recipient, bytes calldata _data)
        internal
        view
        returns (uint256 _totalAmountIn)
    {
        bytes4 _selector = bytes4(_data[:4]);
        // Check that it's the multicall function that's being called.
        if (_selector != ISwapRouter.multicall.selector) revert OnlyMulticallsAllowed();

        ( /*uint256 deadline*/ , bytes[] memory _calls) = abi.decode(_data[4:], (uint256, bytes[]));

        uint256 _callsLength = _calls.length;
        for (uint256 i = 0; i < _callsLength; i++) {
            bytes memory _call = _calls[i];
            // Get the selector
            _selector = bytes4(_call.slice(0, 4));
            // Remove the selector
            bytes memory _callWithoutSelector = _call.slice(4, _call.length - 4);

            // check TokenIn if it's the first call of a multicall
            bool _checkTokenIn = i == 0;
            // check TokenOut if it's the last call of a multicall
            bool _checkTokenOut = i == _callsLength - 1;

            // Check that selector is an approved selector and validate its arguments.
            if (_selector == ISwapRouter.exactInputSingle.selector) {
                _totalAmountIn += checkExactInputSingle(
                    _callWithoutSelector, _tokenIn, _tokenOut, _recipient, _checkTokenIn, _checkTokenOut
                );
            } else if (_selector == ISwapRouter.exactInput.selector) {
                _totalAmountIn += checkExactInput(
                    _callWithoutSelector, _tokenIn, _tokenOut, _recipient, _checkTokenIn, _checkTokenOut
                );
            } else if (_selector == ISwapRouter.sweepToken.selector) {
                checkSweepToken(_callWithoutSelector, _tokenOut, _recipient);
            } else if (_selector == ISwapRouter.swapExactTokensForTokens.selector) {
                _totalAmountIn += checkSwapExactTokensForTokens(
                    _callWithoutSelector, _tokenIn, _tokenOut, _recipient, _checkTokenIn, _checkTokenOut
                );
            } else if (_selector == ISwapRouter.unwrapWETH9.selector) {
                checkUnwrapWETH9(_callWithoutSelector, _recipient);
            } else {
                revert UnhandledFunction(_selector);
            }
        }
    }

    function checkExactInputSingle(
        bytes memory _data,
        address _tokenInExpected,
        address _tokenOutExpected,
        address _recipientExpected,
        bool _checkTokenIn,
        bool _checkTokenOut
    ) internal view returns (uint256) {
        (
            address _tokenIn,
            address _tokenOut,
            /*uint24 _fee*/
            ,
            address _recipient,
            uint256 _amountIn,
            /*uint256 _amountOutMinimum*/
            ,
            /*uint160 _sqrtPriceLimitX96*/
        ) = abi.decode(_data, (address, address, uint24, address, uint256, uint256, uint160));

        if (_checkTokenIn) {
            bool _tokensMatch = checkTokens(_tokenIn, _tokenInExpected);
            if (!_tokensMatch) revert TokenInMismatch(ISwapRouter.exactInputSingle.selector);
        }
        if (_checkTokenOut) {
            bool _tokensMatch = checkTokens(_tokenOut, _tokenOutExpected);
            if (!_tokensMatch) revert TokenOutMismatch(ISwapRouter.exactInputSingle.selector);
        }
        checkRecipient(_recipient, _recipientExpected, ISwapRouter.exactInputSingle.selector);

        return _amountIn;
    }

    function checkExactInput(
        bytes memory _data,
        address _tokenInExpected,
        address _tokenOutExpected,
        address _recipientExpected,
        bool _checkTokenIn,
        bool _checkTokenOut
    ) internal view returns (uint256) {
        (
            bytes memory _path,
            address _recipient,
            uint256 _amountIn,
            /*uint256 amountOutMinimum*/
            // First 32 bytes point to the location of dynamic bytes _path
        ) = abi.decode(_data.slice(32, _data.length - 32), (bytes, address, uint256, uint256));

        if (_checkTokenIn) {
            (address _tokenA, /*address _tokenB*/,) = Path.decodeFirstPool(_path);
            bool _tokensMatch = checkTokens(_tokenA, _tokenInExpected);
            if (!_tokensMatch) revert TokenInMismatch(ISwapRouter.exactInput.selector);
        }

        if (_checkTokenOut) {
            ( /*address _tokenA*/ , address _tokenB,) = Path.decodeLastPool(_path);
            bool _tokensMatch = checkTokens(_tokenB, _tokenOutExpected);
            if (!_tokensMatch) revert TokenOutMismatch(ISwapRouter.exactInput.selector);
        }
        checkRecipient(_recipient, _recipientExpected, ISwapRouter.exactInput.selector);

        return _amountIn;
    }

    function checkSweepToken(bytes memory _data, address _tokenOutExpected, address _recipientExpected) internal view {
        (address _token, /*uint256 _amountMinimum*/, address _recipient) =
            abi.decode(_data, (address, uint256, address));
        bool _tokensMatch = checkTokens(_token, _tokenOutExpected);
        if (!_tokensMatch) {
            revert TokenOutMismatch(ISwapRouter.sweepToken.selector);
        }
        checkRecipient(_recipient, _recipientExpected, ISwapRouter.sweepToken.selector);
    }

    function checkSwapExactTokensForTokens(
        bytes memory _data,
        address _tokenInExpected,
        address _tokenOutExpected,
        address _recipientExpected,
        bool _checkTokenIn,
        bool _checkTokenOut
    ) internal view returns (uint256) {
        (
            uint256 _amountIn,
            /*uint256 amountOutMin*/
            ,
            address[] memory _path,
            address _recipient
        ) = abi.decode(_data, (uint256, uint256, address[], address));

        if (_checkTokenIn) {
            bool _tokensMatch = checkTokens(_path[0], _tokenInExpected);
            if (!_tokensMatch) revert TokenInMismatch(ISwapRouter.swapExactTokensForTokens.selector);
        }
        if (_checkTokenOut) {
            bool _tokensMatch = checkTokens(_path[_path.length - 1], _tokenOutExpected);
            if (!_tokensMatch) revert TokenOutMismatch(ISwapRouter.swapExactTokensForTokens.selector);
        }
        checkRecipient(_recipient, _recipientExpected, ISwapRouter.swapExactTokensForTokens.selector);

        return _amountIn;
    }

    function checkUnwrapWETH9(bytes memory _data, address _recipientExpected) internal pure {
        ( /*uint256 amountOutMin*/ , address _recipient) = abi.decode(_data, (uint256, address));
        checkRecipient(_recipient, _recipientExpected, ISwapRouter.unwrapWETH9.selector);
    }

    function checkRecipient(address _recipient, address _recipientExpected, bytes4 _selector) internal pure {
        if (_selector == ISwapRouter.sweepToken.selector || _selector == ISwapRouter.unwrapWETH9.selector) {
            if (_recipient != _recipientExpected) revert RecipientMismatch(_selector);
        } else {
            // address(2) is a flag for identifying address(this).
            // See https://github.com/Uniswap/swap-router-contracts/blob/9dc4a9cce101be984e148e1af6fe605ebcfa658a/contracts/libraries/Constants.sol#L14
            if (_recipient != _recipientExpected && _recipient != address(2)) {
                revert RecipientMismatch(_selector);
            }
        }
    }

    function getBalance(address _tokenOut, address _recipient) internal view returns (uint256) {
        if (_tokenOut == address(eth)) {
            return address(_recipient).balance;
        } else {
            return ERC20(_tokenOut).balanceOf(address(_recipient));
        }
    }

    // Return true if two tokens match, OR if _tokenExpected is eth, token must be weth.
    function checkTokens(address _token, address _tokenExpected) internal view returns (bool) {
        // `TokenIn` should never == eth by the time this check is reached.
        return _token == _tokenExpected || (_tokenExpected == eth ? _token == address(weth) : false);
    }

    /// @notice Required to receive ETH on `weth.withdraw()`
    receive() external payable {}
}

File 2 of 9 : ERC20.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)
/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.
abstract contract ERC20 {
    /*///////////////////////////////////////////////////////////////
                                  EVENTS
    //////////////////////////////////////////////////////////////*/

    event Transfer(address indexed from, address indexed to, uint256 amount);

    event Approval(address indexed owner, address indexed spender, uint256 amount);

    /*///////////////////////////////////////////////////////////////
                             METADATA STORAGE
    //////////////////////////////////////////////////////////////*/

    string public name;

    string public symbol;

    uint8 public immutable decimals;

    /*///////////////////////////////////////////////////////////////
                              ERC20 STORAGE
    //////////////////////////////////////////////////////////////*/

    uint256 public totalSupply;

    mapping(address => uint256) public balanceOf;

    mapping(address => mapping(address => uint256)) public allowance;

    /*///////////////////////////////////////////////////////////////
                             EIP-2612 STORAGE
    //////////////////////////////////////////////////////////////*/

    bytes32 public constant PERMIT_TYPEHASH =
        keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");

    uint256 internal immutable INITIAL_CHAIN_ID;

    bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;

    mapping(address => uint256) public nonces;

    /*///////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(
        string memory _name,
        string memory _symbol,
        uint8 _decimals
    ) {
        name = _name;
        symbol = _symbol;
        decimals = _decimals;

        INITIAL_CHAIN_ID = block.chainid;
        INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
    }

    /*///////////////////////////////////////////////////////////////
                              ERC20 LOGIC
    //////////////////////////////////////////////////////////////*/

    function approve(address spender, uint256 amount) public virtual returns (bool) {
        allowance[msg.sender][spender] = amount;

        emit Approval(msg.sender, spender, amount);

        return true;
    }

    function transfer(address to, uint256 amount) public virtual returns (bool) {
        balanceOf[msg.sender] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(msg.sender, to, amount);

        return true;
    }

    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public virtual returns (bool) {
        uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.

        if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;

        balanceOf[from] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(from, to, amount);

        return true;
    }

    /*///////////////////////////////////////////////////////////////
                              EIP-2612 LOGIC
    //////////////////////////////////////////////////////////////*/

    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual {
        require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");

        // Unchecked because the only math done is incrementing
        // the owner's nonce which cannot realistically overflow.
        unchecked {
            bytes32 digest = keccak256(
                abi.encodePacked(
                    "\x19\x01",
                    DOMAIN_SEPARATOR(),
                    keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))
                )
            );

            address recoveredAddress = ecrecover(digest, v, r, s);

            require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");

            allowance[recoveredAddress][spender] = value;
        }

        emit Approval(owner, spender, value);
    }

    function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
        return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
    }

    function computeDomainSeparator() internal view virtual returns (bytes32) {
        return
            keccak256(
                abi.encode(
                    keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
                    keccak256(bytes(name)),
                    keccak256("1"),
                    block.chainid,
                    address(this)
                )
            );
    }

    /*///////////////////////////////////////////////////////////////
                       INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(address to, uint256 amount) internal virtual {
        totalSupply += amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(address(0), to, amount);
    }

    function _burn(address from, uint256 amount) internal virtual {
        balanceOf[from] -= amount;

        // Cannot underflow because a user's balance
        // will never be larger than the total supply.
        unchecked {
            totalSupply -= amount;
        }

        emit Transfer(from, address(0), amount);
    }
}

File 3 of 9 : SafeTransferLib.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

import {ERC20} from "../tokens/ERC20.sol";

/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/SafeTransferLib.sol)
/// @author Modified from Gnosis (https://github.com/gnosis/gp-v2-contracts/blob/main/src/contracts/libraries/GPv2SafeERC20.sol)
/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.
library SafeTransferLib {
    /*///////////////////////////////////////////////////////////////
                            ETH OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function safeTransferETH(address to, uint256 amount) internal {
        bool callStatus;

        assembly {
            // Transfer the ETH and store if it succeeded or not.
            callStatus := call(gas(), to, amount, 0, 0, 0, 0)
        }

        require(callStatus, "ETH_TRANSFER_FAILED");
    }

    /*///////////////////////////////////////////////////////////////
                           ERC20 OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function safeTransferFrom(
        ERC20 token,
        address from,
        address to,
        uint256 amount
    ) internal {
        bool callStatus;

        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata to memory piece by piece:
            mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000) // Begin with the function selector.
            mstore(add(freeMemoryPointer, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff)) // Mask and append the "from" argument.
            mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Mask and append the "to" argument.
            mstore(add(freeMemoryPointer, 68), amount) // Finally append the "amount" argument. No mask as it's a full 32 byte value.

            // Call the token and store if it succeeded or not.
            // We use 100 because the calldata length is 4 + 32 * 3.
            callStatus := call(gas(), token, 0, freeMemoryPointer, 100, 0, 0)
        }

        require(didLastOptionalReturnCallSucceed(callStatus), "TRANSFER_FROM_FAILED");
    }

    function safeTransfer(
        ERC20 token,
        address to,
        uint256 amount
    ) internal {
        bool callStatus;

        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata to memory piece by piece:
            mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) // Begin with the function selector.
            mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Mask and append the "to" argument.
            mstore(add(freeMemoryPointer, 36), amount) // Finally append the "amount" argument. No mask as it's a full 32 byte value.

            // Call the token and store if it succeeded or not.
            // We use 68 because the calldata length is 4 + 32 * 2.
            callStatus := call(gas(), token, 0, freeMemoryPointer, 68, 0, 0)
        }

        require(didLastOptionalReturnCallSucceed(callStatus), "TRANSFER_FAILED");
    }

    function safeApprove(
        ERC20 token,
        address to,
        uint256 amount
    ) internal {
        bool callStatus;

        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata to memory piece by piece:
            mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000) // Begin with the function selector.
            mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Mask and append the "to" argument.
            mstore(add(freeMemoryPointer, 36), amount) // Finally append the "amount" argument. No mask as it's a full 32 byte value.

            // Call the token and store if it succeeded or not.
            // We use 68 because the calldata length is 4 + 32 * 2.
            callStatus := call(gas(), token, 0, freeMemoryPointer, 68, 0, 0)
        }

        require(didLastOptionalReturnCallSucceed(callStatus), "APPROVE_FAILED");
    }

    /*///////////////////////////////////////////////////////////////
                         INTERNAL HELPER LOGIC
    //////////////////////////////////////////////////////////////*/

    function didLastOptionalReturnCallSucceed(bool callStatus) private pure returns (bool success) {
        assembly {
            // Get how many bytes the call returned.
            let returnDataSize := returndatasize()

            // If the call reverted:
            if iszero(callStatus) {
                // Copy the revert message into memory.
                returndatacopy(0, 0, returnDataSize)

                // Revert with the same message.
                revert(0, returnDataSize)
            }

            switch returnDataSize
            case 32 {
                // Copy the return data into memory.
                returndatacopy(0, 0, returnDataSize)

                // Set success to whether it returned true.
                success := iszero(iszero(mload(0)))
            }
            case 0 {
                // There was no return data.
                success := 1
            }
            default {
                // It returned some malformed input.
                success := 0
            }
        }
    }
}

File 4 of 9 : ISwapWrapper.sol
//SPDX-License-Identifier: BSD 3-Clause
pragma solidity >=0.8.0;

error ETHAmountInMismatch();

/**
 * @notice ISwapWrapper is the interface that all swap wrappers should implement.
 * This will be used to support swap protocols like Uniswap V2 and V3, Sushiswap, 1inch, etc.
 */
interface ISwapWrapper {
    /// @notice Event emitted after a successful swap.
    event WrapperSwapExecuted(
        address indexed tokenIn,
        address indexed tokenOut,
        address sender,
        address indexed recipient,
        uint256 amountIn,
        uint256 amountOut
    );

    /// @notice Name of swap wrapper for UX readability.
    function name() external returns (string memory);

    /**
     * @notice Swap function. Generally we expect the implementer to call some exactAmountIn-like swap method, and so the documentation
     * is written with this in mind. However, the method signature is general enough to support exactAmountOut swaps as well.
     * @param _tokenIn Token to be swapped (or 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE for ETH).
     * @param _tokenOut Token to receive (or 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE for ETH).
     * @param _recipient Receiver of `_tokenOut`.
     * @param _amount Amount of `_tokenIn` that should be swapped.
     * @param _data Additional data that the swap wrapper may require to execute the swap.
     * @return Amount of _tokenOut received.
     */
    function swap(address _tokenIn, address _tokenOut, address _recipient, uint256 _amount, bytes calldata _data)
        external
        payable
        returns (uint256);
}

File 5 of 9 : ISwapRouter02.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.13;

import "./IUniswapV3SwapCallback.sol";

/// @title Router token swapping functionality
/// @notice Functions for swapping tokens via Uniswap V3
interface ISwapRouter is IUniswapV3SwapCallback {
    struct ExactInputSingleParams {
        address tokenIn;
        address tokenOut;
        uint24 fee;
        address recipient;
        uint256 amountIn;
        uint256 amountOutMinimum;
        uint160 sqrtPriceLimitX96;
    }

    struct ExactInputParams {
        bytes path;
        address recipient;
        uint256 amountIn;
        uint256 amountOutMinimum;
    }

    function exactInput(ExactInputParams memory params) external payable returns (uint256 amountOut);

    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);

    function multicall(uint256 deadline, bytes[] calldata data) external payable returns (bytes[] memory);

    function sweepToken(address token, uint256 amountMinimum, address recipient) external payable;

    function unwrapWETH9WithFee(uint256 amountMinimum, address recipient, uint256 feeBips, address feeRecipient)
        external
        payable;

    function wrapETH(uint256 value) external payable;

    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;

    function WETH9() external view returns (address payable);

    //V2 Periphery
    function swapExactTokensForTokens(uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to)
        external
        payable
        returns (uint256 amountOut);
}

File 6 of 9 : IUniswapV3SwapCallback.sol
// Sourced from https://github.com/Uniswap/v3-core/blob/ed88be38ab2032d82bf10ac6f8d03aa631889d48/contracts/interfaces/callback/IUniswapV3SwapCallback.sol
// Modified solidity pragma.

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.8.13;

/// @title Callback for IUniswapV3PoolActions#swap
/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface
interface IUniswapV3SwapCallback {
    /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.
    /// @dev In the implementation you must pay the pool tokens owed for the swap.
    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.
    /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.
    /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by
    /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.
    /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by
    /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.
    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call
    function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata data) external;
}

File 7 of 9 : IWETH9.sol
// SPDX-License-Identifier: BSD-2-Clause
// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol v0.5.2. SEE SOURCE BELOW. !!
pragma solidity 0.8.13;

interface IWETH9 {
    function name() external view returns (string memory);

    function approve(address guy, uint256 wad) external returns (bool);

    function totalSupply() external view returns (uint256);

    function transferFrom(address src, address dst, uint256 wad) external returns (bool);

    function withdraw(uint256 wad) external;

    function decimals() external view returns (uint8);

    function balanceOf(address) external view returns (uint256);

    function symbol() external view returns (string memory);

    function transfer(address dst, uint256 wad) external returns (bool);

    function deposit() external payable;

    function allowance(address, address) external view returns (uint256);

    event Approval(address indexed src, address indexed guy, uint256 wad);
    event Transfer(address indexed src, address indexed dst, uint256 wad);
    event Deposit(address indexed dst, uint256 wad);
    event Withdrawal(address indexed src, uint256 wad);
}

// THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON:
/*
[{"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"name":"guy","type":"address"},{"name":"wad","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"name":"src","type":"address"},{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"wad","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"guy","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Withdrawal","type":"event"}]*/

File 8 of 9 : BytesLib.sol
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * @title Solidity Bytes Arrays Utils
 * @author Gonçalo Sá <[email protected]>
 *
 * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.
 *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.
 * @notice Link: https://github.com/Uniswap/v3-periphery/blob/b325bb0905d922ae61fcc7df85ee802e8df5e96c/contracts/libraries/BytesLib.sol
 */
pragma solidity >=0.8.0 <0.9.0;

library BytesLib {
    function slice(bytes memory _bytes, uint256 _start, uint256 _length) internal pure returns (bytes memory) {
        require(_length + 31 >= _length, "slice_overflow");
        require(_bytes.length >= _start + _length, "slice_outOfBounds");

        bytes memory tempBytes;

        assembly {
            switch iszero(_length)
            case 0 {
                // Get a location of some free memory and store it in tempBytes as
                // Solidity does for memory variables.
                tempBytes := mload(0x40)

                // The first word of the slice result is potentially a partial
                // word read from the original array. To read it, we calculate
                // the length of that partial word and start copying that many
                // bytes into the array. The first word we copy will start with
                // data we don't care about, but the last `lengthmod` bytes will
                // land at the beginning of the contents of the new array. When
                // we're done copying, we overwrite the full first word with
                // the actual length of the slice.
                let lengthmod := and(_length, 31)

                // The multiplication in the next line is necessary
                // because when slicing multiples of 32 bytes (lengthmod == 0)
                // the following copy loop was copying the origin's length
                // and then ending prematurely not copying everything it should.
                let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))
                let end := add(mc, _length)

                for {
                    // The multiplication in the next line has the same exact purpose
                    // as the one above.
                    let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)
                } lt(mc, end) {
                    mc := add(mc, 0x20)
                    cc := add(cc, 0x20)
                } { mstore(mc, mload(cc)) }

                mstore(tempBytes, _length)

                //update free-memory pointer
                //allocating the array padded to 32 bytes like the compiler does now
                mstore(0x40, and(add(mc, 31), not(31)))
            }
            //if we want a zero-length slice let's just return a zero-length array
            default {
                tempBytes := mload(0x40)
                //zero out the 32 bytes slice we are about to return
                //we need to do it because Solidity does not garbage collect
                mstore(tempBytes, 0)

                mstore(0x40, add(tempBytes, 0x20))
            }
        }

        return tempBytes;
    }

    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {
        require(_bytes.length >= _start + 20, "toAddress_outOfBounds");
        address tempAddress;

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

        return tempAddress;
    }

    function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) {
        require(_start + 3 >= _start, "toUint24_overflow");
        require(_bytes.length >= _start + 3, "toUint24_outOfBounds");
        uint24 tempUint;

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

        return tempUint;
    }
}

File 9 of 9 : Path.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.6.0;

import "./BytesLib.sol";

/// @title MODIFIED FILE: Functions for manipulating path data for multihop swaps
/// @notice Additional `decodeLastPool` method was added to the orignal file linked below.
/// @notice Link: https://github.com/Uniswap/v3-periphery/blob/b325bb0905d922ae61fcc7df85ee802e8df5e96c/contracts/libraries/Path.sol
library Path {
    using BytesLib for bytes;

    /// @dev The length of the bytes encoded address
    uint256 private constant ADDR_SIZE = 20;
    /// @dev The length of the bytes encoded fee
    uint256 private constant FEE_SIZE = 3;

    /// @dev The offset of a single token address and pool fee
    uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;
    /// @dev The offset of an encoded pool key
    uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;
    /// @dev The minimum length of an encoding that contains 2 or more pools
    uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;

    /// @notice Returns true iff the path contains two or more pools
    /// @param path The encoded swap path
    /// @return True if path contains two or more pools, otherwise false
    function hasMultiplePools(bytes memory path) internal pure returns (bool) {
        return path.length >= MULTIPLE_POOLS_MIN_LENGTH;
    }

    /// @notice Returns the number of pools in the path
    /// @param path The encoded swap path
    /// @return The number of pools in the path
    function numPools(bytes memory path) internal pure returns (uint256) {
        // Ignore the first token address. From then on every fee and token offset indicates a pool.
        return ((path.length - ADDR_SIZE) / NEXT_OFFSET);
    }

    /// @notice Decodes the first pool in path
    /// @param path The bytes encoded swap path
    /// @return tokenA The first token of the given pool
    /// @return tokenB The second token of the given pool
    /// @return fee The fee level of the pool
    function decodeFirstPool(bytes memory path) internal pure returns (address tokenA, address tokenB, uint24 fee) {
        tokenA = path.toAddress(0);
        fee = path.toUint24(ADDR_SIZE);
        tokenB = path.toAddress(NEXT_OFFSET);
    }

    /// @notice Gets the segment corresponding to the first pool in the path
    /// @param path The bytes encoded swap path
    /// @return The segment containing all data necessary to target the first pool in the path
    function getFirstPool(bytes memory path) internal pure returns (bytes memory) {
        return path.slice(0, POP_OFFSET);
    }

    /// @notice Skips a token + fee element from the buffer and returns the remainder
    /// @param path The swap path
    /// @return The remaining token + fee elements in the path
    function skipToken(bytes memory path) internal pure returns (bytes memory) {
        return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);
    }

    /// @notice Custom method we've added: Decodes the last pool in path
    /// @param path The bytes encoded swap path
    /// @return tokenA The first token of the given pool
    /// @return tokenB The second token of the given pool
    /// @return fee The fee level of the pool
    function decodeLastPool(bytes memory path) internal pure returns (address tokenA, address tokenB, uint24 fee) {
        path = path.slice(path.length - POP_OFFSET, POP_OFFSET);
        tokenA = path.toAddress(0);
        fee = path.toUint24(ADDR_SIZE);
        tokenB = path.toAddress(NEXT_OFFSET);
    }
}

Settings
{
  "remappings": [
    "ds-test/=lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "murky/=lib/murky/src/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "solmate/=lib/solmate/src/",
    "weird-erc20/=lib/solmate/lib/weird-erc20/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 9999999
  },
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"address","name":"_uniV3SwapRouter","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ETHAmountInMismatch","type":"error"},{"inputs":[],"name":"OnlyMulticallsAllowed","type":"error"},{"inputs":[],"name":"PathMismatch","type":"error"},{"inputs":[{"internalType":"bytes4","name":"selector","type":"bytes4"}],"name":"RecipientMismatch","type":"error"},{"inputs":[{"internalType":"bytes4","name":"selector","type":"bytes4"}],"name":"TokenInMismatch","type":"error"},{"inputs":[{"internalType":"bytes4","name":"selector","type":"bytes4"}],"name":"TokenOutMismatch","type":"error"},{"inputs":[],"name":"TotalAmountMismatch","type":"error"},{"inputs":[],"name":"TxFailed","type":"error"},{"inputs":[{"internalType":"bytes4","name":"selector","type":"bytes4"}],"name":"UnhandledFunction","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"tokenIn","type":"address"},{"indexed":true,"internalType":"address","name":"tokenOut","type":"address"},{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"WrapperSwapExecuted","type":"event"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenIn","type":"address"},{"internalType":"address","name":"_tokenOut","type":"address"},{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"swap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"swapRouter","outputs":[{"internalType":"contract ISwapRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"contract IWETH9","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

60c06040523480156200001157600080fd5b506040516200217c3803806200217c8339810160408190526200003491620001b7565b815162000049906000906020850190620000d0565b506001600160a01b0381166080819052604080516312a9293f60e21b81529051634aa4a4fc916004808201926020929091908290030181865afa15801562000095573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000bb9190620002a8565b6001600160a01b031660a052506200030b9050565b828054620000de90620002cf565b90600052602060002090601f0160209004810192826200010257600085556200014d565b82601f106200011d57805160ff19168380011785556200014d565b828001600101855582156200014d579182015b828111156200014d57825182559160200191906001019062000130565b506200015b9291506200015f565b5090565b5b808211156200015b576000815560010162000160565b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114620001a257600080fd5b50565b8051620001b2816200018c565b919050565b60008060408385031215620001cb57600080fd5b82516001600160401b0380821115620001e357600080fd5b818501915085601f830112620001f857600080fd5b8151818111156200020d576200020d62000176565b604051601f8201601f19908116603f0116810190838211818310171562000238576200023862000176565b816040528281526020935088848487010111156200025557600080fd5b600091505b828210156200027957848201840151818301850152908301906200025a565b828211156200028b5760008484830101525b95506200029d915050858201620001a5565b925050509250929050565b600060208284031215620002bb57600080fd5b8151620002c8816200018c565b9392505050565b600181811c90821680620002e457607f821691505b6020821081036200030557634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a051611e316200034b60003960008181608c015261121801526000818160e50152818161028e015281816102d001526103430152611e316000f3fe6080604052600436106100435760003560e01c806306fdde031461004f5780633fc8cef31461007a578063c31c9c07146100d3578063da1452631461010757600080fd5b3661004a57005b600080fd5b34801561005b57600080fd5b50610064610128565b6040516100719190611677565b60405180910390f35b34801561008657600080fd5b506100ae7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610071565b3480156100df57600080fd5b506100ae7f000000000000000000000000000000000000000000000000000000000000000081565b61011a6101153660046116ed565b6101b6565b604051908152602001610071565b60008054610135906117a0565b80601f0160208091040260200160405190810160405280929190818152602001828054610161906117a0565b80156101ae5780601f10610183576101008083540402835291602001916101ae565b820191906000526020600020905b81548152906001019060200180831161019157829003601f168201915b505050505081565b600073ffffffffffffffffffffffffffffffffffffffff871673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148080156101f25750843414155b806102065750801580156102065750600034115b1561023d576040517f61746dbd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610249888861049d565b9050816102f55761027273ffffffffffffffffffffffffffffffffffffffff8a16333089610593565b6102b473ffffffffffffffffffffffffffffffffffffffff8a167f00000000000000000000000000000000000000000000000000000000000000006000610682565b6102f573ffffffffffffffffffffffffffffffffffffffff8a167f000000000000000000000000000000000000000000000000000000000000000088610682565b60006103048a8a8a898961074f565b905086811461033f576040517f1ae3648700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1684610384576000610386565b885b88886040516103969291906117f3565b60006040518083038185875af1925050503d80600081146103d3576040519150601f19603f3d011682016040523d82523d6000602084013e6103d8565b606091505b5050905080610413576040517f2b96f51300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000836104208c8c61049d565b61042a9190611832565b604080513381526020810186905290810182905290915073ffffffffffffffffffffffffffffffffffffffff808c16918d8216918f16907fb1b8682cc43fc0063470cc507f616e8f273f9df242d968fe84580a72f2b779619060600160405180910390a49b9a5050505050505050505050565b60007fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8416016104fa575073ffffffffffffffffffffffffffffffffffffffff81163161058d565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa158015610566573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058a9190611849565b90505b92915050565b60006040517f23b872dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015273ffffffffffffffffffffffffffffffffffffffff8416602482015282604482015260008060648360008a5af191505061061081610ac0565b61067b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c454400000000000000000000000060448201526064015b60405180910390fd5b5050505050565b60006040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201528260248201526000806044836000895af19150506106e381610ac0565b610749576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f415050524f56455f4641494c45440000000000000000000000000000000000006044820152606401610672565b50505050565b60008061075f6004828587611862565b6107689161188c565b90507fffffffff0000000000000000000000000000000000000000000000000000000081167f5ae401dc00000000000000000000000000000000000000000000000000000000146107e5576040517f364a674500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006107f48460048188611862565b81019061080191906119bc565b8051909250905060005b81811015610ab357600083828151811061082757610827611abc565b602002602001015190506108486000600483610b079092919063ffffffff16565b61085190611aeb565b9450600061086f60048084516108679190611832565b849190610b07565b905082156000610880600187611832565b851490507ffb1ba551000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008916016108ec576108db838f8f8f8686610c81565b6108e5908a611b3b565b9850610a9c565b7f47a7e7c1000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000891601610943576108db838f8f8f8686610dbf565b7f20d54a45000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000089160161099c57610997838e8e610f2f565b610a9c565b7fb8d4bc0d000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008916016109f3576108db838f8f8f8686610fe5565b7fb6bfb484000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000891601610a4657610997838d61115d565b6040517f9a0778260000000000000000000000000000000000000000000000000000000081527fffffffff0000000000000000000000000000000000000000000000000000000089166004820152602401610672565b505050508080610aab90611b53565b91505061080b565b5050505095945050505050565b60003d82610ad257806000803e806000fd5b8060208114610aea578015610afb5760009250610b00565b816000803e60005115159250610b00565b600192505b5050919050565b606081610b1581601f611b3b565b1015610b7d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610672565b610b878284611b3b565b84511015610bf1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610672565b606082158015610c105760405191506000825260208201604052610c78565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015610c49578051835260209283019201610c31565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60008060008060008a806020019051810190610c9d9190611b9b565b50509450945050935093508615610d17576000610cba858c6111a7565b905080610d15576040517f5c4440c90000000000000000000000000000000000000000000000000000000081527f04e45aaf000000000000000000000000000000000000000000000000000000006004820152602401610672565b505b8515610d86576000610d29848b6111a7565b905080610d84576040517f27f5b90d0000000000000000000000000000000000000000000000000000000081527f04e45aaf000000000000000000000000000000000000000000000000000000006004820152602401610672565b505b610db182897f04e45aaf0000000000000000000000000000000000000000000000000000000061126c565b9a9950505050505050505050565b600080600080610ddf6020808c51610dd79190611832565b8c9190610b07565b806020019051810190610df29190611c2c565b509250925092508515610e78576000610e0a84611439565b505090506000610e1a828c6111a7565b905080610e75576040517f5c4440c90000000000000000000000000000000000000000000000000000000081527fb858183f000000000000000000000000000000000000000000000000000000006004820152602401610672565b50505b8415610ef7576000610e8984611475565b509150506000610e99828b6111a7565b905080610ef4576040517f27f5b90d0000000000000000000000000000000000000000000000000000000081527fb858183f000000000000000000000000000000000000000000000000000000006004820152602401610672565b50505b610f2282887fb858183f0000000000000000000000000000000000000000000000000000000061126c565b9998505050505050505050565b60008084806020019051810190610f469190611cc8565b92505091506000610f5783866111a7565b905080610fb2576040517f27f5b90d0000000000000000000000000000000000000000000000000000000081527fdf2ab5bb000000000000000000000000000000000000000000000000000000006004820152602401610672565b610fdd82857fdf2ab5bb0000000000000000000000000000000000000000000000000000000061126c565b505050505050565b60008060008089806020019051810190610fff9190611d0b565b93509350509250851561108f5760006110328360008151811061102457611024611abc565b60200260200101518b6111a7565b90508061108d576040517f5c4440c90000000000000000000000000000000000000000000000000000000081527f472b43f3000000000000000000000000000000000000000000000000000000006004820152602401610672565b505b84156111245760006110c783600185516110a99190611832565b815181106110b9576110b9611abc565b60200260200101518a6111a7565b905080611122576040517f27f5b90d0000000000000000000000000000000000000000000000000000000081527f472b43f3000000000000000000000000000000000000000000000000000000006004820152602401610672565b505b61114f81887f472b43f30000000000000000000000000000000000000000000000000000000061126c565b509098975050505050505050565b6000828060200190518101906111739190611dcb565b91506111a2905081837f49404b7c0000000000000000000000000000000000000000000000000000000061126c565b505050565b60008173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16148061058a575073ffffffffffffffffffffffffffffffffffffffff821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1461121657600061058a565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16149392505050565b7fffffffff0000000000000000000000000000000000000000000000000000000081167fdf2ab5bb0000000000000000000000000000000000000000000000000000000014806112fd57507fffffffff0000000000000000000000000000000000000000000000000000000081167f49404b7c00000000000000000000000000000000000000000000000000000000145b1561138b578173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16146111a2576040517f02a3e6980000000000000000000000000000000000000000000000000000000081527fffffffff0000000000000000000000000000000000000000000000000000000082166004820152602401610672565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141580156113de575073ffffffffffffffffffffffffffffffffffffffff8316600214155b156111a2576040517f02a3e6980000000000000000000000000000000000000000000000000000000081527fffffffff0000000000000000000000000000000000000000000000000000000082166004820152602401610672565b6000808061144784826114c7565b9250611454846014611557565b905061146c61146560036014611b3b565b85906114c7565b91509193909250565b600080806114be6014611489600382611b3b565b6114939190611b3b565b855161149f9190611832565b60146114ac600382611b3b565b6114b69190611b3b565b869190610b07565b93506114478460005b60006114d4826014611b3b565b8351101561153e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e647300000000000000000000006044820152606401610672565b5001602001516c01000000000000000000000000900490565b600081611565816003611b3b565b10156115cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f746f55696e7432345f6f766572666c6f770000000000000000000000000000006044820152606401610672565b6115d8826003611b3b565b83511015611642576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f746f55696e7432345f6f75744f66426f756e64730000000000000000000000006044820152606401610672565b50016003015190565b60005b8381101561166657818101518382015260200161164e565b838111156107495750506000910152565b602081526000825180602084015261169681604085016020870161164b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b73ffffffffffffffffffffffffffffffffffffffff811681146116ea57600080fd5b50565b60008060008060008060a0878903121561170657600080fd5b8635611711816116c8565b95506020870135611721816116c8565b94506040870135611731816116c8565b935060608701359250608087013567ffffffffffffffff8082111561175557600080fd5b818901915089601f83011261176957600080fd5b81358181111561177857600080fd5b8a602082850101111561178a57600080fd5b6020830194508093505050509295509295509295565b600181811c908216806117b457607f821691505b6020821081036117ed577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561184457611844611803565b500390565b60006020828403121561185b57600080fd5b5051919050565b6000808585111561187257600080fd5b8386111561187f57600080fd5b5050820193919092039150565b7fffffffff0000000000000000000000000000000000000000000000000000000081358181169160048510156118cc5780818660040360031b1b83161692505b505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561194a5761194a6118d4565b604052919050565b600067ffffffffffffffff82111561196c5761196c6118d4565b5060051b60200190565b600067ffffffffffffffff821115611990576119906118d4565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60008060408084860312156119d057600080fd5b8335925060208085013567ffffffffffffffff808211156119f057600080fd5b818701915087601f830112611a0457600080fd5b8135611a17611a1282611952565b611903565b81815260059190911b8301840190848101908a831115611a3657600080fd5b8585015b83811015611aaa57803585811115611a525760008081fd5b8601603f81018d13611a645760008081fd5b87810135611a74611a1282611976565b8181528e8b838501011115611a895760008081fd5b818b84018b83013760009181018a0191909152845250918601918601611a3a565b50809750505050505050509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000815160208301517fffffffff0000000000000000000000000000000000000000000000000000000080821693506004831015611b335780818460040360031b1b83161693505b505050919050565b60008219821115611b4e57611b4e611803565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611b8457611b84611803565b5060010190565b8051611b96816116c8565b919050565b600080600080600080600060e0888a031215611bb657600080fd5b8751611bc1816116c8565b6020890151909750611bd2816116c8565b604089015190965062ffffff81168114611beb57600080fd5b6060890151909550611bfc816116c8565b809450506080880151925060a0880151915060c0880151611c1c816116c8565b8091505092959891949750929550565b60008060008060808587031215611c4257600080fd5b845167ffffffffffffffff811115611c5957600080fd5b8501601f81018713611c6a57600080fd5b8051611c78611a1282611976565b818152886020838501011115611c8d57600080fd5b611c9e82602083016020860161164b565b8096505050506020850151611cb2816116c8565b6040860151606090960151949790965092505050565b600080600060608486031215611cdd57600080fd5b8351611ce8816116c8565b602085015160408601519194509250611d00816116c8565b809150509250925092565b60008060008060808587031215611d2157600080fd5b845193506020808601519350604086015167ffffffffffffffff811115611d4757600080fd5b8601601f81018813611d5857600080fd5b8051611d66611a1282611952565b81815260059190911b8201830190838101908a831115611d8557600080fd5b928401925b82841015611dac578351611d9d816116c8565b82529284019290840190611d8a565b8096505050505050611dc060608601611b8b565b905092959194509250565b60008060408385031215611dde57600080fd5b825191506020830151611df0816116c8565b80915050925092905056fea26469706673582212206f1b85be2ca7af517505ed12d9d5b77d7fbee1026625e1a000767ff619b1c1f664736f6c634300080d0033000000000000000000000000000000000000000000000000000000000000004000000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc45000000000000000000000000000000000000000000000000000000000000001a556e6973776170204175746f526f757465722057726170706572000000000000

Deployed Bytecode

0x6080604052600436106100435760003560e01c806306fdde031461004f5780633fc8cef31461007a578063c31c9c07146100d3578063da1452631461010757600080fd5b3661004a57005b600080fd5b34801561005b57600080fd5b50610064610128565b6040516100719190611677565b60405180910390f35b34801561008657600080fd5b506100ae7f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610071565b3480156100df57600080fd5b506100ae7f00000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc4581565b61011a6101153660046116ed565b6101b6565b604051908152602001610071565b60008054610135906117a0565b80601f0160208091040260200160405190810160405280929190818152602001828054610161906117a0565b80156101ae5780601f10610183576101008083540402835291602001916101ae565b820191906000526020600020905b81548152906001019060200180831161019157829003601f168201915b505050505081565b600073ffffffffffffffffffffffffffffffffffffffff871673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148080156101f25750843414155b806102065750801580156102065750600034115b1561023d576040517f61746dbd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610249888861049d565b9050816102f55761027273ffffffffffffffffffffffffffffffffffffffff8a16333089610593565b6102b473ffffffffffffffffffffffffffffffffffffffff8a167f00000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc456000610682565b6102f573ffffffffffffffffffffffffffffffffffffffff8a167f00000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc4588610682565b60006103048a8a8a898961074f565b905086811461033f576040517f1ae3648700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f00000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc4573ffffffffffffffffffffffffffffffffffffffff1684610384576000610386565b885b88886040516103969291906117f3565b60006040518083038185875af1925050503d80600081146103d3576040519150601f19603f3d011682016040523d82523d6000602084013e6103d8565b606091505b5050905080610413576040517f2b96f51300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000836104208c8c61049d565b61042a9190611832565b604080513381526020810186905290810182905290915073ffffffffffffffffffffffffffffffffffffffff808c16918d8216918f16907fb1b8682cc43fc0063470cc507f616e8f273f9df242d968fe84580a72f2b779619060600160405180910390a49b9a5050505050505050505050565b60007fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8416016104fa575073ffffffffffffffffffffffffffffffffffffffff81163161058d565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa158015610566573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058a9190611849565b90505b92915050565b60006040517f23b872dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015273ffffffffffffffffffffffffffffffffffffffff8416602482015282604482015260008060648360008a5af191505061061081610ac0565b61067b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c454400000000000000000000000060448201526064015b60405180910390fd5b5050505050565b60006040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201528260248201526000806044836000895af19150506106e381610ac0565b610749576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f415050524f56455f4641494c45440000000000000000000000000000000000006044820152606401610672565b50505050565b60008061075f6004828587611862565b6107689161188c565b90507fffffffff0000000000000000000000000000000000000000000000000000000081167f5ae401dc00000000000000000000000000000000000000000000000000000000146107e5576040517f364a674500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006107f48460048188611862565b81019061080191906119bc565b8051909250905060005b81811015610ab357600083828151811061082757610827611abc565b602002602001015190506108486000600483610b079092919063ffffffff16565b61085190611aeb565b9450600061086f60048084516108679190611832565b849190610b07565b905082156000610880600187611832565b851490507ffb1ba551000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008916016108ec576108db838f8f8f8686610c81565b6108e5908a611b3b565b9850610a9c565b7f47a7e7c1000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000891601610943576108db838f8f8f8686610dbf565b7f20d54a45000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000089160161099c57610997838e8e610f2f565b610a9c565b7fb8d4bc0d000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008916016109f3576108db838f8f8f8686610fe5565b7fb6bfb484000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000891601610a4657610997838d61115d565b6040517f9a0778260000000000000000000000000000000000000000000000000000000081527fffffffff0000000000000000000000000000000000000000000000000000000089166004820152602401610672565b505050508080610aab90611b53565b91505061080b565b5050505095945050505050565b60003d82610ad257806000803e806000fd5b8060208114610aea578015610afb5760009250610b00565b816000803e60005115159250610b00565b600192505b5050919050565b606081610b1581601f611b3b565b1015610b7d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610672565b610b878284611b3b565b84511015610bf1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610672565b606082158015610c105760405191506000825260208201604052610c78565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015610c49578051835260209283019201610c31565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60008060008060008a806020019051810190610c9d9190611b9b565b50509450945050935093508615610d17576000610cba858c6111a7565b905080610d15576040517f5c4440c90000000000000000000000000000000000000000000000000000000081527f04e45aaf000000000000000000000000000000000000000000000000000000006004820152602401610672565b505b8515610d86576000610d29848b6111a7565b905080610d84576040517f27f5b90d0000000000000000000000000000000000000000000000000000000081527f04e45aaf000000000000000000000000000000000000000000000000000000006004820152602401610672565b505b610db182897f04e45aaf0000000000000000000000000000000000000000000000000000000061126c565b9a9950505050505050505050565b600080600080610ddf6020808c51610dd79190611832565b8c9190610b07565b806020019051810190610df29190611c2c565b509250925092508515610e78576000610e0a84611439565b505090506000610e1a828c6111a7565b905080610e75576040517f5c4440c90000000000000000000000000000000000000000000000000000000081527fb858183f000000000000000000000000000000000000000000000000000000006004820152602401610672565b50505b8415610ef7576000610e8984611475565b509150506000610e99828b6111a7565b905080610ef4576040517f27f5b90d0000000000000000000000000000000000000000000000000000000081527fb858183f000000000000000000000000000000000000000000000000000000006004820152602401610672565b50505b610f2282887fb858183f0000000000000000000000000000000000000000000000000000000061126c565b9998505050505050505050565b60008084806020019051810190610f469190611cc8565b92505091506000610f5783866111a7565b905080610fb2576040517f27f5b90d0000000000000000000000000000000000000000000000000000000081527fdf2ab5bb000000000000000000000000000000000000000000000000000000006004820152602401610672565b610fdd82857fdf2ab5bb0000000000000000000000000000000000000000000000000000000061126c565b505050505050565b60008060008089806020019051810190610fff9190611d0b565b93509350509250851561108f5760006110328360008151811061102457611024611abc565b60200260200101518b6111a7565b90508061108d576040517f5c4440c90000000000000000000000000000000000000000000000000000000081527f472b43f3000000000000000000000000000000000000000000000000000000006004820152602401610672565b505b84156111245760006110c783600185516110a99190611832565b815181106110b9576110b9611abc565b60200260200101518a6111a7565b905080611122576040517f27f5b90d0000000000000000000000000000000000000000000000000000000081527f472b43f3000000000000000000000000000000000000000000000000000000006004820152602401610672565b505b61114f81887f472b43f30000000000000000000000000000000000000000000000000000000061126c565b509098975050505050505050565b6000828060200190518101906111739190611dcb565b91506111a2905081837f49404b7c0000000000000000000000000000000000000000000000000000000061126c565b505050565b60008173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16148061058a575073ffffffffffffffffffffffffffffffffffffffff821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1461121657600061058a565b7f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16149392505050565b7fffffffff0000000000000000000000000000000000000000000000000000000081167fdf2ab5bb0000000000000000000000000000000000000000000000000000000014806112fd57507fffffffff0000000000000000000000000000000000000000000000000000000081167f49404b7c00000000000000000000000000000000000000000000000000000000145b1561138b578173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16146111a2576040517f02a3e6980000000000000000000000000000000000000000000000000000000081527fffffffff0000000000000000000000000000000000000000000000000000000082166004820152602401610672565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141580156113de575073ffffffffffffffffffffffffffffffffffffffff8316600214155b156111a2576040517f02a3e6980000000000000000000000000000000000000000000000000000000081527fffffffff0000000000000000000000000000000000000000000000000000000082166004820152602401610672565b6000808061144784826114c7565b9250611454846014611557565b905061146c61146560036014611b3b565b85906114c7565b91509193909250565b600080806114be6014611489600382611b3b565b6114939190611b3b565b855161149f9190611832565b60146114ac600382611b3b565b6114b69190611b3b565b869190610b07565b93506114478460005b60006114d4826014611b3b565b8351101561153e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e647300000000000000000000006044820152606401610672565b5001602001516c01000000000000000000000000900490565b600081611565816003611b3b565b10156115cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f746f55696e7432345f6f766572666c6f770000000000000000000000000000006044820152606401610672565b6115d8826003611b3b565b83511015611642576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f746f55696e7432345f6f75744f66426f756e64730000000000000000000000006044820152606401610672565b50016003015190565b60005b8381101561166657818101518382015260200161164e565b838111156107495750506000910152565b602081526000825180602084015261169681604085016020870161164b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b73ffffffffffffffffffffffffffffffffffffffff811681146116ea57600080fd5b50565b60008060008060008060a0878903121561170657600080fd5b8635611711816116c8565b95506020870135611721816116c8565b94506040870135611731816116c8565b935060608701359250608087013567ffffffffffffffff8082111561175557600080fd5b818901915089601f83011261176957600080fd5b81358181111561177857600080fd5b8a602082850101111561178a57600080fd5b6020830194508093505050509295509295509295565b600181811c908216806117b457607f821691505b6020821081036117ed577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561184457611844611803565b500390565b60006020828403121561185b57600080fd5b5051919050565b6000808585111561187257600080fd5b8386111561187f57600080fd5b5050820193919092039150565b7fffffffff0000000000000000000000000000000000000000000000000000000081358181169160048510156118cc5780818660040360031b1b83161692505b505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561194a5761194a6118d4565b604052919050565b600067ffffffffffffffff82111561196c5761196c6118d4565b5060051b60200190565b600067ffffffffffffffff821115611990576119906118d4565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60008060408084860312156119d057600080fd5b8335925060208085013567ffffffffffffffff808211156119f057600080fd5b818701915087601f830112611a0457600080fd5b8135611a17611a1282611952565b611903565b81815260059190911b8301840190848101908a831115611a3657600080fd5b8585015b83811015611aaa57803585811115611a525760008081fd5b8601603f81018d13611a645760008081fd5b87810135611a74611a1282611976565b8181528e8b838501011115611a895760008081fd5b818b84018b83013760009181018a0191909152845250918601918601611a3a565b50809750505050505050509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000815160208301517fffffffff0000000000000000000000000000000000000000000000000000000080821693506004831015611b335780818460040360031b1b83161693505b505050919050565b60008219821115611b4e57611b4e611803565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611b8457611b84611803565b5060010190565b8051611b96816116c8565b919050565b600080600080600080600060e0888a031215611bb657600080fd5b8751611bc1816116c8565b6020890151909750611bd2816116c8565b604089015190965062ffffff81168114611beb57600080fd5b6060890151909550611bfc816116c8565b809450506080880151925060a0880151915060c0880151611c1c816116c8565b8091505092959891949750929550565b60008060008060808587031215611c4257600080fd5b845167ffffffffffffffff811115611c5957600080fd5b8501601f81018713611c6a57600080fd5b8051611c78611a1282611976565b818152886020838501011115611c8d57600080fd5b611c9e82602083016020860161164b565b8096505050506020850151611cb2816116c8565b6040860151606090960151949790965092505050565b600080600060608486031215611cdd57600080fd5b8351611ce8816116c8565b602085015160408601519194509250611d00816116c8565b809150509250925092565b60008060008060808587031215611d2157600080fd5b845193506020808601519350604086015167ffffffffffffffff811115611d4757600080fd5b8601601f81018813611d5857600080fd5b8051611d66611a1282611952565b81815260059190911b8201830190838101908a831115611d8557600080fd5b928401925b82841015611dac578351611d9d816116c8565b82529284019290840190611d8a565b8096505050505050611dc060608601611b8b565b905092959194509250565b60008060408385031215611dde57600080fd5b825191506020830151611df0816116c8565b80915050925092905056fea26469706673582212206f1b85be2ca7af517505ed12d9d5b77d7fbee1026625e1a000767ff619b1c1f664736f6c634300080d0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000000000000000000000000000000000000000004000000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc45000000000000000000000000000000000000000000000000000000000000001a556e6973776170204175746f526f757465722057726170706572000000000000

-----Decoded View---------------
Arg [0] : _name (string): Uniswap AutoRouter Wrapper
Arg [1] : _uniV3SwapRouter (address): 0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [1] : 00000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc45
Arg [2] : 000000000000000000000000000000000000000000000000000000000000001a
Arg [3] : 556e6973776170204175746f526f757465722057726170706572000000000000


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.