Contract Address Details

0xe5A5837b96176d6E47E541F186B2348DED2c0A1d

Contract Name
Vesting
Creator
0xc7d98c–7f3521 at 0xa74aff–eb0df7
Balance
0 CLO ( )
Tokens
Fetching tokens...
Transactions
14 Transactions
Transfers
90 Transfers
Gas Used
1,869,709
Last Balance Update
15123213
Contract name:
Vesting




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




Optimization runs
200
EVM Version
default




Verified at
2024-02-22T10:11:13.121890Z

Constructor Arguments

000000000000000000000000df4da43dd3e9918f0784f8c92b8aa1b304c43243

Arg [0] (address) : 0xdf4da43dd3e9918f0784f8c92b8aa1b304c43243

              

Contract source code

// 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 private _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 Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        emit OwnershipTransferred(_owner, address(0));
        _owner = address(0);
    }

    /**
     * @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 balanceOf(address account) external view returns (uint256);
    function transfer(address recipient, uint256 amount) external returns (bool);
}

abstract contract ERC223Recipient { 
    mapping(address => bool) public depositors; // address of users who has right to deposit and allocate tokens

    modifier onlyDepositor() {
        require(depositors[msg.sender], "Only depositors allowed");
        _;
    }

    /**
    * @dev Standard ERC223 function that will handle incoming token transfers.
    */
    function tokenReceived(address _from, uint256, bytes memory) external virtual returns(bytes4) {
        require(depositors[_from], "Only depositors allowed");
        return this.tokenReceived.selector;
    }

}

contract Vesting is Ownable, ERC223Recipient {
    address public vestedToken;
    uint256 public totalAllocated;
    uint256 public totalClaimed;
    
    struct Allocation {
        uint256 amount;             // amount of token
        uint256 unlockPercentage;   // percentage (with 2 decimals) of initially unlocked token
        uint256 cliffFinish;       // Timestamp (unix time) when finish vesting. First release 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)        
    }

    mapping(address beneficiary => Allocation[]) public beneficiaries; // beneficiary => Allocation
    mapping(address => uint256) public claimedAmount;   // beneficiary => already claimed amount

    event SetDepositor(address depositor, bool enable);
    event Claim(address indexed beneficiary, uint256 amount);
    event AddAllocation(
        address indexed to,         // beneficiary of tokens
        uint256 amount,             // amount of token
        uint256 unlockPercentage,   // percentage (with 2 decimals) of initially unlocked token
        uint256 cliffFinish,       // Timestamp (unix time) when finish vesting. First release 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)        
    );
    event Rescue(address _token, uint256 _amount);

    constructor (
        address _vestedToken        // vesting token
    ) {
        require(_vestedToken != address(0));
        vestedToken = _vestedToken;
    }

    // Depositor has right to transfer token to contract and allocate token to the beneficiary
    function setDepositor(address depositor, bool enable) external onlyOwner {
        depositors[depositor] = enable;
        emit SetDepositor(depositor, enable);
    }

    function allocateTokens(
        address to, // beneficiary of tokens
        uint256 amount, // amount of token
        uint256 unlockPercentage,   // percentage (with 2 decimals) of initially unlocked token
        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
        onlyDepositor
    {
        require(beneficiaries[to].length < 100, "Too many allocations for one address, use another address");
        safeTransferFrom(vestedToken, msg.sender, address(this), amount);
        require(amount <= getUnallocatedAmount(), "Not enough tokens");
        beneficiaries[to].push(Allocation(amount, unlockPercentage, cliffFinish, vestingPercentage, vestingInterval));
        totalAllocated += amount;
        // Check ERC223 compatibility of the beneficiary 
        if (isContract(to)) {
            ERC223Recipient(to).tokenReceived(address(this), 0, "");
        }
        emit AddAllocation(to, amount, unlockPercentage, cliffFinish, vestingPercentage, vestingInterval);
    }

    function claim() external {
        claimBehalf(msg.sender);
    }

    function claimBehalf(address beneficiary) public {
        (uint256 unlockedAmount,,) = getUnlockedAmount(beneficiary);
        if(unlockedAmount != 0) {
            claimedAmount[beneficiary] += unlockedAmount;
            totalClaimed += unlockedAmount;
            safeTransfer(vestedToken, beneficiary, unlockedAmount);
        }
        emit Claim(beneficiary, unlockedAmount);
    }

    function getUnlockedAmount(address beneficiary) public view returns(uint256 unlockedAmount, uint256 lockedAmount, uint256 nextUnlock) {
        uint256 len = beneficiaries[beneficiary].length;
        nextUnlock = 10000000000;
        for (uint256 i = 0; i < len; i++) {
            Allocation memory b = beneficiaries[beneficiary][i];
            uint256 amount = b.amount;
            lockedAmount += amount;
            uint256 unlocked = amount * b.unlockPercentage / 10000;
            if (b.cliffFinish <= block.timestamp) {
                uint256 intervals = (block.timestamp - b.cliffFinish) / b.vestingInterval + 1;
                unlocked = unlocked + (amount * intervals * b.vestingPercentage / 10000);
                uint256 next = intervals * b.vestingInterval + b.cliffFinish;
                if(nextUnlock > next) nextUnlock = next;
            } else if (nextUnlock > b.cliffFinish) nextUnlock = b.cliffFinish;
            if (unlocked > amount) unlocked = amount;
            unlockedAmount += unlocked;
        }
        lockedAmount -= unlockedAmount;
        unlockedAmount = unlockedAmount - claimedAmount[beneficiary];
    }

    function getBeneficiary(address beneficiary) external view returns(Allocation[] memory) {
        return beneficiaries[beneficiary];
    }

    function getUnallocatedAmount() public view returns(uint256 amount) {
        amount = IERC20(vestedToken).balanceOf(address(this));
        uint256 unclaimed = totalAllocated - totalClaimed;
        amount = amount - unclaimed;
    }

    function rescueTokens(address _token) onlyOwner external {
        uint256 amount;
        if (_token == vestedToken) {
            amount = getUnallocatedAmount();
        } else {
            amount = IERC20(_token).balanceOf(address(this));
        }

        safeTransfer(_token, msg.sender, amount);
        emit Rescue(_token, amount);
    }

    /**
     * @dev Returns true if `account` is a contract.
     *
     * This test is non-exhaustive, and there may be false-negatives: during the
     * execution of a contract's constructor, its address will be reported as
     * not containing a contract.
     *
     * > It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies in extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 0;
    }
    
    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');
    }
}
        

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_vestedToken","internalType":"address"}]},{"type":"event","name":"AddAllocation","inputs":[{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"uint256","name":"unlockPercentage","internalType":"uint256","indexed":false},{"type":"uint256","name":"cliffFinish","internalType":"uint256","indexed":false},{"type":"uint256","name":"vestingPercentage","internalType":"uint256","indexed":false},{"type":"uint256","name":"vestingInterval","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Claim","inputs":[{"type":"address","name":"beneficiary","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","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":"event","name":"SetDepositor","inputs":[{"type":"address","name":"depositor","internalType":"address","indexed":false},{"type":"bool","name":"enable","internalType":"bool","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"allocateTokens","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"unlockPercentage","internalType":"uint256"},{"type":"uint256","name":"cliffFinish","internalType":"uint256"},{"type":"uint256","name":"vestingPercentage","internalType":"uint256"},{"type":"uint256","name":"vestingInterval","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"unlockPercentage","internalType":"uint256"},{"type":"uint256","name":"cliffFinish","internalType":"uint256"},{"type":"uint256","name":"vestingPercentage","internalType":"uint256"},{"type":"uint256","name":"vestingInterval","internalType":"uint256"}],"name":"beneficiaries","inputs":[{"type":"address","name":"beneficiary","internalType":"address"},{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"claim","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"claimBehalf","inputs":[{"type":"address","name":"beneficiary","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"claimedAmount","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"depositors","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"","internalType":"struct Vesting.Allocation[]","components":[{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"unlockPercentage","internalType":"uint256"},{"type":"uint256","name":"cliffFinish","internalType":"uint256"},{"type":"uint256","name":"vestingPercentage","internalType":"uint256"},{"type":"uint256","name":"vestingInterval","internalType":"uint256"}]}],"name":"getBeneficiary","inputs":[{"type":"address","name":"beneficiary","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"amount","internalType":"uint256"}],"name":"getUnallocatedAmount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"unlockedAmount","internalType":"uint256"},{"type":"uint256","name":"lockedAmount","internalType":"uint256"},{"type":"uint256","name":"nextUnlock","internalType":"uint256"}],"name":"getUnlockedAmount","inputs":[{"type":"address","name":"beneficiary","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"rescueTokens","inputs":[{"type":"address","name":"_token","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setDepositor","inputs":[{"type":"address","name":"depositor","internalType":"address"},{"type":"bool","name":"enable","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bytes4","name":"","internalType":"bytes4"}],"name":"tokenReceived","inputs":[{"type":"address","name":"_from","internalType":"address"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"bytes","name":"","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalAllocated","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalClaimed","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"vestedToken","inputs":[]}]
            

Contract Creation Code

0x608060405234801561001057600080fd5b506040516114c83803806114c883398101604081905261002f916100a6565b600080546001600160a01b0319163390811782556040519091907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a36001600160a01b03811661008157600080fd5b600280546001600160a01b0319166001600160a01b03929092169190911790556100d6565b6000602082840312156100b857600080fd5b81516001600160a01b03811681146100cf57600080fd5b9392505050565b6113e3806100e56000396000f3fe608060405234801561001057600080fd5b50600436106101155760003560e01c80636bd7a97a116100a25780638943ec02116100715780638943ec02146102705780638da5cb5b1461029c578063d54ad2a1146102ad578063eed75f6d146102b6578063f2fde38b146102e957600080fd5b80636bd7a97a1461022f5780636f860d7414610242578063715018a614610255578063889014961461025d57600080fd5b806345f7f249116100e957806345f7f249146101985780634e71d92d146101a1578063505a1b31146101a9578063529849e9146101c95780635de297411461020457600080fd5b8062ae3bf81461011a57806304e869031461012f57806328733bb714610162578063420d4a021461016a575b600080fd5b61012d610128366004611012565b6102fc565b005b61014f61013d366004611012565b60066020526000908152604090205481565b6040519081526020015b60405180910390f35b61014f610423565b61017d610178366004611012565b6104b6565b60408051938452602084019290925290820152606001610159565b61014f60035481565b61012d6106a7565b6101bc6101b7366004611012565b6106b2565b6040516101599190611034565b6101dc6101d73660046110a2565b610759565b604080519586526020860194909452928401919091526060830152608082015260a001610159565b600254610217906001600160a01b031681565b6040516001600160a01b039091168152602001610159565b61012d61023d3660046110cc565b6107a7565b61012d610250366004611127565b610a6d565b61012d610b02565b61012d61026b366004611012565b610b85565b61028361027e366004611174565b610c40565b6040516001600160e01b03199091168152602001610159565b6000546001600160a01b0316610217565b61014f60045481565b6102d96102c4366004611012565b60016020526000908152604090205460ff1681565b6040519015158152602001610159565b61012d6102f7366004611012565b610cb2565b3361030f6000546001600160a01b031690565b6001600160a01b03161461033e5760405162461bcd60e51b81526004016103359061123f565b60405180910390fd5b6002546000906001600160a01b03908116908316036103665761035f610423565b90506103d1565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa1580156103aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103ce9190611274565b90505b6103dc823383610dab565b604080516001600160a01b0384168152602081018390527f542fa6bfee3b4746210fbdd1d83f9e49b65adde3639f8d8f165dd18347938af291015b60405180910390a15050565b6002546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa15801561046c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104909190611274565b905060006004546003546104a491906112a3565b90506104b081836112a3565b91505090565b6001600160a01b03811660009081526005602052604081205481906402540be40090825b8181101561066c576001600160a01b038616600090815260056020526040812080548390811061050c5761050c6112bc565b60009182526020918290206040805160a0810182526005909302909101805480845260018201549484019490945260028101549183019190915260038101546060830152600401546080820152915061056581876112d2565b9550600061271083602001518361057c91906112e5565b61058691906112fc565b90504283604001511161062b57600083608001518460400151426105aa91906112a3565b6105b491906112fc565b6105bf9060016112d2565b9050612710846060015182856105d591906112e5565b6105df91906112e5565b6105e991906112fc565b6105f390836112d2565b91506000846040015185608001518361060c91906112e5565b61061691906112d2565b905080881115610624578097505b505061063f565b826040015186111561063f57826040015195505b8181111561064a5750805b61065481896112d2565b975050505080806106649061131e565b9150506104da565b5061067784846112a3565b6001600160a01b03861660009081526006602052604090205490935061069d90856112a3565b9350509193909250565b6106b033610b85565b565b6001600160a01b0381166000908152600560209081526040808320805482518185028101850190935280835260609492939192909184015b8282101561074e57838290600052602060002090600502016040518060a001604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481525050815260200190600101906106ea565b505050509050919050565b6005602052816000526040600020818154811061077557600080fd5b600091825260209091206005909102018054600182015460028301546003840154600490940154929550909350919085565b3360009081526001602052604090205460ff166108005760405162461bcd60e51b815260206004820152601760248201527613db9b1e4819195c1bdcda5d1bdc9cc8185b1b1bddd959604a1b6044820152606401610335565b6001600160a01b03861660009081526005602052604090205460641161088e5760405162461bcd60e51b815260206004820152603960248201527f546f6f206d616e7920616c6c6f636174696f6e7320666f72206f6e652061646460448201527f726573732c2075736520616e6f746865722061646472657373000000000000006064820152608401610335565b6002546108a6906001600160a01b0316333088610ec6565b6108ae610423565b8511156108f15760405162461bcd60e51b81526020600482015260116024820152704e6f7420656e6f75676820746f6b656e7360781b6044820152606401610335565b6001600160a01b0386166000908152600560208181526040808420815160a0810183528a81528084018a81529281018981526060820189815260808301898152845460018181018755958a5296892093519690970290920194855592519184019190915590516002830155516003808301919091559151600490910155805487929061097e9084906112d2565b9091555050853b15610a0b576040516344a1f60160e11b81523060048201526000602482018190526060604483015260648201526001600160a01b03871690638943ec02906084016020604051808303816000875af11580156109e5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a099190611337565b505b604080518681526020810186905290810184905260608101839052608081018290526001600160a01b038716907f585acc8130c6cd35ae5bb61237605676cd4ec0a81dc2bf91a06b37270e81c3929060a00160405180910390a2505050505050565b33610a806000546001600160a01b031690565b6001600160a01b031614610aa65760405162461bcd60e51b81526004016103359061123f565b6001600160a01b038216600081815260016020908152604091829020805460ff19168515159081179091558251938452908301527fb1252fa67b4c05afbdaadfae34890b205103c0212a9e062b3978e8cd573631a99101610417565b33610b156000546001600160a01b031690565b6001600160a01b031614610b3b5760405162461bcd60e51b81526004016103359061123f565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000610b90826104b6565b5050905080600014610bf9576001600160a01b03821660009081526006602052604081208054839290610bc49084906112d2565b925050819055508060046000828254610bdd91906112d2565b9091555050600254610bf9906001600160a01b03168383610dab565b816001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d482604051610c3491815260200190565b60405180910390a25050565b6001600160a01b03831660009081526001602052604081205460ff16610ca25760405162461bcd60e51b815260206004820152601760248201527613db9b1e4819195c1bdcda5d1bdc9cc8185b1b1bddd959604a1b6044820152606401610335565b506344a1f60160e11b9392505050565b33610cc56000546001600160a01b031690565b6001600160a01b031614610ceb5760405162461bcd60e51b81526004016103359061123f565b6001600160a01b038116610d505760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610335565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691610e079190611361565b6000604051808303816000865af19150503d8060008114610e44576040519150601f19603f3d011682016040523d82523d6000602084013e610e49565b606091505b5091509150818015610e73575080511580610e73575080806020019051810190610e739190611390565b610ebf5760405162461bcd60e51b815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610335565b5050505050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691610f2a9190611361565b6000604051808303816000865af19150503d8060008114610f67576040519150601f19603f3d011682016040523d82523d6000602084013e610f6c565b606091505b5091509150818015610f96575080511580610f96575080806020019051810190610f969190611390565b610fee5760405162461bcd60e51b8152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f46416044820152631253115160e21b6064820152608401610335565b505050505050565b80356001600160a01b038116811461100d57600080fd5b919050565b60006020828403121561102457600080fd5b61102d82610ff6565b9392505050565b602080825282518282018190526000919060409081850190868401855b828110156110955781518051855286810151878601528581015186860152606080820151908601526080908101519085015260a09093019290850190600101611051565b5091979650505050505050565b600080604083850312156110b557600080fd5b6110be83610ff6565b946020939093013593505050565b60008060008060008060c087890312156110e557600080fd5b6110ee87610ff6565b9860208801359850604088013597606081013597506080810135965060a00135945092505050565b801515811461112457600080fd5b50565b6000806040838503121561113a57600080fd5b61114383610ff6565b9150602083013561115381611116565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b60008060006060848603121561118957600080fd5b61119284610ff6565b925060208401359150604084013567ffffffffffffffff808211156111b657600080fd5b818601915086601f8301126111ca57600080fd5b8135818111156111dc576111dc61115e565b604051601f8201601f19908116603f011681019083821181831017156112045761120461115e565b8160405282815289602084870101111561121d57600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60006020828403121561128657600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b818103818111156112b6576112b661128d565b92915050565b634e487b7160e01b600052603260045260246000fd5b808201808211156112b6576112b661128d565b80820281158282048414176112b6576112b661128d565b60008261131957634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016113305761133061128d565b5060010190565b60006020828403121561134957600080fd5b81516001600160e01b03198116811461102d57600080fd5b6000825160005b818110156113825760208186018101518583015201611368565b506000920191825250919050565b6000602082840312156113a257600080fd5b815161102d8161111656fea2646970667358221220e4c628f6abee3efb1f783b62b6e31cca85f41bc6dba637b6828bd79d78496ac164736f6c63430008130033000000000000000000000000df4da43dd3e9918f0784f8c92b8aa1b304c43243

Deployed ByteCode

0x608060405234801561001057600080fd5b50600436106101155760003560e01c80636bd7a97a116100a25780638943ec02116100715780638943ec02146102705780638da5cb5b1461029c578063d54ad2a1146102ad578063eed75f6d146102b6578063f2fde38b146102e957600080fd5b80636bd7a97a1461022f5780636f860d7414610242578063715018a614610255578063889014961461025d57600080fd5b806345f7f249116100e957806345f7f249146101985780634e71d92d146101a1578063505a1b31146101a9578063529849e9146101c95780635de297411461020457600080fd5b8062ae3bf81461011a57806304e869031461012f57806328733bb714610162578063420d4a021461016a575b600080fd5b61012d610128366004611012565b6102fc565b005b61014f61013d366004611012565b60066020526000908152604090205481565b6040519081526020015b60405180910390f35b61014f610423565b61017d610178366004611012565b6104b6565b60408051938452602084019290925290820152606001610159565b61014f60035481565b61012d6106a7565b6101bc6101b7366004611012565b6106b2565b6040516101599190611034565b6101dc6101d73660046110a2565b610759565b604080519586526020860194909452928401919091526060830152608082015260a001610159565b600254610217906001600160a01b031681565b6040516001600160a01b039091168152602001610159565b61012d61023d3660046110cc565b6107a7565b61012d610250366004611127565b610a6d565b61012d610b02565b61012d61026b366004611012565b610b85565b61028361027e366004611174565b610c40565b6040516001600160e01b03199091168152602001610159565b6000546001600160a01b0316610217565b61014f60045481565b6102d96102c4366004611012565b60016020526000908152604090205460ff1681565b6040519015158152602001610159565b61012d6102f7366004611012565b610cb2565b3361030f6000546001600160a01b031690565b6001600160a01b03161461033e5760405162461bcd60e51b81526004016103359061123f565b60405180910390fd5b6002546000906001600160a01b03908116908316036103665761035f610423565b90506103d1565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa1580156103aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103ce9190611274565b90505b6103dc823383610dab565b604080516001600160a01b0384168152602081018390527f542fa6bfee3b4746210fbdd1d83f9e49b65adde3639f8d8f165dd18347938af291015b60405180910390a15050565b6002546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa15801561046c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104909190611274565b905060006004546003546104a491906112a3565b90506104b081836112a3565b91505090565b6001600160a01b03811660009081526005602052604081205481906402540be40090825b8181101561066c576001600160a01b038616600090815260056020526040812080548390811061050c5761050c6112bc565b60009182526020918290206040805160a0810182526005909302909101805480845260018201549484019490945260028101549183019190915260038101546060830152600401546080820152915061056581876112d2565b9550600061271083602001518361057c91906112e5565b61058691906112fc565b90504283604001511161062b57600083608001518460400151426105aa91906112a3565b6105b491906112fc565b6105bf9060016112d2565b9050612710846060015182856105d591906112e5565b6105df91906112e5565b6105e991906112fc565b6105f390836112d2565b91506000846040015185608001518361060c91906112e5565b61061691906112d2565b905080881115610624578097505b505061063f565b826040015186111561063f57826040015195505b8181111561064a5750805b61065481896112d2565b975050505080806106649061131e565b9150506104da565b5061067784846112a3565b6001600160a01b03861660009081526006602052604090205490935061069d90856112a3565b9350509193909250565b6106b033610b85565b565b6001600160a01b0381166000908152600560209081526040808320805482518185028101850190935280835260609492939192909184015b8282101561074e57838290600052602060002090600502016040518060a001604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481525050815260200190600101906106ea565b505050509050919050565b6005602052816000526040600020818154811061077557600080fd5b600091825260209091206005909102018054600182015460028301546003840154600490940154929550909350919085565b3360009081526001602052604090205460ff166108005760405162461bcd60e51b815260206004820152601760248201527613db9b1e4819195c1bdcda5d1bdc9cc8185b1b1bddd959604a1b6044820152606401610335565b6001600160a01b03861660009081526005602052604090205460641161088e5760405162461bcd60e51b815260206004820152603960248201527f546f6f206d616e7920616c6c6f636174696f6e7320666f72206f6e652061646460448201527f726573732c2075736520616e6f746865722061646472657373000000000000006064820152608401610335565b6002546108a6906001600160a01b0316333088610ec6565b6108ae610423565b8511156108f15760405162461bcd60e51b81526020600482015260116024820152704e6f7420656e6f75676820746f6b656e7360781b6044820152606401610335565b6001600160a01b0386166000908152600560208181526040808420815160a0810183528a81528084018a81529281018981526060820189815260808301898152845460018181018755958a5296892093519690970290920194855592519184019190915590516002830155516003808301919091559151600490910155805487929061097e9084906112d2565b9091555050853b15610a0b576040516344a1f60160e11b81523060048201526000602482018190526060604483015260648201526001600160a01b03871690638943ec02906084016020604051808303816000875af11580156109e5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a099190611337565b505b604080518681526020810186905290810184905260608101839052608081018290526001600160a01b038716907f585acc8130c6cd35ae5bb61237605676cd4ec0a81dc2bf91a06b37270e81c3929060a00160405180910390a2505050505050565b33610a806000546001600160a01b031690565b6001600160a01b031614610aa65760405162461bcd60e51b81526004016103359061123f565b6001600160a01b038216600081815260016020908152604091829020805460ff19168515159081179091558251938452908301527fb1252fa67b4c05afbdaadfae34890b205103c0212a9e062b3978e8cd573631a99101610417565b33610b156000546001600160a01b031690565b6001600160a01b031614610b3b5760405162461bcd60e51b81526004016103359061123f565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000610b90826104b6565b5050905080600014610bf9576001600160a01b03821660009081526006602052604081208054839290610bc49084906112d2565b925050819055508060046000828254610bdd91906112d2565b9091555050600254610bf9906001600160a01b03168383610dab565b816001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d482604051610c3491815260200190565b60405180910390a25050565b6001600160a01b03831660009081526001602052604081205460ff16610ca25760405162461bcd60e51b815260206004820152601760248201527613db9b1e4819195c1bdcda5d1bdc9cc8185b1b1bddd959604a1b6044820152606401610335565b506344a1f60160e11b9392505050565b33610cc56000546001600160a01b031690565b6001600160a01b031614610ceb5760405162461bcd60e51b81526004016103359061123f565b6001600160a01b038116610d505760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610335565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691610e079190611361565b6000604051808303816000865af19150503d8060008114610e44576040519150601f19603f3d011682016040523d82523d6000602084013e610e49565b606091505b5091509150818015610e73575080511580610e73575080806020019051810190610e739190611390565b610ebf5760405162461bcd60e51b815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610335565b5050505050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691610f2a9190611361565b6000604051808303816000865af19150503d8060008114610f67576040519150601f19603f3d011682016040523d82523d6000602084013e610f6c565b606091505b5091509150818015610f96575080511580610f96575080806020019051810190610f969190611390565b610fee5760405162461bcd60e51b8152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f46416044820152631253115160e21b6064820152608401610335565b505050505050565b80356001600160a01b038116811461100d57600080fd5b919050565b60006020828403121561102457600080fd5b61102d82610ff6565b9392505050565b602080825282518282018190526000919060409081850190868401855b828110156110955781518051855286810151878601528581015186860152606080820151908601526080908101519085015260a09093019290850190600101611051565b5091979650505050505050565b600080604083850312156110b557600080fd5b6110be83610ff6565b946020939093013593505050565b60008060008060008060c087890312156110e557600080fd5b6110ee87610ff6565b9860208801359850604088013597606081013597506080810135965060a00135945092505050565b801515811461112457600080fd5b50565b6000806040838503121561113a57600080fd5b61114383610ff6565b9150602083013561115381611116565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b60008060006060848603121561118957600080fd5b61119284610ff6565b925060208401359150604084013567ffffffffffffffff808211156111b657600080fd5b818601915086601f8301126111ca57600080fd5b8135818111156111dc576111dc61115e565b604051601f8201601f19908116603f011681019083821181831017156112045761120461115e565b8160405282815289602084870101111561121d57600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60006020828403121561128657600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b818103818111156112b6576112b661128d565b92915050565b634e487b7160e01b600052603260045260246000fd5b808201808211156112b6576112b661128d565b80820281158282048414176112b6576112b661128d565b60008261131957634e487b7160e01b600052601260045260246000fd5b500490565b6000600182016113305761133061128d565b5060010190565b60006020828403121561134957600080fd5b81516001600160e01b03198116811461102d57600080fd5b6000825160005b818110156113825760208186018101518583015201611368565b506000920191825250919050565b6000602082840312156113a257600080fd5b815161102d8161111656fea2646970667358221220e4c628f6abee3efb1f783b62b6e31cca85f41bc6dba637b6828bd79d78496ac164736f6c63430008130033