false
false

Contract Address Details

0x43e9f7ca4AEAcd67A7AC4a275cee7BC8AF601bE4

Contract Name
MinterProxyV2
Creator
0x45b3fe–654a5f at 0x89a8c2–43c5ea
Balance
0 SYS ( )
Tokens
Fetching tokens...
Transactions
3 Transactions
Transfers
0 Transfers
Gas Used
145,047
Last Balance Update
793883
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
Contract name:
MinterProxyV2




Optimization enabled
true
Compiler version
v0.8.17+commit.8df45f5f




Optimization runs
1000
EVM Version
london




Verified at
2024-04-12T01:25:23.887186Z

Constructor Arguments

00000000000000000000000000000000000000000000000000000000000000190000000000000000000000008a4aa176007196d48d39c89402d3753c39ae64c1000000000000000000000000d3e822f3ef011ca5f17d82c956d952d8d7c3a1bb

Arg [0] (uint256) : 25
Arg [1] (address) : 0x8a4aa176007196d48d39c89402d3753c39ae64c1
Arg [2] (address) : 0xd3e822f3ef011ca5f17d82c956d952d8d7c3a1bb

              

Contract source code

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;

abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

abstract contract Ownable is Context {
    address private _owner;

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

    constructor() {
        _transferOwnership(_msgSender());
    }

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

    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

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

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

abstract contract Controller is Ownable {
    event ControllerAdded(address controller);
    event ControllerRemoved(address controller);
    mapping(address => bool) controllers;
    uint8 public controllerCnt = 0;

    modifier onlyController() {
        require(isController(_msgSender()), "no controller rights");
        _;
    }

    function isController(address _controller) public view returns (bool) {
        return _controller == owner() || controllers[_controller];
    }

    function addController(address _controller) public onlyOwner {
        if (controllers[_controller] == false) {
            controllers[_controller] = true;
            controllerCnt++;
        }
        emit ControllerAdded(_controller);
    }

    function removeController(address _controller) public onlyOwner {
        if (controllers[_controller] == true) {
            controllers[_controller] = false;
            controllerCnt--;
        }
        emit ControllerRemoved(_controller);
    }
}

abstract contract ReentrancyGuard {
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
        _status = _ENTERED;
    }

    function _nonReentrantAfter() private {
        _status = _NOT_ENTERED;
    }

    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == _ENTERED;
    }
}

interface IERC20 {
    event Transfer(address indexed from, address indexed to, uint256 value);

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

    function totalSupply() external view returns (uint256);

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

    function transfer(address to, uint256 amount) external returns (bool);

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

    function approve(address spender, uint256 amount) external returns (bool);

    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}

interface IERC20Permit {
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    function nonces(address owner) external view returns (uint256);

    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

library Address {
    function isContract(address account) internal view returns (bool) {
        return account.code.length > 0;
    }

    function sendValue(address payable recipient, uint256 amount) internal {
        require(
            address(this).balance >= amount,
            "Address: insufficient balance"
        );

        (bool success, ) = recipient.call{value: amount}("");
        require(
            success,
            "Address: unable to send value, recipient may have reverted"
        );
    }

    function functionCall(
        address target,
        bytes memory data
    ) internal returns (bytes memory) {
        return
            functionCallWithValue(
                target,
                data,
                0,
                "Address: low-level call failed"
            );
    }

    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return
            functionCallWithValue(
                target,
                data,
                value,
                "Address: low-level call with value failed"
            );
    }

    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(
            address(this).balance >= value,
            "Address: insufficient balance for call"
        );
        (bool success, bytes memory returndata) = target.call{value: value}(
            data
        );
        return
            verifyCallResultFromTarget(
                target,
                success,
                returndata,
                errorMessage
            );
    }

    function functionStaticCall(
        address target,
        bytes memory data
    ) internal view returns (bytes memory) {
        return
            functionStaticCall(
                target,
                data,
                "Address: low-level static call failed"
            );
    }

    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return
            verifyCallResultFromTarget(
                target,
                success,
                returndata,
                errorMessage
            );
    }

    function functionDelegateCall(
        address target,
        bytes memory data
    ) internal returns (bytes memory) {
        return
            functionDelegateCall(
                target,
                data,
                "Address: low-level delegate call failed"
            );
    }

    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return
            verifyCallResultFromTarget(
                target,
                success,
                returndata,
                errorMessage
            );
    }

    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(
        bytes memory returndata,
        string memory errorMessage
    ) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}

interface IWrapToken {
    function deposit() external payable;
    function withdraw(uint256) external;
}

library SafeERC20 {
    using Address for address;

    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(
            token,
            abi.encodeWithSelector(token.transfer.selector, to, value)
        );
    }

    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(
            token,
            abi.encodeWithSelector(token.transferFrom.selector, from, to, value)
        );
    }

    function safeApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(
            token,
            abi.encodeWithSelector(token.approve.selector, spender, value)
        );
    }

    function safeIncreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        _callOptionalReturn(
            token,
            abi.encodeWithSelector(
                token.approve.selector,
                spender,
                oldAllowance + value
            )
        );
    }

    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(
                oldAllowance >= value,
                "SafeERC20: decreased allowance below zero"
            );
            _callOptionalReturn(
                token,
                abi.encodeWithSelector(
                    token.approve.selector,
                    spender,
                    oldAllowance - value
                )
            );
        }
    }

    function forceApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        bytes memory approvalCall = abi.encodeWithSelector(
            token.approve.selector,
            spender,
            value
        );

        if (!_callOptionalReturnBool(token, approvalCall)) {
            _callOptionalReturn(
                token,
                abi.encodeWithSelector(token.approve.selector, spender, 0)
            );
            _callOptionalReturn(token, approvalCall);
        }
    }

    function safePermit(
        IERC20Permit token,
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal {
        uint256 nonceBefore = token.nonces(owner);
        token.permit(owner, spender, value, deadline, v, r, s);
        uint256 nonceAfter = token.nonces(owner);
        require(
            nonceAfter == nonceBefore + 1,
            "SafeERC20: permit did not succeed"
        );
    }

    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        bytes memory returndata = address(token).functionCall(
            data,
            "SafeERC20: low-level call failed"
        );
        require(
            returndata.length == 0 || abi.decode(returndata, (bool)),
            "SafeERC20: ERC20 operation did not succeed"
        );
    }

    function _callOptionalReturnBool(
        IERC20 token,
        bytes memory data
    ) private returns (bool) {
        (bool success, bytes memory returndata) = address(token).call(data);
        return
            success &&
            (returndata.length == 0 || abi.decode(returndata, (bool))) &&
            Address.isContract(address(token));
    }
}

library TransferHelper {
    function safeTransferNative(address to, uint256 value) internal {
        (bool success, ) = to.call{value: value}(new bytes(0));
        require(success, "TransferHelper: NATIVE_TRANSFER_FAILED");
    }
}

interface IMintBurnToken {
    function mint(address to, uint256 amount) external;

    function burn(address from, uint256 amount) external;
}

contract MinterProxyV2 is Controller, ReentrancyGuard {
    using SafeERC20 for IERC20;
    using Address for address;
    using Address for address payable;

    address public immutable NATIVE =
        0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;

    address public wNATIVE;

    uint256 MAX_UINT256 =
        0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;

    mapping(uint256 => bool) public completedOrder;

    address public _liquidpool;

    uint256 public _orderID;

    bool private _paused;

    event Paused(address account);

    event Unpaused(address account);

    event LogVaultIn(
        address indexed token,
        uint256 indexed orderID,
        address indexed receiver,
        uint256 amount,
        uint256 serviceFee,
        uint256 gasFee
    );
    event LogVaultOut(
        address indexed token,
        address indexed from,
        uint256 indexed orderID,
        uint256 amount,
        address vault,
        bytes order
    );

    event LogVaultCall(
        address indexed target,
        uint256 amount,
        bool success,
        bytes reason
    );

    constructor(uint256 _id_prefix, address _lp, address _wNative) {
        _liquidpool = _lp;
        _paused = false;
        _orderID = _id_prefix * (10 ** 9);
        wNATIVE = _wNative;
    }

    receive() external payable {}

    fallback() external payable {}

    modifier whenNotPaused() {
        require(!_paused, "MP: paused");
        _;
    }

    function chainID() public view returns (uint) {
        return block.chainid;
    }

    function setLiquidpool(address _lp) external onlyOwner {
        _liquidpool = _lp;
    }

    function setWrapNative(address _wNative) external onlyOwner {
        wNATIVE = _wNative;
    }

    function needWrapNative() internal view returns (bool) {
        return wNATIVE != address(0);
    }

    function liquidpool() internal view returns (address) {
        if (_liquidpool != address(0)) {
            return _liquidpool;
        }
        return address(this);
    }

    function pause() external onlyOwner {
        _paused = true;
        emit Paused(_msgSender());
    }

    function unpause() external onlyOwner {
        _paused = false;
        emit Unpaused(_msgSender());
    }

    function _isSelfLiquidpool() internal view returns (bool) {
        return address(this) == liquidpool();
    }

    function isUUIDCompleted(uint256 uuid) external view returns (bool) {
        return completedOrder[uuid];
    }

    function _registerOrder(uint256 uuid) internal {
        require(!completedOrder[uuid], "MP: already completed");
        completedOrder[uuid] = true;
    }

    function _balanceOf(address receiveToken) internal view returns (uint256) {
        uint256 _balance;
        if (receiveToken == NATIVE) {
            if (needWrapNative()) {
                _balance = IERC20(wNATIVE).balanceOf(liquidpool());
            } else {
                _balance = address(this).balance;
            }
        } else {
            _balance = IERC20(receiveToken).balanceOf(liquidpool());
        }
        return _balance;
    }

    function _balanceOfSelf(
        address receiveToken
    ) internal view returns (uint256) {
        uint256 _balance;
        if (receiveToken == NATIVE) {
            _balance = address(this).balance;
        } else {
            _balance = IERC20(receiveToken).balanceOf(address(this));
        }
        return _balance;
    }

    function _checkVaultOut(
        address tokenAddr,
        uint256 amount,
        bytes calldata order
    ) internal pure {
        require(tokenAddr != address(0), "MP: tokenAddress is invalid");
        require(amount > 0, "MP: amount is 0");
        require(order.length > 0, "MP: order is empty");
    }

    function vaultOut(
        address tokenAddr,
        uint256 amount,
        bool burnable,
        bytes calldata order
    ) external payable nonReentrant whenNotPaused {
        _checkVaultOut(tokenAddr, amount, order);

        if (tokenAddr == NATIVE) {
            require(amount == msg.value, "MP: amount is invalid");
            if (needWrapNative()) {
                uint256 old = IERC20(wNATIVE).balanceOf(address(this));
                IWrapToken(wNATIVE).deposit{value: msg.value}();
                uint256 val = IERC20(wNATIVE).balanceOf(address(this));
                require(val - old == amount, "MP: warp token dismatch");
                if (!_isSelfLiquidpool()) {
                    IERC20(wNATIVE).safeTransfer(_liquidpool, amount);
                }
            } else {
                if (!_isSelfLiquidpool()) {
                    TransferHelper.safeTransferNative(_liquidpool, amount);
                }
            }
        } else if (burnable) {
            uint256 old = IERC20(tokenAddr).balanceOf(_msgSender());
            IMintBurnToken(tokenAddr).burn(_msgSender(), amount);
            uint256 val = IERC20(tokenAddr).balanceOf(_msgSender());
            require(val == old - amount, "MP: burn failed");
        } else {
            IERC20(tokenAddr).safeTransferFrom(
                _msgSender(),
                liquidpool(),
                amount
            );
        }

        _orderID++;
        emit LogVaultOut(
            tokenAddr,
            _msgSender(),
            _orderID,
            amount,
            burnable ? address(0) : liquidpool(),
            order
        );
    }

    function swap(
        address tokenAddr,
        uint256 amount,
        address target,
        address receiveToken,
        address receiver,
        uint256 minAmount,
        bytes calldata callData,
        bytes calldata order
    ) external payable nonReentrant whenNotPaused {
        _checkVaultOut(tokenAddr, amount, order);
        require(
            target != address(this) && target != address(0),
            "MP: target is invalid"
        );
        require(callData.length > 0, "MP: calldata is empty");
        require(receiveToken != address(0), "MP: receiveToken is empty");
        require(receiver != address(0), "MP: receiver is empty");
        require(minAmount > 0, "MP: minAmount is empty");

        uint256 old_balance = _balanceOfSelf(receiveToken);
        if (tokenAddr == NATIVE) {
            require(amount == msg.value, "MP: amount is invalid");
            target.functionCallWithValue(
                callData,
                amount,
                "MP: CallWithValue failed"
            );
        } else {
            IERC20(tokenAddr).safeTransferFrom(
                _msgSender(),
                address(this),
                amount
            );
            if (IERC20(tokenAddr).allowance(address(this), target) < amount) {
                IERC20(tokenAddr).safeApprove(target, MAX_UINT256);
            }
            target.functionCall(callData, "MP: FunctionCall failed");
        }

        uint256 _amountOut = 0;

        uint256 new_balance = _balanceOfSelf(receiveToken);
        require(
            new_balance > old_balance,
            "MP: receive amount should above zero"
        );
        _amountOut = new_balance - old_balance;

        require(_amountOut >= minAmount, "MP: receive amount not enough");
        if (receiveToken == NATIVE) {
            TransferHelper.safeTransferNative(receiver, _amountOut);
        } else {
            IERC20(receiveToken).safeTransfer(receiver, _amountOut);
        }

        _orderID++;
        emit LogVaultOut(
            receiveToken,
            _msgSender(),
            _orderID,
            _amountOut,
            receiver,
            order
        );
    }

    function vaultIn(
        uint256 orderID,
        address receiveToken,
        address receiver,
        bool burnable,
        uint256 amount
    ) external onlyController whenNotPaused {
        require(orderID > 0, "MP: orderID empty");
        require(receiver != address(0), "MP: receiver invaild");
        require(amount > 0, "MP: amount is empty");
        if (!burnable) {
            require(
                _balanceOf(receiveToken) >= amount,
                "MP: insufficient balance"
            );
        }
        _registerOrder(orderID);
        if (receiveToken == NATIVE) {
            if (needWrapNative()) {
                if (_isSelfLiquidpool()) {
                    IERC20(wNATIVE).safeTransfer(receiver, amount);
                } else {
                    IERC20(wNATIVE).safeTransferFrom(
                        liquidpool(),
                        receiver,
                        amount
                    );
                }
            } else {
                TransferHelper.safeTransferNative(receiver, amount);
            }
        } else if (burnable) {
            uint256 old = IERC20(receiveToken).balanceOf(receiver);
            IMintBurnToken(receiveToken).mint(receiver, amount);
            uint256 val = IERC20(receiveToken).balanceOf(receiver);
            require(val == old + amount, "MP: mint failed");
        } else {
            if (_isSelfLiquidpool()) {
                IERC20(receiveToken).safeTransfer(receiver, amount);
            } else {
                IERC20(receiveToken).safeTransferFrom(
                    liquidpool(),
                    receiver,
                    amount
                );
            }
        }
        emit LogVaultIn(receiveToken, orderID, receiver, amount, 0, 0);
    }

    // Fees[] struct
    // 0: uint256 expectAmount
    // 1: uint256 minAmount
    // 2: uint256 feeRate
    // 3: uint256 gasFee
    function vaultInAndCall(
        uint256 orderID,
        address tokenAddr,
        address toAddr,
        bool burnable,
        uint256 amount,
        address receiver,
        address receiveToken,
        uint256[] memory fees,
        bytes calldata data
    ) external onlyController whenNotPaused {
        require(orderID > 0, "MP: orderID empty");
        require(data.length > 0, "MP: data empty");
        require(fees.length == 4, "MP: fees mismatch");
        require(amount > 0, "MP: amount is empty");
        require(fees[1] > 0, "MP: minAmount is empty");
        require(fees[0] > 0, "MP: expectAmount is empty");
        if (!burnable) {
            require(
                _balanceOf(tokenAddr) >= amount,
                "MP: insufficient balance"
            );
        }
        require(receiver != address(0), "MP: receiver is empty");
        require(
            toAddr != address(this) && toAddr != address(0),
            "MP: toAddr invaild"
        );
        _registerOrder(orderID);
        bool fromTokenNative = (tokenAddr == NATIVE);
        if (fromTokenNative) {
            if (needWrapNative()) {
                if (!_isSelfLiquidpool()) {
                    IERC20(wNATIVE).safeTransferFrom(
                        liquidpool(),
                        address(this),
                        amount
                    );
                }
                uint256 old = address(this).balance;
                IWrapToken(wNATIVE).withdraw(amount);
                uint256 val = address(this).balance;
                require(
                    val - old == amount,
                    "MP: native token amount dismatch"
                );
            } else {
                // the native token in this contract, so ignore
                require(
                    address(this).balance >= amount,
                    "MP: native token insuffient"
                );
            }
        } else {
            if (burnable) {
                uint256 old = IERC20(tokenAddr).balanceOf(address(this));
                IMintBurnToken(tokenAddr).mint(address(this), amount);
                uint256 val = IERC20(tokenAddr).balanceOf(address(this));
                require(val == old + amount, "MP: mint failed");
            } else {
                if (!_isSelfLiquidpool()) {
                    IERC20(tokenAddr).safeTransferFrom(
                        _liquidpool,
                        address(this),
                        amount
                    );
                }
            }
            if (IERC20(tokenAddr).allowance(address(this), toAddr) < amount) {
                IERC20(tokenAddr).safeApprove(toAddr, MAX_UINT256);
            }
        }

        (uint256 realOut, uint256 fee) = _callAndTransfer(
            toAddr,
            fromTokenNative ? amount : 0,
            receiver,
            receiveToken,
            fees,
            data
        );
        uint256 totalfee = fee + fees[3];
        if (totalfee > 0) {
            if (receiveToken == NATIVE) {
                if (needWrapNative()) {
                    IWrapToken(wNATIVE).deposit{value: totalfee}();
                    if (!_isSelfLiquidpool()) {
                        IERC20(wNATIVE).safeTransfer(_liquidpool, totalfee);
                    }
                }
            } else {
                IERC20(receiveToken).safeTransfer(_liquidpool, totalfee);
            }
        }

        emit LogVaultIn(receiveToken, orderID, receiver, realOut, fee, fees[3]);
    }

    // Fees[] struct
    // 0: uint256 expectAmount
    // 1: uint256 minAmount
    // 2: uint256 feeRate
    // 3: uint256 gasFee
    function _callAndTransfer(
        address contractAddr,
        uint256 fromNativeAmount,
        address receiver,
        address receiveToken,
        uint256[] memory fees,
        bytes calldata data
    ) internal returns (uint256, uint256) {
        uint256 old_balance = _balanceOfSelf(receiveToken);

        if (fromNativeAmount > 0) {
            contractAddr.functionCallWithValue(
                data,
                fromNativeAmount,
                "MP: CallWithValue failed"
            );
        } else {
            contractAddr.functionCall(data, "MP: FunctionCall failed");
        }
        uint256 real = 0;
        uint256 fee = 0;
        {
            uint256 expectAmount = fees[0];
            uint256 minAmount = fees[1];
            uint256 feeRate = fees[2];
            uint256 gasFee = fees[3];
            uint256 new_balance = _balanceOfSelf(receiveToken);
            require(
                new_balance > old_balance,
                "MP: receiver should get assets"
            );
            uint256 amountOut = new_balance - old_balance;
            require(amountOut >= minAmount, "MP: receive amount not enough");
            require(amountOut >= minAmount + gasFee, "MP: gasFee not enough");

            fee = (amountOut / 10000) * feeRate;

            require(
                amountOut >= minAmount + gasFee + fee,
                "MP: fee not enough"
            );
            real = amountOut - fee - gasFee;
            real = real > expectAmount ? expectAmount : real;
        }

        if (receiver != address(this)) {
            if (receiveToken == NATIVE) {
                TransferHelper.safeTransferNative(receiver, real);
            } else {
                IERC20(receiveToken).safeTransfer(receiver, real);
            }
        }
        return (real, fee);
    }

    function call(
        address target,
        bytes calldata _data
    ) external payable onlyOwner {
        (bool success, bytes memory result) = target.call{value: msg.value}(
            _data
        );
        emit LogVaultCall(target, msg.value, success, result);
    }

    function withdrawFee(
        address token,
        address receiver,
        uint256 amount
    ) external onlyOwner {
        if (token == NATIVE) {
            uint256 balance = address(this).balance;
            uint256 tmp = balance > amount ? amount : balance;
            TransferHelper.safeTransferNative(receiver, tmp);
        } else {
            uint256 balance = IERC20(token).balanceOf(address(this));
            uint256 tmp = balance > amount ? amount : balance;
            IERC20(token).safeTransfer(receiver, tmp);
        }
    }

    function mintTo(
        address tokenAddr,
        address receiver,
        uint256 amount
    ) external onlyController {
        uint256 old = IERC20(tokenAddr).balanceOf(receiver);
        IMintBurnToken(tokenAddr).mint(receiver, amount);
        uint256 val = IERC20(tokenAddr).balanceOf(receiver);
        require(val == old + amount, "MP: mint failed");
    }

    bytes4 constant CONTROLLER = 0xf77c4791;
    bytes4 constant IS_CONTROLLER = 0xb429afeb;

    function isMinter(address _contract) external view returns (bool) {
        (bool success, address result) = _getMinter(_contract);
        if (success && (result == address(this))) {
            return true;
        }

        (bool success1, bool ok) = _isMinter(_contract, address(this));
        if (success1 && ok) {
            return true;
        }
        return false;
    }

    function isMinterWithData(
        address _contract,
        bytes memory data,
        bytes memory expectRes
    ) external view returns (bool) {
        (bool success, address result) = _getMinter(_contract);
        if (success && (result == address(this))) {
            return true;
        }

        (bool success1, bool ok) = _isMinter(_contract, address(this));
        if (success1 && ok) {
            return true;
        }
        if (data.length > 0) {
            (bool success2, bytes memory returndata) = _contract.staticcall(
                data
            );
            return success2 && bytesEqual(returndata, expectRes);
        }
        return false;
    }

    function _getMinter(
        address _contract
    ) internal view returns (bool, address) {
        (bool success, bytes memory returndata) = _contract.staticcall(
            abi.encodeWithSelector(CONTROLLER)
        );
        return (success, bytesToAddress(returndata));
    }

    function _isMinter(
        address _contract,
        address _target
    ) internal view returns (bool, bool) {
        (bool success, bytes memory returndata) = _contract.staticcall(
            abi.encodeWithSelector(IS_CONTROLLER, _target)
        );

        (bool ok, uint res) = toUint(returndata);
        return (success && ok, res == 1);
    }

    function toUint(bytes memory bs) internal pure returns (bool, uint) {
        if (bs.length < 32) {
            return (false, 0);
        }
        uint x;
        assembly {
            x := mload(add(bs, add(0x20, 0)))
        }
        return (true, x);
    }

    function bytesToAddress(
        bytes memory bys
    ) internal pure returns (address addr) {
        assembly {
            addr := mload(add(bys, 32))
        }
    }

    function bytesEqual(
        bytes memory a,
        bytes memory b
    ) public pure returns (bool) {
        return keccak256(a) == keccak256(b);
    }
}
        

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"_id_prefix","internalType":"uint256"},{"type":"address","name":"_lp","internalType":"address"},{"type":"address","name":"_wNative","internalType":"address"}]},{"type":"event","name":"ControllerAdded","inputs":[{"type":"address","name":"controller","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"ControllerRemoved","inputs":[{"type":"address","name":"controller","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"LogVaultCall","inputs":[{"type":"address","name":"target","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"bool","name":"success","internalType":"bool","indexed":false},{"type":"bytes","name":"reason","internalType":"bytes","indexed":false}],"anonymous":false},{"type":"event","name":"LogVaultIn","inputs":[{"type":"address","name":"token","internalType":"address","indexed":true},{"type":"uint256","name":"orderID","internalType":"uint256","indexed":true},{"type":"address","name":"receiver","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"uint256","name":"serviceFee","internalType":"uint256","indexed":false},{"type":"uint256","name":"gasFee","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"LogVaultOut","inputs":[{"type":"address","name":"token","internalType":"address","indexed":true},{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"uint256","name":"orderID","internalType":"uint256","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"address","name":"vault","internalType":"address","indexed":false},{"type":"bytes","name":"order","internalType":"bytes","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Paused","inputs":[{"type":"address","name":"account","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Unpaused","inputs":[{"type":"address","name":"account","internalType":"address","indexed":false}],"anonymous":false},{"type":"fallback","stateMutability":"payable"},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"NATIVE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"_liquidpool","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"_orderID","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addController","inputs":[{"type":"address","name":"_controller","internalType":"address"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"bytesEqual","inputs":[{"type":"bytes","name":"a","internalType":"bytes"},{"type":"bytes","name":"b","internalType":"bytes"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"call","inputs":[{"type":"address","name":"target","internalType":"address"},{"type":"bytes","name":"_data","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"chainID","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"completedOrder","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"controllerCnt","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isController","inputs":[{"type":"address","name":"_controller","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isMinter","inputs":[{"type":"address","name":"_contract","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isMinterWithData","inputs":[{"type":"address","name":"_contract","internalType":"address"},{"type":"bytes","name":"data","internalType":"bytes"},{"type":"bytes","name":"expectRes","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isUUIDCompleted","inputs":[{"type":"uint256","name":"uuid","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"mintTo","inputs":[{"type":"address","name":"tokenAddr","internalType":"address"},{"type":"address","name":"receiver","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"pause","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"removeController","inputs":[{"type":"address","name":"_controller","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setLiquidpool","inputs":[{"type":"address","name":"_lp","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setWrapNative","inputs":[{"type":"address","name":"_wNative","internalType":"address"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"swap","inputs":[{"type":"address","name":"tokenAddr","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"address","name":"target","internalType":"address"},{"type":"address","name":"receiveToken","internalType":"address"},{"type":"address","name":"receiver","internalType":"address"},{"type":"uint256","name":"minAmount","internalType":"uint256"},{"type":"bytes","name":"callData","internalType":"bytes"},{"type":"bytes","name":"order","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"unpause","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"vaultIn","inputs":[{"type":"uint256","name":"orderID","internalType":"uint256"},{"type":"address","name":"receiveToken","internalType":"address"},{"type":"address","name":"receiver","internalType":"address"},{"type":"bool","name":"burnable","internalType":"bool"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"vaultInAndCall","inputs":[{"type":"uint256","name":"orderID","internalType":"uint256"},{"type":"address","name":"tokenAddr","internalType":"address"},{"type":"address","name":"toAddr","internalType":"address"},{"type":"bool","name":"burnable","internalType":"bool"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"address","name":"receiver","internalType":"address"},{"type":"address","name":"receiveToken","internalType":"address"},{"type":"uint256[]","name":"fees","internalType":"uint256[]"},{"type":"bytes","name":"data","internalType":"bytes"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"vaultOut","inputs":[{"type":"address","name":"tokenAddr","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"bool","name":"burnable","internalType":"bool"},{"type":"bytes","name":"order","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"wNATIVE","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdrawFee","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"address","name":"receiver","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"receive","stateMutability":"payable"}]
              

Contract Creation Code

0x60a06040526002805460ff1916905573eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6080526000196005553480156200003957600080fd5b5060405162004380380380620043808339810160408190526200005c916200013a565b6200006733620000cd565b6001600355600780546001600160a01b0319166001600160a01b0384161790556009805460ff19169055620000a183633b9aca006200017b565b600855600480546001600160a01b0319166001600160a01b039290921691909117905550620001a79050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200013557600080fd5b919050565b6000806000606084860312156200015057600080fd5b8351925062000162602085016200011d565b915062000172604085016200011d565b90509250925092565b8082028115828204841417620001a157634e487b7160e01b600052601160045260246000fd5b92915050565b60805161417762000209600039600081816103d001528181610586015281816107dc015281816110ac015281816113c00152818161168f01528181612092015281816124da01528181612f280152818161320c015261371501526141776000f3fe6080604052600436106101975760003560e01c80638456cb59116100e0578063b429afeb11610084578063d4d5ea4511610061578063d4d5ea45146104a5578063ef9bcb27146104c5578063f2fde38b146104e5578063f6a74ed71461050557005b8063b429afeb14610445578063cec7d38814610465578063d039eff21461048557005b8063a0cf0aea116100bd578063a0cf0aea146103be578063a7fc7a07146103f2578063aa271e1a14610412578063adc879e91461043257005b80638456cb591461036b5780638da5cb5b146103805780638fd903f51461039e57005b806340bdd3e911610147578063565bc23411610124578063565bc234146102dc5780635b7dd1bb146102ef578063681b19ff1461030f57806378bbe8b61461033f57005b806340bdd3e9146102785780634c314eef146102985780635342389e146102b857005b80631b8b921d116101755780631b8b921d1461023d5780633f163c47146102505780633f4ba83a1461026357005b80628e59cf146101a05780630833bc9a146101dd5780631095b6d71461021d57005b3661019e57005b005b3480156101ac57600080fd5b506007546101c0906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156101e957600080fd5b5061020d6101f8366004613986565b60009081526006602052604090205460ff1690565b60405190151581526020016101d4565b34801561022957600080fd5b5061019e6102383660046139bb565b610525565b61019e61024b366004613a39565b61067b565b61019e61025e366004613a9a565b610786565b34801561026f57600080fd5b5061019e610cd9565b34801561028457600080fd5b5061020d610293366004613bc2565b610d7d565b3480156102a457600080fd5b5061020d6102b3366004613c26565b610d99565b3480156102c457600080fd5b506102ce60085481565b6040519081526020016101d4565b61019e6102ea366004613c9a565b610e93565b3480156102fb57600080fd5b5061019e61030a366004613d63565b61149c565b34801561031b57600080fd5b5061020d61032a366004613986565b60066020526000908152604090205460ff1681565b34801561034b57600080fd5b506002546103599060ff1681565b60405160ff90911681526020016101d4565b34801561037757600080fd5b5061019e61196a565b34801561038c57600080fd5b506000546001600160a01b03166101c0565b3480156103aa57600080fd5b506004546101c0906001600160a01b031681565b3480156103ca57600080fd5b506101c07f000000000000000000000000000000000000000000000000000000000000000081565b3480156103fe57600080fd5b5061019e61040d366004613dba565b6119f9565b34801561041e57600080fd5b5061020d61042d366004613dba565b611b07565b34801561043e57600080fd5b50466102ce565b34801561045157600080fd5b5061020d610460366004613dba565b611b75565b34801561047157600080fd5b5061019e610480366004613dba565b611bac565b34801561049157600080fd5b5061019e6104a0366004613dba565b611c35565b3480156104b157600080fd5b5061019e6104c0366004613dd5565b611cbe565b3480156104d157600080fd5b5061019e6104e03660046139bb565b61266c565b3480156104f157600080fd5b5061019e610500366004613dba565b61284e565b34801561051157600080fd5b5061019e610520366004613dba565b612930565b6000546001600160a01b031633146105845760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036105e2574760008282116105cd57816105cf565b825b90506105db8482612a35565b5050505050565b6040516370a0823160e01b81523060048201526000906001600160a01b038516906370a0823190602401602060405180830381865afa158015610629573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064d9190613f2c565b9050600082821161065e5781610660565b825b90506105db6001600160a01b0386168583612b18565b505050565b6000546001600160a01b031633146106d55760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161057b565b600080846001600160a01b03163485856040516106f3929190613f45565b60006040518083038185875af1925050503d8060008114610730576040519150601f19603f3d011682016040523d82523d6000602084013e610735565b606091505b5091509150846001600160a01b03167fbb9c4c4e98e306e63e340c78eed06da47fecfc0e2e0c6e88b42aca99dc5d52c334848460405161077793929190613fa5565b60405180910390a25050505050565b61078e612b94565b60095460ff16156107ce5760405162461bcd60e51b815260206004820152600a60248201526913540e881c185d5cd95960b21b604482015260640161057b565b6107da85858484612bed565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316856001600160a01b031603610a71573484146108625760405162461bcd60e51b815260206004820152601560248201527f4d503a20616d6f756e7420697320696e76616c69640000000000000000000000604482015260640161057b565b6004546001600160a01b031615610a4a57600480546040516370a0823160e01b815230928101929092526000916001600160a01b03909116906370a0823190602401602060405180830381865afa1580156108c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e59190613f2c565b9050600460009054906101000a90046001600160a01b03166001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561093757600080fd5b505af115801561094b573d6000803e3d6000fd5b5050600480546040516370a0823160e01b81523092810192909252600094506001600160a01b031692506370a082319150602401602060405180830381865afa15801561099c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c09190613f2c565b9050856109cd8383613fe5565b14610a1a5760405162461bcd60e51b815260206004820152601760248201527f4d503a207761727020746f6b656e206469736d61746368000000000000000000604482015260640161057b565b610a22612ce6565b610a4357600754600454610a43916001600160a01b03918216911688612b18565b5050610c5b565b610a52612ce6565b610a6c57600754610a6c906001600160a01b031685612a35565b610c5b565b8215610c3d5760006001600160a01b0386166370a08231336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610acd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610af19190613f2c565b90506001600160a01b038616639dc29fac336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101889052604401600060405180830381600087803b158015610b4b57600080fd5b505af1158015610b5f573d6000803e3d6000fd5b505050506000866001600160a01b03166370a08231610b7b3390565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610bbf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610be39190613f2c565b9050610bef8683613fe5565b8114610a435760405162461bcd60e51b815260206004820152600f60248201527f4d503a206275726e206661696c65640000000000000000000000000000000000604482015260640161057b565b610c5b33610c49612d09565b6001600160a01b038816919087612d32565b60088054906000610c6b83613ff8565b9091555050600854336001600160a01b0387167f873a952504255baba041a0843512f2748152611db0d25da60657af220f7540ba8787610cb257610cad612d09565b610cb5565b60005b8787604051610cc79493929190614011565b60405180910390a46105db6001600355565b6000546001600160a01b03163314610d335760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161057b565b6009805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6000818051906020012083805190602001201490505b92915050565b6000806000610da786612d83565b91509150818015610dc057506001600160a01b03811630145b15610dd057600192505050610e8c565b600080610ddd8830612e3f565b91509150818015610deb5750805b15610dfd576001945050505050610e8c565b865115610e8357600080896001600160a01b031689604051610e1f9190614057565b600060405180830381855afa9150503d8060008114610e5a576040519150601f19603f3d011682016040523d82523d6000602084013e610e5f565b606091505b5091509150818015610e765750610e768189610d7d565b9650505050505050610e8c565b60009450505050505b9392505050565b610e9b612b94565b60095460ff1615610edb5760405162461bcd60e51b815260206004820152600a60248201526913540e881c185d5cd95960b21b604482015260640161057b565b610ee78a8a8484612bed565b6001600160a01b0388163014801590610f0857506001600160a01b03881615155b610f545760405162461bcd60e51b815260206004820152601560248201527f4d503a2074617267657420697320696e76616c69640000000000000000000000604482015260640161057b565b82610fa15760405162461bcd60e51b815260206004820152601560248201527f4d503a2063616c6c6461746120697320656d7074790000000000000000000000604482015260640161057b565b6001600160a01b038716610ff75760405162461bcd60e51b815260206004820152601960248201527f4d503a2072656365697665546f6b656e20697320656d70747900000000000000604482015260640161057b565b6001600160a01b03861661104d5760405162461bcd60e51b815260206004820152601560248201527f4d503a20726563656976657220697320656d7074790000000000000000000000604482015260640161057b565b6000851161109d5760405162461bcd60e51b815260206004820152601660248201527f4d503a206d696e416d6f756e7420697320656d70747900000000000000000000604482015260640161057b565b60006110a888612f23565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168b6001600160a01b0316036111b857348a146111325760405162461bcd60e51b815260206004820152601560248201527f4d503a20616d6f756e7420697320696e76616c69640000000000000000000000604482015260640161057b565b6111b285858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601881527f4d503a2043616c6c5769746856616c7565206661696c6564000000000000000060208201526001600160a01b038e169392508e9150612fcf565b506112e0565b6111cd6001600160a01b038c1633308d612d32565b604051636eb1769f60e11b81523060048201526001600160a01b038a811660248301528b91908d169063dd62ed3e90604401602060405180830381865afa15801561121c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112409190613f2c565b101561125f5760055461125f906001600160a01b038d16908b906130c3565b6112de85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601781527f4d503a2046756e6374696f6e43616c6c206661696c656400000000000000000060208201526001600160a01b038e1693925090506131f8565b505b6000806112ec8a612f23565b90508281116113625760405162461bcd60e51b8152602060048201526024808201527f4d503a207265636569766520616d6f756e742073686f756c642061626f76652060448201527f7a65726f00000000000000000000000000000000000000000000000000000000606482015260840161057b565b61136c8382613fe5565b9150878210156113be5760405162461bcd60e51b815260206004820152601d60248201527f4d503a207265636569766520616d6f756e74206e6f7420656e6f756768000000604482015260640161057b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168a6001600160a01b031603611406576114018983612a35565b61141a565b61141a6001600160a01b038b168a84612b18565b6008805490600061142a83613ff8565b9091555050600854336001600160a01b03168b6001600160a01b03167f873a952504255baba041a0843512f2748152611db0d25da60657af220f7540ba858d8a8a60405161147b9493929190614011565b60405180910390a45050506114906001600355565b50505050505050505050565b6114a533611b75565b6114f15760405162461bcd60e51b815260206004820152601460248201527f6e6f20636f6e74726f6c6c657220726967687473000000000000000000000000604482015260640161057b565b60095460ff16156115315760405162461bcd60e51b815260206004820152600a60248201526913540e881c185d5cd95960b21b604482015260640161057b565b600085116115815760405162461bcd60e51b815260206004820152601160248201527f4d503a206f72646572494420656d707479000000000000000000000000000000604482015260640161057b565b6001600160a01b0383166115d75760405162461bcd60e51b815260206004820152601460248201527f4d503a20726563656976657220696e7661696c64000000000000000000000000604482015260640161057b565b600081116116275760405162461bcd60e51b815260206004820152601360248201527f4d503a20616d6f756e7420697320656d70747900000000000000000000000000604482015260640161057b565b81611684578061163685613207565b10156116845760405162461bcd60e51b815260206004820152601860248201527f4d503a20696e73756666696369656e742062616c616e63650000000000000000604482015260640161057b565b61168d85613326565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b031603611729576004546001600160a01b03161561171f576116df612ce6565b15611700576004546116fb906001600160a01b03168483612b18565b611901565b6116fb61170b612d09565b6004546001600160a01b0316908584612d32565b6116fb8382612a35565b81156118c3576040516370a0823160e01b81526001600160a01b038481166004830152600091908616906370a0823190602401602060405180830381865afa158015611779573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061179d9190613f2c565b6040516340c10f1960e01b81526001600160a01b03868116600483015260248201859052919250908616906340c10f1990604401600060405180830381600087803b1580156117eb57600080fd5b505af11580156117ff573d6000803e3d6000fd5b50506040516370a0823160e01b81526001600160a01b03878116600483015260009350881691506370a0823190602401602060405180830381865afa15801561184c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118709190613f2c565b905061187c8383614073565b81146118bc5760405162461bcd60e51b815260206004820152600f60248201526e13540e881b5a5b9d0819985a5b1959608a1b604482015260640161057b565b5050611901565b6118cb612ce6565b156118e4576116fb6001600160a01b0385168483612b18565b6119016118ef612d09565b6001600160a01b038616908584612d32565b826001600160a01b031685856001600160a01b03167f74aaf2992820754761f714bb3dcf12d7e3bb2e5f41949629e2e88a4a219e20478460008060405161195b939291909283526020830191909152604082015260600190565b60405180910390a45050505050565b6000546001600160a01b031633146119c45760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161057b565b6009805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610d603390565b6000546001600160a01b03163314611a535760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161057b565b6001600160a01b03811660009081526001602052604081205460ff1615159003611ac7576001600160a01b03811660009081526001602081905260408220805460ff191690911790556002805460ff1691611aad83614086565b91906101000a81548160ff021916908360ff160217905550505b6040516001600160a01b03821681527f0a8bb31534c0ed46f380cb867bd5c803a189ced9a764e30b3a4991a9901d7474906020015b60405180910390a150565b6000806000611b1584612d83565b91509150818015611b2e57506001600160a01b03811630145b15611b3d575060019392505050565b600080611b4a8630612e3f565b91509150818015611b585750805b15611b695750600195945050505050565b50600095945050505050565b600080546001600160a01b0383811691161480610d935750506001600160a01b031660009081526001602052604090205460ff1690565b6000546001600160a01b03163314611c065760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161057b565b6004805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6000546001600160a01b03163314611c8f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161057b565b6007805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b611cc733611b75565b611d135760405162461bcd60e51b815260206004820152601460248201527f6e6f20636f6e74726f6c6c657220726967687473000000000000000000000000604482015260640161057b565b60095460ff1615611d535760405162461bcd60e51b815260206004820152600a60248201526913540e881c185d5cd95960b21b604482015260640161057b565b60008a11611da35760405162461bcd60e51b815260206004820152601160248201527f4d503a206f72646572494420656d707479000000000000000000000000000000604482015260640161057b565b80611df05760405162461bcd60e51b815260206004820152600e60248201527f4d503a206461746120656d707479000000000000000000000000000000000000604482015260640161057b565b8251600414611e415760405162461bcd60e51b815260206004820152601160248201527f4d503a2066656573206d69736d61746368000000000000000000000000000000604482015260640161057b565b60008611611e915760405162461bcd60e51b815260206004820152601360248201527f4d503a20616d6f756e7420697320656d70747900000000000000000000000000604482015260640161057b565b600083600181518110611ea657611ea66140a5565b602002602001015111611efb5760405162461bcd60e51b815260206004820152601660248201527f4d503a206d696e416d6f756e7420697320656d70747900000000000000000000604482015260640161057b565b600083600081518110611f1057611f106140a5565b602002602001015111611f655760405162461bcd60e51b815260206004820152601960248201527f4d503a20657870656374416d6f756e7420697320656d70747900000000000000604482015260640161057b565b86611fc25785611f748a613207565b1015611fc25760405162461bcd60e51b815260206004820152601860248201527f4d503a20696e73756666696369656e742062616c616e63650000000000000000604482015260640161057b565b6001600160a01b0385166120185760405162461bcd60e51b815260206004820152601560248201527f4d503a20726563656976657220697320656d7074790000000000000000000000604482015260640161057b565b6001600160a01b038816301480159061203957506001600160a01b03881615155b6120855760405162461bcd60e51b815260206004820152601260248201527f4d503a20746f4164647220696e7661696c640000000000000000000000000000604482015260640161057b565b61208e8a613326565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168a6001600160a01b0316149050801561223a576004546001600160a01b0316156121e5576120e6612ce6565b612109576121096120f5612d09565b6004546001600160a01b031690308a612d32565b600480546040517f2e1a7d4d00000000000000000000000000000000000000000000000000000000815291820189905247916001600160a01b0390911690632e1a7d4d90602401600060405180830381600087803b15801561216a57600080fd5b505af115801561217e573d6000803e3d6000fd5b504792508a915061219190508383613fe5565b146121de5760405162461bcd60e51b815260206004820181905260248201527f4d503a206e617469766520746f6b656e20616d6f756e74206469736d61746368604482015260640161057b565b5050612485565b864710156122355760405162461bcd60e51b815260206004820152601b60248201527f4d503a206e617469766520746f6b656e20696e7375666669656e740000000000604482015260640161057b565b612485565b87156123cc576040516370a0823160e01b81523060048201526000906001600160a01b038c16906370a0823190602401602060405180830381865afa158015612287573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122ab9190613f2c565b6040516340c10f1960e01b8152306004820152602481018a90529091506001600160a01b038c16906340c10f1990604401600060405180830381600087803b1580156122f657600080fd5b505af115801561230a573d6000803e3d6000fd5b50506040516370a0823160e01b8152306004820152600092506001600160a01b038e1691506370a0823190602401602060405180830381865afa158015612355573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123799190613f2c565b90506123858983614073565b81146123c55760405162461bcd60e51b815260206004820152600f60248201526e13540e881b5a5b9d0819985a5b1959608a1b604482015260640161057b565b50506123f3565b6123d4612ce6565b6123f3576007546123f3906001600160a01b038c81169116308a612d32565b604051636eb1769f60e11b81523060048201526001600160a01b038a811660248301528891908c169063dd62ed3e90604401602060405180830381865afa158015612442573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124669190613f2c565b101561248557600554612485906001600160a01b038c16908b906130c3565b6000806124a48b8461249857600061249a565b8a5b8a8a8a8a8a6133a0565b915091506000866003815181106124bd576124bd6140a5565b6020026020010151826124d09190614073565b905080156125e1577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316886001600160a01b0316036125c7576004546001600160a01b0316156125c25760048054604080517fd0e30db000000000000000000000000000000000000000000000000000000000815290516001600160a01b039092169263d0e30db0928592808301926000929182900301818588803b15801561258057600080fd5b505af1158015612594573d6000803e3d6000fd5b50505050506125a1612ce6565b6125c2576007546004546125c2916001600160a01b03918216911683612b18565b6125e1565b6007546125e1906001600160a01b038a8116911683612b18565b886001600160a01b03168e896001600160a01b03167f74aaf2992820754761f714bb3dcf12d7e3bb2e5f41949629e2e88a4a219e204786868c60038151811061262c5761262c6140a5565b6020026020010151604051612654939291909283526020830191909152604082015260600190565b60405180910390a45050505050505050505050505050565b61267533611b75565b6126c15760405162461bcd60e51b815260206004820152601460248201527f6e6f20636f6e74726f6c6c657220726967687473000000000000000000000000604482015260640161057b565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908516906370a0823190602401602060405180830381865afa15801561270b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061272f9190613f2c565b6040516340c10f1960e01b81526001600160a01b03858116600483015260248201859052919250908516906340c10f1990604401600060405180830381600087803b15801561277d57600080fd5b505af1158015612791573d6000803e3d6000fd5b50506040516370a0823160e01b81526001600160a01b03868116600483015260009350871691506370a0823190602401602060405180830381865afa1580156127de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128029190613f2c565b905061280e8383614073565b81146105db5760405162461bcd60e51b815260206004820152600f60248201526e13540e881b5a5b9d0819985a5b1959608a1b604482015260640161057b565b6000546001600160a01b031633146128a85760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161057b565b6001600160a01b0381166129245760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161057b565b61292d81613780565b50565b6000546001600160a01b0316331461298a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161057b565b6001600160a01b03811660009081526001602081905260409091205460ff16151590036129fc576001600160a01b0381166000908152600160205260408120805460ff191690556002805460ff16916129e2836140bb565b91906101000a81548160ff021916908360ff160217905550505b6040516001600160a01b03821681527f33d83959be2573f5453b12eb9d43b3499bc57d96bd2f067ba44803c859e8111390602001611afc565b604080516000808252602082019092526001600160a01b038416908390604051612a5f9190614057565b60006040518083038185875af1925050503d8060008114612a9c576040519150601f19603f3d011682016040523d82523d6000602084013e612aa1565b606091505b50509050806106765760405162461bcd60e51b815260206004820152602660248201527f5472616e7366657248656c7065723a204e41544956455f5452414e534645525f60448201527f4641494c45440000000000000000000000000000000000000000000000000000606482015260840161057b565b6040516001600160a01b0383166024820152604481018290526106769084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526137dd565b600260035403612be65760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161057b565b6002600355565b6001600160a01b038416612c435760405162461bcd60e51b815260206004820152601b60248201527f4d503a20746f6b656e4164647265737320697320696e76616c69640000000000604482015260640161057b565b60008311612c935760405162461bcd60e51b815260206004820152600f60248201527f4d503a20616d6f756e7420697320300000000000000000000000000000000000604482015260640161057b565b80612ce05760405162461bcd60e51b815260206004820152601260248201527f4d503a206f7264657220697320656d7074790000000000000000000000000000604482015260640161057b565b50505050565b6000612cf0612d09565b6001600160a01b0316306001600160a01b031614905090565b6007546000906001600160a01b031615612d2d57506007546001600160a01b031690565b503090565b6040516001600160a01b0380851660248301528316604482015260648101829052612ce09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401612b5d565b60408051600481526024810182526020810180516001600160e01b03167ff77c47910000000000000000000000000000000000000000000000000000000017905290516000918291829182916001600160a01b03871691612de391614057565b600060405180830381855afa9150503d8060008114612e1e576040519150601f19603f3d011682016040523d82523d6000602084013e612e23565b606091505b509150915081612e34826020015190565b935093505050915091565b604080516001600160a01b0383811660248084019190915283518084039091018152604490920183526020820180516001600160e01b03167fb429afeb000000000000000000000000000000000000000000000000000000001790529151600092839283928392881691612eb291614057565b600060405180830381855afa9150503d8060008114612eed576040519150601f19603f3d011682016040523d82523d6000602084013e612ef2565b606091505b5091509150600080612f03836138c5565b91509150838015612f115750815b955060011493505050505b9250929050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031603612f66575047610d93565b6040516370a0823160e01b81523060048201526001600160a01b038416906370a08231906024015b602060405180830381865afa158015612fab573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8c9190613f2c565b6060824710156130475760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840161057b565b600080866001600160a01b031685876040516130639190614057565b60006040518083038185875af1925050503d80600081146130a0576040519150601f19603f3d011682016040523d82523d6000602084013e6130a5565b606091505b50915091506130b6878383876138e8565b925050505b949350505050565b80158061313d5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015613117573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061313b9190613f2c565b155b6131af5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e636500000000000000000000606482015260840161057b565b6040516001600160a01b0383166024820152604481018290526106769084907f095ea7b30000000000000000000000000000000000000000000000000000000090606401612b5d565b60606130bb8484600085612fcf565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036132e3576004546001600160a01b0316156132dc576004546001600160a01b03166370a0823161326d612d09565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa1580156132b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132d59190613f2c565b9050610d93565b5047610d93565b826001600160a01b03166370a082316132fa612d09565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401612f8e565b60008181526006602052604090205460ff16156133855760405162461bcd60e51b815260206004820152601560248201527f4d503a20616c726561647920636f6d706c657465640000000000000000000000604482015260640161057b565b6000908152600660205260409020805460ff19166001179055565b60008060006133ae87612f23565b9050881561343c5761343685858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601881527f4d503a2043616c6c5769746856616c7565206661696c6564000000000000000060208201526001600160a01b038f169392508d9150612fcf565b506134bd565b6134bb85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601781527f4d503a2046756e6374696f6e43616c6c206661696c656400000000000000000060208201526001600160a01b038f1693925090506131f8565b505b6000806000886000815181106134d5576134d56140a5565b602002602001015190506000896001815181106134f4576134f46140a5565b6020026020010151905060008a600281518110613513576135136140a5565b6020026020010151905060008b600381518110613532576135326140a5565b6020026020010151905060006135478e612f23565b90508781116135985760405162461bcd60e51b815260206004820152601e60248201527f4d503a2072656365697665722073686f756c6420676574206173736574730000604482015260640161057b565b60006135a48983613fe5565b9050848110156135f65760405162461bcd60e51b815260206004820152601d60248201527f4d503a207265636569766520616d6f756e74206e6f7420656e6f756768000000604482015260640161057b565b6136008386614073565b81101561364f5760405162461bcd60e51b815260206004820152601560248201527f4d503a20676173466565206e6f7420656e6f7567680000000000000000000000604482015260640161057b565b8361365c612710836140d8565b61366691906140fa565b9650866136738487614073565b61367d9190614073565b8110156136cc5760405162461bcd60e51b815260206004820152601260248201527f4d503a20666565206e6f7420656e6f7567680000000000000000000000000000604482015260640161057b565b826136d78883613fe5565b6136e19190613fe5565b97508588116136f057876136f2565b855b9750505050505050306001600160a01b03168a6001600160a01b03161461376f577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b03160361375b576137568a83612a35565b61376f565b61376f6001600160a01b038a168b84612b18565b909b909a5098505050505050505050565b600080546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000613832826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166131f89092919063ffffffff16565b90508051600014806138535750808060200190518101906138539190614111565b6106765760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161057b565b6000806020835110156138dd57506000928392509050565b505060200151600191565b60608315613957578251600003613950576001600160a01b0385163b6139505760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161057b565b50816130bb565b6130bb838381511561396c5781518083602001fd5b8060405162461bcd60e51b815260040161057b919061412e565b60006020828403121561399857600080fd5b5035919050565b80356001600160a01b03811681146139b657600080fd5b919050565b6000806000606084860312156139d057600080fd5b6139d98461399f565b92506139e76020850161399f565b9150604084013590509250925092565b60008083601f840112613a0957600080fd5b50813567ffffffffffffffff811115613a2157600080fd5b602083019150836020828501011115612f1c57600080fd5b600080600060408486031215613a4e57600080fd5b613a578461399f565b9250602084013567ffffffffffffffff811115613a7357600080fd5b613a7f868287016139f7565b9497909650939450505050565b801515811461292d57600080fd5b600080600080600060808688031215613ab257600080fd5b613abb8661399f565b9450602086013593506040860135613ad281613a8c565b9250606086013567ffffffffffffffff811115613aee57600080fd5b613afa888289016139f7565b969995985093965092949392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613b4a57613b4a613b0b565b604052919050565b600082601f830112613b6357600080fd5b813567ffffffffffffffff811115613b7d57613b7d613b0b565b613b90601f8201601f1916602001613b21565b818152846020838601011115613ba557600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215613bd557600080fd5b823567ffffffffffffffff80821115613bed57600080fd5b613bf986838701613b52565b93506020850135915080821115613c0f57600080fd5b50613c1c85828601613b52565b9150509250929050565b600080600060608486031215613c3b57600080fd5b613c448461399f565b9250602084013567ffffffffffffffff80821115613c6157600080fd5b613c6d87838801613b52565b93506040860135915080821115613c8357600080fd5b50613c9086828701613b52565b9150509250925092565b6000806000806000806000806000806101008b8d031215613cba57600080fd5b613cc38b61399f565b995060208b01359850613cd860408c0161399f565b9750613ce660608c0161399f565b9650613cf460808c0161399f565b955060a08b0135945060c08b013567ffffffffffffffff80821115613d1857600080fd5b613d248e838f016139f7565b909650945060e08d0135915080821115613d3d57600080fd5b50613d4a8d828e016139f7565b915080935050809150509295989b9194979a5092959850565b600080600080600060a08688031215613d7b57600080fd5b85359450613d8b6020870161399f565b9350613d996040870161399f565b92506060860135613da981613a8c565b949793965091946080013592915050565b600060208284031215613dcc57600080fd5b610e8c8261399f565b6000806000806000806000806000806101208b8d031215613df557600080fd5b8a359950613e0560208c0161399f565b9850613e1360408c0161399f565b9750613e2260608c0135613a8c565b60608b0135965060808b01359550613e3c60a08c0161399f565b9450613e4a60c08c0161399f565b935067ffffffffffffffff60e08c01351115613e6557600080fd5b60e08b01358b018c601f820112613e7b57600080fd5b67ffffffffffffffff81351115613e9457613e94613b0b565b613ea46020823560051b01613b21565b81358082526020808301929160051b8401018f811115613ec357600080fd5b6020840193505b80841015613ee5578335835260209384019390920191613eca565b509450505067ffffffffffffffff6101008c01351115613f0457600080fd5b613f158c6101008d01358d016139f7565b81935080925050509295989b9194979a5092959850565b600060208284031215613f3e57600080fd5b5051919050565b8183823760009101908152919050565b60005b83811015613f70578181015183820152602001613f58565b50506000910152565b60008151808452613f91816020860160208601613f55565b601f01601f19169290920160200192915050565b8381528215156020820152606060408201526000613fc66060830184613f79565b95945050505050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610d9357610d93613fcf565b60006001820161400a5761400a613fcf565b5060010190565b8481526001600160a01b038416602082015260606040820152816060820152818360808301376000818301608090810191909152601f909201601f191601019392505050565b60008251614069818460208701613f55565b9190910192915050565b80820180821115610d9357610d93613fcf565b600060ff821660ff810361409c5761409c613fcf565b60010192915050565b634e487b7160e01b600052603260045260246000fd5b600060ff8216806140ce576140ce613fcf565b6000190192915050565b6000826140f557634e487b7160e01b600052601260045260246000fd5b500490565b8082028115828204841417610d9357610d93613fcf565b60006020828403121561412357600080fd5b8151610e8c81613a8c565b602081526000610e8c6020830184613f7956fea2646970667358221220f5cfa92acd761df0d872b55e7a495aa14b005971cec1ee7edb27bb79b09916e764736f6c6343000811003300000000000000000000000000000000000000000000000000000000000000190000000000000000000000008a4aa176007196d48d39c89402d3753c39ae64c1000000000000000000000000d3e822f3ef011ca5f17d82c956d952d8d7c3a1bb

Deployed ByteCode

0x6080604052600436106101975760003560e01c80638456cb59116100e0578063b429afeb11610084578063d4d5ea4511610061578063d4d5ea45146104a5578063ef9bcb27146104c5578063f2fde38b146104e5578063f6a74ed71461050557005b8063b429afeb14610445578063cec7d38814610465578063d039eff21461048557005b8063a0cf0aea116100bd578063a0cf0aea146103be578063a7fc7a07146103f2578063aa271e1a14610412578063adc879e91461043257005b80638456cb591461036b5780638da5cb5b146103805780638fd903f51461039e57005b806340bdd3e911610147578063565bc23411610124578063565bc234146102dc5780635b7dd1bb146102ef578063681b19ff1461030f57806378bbe8b61461033f57005b806340bdd3e9146102785780634c314eef146102985780635342389e146102b857005b80631b8b921d116101755780631b8b921d1461023d5780633f163c47146102505780633f4ba83a1461026357005b80628e59cf146101a05780630833bc9a146101dd5780631095b6d71461021d57005b3661019e57005b005b3480156101ac57600080fd5b506007546101c0906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156101e957600080fd5b5061020d6101f8366004613986565b60009081526006602052604090205460ff1690565b60405190151581526020016101d4565b34801561022957600080fd5b5061019e6102383660046139bb565b610525565b61019e61024b366004613a39565b61067b565b61019e61025e366004613a9a565b610786565b34801561026f57600080fd5b5061019e610cd9565b34801561028457600080fd5b5061020d610293366004613bc2565b610d7d565b3480156102a457600080fd5b5061020d6102b3366004613c26565b610d99565b3480156102c457600080fd5b506102ce60085481565b6040519081526020016101d4565b61019e6102ea366004613c9a565b610e93565b3480156102fb57600080fd5b5061019e61030a366004613d63565b61149c565b34801561031b57600080fd5b5061020d61032a366004613986565b60066020526000908152604090205460ff1681565b34801561034b57600080fd5b506002546103599060ff1681565b60405160ff90911681526020016101d4565b34801561037757600080fd5b5061019e61196a565b34801561038c57600080fd5b506000546001600160a01b03166101c0565b3480156103aa57600080fd5b506004546101c0906001600160a01b031681565b3480156103ca57600080fd5b506101c07f000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b3480156103fe57600080fd5b5061019e61040d366004613dba565b6119f9565b34801561041e57600080fd5b5061020d61042d366004613dba565b611b07565b34801561043e57600080fd5b50466102ce565b34801561045157600080fd5b5061020d610460366004613dba565b611b75565b34801561047157600080fd5b5061019e610480366004613dba565b611bac565b34801561049157600080fd5b5061019e6104a0366004613dba565b611c35565b3480156104b157600080fd5b5061019e6104c0366004613dd5565b611cbe565b3480156104d157600080fd5b5061019e6104e03660046139bb565b61266c565b3480156104f157600080fd5b5061019e610500366004613dba565b61284e565b34801561051157600080fd5b5061019e610520366004613dba565b612930565b6000546001600160a01b031633146105845760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b7f000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b0316836001600160a01b0316036105e2574760008282116105cd57816105cf565b825b90506105db8482612a35565b5050505050565b6040516370a0823160e01b81523060048201526000906001600160a01b038516906370a0823190602401602060405180830381865afa158015610629573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064d9190613f2c565b9050600082821161065e5781610660565b825b90506105db6001600160a01b0386168583612b18565b505050565b6000546001600160a01b031633146106d55760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161057b565b600080846001600160a01b03163485856040516106f3929190613f45565b60006040518083038185875af1925050503d8060008114610730576040519150601f19603f3d011682016040523d82523d6000602084013e610735565b606091505b5091509150846001600160a01b03167fbb9c4c4e98e306e63e340c78eed06da47fecfc0e2e0c6e88b42aca99dc5d52c334848460405161077793929190613fa5565b60405180910390a25050505050565b61078e612b94565b60095460ff16156107ce5760405162461bcd60e51b815260206004820152600a60248201526913540e881c185d5cd95960b21b604482015260640161057b565b6107da85858484612bed565b7f000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b0316856001600160a01b031603610a71573484146108625760405162461bcd60e51b815260206004820152601560248201527f4d503a20616d6f756e7420697320696e76616c69640000000000000000000000604482015260640161057b565b6004546001600160a01b031615610a4a57600480546040516370a0823160e01b815230928101929092526000916001600160a01b03909116906370a0823190602401602060405180830381865afa1580156108c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e59190613f2c565b9050600460009054906101000a90046001600160a01b03166001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561093757600080fd5b505af115801561094b573d6000803e3d6000fd5b5050600480546040516370a0823160e01b81523092810192909252600094506001600160a01b031692506370a082319150602401602060405180830381865afa15801561099c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c09190613f2c565b9050856109cd8383613fe5565b14610a1a5760405162461bcd60e51b815260206004820152601760248201527f4d503a207761727020746f6b656e206469736d61746368000000000000000000604482015260640161057b565b610a22612ce6565b610a4357600754600454610a43916001600160a01b03918216911688612b18565b5050610c5b565b610a52612ce6565b610a6c57600754610a6c906001600160a01b031685612a35565b610c5b565b8215610c3d5760006001600160a01b0386166370a08231336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610acd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610af19190613f2c565b90506001600160a01b038616639dc29fac336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101889052604401600060405180830381600087803b158015610b4b57600080fd5b505af1158015610b5f573d6000803e3d6000fd5b505050506000866001600160a01b03166370a08231610b7b3390565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610bbf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610be39190613f2c565b9050610bef8683613fe5565b8114610a435760405162461bcd60e51b815260206004820152600f60248201527f4d503a206275726e206661696c65640000000000000000000000000000000000604482015260640161057b565b610c5b33610c49612d09565b6001600160a01b038816919087612d32565b60088054906000610c6b83613ff8565b9091555050600854336001600160a01b0387167f873a952504255baba041a0843512f2748152611db0d25da60657af220f7540ba8787610cb257610cad612d09565b610cb5565b60005b8787604051610cc79493929190614011565b60405180910390a46105db6001600355565b6000546001600160a01b03163314610d335760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161057b565b6009805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6000818051906020012083805190602001201490505b92915050565b6000806000610da786612d83565b91509150818015610dc057506001600160a01b03811630145b15610dd057600192505050610e8c565b600080610ddd8830612e3f565b91509150818015610deb5750805b15610dfd576001945050505050610e8c565b865115610e8357600080896001600160a01b031689604051610e1f9190614057565b600060405180830381855afa9150503d8060008114610e5a576040519150601f19603f3d011682016040523d82523d6000602084013e610e5f565b606091505b5091509150818015610e765750610e768189610d7d565b9650505050505050610e8c565b60009450505050505b9392505050565b610e9b612b94565b60095460ff1615610edb5760405162461bcd60e51b815260206004820152600a60248201526913540e881c185d5cd95960b21b604482015260640161057b565b610ee78a8a8484612bed565b6001600160a01b0388163014801590610f0857506001600160a01b03881615155b610f545760405162461bcd60e51b815260206004820152601560248201527f4d503a2074617267657420697320696e76616c69640000000000000000000000604482015260640161057b565b82610fa15760405162461bcd60e51b815260206004820152601560248201527f4d503a2063616c6c6461746120697320656d7074790000000000000000000000604482015260640161057b565b6001600160a01b038716610ff75760405162461bcd60e51b815260206004820152601960248201527f4d503a2072656365697665546f6b656e20697320656d70747900000000000000604482015260640161057b565b6001600160a01b03861661104d5760405162461bcd60e51b815260206004820152601560248201527f4d503a20726563656976657220697320656d7074790000000000000000000000604482015260640161057b565b6000851161109d5760405162461bcd60e51b815260206004820152601660248201527f4d503a206d696e416d6f756e7420697320656d70747900000000000000000000604482015260640161057b565b60006110a888612f23565b90507f000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b03168b6001600160a01b0316036111b857348a146111325760405162461bcd60e51b815260206004820152601560248201527f4d503a20616d6f756e7420697320696e76616c69640000000000000000000000604482015260640161057b565b6111b285858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601881527f4d503a2043616c6c5769746856616c7565206661696c6564000000000000000060208201526001600160a01b038e169392508e9150612fcf565b506112e0565b6111cd6001600160a01b038c1633308d612d32565b604051636eb1769f60e11b81523060048201526001600160a01b038a811660248301528b91908d169063dd62ed3e90604401602060405180830381865afa15801561121c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112409190613f2c565b101561125f5760055461125f906001600160a01b038d16908b906130c3565b6112de85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601781527f4d503a2046756e6374696f6e43616c6c206661696c656400000000000000000060208201526001600160a01b038e1693925090506131f8565b505b6000806112ec8a612f23565b90508281116113625760405162461bcd60e51b8152602060048201526024808201527f4d503a207265636569766520616d6f756e742073686f756c642061626f76652060448201527f7a65726f00000000000000000000000000000000000000000000000000000000606482015260840161057b565b61136c8382613fe5565b9150878210156113be5760405162461bcd60e51b815260206004820152601d60248201527f4d503a207265636569766520616d6f756e74206e6f7420656e6f756768000000604482015260640161057b565b7f000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b03168a6001600160a01b031603611406576114018983612a35565b61141a565b61141a6001600160a01b038b168a84612b18565b6008805490600061142a83613ff8565b9091555050600854336001600160a01b03168b6001600160a01b03167f873a952504255baba041a0843512f2748152611db0d25da60657af220f7540ba858d8a8a60405161147b9493929190614011565b60405180910390a45050506114906001600355565b50505050505050505050565b6114a533611b75565b6114f15760405162461bcd60e51b815260206004820152601460248201527f6e6f20636f6e74726f6c6c657220726967687473000000000000000000000000604482015260640161057b565b60095460ff16156115315760405162461bcd60e51b815260206004820152600a60248201526913540e881c185d5cd95960b21b604482015260640161057b565b600085116115815760405162461bcd60e51b815260206004820152601160248201527f4d503a206f72646572494420656d707479000000000000000000000000000000604482015260640161057b565b6001600160a01b0383166115d75760405162461bcd60e51b815260206004820152601460248201527f4d503a20726563656976657220696e7661696c64000000000000000000000000604482015260640161057b565b600081116116275760405162461bcd60e51b815260206004820152601360248201527f4d503a20616d6f756e7420697320656d70747900000000000000000000000000604482015260640161057b565b81611684578061163685613207565b10156116845760405162461bcd60e51b815260206004820152601860248201527f4d503a20696e73756666696369656e742062616c616e63650000000000000000604482015260640161057b565b61168d85613326565b7f000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b0316846001600160a01b031603611729576004546001600160a01b03161561171f576116df612ce6565b15611700576004546116fb906001600160a01b03168483612b18565b611901565b6116fb61170b612d09565b6004546001600160a01b0316908584612d32565b6116fb8382612a35565b81156118c3576040516370a0823160e01b81526001600160a01b038481166004830152600091908616906370a0823190602401602060405180830381865afa158015611779573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061179d9190613f2c565b6040516340c10f1960e01b81526001600160a01b03868116600483015260248201859052919250908616906340c10f1990604401600060405180830381600087803b1580156117eb57600080fd5b505af11580156117ff573d6000803e3d6000fd5b50506040516370a0823160e01b81526001600160a01b03878116600483015260009350881691506370a0823190602401602060405180830381865afa15801561184c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118709190613f2c565b905061187c8383614073565b81146118bc5760405162461bcd60e51b815260206004820152600f60248201526e13540e881b5a5b9d0819985a5b1959608a1b604482015260640161057b565b5050611901565b6118cb612ce6565b156118e4576116fb6001600160a01b0385168483612b18565b6119016118ef612d09565b6001600160a01b038616908584612d32565b826001600160a01b031685856001600160a01b03167f74aaf2992820754761f714bb3dcf12d7e3bb2e5f41949629e2e88a4a219e20478460008060405161195b939291909283526020830191909152604082015260600190565b60405180910390a45050505050565b6000546001600160a01b031633146119c45760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161057b565b6009805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610d603390565b6000546001600160a01b03163314611a535760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161057b565b6001600160a01b03811660009081526001602052604081205460ff1615159003611ac7576001600160a01b03811660009081526001602081905260408220805460ff191690911790556002805460ff1691611aad83614086565b91906101000a81548160ff021916908360ff160217905550505b6040516001600160a01b03821681527f0a8bb31534c0ed46f380cb867bd5c803a189ced9a764e30b3a4991a9901d7474906020015b60405180910390a150565b6000806000611b1584612d83565b91509150818015611b2e57506001600160a01b03811630145b15611b3d575060019392505050565b600080611b4a8630612e3f565b91509150818015611b585750805b15611b695750600195945050505050565b50600095945050505050565b600080546001600160a01b0383811691161480610d935750506001600160a01b031660009081526001602052604090205460ff1690565b6000546001600160a01b03163314611c065760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161057b565b6004805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6000546001600160a01b03163314611c8f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161057b565b6007805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b611cc733611b75565b611d135760405162461bcd60e51b815260206004820152601460248201527f6e6f20636f6e74726f6c6c657220726967687473000000000000000000000000604482015260640161057b565b60095460ff1615611d535760405162461bcd60e51b815260206004820152600a60248201526913540e881c185d5cd95960b21b604482015260640161057b565b60008a11611da35760405162461bcd60e51b815260206004820152601160248201527f4d503a206f72646572494420656d707479000000000000000000000000000000604482015260640161057b565b80611df05760405162461bcd60e51b815260206004820152600e60248201527f4d503a206461746120656d707479000000000000000000000000000000000000604482015260640161057b565b8251600414611e415760405162461bcd60e51b815260206004820152601160248201527f4d503a2066656573206d69736d61746368000000000000000000000000000000604482015260640161057b565b60008611611e915760405162461bcd60e51b815260206004820152601360248201527f4d503a20616d6f756e7420697320656d70747900000000000000000000000000604482015260640161057b565b600083600181518110611ea657611ea66140a5565b602002602001015111611efb5760405162461bcd60e51b815260206004820152601660248201527f4d503a206d696e416d6f756e7420697320656d70747900000000000000000000604482015260640161057b565b600083600081518110611f1057611f106140a5565b602002602001015111611f655760405162461bcd60e51b815260206004820152601960248201527f4d503a20657870656374416d6f756e7420697320656d70747900000000000000604482015260640161057b565b86611fc25785611f748a613207565b1015611fc25760405162461bcd60e51b815260206004820152601860248201527f4d503a20696e73756666696369656e742062616c616e63650000000000000000604482015260640161057b565b6001600160a01b0385166120185760405162461bcd60e51b815260206004820152601560248201527f4d503a20726563656976657220697320656d7074790000000000000000000000604482015260640161057b565b6001600160a01b038816301480159061203957506001600160a01b03881615155b6120855760405162461bcd60e51b815260206004820152601260248201527f4d503a20746f4164647220696e7661696c640000000000000000000000000000604482015260640161057b565b61208e8a613326565b60007f000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b03168a6001600160a01b0316149050801561223a576004546001600160a01b0316156121e5576120e6612ce6565b612109576121096120f5612d09565b6004546001600160a01b031690308a612d32565b600480546040517f2e1a7d4d00000000000000000000000000000000000000000000000000000000815291820189905247916001600160a01b0390911690632e1a7d4d90602401600060405180830381600087803b15801561216a57600080fd5b505af115801561217e573d6000803e3d6000fd5b504792508a915061219190508383613fe5565b146121de5760405162461bcd60e51b815260206004820181905260248201527f4d503a206e617469766520746f6b656e20616d6f756e74206469736d61746368604482015260640161057b565b5050612485565b864710156122355760405162461bcd60e51b815260206004820152601b60248201527f4d503a206e617469766520746f6b656e20696e7375666669656e740000000000604482015260640161057b565b612485565b87156123cc576040516370a0823160e01b81523060048201526000906001600160a01b038c16906370a0823190602401602060405180830381865afa158015612287573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122ab9190613f2c565b6040516340c10f1960e01b8152306004820152602481018a90529091506001600160a01b038c16906340c10f1990604401600060405180830381600087803b1580156122f657600080fd5b505af115801561230a573d6000803e3d6000fd5b50506040516370a0823160e01b8152306004820152600092506001600160a01b038e1691506370a0823190602401602060405180830381865afa158015612355573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123799190613f2c565b90506123858983614073565b81146123c55760405162461bcd60e51b815260206004820152600f60248201526e13540e881b5a5b9d0819985a5b1959608a1b604482015260640161057b565b50506123f3565b6123d4612ce6565b6123f3576007546123f3906001600160a01b038c81169116308a612d32565b604051636eb1769f60e11b81523060048201526001600160a01b038a811660248301528891908c169063dd62ed3e90604401602060405180830381865afa158015612442573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124669190613f2c565b101561248557600554612485906001600160a01b038c16908b906130c3565b6000806124a48b8461249857600061249a565b8a5b8a8a8a8a8a6133a0565b915091506000866003815181106124bd576124bd6140a5565b6020026020010151826124d09190614073565b905080156125e1577f000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b0316886001600160a01b0316036125c7576004546001600160a01b0316156125c25760048054604080517fd0e30db000000000000000000000000000000000000000000000000000000000815290516001600160a01b039092169263d0e30db0928592808301926000929182900301818588803b15801561258057600080fd5b505af1158015612594573d6000803e3d6000fd5b50505050506125a1612ce6565b6125c2576007546004546125c2916001600160a01b03918216911683612b18565b6125e1565b6007546125e1906001600160a01b038a8116911683612b18565b886001600160a01b03168e896001600160a01b03167f74aaf2992820754761f714bb3dcf12d7e3bb2e5f41949629e2e88a4a219e204786868c60038151811061262c5761262c6140a5565b6020026020010151604051612654939291909283526020830191909152604082015260600190565b60405180910390a45050505050505050505050505050565b61267533611b75565b6126c15760405162461bcd60e51b815260206004820152601460248201527f6e6f20636f6e74726f6c6c657220726967687473000000000000000000000000604482015260640161057b565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908516906370a0823190602401602060405180830381865afa15801561270b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061272f9190613f2c565b6040516340c10f1960e01b81526001600160a01b03858116600483015260248201859052919250908516906340c10f1990604401600060405180830381600087803b15801561277d57600080fd5b505af1158015612791573d6000803e3d6000fd5b50506040516370a0823160e01b81526001600160a01b03868116600483015260009350871691506370a0823190602401602060405180830381865afa1580156127de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128029190613f2c565b905061280e8383614073565b81146105db5760405162461bcd60e51b815260206004820152600f60248201526e13540e881b5a5b9d0819985a5b1959608a1b604482015260640161057b565b6000546001600160a01b031633146128a85760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161057b565b6001600160a01b0381166129245760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161057b565b61292d81613780565b50565b6000546001600160a01b0316331461298a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161057b565b6001600160a01b03811660009081526001602081905260409091205460ff16151590036129fc576001600160a01b0381166000908152600160205260408120805460ff191690556002805460ff16916129e2836140bb565b91906101000a81548160ff021916908360ff160217905550505b6040516001600160a01b03821681527f33d83959be2573f5453b12eb9d43b3499bc57d96bd2f067ba44803c859e8111390602001611afc565b604080516000808252602082019092526001600160a01b038416908390604051612a5f9190614057565b60006040518083038185875af1925050503d8060008114612a9c576040519150601f19603f3d011682016040523d82523d6000602084013e612aa1565b606091505b50509050806106765760405162461bcd60e51b815260206004820152602660248201527f5472616e7366657248656c7065723a204e41544956455f5452414e534645525f60448201527f4641494c45440000000000000000000000000000000000000000000000000000606482015260840161057b565b6040516001600160a01b0383166024820152604481018290526106769084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526137dd565b600260035403612be65760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161057b565b6002600355565b6001600160a01b038416612c435760405162461bcd60e51b815260206004820152601b60248201527f4d503a20746f6b656e4164647265737320697320696e76616c69640000000000604482015260640161057b565b60008311612c935760405162461bcd60e51b815260206004820152600f60248201527f4d503a20616d6f756e7420697320300000000000000000000000000000000000604482015260640161057b565b80612ce05760405162461bcd60e51b815260206004820152601260248201527f4d503a206f7264657220697320656d7074790000000000000000000000000000604482015260640161057b565b50505050565b6000612cf0612d09565b6001600160a01b0316306001600160a01b031614905090565b6007546000906001600160a01b031615612d2d57506007546001600160a01b031690565b503090565b6040516001600160a01b0380851660248301528316604482015260648101829052612ce09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401612b5d565b60408051600481526024810182526020810180516001600160e01b03167ff77c47910000000000000000000000000000000000000000000000000000000017905290516000918291829182916001600160a01b03871691612de391614057565b600060405180830381855afa9150503d8060008114612e1e576040519150601f19603f3d011682016040523d82523d6000602084013e612e23565b606091505b509150915081612e34826020015190565b935093505050915091565b604080516001600160a01b0383811660248084019190915283518084039091018152604490920183526020820180516001600160e01b03167fb429afeb000000000000000000000000000000000000000000000000000000001790529151600092839283928392881691612eb291614057565b600060405180830381855afa9150503d8060008114612eed576040519150601f19603f3d011682016040523d82523d6000602084013e612ef2565b606091505b5091509150600080612f03836138c5565b91509150838015612f115750815b955060011493505050505b9250929050565b6000807f000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b0316836001600160a01b031603612f66575047610d93565b6040516370a0823160e01b81523060048201526001600160a01b038416906370a08231906024015b602060405180830381865afa158015612fab573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8c9190613f2c565b6060824710156130475760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840161057b565b600080866001600160a01b031685876040516130639190614057565b60006040518083038185875af1925050503d80600081146130a0576040519150601f19603f3d011682016040523d82523d6000602084013e6130a5565b606091505b50915091506130b6878383876138e8565b925050505b949350505050565b80158061313d5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015613117573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061313b9190613f2c565b155b6131af5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e636500000000000000000000606482015260840161057b565b6040516001600160a01b0383166024820152604481018290526106769084907f095ea7b30000000000000000000000000000000000000000000000000000000090606401612b5d565b60606130bb8484600085612fcf565b6000807f000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b0316836001600160a01b0316036132e3576004546001600160a01b0316156132dc576004546001600160a01b03166370a0823161326d612d09565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa1580156132b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132d59190613f2c565b9050610d93565b5047610d93565b826001600160a01b03166370a082316132fa612d09565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401612f8e565b60008181526006602052604090205460ff16156133855760405162461bcd60e51b815260206004820152601560248201527f4d503a20616c726561647920636f6d706c657465640000000000000000000000604482015260640161057b565b6000908152600660205260409020805460ff19166001179055565b60008060006133ae87612f23565b9050881561343c5761343685858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601881527f4d503a2043616c6c5769746856616c7565206661696c6564000000000000000060208201526001600160a01b038f169392508d9150612fcf565b506134bd565b6134bb85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601781527f4d503a2046756e6374696f6e43616c6c206661696c656400000000000000000060208201526001600160a01b038f1693925090506131f8565b505b6000806000886000815181106134d5576134d56140a5565b602002602001015190506000896001815181106134f4576134f46140a5565b6020026020010151905060008a600281518110613513576135136140a5565b6020026020010151905060008b600381518110613532576135326140a5565b6020026020010151905060006135478e612f23565b90508781116135985760405162461bcd60e51b815260206004820152601e60248201527f4d503a2072656365697665722073686f756c6420676574206173736574730000604482015260640161057b565b60006135a48983613fe5565b9050848110156135f65760405162461bcd60e51b815260206004820152601d60248201527f4d503a207265636569766520616d6f756e74206e6f7420656e6f756768000000604482015260640161057b565b6136008386614073565b81101561364f5760405162461bcd60e51b815260206004820152601560248201527f4d503a20676173466565206e6f7420656e6f7567680000000000000000000000604482015260640161057b565b8361365c612710836140d8565b61366691906140fa565b9650866136738487614073565b61367d9190614073565b8110156136cc5760405162461bcd60e51b815260206004820152601260248201527f4d503a20666565206e6f7420656e6f7567680000000000000000000000000000604482015260640161057b565b826136d78883613fe5565b6136e19190613fe5565b97508588116136f057876136f2565b855b9750505050505050306001600160a01b03168a6001600160a01b03161461376f577f000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b0316896001600160a01b03160361375b576137568a83612a35565b61376f565b61376f6001600160a01b038a168b84612b18565b909b909a5098505050505050505050565b600080546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000613832826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166131f89092919063ffffffff16565b90508051600014806138535750808060200190518101906138539190614111565b6106765760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161057b565b6000806020835110156138dd57506000928392509050565b505060200151600191565b60608315613957578251600003613950576001600160a01b0385163b6139505760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161057b565b50816130bb565b6130bb838381511561396c5781518083602001fd5b8060405162461bcd60e51b815260040161057b919061412e565b60006020828403121561399857600080fd5b5035919050565b80356001600160a01b03811681146139b657600080fd5b919050565b6000806000606084860312156139d057600080fd5b6139d98461399f565b92506139e76020850161399f565b9150604084013590509250925092565b60008083601f840112613a0957600080fd5b50813567ffffffffffffffff811115613a2157600080fd5b602083019150836020828501011115612f1c57600080fd5b600080600060408486031215613a4e57600080fd5b613a578461399f565b9250602084013567ffffffffffffffff811115613a7357600080fd5b613a7f868287016139f7565b9497909650939450505050565b801515811461292d57600080fd5b600080600080600060808688031215613ab257600080fd5b613abb8661399f565b9450602086013593506040860135613ad281613a8c565b9250606086013567ffffffffffffffff811115613aee57600080fd5b613afa888289016139f7565b969995985093965092949392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613b4a57613b4a613b0b565b604052919050565b600082601f830112613b6357600080fd5b813567ffffffffffffffff811115613b7d57613b7d613b0b565b613b90601f8201601f1916602001613b21565b818152846020838601011115613ba557600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215613bd557600080fd5b823567ffffffffffffffff80821115613bed57600080fd5b613bf986838701613b52565b93506020850135915080821115613c0f57600080fd5b50613c1c85828601613b52565b9150509250929050565b600080600060608486031215613c3b57600080fd5b613c448461399f565b9250602084013567ffffffffffffffff80821115613c6157600080fd5b613c6d87838801613b52565b93506040860135915080821115613c8357600080fd5b50613c9086828701613b52565b9150509250925092565b6000806000806000806000806000806101008b8d031215613cba57600080fd5b613cc38b61399f565b995060208b01359850613cd860408c0161399f565b9750613ce660608c0161399f565b9650613cf460808c0161399f565b955060a08b0135945060c08b013567ffffffffffffffff80821115613d1857600080fd5b613d248e838f016139f7565b909650945060e08d0135915080821115613d3d57600080fd5b50613d4a8d828e016139f7565b915080935050809150509295989b9194979a5092959850565b600080600080600060a08688031215613d7b57600080fd5b85359450613d8b6020870161399f565b9350613d996040870161399f565b92506060860135613da981613a8c565b949793965091946080013592915050565b600060208284031215613dcc57600080fd5b610e8c8261399f565b6000806000806000806000806000806101208b8d031215613df557600080fd5b8a359950613e0560208c0161399f565b9850613e1360408c0161399f565b9750613e2260608c0135613a8c565b60608b0135965060808b01359550613e3c60a08c0161399f565b9450613e4a60c08c0161399f565b935067ffffffffffffffff60e08c01351115613e6557600080fd5b60e08b01358b018c601f820112613e7b57600080fd5b67ffffffffffffffff81351115613e9457613e94613b0b565b613ea46020823560051b01613b21565b81358082526020808301929160051b8401018f811115613ec357600080fd5b6020840193505b80841015613ee5578335835260209384019390920191613eca565b509450505067ffffffffffffffff6101008c01351115613f0457600080fd5b613f158c6101008d01358d016139f7565b81935080925050509295989b9194979a5092959850565b600060208284031215613f3e57600080fd5b5051919050565b8183823760009101908152919050565b60005b83811015613f70578181015183820152602001613f58565b50506000910152565b60008151808452613f91816020860160208601613f55565b601f01601f19169290920160200192915050565b8381528215156020820152606060408201526000613fc66060830184613f79565b95945050505050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610d9357610d93613fcf565b60006001820161400a5761400a613fcf565b5060010190565b8481526001600160a01b038416602082015260606040820152816060820152818360808301376000818301608090810191909152601f909201601f191601019392505050565b60008251614069818460208701613f55565b9190910192915050565b80820180821115610d9357610d93613fcf565b600060ff821660ff810361409c5761409c613fcf565b60010192915050565b634e487b7160e01b600052603260045260246000fd5b600060ff8216806140ce576140ce613fcf565b6000190192915050565b6000826140f557634e487b7160e01b600052601260045260246000fd5b500490565b8082028115828204841417610d9357610d93613fcf565b60006020828403121561412357600080fd5b8151610e8c81613a8c565b602081526000610e8c6020830184613f7956fea2646970667358221220f5cfa92acd761df0d872b55e7a495aa14b005971cec1ee7edb27bb79b09916e764736f6c63430008110033