false
false
0

Contract Address Details

0x3eBCEE85AcA5e4bBd98D38310218CdA47055F240

Contract Name
Launchpad
Creator
0xc7d98c–7f3521 at 0x885e98–e50880
Balance
0 CLO
Tokens
Fetching tokens...
Transactions
0 Transactions
Transfers
0 Transfers
Gas Used
Fetching gas used...
Last Balance Update
18644643
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
Contract name:
Launchpad




Optimization enabled
true
Compiler version
v0.8.19+commit.7dd6d404




Optimization runs
200
EVM Version
paris




Verified at
2025-01-26T20:02:52.922365Z

Launchpad.sol

// SPDX-License-Identifier: No License (None)
pragma solidity 0.8.19;

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable {
    address internal _owner;

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor () {
        _owner = msg.sender;
        emit OwnershipTransferred(address(0), msg.sender);
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == msg.sender, "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
}

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

interface IVesting {
    function initialize(address owner_, address vestedToken_) external;
    function allocateTokens(
        address to, // beneficiary of tokens
        uint256 amount, // amount of token to lock on vesting contract
        uint256 cliffFinish,       // Timestamp (unix time) when starts vesting. First vesting will be at this time
        uint256 vestingPercentage,  // percentage (with 2 decimals) of tokens will be unlocked every interval (i.e. 10% per 30 days)
        uint256 vestingInterval     // interval (in seconds) of vesting (i.e. 30 days)
    ) external;
}

contract Launchpad is Ownable {
    address public vestingImplementation;

    struct VestingParams {
        uint256 unlockPercentage; // percentage (with 2 decimals) of initially unlocked token. I.e. 500 means 5% unlocked and 95% will go to vesting, 10000 means 100% unlocked (vesting will not be used)
        uint256 cliffPeriod;    // cliff period (in seconds). The first release will be after this time.
        uint256 vestingPercentage;        // percentage (with 2 decimals) of locked tokens will be unlocked every interval I.e. 500 means 5% per vestingInterval
        uint256 vestingInterval;     // interval (in seconds) of vesting (i.e. 2592000 = 30 days)        
    }

    struct ICOParams {
        address token;      // ICO token
        address paymentToken;   // if address(0) - native coin
        uint256 amount;     // amount of token to sell
        uint256 startPrice; // price of 1 token in paymentTokens
        uint256 endPrice;   // if 0 then price is fixed, else price grows liner from startPrice to endPrice based on sold tokens.
        uint256 startDate; // timestamp when ICO starts. The date must be in future.
        uint256 endDate;   // timestamp when ICO ends, if 0 then ICO will be active until sell all tokens
        uint256 bonusReserve;  // amount of tokens that will be used for bonus. Bonus will be paid until it's available
        uint256 bonusPercentage;  // percent of bonus (with 2 decimals) which will be added to bought amount. I.e. 2500 = 25%
        uint256 bonusActivator;   // percent of total ICO tokens that should be bought to activate bonus (with 2 decimals). I.e. 1000 = 10% 
        // Let say total amount of tokens on this ICO is 1,000,000, so to receive bonus a user should buy at least 100,000 tokens at ones (10%) 

        VestingParams vestingParams;   // parameters of vesting
    }


    struct ICOState {
        address ICOOwner;   //  address of ICO owner (creator) who will receive payment tokens
        uint8 icoTokenDecimals; // number decimals of ICO token (get from token.decimals())
        address vestingContract;    //  address of vesting contract
        bool isClosed;      // ICO is closed
        uint256 totalSold;  // total amount of sold tokens
        uint256 totalReceived;   // total amount received (in paymentToken)
    }

    mapping (address token => address vestingContract) public vestingContracts;
    mapping (uint256 ICOid => ICOParams) public icoParams;
    mapping (uint256 ICOid => ICOState) public icoState;
    uint256 public counter; // counter of ICOs
    bool public isPaused;    // launchpad is paused

    event BuyToken(address buyer, uint256 ICO_id, uint256 amountPaid, uint256 amountBought, uint256 bonus);
    event ICOCreated(uint256 ICO_id, address token, address owner, address vestingContract);
    event CloseICO(uint256 ICO_id, address owner, address token, uint256 refund);

    // initialize if use upgradable proxy
    function initialize(address vestingImplementation_) external {
        require(_owner == address(0), "Already init");
        _owner = msg.sender;
        emit OwnershipTransferred(address(0), msg.sender);
        vestingImplementation = vestingImplementation_;
    }

    modifier checkICO(uint256 id) {
        require(block.timestamp >= icoParams[id].startDate, "ICO is not started yet");
        require(block.timestamp <= icoParams[id].endDate || icoParams[id].endDate == 0, "ICO is finished");
        require(!icoState[id].isClosed, "ICO is closed");
        require(!isPaused, "Launchpad is paused");
        _;
    }

    // returns ICO details by ICO id
    function getICO(uint256 id) external view returns(ICOParams memory params, ICOState memory state) {
        params = icoParams[id];
        state = icoState[id];
    }

    // returns value of tokens to pay for tokens amount
    function getValue(
        uint256 id,     // ICO id
        uint256 amount  // amount of ICO tokens to buy
    ) public view returns(
        uint256 availableAmount, // amount of available tokens (in case if ICO has less tokens then requested)
        uint256 value // value that user have to pay in paymentToken for availableAmount
    ) {
        uint256 total = icoParams[id].amount;
        uint256 sold = icoState[id].totalSold;
        availableAmount = total - sold;
        if (amount < availableAmount) availableAmount = amount;
        uint256 endPrice = icoParams[id].endPrice;
        if (endPrice == 0) {    // fix price
            value = availableAmount * icoParams[id].startPrice / (10**icoState[id].icoTokenDecimals);
        } else {    // liner growing price
            uint256 startPrice = icoParams[id].startPrice;
            uint256 currentPrice = startPrice + ((endPrice - startPrice) * sold / total);
            endPrice = startPrice + ((endPrice - startPrice) * (sold + availableAmount) / total);   // price after purchase
            value = availableAmount * (currentPrice + endPrice) / (2 * 10**icoState[id].icoTokenDecimals);
        }
    }

    // create new ICO. User should approve ICO tokens (amount + bonusReserve)
    function createICO(ICOParams memory params) external {
        safeTransferFrom(params.token, msg.sender, address(this), params.amount + params.bonusReserve);
        uint256 id = counter;
        ++counter;
        icoParams[id] = params;
        icoState[id].ICOOwner = msg.sender;
        icoState[id].icoTokenDecimals = IERC20(params.token).decimals();

        require(params.vestingParams.unlockPercentage <= 10000, "Incorrect unlockPercentage");
        address vc;
        if (params.vestingParams.unlockPercentage < 10000) {
            // use vesting
            vc = vestingContracts[params.token];
            if(vc == address(0)) {
                vc = clone(vestingImplementation);
                IVesting(vc).initialize(msg.sender, params.token);
                vestingContracts[params.token] = vc;
            }
            icoState[id].vestingContract = vc;
        }
        emit ICOCreated(id, params.token, msg.sender, vc);
    }

    // Buy ICO tokens. The value of paymentToken should be approved to ICO contract
    function buyToken(
        uint256 id,     // ICO id
        uint256 amountToBuy,    // amount of token to buy
        address buyer           // buyer address
    ) external payable checkICO(id) {
        require(buyer != address(0), "Incorrect buyer");
        uint256 amountToPay;
        (amountToBuy, amountToPay) = getValue(id, amountToBuy);
        require(amountToBuy != 0, "sold out");

        ICOParams storage p = icoParams[id];
        ICOState storage s = icoState[id];
        address paymentToken = p.paymentToken;
        if(paymentToken == address(0)) {    // pay with native coin
            require(msg.value >= amountToPay, "Low payment");
            if (msg.value > amountToPay) safeTransferETH(msg.sender, msg.value - amountToPay);  // return rest
            safeTransferETH(s.ICOOwner, amountToPay);
        } else {    // pay with tokens
            safeTransferFrom(paymentToken, msg.sender, s.ICOOwner, amountToPay);
        }
        s.totalReceived += amountToPay;
        s.totalSold += amountToBuy;

        // calculate bonus
        uint256 bonus;
        {
        uint256 bonusReserve = p.bonusReserve;
        if (bonusReserve != 0) {
            if(p.amount * p.bonusActivator / 10000 <= amountToBuy) {
                bonus = amountToBuy * p.bonusPercentage / 10000;
                if (bonusReserve < bonus) bonus = bonusReserve;
                p.bonusReserve -= bonus;
            }
        }
        }

        uint256 unlockedAmount = amountToBuy + bonus;
        if(s.vestingContract != address(0)) {
            // set vesting
            uint256 cliffFinish = block.timestamp + p.vestingParams.cliffPeriod;
            unlockedAmount = unlockedAmount * p.vestingParams.unlockPercentage / 10000;
            uint256 lockedAmount = amountToBuy + bonus - unlockedAmount;
            if (lockedAmount != 0) {
                safeApprove(p.token, s.vestingContract, lockedAmount);
                IVesting(s.vestingContract).allocateTokens(buyer, lockedAmount, cliffFinish, p.vestingParams.vestingPercentage, p.vestingParams.vestingInterval);
            }
        }
        safeTransfer(p.token, buyer, unlockedAmount);
        emit BuyToken(buyer, id, amountToPay, amountToBuy, bonus);
    }    

    // allow ICO owner to close ICO and get back unsold tokens
    function closeICO(uint256 id) external {
        ICOParams storage p = icoParams[id];
        ICOState storage s = icoState[id];
        require(s.ICOOwner == msg.sender, "Only ICO owner");
        require(!s.isClosed, "Already closed");
        s.isClosed = true;
        uint256 value = p.amount - s.totalSold + p.bonusReserve;    // refund leftover tokens
        p.amount = s.totalSold;
        p.bonusReserve = 0;
        safeTransfer(p.token, msg.sender, value);
        emit CloseICO(id, msg.sender, p.token, value);
    }

    // Launchpad owner's functions
    function setPauseLaunchpad(bool pause) external onlyOwner {
        isPaused = pause;
    }

    function setVestingImplementation(address vestingImplementation_) external onlyOwner {
        vestingImplementation = vestingImplementation_;
    }

    event Rescue(address _token, uint256 _amount);
    function rescueTokens(address _token) onlyOwner external {
        uint256 amount;
        if (_token == address(0)) {
            amount = address(this).balance;
            safeTransferETH(msg.sender, amount);
        } else {
            amount = IERC20(_token).balanceOf(address(this));
            safeTransfer(_token, msg.sender, amount);
        }
        emit Rescue(_token, amount);
    }

    /**
     * @dev A clone instance deployment failed.
     */
    error ERC1167FailedCreateClone();

    /**
     * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
     *
     * This function uses the create opcode, which should never revert.
     */
    function clone(address implementation) internal returns (address instance) {
        /// @solidity memory-safe-assembly
        assembly {
            // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes
            // of the `implementation` address with the bytecode before the address.
            mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))
            // Packs the remaining 17 bytes of `implementation` with the bytecode after the address.
            mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3))
            instance := create(0, 0x09, 0x37)
        }
        if (instance == address(0)) {
            revert ERC1167FailedCreateClone();
        }
    }

    // allow to receive ERC223 tokens
    function tokenReceived(address, uint256, bytes memory) external virtual returns(bytes4) {
        return this.tokenReceived.selector;
    }

    function safeApprove(address token, address to, uint value) internal {
        // bytes4(keccak256(bytes('approve(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED');
    }
    
    function safeTransfer(address token, address to, uint value) internal {
        // bytes4(keccak256(bytes('transfer(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED');
    }

    function safeTransferFrom(address token, address from, address to, uint value) internal {
        // bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED');
    }

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

Compiler Settings

{"outputSelection":{"*":{"*":["abi","metadata","devdoc","userdoc","storageLayout","evm.legacyAssembly","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers","evm.gasEstimates","evm.assembly"],"":["ast"]}},"optimizer":{"runs":200,"enabled":true},"libraries":{},"evmVersion":"paris"}
              

Contract ABI

[{"type":"error","name":"ERC1167FailedCreateClone","inputs":[]},{"type":"event","name":"BuyToken","inputs":[{"type":"address","name":"buyer","internalType":"address","indexed":false},{"type":"uint256","name":"ICO_id","internalType":"uint256","indexed":false},{"type":"uint256","name":"amountPaid","internalType":"uint256","indexed":false},{"type":"uint256","name":"amountBought","internalType":"uint256","indexed":false},{"type":"uint256","name":"bonus","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"CloseICO","inputs":[{"type":"uint256","name":"ICO_id","internalType":"uint256","indexed":false},{"type":"address","name":"owner","internalType":"address","indexed":false},{"type":"address","name":"token","internalType":"address","indexed":false},{"type":"uint256","name":"refund","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"ICOCreated","inputs":[{"type":"uint256","name":"ICO_id","internalType":"uint256","indexed":false},{"type":"address","name":"token","internalType":"address","indexed":false},{"type":"address","name":"owner","internalType":"address","indexed":false},{"type":"address","name":"vestingContract","internalType":"address","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":"Rescue","inputs":[{"type":"address","name":"_token","internalType":"address","indexed":false},{"type":"uint256","name":"_amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"payable","outputs":[],"name":"buyToken","inputs":[{"type":"uint256","name":"id","internalType":"uint256"},{"type":"uint256","name":"amountToBuy","internalType":"uint256"},{"type":"address","name":"buyer","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"closeICO","inputs":[{"type":"uint256","name":"id","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"counter","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"createICO","inputs":[{"type":"tuple","name":"params","internalType":"struct Launchpad.ICOParams","components":[{"type":"address","name":"token","internalType":"address"},{"type":"address","name":"paymentToken","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"startPrice","internalType":"uint256"},{"type":"uint256","name":"endPrice","internalType":"uint256"},{"type":"uint256","name":"startDate","internalType":"uint256"},{"type":"uint256","name":"endDate","internalType":"uint256"},{"type":"uint256","name":"bonusReserve","internalType":"uint256"},{"type":"uint256","name":"bonusPercentage","internalType":"uint256"},{"type":"uint256","name":"bonusActivator","internalType":"uint256"},{"type":"tuple","name":"vestingParams","internalType":"struct Launchpad.VestingParams","components":[{"type":"uint256","name":"unlockPercentage","internalType":"uint256"},{"type":"uint256","name":"cliffPeriod","internalType":"uint256"},{"type":"uint256","name":"vestingPercentage","internalType":"uint256"},{"type":"uint256","name":"vestingInterval","internalType":"uint256"}]}]}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"params","internalType":"struct Launchpad.ICOParams","components":[{"type":"address","name":"token","internalType":"address"},{"type":"address","name":"paymentToken","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"startPrice","internalType":"uint256"},{"type":"uint256","name":"endPrice","internalType":"uint256"},{"type":"uint256","name":"startDate","internalType":"uint256"},{"type":"uint256","name":"endDate","internalType":"uint256"},{"type":"uint256","name":"bonusReserve","internalType":"uint256"},{"type":"uint256","name":"bonusPercentage","internalType":"uint256"},{"type":"uint256","name":"bonusActivator","internalType":"uint256"},{"type":"tuple","name":"vestingParams","internalType":"struct Launchpad.VestingParams","components":[{"type":"uint256","name":"unlockPercentage","internalType":"uint256"},{"type":"uint256","name":"cliffPeriod","internalType":"uint256"},{"type":"uint256","name":"vestingPercentage","internalType":"uint256"},{"type":"uint256","name":"vestingInterval","internalType":"uint256"}]}]},{"type":"tuple","name":"state","internalType":"struct Launchpad.ICOState","components":[{"type":"address","name":"ICOOwner","internalType":"address"},{"type":"uint8","name":"icoTokenDecimals","internalType":"uint8"},{"type":"address","name":"vestingContract","internalType":"address"},{"type":"bool","name":"isClosed","internalType":"bool"},{"type":"uint256","name":"totalSold","internalType":"uint256"},{"type":"uint256","name":"totalReceived","internalType":"uint256"}]}],"name":"getICO","inputs":[{"type":"uint256","name":"id","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"availableAmount","internalType":"uint256"},{"type":"uint256","name":"value","internalType":"uint256"}],"name":"getValue","inputs":[{"type":"uint256","name":"id","internalType":"uint256"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"token","internalType":"address"},{"type":"address","name":"paymentToken","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"startPrice","internalType":"uint256"},{"type":"uint256","name":"endPrice","internalType":"uint256"},{"type":"uint256","name":"startDate","internalType":"uint256"},{"type":"uint256","name":"endDate","internalType":"uint256"},{"type":"uint256","name":"bonusReserve","internalType":"uint256"},{"type":"uint256","name":"bonusPercentage","internalType":"uint256"},{"type":"uint256","name":"bonusActivator","internalType":"uint256"},{"type":"tuple","name":"vestingParams","internalType":"struct Launchpad.VestingParams","components":[{"type":"uint256","name":"unlockPercentage","internalType":"uint256"},{"type":"uint256","name":"cliffPeriod","internalType":"uint256"},{"type":"uint256","name":"vestingPercentage","internalType":"uint256"},{"type":"uint256","name":"vestingInterval","internalType":"uint256"}]}],"name":"icoParams","inputs":[{"type":"uint256","name":"ICOid","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"ICOOwner","internalType":"address"},{"type":"uint8","name":"icoTokenDecimals","internalType":"uint8"},{"type":"address","name":"vestingContract","internalType":"address"},{"type":"bool","name":"isClosed","internalType":"bool"},{"type":"uint256","name":"totalSold","internalType":"uint256"},{"type":"uint256","name":"totalReceived","internalType":"uint256"}],"name":"icoState","inputs":[{"type":"uint256","name":"ICOid","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"initialize","inputs":[{"type":"address","name":"vestingImplementation_","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isPaused","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"rescueTokens","inputs":[{"type":"address","name":"_token","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setPauseLaunchpad","inputs":[{"type":"bool","name":"pause","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setVestingImplementation","inputs":[{"type":"address","name":"vestingImplementation_","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bytes4","name":"","internalType":"bytes4"}],"name":"tokenReceived","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"bytes","name":"","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"vestingContract","internalType":"address"}],"name":"vestingContracts","inputs":[{"type":"address","name":"token","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"vestingImplementation","inputs":[]}]
              

Contract Creation Code

0x608060405234801561001057600080fd5b50600080546001600160a01b0319163390811782556040519091907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a361214a8061005f6000396000f3fe6080604052600436106101085760003560e01c80638882a2f611610095578063b187bd2611610064578063b187bd261461039e578063c4d66de8146103c8578063ce1ee86a146103e8578063f2fde38b14610408578063fc4c07cf1461042857600080fd5b80638882a2f6146103075780638943ec021461032757806389603de0146103605780638da5cb5b1461038057600080fd5b8063423a50b8116100dc578063423a50b8146101c757806355089bac146101e75780635e237b351461028e57806361bc221a146102ae5780636a19e6de146102d257600080fd5b8062ae3bf81461010d57806321466eb51461012f57806331869ebf146101425780633791587414610179575b600080fd5b34801561011957600080fd5b5061012d610128366004611a4e565b6104ec565b005b61012d61013d366004611a69565b61060a565b34801561014e57600080fd5b5061016261015d366004611a9e565b610b0a565b604051610170929190611ab7565b60405180910390f35b34801561018557600080fd5b506101af610194366004611a4e565b6002602052600090815260409020546001600160a01b031681565b6040516001600160a01b039091168152602001610170565b3480156101d357600080fd5b5061012d6101e2366004611c9a565b610c74565b3480156101f357600080fd5b5061024b610202366004611a9e565b60046020526000908152604090208054600182015460028301546003909301546001600160a01b038084169460ff600160a01b9586900481169592851694929092049091169186565b604080516001600160a01b03978816815260ff969096166020870152939095169284019290925215156060830152608082015260a081019190915260c001610170565b34801561029a57600080fd5b5061012d6102a9366004611d50565b610fc7565b3480156102ba57600080fd5b506102c460055481565b604051908152602001610170565b3480156102de57600080fd5b506102f26102ed366004611d6d565b611013565b60408051928352602083019190915201610170565b34801561031357600080fd5b506001546101af906001600160a01b031681565b34801561033357600080fd5b50610347610342366004611d8f565b61118c565b6040516001600160e01b03199091168152602001610170565b34801561036c57600080fd5b5061012d61037b366004611a9e565b61119c565b34801561038c57600080fd5b506000546001600160a01b03166101af565b3480156103aa57600080fd5b506006546103b89060ff1681565b6040519015158152602001610170565b3480156103d457600080fd5b5061012d6103e3366004611a4e565b611307565b3480156103f457600080fd5b5061012d610403366004611a4e565b6113b0565b34801561041457600080fd5b5061012d610423366004611a4e565b61140b565b34801561043457600080fd5b506104d5610443366004611a9e565b600360208181526000928352604092839020805460018201546002830154948301546004840154600585015460068601546007870154600888015460098901548c51608081018e52600a8b01548152600b8b01549b81019b909b52600c8a01549c8b019c909c52600d9098015460608a01526001600160a01b039687169a95909616989793969295919490939192918b565b6040516101709b9a99989796959493929190611e3e565b336104ff6000546001600160a01b031690565b6001600160a01b03161461052e5760405162461bcd60e51b815260040161052590611ed0565b60405180910390fd5b60006001600160a01b03821661054f57504761054a3382611504565b6105c4565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610593573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105b79190611f05565b90506105c48233836115d2565b604080516001600160a01b0384168152602081018390527f542fa6bfee3b4746210fbdd1d83f9e49b65adde3639f8d8f165dd18347938af2910160405180910390a15050565b60008381526003602052604090206005015483904210156106665760405162461bcd60e51b81526020600482015260166024820152751250d3c81a5cc81b9bdd081cdd185c9d1959081e595d60521b6044820152606401610525565b600081815260036020526040902060060154421115806106955750600081815260036020526040902060060154155b6106d35760405162461bcd60e51b815260206004820152600f60248201526e1250d3c81a5cc8199a5b9a5cda1959608a1b6044820152606401610525565b600081815260046020526040902060010154600160a01b900460ff161561072c5760405162461bcd60e51b815260206004820152600d60248201526c1250d3c81a5cc818db1bdcd959609a1b6044820152606401610525565b60065460ff16156107755760405162461bcd60e51b815260206004820152601360248201527213185d5b98da1c1859081a5cc81c185d5cd959606a1b6044820152606401610525565b6001600160a01b0382166107bd5760405162461bcd60e51b815260206004820152600f60248201526e24b731b7b93932b1ba10313abcb2b960891b6044820152606401610525565b60006107c98585611013565b9094509050600084900361080a5760405162461bcd60e51b81526020600482015260086024820152671cdbdb19081bdd5d60c21b6044820152606401610525565b6000858152600360209081526040808320600490925290912060018201546001600160a01b0316806108a957833410156108745760405162461bcd60e51b815260206004820152600b60248201526a131bddc81c185e5b595b9d60aa1b6044820152606401610525565b8334111561088f5761088f3361088a8634611f34565b611504565b81546108a4906001600160a01b031685611504565b6108c2565b81546108c290829033906001600160a01b0316876116ed565b838260030160008282546108d69190611f4d565b92505081905550868260020160008282546108f19190611f4d565b90915550506007830154600090801561097057886127108660090154876002015461091c9190611f60565b6109269190611f77565b116109705761271085600801548a61093e9190611f60565b6109489190611f77565b915081811015610956578091505b8185600701600082825461096a9190611f34565b90915550505b50600061097d828a611f4d565b60018501549091506001600160a01b031615610a9057600b8501546000906109a59042611f4d565b600a870154909150612710906109bb9084611f60565b6109c59190611f77565b91506000826109d4858d611f4d565b6109de9190611f34565b90508015610a8d5786546001870154610a04916001600160a01b0390811691168361181d565b6001860154600c880154600d89015460405163431b1acb60e01b81526001600160a01b038e8116600483015260248201869052604482018790526064820193909352608481019190915291169063431b1acb9060a401600060405180830381600087803b158015610a7457600080fd5b505af1158015610a88573d6000803e3d6000fd5b505050505b50505b8454610aa6906001600160a01b031689836115d2565b604080516001600160a01b038a168152602081018c9052908101879052606081018a9052608081018390527f88ec88080cc26f1cd03f72bfe52eb411992bd2c91c32bcdf596693ed20e9d85d9060a00160405180910390a150505050505050505050565b610b126119a3565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525050600081815260036020818152604080842081516101608101835281546001600160a01b0390811682526001808401548216838701526002808501548487015284880154606080860191909152600480870154608080880191909152600588015460a080890191909152600689015460c0808a019190915260078a015460e08a015260088a01546101008a015260098a01546101208a01528a518084018c52600a8b01548152600b8b0154818e0152600c8b0154818d0152600d909a01548a8601526101408901999099529c8c5290895299879020875196870188528054808616885260ff600160a01b9182900481169a89019a909a52938101549485169787019790975291909204909516151594830194909452928201549481019490945290910154928201929092529091565b610c97816000015133308460e001518560400151610c929190611f4d565b6116ed565b60058054906000610ca783611f99565b909155506000818152600360208181526040808420865181546001600160a01b039182166001600160a01b0319918216178355848901516001840180549184169183169190911790558389015160028401556060808a015196840196909655608089015160048085019190915560a08a0151600585015560c08a0151600685015560e08a015160078501556101008a015160088501556101208a015160098501556101408a01518051600a86015580870151600b86015580860151600c86015590960151600d90930192909255848452948290208054909116331790558551815163313ce56760e01b8152915194169363313ce5679382810193928290030181865afa158015610dbb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ddf9190611fb2565b6000828152600460205260409020805460ff92909216600160a01b0260ff60a01b19909216919091179055610140820151516127101015610e625760405162461bcd60e51b815260206004820152601a60248201527f496e636f727265637420756e6c6f636b50657263656e746167650000000000006044820152606401610525565b6000612710836101400151600001511015610f71575081516001600160a01b039081166000908152600260205260409020541680610f4657600154610eaf906001600160a01b0316611931565b835160405163485cc95560e01b81523360048201526001600160a01b03918216602482015291925082169063485cc95590604401600060405180830381600087803b158015610efd57600080fd5b505af1158015610f11573d6000803e3d6000fd5b505084516001600160a01b03908116600090815260026020526040902080546001600160a01b03191691851691909117905550505b600082815260046020526040902060010180546001600160a01b0319166001600160a01b0383161790555b8251604080518481526001600160a01b03928316602082015233818301529183166060830152517f23c4aa757e39eb798ed23a9649a07ad8c3ba4626211baf9c8bc569090914173e9181900360800190a1505050565b33610fda6000546001600160a01b031690565b6001600160a01b0316146110005760405162461bcd60e51b815260040161052590611ed0565b6006805460ff1916911515919091179055565b6000828152600360209081526040808320600290810154600490935290832001548291906110418183611f34565b93508385101561104f578493505b600086815260036020526040812060040154908190036110bb5760008781526004602052604090205461108d90600160a01b900460ff16600a6120b9565b600088815260036020819052604090912001546110aa9087611f60565b6110b49190611f77565b9350611182565b6000878152600360208190526040822001549084846110da8486611f34565b6110e49190611f60565b6110ee9190611f77565b6110f89083611f4d565b9050846111058886611f4d565b61110f8486611f34565b6111199190611f60565b6111239190611f77565b61112d9083611f4d565b60008a81526004602052604090205490935061115490600160a01b900460ff16600a6120b9565b61115f906002611f60565b6111698483611f4d565b6111739089611f60565b61117d9190611f77565b955050505b5050509250929050565b6344a1f60160e11b5b9392505050565b6000818152600360209081526040808320600490925290912080546001600160a01b031633146111ff5760405162461bcd60e51b815260206004820152600e60248201526d27b7363c9024a1a79037bbb732b960911b6044820152606401610525565b6001810154600160a01b900460ff161561124c5760405162461bcd60e51b815260206004820152600e60248201526d105b1c9958591e4818db1bdcd95960921b6044820152606401610525565b60018101805460ff60a01b1916600160a01b1790556007820154600280830154908401546000929161127d91611f34565b6112879190611f4d565b600280840154908501556000600785015583549091506112b1906001600160a01b031633836115d2565b8254604080518681523360208201526001600160a01b039092168282015260608201839052517fd9200d3b6d4769b5d4fdc7ef18184f6afd5a8ddaf0e48ad27b9af5275e5177699181900360800190a150505050565b6000546001600160a01b03161561134f5760405162461bcd60e51b815260206004820152600c60248201526b105b1c9958591e481a5b9a5d60a21b6044820152606401610525565b600080546001600160a01b0319163390811782556040519091907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b336113c36000546001600160a01b031690565b6001600160a01b0316146113e95760405162461bcd60e51b815260040161052590611ed0565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b3361141e6000546001600160a01b031690565b6001600160a01b0316146114445760405162461bcd60e51b815260040161052590611ed0565b6001600160a01b0381166114a95760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610525565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b604080516000808252602082019092526001600160a01b03841690839060405161152e91906120c8565b60006040518083038185875af1925050503d806000811461156b576040519150601f19603f3d011682016040523d82523d6000602084013e611570565b606091505b50509050806115cd5760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b6064820152608401610525565b505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161162e91906120c8565b6000604051808303816000865af19150503d806000811461166b576040519150601f19603f3d011682016040523d82523d6000602084013e611670565b606091505b509150915081801561169a57508051158061169a57508080602001905181019061169a91906120f7565b6116e65760405162461bcd60e51b815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610525565b5050505050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b179052915160009283929088169161175191906120c8565b6000604051808303816000865af19150503d806000811461178e576040519150601f19603f3d011682016040523d82523d6000602084013e611793565b606091505b50915091508180156117bd5750805115806117bd5750808060200190518101906117bd91906120f7565b6118155760405162461bcd60e51b8152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f46416044820152631253115160e21b6064820152608401610525565b505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b179052915160009283929087169161187991906120c8565b6000604051808303816000865af19150503d80600081146118b6576040519150601f19603f3d011682016040523d82523d6000602084013e6118bb565b606091505b50915091508180156118e55750805115806118e55750808060200190518101906118e591906120f7565b6116e65760405162461bcd60e51b815260206004820152601e60248201527f5472616e7366657248656c7065723a20415050524f56455f4641494c454400006044820152606401610525565b6000763d602d80600a3d3981f3363d3d373d3d3d363d730000008260601b60e81c176000526e5af43d82803e903d91602b57fd5bf38260781b17602052603760096000f090506001600160a01b03811661199e576040516330be1a3d60e21b815260040160405180910390fd5b919050565b60405180610160016040528060006001600160a01b0316815260200160006001600160a01b031681526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001611a326040518060800160405280600081526020016000815260200160008152602001600081525090565b905290565b80356001600160a01b038116811461199e57600080fd5b600060208284031215611a6057600080fd5b61119582611a37565b600080600060608486031215611a7e57600080fd5b8335925060208401359150611a9560408501611a37565b90509250925092565b600060208284031215611ab057600080fd5b5035919050565b82516001600160a01b0316815261028081016020840151611ae360208401826001600160a01b03169052565b5060408401516040830152606084015160608301526080840151608083015260a084015160a083015260c084015160c083015260e084015160e083015261010080850151818401525061012080850151818401525061014080850151611b6c82850182805182526020810151602083015260408101516040830152606081015160608301525050565b505082516001600160a01b039081166101c0840152602084015160ff166101e084015260408401511661020083015260608301511515610220830152608083015161024083015260a0830151610260830152611195565b634e487b7160e01b600052604160045260246000fd5b604051610160810167ffffffffffffffff81118282101715611bfd57611bfd611bc3565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611c2c57611c2c611bc3565b604052919050565b600060808284031215611c4657600080fd5b6040516080810181811067ffffffffffffffff82111715611c6957611c69611bc3565b8060405250809150823581526020830135602082015260408301356040820152606083013560608201525092915050565b60006101c08284031215611cad57600080fd5b611cb5611bd9565b611cbe83611a37565b8152611ccc60208401611a37565b602082015260408301356040820152606083013560608201526080830135608082015260a083013560a082015260c083013560c082015260e083013560e0820152610100808401358183015250610120808401358183015250610140611d3485828601611c34565b908201529392505050565b8015158114611d4d57600080fd5b50565b600060208284031215611d6257600080fd5b813561119581611d3f565b60008060408385031215611d8057600080fd5b50508035926020909101359150565b600080600060608486031215611da457600080fd5b611dad84611a37565b92506020808501359250604085013567ffffffffffffffff80821115611dd257600080fd5b818701915087601f830112611de657600080fd5b813581811115611df857611df8611bc3565b611e0a601f8201601f19168501611c03565b91508082528884828501011115611e2057600080fd5b80848401858401376000848284010152508093505050509250925092565b6001600160a01b038c811682528b166020820152604081018a9052606081018990526080810188905260a0810187905260c0810186905260e08101859052610100810184905261012081018390526101c08101611ec0610140830184805182526020810151602083015260408101516040830152606081015160608301525050565b9c9b505050505050505050505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b600060208284031215611f1757600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b81810381811115611f4757611f47611f1e565b92915050565b80820180821115611f4757611f47611f1e565b8082028115828204841417611f4757611f47611f1e565b600082611f9457634e487b7160e01b600052601260045260246000fd5b500490565b600060018201611fab57611fab611f1e565b5060010190565b600060208284031215611fc457600080fd5b815160ff8116811461119557600080fd5b600181815b80851115612010578160001904821115611ff657611ff6611f1e565b8085161561200357918102915b93841c9390800290611fda565b509250929050565b60008261202757506001611f47565b8161203457506000611f47565b816001811461204a576002811461205457612070565b6001915050611f47565b60ff84111561206557612065611f1e565b50506001821b611f47565b5060208310610133831016604e8410600b8410161715612093575081810a611f47565b61209d8383611fd5565b80600019048211156120b1576120b1611f1e565b029392505050565b600061119560ff841683612018565b6000825160005b818110156120e957602081860181015185830152016120cf565b506000920191825250919050565b60006020828403121561210957600080fd5b815161119581611d3f56fea2646970667358221220adf527d105120d455e7e14f94267a52da3b82075ee644eb699df9367fb1a565064736f6c63430008130033

Deployed ByteCode

0x6080604052600436106101085760003560e01c80638882a2f611610095578063b187bd2611610064578063b187bd261461039e578063c4d66de8146103c8578063ce1ee86a146103e8578063f2fde38b14610408578063fc4c07cf1461042857600080fd5b80638882a2f6146103075780638943ec021461032757806389603de0146103605780638da5cb5b1461038057600080fd5b8063423a50b8116100dc578063423a50b8146101c757806355089bac146101e75780635e237b351461028e57806361bc221a146102ae5780636a19e6de146102d257600080fd5b8062ae3bf81461010d57806321466eb51461012f57806331869ebf146101425780633791587414610179575b600080fd5b34801561011957600080fd5b5061012d610128366004611a4e565b6104ec565b005b61012d61013d366004611a69565b61060a565b34801561014e57600080fd5b5061016261015d366004611a9e565b610b0a565b604051610170929190611ab7565b60405180910390f35b34801561018557600080fd5b506101af610194366004611a4e565b6002602052600090815260409020546001600160a01b031681565b6040516001600160a01b039091168152602001610170565b3480156101d357600080fd5b5061012d6101e2366004611c9a565b610c74565b3480156101f357600080fd5b5061024b610202366004611a9e565b60046020526000908152604090208054600182015460028301546003909301546001600160a01b038084169460ff600160a01b9586900481169592851694929092049091169186565b604080516001600160a01b03978816815260ff969096166020870152939095169284019290925215156060830152608082015260a081019190915260c001610170565b34801561029a57600080fd5b5061012d6102a9366004611d50565b610fc7565b3480156102ba57600080fd5b506102c460055481565b604051908152602001610170565b3480156102de57600080fd5b506102f26102ed366004611d6d565b611013565b60408051928352602083019190915201610170565b34801561031357600080fd5b506001546101af906001600160a01b031681565b34801561033357600080fd5b50610347610342366004611d8f565b61118c565b6040516001600160e01b03199091168152602001610170565b34801561036c57600080fd5b5061012d61037b366004611a9e565b61119c565b34801561038c57600080fd5b506000546001600160a01b03166101af565b3480156103aa57600080fd5b506006546103b89060ff1681565b6040519015158152602001610170565b3480156103d457600080fd5b5061012d6103e3366004611a4e565b611307565b3480156103f457600080fd5b5061012d610403366004611a4e565b6113b0565b34801561041457600080fd5b5061012d610423366004611a4e565b61140b565b34801561043457600080fd5b506104d5610443366004611a9e565b600360208181526000928352604092839020805460018201546002830154948301546004840154600585015460068601546007870154600888015460098901548c51608081018e52600a8b01548152600b8b01549b81019b909b52600c8a01549c8b019c909c52600d9098015460608a01526001600160a01b039687169a95909616989793969295919490939192918b565b6040516101709b9a99989796959493929190611e3e565b336104ff6000546001600160a01b031690565b6001600160a01b03161461052e5760405162461bcd60e51b815260040161052590611ed0565b60405180910390fd5b60006001600160a01b03821661054f57504761054a3382611504565b6105c4565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610593573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105b79190611f05565b90506105c48233836115d2565b604080516001600160a01b0384168152602081018390527f542fa6bfee3b4746210fbdd1d83f9e49b65adde3639f8d8f165dd18347938af2910160405180910390a15050565b60008381526003602052604090206005015483904210156106665760405162461bcd60e51b81526020600482015260166024820152751250d3c81a5cc81b9bdd081cdd185c9d1959081e595d60521b6044820152606401610525565b600081815260036020526040902060060154421115806106955750600081815260036020526040902060060154155b6106d35760405162461bcd60e51b815260206004820152600f60248201526e1250d3c81a5cc8199a5b9a5cda1959608a1b6044820152606401610525565b600081815260046020526040902060010154600160a01b900460ff161561072c5760405162461bcd60e51b815260206004820152600d60248201526c1250d3c81a5cc818db1bdcd959609a1b6044820152606401610525565b60065460ff16156107755760405162461bcd60e51b815260206004820152601360248201527213185d5b98da1c1859081a5cc81c185d5cd959606a1b6044820152606401610525565b6001600160a01b0382166107bd5760405162461bcd60e51b815260206004820152600f60248201526e24b731b7b93932b1ba10313abcb2b960891b6044820152606401610525565b60006107c98585611013565b9094509050600084900361080a5760405162461bcd60e51b81526020600482015260086024820152671cdbdb19081bdd5d60c21b6044820152606401610525565b6000858152600360209081526040808320600490925290912060018201546001600160a01b0316806108a957833410156108745760405162461bcd60e51b815260206004820152600b60248201526a131bddc81c185e5b595b9d60aa1b6044820152606401610525565b8334111561088f5761088f3361088a8634611f34565b611504565b81546108a4906001600160a01b031685611504565b6108c2565b81546108c290829033906001600160a01b0316876116ed565b838260030160008282546108d69190611f4d565b92505081905550868260020160008282546108f19190611f4d565b90915550506007830154600090801561097057886127108660090154876002015461091c9190611f60565b6109269190611f77565b116109705761271085600801548a61093e9190611f60565b6109489190611f77565b915081811015610956578091505b8185600701600082825461096a9190611f34565b90915550505b50600061097d828a611f4d565b60018501549091506001600160a01b031615610a9057600b8501546000906109a59042611f4d565b600a870154909150612710906109bb9084611f60565b6109c59190611f77565b91506000826109d4858d611f4d565b6109de9190611f34565b90508015610a8d5786546001870154610a04916001600160a01b0390811691168361181d565b6001860154600c880154600d89015460405163431b1acb60e01b81526001600160a01b038e8116600483015260248201869052604482018790526064820193909352608481019190915291169063431b1acb9060a401600060405180830381600087803b158015610a7457600080fd5b505af1158015610a88573d6000803e3d6000fd5b505050505b50505b8454610aa6906001600160a01b031689836115d2565b604080516001600160a01b038a168152602081018c9052908101879052606081018a9052608081018390527f88ec88080cc26f1cd03f72bfe52eb411992bd2c91c32bcdf596693ed20e9d85d9060a00160405180910390a150505050505050505050565b610b126119a3565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525050600081815260036020818152604080842081516101608101835281546001600160a01b0390811682526001808401548216838701526002808501548487015284880154606080860191909152600480870154608080880191909152600588015460a080890191909152600689015460c0808a019190915260078a015460e08a015260088a01546101008a015260098a01546101208a01528a518084018c52600a8b01548152600b8b0154818e0152600c8b0154818d0152600d909a01548a8601526101408901999099529c8c5290895299879020875196870188528054808616885260ff600160a01b9182900481169a89019a909a52938101549485169787019790975291909204909516151594830194909452928201549481019490945290910154928201929092529091565b610c97816000015133308460e001518560400151610c929190611f4d565b6116ed565b60058054906000610ca783611f99565b909155506000818152600360208181526040808420865181546001600160a01b039182166001600160a01b0319918216178355848901516001840180549184169183169190911790558389015160028401556060808a015196840196909655608089015160048085019190915560a08a0151600585015560c08a0151600685015560e08a015160078501556101008a015160088501556101208a015160098501556101408a01518051600a86015580870151600b86015580860151600c86015590960151600d90930192909255848452948290208054909116331790558551815163313ce56760e01b8152915194169363313ce5679382810193928290030181865afa158015610dbb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ddf9190611fb2565b6000828152600460205260409020805460ff92909216600160a01b0260ff60a01b19909216919091179055610140820151516127101015610e625760405162461bcd60e51b815260206004820152601a60248201527f496e636f727265637420756e6c6f636b50657263656e746167650000000000006044820152606401610525565b6000612710836101400151600001511015610f71575081516001600160a01b039081166000908152600260205260409020541680610f4657600154610eaf906001600160a01b0316611931565b835160405163485cc95560e01b81523360048201526001600160a01b03918216602482015291925082169063485cc95590604401600060405180830381600087803b158015610efd57600080fd5b505af1158015610f11573d6000803e3d6000fd5b505084516001600160a01b03908116600090815260026020526040902080546001600160a01b03191691851691909117905550505b600082815260046020526040902060010180546001600160a01b0319166001600160a01b0383161790555b8251604080518481526001600160a01b03928316602082015233818301529183166060830152517f23c4aa757e39eb798ed23a9649a07ad8c3ba4626211baf9c8bc569090914173e9181900360800190a1505050565b33610fda6000546001600160a01b031690565b6001600160a01b0316146110005760405162461bcd60e51b815260040161052590611ed0565b6006805460ff1916911515919091179055565b6000828152600360209081526040808320600290810154600490935290832001548291906110418183611f34565b93508385101561104f578493505b600086815260036020526040812060040154908190036110bb5760008781526004602052604090205461108d90600160a01b900460ff16600a6120b9565b600088815260036020819052604090912001546110aa9087611f60565b6110b49190611f77565b9350611182565b6000878152600360208190526040822001549084846110da8486611f34565b6110e49190611f60565b6110ee9190611f77565b6110f89083611f4d565b9050846111058886611f4d565b61110f8486611f34565b6111199190611f60565b6111239190611f77565b61112d9083611f4d565b60008a81526004602052604090205490935061115490600160a01b900460ff16600a6120b9565b61115f906002611f60565b6111698483611f4d565b6111739089611f60565b61117d9190611f77565b955050505b5050509250929050565b6344a1f60160e11b5b9392505050565b6000818152600360209081526040808320600490925290912080546001600160a01b031633146111ff5760405162461bcd60e51b815260206004820152600e60248201526d27b7363c9024a1a79037bbb732b960911b6044820152606401610525565b6001810154600160a01b900460ff161561124c5760405162461bcd60e51b815260206004820152600e60248201526d105b1c9958591e4818db1bdcd95960921b6044820152606401610525565b60018101805460ff60a01b1916600160a01b1790556007820154600280830154908401546000929161127d91611f34565b6112879190611f4d565b600280840154908501556000600785015583549091506112b1906001600160a01b031633836115d2565b8254604080518681523360208201526001600160a01b039092168282015260608201839052517fd9200d3b6d4769b5d4fdc7ef18184f6afd5a8ddaf0e48ad27b9af5275e5177699181900360800190a150505050565b6000546001600160a01b03161561134f5760405162461bcd60e51b815260206004820152600c60248201526b105b1c9958591e481a5b9a5d60a21b6044820152606401610525565b600080546001600160a01b0319163390811782556040519091907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b336113c36000546001600160a01b031690565b6001600160a01b0316146113e95760405162461bcd60e51b815260040161052590611ed0565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b3361141e6000546001600160a01b031690565b6001600160a01b0316146114445760405162461bcd60e51b815260040161052590611ed0565b6001600160a01b0381166114a95760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610525565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b604080516000808252602082019092526001600160a01b03841690839060405161152e91906120c8565b60006040518083038185875af1925050503d806000811461156b576040519150601f19603f3d011682016040523d82523d6000602084013e611570565b606091505b50509050806115cd5760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b6064820152608401610525565b505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161162e91906120c8565b6000604051808303816000865af19150503d806000811461166b576040519150601f19603f3d011682016040523d82523d6000602084013e611670565b606091505b509150915081801561169a57508051158061169a57508080602001905181019061169a91906120f7565b6116e65760405162461bcd60e51b815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610525565b5050505050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b179052915160009283929088169161175191906120c8565b6000604051808303816000865af19150503d806000811461178e576040519150601f19603f3d011682016040523d82523d6000602084013e611793565b606091505b50915091508180156117bd5750805115806117bd5750808060200190518101906117bd91906120f7565b6118155760405162461bcd60e51b8152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f46416044820152631253115160e21b6064820152608401610525565b505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b179052915160009283929087169161187991906120c8565b6000604051808303816000865af19150503d80600081146118b6576040519150601f19603f3d011682016040523d82523d6000602084013e6118bb565b606091505b50915091508180156118e55750805115806118e55750808060200190518101906118e591906120f7565b6116e65760405162461bcd60e51b815260206004820152601e60248201527f5472616e7366657248656c7065723a20415050524f56455f4641494c454400006044820152606401610525565b6000763d602d80600a3d3981f3363d3d373d3d3d363d730000008260601b60e81c176000526e5af43d82803e903d91602b57fd5bf38260781b17602052603760096000f090506001600160a01b03811661199e576040516330be1a3d60e21b815260040160405180910390fd5b919050565b60405180610160016040528060006001600160a01b0316815260200160006001600160a01b031681526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001611a326040518060800160405280600081526020016000815260200160008152602001600081525090565b905290565b80356001600160a01b038116811461199e57600080fd5b600060208284031215611a6057600080fd5b61119582611a37565b600080600060608486031215611a7e57600080fd5b8335925060208401359150611a9560408501611a37565b90509250925092565b600060208284031215611ab057600080fd5b5035919050565b82516001600160a01b0316815261028081016020840151611ae360208401826001600160a01b03169052565b5060408401516040830152606084015160608301526080840151608083015260a084015160a083015260c084015160c083015260e084015160e083015261010080850151818401525061012080850151818401525061014080850151611b6c82850182805182526020810151602083015260408101516040830152606081015160608301525050565b505082516001600160a01b039081166101c0840152602084015160ff166101e084015260408401511661020083015260608301511515610220830152608083015161024083015260a0830151610260830152611195565b634e487b7160e01b600052604160045260246000fd5b604051610160810167ffffffffffffffff81118282101715611bfd57611bfd611bc3565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611c2c57611c2c611bc3565b604052919050565b600060808284031215611c4657600080fd5b6040516080810181811067ffffffffffffffff82111715611c6957611c69611bc3565b8060405250809150823581526020830135602082015260408301356040820152606083013560608201525092915050565b60006101c08284031215611cad57600080fd5b611cb5611bd9565b611cbe83611a37565b8152611ccc60208401611a37565b602082015260408301356040820152606083013560608201526080830135608082015260a083013560a082015260c083013560c082015260e083013560e0820152610100808401358183015250610120808401358183015250610140611d3485828601611c34565b908201529392505050565b8015158114611d4d57600080fd5b50565b600060208284031215611d6257600080fd5b813561119581611d3f565b60008060408385031215611d8057600080fd5b50508035926020909101359150565b600080600060608486031215611da457600080fd5b611dad84611a37565b92506020808501359250604085013567ffffffffffffffff80821115611dd257600080fd5b818701915087601f830112611de657600080fd5b813581811115611df857611df8611bc3565b611e0a601f8201601f19168501611c03565b91508082528884828501011115611e2057600080fd5b80848401858401376000848284010152508093505050509250925092565b6001600160a01b038c811682528b166020820152604081018a9052606081018990526080810188905260a0810187905260c0810186905260e08101859052610100810184905261012081018390526101c08101611ec0610140830184805182526020810151602083015260408101516040830152606081015160608301525050565b9c9b505050505050505050505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b600060208284031215611f1757600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b81810381811115611f4757611f47611f1e565b92915050565b80820180821115611f4757611f47611f1e565b8082028115828204841417611f4757611f47611f1e565b600082611f9457634e487b7160e01b600052601260045260246000fd5b500490565b600060018201611fab57611fab611f1e565b5060010190565b600060208284031215611fc457600080fd5b815160ff8116811461119557600080fd5b600181815b80851115612010578160001904821115611ff657611ff6611f1e565b8085161561200357918102915b93841c9390800290611fda565b509250929050565b60008261202757506001611f47565b8161203457506000611f47565b816001811461204a576002811461205457612070565b6001915050611f47565b60ff84111561206557612065611f1e565b50506001821b611f47565b5060208310610133831016604e8410600b8410161715612093575081810a611f47565b61209d8383611fd5565b80600019048211156120b1576120b1611f1e565b029392505050565b600061119560ff841683612018565b6000825160005b818110156120e957602081860181015185830152016120cf565b506000920191825250919050565b60006020828403121561210957600080fd5b815161119581611d3f56fea2646970667358221220adf527d105120d455e7e14f94267a52da3b82075ee644eb699df9367fb1a565064736f6c63430008130033