ETH Price: $2,506.55 (-0.36%)
Gas: 1.76 Gwei

Token

CPUcoin (CPU)
 

Overview

Max Total Supply

5,000,000,000 CPU

Holders

223 (0.00%)

Market

Price

$0.01 @ 0.000004 ETH (+2.23%)

Onchain Market Cap

$45,885,700.00

Circulating Supply Market Cap

$0.00

Other Info

Token Contract (WITH 18 Decimals)

Balance
125,955.593084201858912021 CPU

Value
$1,155.91 ( ~0.461155822908195 Eth) [0.0025%]
0x10C699C787422F2306f5BAaC75367B3b9662AC76
Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

The decentralized Infrastructure-as-a-Service solution to reduce cloud infrastructure costs by creating a new sharing economy for unused CPU/GPU power.

Market

Volume (24H):$61,360.00
Market Capitalization:$0.00
Circulating Supply:0.00 CPU
Market Data Source: Coinmarketcap

# Exchange Pair Price  24H Volume % Volume
1
MEXC
CPU-USDT$0.0092
0.0000037 Eth
$51,477.00
5,607,334.500 CPU
83.8449%
2
ProBit Global
CPU-USDT$0.0092
0.0000037 Eth
$9,816.94
1,070,697.140 CPU
16.0098%
3
Uniswap V3 (Ethereum)
0X6D52DFEFB16BB9CDC78BFCA09061E44574886626-0XC02AAA39B223FE8D0A0E5C4F27EAD9083C756CC2$0.0096
0.0000038 Eth
$93.51
9,714.546 0X6D52DFEFB16BB9CDC78BFCA09061E44574886626
0.1453%

Contract Source Code Verified (Exact Match)

Contract Name:
CpuCoin

Compiler Version
v0.5.7+commit.6da8b019

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2019-05-09
*/

pragma solidity ^0.5.7;

contract Identity {
    mapping(address => string) private _names;

    /**
     * Handy function to associate a short name with the account.
     */
    function iAm(string memory shortName) public {
        _names[msg.sender] = shortName;
    }

    /**
     * Handy function to confirm address of the current account.
     */
    function whereAmI() public view returns (address yourAddress) {
        address myself = msg.sender;
        return myself;
    }

    /**
     * Handy function to confirm short name of the current account.
     */
    function whoAmI() public view returns (string memory yourName) {
        return (_names[msg.sender]);
    }
}


pragma solidity ^0.5.0;

/**
 * @title ERC20 interface
 * @dev see https://eips.ethereum.org/EIPS/eip-20
 */
interface IERC20 {
    function transfer(address to, uint256 value) external returns (bool);

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

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

    function totalSupply() external view returns (uint256);

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

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

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

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


pragma solidity ^0.5.0;

/**
 * @title SafeMath
 * @dev Unsigned math operations with safety checks that revert on error.
 */
library SafeMath {
    /**
     * @dev Multiplies two unsigned integers, reverts on overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b);

        return c;
    }

    /**
     * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "Insufficient funds");
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Adds two unsigned integers, reverts on overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a);

        return c;
    }

    /**
     * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),
     * reverts when dividing by zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b != 0);
        return a % b;
    }
}


pragma solidity ^0.5.0;


/**
 * @title Standard ERC20 token
 *
 * @dev Implementation of the basic standard token.
 * https://eips.ethereum.org/EIPS/eip-20
 * Originally based on code by FirstBlood:
 * https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
 *
 * This implementation emits additional Approval events, allowing applications to reconstruct the allowance status for
 * all accounts just by listening to said events. Note that this isn't required by the specification, and other
 * compliant implementations may not do it.
 */
contract ERC20 is IERC20 {
    using SafeMath for uint256;

    mapping (address => uint256) private _balances;

    mapping (address => mapping (address => uint256)) private _allowed;

    uint256 private _totalSupply;

    /**
     * @dev Total number of tokens in existence.
     */
    function totalSupply() public view returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev Gets the balance of the specified address.
     * @param owner The address to query the balance of.
     * @return A uint256 representing the amount owned by the passed address.
     */
    function balanceOf(address owner) public view returns (uint256) {
        return _balances[owner];
    }

    /**
     * @dev Function to check the amount of tokens that an owner allowed to a spender.
     * @param owner address The address which owns the funds.
     * @param spender address The address which will spend the funds.
     * @return A uint256 specifying the amount of tokens still available for the spender.
     */
    function allowance(address owner, address spender) public view returns (uint256) {
        return _allowed[owner][spender];
    }

    /**
     * @dev Transfer token to a specified address.
     * @param to The address to transfer to.
     * @param value The amount to be transferred.
     */
    function transfer(address to, uint256 value) public returns (bool) {
        _transfer(msg.sender, to, value);
        return true;
    }

    /**
     * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
     * Beware that changing an allowance with this method brings the risk that someone may use both the old
     * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
     * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     * @param spender The address which will spend the funds.
     * @param value The amount of tokens to be spent.
     */
    function approve(address spender, uint256 value) public returns (bool) {
        _approve(msg.sender, spender, value);
        return true;
    }

    /**
     * @dev Transfer tokens from one address to another.
     * Note that while this function emits an Approval event, this is not required as per the specification,
     * and other compliant implementations may not emit the event.
     * @param from address The address which you want to send tokens from
     * @param to address The address which you want to transfer to
     * @param value uint256 the amount of tokens to be transferred
     */
    function transferFrom(address from, address to, uint256 value) public returns (bool) {
        _transfer(from, to, value);
        _approve(from, msg.sender, _allowed[from][msg.sender].sub(value));
        return true;
    }

    /**
     * @dev Increase the amount of tokens that an owner allowed to a spender.
     * approve should be called when _allowed[msg.sender][spender] == 0. To increment
     * allowed value is better to use this function to avoid 2 calls (and wait until
     * the first transaction is mined)
     * From MonolithDAO Token.sol
     * Emits an Approval event.
     * @param spender The address which will spend the funds.
     * @param addedValue The amount of tokens to increase the allowance by.
     */
    function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
        _approve(msg.sender, spender, _allowed[msg.sender][spender].add(addedValue));
        return true;
    }

    /**
     * @dev Decrease the amount of tokens that an owner allowed to a spender.
     * approve should be called when _allowed[msg.sender][spender] == 0. To decrement
     * allowed value is better to use this function to avoid 2 calls (and wait until
     * the first transaction is mined)
     * From MonolithDAO Token.sol
     * Emits an Approval event.
     * @param spender The address which will spend the funds.
     * @param subtractedValue The amount of tokens to decrease the allowance by.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
        _approve(msg.sender, spender, _allowed[msg.sender][spender].sub(subtractedValue));
        return true;
    }

    /**
     * @dev Transfer token for a specified addresses.
     * @param from The address to transfer from.
     * @param to The address to transfer to.
     * @param value The amount to be transferred.
     */
    function _transfer(address from, address to, uint256 value) internal {
        require(to != address(0));

        _balances[from] = _balances[from].sub(value);
        _balances[to] = _balances[to].add(value);
        emit Transfer(from, to, value);
    }

    /**
     * @dev Internal function that mints an amount of the token and assigns it to
     * an account. This encapsulates the modification of balances such that the
     * proper events are emitted.
     * @param account The account that will receive the created tokens.
     * @param value The amount that will be created.
     */
    function _mint(address account, uint256 value) internal {
        require(account != address(0));

        _totalSupply = _totalSupply.add(value);
        _balances[account] = _balances[account].add(value);
        emit Transfer(address(0), account, value);
    }

    /**
     * @dev Internal function that burns an amount of the token of a given
     * account.
     * @param account The account whose tokens will be burnt.
     * @param value The amount that will be burnt.
     */
    function _burn(address account, uint256 value) internal {
        require(account != address(0));

        _totalSupply = _totalSupply.sub(value);
        _balances[account] = _balances[account].sub(value);
        emit Transfer(account, address(0), value);
    }

    /**
     * @dev Approve an address to spend another addresses' tokens.
     * @param owner The address that owns the tokens.
     * @param spender The address that will spend the tokens.
     * @param value The number of tokens that can be spent.
     */
    function _approve(address owner, address spender, uint256 value) internal {
        require(owner != address(0));
        require(spender != address(0));

        _allowed[owner][spender] = value;
        emit Approval(owner, spender, value);
    }

    /**
     * @dev Internal function that burns an amount of the token of a given
     * account, deducting from the sender's allowance for said account. Uses the
     * internal burn function.
     * Emits an Approval event (reflecting the reduced allowance).
     * @param account The account whose tokens will be burnt.
     * @param value The amount that will be burnt.
     */
    function _burnFrom(address account, uint256 value) internal {
        _burn(account, value);
        _approve(account, msg.sender, _allowed[account][msg.sender].sub(value));
    }
}


pragma solidity ^0.5.0;


/**
 * @title Burnable Token
 * @dev Token that can be irreversibly burned (destroyed).
 */
contract ERC20Burnable is ERC20 {
    /**
     * @dev Burns a specific amount of tokens.
     * @param value The amount of token to be burned.
     */
    function burn(uint256 value) public {
        _burn(msg.sender, value);
    }

    /**
     * @dev Burns a specific amount of tokens from the target address and decrements allowance.
     * @param from address The account whose tokens will be burned.
     * @param value uint256 The amount of token to be burned.
     */
    function burnFrom(address from, uint256 value) public {
        _burnFrom(from, value);
    }
}


pragma solidity ^0.5.0;


/**
 * @title ERC20Detailed token
 * @dev The decimals are only for visualization purposes.
 * All the operations are done using the smallest and indivisible token unit,
 * just as on Ethereum all the operations are done in wei.
 */
contract ERC20Detailed is IERC20 {
    string private _name;
    string private _symbol;
    uint8 private _decimals;

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

    /**
     * @return the name of the token.
     */
    function name() public view returns (string memory) {
        return _name;
    }

    /**
     * @return the symbol of the token.
     */
    function symbol() public view returns (string memory) {
        return _symbol;
    }

    /**
     * @return the number of decimals of the token.
     */
    function decimals() public view returns (uint8) {
        return _decimals;
    }
}


pragma solidity ^0.5.0;

/**
 * @title Ownable
 * @dev The Ownable contract has an owner address, and provides basic authorization control
 * functions, this simplifies the implementation of "user permissions".
 */
contract Ownable {
    address private _owner;

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

    /**
     * @dev The Ownable constructor sets the original `owner` of the contract to the sender
     * account.
     */
    constructor () internal {
        _owner = msg.sender;
        emit OwnershipTransferred(address(0), _owner);
    }

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

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(isOwner());
        _;
    }

    /**
     * @return true if `msg.sender` is the owner of the contract.
     */
    function isOwner() public view returns (bool) {
        return msg.sender == _owner;
    }

    /**
     * @dev Allows the current owner to relinquish control of the contract.
     * It will not be possible to call the functions with the `onlyOwner`
     * modifier anymore.
     * @notice Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public onlyOwner {
        emit OwnershipTransferred(_owner, address(0));
        _owner = address(0);
    }

    /**
     * @dev Allows the current owner to transfer control of the contract to a newOwner.
     * @param newOwner The address to transfer ownership to.
     */
    function transferOwnership(address newOwner) public onlyOwner {
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers control of the contract to a newOwner.
     * @param newOwner The address to transfer ownership to.
     */
    function _transferOwnership(address newOwner) internal {
        require(newOwner != address(0));
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
}


pragma solidity ^0.5.0;

/**
 * @title Roles
 * @dev Library for managing addresses assigned to a Role.
 */
library Roles {
    struct Role {
        mapping (address => bool) bearer;
    }

    /**
     * @dev Give an account access to this role.
     */
    function add(Role storage role, address account) internal {
        require(!has(role, account));
        role.bearer[account] = true;
    }

    /**
     * @dev Remove an account's access to this role.
     */
    function remove(Role storage role, address account) internal {
        require(has(role, account));
        role.bearer[account] = false;
    }

    /**
     * @dev Check if an account has this role.
     * @return bool
     */
    function has(Role storage role, address account) internal view returns (bool) {
        require(account != address(0));
        return role.bearer[account];
    }
}


pragma solidity ^0.5.7;


/**
 * @dev This role allows the contract to be paused, so that in case something goes horribly wrong
 * during an ICO, the owner/administrator has an ability to suspend all transactions while things
 * are sorted out.
 *
 * NOTE: We have implemented a role model only the contract owner can assign/un-assign roles.
 * This is necessary to support enterprise software, which requires a permissions model in which
 * roles can be owner-administered, in contrast to a blockchain community approach in which
 * permissions can be self-administered. Therefore, this implementation replaces the self-service
 * "renounce" approach with one where only the owner is allowed to makes role changes.
 *
 * Owner is not allowed to renounce ownership, lest the contract go without administration. But
 * it is ok for owner to shed initially granted roles by removing role from self.
 */
contract PauserRole is Ownable {
    using Roles for Roles.Role;

    event PauserAdded(address indexed account);
    event PauserRemoved(address indexed account);

    Roles.Role private _pausers;

    constructor () internal {
        _addPauser(msg.sender);
    }

    modifier onlyPauser() {
        require(isPauser(msg.sender), "onlyPauser");
        _;
    }

    function isPauser(address account) public view returns (bool) {
        return _pausers.has(account);
    }

    function addPauser(address account) public onlyOwner {
        _addPauser(account);
    }

    function removePauser(address account) public onlyOwner {
        _removePauser(account);
    }

    function _addPauser(address account) private {
        require(account != address(0));
        _pausers.add(account);
        emit PauserAdded(account);
    }

    function _removePauser(address account) private {
        require(account != address(0));
        _pausers.remove(account);
        emit PauserRemoved(account);
    }


    // =========================================================================
    // === Overridden ERC20 functionality
    // =========================================================================

    /**
     * Ensure there is no way for the contract to end up with no owner. That would inadvertently result in
     * pauser administration becoming impossible. We override this to always disallow it.
     */
    function renounceOwnership() public onlyOwner {
        require(false, "forbidden");
    }

    /**
     * @dev Allows the current owner to transfer control of the contract to a newOwner.
     * @param newOwner The address to transfer ownership to.
     */
    function transferOwnership(address newOwner) public onlyOwner {
        _removePauser(msg.sender);
        super.transferOwnership(newOwner);
        _addPauser(newOwner);
    }
}


pragma solidity ^0.5.0;


/**
 * @title Pausable
 * @dev Base contract which allows children to implement an emergency stop mechanism.
 */
contract Pausable is PauserRole {
    event Paused(address account);
    event Unpaused(address account);

    bool private _paused;

    constructor () internal {
        _paused = false;
    }

    /**
     * @return True if the contract is paused, false otherwise.
     */
    function paused() public view returns (bool) {
        return _paused;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     */
    modifier whenNotPaused() {
        require(!_paused);
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     */
    modifier whenPaused() {
        require(_paused);
        _;
    }

    /**
     * @dev Called by a pauser to pause, triggers stopped state.
     */
    function pause() public onlyPauser whenNotPaused {
        _paused = true;
        emit Paused(msg.sender);
    }

    /**
     * @dev Called by a pauser to unpause, returns to normal state.
     */
    function unpause() public onlyPauser whenPaused {
        _paused = false;
        emit Unpaused(msg.sender);
    }
}


pragma solidity ^0.5.0;


/**
 * @title Pausable token
 * @dev ERC20 modified with pausable transfers.
 */
contract ERC20Pausable is ERC20, Pausable {
    function transfer(address to, uint256 value) public whenNotPaused returns (bool) {
        return super.transfer(to, value);
    }

    function transferFrom(address from, address to, uint256 value) public whenNotPaused returns (bool) {
        return super.transferFrom(from, to, value);
    }

    function approve(address spender, uint256 value) public whenNotPaused returns (bool) {
        return super.approve(spender, value);
    }

    function increaseAllowance(address spender, uint addedValue) public whenNotPaused returns (bool) {
        return super.increaseAllowance(spender, addedValue);
    }

    function decreaseAllowance(address spender, uint subtractedValue) public whenNotPaused returns (bool) {
        return super.decreaseAllowance(spender, subtractedValue);
    }
}


pragma solidity ^0.5.7;


contract VerifiedAccount is ERC20, Ownable {

    mapping(address => bool) private _isRegistered;

    constructor () internal {
        // The smart contract starts off registering itself, since address is known.
        registerAccount();
    }

    event AccountRegistered(address indexed account);

    /**
     * This registers the calling wallet address as a known address. Operations that transfer responsibility
     * may require the target account to be a registered account, to protect the system from getting into a
     * state where administration or a large amount of funds can become forever inaccessible.
     */
    function registerAccount() public returns (bool ok) {
        _isRegistered[msg.sender] = true;
        emit AccountRegistered(msg.sender);
        return true;
    }

    function isRegistered(address account) public view returns (bool ok) {
        return _isRegistered[account];
    }

    function _accountExists(address account) internal view returns (bool exists) {
        return account == msg.sender || _isRegistered[account];
    }

    modifier onlyExistingAccount(address account) {
        require(_accountExists(account), "account not registered");
        _;
    }


    // =========================================================================
    // === Safe ERC20 methods
    // =========================================================================

    function safeTransfer(address to, uint256 value) public onlyExistingAccount(to) returns (bool ok) {
        transfer(to, value);
        return true;
    }

    function safeApprove(address spender, uint256 value) public onlyExistingAccount(spender) returns (bool ok) {
        approve(spender, value);
        return true;
    }

    function safeTransferFrom(address from, address to, uint256 value) public onlyExistingAccount(to) returns (bool ok) {
        transferFrom(from, to, value);
        return true;
    }


    // =========================================================================
    // === Safe ownership transfer
    // =========================================================================

    /**
     * @dev Allows the current owner to transfer control of the contract to a newOwner.
     * @param newOwner The address to transfer ownership to.
     */
    function transferOwnership(address newOwner) public onlyExistingAccount(newOwner) onlyOwner {
        super.transferOwnership(newOwner);
    }
}


pragma solidity ^0.5.7;


/**
 * @dev GrantorRole trait
 *
 * This adds support for a role that allows creation of vesting token grants, allocated from the
 * role holder's wallet.
 *
 * NOTE: We have implemented a role model only the contract owner can assign/un-assign roles.
 * This is necessary to support enterprise software, which requires a permissions model in which
 * roles can be owner-administered, in contrast to a blockchain community approach in which
 * permissions can be self-administered. Therefore, this implementation replaces the self-service
 * "renounce" approach with one where only the owner is allowed to makes role changes.
 *
 * Owner is not allowed to renounce ownership, lest the contract go without administration. But
 * it is ok for owner to shed initially granted roles by removing role from self.
 */
contract GrantorRole is Ownable {
    bool private constant OWNER_UNIFORM_GRANTOR_FLAG = false;

    using Roles for Roles.Role;

    event GrantorAdded(address indexed account);
    event GrantorRemoved(address indexed account);

    Roles.Role private _grantors;
    mapping(address => bool) private _isUniformGrantor;

    constructor () internal {
        _addGrantor(msg.sender, OWNER_UNIFORM_GRANTOR_FLAG);
    }

    modifier onlyGrantor() {
        require(isGrantor(msg.sender), "onlyGrantor");
        _;
    }

    modifier onlyGrantorOrSelf(address account) {
        require(isGrantor(msg.sender) || msg.sender == account, "onlyGrantorOrSelf");
        _;
    }

    function isGrantor(address account) public view returns (bool) {
        return _grantors.has(account);
    }

    function addGrantor(address account, bool isUniformGrantor) public onlyOwner {
        _addGrantor(account, isUniformGrantor);
    }

    function removeGrantor(address account) public onlyOwner {
        _removeGrantor(account);
    }

    function _addGrantor(address account, bool isUniformGrantor) private {
        require(account != address(0));
        _grantors.add(account);
        _isUniformGrantor[account] = isUniformGrantor;
        emit GrantorAdded(account);
    }

    function _removeGrantor(address account) private {
        require(account != address(0));
        _grantors.remove(account);
        emit GrantorRemoved(account);
    }

    function isUniformGrantor(address account) public view returns (bool) {
        return isGrantor(account) && _isUniformGrantor[account];
    }

    modifier onlyUniformGrantor() {
        require(isUniformGrantor(msg.sender), "onlyUniformGrantor");
        // Only grantor role can do this.
        _;
    }


    // =========================================================================
    // === Overridden ERC20 functionality
    // =========================================================================

    /**
     * Ensure there is no way for the contract to end up with no owner. That would inadvertently result in
     * token grant administration becoming impossible. We override this to always disallow it.
     */
    function renounceOwnership() public onlyOwner {
        require(false, "forbidden");
    }

    /**
     * @dev Allows the current owner to transfer control of the contract to a newOwner.
     * @param newOwner The address to transfer ownership to.
     */
    function transferOwnership(address newOwner) public onlyOwner {
        _removeGrantor(msg.sender);
        super.transferOwnership(newOwner);
        _addGrantor(newOwner, OWNER_UNIFORM_GRANTOR_FLAG);
    }
}


pragma solidity ^0.5.7;


interface IERC20Vestable {
    function getIntrinsicVestingSchedule(address grantHolder)
    external
    view
    returns (
        uint32 cliffDuration,
        uint32 vestDuration,
        uint32 vestIntervalDays
    );

    function grantVestingTokens(
        address beneficiary,
        uint256 totalAmount,
        uint256 vestingAmount,
        uint32 startDay,
        uint32 duration,
        uint32 cliffDuration,
        uint32 interval,
        bool isRevocable
    ) external returns (bool ok);

    function today() external view returns (uint32 dayNumber);

    function vestingForAccountAsOf(
        address grantHolder,
        uint32 onDayOrToday
    )
    external
    view
    returns (
        uint256 amountVested,
        uint256 amountNotVested,
        uint256 amountOfGrant,
        uint32 vestStartDay,
        uint32 cliffDuration,
        uint32 vestDuration,
        uint32 vestIntervalDays,
        bool isActive,
        bool wasRevoked
    );

    function vestingAsOf(uint32 onDayOrToday) external view returns (
        uint256 amountVested,
        uint256 amountNotVested,
        uint256 amountOfGrant,
        uint32 vestStartDay,
        uint32 cliffDuration,
        uint32 vestDuration,
        uint32 vestIntervalDays,
        bool isActive,
        bool wasRevoked
    );

    function revokeGrant(address grantHolder, uint32 onDay) external returns (bool);


    event VestingScheduleCreated(
        address indexed vestingLocation,
        uint32 cliffDuration, uint32 indexed duration, uint32 interval,
        bool indexed isRevocable);

    event VestingTokensGranted(
        address indexed beneficiary,
        uint256 indexed vestingAmount,
        uint32 startDay,
        address vestingLocation,
        address indexed grantor);

    event GrantRevoked(address indexed grantHolder, uint32 indexed onDay);
}


pragma solidity ^0.5.7;


/**
 * @title Contract for grantable ERC20 token vesting schedules
 *
 * @notice Adds to an ERC20 support for grantor wallets, which are able to grant vesting tokens to
 *   beneficiary wallets, following per-wallet custom vesting schedules.
 *
 * @dev Contract which gives subclass contracts the ability to act as a pool of funds for allocating
 *   tokens to any number of other addresses. Token grants support the ability to vest over time in
 *   accordance a predefined vesting schedule. A given wallet can receive no more than one token grant.
 *
 *   Tokens are transferred from the pool to the recipient at the time of grant, but the recipient
 *   will only able to transfer tokens out of their wallet after they have vested. Transfers of non-
 *   vested tokens are prevented.
 *
 *   Two types of toke grants are supported:
 *   - Irrevocable grants, intended for use in cases when vesting tokens have been issued in exchange
 *     for value, such as with tokens that have been purchased in an ICO.
 *   - Revocable grants, intended for use in cases when vesting tokens have been gifted to the holder,
 *     such as with employee grants that are given as compensation.
 */
contract ERC20Vestable is ERC20, VerifiedAccount, GrantorRole, IERC20Vestable {
    using SafeMath for uint256;

    // Date-related constants for sanity-checking dates to reject obvious erroneous inputs
    // and conversions from seconds to days and years that are more or less leap year-aware.
    uint32 private constant THOUSAND_YEARS_DAYS = 365243;                   /* See https://www.timeanddate.com/date/durationresult.html?m1=1&d1=1&y1=2000&m2=1&d2=1&y2=3000 */
    uint32 private constant TEN_YEARS_DAYS = THOUSAND_YEARS_DAYS / 100;     /* Includes leap years (though it doesn't really matter) */
    uint32 private constant SECONDS_PER_DAY = 24 * 60 * 60;                 /* 86400 seconds in a day */
    uint32 private constant JAN_1_2000_SECONDS = 946684800;                 /* Saturday, January 1, 2000 0:00:00 (GMT) (see https://www.epochconverter.com/) */
    uint32 private constant JAN_1_2000_DAYS = JAN_1_2000_SECONDS / SECONDS_PER_DAY;
    uint32 private constant JAN_1_3000_DAYS = JAN_1_2000_DAYS + THOUSAND_YEARS_DAYS;

    struct vestingSchedule {
        bool isValid;               /* true if an entry exists and is valid */
        bool isRevocable;           /* true if the vesting option is revocable (a gift), false if irrevocable (purchased) */
        uint32 cliffDuration;       /* Duration of the cliff, with respect to the grant start day, in days. */
        uint32 duration;            /* Duration of the vesting schedule, with respect to the grant start day, in days. */
        uint32 interval;            /* Duration in days of the vesting interval. */
    }

    struct tokenGrant {
        bool isActive;              /* true if this vesting entry is active and in-effect entry. */
        bool wasRevoked;            /* true if this vesting schedule was revoked. */
        uint32 startDay;            /* Start day of the grant, in days since the UNIX epoch (start of day). */
        uint256 amount;             /* Total number of tokens that vest. */
        address vestingLocation;    /* Address of wallet that is holding the vesting schedule. */
        address grantor;            /* Grantor that made the grant */
    }

    mapping(address => vestingSchedule) private _vestingSchedules;
    mapping(address => tokenGrant) private _tokenGrants;


    // =========================================================================
    // === Methods for administratively creating a vesting schedule for an account.
    // =========================================================================

    /**
     * @dev This one-time operation permanently establishes a vesting schedule in the given account.
     *
     * For standard grants, this establishes the vesting schedule in the beneficiary's account.
     * For uniform grants, this establishes the vesting schedule in the linked grantor's account.
     *
     * @param vestingLocation = Account into which to store the vesting schedule. Can be the account
     *   of the beneficiary (for one-off grants) or the account of the grantor (for uniform grants
     *   made from grant pools).
     * @param cliffDuration = Duration of the cliff, with respect to the grant start day, in days.
     * @param duration = Duration of the vesting schedule, with respect to the grant start day, in days.
     * @param interval = Number of days between vesting increases.
     * @param isRevocable = True if the grant can be revoked (i.e. was a gift) or false if it cannot
     *   be revoked (i.e. tokens were purchased).
     */
    function _setVestingSchedule(
        address vestingLocation,
        uint32 cliffDuration, uint32 duration, uint32 interval,
        bool isRevocable) internal returns (bool ok) {

        // Check for a valid vesting schedule given (disallow absurd values to reject likely bad input).
        require(
            duration > 0 && duration <= TEN_YEARS_DAYS
            && cliffDuration < duration
            && interval >= 1,
            "invalid vesting schedule"
        );

        // Make sure the duration values are in harmony with interval (both should be an exact multiple of interval).
        require(
            duration % interval == 0 && cliffDuration % interval == 0,
            "invalid cliff/duration for interval"
        );

        // Create and populate a vesting schedule.
        _vestingSchedules[vestingLocation] = vestingSchedule(
            true/*isValid*/,
            isRevocable,
            cliffDuration, duration, interval
        );

        // Emit the event and return success.
        emit VestingScheduleCreated(
            vestingLocation,
            cliffDuration, duration, interval,
            isRevocable);
        return true;
    }

    function _hasVestingSchedule(address account) internal view returns (bool ok) {
        return _vestingSchedules[account].isValid;
    }

    /**
     * @dev returns all information about the vesting schedule directly associated with the given
     * account. This can be used to double check that a uniform grantor has been set up with a
     * correct vesting schedule. Also, recipients of standard (non-uniform) grants can use this.
     * This method is only callable by the account holder or a grantor, so this is mainly intended
     * for administrative use.
     *
     * Holders of uniform grants must use vestingAsOf() to view their vesting schedule, as it is
     * stored in the grantor account.
     *
     * @param grantHolder = The address to do this for.
     *   the special value 0 to indicate today.
     * @return = A tuple with the following values:
     *   vestDuration = grant duration in days.
     *   cliffDuration = duration of the cliff.
     *   vestIntervalDays = number of days between vesting periods.
     */
    function getIntrinsicVestingSchedule(address grantHolder)
    public
    view
    onlyGrantorOrSelf(grantHolder)
    returns (
        uint32 vestDuration,
        uint32 cliffDuration,
        uint32 vestIntervalDays
    )
    {
        return (
        _vestingSchedules[grantHolder].duration,
        _vestingSchedules[grantHolder].cliffDuration,
        _vestingSchedules[grantHolder].interval
        );
    }


    // =========================================================================
    // === Token grants (general-purpose)
    // === Methods to be used for administratively creating one-off token grants with vesting schedules.
    // =========================================================================

    /**
     * @dev Immediately grants tokens to an account, referencing a vesting schedule which may be
     * stored in the same account (individual/one-off) or in a different account (shared/uniform).
     *
     * @param beneficiary = Address to which tokens will be granted.
     * @param totalAmount = Total number of tokens to deposit into the account.
     * @param vestingAmount = Out of totalAmount, the number of tokens subject to vesting.
     * @param startDay = Start day of the grant's vesting schedule, in days since the UNIX epoch
     *   (start of day). The startDay may be given as a date in the future or in the past, going as far
     *   back as year 2000.
     * @param vestingLocation = Account where the vesting schedule is held (must already exist).
     * @param grantor = Account which performed the grant. Also the account from where the granted
     *   funds will be withdrawn.
     */
    function _grantVestingTokens(
        address beneficiary,
        uint256 totalAmount,
        uint256 vestingAmount,
        uint32 startDay,
        address vestingLocation,
        address grantor
    )
    internal returns (bool ok)
    {
        // Make sure no prior grant is in effect.
        require(!_tokenGrants[beneficiary].isActive, "grant already exists");

        // Check for valid vestingAmount
        require(
            vestingAmount <= totalAmount && vestingAmount > 0
            && startDay >= JAN_1_2000_DAYS && startDay < JAN_1_3000_DAYS,
            "invalid vesting params");

        // Make sure the vesting schedule we are about to use is valid.
        require(_hasVestingSchedule(vestingLocation), "no such vesting schedule");

        // Transfer the total number of tokens from grantor into the account's holdings.
        _transfer(grantor, beneficiary, totalAmount);
        /* Emits a Transfer event. */

        // Create and populate a token grant, referencing vesting schedule.
        _tokenGrants[beneficiary] = tokenGrant(
            true/*isActive*/,
            false/*wasRevoked*/,
            startDay,
            vestingAmount,
            vestingLocation, /* The wallet address where the vesting schedule is kept. */
            grantor             /* The account that performed the grant (where revoked funds would be sent) */
        );

        // Emit the event and return success.
        emit VestingTokensGranted(beneficiary, vestingAmount, startDay, vestingLocation, grantor);
        return true;
    }

    /**
     * @dev Immediately grants tokens to an address, including a portion that will vest over time
     * according to a set vesting schedule. The overall duration and cliff duration of the grant must
     * be an even multiple of the vesting interval.
     *
     * @param beneficiary = Address to which tokens will be granted.
     * @param totalAmount = Total number of tokens to deposit into the account.
     * @param vestingAmount = Out of totalAmount, the number of tokens subject to vesting.
     * @param startDay = Start day of the grant's vesting schedule, in days since the UNIX epoch
     *   (start of day). The startDay may be given as a date in the future or in the past, going as far
     *   back as year 2000.
     * @param duration = Duration of the vesting schedule, with respect to the grant start day, in days.
     * @param cliffDuration = Duration of the cliff, with respect to the grant start day, in days.
     * @param interval = Number of days between vesting increases.
     * @param isRevocable = True if the grant can be revoked (i.e. was a gift) or false if it cannot
     *   be revoked (i.e. tokens were purchased).
     */
    function grantVestingTokens(
        address beneficiary,
        uint256 totalAmount,
        uint256 vestingAmount,
        uint32 startDay,
        uint32 duration,
        uint32 cliffDuration,
        uint32 interval,
        bool isRevocable
    ) public onlyGrantor returns (bool ok) {
        // Make sure no prior vesting schedule has been set.
        require(!_tokenGrants[beneficiary].isActive, "grant already exists");

        // The vesting schedule is unique to this wallet and so will be stored here,
        _setVestingSchedule(beneficiary, cliffDuration, duration, interval, isRevocable);

        // Issue grantor tokens to the beneficiary, using beneficiary's own vesting schedule.
        _grantVestingTokens(beneficiary, totalAmount, vestingAmount, startDay, beneficiary, msg.sender);

        return true;
    }

    /**
     * @dev This variant only grants tokens if the beneficiary account has previously self-registered.
     */
    function safeGrantVestingTokens(
        address beneficiary, uint256 totalAmount, uint256 vestingAmount,
        uint32 startDay, uint32 duration, uint32 cliffDuration, uint32 interval,
        bool isRevocable) public onlyGrantor onlyExistingAccount(beneficiary) returns (bool ok) {

        return grantVestingTokens(
            beneficiary, totalAmount, vestingAmount,
            startDay, duration, cliffDuration, interval,
            isRevocable);
    }


    // =========================================================================
    // === Check vesting.
    // =========================================================================

    /**
     * @dev returns the day number of the current day, in days since the UNIX epoch.
     */
    function today() public view returns (uint32 dayNumber) {
        return uint32(block.timestamp / SECONDS_PER_DAY);
    }

    function _effectiveDay(uint32 onDayOrToday) internal view returns (uint32 dayNumber) {
        return onDayOrToday == 0 ? today() : onDayOrToday;
    }

    /**
     * @dev Determines the amount of tokens that have not vested in the given account.
     *
     * The math is: not vested amount = vesting amount * (end date - on date)/(end date - start date)
     *
     * @param grantHolder = The account to check.
     * @param onDayOrToday = The day to check for, in days since the UNIX epoch. Can pass
     *   the special value 0 to indicate today.
     */
    function _getNotVestedAmount(address grantHolder, uint32 onDayOrToday) internal view returns (uint256 amountNotVested) {
        tokenGrant storage grant = _tokenGrants[grantHolder];
        vestingSchedule storage vesting = _vestingSchedules[grant.vestingLocation];
        uint32 onDay = _effectiveDay(onDayOrToday);

        // If there's no schedule, or before the vesting cliff, then the full amount is not vested.
        if (!grant.isActive || onDay < grant.startDay + vesting.cliffDuration)
        {
            // None are vested (all are not vested)
            return grant.amount;
        }
        // If after end of vesting, then the not vested amount is zero (all are vested).
        else if (onDay >= grant.startDay + vesting.duration)
        {
            // All are vested (none are not vested)
            return uint256(0);
        }
        // Otherwise a fractional amount is vested.
        else
        {
            // Compute the exact number of days vested.
            uint32 daysVested = onDay - grant.startDay;
            // Adjust result rounding down to take into consideration the interval.
            uint32 effectiveDaysVested = (daysVested / vesting.interval) * vesting.interval;

            // Compute the fraction vested from schedule using 224.32 fixed point math for date range ratio.
            // Note: This is safe in 256-bit math because max value of X billion tokens = X*10^27 wei, and
            // typical token amounts can fit into 90 bits. Scaling using a 32 bits value results in only 125
            // bits before reducing back to 90 bits by dividing. There is plenty of room left, even for token
            // amounts many orders of magnitude greater than mere billions.
            uint256 vested = grant.amount.mul(effectiveDaysVested).div(vesting.duration);
            return grant.amount.sub(vested);
        }
    }

    /**
     * @dev Computes the amount of funds in the given account which are available for use as of
     * the given day. If there's no vesting schedule then 0 tokens are considered to be vested and
     * this just returns the full account balance.
     *
     * The math is: available amount = total funds - notVestedAmount.
     *
     * @param grantHolder = The account to check.
     * @param onDay = The day to check for, in days since the UNIX epoch.
     */
    function _getAvailableAmount(address grantHolder, uint32 onDay) internal view returns (uint256 amountAvailable) {
        uint256 totalTokens = balanceOf(grantHolder);
        uint256 vested = totalTokens.sub(_getNotVestedAmount(grantHolder, onDay));
        return vested;
    }

    /**
     * @dev returns all information about the grant's vesting as of the given day
     * for the given account. Only callable by the account holder or a grantor, so
     * this is mainly intended for administrative use.
     *
     * @param grantHolder = The address to do this for.
     * @param onDayOrToday = The day to check for, in days since the UNIX epoch. Can pass
     *   the special value 0 to indicate today.
     * @return = A tuple with the following values:
     *   amountVested = the amount out of vestingAmount that is vested
     *   amountNotVested = the amount that is vested (equal to vestingAmount - vestedAmount)
     *   amountOfGrant = the amount of tokens subject to vesting.
     *   vestStartDay = starting day of the grant (in days since the UNIX epoch).
     *   vestDuration = grant duration in days.
     *   cliffDuration = duration of the cliff.
     *   vestIntervalDays = number of days between vesting periods.
     *   isActive = true if the vesting schedule is currently active.
     *   wasRevoked = true if the vesting schedule was revoked.
     */
    function vestingForAccountAsOf(
        address grantHolder,
        uint32 onDayOrToday
    )
    public
    view
    onlyGrantorOrSelf(grantHolder)
    returns (
        uint256 amountVested,
        uint256 amountNotVested,
        uint256 amountOfGrant,
        uint32 vestStartDay,
        uint32 vestDuration,
        uint32 cliffDuration,
        uint32 vestIntervalDays,
        bool isActive,
        bool wasRevoked
    )
    {
        tokenGrant storage grant = _tokenGrants[grantHolder];
        vestingSchedule storage vesting = _vestingSchedules[grant.vestingLocation];
        uint256 notVestedAmount = _getNotVestedAmount(grantHolder, onDayOrToday);
        uint256 grantAmount = grant.amount;

        return (
        grantAmount.sub(notVestedAmount),
        notVestedAmount,
        grantAmount,
        grant.startDay,
        vesting.duration,
        vesting.cliffDuration,
        vesting.interval,
        grant.isActive,
        grant.wasRevoked
        );
    }

    /**
     * @dev returns all information about the grant's vesting as of the given day
     * for the current account, to be called by the account holder.
     *
     * @param onDayOrToday = The day to check for, in days since the UNIX epoch. Can pass
     *   the special value 0 to indicate today.
     * @return = A tuple with the following values:
     *   amountVested = the amount out of vestingAmount that is vested
     *   amountNotVested = the amount that is vested (equal to vestingAmount - vestedAmount)
     *   amountOfGrant = the amount of tokens subject to vesting.
     *   vestStartDay = starting day of the grant (in days since the UNIX epoch).
     *   cliffDuration = duration of the cliff.
     *   vestDuration = grant duration in days.
     *   vestIntervalDays = number of days between vesting periods.
     *   isActive = true if the vesting schedule is currently active.
     *   wasRevoked = true if the vesting schedule was revoked.
     */
    function vestingAsOf(uint32 onDayOrToday) public view returns (
        uint256 amountVested,
        uint256 amountNotVested,
        uint256 amountOfGrant,
        uint32 vestStartDay,
        uint32 vestDuration,
        uint32 cliffDuration,
        uint32 vestIntervalDays,
        bool isActive,
        bool wasRevoked
    )
    {
        return vestingForAccountAsOf(msg.sender, onDayOrToday);
    }

    /**
     * @dev returns true if the account has sufficient funds available to cover the given amount,
     *   including consideration for vesting tokens.
     *
     * @param account = The account to check.
     * @param amount = The required amount of vested funds.
     * @param onDay = The day to check for, in days since the UNIX epoch.
     */
    function _fundsAreAvailableOn(address account, uint256 amount, uint32 onDay) internal view returns (bool ok) {
        return (amount <= _getAvailableAmount(account, onDay));
    }

    /**
     * @dev Modifier to make a function callable only when the amount is sufficiently vested right now.
     *
     * @param account = The account to check.
     * @param amount = The required amount of vested funds.
     */
    modifier onlyIfFundsAvailableNow(address account, uint256 amount) {
        // Distinguish insufficient overall balance from insufficient vested funds balance in failure msg.
        require(_fundsAreAvailableOn(account, amount, today()),
            balanceOf(account) < amount ? "insufficient funds" : "insufficient vested funds");
        _;
    }


    // =========================================================================
    // === Grant revocation
    // =========================================================================

    /**
     * @dev If the account has a revocable grant, this forces the grant to end based on computing
     * the amount vested up to the given date. All tokens that would no longer vest are returned
     * to the account of the original grantor.
     *
     * @param grantHolder = Address to which tokens will be granted.
     * @param onDay = The date upon which the vesting schedule will be effectively terminated,
     *   in days since the UNIX epoch (start of day).
     */
    function revokeGrant(address grantHolder, uint32 onDay) public onlyGrantor returns (bool ok) {
        tokenGrant storage grant = _tokenGrants[grantHolder];
        vestingSchedule storage vesting = _vestingSchedules[grant.vestingLocation];
        uint256 notVestedAmount;

        // Make sure grantor can only revoke from own pool.
        require(msg.sender == owner() || msg.sender == grant.grantor, "not allowed");
        // Make sure a vesting schedule has previously been set.
        require(grant.isActive, "no active grant");
        // Make sure it's revocable.
        require(vesting.isRevocable, "irrevocable");
        // Fail on likely erroneous input.
        require(onDay <= grant.startDay + vesting.duration, "no effect");
        // Don"t let grantor revoke anf portion of vested amount.
        require(onDay >= today(), "cannot revoke vested holdings");

        notVestedAmount = _getNotVestedAmount(grantHolder, onDay);

        // Use ERC20 _approve() to forcibly approve grantor to take back not-vested tokens from grantHolder.
        _approve(grantHolder, grant.grantor, notVestedAmount);
        /* Emits an Approval Event. */
        transferFrom(grantHolder, grant.grantor, notVestedAmount);
        /* Emits a Transfer and an Approval Event. */

        // Kill the grant by updating wasRevoked and isActive.
        _tokenGrants[grantHolder].wasRevoked = true;
        _tokenGrants[grantHolder].isActive = false;

        emit GrantRevoked(grantHolder, onDay);
        /* Emits the GrantRevoked event. */
        return true;
    }


    // =========================================================================
    // === Overridden ERC20 functionality
    // =========================================================================

    /**
     * @dev Methods transfer() and approve() require an additional available funds check to
     * prevent spending held but non-vested tokens. Note that transferFrom() does NOT have this
     * additional check because approved funds come from an already set-aside allowance, not from the wallet.
     */
    function transfer(address to, uint256 value) public onlyIfFundsAvailableNow(msg.sender, value) returns (bool ok) {
        return super.transfer(to, value);
    }

    /**
     * @dev Additional available funds check to prevent spending held but non-vested tokens.
     */
    function approve(address spender, uint256 value) public onlyIfFundsAvailableNow(msg.sender, value) returns (bool ok) {
        return super.approve(spender, value);
    }
}


pragma solidity ^0.5.7;


/**
 * @title Contract for uniform granting of vesting tokens
 *
 * @notice Adds methods for programmatic creation of uniform or standard token vesting grants.
 *
 * @dev This is primarily for use by exchanges and scripted internal employee incentive grant creation.
 */
contract UniformTokenGrantor is ERC20Vestable {

    struct restrictions {
        bool isValid;
        uint32 minStartDay;        /* The smallest value for startDay allowed in grant creation. */
        uint32 maxStartDay;        /* The maximum value for startDay allowed in grant creation. */
        uint32 expirationDay;       /* The last day this grantor may make grants. */
    }

    mapping(address => restrictions) private _restrictions;


    // =========================================================================
    // === Uniform token grant setup
    // === Methods used by owner to set up uniform grants on restricted grantor
    // =========================================================================

    event GrantorRestrictionsSet(
        address indexed grantor,
        uint32 minStartDay,
        uint32 maxStartDay,
        uint32 expirationDay);

    /**
     * @dev Lets owner set or change existing specific restrictions. Restrictions must be established
     * before the grantor will be allowed to issue grants.
     *
     * All date values are expressed as number of days since the UNIX epoch. Note that the inputs are
     * themselves not very thoroughly restricted. However, this method can be called more than once
     * if incorrect values need to be changed, or to extend a grantor's expiration date.
     *
     * @param grantor = Address which will receive the uniform grantable vesting schedule.
     * @param minStartDay = The smallest value for startDay allowed in grant creation.
     * @param maxStartDay = The maximum value for startDay allowed in grant creation.
     * @param expirationDay = The last day this grantor may make grants.
     */
    function setRestrictions(
        address grantor,
        uint32 minStartDay,
        uint32 maxStartDay,
        uint32 expirationDay
    )
    public
    onlyOwner
    onlyExistingAccount(grantor)
    returns (bool ok)
    {
        require(
            isUniformGrantor(grantor)
         && maxStartDay > minStartDay
         && expirationDay > today(), "invalid params");

        // We allow owner to set or change existing specific restrictions.
        _restrictions[grantor] = restrictions(
            true/*isValid*/,
            minStartDay,
            maxStartDay,
            expirationDay
        );

        // Emit the event and return success.
        emit GrantorRestrictionsSet(grantor, minStartDay, maxStartDay, expirationDay);
        return true;
    }

    /**
     * @dev Lets owner permanently establish a vesting schedule for a restricted grantor to use when
     * creating uniform token grants. Grantee accounts forever refer to the grantor's account to look up
     * vesting, so this method can only be used once per grantor.
     *
     * @param grantor = Address which will receive the uniform grantable vesting schedule.
     * @param duration = Duration of the vesting schedule, with respect to the grant start day, in days.
     * @param cliffDuration = Duration of the cliff, with respect to the grant start day, in days.
     * @param interval = Number of days between vesting increases.
     * @param isRevocable = True if the grant can be revoked (i.e. was a gift) or false if it cannot
     *   be revoked (i.e. tokens were purchased).
     */
    function setGrantorVestingSchedule(
        address grantor,
        uint32 duration,
        uint32 cliffDuration,
        uint32 interval,
        bool isRevocable
    )
    public
    onlyOwner
    onlyExistingAccount(grantor)
    returns (bool ok)
    {
        // Only allow doing this to restricted grantor role account.
        require(isUniformGrantor(grantor), "uniform grantor only");
        // Make sure no prior vesting schedule has been set!
        require(!_hasVestingSchedule(grantor), "schedule already exists");

        // The vesting schedule is unique to this grantor wallet and so will be stored here to be
        // referenced by future grants. Emits VestingScheduleCreated event.
        _setVestingSchedule(grantor, cliffDuration, duration, interval, isRevocable);

        return true;
    }


    // =========================================================================
    // === Uniform token grants
    // === Methods to be used by exchanges to use for creating tokens.
    // =========================================================================

    function isUniformGrantorWithSchedule(address account) internal view returns (bool ok) {
        // Check for grantor that has a uniform vesting schedule already set.
        return isUniformGrantor(account) && _hasVestingSchedule(account);
    }

    modifier onlyUniformGrantorWithSchedule(address account) {
        require(isUniformGrantorWithSchedule(account), "grantor account not ready");
        _;
    }

    modifier whenGrantorRestrictionsMet(uint32 startDay) {
        restrictions storage restriction = _restrictions[msg.sender];
        require(restriction.isValid, "set restrictions first");

        require(
            startDay >= restriction.minStartDay
            && startDay < restriction.maxStartDay, "startDay too early");

        require(today() < restriction.expirationDay, "grantor expired");
        _;
    }

    /**
     * @dev Immediately grants tokens to an address, including a portion that will vest over time
     * according to the uniform vesting schedule already established in the grantor's account.
     *
     * @param beneficiary = Address to which tokens will be granted.
     * @param totalAmount = Total number of tokens to deposit into the account.
     * @param vestingAmount = Out of totalAmount, the number of tokens subject to vesting.
     * @param startDay = Start day of the grant's vesting schedule, in days since the UNIX epoch
     *   (start of day). The startDay may be given as a date in the future or in the past, going as far
     *   back as year 2000.
     */
    function grantUniformVestingTokens(
        address beneficiary,
        uint256 totalAmount,
        uint256 vestingAmount,
        uint32 startDay
    )
    public
    onlyUniformGrantorWithSchedule(msg.sender)
    whenGrantorRestrictionsMet(startDay)
    returns (bool ok)
    {
        // Issue grantor tokens to the beneficiary, using beneficiary's own vesting schedule.
        // Emits VestingTokensGranted event.
        return _grantVestingTokens(beneficiary, totalAmount, vestingAmount, startDay, msg.sender, msg.sender);
    }

    /**
     * @dev This variant only grants tokens if the beneficiary account has previously self-registered.
     */
    function safeGrantUniformVestingTokens(
        address beneficiary,
        uint256 totalAmount,
        uint256 vestingAmount,
        uint32 startDay
    )
    public
    onlyUniformGrantorWithSchedule(msg.sender)
    whenGrantorRestrictionsMet(startDay)
    onlyExistingAccount(beneficiary)
    returns (bool ok)
    {
        // Issue grantor tokens to the beneficiary, using beneficiary's own vesting schedule.
        // Emits VestingTokensGranted event.
        return _grantVestingTokens(beneficiary, totalAmount, vestingAmount, startDay, msg.sender, msg.sender);
    }
}


pragma solidity ^0.5.7;


/**
 * @dev An ERC20 implementation of the CPUcoin ecosystem token. All tokens are initially pre-assigned to
 * the creator, and can later be distributed freely using transfer transferFrom and other ERC20
 * functions.
 */
contract CpuCoin is Identity, ERC20, ERC20Pausable, ERC20Burnable, ERC20Detailed, UniformTokenGrantor {
    uint32 public constant VERSION = 8;

    uint8 private constant DECIMALS = 18;
    uint256 private constant TOKEN_WEI = 10 ** uint256(DECIMALS);

    uint256 private constant INITIAL_WHOLE_TOKENS = uint256(5 * (10 ** 9));
    uint256 private constant INITIAL_SUPPLY = uint256(INITIAL_WHOLE_TOKENS) * uint256(TOKEN_WEI);

    /**
     * @dev Constructor that gives msg.sender all of existing tokens.
     */
    constructor () ERC20Detailed("CPUcoin", "CPU", DECIMALS) public {
        // This is the only place where we ever mint tokens.
        _mint(msg.sender, INITIAL_SUPPLY);
    }

    event DepositReceived(address indexed from, uint256 value);

    /**
     * fallback function: collect any ether sent to us (whether we asked for it or not).
     */
    function() payable external {
        // Track where unexpected ETH came from so we can follow up later.
        emit DepositReceived(msg.sender, msg.value);
    }

    /**
     * @dev Allow only the owner to burn tokens from the owner's wallet, also decreasing the total
     * supply. There is no reason for a token holder to EVER call this method directly. It will be
     * used by the future Dyncoin contract to implement the CpuCoin side of of token redemption.
     */
    function burn(uint256 value) onlyIfFundsAvailableNow(msg.sender, value) public {
        // This is the only place where we ever burn tokens.
        _burn(msg.sender, value);
    }

    /**
     * @dev Allow pauser to kill the contract (which must already be paused), with enough restrictions
     * in place to ensure this could not happen by accident very easily. ETH is returned to owner wallet.
     */
    function kill() whenPaused onlyPauser public returns (bool itsDeadJim) {
        require(isPauser(msg.sender), "onlyPauser");
        address payable payableOwner = address(uint160(owner()));
        selfdestruct(payableOwner);
        return true;
    }
}

Contract Security Audit

Contract ABI

[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"value","type":"uint256"}],"name":"approve","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"account","type":"address"}],"name":"isGrantor","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"grantHolder","type":"address"},{"name":"onDay","type":"uint32"}],"name":"revokeGrant","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"from","type":"address"},{"name":"to","type":"address"},{"name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"onDayOrToday","type":"uint32"}],"name":"vestingAsOf","outputs":[{"name":"amountVested","type":"uint256"},{"name":"amountNotVested","type":"uint256"},{"name":"amountOfGrant","type":"uint256"},{"name":"vestStartDay","type":"uint32"},{"name":"vestDuration","type":"uint32"},{"name":"cliffDuration","type":"uint32"},{"name":"vestIntervalDays","type":"uint32"},{"name":"isActive","type":"bool"},{"name":"wasRevoked","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"whereAmI","outputs":[{"name":"yourAddress","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"account","type":"address"}],"name":"removeGrantor","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"beneficiary","type":"address"},{"name":"totalAmount","type":"uint256"},{"name":"vestingAmount","type":"uint256"},{"name":"startDay","type":"uint32"}],"name":"safeGrantUniformVestingTokens","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"kill","outputs":[{"name":"itsDeadJim","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"beneficiary","type":"address"},{"name":"totalAmount","type":"uint256"},{"name":"vestingAmount","type":"uint256"},{"name":"startDay","type":"uint32"},{"name":"duration","type":"uint32"},{"name":"cliffDuration","type":"uint32"},{"name":"interval","type":"uint32"},{"name":"isRevocable","type":"bool"}],"name":"safeGrantVestingTokens","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"}],"name":"safeTransfer","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"from","type":"address"},{"name":"to","type":"address"},{"name":"value","type":"uint256"}],"name":"safeTransferFrom","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"value","type":"uint256"}],"name":"burn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"account","type":"address"},{"name":"isUniformGrantor","type":"bool"}],"name":"addGrantor","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"account","type":"address"}],"name":"isPauser","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"account","type":"address"}],"name":"removePauser","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"grantor","type":"address"},{"name":"duration","type":"uint32"},{"name":"cliffDuration","type":"uint32"},{"name":"interval","type":"uint32"},{"name":"isRevocable","type":"bool"}],"name":"setGrantorVestingSchedule","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"account","type":"address"}],"name":"isUniformGrantor","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"from","type":"address"},{"name":"value","type":"uint256"}],"name":"burnFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"beneficiary","type":"address"},{"name":"totalAmount","type":"uint256"},{"name":"vestingAmount","type":"uint256"},{"name":"startDay","type":"uint32"},{"name":"duration","type":"uint32"},{"name":"cliffDuration","type":"uint32"},{"name":"interval","type":"uint32"},{"name":"isRevocable","type":"bool"}],"name":"grantVestingTokens","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"account","type":"address"}],"name":"addPauser","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"shortName","type":"string"}],"name":"iAm","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"grantor","type":"address"},{"name":"minStartDay","type":"uint32"},{"name":"maxStartDay","type":"uint32"},{"name":"expirationDay","type":"uint32"}],"name":"setRestrictions","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"}],"name":"transfer","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"grantHolder","type":"address"}],"name":"getIntrinsicVestingSchedule","outputs":[{"name":"vestDuration","type":"uint32"},{"name":"cliffDuration","type":"uint32"},{"name":"vestIntervalDays","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"today","outputs":[{"name":"dayNumber","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"account","type":"address"}],"name":"isRegistered","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"grantHolder","type":"address"},{"name":"onDayOrToday","type":"uint32"}],"name":"vestingForAccountAsOf","outputs":[{"name":"amountVested","type":"uint256"},{"name":"amountNotVested","type":"uint256"},{"name":"amountOfGrant","type":"uint256"},{"name":"vestStartDay","type":"uint32"},{"name":"vestDuration","type":"uint32"},{"name":"cliffDuration","type":"uint32"},{"name":"vestIntervalDays","type":"uint32"},{"name":"isActive","type":"bool"},{"name":"wasRevoked","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"registerAccount","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"whoAmI","outputs":[{"name":"yourName","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"},{"name":"spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"value","type":"uint256"}],"name":"safeApprove","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"beneficiary","type":"address"},{"name":"totalAmount","type":"uint256"},{"name":"vestingAmount","type":"uint256"},{"name":"startDay","type":"uint32"}],"name":"grantUniformVestingTokens","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"VERSION","outputs":[{"name":"","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"DepositReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"grantor","type":"address"},{"indexed":false,"name":"minStartDay","type":"uint32"},{"indexed":false,"name":"maxStartDay","type":"uint32"},{"indexed":false,"name":"expirationDay","type":"uint32"}],"name":"GrantorRestrictionsSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"vestingLocation","type":"address"},{"indexed":false,"name":"cliffDuration","type":"uint32"},{"indexed":true,"name":"duration","type":"uint32"},{"indexed":false,"name":"interval","type":"uint32"},{"indexed":true,"name":"isRevocable","type":"bool"}],"name":"VestingScheduleCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"beneficiary","type":"address"},{"indexed":true,"name":"vestingAmount","type":"uint256"},{"indexed":false,"name":"startDay","type":"uint32"},{"indexed":false,"name":"vestingLocation","type":"address"},{"indexed":true,"name":"grantor","type":"address"}],"name":"VestingTokensGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"grantHolder","type":"address"},{"indexed":true,"name":"onDay","type":"uint32"}],"name":"GrantRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"}],"name":"GrantorAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"}],"name":"GrantorRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"}],"name":"AccountRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"}],"name":"PauserAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"}],"name":"PauserRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"}]

60806040523480156200001157600080fd5b506040518060400160405280600781526020017f435055636f696e000000000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f4350550000000000000000000000000000000000000000000000000000000000815250601233600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36200014f336200020460201b60201c565b6000600660006101000a81548160ff021916908315150217905550826007908051906020019062000182929190620006c9565b5081600890805190602001906200019b929190620006c9565b5080600960006101000a81548160ff021916908360ff160217905550505050620001ca620002a060201b60201c565b50620001de3360006200034460201b60201c565b620001fe33601260ff16600a0a64012a05f200026200043860201b60201c565b62000778565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156200023f57600080fd5b6200025a8160056200059b60201b6200570b1790919060201c565b8073ffffffffffffffffffffffffffffffffffffffff167f6719d08c1888103bea251a4ed56406bd0c3e69723c8a1686e017e7bbe159b6f860405160405180910390a250565b60006001600a60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff167fcd822dc9688e20acea68724a2fbcfe4f3e526d20ecaa37b18fe3047ab377d6a560405160405180910390a26001905090565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156200037f57600080fd5b6200039a82600b6200059b60201b6200570b1790919060201c565b80600c60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff167f614c7c37719098320f845a142223983b9adcc4c3f2663971d5b0eb4c661a24e760405160405180910390a25050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156200047357600080fd5b6200048f816003546200061660201b620056ec1790919060201c565b600381905550620004ee81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546200061660201b620056ec1790919060201c565b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b620005ad82826200063660201b60201c565b15620005b857600080fd5b60018260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b6000808284019050838110156200062c57600080fd5b8091505092915050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156200067257600080fd5b8260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200070c57805160ff19168380011785556200073d565b828001600101855582156200073d579182015b828111156200073c5782518255916020019190600101906200071f565b5b5090506200074c919062000750565b5090565b6200077591905b808211156200077157600081600090555060010162000757565b5090565b90565b6159ce80620007886000396000f3fe6080604052600436106102935760003560e01c806370a082311161015a578063a9059cbb116100c1578063da91254c1161007a578063da91254c1461147a578063dd62ed3e1461150a578063f2fde38b1461158f578063fbc6d1cb146115e0578063fd1154c214611653578063ffa1ad74146116e057610293565b8063a9059cbb146111bc578063acc27b981461122f578063b74e452b146112c6578063c3c5a547146112fd578063d56ad0ba14611366578063d9f226e91461144b57610293565b80638456cb59116101135780638456cb5914610f835780638da5cb5b14610f9a5780638f32d59b14610ff157806395d89b411461102057806399ad427b146110b0578063a457c2d71461114957610293565b806370a0823114610cc9578063715018a614610d2e57806379cc679014610d455780637af023a914610da057806382dc1ec414610e6a5780638403eeb514610ebb57610293565b80633f4ba83a116101fe57806344e393cb116101b757806344e393cb14610a7557806346fbf68e14610ad25780635c975abb14610b3b5780636b2c0f5514610b6a5780636d589d6414610bbb5780636d71a9c614610c6057610293565b80633f4ba83a1461082457806341c0e1b51461083b57806341d5f6191461086a578063423f6cef1461093457806342842e0e146109a757806342966c6814610a3a57610293565b80632455a035116102505780632455a03514610586578063313ce5671461064b57806332ae38481461067c578063332cc9c6146106d357806339509351146107245780633d3b993c1461079757610293565b806306fdde03146102e3578063095ea7b31461037357806318160ddd146103e6578063190de9f7146104115780631bd2cf381461047a57806323b872dd146104f3575b3373ffffffffffffffffffffffffffffffffffffffff167f9936746a4565f9766fa768f88f56a7487c78780ac179562773d1c75c5269537e346040518082815260200191505060405180910390a2005b3480156102ef57600080fd5b506102f8611717565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561033857808201518184015260208101905061031d565b50505050905090810190601f1680156103655780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561037f57600080fd5b506103cc6004803603604081101561039657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506117b9565b604051808215151515815260200191505060405180910390f35b3480156103f257600080fd5b506103fb61190b565b6040518082815260200191505060405180910390f35b34801561041d57600080fd5b506104606004803603602081101561043457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611915565b604051808215151515815260200191505060405180910390f35b34801561048657600080fd5b506104d96004803603604081101561049d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803563ffffffff169060200190929190505050611932565b604051808215151515815260200191505060405180910390f35b3480156104ff57600080fd5b5061056c6004803603606081101561051657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611f12565b604051808215151515815260200191505060405180910390f35b34801561059257600080fd5b506105c5600480360360208110156105a957600080fd5b81019080803563ffffffff169060200190929190505050611f42565b604051808a81526020018981526020018881526020018763ffffffff1663ffffffff1681526020018663ffffffff1663ffffffff1681526020018563ffffffff1663ffffffff1681526020018463ffffffff1663ffffffff1681526020018315151515815260200182151515158152602001995050505050505050505060405180910390f35b34801561065757600080fd5b50610660611f79565b604051808260ff1660ff16815260200191505060405180910390f35b34801561068857600080fd5b50610691611f90565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156106df57600080fd5b50610722600480360360208110156106f657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611f9d565b005b34801561073057600080fd5b5061077d6004803603604081101561074757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611fba565b604051808215151515815260200191505060405180910390f35b3480156107a357600080fd5b5061080a600480360360808110156107ba57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190929190803563ffffffff169060200190929190505050611fe8565b604051808215151515815260200191505060405180910390f35b34801561083057600080fd5b50610839612323565b005b34801561084757600080fd5b50610850612437565b604051808215151515815260200191505060405180910390f35b34801561087657600080fd5b5061091a600480360361010081101561088e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190929190803563ffffffff169060200190929190803563ffffffff169060200190929190803563ffffffff169060200190929190803563ffffffff16906020019092919080351515906020019092919050505061256d565b604051808215151515815260200191505060405180910390f35b34801561094057600080fd5b5061098d6004803603604081101561095757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050612685565b604051808215151515815260200191505060405180910390f35b3480156109b357600080fd5b50610a20600480360360608110156109ca57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050612719565b604051808215151515815260200191505060405180910390f35b348015610a4657600080fd5b50610a7360048036036020811015610a5d57600080fd5b81019080803590602001909291905050506127af565b005b348015610a8157600080fd5b50610ad060048036036040811015610a9857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035151590602001909291905050506128fa565b005b348015610ade57600080fd5b50610b2160048036036020811015610af557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612919565b604051808215151515815260200191505060405180910390f35b348015610b4757600080fd5b50610b50612936565b604051808215151515815260200191505060405180910390f35b348015610b7657600080fd5b50610bb960048036036020811015610b8d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061294d565b005b348015610bc757600080fd5b50610c46600480360360a0811015610bde57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803563ffffffff169060200190929190803563ffffffff169060200190929190803563ffffffff16906020019092919080351515906020019092919050505061296a565b604051808215151515815260200191505060405180910390f35b348015610c6c57600080fd5b50610caf60048036036020811015610c8357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612b0c565b604051808215151515815260200191505060405180910390f35b348015610cd557600080fd5b50610d1860048036036020811015610cec57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612b73565b6040518082815260200191505060405180910390f35b348015610d3a57600080fd5b50610d43612bbc565b005b348015610d5157600080fd5b50610d9e60048036036040811015610d6857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050612c43565b005b348015610dac57600080fd5b50610e506004803603610100811015610dc457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190929190803563ffffffff169060200190929190803563ffffffff169060200190929190803563ffffffff169060200190929190803563ffffffff169060200190929190803515159060200190929190505050612c51565b604051808215151515815260200191505060405180910390f35b348015610e7657600080fd5b50610eb960048036036020811015610e8d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612dbe565b005b348015610ec757600080fd5b50610f8160048036036020811015610ede57600080fd5b8101908080359060200190640100000000811115610efb57600080fd5b820183602082011115610f0d57600080fd5b80359060200191846001830284011164010000000083111715610f2f57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050612ddb565b005b348015610f8f57600080fd5b50610f98612e31565b005b348015610fa657600080fd5b50610faf612f46565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b348015610ffd57600080fd5b50611006612f70565b604051808215151515815260200191505060405180910390f35b34801561102c57600080fd5b50611035612fc8565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561107557808201518184015260208101905061105a565b50505050905090810190601f1680156110a25780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156110bc57600080fd5b5061112f600480360360808110156110d357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803563ffffffff169060200190929190803563ffffffff169060200190929190803563ffffffff16906020019092919050505061306a565b604051808215151515815260200191505060405180910390f35b34801561115557600080fd5b506111a26004803603604081101561116c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050613345565b604051808215151515815260200191505060405180910390f35b3480156111c857600080fd5b50611215600480360360408110156111df57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050613373565b604051808215151515815260200191505060405180910390f35b34801561123b57600080fd5b5061127e6004803603602081101561125257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506134c5565b604051808463ffffffff1663ffffffff1681526020018363ffffffff1663ffffffff1681526020018263ffffffff1663ffffffff168152602001935050505060405180910390f35b3480156112d257600080fd5b506112db613683565b604051808263ffffffff1663ffffffff16815260200191505060405180910390f35b34801561130957600080fd5b5061134c6004803603602081101561132057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061369d565b604051808215151515815260200191505060405180910390f35b34801561137257600080fd5b506113c56004803603604081101561138957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803563ffffffff1690602001909291905050506136f3565b604051808a81526020018981526020018881526020018763ffffffff1663ffffffff1681526020018663ffffffff1663ffffffff1681526020018563ffffffff1663ffffffff1681526020018463ffffffff1663ffffffff1681526020018315151515815260200182151515158152602001995050505050505050505060405180910390f35b34801561145757600080fd5b50611460613925565b604051808215151515815260200191505060405180910390f35b34801561148657600080fd5b5061148f6139c9565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156114cf5780820151818401526020810190506114b4565b50505050905090810190601f1680156114fc5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561151657600080fd5b506115796004803603604081101561152d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613aa7565b6040518082815260200191505060405180910390f35b34801561159b57600080fd5b506115de600480360360208110156115b257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613b2e565b005b3480156115ec57600080fd5b506116396004803603604081101561160357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050613b5f565b604051808215151515815260200191505060405180910390f35b34801561165f57600080fd5b506116c66004803603608081101561167657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190929190803563ffffffff169060200190929190505050613bf3565b604051808215151515815260200191505060405180910390f35b3480156116ec57600080fd5b506116f5613eb1565b604051808263ffffffff1663ffffffff16815260200191505060405180910390f35b606060078054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156117af5780601f10611784576101008083540402835291602001916117af565b820191906000526020600020905b81548152906001019060200180831161179257829003601f168201915b5050505050905090565b600033826117cf82826117ca613683565b613eb6565b816117d984612b73565b10611819576040518060400160405280601981526020017f696e73756666696369656e74207665737465642066756e647300000000000000815250611850565b6040518060400160405280601281526020017f696e73756666696369656e742066756e647300000000000000000000000000008152505b906118f6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156118bb5780820151818401526020810190506118a0565b50505050905090810190601f1680156118e85780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506119018585613ece565b9250505092915050565b6000600354905090565b600061192b82600b613efc90919063ffffffff16565b9050919050565b600061193d33611915565b6119af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600b8152602001807f6f6e6c794772616e746f7200000000000000000000000000000000000000000081525060200191505060405180910390fd5b6000600e60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000600d60008360020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000611a63612f46565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480611aeb57508260030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b611b5d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600b8152602001807f6e6f7420616c6c6f77656400000000000000000000000000000000000000000081525060200191505060405180910390fd5b8260000160009054906101000a900460ff16611be1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f6e6f20616374697665206772616e74000000000000000000000000000000000081525060200191505060405180910390fd5b8160000160019054906101000a900460ff16611c65576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600b8152602001807f69727265766f6361626c6500000000000000000000000000000000000000000081525060200191505060405180910390fd5b8160000160069054906101000a900463ffffffff168360000160029054906101000a900463ffffffff160163ffffffff168563ffffffff161115611d11576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260098152602001807f6e6f20656666656374000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b611d19613683565b63ffffffff168563ffffffff161015611d9a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f63616e6e6f74207265766f6b652076657374656420686f6c64696e677300000081525060200191505060405180910390fd5b611da48686613f8e565b9050611dd5868460030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836141c8565b611e04868460030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683611f12565b506001600e60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160016101000a81548160ff0219169083151502179055506000600e60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548160ff0219169083151502179055508463ffffffff168673ffffffffffffffffffffffffffffffffffffffff167f906c0c4c98565a396c542d9102cae7a794e84af6763123e068a1b277333bf4a460405160405180910390a36001935050505092915050565b6000600660009054906101000a900460ff1615611f2e57600080fd5b611f39848484614327565b90509392505050565b6000806000806000806000806000611f5a338b6136f3565b9850985098509850985098509850985098509193959799909294969850565b6000600960009054906101000a900460ff16905090565b6000803390508091505090565b611fa5612f70565b611fae57600080fd5b611fb7816143d8565b50565b6000600660009054906101000a900460ff1615611fd657600080fd5b611fe0838361446c565b905092915050565b600033611ff481614511565b612066576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f6772616e746f72206163636f756e74206e6f742072656164790000000000000081525060200191505060405180910390fd5b826000600f60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060000160009054906101000a900460ff1661212e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f736574207265737472696374696f6e732066697273740000000000000000000081525060200191505060405180910390fd5b8060000160019054906101000a900463ffffffff1663ffffffff168263ffffffff161015801561217d57508060000160059054906101000a900463ffffffff1663ffffffff168263ffffffff16105b6121ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f737461727444617920746f6f206561726c79000000000000000000000000000081525060200191505060405180910390fd5b8060000160099054906101000a900463ffffffff1663ffffffff16612212613683565b63ffffffff161061228b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f6772616e746f722065787069726564000000000000000000000000000000000081525060200191505060405180910390fd5b8761229581614534565b612307576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6163636f756e74206e6f7420726567697374657265640000000000000000000081525060200191505060405180910390fd5b6123158989898933336145c0565b945050505050949350505050565b61232c33612919565b61239e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600a8152602001807f6f6e6c795061757365720000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600660009054906101000a900460ff166123b757600080fd5b6000600660006101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa33604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1565b6000600660009054906101000a900460ff1661245257600080fd5b61245b33612919565b6124cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600a8152602001807f6f6e6c795061757365720000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6124d633612919565b612548576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600a8152602001807f6f6e6c795061757365720000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6000612552612f46565b90508073ffffffffffffffffffffffffffffffffffffffff16ff5b600061257833611915565b6125ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600b8152602001807f6f6e6c794772616e746f7200000000000000000000000000000000000000000081525060200191505060405180910390fd5b886125f481614534565b612666576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6163636f756e74206e6f7420726567697374657265640000000000000000000081525060200191505060405180910390fd5b6126768a8a8a8a8a8a8a8a612c51565b91505098975050505050505050565b60008261269181614534565b612703576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6163636f756e74206e6f7420726567697374657265640000000000000000000081525060200191505060405180910390fd5b61270d8484613373565b50600191505092915050565b60008261272581614534565b612797576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6163636f756e74206e6f7420726567697374657265640000000000000000000081525060200191505060405180910390fd5b6127a2858585611f12565b5060019150509392505050565b33816127c382826127be613683565b613eb6565b816127cd84612b73565b1061280d576040518060400160405280601981526020017f696e73756666696369656e74207665737465642066756e647300000000000000815250612844565b6040518060400160405280601281526020017f696e73756666696369656e742066756e647300000000000000000000000000008152505b906128ea576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156128af578082015181840152602081019050612894565b50505050905090810190601f1680156128dc5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506128f53384614a53565b505050565b612902612f70565b61290b57600080fd5b6129158282614ba7565b5050565b600061292f826005613efc90919063ffffffff16565b9050919050565b6000600660009054906101000a900460ff16905090565b612955612f70565b61295e57600080fd5b61296781614c93565b50565b6000612974612f70565b61297d57600080fd5b8561298781614534565b6129f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6163636f756e74206e6f7420726567697374657265640000000000000000000081525060200191505060405180910390fd5b612a0287612b0c565b612a74576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f756e69666f726d206772616e746f72206f6e6c7900000000000000000000000081525060200191505060405180910390fd5b612a7d87614d27565b15612af0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f7363686564756c6520616c72656164792065786973747300000000000000000081525060200191505060405180910390fd5b612afd8786888787614d80565b50600191505095945050505050565b6000612b1782611915565b8015612b6c5750600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b9050919050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b612bc4612f70565b612bcd57600080fd5b6000612c41576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260098152602001807f666f7262696464656e000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b565b612c4d82826150a7565b5050565b6000612c5c33611915565b612cce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600b8152602001807f6f6e6c794772616e746f7200000000000000000000000000000000000000000081525060200191505060405180910390fd5b600e60008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff1615612d91576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f6772616e7420616c72656164792065786973747300000000000000000000000081525060200191505060405180910390fd5b612d9e8985878686614d80565b50612dad898989898d336145c0565b506001905098975050505050505050565b612dc6612f70565b612dcf57600080fd5b612dd88161514e565b50565b806000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209080519060200190612e2d9291906158da565b5050565b612e3a33612919565b612eac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600a8152602001807f6f6e6c795061757365720000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600660009054906101000a900460ff1615612ec657600080fd5b6001600660006101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25833604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b606060088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156130605780601f1061303557610100808354040283529160200191613060565b820191906000526020600020905b81548152906001019060200180831161304357829003601f168201915b5050505050905090565b6000613074612f70565b61307d57600080fd5b8461308781614534565b6130f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6163636f756e74206e6f7420726567697374657265640000000000000000000081525060200191505060405180910390fd5b61310286612b0c565b801561311957508463ffffffff168463ffffffff16115b80156131375750613128613683565b63ffffffff168363ffffffff16115b6131a9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f696e76616c696420706172616d7300000000000000000000000000000000000081525060200191505060405180910390fd5b60405180608001604052806001151581526020018663ffffffff1681526020018563ffffffff1681526020018463ffffffff16815250600f60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160056101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160096101000a81548163ffffffff021916908363ffffffff1602179055509050508573ffffffffffffffffffffffffffffffffffffffff167fd204f080300249d73110cd2c2e8d720f0362e94b8e0f1b797ac249acca176551868686604051808463ffffffff1663ffffffff1681526020018363ffffffff1663ffffffff1681526020018263ffffffff1663ffffffff168152602001935050505060405180910390a26001915050949350505050565b6000600660009054906101000a900460ff161561336157600080fd5b61336b83836151e2565b905092915050565b600033826133898282613384613683565b613eb6565b8161339384612b73565b106133d3576040518060400160405280601981526020017f696e73756666696369656e74207665737465642066756e64730000000000000081525061340a565b6040518060400160405280601281526020017f696e73756666696369656e742066756e647300000000000000000000000000008152505b906134b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561347557808201518184015260208101905061345a565b50505050905090810190601f1680156134a25780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506134bb8585615287565b9250505092915050565b6000806000836134d433611915565b8061350a57508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b61357c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f6f6e6c794772616e746f724f7253656c6600000000000000000000000000000081525060200191505060405180910390fd5b600d60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160069054906101000a900463ffffffff16600d60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160029054906101000a900463ffffffff16600d60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001600a9054906101000a900463ffffffff16935093509350509193909250565b60006201518063ffffffff16428161369757fe5b04905090565b6000600a60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b60008060008060008060008060008a61370b33611915565b8061374157508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b6137b3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f6f6e6c794772616e746f724f7253656c6600000000000000000000000000000081525060200191505060405180910390fd5b6000600e60008e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000600d60008360020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060006138698f8f613f8e565b905060008360010154905061388782826152b590919063ffffffff16565b82828660000160029054906101000a900463ffffffff168660000160069054906101000a900463ffffffff168760000160029054906101000a900463ffffffff1688600001600a9054906101000a900463ffffffff168a60000160009054906101000a900460ff168b60000160019054906101000a900460ff169d509d509d509d509d509d509d509d509d5050505050509295985092959850929598565b60006001600a60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff167fcd822dc9688e20acea68724a2fbcfe4f3e526d20ecaa37b18fe3047ab377d6a560405160405180910390a26001905090565b60606000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015613a9d5780601f10613a7257610100808354040283529160200191613a9d565b820191906000526020600020905b815481529060010190602001808311613a8057829003601f168201915b5050505050905090565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b613b36612f70565b613b3f57600080fd5b613b48336143d8565b613b518161533e565b613b5c816000614ba7565b50565b600082613b6b81614534565b613bdd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6163636f756e74206e6f7420726567697374657265640000000000000000000081525060200191505060405180910390fd5b613be784846117b9565b50600191505092915050565b600033613bff81614511565b613c71576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f6772616e746f72206163636f756e74206e6f742072656164790000000000000081525060200191505060405180910390fd5b826000600f60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060000160009054906101000a900460ff16613d39576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f736574207265737472696374696f6e732066697273740000000000000000000081525060200191505060405180910390fd5b8060000160019054906101000a900463ffffffff1663ffffffff168263ffffffff1610158015613d8857508060000160059054906101000a900463ffffffff1663ffffffff168263ffffffff16105b613dfa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f737461727444617920746f6f206561726c79000000000000000000000000000081525060200191505060405180910390fd5b8060000160099054906101000a900463ffffffff1663ffffffff16613e1d613683565b63ffffffff1610613e96576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f6772616e746f722065787069726564000000000000000000000000000000000081525060200191505060405180910390fd5b613ea48888888833336145c0565b9350505050949350505050565b600881565b6000613ec284836153d8565b83111590509392505050565b6000600660009054906101000a900460ff1615613eea57600080fd5b613ef48383615411565b905092915050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415613f3757600080fd5b8260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b600080600e60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000600d60008360020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600061404485615428565b90508260000160009054906101000a900460ff16158061409957508160000160029054906101000a900463ffffffff168360000160029054906101000a900463ffffffff160163ffffffff168163ffffffff16105b156140ad57826001015493505050506141c2565b8160000160069054906101000a900463ffffffff168360000160029054906101000a900463ffffffff160163ffffffff168163ffffffff16106140f657600093505050506141c2565b60008360000160029054906101000a900463ffffffff1682039050600083600001600a9054906101000a900463ffffffff1684600001600a9054906101000a900463ffffffff1663ffffffff168363ffffffff168161415157fe5b0402905060006141a08560000160069054906101000a900463ffffffff1663ffffffff166141928463ffffffff16896001015461544d90919063ffffffff16565b61548790919063ffffffff16565b90506141b98187600101546152b590919063ffffffff16565b96505050505050505b92915050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561420257600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561423c57600080fd5b80600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b60006143348484846154ad565b6143cd84336143c885600260008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546152b590919063ffffffff16565b6141c8565b600190509392505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561441257600080fd5b61442681600b61567b90919063ffffffff16565b8073ffffffffffffffffffffffffffffffffffffffff167f33a8bb468e8361c5c40d643192eb6970b91cb87aa0200f8709f5b805087b905360405160405180910390a250565b6000614507338461450285600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546156ec90919063ffffffff16565b6141c8565b6001905092915050565b600061451c82612b0c565b801561452d575061452c82614d27565b5b9050919050565b60003373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806145b95750600a60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b9050919050565b6000600e60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff1615614685576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f6772616e7420616c72656164792065786973747300000000000000000000000081525060200191505060405180910390fd5b8585111580156146955750600085115b80156146c957506201518063ffffffff1663386d438063ffffffff16816146b857fe5b0463ffffffff168463ffffffff1610155b80156147015750620592bb6201518063ffffffff1663386d438063ffffffff16816146f057fe5b040163ffffffff168463ffffffff16105b614773576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f696e76616c69642076657374696e6720706172616d730000000000000000000081525060200191505060405180910390fd5b61477c83614d27565b6147ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f6e6f20737563682076657374696e67207363686564756c65000000000000000081525060200191505060405180910390fd5b6147f98288886154ad565b6040518060c001604052806001151581526020016000151581526020018563ffffffff1681526020018681526020018473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff16815250600e60008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548160ff02191690831515021790555060408201518160000160026101000a81548163ffffffff021916908363ffffffff1602179055506060820151816001015560808201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060a08201518160030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509050508173ffffffffffffffffffffffffffffffffffffffff16858873ffffffffffffffffffffffffffffffffffffffff167fce19dc9f3460f5845c81c7fa52526977d7e7275df4b1d0e40ea09653252e0c758787604051808363ffffffff1663ffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a4600190509695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415614a8d57600080fd5b614aa2816003546152b590919063ffffffff16565b600381905550614afa81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546152b590919063ffffffff16565b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415614be157600080fd5b614bf582600b61570b90919063ffffffff16565b80600c60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff167f614c7c37719098320f845a142223983b9adcc4c3f2663971d5b0eb4c661a24e760405160405180910390a25050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415614ccd57600080fd5b614ce181600561567b90919063ffffffff16565b8073ffffffffffffffffffffffffffffffffffffffff167fcd265ebaf09df2871cc7bd4133404a235ba12eff2041bb89d9c714a2621c7c7e60405160405180910390a250565b6000600d60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff169050919050565b6000808463ffffffff16118015614db657506064620592bb63ffffffff1681614da557fe5b0463ffffffff168463ffffffff1611155b8015614dcd57508363ffffffff168563ffffffff16105b8015614de0575060018363ffffffff1610155b614e52576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f696e76616c69642076657374696e67207363686564756c65000000000000000081525060200191505060405180910390fd5b60008363ffffffff168563ffffffff1681614e6957fe5b0663ffffffff16148015614e98575060008363ffffffff168663ffffffff1681614e8f57fe5b0663ffffffff16145b614eed576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806159806023913960400191505060405180910390fd5b6040518060a0016040528060011515815260200183151581526020018663ffffffff1681526020018563ffffffff1681526020018463ffffffff16815250600d60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548160ff02191690831515021790555060408201518160000160026101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160066101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600a6101000a81548163ffffffff021916908363ffffffff1602179055509050508115158463ffffffff168773ffffffffffffffffffffffffffffffffffffffff167fb84219eaee5910cc5311a393fbd4287b14bc791973b97f64d4b61b6d8554adc78887604051808363ffffffff1663ffffffff1681526020018263ffffffff1663ffffffff1681526020019250505060405180910390a46001905095945050505050565b6150b18282614a53565b61514a823361514584600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546152b590919063ffffffff16565b6141c8565b5050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561518857600080fd5b61519c81600561570b90919063ffffffff16565b8073ffffffffffffffffffffffffffffffffffffffff167f6719d08c1888103bea251a4ed56406bd0c3e69723c8a1686e017e7bbe159b6f860405160405180910390a250565b600061527d338461527885600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546152b590919063ffffffff16565b6141c8565b6001905092915050565b6000600660009054906101000a900460ff16156152a357600080fd5b6152ad838361577d565b905092915050565b60008282111561532d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f496e73756666696369656e742066756e6473000000000000000000000000000081525060200191505060405180910390fd5b600082840390508091505092915050565b8061534881614534565b6153ba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6163636f756e74206e6f7420726567697374657265640000000000000000000081525060200191505060405180910390fd5b6153c2612f70565b6153cb57600080fd5b6153d482615794565b5050565b6000806153e484612b73565b905060006154046153f58686613f8e565b836152b590919063ffffffff16565b9050809250505092915050565b600061541e3384846141c8565b6001905092915050565b6000808263ffffffff161461543d5781615446565b615445613683565b5b9050919050565b6000808314156154605760009050615481565b600082840290508284828161547157fe5b041461547c57600080fd5b809150505b92915050565b600080821161549557600080fd5b60008284816154a057fe5b0490508091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156154e757600080fd5b61553981600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546152b590919063ffffffff16565b600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506155ce81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546156ec90919063ffffffff16565b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6156858282613efc565b61568e57600080fd5b60008260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b60008082840190508381101561570157600080fd5b8091505092915050565b6157158282613efc565b1561571f57600080fd5b60018260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b600061578a3384846154ad565b6001905092915050565b61579c612f70565b6157a557600080fd5b6157ae33614c93565b6157b7816157c3565b6157c08161514e565b50565b6157cb612f70565b6157d457600080fd5b6157dd816157e0565b50565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561581a57600080fd5b8073ffffffffffffffffffffffffffffffffffffffff16600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a380600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061591b57805160ff1916838001178555615949565b82800160010185558215615949579182015b8281111561594857825182559160200191906001019061592d565b5b509050615956919061595a565b5090565b61597c91905b80821115615978576000816000905550600101615960565b5090565b9056fe696e76616c696420636c6966662f6475726174696f6e20666f7220696e74657276616ca165627a7a72305820d649a15d4562c80ee725bf10910265b540c343bfc9ac6c5ae7465332b2b54a1e0029

Deployed Bytecode

0x6080604052600436106102935760003560e01c806370a082311161015a578063a9059cbb116100c1578063da91254c1161007a578063da91254c1461147a578063dd62ed3e1461150a578063f2fde38b1461158f578063fbc6d1cb146115e0578063fd1154c214611653578063ffa1ad74146116e057610293565b8063a9059cbb146111bc578063acc27b981461122f578063b74e452b146112c6578063c3c5a547146112fd578063d56ad0ba14611366578063d9f226e91461144b57610293565b80638456cb59116101135780638456cb5914610f835780638da5cb5b14610f9a5780638f32d59b14610ff157806395d89b411461102057806399ad427b146110b0578063a457c2d71461114957610293565b806370a0823114610cc9578063715018a614610d2e57806379cc679014610d455780637af023a914610da057806382dc1ec414610e6a5780638403eeb514610ebb57610293565b80633f4ba83a116101fe57806344e393cb116101b757806344e393cb14610a7557806346fbf68e14610ad25780635c975abb14610b3b5780636b2c0f5514610b6a5780636d589d6414610bbb5780636d71a9c614610c6057610293565b80633f4ba83a1461082457806341c0e1b51461083b57806341d5f6191461086a578063423f6cef1461093457806342842e0e146109a757806342966c6814610a3a57610293565b80632455a035116102505780632455a03514610586578063313ce5671461064b57806332ae38481461067c578063332cc9c6146106d357806339509351146107245780633d3b993c1461079757610293565b806306fdde03146102e3578063095ea7b31461037357806318160ddd146103e6578063190de9f7146104115780631bd2cf381461047a57806323b872dd146104f3575b3373ffffffffffffffffffffffffffffffffffffffff167f9936746a4565f9766fa768f88f56a7487c78780ac179562773d1c75c5269537e346040518082815260200191505060405180910390a2005b3480156102ef57600080fd5b506102f8611717565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561033857808201518184015260208101905061031d565b50505050905090810190601f1680156103655780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561037f57600080fd5b506103cc6004803603604081101561039657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506117b9565b604051808215151515815260200191505060405180910390f35b3480156103f257600080fd5b506103fb61190b565b6040518082815260200191505060405180910390f35b34801561041d57600080fd5b506104606004803603602081101561043457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611915565b604051808215151515815260200191505060405180910390f35b34801561048657600080fd5b506104d96004803603604081101561049d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803563ffffffff169060200190929190505050611932565b604051808215151515815260200191505060405180910390f35b3480156104ff57600080fd5b5061056c6004803603606081101561051657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611f12565b604051808215151515815260200191505060405180910390f35b34801561059257600080fd5b506105c5600480360360208110156105a957600080fd5b81019080803563ffffffff169060200190929190505050611f42565b604051808a81526020018981526020018881526020018763ffffffff1663ffffffff1681526020018663ffffffff1663ffffffff1681526020018563ffffffff1663ffffffff1681526020018463ffffffff1663ffffffff1681526020018315151515815260200182151515158152602001995050505050505050505060405180910390f35b34801561065757600080fd5b50610660611f79565b604051808260ff1660ff16815260200191505060405180910390f35b34801561068857600080fd5b50610691611f90565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156106df57600080fd5b50610722600480360360208110156106f657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611f9d565b005b34801561073057600080fd5b5061077d6004803603604081101561074757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611fba565b604051808215151515815260200191505060405180910390f35b3480156107a357600080fd5b5061080a600480360360808110156107ba57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190929190803563ffffffff169060200190929190505050611fe8565b604051808215151515815260200191505060405180910390f35b34801561083057600080fd5b50610839612323565b005b34801561084757600080fd5b50610850612437565b604051808215151515815260200191505060405180910390f35b34801561087657600080fd5b5061091a600480360361010081101561088e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190929190803563ffffffff169060200190929190803563ffffffff169060200190929190803563ffffffff169060200190929190803563ffffffff16906020019092919080351515906020019092919050505061256d565b604051808215151515815260200191505060405180910390f35b34801561094057600080fd5b5061098d6004803603604081101561095757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050612685565b604051808215151515815260200191505060405180910390f35b3480156109b357600080fd5b50610a20600480360360608110156109ca57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050612719565b604051808215151515815260200191505060405180910390f35b348015610a4657600080fd5b50610a7360048036036020811015610a5d57600080fd5b81019080803590602001909291905050506127af565b005b348015610a8157600080fd5b50610ad060048036036040811015610a9857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035151590602001909291905050506128fa565b005b348015610ade57600080fd5b50610b2160048036036020811015610af557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612919565b604051808215151515815260200191505060405180910390f35b348015610b4757600080fd5b50610b50612936565b604051808215151515815260200191505060405180910390f35b348015610b7657600080fd5b50610bb960048036036020811015610b8d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061294d565b005b348015610bc757600080fd5b50610c46600480360360a0811015610bde57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803563ffffffff169060200190929190803563ffffffff169060200190929190803563ffffffff16906020019092919080351515906020019092919050505061296a565b604051808215151515815260200191505060405180910390f35b348015610c6c57600080fd5b50610caf60048036036020811015610c8357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612b0c565b604051808215151515815260200191505060405180910390f35b348015610cd557600080fd5b50610d1860048036036020811015610cec57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612b73565b6040518082815260200191505060405180910390f35b348015610d3a57600080fd5b50610d43612bbc565b005b348015610d5157600080fd5b50610d9e60048036036040811015610d6857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050612c43565b005b348015610dac57600080fd5b50610e506004803603610100811015610dc457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190929190803563ffffffff169060200190929190803563ffffffff169060200190929190803563ffffffff169060200190929190803563ffffffff169060200190929190803515159060200190929190505050612c51565b604051808215151515815260200191505060405180910390f35b348015610e7657600080fd5b50610eb960048036036020811015610e8d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612dbe565b005b348015610ec757600080fd5b50610f8160048036036020811015610ede57600080fd5b8101908080359060200190640100000000811115610efb57600080fd5b820183602082011115610f0d57600080fd5b80359060200191846001830284011164010000000083111715610f2f57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050612ddb565b005b348015610f8f57600080fd5b50610f98612e31565b005b348015610fa657600080fd5b50610faf612f46565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b348015610ffd57600080fd5b50611006612f70565b604051808215151515815260200191505060405180910390f35b34801561102c57600080fd5b50611035612fc8565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561107557808201518184015260208101905061105a565b50505050905090810190601f1680156110a25780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156110bc57600080fd5b5061112f600480360360808110156110d357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803563ffffffff169060200190929190803563ffffffff169060200190929190803563ffffffff16906020019092919050505061306a565b604051808215151515815260200191505060405180910390f35b34801561115557600080fd5b506111a26004803603604081101561116c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050613345565b604051808215151515815260200191505060405180910390f35b3480156111c857600080fd5b50611215600480360360408110156111df57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050613373565b604051808215151515815260200191505060405180910390f35b34801561123b57600080fd5b5061127e6004803603602081101561125257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506134c5565b604051808463ffffffff1663ffffffff1681526020018363ffffffff1663ffffffff1681526020018263ffffffff1663ffffffff168152602001935050505060405180910390f35b3480156112d257600080fd5b506112db613683565b604051808263ffffffff1663ffffffff16815260200191505060405180910390f35b34801561130957600080fd5b5061134c6004803603602081101561132057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061369d565b604051808215151515815260200191505060405180910390f35b34801561137257600080fd5b506113c56004803603604081101561138957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803563ffffffff1690602001909291905050506136f3565b604051808a81526020018981526020018881526020018763ffffffff1663ffffffff1681526020018663ffffffff1663ffffffff1681526020018563ffffffff1663ffffffff1681526020018463ffffffff1663ffffffff1681526020018315151515815260200182151515158152602001995050505050505050505060405180910390f35b34801561145757600080fd5b50611460613925565b604051808215151515815260200191505060405180910390f35b34801561148657600080fd5b5061148f6139c9565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156114cf5780820151818401526020810190506114b4565b50505050905090810190601f1680156114fc5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561151657600080fd5b506115796004803603604081101561152d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613aa7565b6040518082815260200191505060405180910390f35b34801561159b57600080fd5b506115de600480360360208110156115b257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613b2e565b005b3480156115ec57600080fd5b506116396004803603604081101561160357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050613b5f565b604051808215151515815260200191505060405180910390f35b34801561165f57600080fd5b506116c66004803603608081101561167657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190929190803563ffffffff169060200190929190505050613bf3565b604051808215151515815260200191505060405180910390f35b3480156116ec57600080fd5b506116f5613eb1565b604051808263ffffffff1663ffffffff16815260200191505060405180910390f35b606060078054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156117af5780601f10611784576101008083540402835291602001916117af565b820191906000526020600020905b81548152906001019060200180831161179257829003601f168201915b5050505050905090565b600033826117cf82826117ca613683565b613eb6565b816117d984612b73565b10611819576040518060400160405280601981526020017f696e73756666696369656e74207665737465642066756e647300000000000000815250611850565b6040518060400160405280601281526020017f696e73756666696369656e742066756e647300000000000000000000000000008152505b906118f6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156118bb5780820151818401526020810190506118a0565b50505050905090810190601f1680156118e85780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506119018585613ece565b9250505092915050565b6000600354905090565b600061192b82600b613efc90919063ffffffff16565b9050919050565b600061193d33611915565b6119af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600b8152602001807f6f6e6c794772616e746f7200000000000000000000000000000000000000000081525060200191505060405180910390fd5b6000600e60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000600d60008360020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000611a63612f46565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480611aeb57508260030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b611b5d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600b8152602001807f6e6f7420616c6c6f77656400000000000000000000000000000000000000000081525060200191505060405180910390fd5b8260000160009054906101000a900460ff16611be1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f6e6f20616374697665206772616e74000000000000000000000000000000000081525060200191505060405180910390fd5b8160000160019054906101000a900460ff16611c65576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600b8152602001807f69727265766f6361626c6500000000000000000000000000000000000000000081525060200191505060405180910390fd5b8160000160069054906101000a900463ffffffff168360000160029054906101000a900463ffffffff160163ffffffff168563ffffffff161115611d11576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260098152602001807f6e6f20656666656374000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b611d19613683565b63ffffffff168563ffffffff161015611d9a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f63616e6e6f74207265766f6b652076657374656420686f6c64696e677300000081525060200191505060405180910390fd5b611da48686613f8e565b9050611dd5868460030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836141c8565b611e04868460030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683611f12565b506001600e60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160016101000a81548160ff0219169083151502179055506000600e60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548160ff0219169083151502179055508463ffffffff168673ffffffffffffffffffffffffffffffffffffffff167f906c0c4c98565a396c542d9102cae7a794e84af6763123e068a1b277333bf4a460405160405180910390a36001935050505092915050565b6000600660009054906101000a900460ff1615611f2e57600080fd5b611f39848484614327565b90509392505050565b6000806000806000806000806000611f5a338b6136f3565b9850985098509850985098509850985098509193959799909294969850565b6000600960009054906101000a900460ff16905090565b6000803390508091505090565b611fa5612f70565b611fae57600080fd5b611fb7816143d8565b50565b6000600660009054906101000a900460ff1615611fd657600080fd5b611fe0838361446c565b905092915050565b600033611ff481614511565b612066576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f6772616e746f72206163636f756e74206e6f742072656164790000000000000081525060200191505060405180910390fd5b826000600f60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060000160009054906101000a900460ff1661212e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f736574207265737472696374696f6e732066697273740000000000000000000081525060200191505060405180910390fd5b8060000160019054906101000a900463ffffffff1663ffffffff168263ffffffff161015801561217d57508060000160059054906101000a900463ffffffff1663ffffffff168263ffffffff16105b6121ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f737461727444617920746f6f206561726c79000000000000000000000000000081525060200191505060405180910390fd5b8060000160099054906101000a900463ffffffff1663ffffffff16612212613683565b63ffffffff161061228b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f6772616e746f722065787069726564000000000000000000000000000000000081525060200191505060405180910390fd5b8761229581614534565b612307576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6163636f756e74206e6f7420726567697374657265640000000000000000000081525060200191505060405180910390fd5b6123158989898933336145c0565b945050505050949350505050565b61232c33612919565b61239e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600a8152602001807f6f6e6c795061757365720000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600660009054906101000a900460ff166123b757600080fd5b6000600660006101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa33604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1565b6000600660009054906101000a900460ff1661245257600080fd5b61245b33612919565b6124cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600a8152602001807f6f6e6c795061757365720000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6124d633612919565b612548576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600a8152602001807f6f6e6c795061757365720000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6000612552612f46565b90508073ffffffffffffffffffffffffffffffffffffffff16ff5b600061257833611915565b6125ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600b8152602001807f6f6e6c794772616e746f7200000000000000000000000000000000000000000081525060200191505060405180910390fd5b886125f481614534565b612666576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6163636f756e74206e6f7420726567697374657265640000000000000000000081525060200191505060405180910390fd5b6126768a8a8a8a8a8a8a8a612c51565b91505098975050505050505050565b60008261269181614534565b612703576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6163636f756e74206e6f7420726567697374657265640000000000000000000081525060200191505060405180910390fd5b61270d8484613373565b50600191505092915050565b60008261272581614534565b612797576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6163636f756e74206e6f7420726567697374657265640000000000000000000081525060200191505060405180910390fd5b6127a2858585611f12565b5060019150509392505050565b33816127c382826127be613683565b613eb6565b816127cd84612b73565b1061280d576040518060400160405280601981526020017f696e73756666696369656e74207665737465642066756e647300000000000000815250612844565b6040518060400160405280601281526020017f696e73756666696369656e742066756e647300000000000000000000000000008152505b906128ea576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156128af578082015181840152602081019050612894565b50505050905090810190601f1680156128dc5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506128f53384614a53565b505050565b612902612f70565b61290b57600080fd5b6129158282614ba7565b5050565b600061292f826005613efc90919063ffffffff16565b9050919050565b6000600660009054906101000a900460ff16905090565b612955612f70565b61295e57600080fd5b61296781614c93565b50565b6000612974612f70565b61297d57600080fd5b8561298781614534565b6129f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6163636f756e74206e6f7420726567697374657265640000000000000000000081525060200191505060405180910390fd5b612a0287612b0c565b612a74576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f756e69666f726d206772616e746f72206f6e6c7900000000000000000000000081525060200191505060405180910390fd5b612a7d87614d27565b15612af0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f7363686564756c6520616c72656164792065786973747300000000000000000081525060200191505060405180910390fd5b612afd8786888787614d80565b50600191505095945050505050565b6000612b1782611915565b8015612b6c5750600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b9050919050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b612bc4612f70565b612bcd57600080fd5b6000612c41576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260098152602001807f666f7262696464656e000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b565b612c4d82826150a7565b5050565b6000612c5c33611915565b612cce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600b8152602001807f6f6e6c794772616e746f7200000000000000000000000000000000000000000081525060200191505060405180910390fd5b600e60008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff1615612d91576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f6772616e7420616c72656164792065786973747300000000000000000000000081525060200191505060405180910390fd5b612d9e8985878686614d80565b50612dad898989898d336145c0565b506001905098975050505050505050565b612dc6612f70565b612dcf57600080fd5b612dd88161514e565b50565b806000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209080519060200190612e2d9291906158da565b5050565b612e3a33612919565b612eac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600a8152602001807f6f6e6c795061757365720000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600660009054906101000a900460ff1615612ec657600080fd5b6001600660006101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25833604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b606060088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156130605780601f1061303557610100808354040283529160200191613060565b820191906000526020600020905b81548152906001019060200180831161304357829003601f168201915b5050505050905090565b6000613074612f70565b61307d57600080fd5b8461308781614534565b6130f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6163636f756e74206e6f7420726567697374657265640000000000000000000081525060200191505060405180910390fd5b61310286612b0c565b801561311957508463ffffffff168463ffffffff16115b80156131375750613128613683565b63ffffffff168363ffffffff16115b6131a9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f696e76616c696420706172616d7300000000000000000000000000000000000081525060200191505060405180910390fd5b60405180608001604052806001151581526020018663ffffffff1681526020018563ffffffff1681526020018463ffffffff16815250600f60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160056101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160096101000a81548163ffffffff021916908363ffffffff1602179055509050508573ffffffffffffffffffffffffffffffffffffffff167fd204f080300249d73110cd2c2e8d720f0362e94b8e0f1b797ac249acca176551868686604051808463ffffffff1663ffffffff1681526020018363ffffffff1663ffffffff1681526020018263ffffffff1663ffffffff168152602001935050505060405180910390a26001915050949350505050565b6000600660009054906101000a900460ff161561336157600080fd5b61336b83836151e2565b905092915050565b600033826133898282613384613683565b613eb6565b8161339384612b73565b106133d3576040518060400160405280601981526020017f696e73756666696369656e74207665737465642066756e64730000000000000081525061340a565b6040518060400160405280601281526020017f696e73756666696369656e742066756e647300000000000000000000000000008152505b906134b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561347557808201518184015260208101905061345a565b50505050905090810190601f1680156134a25780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506134bb8585615287565b9250505092915050565b6000806000836134d433611915565b8061350a57508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b61357c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f6f6e6c794772616e746f724f7253656c6600000000000000000000000000000081525060200191505060405180910390fd5b600d60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160069054906101000a900463ffffffff16600d60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160029054906101000a900463ffffffff16600d60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001600a9054906101000a900463ffffffff16935093509350509193909250565b60006201518063ffffffff16428161369757fe5b04905090565b6000600a60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b60008060008060008060008060008a61370b33611915565b8061374157508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b6137b3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f6f6e6c794772616e746f724f7253656c6600000000000000000000000000000081525060200191505060405180910390fd5b6000600e60008e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000600d60008360020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060006138698f8f613f8e565b905060008360010154905061388782826152b590919063ffffffff16565b82828660000160029054906101000a900463ffffffff168660000160069054906101000a900463ffffffff168760000160029054906101000a900463ffffffff1688600001600a9054906101000a900463ffffffff168a60000160009054906101000a900460ff168b60000160019054906101000a900460ff169d509d509d509d509d509d509d509d509d5050505050509295985092959850929598565b60006001600a60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff167fcd822dc9688e20acea68724a2fbcfe4f3e526d20ecaa37b18fe3047ab377d6a560405160405180910390a26001905090565b60606000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015613a9d5780601f10613a7257610100808354040283529160200191613a9d565b820191906000526020600020905b815481529060010190602001808311613a8057829003601f168201915b5050505050905090565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b613b36612f70565b613b3f57600080fd5b613b48336143d8565b613b518161533e565b613b5c816000614ba7565b50565b600082613b6b81614534565b613bdd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6163636f756e74206e6f7420726567697374657265640000000000000000000081525060200191505060405180910390fd5b613be784846117b9565b50600191505092915050565b600033613bff81614511565b613c71576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f6772616e746f72206163636f756e74206e6f742072656164790000000000000081525060200191505060405180910390fd5b826000600f60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060000160009054906101000a900460ff16613d39576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f736574207265737472696374696f6e732066697273740000000000000000000081525060200191505060405180910390fd5b8060000160019054906101000a900463ffffffff1663ffffffff168263ffffffff1610158015613d8857508060000160059054906101000a900463ffffffff1663ffffffff168263ffffffff16105b613dfa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f737461727444617920746f6f206561726c79000000000000000000000000000081525060200191505060405180910390fd5b8060000160099054906101000a900463ffffffff1663ffffffff16613e1d613683565b63ffffffff1610613e96576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f6772616e746f722065787069726564000000000000000000000000000000000081525060200191505060405180910390fd5b613ea48888888833336145c0565b9350505050949350505050565b600881565b6000613ec284836153d8565b83111590509392505050565b6000600660009054906101000a900460ff1615613eea57600080fd5b613ef48383615411565b905092915050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415613f3757600080fd5b8260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b600080600e60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000600d60008360020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600061404485615428565b90508260000160009054906101000a900460ff16158061409957508160000160029054906101000a900463ffffffff168360000160029054906101000a900463ffffffff160163ffffffff168163ffffffff16105b156140ad57826001015493505050506141c2565b8160000160069054906101000a900463ffffffff168360000160029054906101000a900463ffffffff160163ffffffff168163ffffffff16106140f657600093505050506141c2565b60008360000160029054906101000a900463ffffffff1682039050600083600001600a9054906101000a900463ffffffff1684600001600a9054906101000a900463ffffffff1663ffffffff168363ffffffff168161415157fe5b0402905060006141a08560000160069054906101000a900463ffffffff1663ffffffff166141928463ffffffff16896001015461544d90919063ffffffff16565b61548790919063ffffffff16565b90506141b98187600101546152b590919063ffffffff16565b96505050505050505b92915050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561420257600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561423c57600080fd5b80600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b60006143348484846154ad565b6143cd84336143c885600260008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546152b590919063ffffffff16565b6141c8565b600190509392505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561441257600080fd5b61442681600b61567b90919063ffffffff16565b8073ffffffffffffffffffffffffffffffffffffffff167f33a8bb468e8361c5c40d643192eb6970b91cb87aa0200f8709f5b805087b905360405160405180910390a250565b6000614507338461450285600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546156ec90919063ffffffff16565b6141c8565b6001905092915050565b600061451c82612b0c565b801561452d575061452c82614d27565b5b9050919050565b60003373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806145b95750600a60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b9050919050565b6000600e60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff1615614685576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f6772616e7420616c72656164792065786973747300000000000000000000000081525060200191505060405180910390fd5b8585111580156146955750600085115b80156146c957506201518063ffffffff1663386d438063ffffffff16816146b857fe5b0463ffffffff168463ffffffff1610155b80156147015750620592bb6201518063ffffffff1663386d438063ffffffff16816146f057fe5b040163ffffffff168463ffffffff16105b614773576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f696e76616c69642076657374696e6720706172616d730000000000000000000081525060200191505060405180910390fd5b61477c83614d27565b6147ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f6e6f20737563682076657374696e67207363686564756c65000000000000000081525060200191505060405180910390fd5b6147f98288886154ad565b6040518060c001604052806001151581526020016000151581526020018563ffffffff1681526020018681526020018473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff16815250600e60008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548160ff02191690831515021790555060408201518160000160026101000a81548163ffffffff021916908363ffffffff1602179055506060820151816001015560808201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060a08201518160030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509050508173ffffffffffffffffffffffffffffffffffffffff16858873ffffffffffffffffffffffffffffffffffffffff167fce19dc9f3460f5845c81c7fa52526977d7e7275df4b1d0e40ea09653252e0c758787604051808363ffffffff1663ffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a4600190509695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415614a8d57600080fd5b614aa2816003546152b590919063ffffffff16565b600381905550614afa81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546152b590919063ffffffff16565b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415614be157600080fd5b614bf582600b61570b90919063ffffffff16565b80600c60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff167f614c7c37719098320f845a142223983b9adcc4c3f2663971d5b0eb4c661a24e760405160405180910390a25050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415614ccd57600080fd5b614ce181600561567b90919063ffffffff16565b8073ffffffffffffffffffffffffffffffffffffffff167fcd265ebaf09df2871cc7bd4133404a235ba12eff2041bb89d9c714a2621c7c7e60405160405180910390a250565b6000600d60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff169050919050565b6000808463ffffffff16118015614db657506064620592bb63ffffffff1681614da557fe5b0463ffffffff168463ffffffff1611155b8015614dcd57508363ffffffff168563ffffffff16105b8015614de0575060018363ffffffff1610155b614e52576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f696e76616c69642076657374696e67207363686564756c65000000000000000081525060200191505060405180910390fd5b60008363ffffffff168563ffffffff1681614e6957fe5b0663ffffffff16148015614e98575060008363ffffffff168663ffffffff1681614e8f57fe5b0663ffffffff16145b614eed576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806159806023913960400191505060405180910390fd5b6040518060a0016040528060011515815260200183151581526020018663ffffffff1681526020018563ffffffff1681526020018463ffffffff16815250600d60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548160ff02191690831515021790555060408201518160000160026101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160066101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600a6101000a81548163ffffffff021916908363ffffffff1602179055509050508115158463ffffffff168773ffffffffffffffffffffffffffffffffffffffff167fb84219eaee5910cc5311a393fbd4287b14bc791973b97f64d4b61b6d8554adc78887604051808363ffffffff1663ffffffff1681526020018263ffffffff1663ffffffff1681526020019250505060405180910390a46001905095945050505050565b6150b18282614a53565b61514a823361514584600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546152b590919063ffffffff16565b6141c8565b5050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561518857600080fd5b61519c81600561570b90919063ffffffff16565b8073ffffffffffffffffffffffffffffffffffffffff167f6719d08c1888103bea251a4ed56406bd0c3e69723c8a1686e017e7bbe159b6f860405160405180910390a250565b600061527d338461527885600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546152b590919063ffffffff16565b6141c8565b6001905092915050565b6000600660009054906101000a900460ff16156152a357600080fd5b6152ad838361577d565b905092915050565b60008282111561532d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f496e73756666696369656e742066756e6473000000000000000000000000000081525060200191505060405180910390fd5b600082840390508091505092915050565b8061534881614534565b6153ba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6163636f756e74206e6f7420726567697374657265640000000000000000000081525060200191505060405180910390fd5b6153c2612f70565b6153cb57600080fd5b6153d482615794565b5050565b6000806153e484612b73565b905060006154046153f58686613f8e565b836152b590919063ffffffff16565b9050809250505092915050565b600061541e3384846141c8565b6001905092915050565b6000808263ffffffff161461543d5781615446565b615445613683565b5b9050919050565b6000808314156154605760009050615481565b600082840290508284828161547157fe5b041461547c57600080fd5b809150505b92915050565b600080821161549557600080fd5b60008284816154a057fe5b0490508091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156154e757600080fd5b61553981600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546152b590919063ffffffff16565b600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506155ce81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546156ec90919063ffffffff16565b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6156858282613efc565b61568e57600080fd5b60008260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b60008082840190508381101561570157600080fd5b8091505092915050565b6157158282613efc565b1561571f57600080fd5b60018260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b600061578a3384846154ad565b6001905092915050565b61579c612f70565b6157a557600080fd5b6157ae33614c93565b6157b7816157c3565b6157c08161514e565b50565b6157cb612f70565b6157d457600080fd5b6157dd816157e0565b50565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561581a57600080fd5b8073ffffffffffffffffffffffffffffffffffffffff16600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a380600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061591b57805160ff1916838001178555615949565b82800160010185558215615949579182015b8281111561594857825182559160200191906001019061592d565b5b509050615956919061595a565b5090565b61597c91905b80821115615978576000816000905550600101615960565b5090565b9056fe696e76616c696420636c6966662f6475726174696f6e20666f7220696e74657276616ca165627a7a72305820d649a15d4562c80ee725bf10910265b540c343bfc9ac6c5ae7465332b2b54a1e0029

Deployed Bytecode Sourcemap

62112:2065:0:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63140:10;63124:38;;;63152:9;63124:38;;;;;;;;;;;;;;;;;;62112:2065;12597:83;;8:9:-1;5:2;;;30:1;27;20:12;5:2;12597:83:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;12597:83:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;54026:172;;8:9:-1;5:2;;;30:1;27;20:12;5:2;54026:172:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;54026:172:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;4345:91;;8:9:-1;5:2;;;30:1;27;20:12;5:2;4345:91:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;25424:111;;8:9:-1;5:2;;;30:1;27;20:12;5:2;25424:111:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;25424:111:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;51606:1598;;8:9:-1;5:2;;;30:1;27;20:12;5:2;51606:1598:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;51606:1598:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;20640:160;;8:9:-1;5:2;;;30:1;27;20:12;5:2;20640:160:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;20640:160:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;49335:420;;8:9:-1;5:2;;;30:1;27;20:12;5:2;49335:420:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;49335:420:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12913:83;;8:9:-1;5:2;;;30:1;27;20:12;5:2;12913:83:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;373:132;;8:9:-1;5:2;;;30:1;27;20:12;5:2;373:132:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;25685:99;;8:9:-1;5:2;;;30:1;27;20:12;5:2;25685:99:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;25685:99:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;20956:167;;8:9:-1;5:2;;;30:1;27;20:12;5:2;20956:167:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;20956:167:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;61253:593;;8:9:-1;5:2;;;30:1;27;20:12;5:2;61253:593:0;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;61253:593:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;20210:118;;8:9:-1;5:2;;;30:1;27;20:12;5:2;20210:118:0;;;:::i;:::-;;63915:259;;8:9:-1;5:2;;;30:1;27;20:12;5:2;63915:259:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;42015:471;;8:9:-1;5:2;;;30:1;27;20:12;5:2;42015:471:0;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;42015:471:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;22799:158;;8:9:-1;5:2;;;30:1;27;20:12;5:2;22799:158:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;22799:158:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;23144:186;;8:9:-1;5:2;;;30:1;27;20:12;5:2;23144:186:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;23144:186:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;63494:184;;8:9:-1;5:2;;;30:1;27;20:12;5:2;63494:184:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;63494:184:0;;;;;;;;;;;;;;;;;:::i;:::-;;25543:134;;8:9:-1;5:2;;;30:1;27;20:12;5:2;25543:134:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;25543:134:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;17468:109;;8:9:-1;5:2;;;30:1;27;20:12;5:2;17468:109:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;17468:109:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;19463:78;;8:9:-1;5:2;;;30:1;27;20:12;5:2;19463:78:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;17684:97;;8:9:-1;5:2;;;30:1;27;20:12;5:2;17684:97:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;17684:97:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;57889:841;;8:9:-1;5:2;;;30:1;27;20:12;5:2;57889:841:0;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;57889:841:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;26225:144;;8:9:-1;5:2;;;30:1;27;20:12;5:2;26225:144:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;26225:144:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;4655:106;;8:9:-1;5:2;;;30:1;27;20:12;5:2;4655:106:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;4655:106:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;26981:92;;8:9:-1;5:2;;;30:1;27;20:12;5:2;26981:92:0;;;:::i;:::-;;11865:95;;8:9:-1;5:2;;;30:1;27;20:12;5:2;11865:95:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;11865:95:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;41030:855;;8:9:-1;5:2;;;30:1;27;20:12;5:2;41030:855:0;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;41030:855:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;17585:91;;8:9:-1;5:2;;;30:1;27;20:12;5:2;17585:91:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;17585:91:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;187:94;;8:9:-1;5:2;;;30:1;27;20:12;5:2;187:94:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;187:94:0;;;;;;;;;;21:11:-1;8;5:28;2:2;;;46:1;43;36:12;2:2;187:94:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;187:94:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;187:94:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;187:94:0;;;;;;;;;;;;;;;:::i;:::-;;19999:116;;8:9:-1;5:2;;;30:1;27;20:12;5:2;19999:116:0;;;:::i;:::-;;13688:79;;8:9:-1;5:2;;;30:1;27;20:12;5:2;13688:79:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;14023:92;;8:9:-1;5:2;;;30:1;27;20:12;5:2;14023:92:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;12747:87;;8:9:-1;5:2;;;30:1;27;20:12;5:2;12747:87:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;12747:87:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56258:803;;8:9:-1;5:2;;;30:1;27;20:12;5:2;56258:803:0;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;56258:803:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;21131:177;;8:9:-1;5:2;;;30:1;27;20:12;5:2;21131:177:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;21131:177:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;53742:164;;8:9:-1;5:2;;;30:1;27;20:12;5:2;53742:164:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;53742:164:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;36549:429;;8:9:-1;5:2;;;30:1;27;20:12;5:2;36549:429:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;36549:429:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;42793:123;;8:9:-1;5:2;;;30:1;27;20:12;5:2;42793:123:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;22174:117;;8:9:-1;5:2;;;30:1;27;20:12;5:2;22174:117:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;22174:117:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;47314:1023;;8:9:-1;5:2;;;30:1;27;20:12;5:2;47314:1023:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;47314:1023:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21996:170;;8:9:-1;5:2;;;30:1;27;20:12;5:2;21996:170:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;600:109;;8:9:-1;5:2;;;30:1;27;20:12;5:2;600:109:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;600:109:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5100:131;;8:9:-1;5:2;;;30:1;27;20:12;5:2;5100:131:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;5100:131:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;27250:211;;8:9:-1;5:2;;;30:1;27;20:12;5:2;27250:211:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;27250:211:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;22965:171;;8:9:-1;5:2;;;30:1;27;20:12;5:2;22965:171:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;22965:171:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;60572:551;;8:9:-1;5:2;;;30:1;27;20:12;5:2;60572:551:0;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;60572:551:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;62221:34;;8:9:-1;5:2;;;30:1;27;20:12;5:2;62221:34:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;12597:83;12634:13;12667:5;12660:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12597:83;:::o;54026:172::-;54134:7;54106:10;54118:5;50747:46;50768:7;50777:6;50785:7;:5;:7::i;:::-;50747:20;:46::i;:::-;50829:6;50808:18;50818:7;50808:9;:18::i;:::-;:27;:80;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50739:150;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;50739:150:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;54161:29;54175:7;54184:5;54161:13;:29::i;:::-;54154:36;;54026:172;;;;;;:::o;4345:91::-;4389:7;4416:12;;4409:19;;4345:91;:::o;25424:111::-;25481:4;25505:22;25519:7;25505:9;:13;;:22;;;;:::i;:::-;25498:29;;25424:111;;;:::o;51606:1598::-;51690:7;25200:21;25210:10;25200:9;:21::i;:::-;25192:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;51710:24;51737:12;:25;51750:11;51737:25;;;;;;;;;;;;;;;51710:52;;51773:31;51807:17;:40;51825:5;:21;;;;;;;;;;;;51807:40;;;;;;;;;;;;;;;51773:74;;51858:23;51977:7;:5;:7::i;:::-;51963:21;;:10;:21;;;:52;;;;52002:5;:13;;;;;;;;;;;;51988:27;;:10;:27;;;51963:52;51955:76;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52116:5;:14;;;;;;;;;;;;52108:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52207:7;:19;;;;;;;;;;;;52199:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52331:7;:16;;;;;;;;;;;;52314:5;:14;;;;;;;;;;;;:33;52305:42;;:5;:42;;;;52297:64;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52456:7;:5;:7::i;:::-;52447:16;;:5;:16;;;;52439:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52528:39;52548:11;52561:5;52528:19;:39::i;:::-;52510:57;;52690:53;52699:11;52712:5;:13;;;;;;;;;;;;52727:15;52690:8;:53::i;:::-;52794:57;52807:11;52820:5;:13;;;;;;;;;;;;52835:15;52794:12;:57::i;:::-;;53022:4;52983:12;:25;52996:11;52983:25;;;;;;;;;;;;;;;:36;;;:43;;;;;;;;;;;;;;;;;;53074:5;53037:12;:25;53050:11;53037:25;;;;;;;;;;;;;;;:34;;;:42;;;;;;;;;;;;;;;;;;53123:5;53097:32;;53110:11;53097:32;;;;;;;;;;;;53192:4;53185:11;;;;;51606:1598;;;;:::o;20640:160::-;20733:4;19700:7;;;;;;;;;;;19699:8;19691:17;;;;;;20757:35;20776:4;20782:2;20786:5;20757:18;:35::i;:::-;20750:42;;20640:160;;;;;:::o;49335:420::-;49408:20;49439:23;49473:21;49505:19;49535;49565:20;49596:23;49630:13;49654:15;49700:47;49722:10;49734:12;49700:21;:47::i;:::-;49693:54;;;;;;;;;;;;;;;;;;49335:420;;;;;;;;;;;:::o;12913:83::-;12954:5;12979:9;;;;;;;;;;;12972:16;;12913:83;:::o;373:132::-;414:19;446:14;463:10;446:27;;491:6;484:13;;;373:132;:::o;25685:99::-;13900:9;:7;:9::i;:::-;13892:18;;;;;;25753:23;25768:7;25753:14;:23::i;:::-;25685:99;:::o;20956:167::-;21047:4;19700:7;;;;;;;;;;;19699:8;19691:17;;;;;;21071:44;21095:7;21104:10;21071:23;:44::i;:::-;21064:51;;20956:167;;;;:::o;61253:593::-;61571:7;61465:10;59344:37;59373:7;59344:28;:37::i;:::-;59336:75;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;61509:8;59503:32;59538:13;:25;59552:10;59538:25;;;;;;;;;;;;;;;59503:60;;59582:11;:19;;;;;;;;;;;;59574:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;59675:11;:23;;;;;;;;;;;;59663:35;;:8;:35;;;;:86;;;;;59726:11;:23;;;;;;;;;;;;59715:34;;:8;:34;;;59663:86;59641:131;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;59803:11;:25;;;;;;;;;;;;59793:35;;:7;:5;:7::i;:::-;:35;;;59785:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;61544:11;22522:23;22537:7;22522:14;:23::i;:::-;22514:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;61744:94;61764:11;61777;61790:13;61805:8;61815:10;61827;61744:19;:94::i;:::-;61737:101;;59859:1;59422;;61253:593;;;;;;;:::o;20210:118::-;17405:20;17414:10;17405:8;:20::i;:::-;17397:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19879:7;;;;;;;;;;;19871:16;;;;;;20279:5;20269:7;;:15;;;;;;;;;;;;;;;;;;20300:20;20309:10;20300:20;;;;;;;;;;;;;;;;;;;;;;20210:118::o;63915:259::-;63969:15;19879:7;;;;;;;;;;;19871:16;;;;;;17405:20;17414:10;17405:8;:20::i;:::-;17397:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;64005:20;64014:10;64005:8;:20::i;:::-;63997:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;64051:28;64098:7;:5;:7::i;:::-;64051:56;;64131:12;64118:26;;;42015:471;42292:7;25200:21;25210:10;25200:9;:21::i;:::-;25192:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;42270:11;22522:23;22537:7;22522:14;:23::i;:::-;22514:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;42321:157;42354:11;42367;42380:13;42408:8;42418;42428:13;42443:8;42466:11;42321:18;:157::i;:::-;42314:164;;25248:1;42015:471;;;;;;;;;;:::o;22799:158::-;22888:7;22875:2;22522:23;22537:7;22522:14;:23::i;:::-;22514:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22908:19;22917:2;22921:5;22908:8;:19::i;:::-;;22945:4;22938:11;;22799:158;;;;;:::o;23144:186::-;23251:7;23238:2;22522:23;22537:7;22522:14;:23::i;:::-;22514:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23271:29;23284:4;23290:2;23294:5;23271:12;:29::i;:::-;;23318:4;23311:11;;23144:186;;;;;;:::o;63494:184::-;63547:10;63559:5;50747:46;50768:7;50777:6;50785:7;:5;:7::i;:::-;50747:20;:46::i;:::-;50829:6;50808:18;50818:7;50808:9;:18::i;:::-;:27;:80;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50739:150;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;50739:150:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63646:24;63652:10;63664:5;63646;:24::i;:::-;63494:184;;;:::o;25543:134::-;13900:9;:7;:9::i;:::-;13892:18;;;;;;25631:38;25643:7;25652:16;25631:11;:38::i;:::-;25543:134;;:::o;17468:109::-;17524:4;17548:21;17561:7;17548:8;:12;;:21;;;;:::i;:::-;17541:28;;17468:109;;;:::o;19463:78::-;19502:4;19526:7;;;;;;;;;;;19519:14;;19463:78;:::o;17684:97::-;13900:9;:7;:9::i;:::-;13892:18;;;;;;17751:22;17765:7;17751:13;:22::i;:::-;17684:97;:::o;57889:841::-;58142:7;13900:9;:7;:9::i;:::-;13892:18;;;;;;58119:7;22522:23;22537:7;22522:14;:23::i;:::-;22514:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;58245:25;58262:7;58245:16;:25::i;:::-;58237:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;58377:28;58397:7;58377:19;:28::i;:::-;58376:29;58368:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;58622:76;58642:7;58651:13;58666:8;58676;58686:11;58622:19;:76::i;:::-;;58718:4;58711:11;;13921:1;57889:841;;;;;;;:::o;26225:144::-;26289:4;26313:18;26323:7;26313:9;:18::i;:::-;:48;;;;;26335:17;:26;26353:7;26335:26;;;;;;;;;;;;;;;;;;;;;;;;;26313:48;26306:55;;26225:144;;;:::o;4655:106::-;4710:7;4737:9;:16;4747:5;4737:16;;;;;;;;;;;;;;;;4730:23;;4655:106;;;:::o;26981:92::-;13900:9;:7;:9::i;:::-;13892:18;;;;;;27046:5;27038:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26981:92::o;11865:95::-;11930:22;11940:4;11946:5;11930:9;:22::i;:::-;11865:95;;:::o;41030:855::-;41321:7;25200:21;25210:10;25200:9;:21::i;:::-;25192:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;41412:12;:25;41425:11;41412:25;;;;;;;;;;;;;;;:34;;;;;;;;;;;;41411:35;41403:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;41570:80;41590:11;41603:13;41618:8;41628;41638:11;41570:19;:80::i;:::-;;41758:95;41778:11;41791;41804:13;41819:8;41829:11;41842:10;41758:19;:95::i;:::-;;41873:4;41866:11;;41030:855;;;;;;;;;;:::o;17585:91::-;13900:9;:7;:9::i;:::-;13892:18;;;;;;17649:19;17660:7;17649:10;:19::i;:::-;17585:91;:::o;187:94::-;264:9;243:6;:18;250:10;243:18;;;;;;;;;;;;;;;:30;;;;;;;;;;;;:::i;:::-;;187:94;:::o;19999:116::-;17405:20;17414:10;17405:8;:20::i;:::-;17397:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19700:7;;;;;;;;;;;19699:8;19691:17;;;;;;20069:4;20059:7;;:14;;;;;;;;;;;;;;;;;;20089:18;20096:10;20089:18;;;;;;;;;;;;;;;;;;;;;;19999:116::o;13688:79::-;13726:7;13753:6;;;;;;;;;;;13746:13;;13688:79;:::o;14023:92::-;14063:4;14101:6;;;;;;;;;;;14087:20;;:10;:20;;;14080:27;;14023:92;:::o;12747:87::-;12786:13;12819:7;12812:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12747:87;:::o;56258:803::-;56480:7;13900:9;:7;:9::i;:::-;13892:18;;;;;;56457:7;22522:23;22537:7;22522:14;:23::i;:::-;22514:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56527:25;56544:7;56527:16;:25::i;:::-;:64;;;;;56580:11;56566:25;;:11;:25;;;56527:64;:101;;;;;56621:7;:5;:7::i;:::-;56605:23;;:13;:23;;;56527:101;56505:142;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56761:133;;;;;;;;56788:4;56761:133;;;;;;56818:11;56761:133;;;;;;56844:11;56761:133;;;;;;56870:13;56761:133;;;;;56736:13;:22;56750:7;56736:22;;;;;;;;;;;;;;;:158;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56982:7;56959:72;;;56991:11;57004;57017:13;56959:72;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;57049:4;57042:11;;13921:1;56258:803;;;;;;:::o;21131:177::-;21227:4;19700:7;;;;;;;;;;;19699:8;19691:17;;;;;;21251:49;21275:7;21284:15;21251:23;:49::i;:::-;21244:56;;21131:177;;;;:::o;53742:164::-;53846:7;53818:10;53830:5;50747:46;50768:7;50777:6;50785:7;:5;:7::i;:::-;50747:20;:46::i;:::-;50829:6;50808:18;50818:7;50808:9;:18::i;:::-;:27;:80;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50739:150;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;50739:150:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;53873:25;53888:2;53892:5;53873:14;:25::i;:::-;53866:32;;53742:164;;;;;;:::o;36549:429::-;36689:19;36719:20;36750:23;36652:11;25328:21;25338:10;25328:9;:21::i;:::-;:46;;;;25367:7;25353:21;;:10;:21;;;25328:46;25320:76;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36815:17;:30;36833:11;36815:30;;;;;;;;;;;;;;;:39;;;;;;;;;;;;36865:17;:30;36883:11;36865:30;;;;;;;;;;;;;;;:44;;;;;;;;;;;;36920:17;:30;36938:11;36920:30;;;;;;;;;;;;;;;:39;;;;;;;;;;;;36797:173;;;;;;36549:429;;;;;;:::o;42793:123::-;42831:16;31337:12;42874:33;;:15;:33;;;;;;42860:48;;42793:123;:::o;22174:117::-;22234:7;22261:13;:22;22275:7;22261:22;;;;;;;;;;;;;;;;;;;;;;;;;22254:29;;22174:117;;;:::o;47314:1023::-;47494:20;47525:23;47559:21;47591:19;47621;47651:20;47682:23;47716:13;47740:15;47457:11;25328:21;25338:10;25328:9;:21::i;:::-;:46;;;;25367:7;25353:21;;:10;:21;;;25328:46;25320:76;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;47779:24;47806:12;:25;47819:11;47806:25;;;;;;;;;;;;;;;47779:52;;47842:31;47876:17;:40;47894:5;:21;;;;;;;;;;;;47876:40;;;;;;;;;;;;;;;47842:74;;47927:23;47953:46;47973:11;47986:12;47953:19;:46::i;:::-;47927:72;;48010:19;48032:5;:12;;;48010:34;;48075:32;48091:15;48075:11;:15;;:32;;;;:::i;:::-;48118:15;48144:11;48166:5;:14;;;;;;;;;;;;48191:7;:16;;;;;;;;;;;;48218:7;:21;;;;;;;;;;;;48250:7;:16;;;;;;;;;;;;48277:5;:14;;;;;;;;;;;;48302:5;:16;;;;;;;;;;;;48057:272;;;;;;;;;;;;;;;;;;;;;;47314:1023;;;;;;;;;;;;:::o;21996:170::-;22039:7;22087:4;22059:13;:25;22073:10;22059:25;;;;;;;;;;;;;;;;:32;;;;;;;;;;;;;;;;;;22125:10;22107:29;;;;;;;;;;;;22154:4;22147:11;;21996:170;:::o;600:109::-;639:22;682:6;:18;689:10;682:18;;;;;;;;;;;;;;;674:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;600:109;:::o;5100:131::-;5172:7;5199:8;:15;5208:5;5199:15;;;;;;;;;;;;;;;:24;5215:7;5199:24;;;;;;;;;;;;;;;;5192:31;;5100:131;;;;:::o;27250:211::-;13900:9;:7;:9::i;:::-;13892:18;;;;;;27323:26;27338:10;27323:14;:26::i;:::-;27360:33;27384:8;27360:23;:33::i;:::-;27404:49;27416:8;24809:5;27404:11;:49::i;:::-;27250:211;:::o;22965:171::-;23063:7;23045;22522:23;22537:7;22522:14;:23::i;:::-;22514:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23083:23;23091:7;23100:5;23083:7;:23::i;:::-;;23124:4;23117:11;;22965:171;;;;;:::o;60572:551::-;60848:7;60780:10;59344:37;59373:7;59344:28;:37::i;:::-;59336:75;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;60824:8;59503:32;59538:13;:25;59552:10;59538:25;;;;;;;;;;;;;;;59503:60;;59582:11;:19;;;;;;;;;;;;59574:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;59675:11;:23;;;;;;;;;;;;59663:35;;:8;:35;;;;:86;;;;;59726:11;:23;;;;;;;;;;;;59715:34;;:8;:34;;;59663:86;59641:131;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;59803:11;:25;;;;;;;;;;;;59793:35;;:7;:5;:7::i;:::-;:35;;;59785:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;61021:94;61041:11;61054;61067:13;61082:8;61092:10;61104;61021:19;:94::i;:::-;61014:101;;59422:1;;60572:551;;;;;;;:::o;62221:34::-;62254:1;62221:34;:::o;50125:182::-;50225:7;50263:35;50283:7;50292:5;50263:19;:35::i;:::-;50253:6;:45;;50245:54;;50125:182;;;;;:::o;20808:140::-;20887:4;19700:7;;;;;;;;;;;19699:8;19691:17;;;;;;20911:29;20925:7;20934:5;20911:13;:29::i;:::-;20904:36;;20808:140;;;;:::o;15988:165::-;16060:4;16104:1;16085:21;;:7;:21;;;;16077:30;;;;;;16125:4;:11;;:20;16137:7;16125:20;;;;;;;;;;;;;;;;;;;;;;;;;16118:27;;15988:165;;;;:::o;43501:1916::-;43595:23;43631:24;43658:12;:25;43671:11;43658:25;;;;;;;;;;;;;;;43631:52;;43694:31;43728:17;:40;43746:5;:21;;;;;;;;;;;;43728:40;;;;;;;;;;;;;;;43694:74;;43779:12;43794:27;43808:12;43794:13;:27::i;:::-;43779:42;;43940:5;:14;;;;;;;;;;;;43939:15;:65;;;;43983:7;:21;;;;;;;;;;;;43966:5;:14;;;;;;;;;;;;:38;43958:46;;:5;:46;;;43939:65;43935:1475;;;44090:5;:12;;;44083:19;;;;;;;43935:1475;44249:7;:16;;;;;;;;;;;;44232:5;:14;;;;;;;;;;;;:33;44223:42;;:5;:42;;;44219:1191;;44359:1;44344:17;;;;;;;44219:1191;44522:17;44550:5;:14;;;;;;;;;;;;44542:5;:22;44522:42;;44664:26;44727:7;:16;;;;;;;;;;;;44707:7;:16;;;;;;;;;;;;44694:29;;:10;:29;;;;;;;;44693:50;44664:79;;45276:14;45293:59;45335:7;:16;;;;;;;;;;;;45293:59;;:37;45310:19;45293:37;;:5;:12;;;:16;;:37;;;;:::i;:::-;:41;;:59;;;;:::i;:::-;45276:76;;45374:24;45391:6;45374:5;:12;;;:16;;:24;;;;:::i;:::-;45367:31;;;;;;;;43501:1916;;;;;:::o;10402:254::-;10512:1;10495:19;;:5;:19;;;;10487:28;;;;;;10553:1;10534:21;;:7;:21;;;;10526:30;;;;;;10596:5;10569:8;:15;10578:5;10569:15;;;;;;;;;;;;;;;:24;10585:7;10569:24;;;;;;;;;;;;;;;:32;;;;10633:7;10617:31;;10626:5;10617:31;;;10642:5;10617:31;;;;;;;;;;;;;;;;;;10402:254;;;:::o;6814:228::-;6893:4;6910:26;6920:4;6926:2;6930:5;6910:9;:26::i;:::-;6947:65;6956:4;6962:10;6974:37;7005:5;6974:8;:14;6983:4;6974:14;;;;;;;;;;;;;;;:26;6989:10;6974:26;;;;;;;;;;;;;;;;:30;;:37;;;;:::i;:::-;6947:8;:65::i;:::-;7030:4;7023:11;;6814:228;;;;;:::o;26044:173::-;26131:1;26112:21;;:7;:21;;;;26104:30;;;;;;26145:25;26162:7;26145:9;:16;;:25;;;;:::i;:::-;26201:7;26186:23;;;;;;;;;;;;26044:173;:::o;7568:203::-;7648:4;7665:76;7674:10;7686:7;7695:45;7729:10;7695:8;:20;7704:10;7695:20;;;;;;;;;;;;;;;:29;7716:7;7695:29;;;;;;;;;;;;;;;;:33;;:45;;;;:::i;:::-;7665:8;:76::i;:::-;7759:4;7752:11;;7568:203;;;;:::o;59011:249::-;59089:7;59195:25;59212:7;59195:16;:25::i;:::-;:57;;;;;59224:28;59244:7;59224:19;:28::i;:::-;59195:57;59188:64;;59011:249;;;:::o;22299:150::-;22363:11;22405:10;22394:21;;:7;:21;;;:47;;;;22419:13;:22;22433:7;22419:22;;;;;;;;;;;;;;;;;;;;;;;;;22394:47;22387:54;;22299:150;;;:::o;38235:1604::-;38472:7;38557:12;:25;38570:11;38557:25;;;;;;;;;;;;;;;:34;;;;;;;;;;;;38556:35;38548:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38710:11;38693:13;:28;;:49;;;;;38741:1;38725:13;:17;38693:49;:93;;;;;31337:12;31604:36;;31446:9;31604:36;;;;;;;;38759:27;;:8;:27;;;;38693:93;:123;;;;;31028:6;31337:12;31604:36;;31446:9;31604:36;;;;;;;;31689:37;38790:26;;:8;:26;;;38693:123;38671:185;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38950:36;38970:15;38950:19;:36::i;:::-;38942:73;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39118:44;39128:7;39137:11;39150;39118:9;:44::i;:::-;39319:341;;;;;;;;39344:4;39319:341;;;;;;39375:5;39319:341;;;;;;39409:8;39319:341;;;;;;39432:13;39319:341;;;;39460:15;39319:341;;;;;;39551:7;39319:341;;;;;39291:12;:25;39304:11;39291:25;;;;;;;;;;;;;;;:369;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39801:7;39725:84;;39759:13;39746:11;39725:84;;;39774:8;39784:15;39725:84;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39827:4;39820:11;;38235:1604;;;;;;;;:::o;9860:269::-;9954:1;9935:21;;:7;:21;;;;9927:30;;;;;;9985:23;10002:5;9985:12;;:16;;:23;;;;:::i;:::-;9970:12;:38;;;;10040:29;10063:5;10040:9;:18;10050:7;10040:18;;;;;;;;;;;;;;;;:22;;:29;;;;:::i;:::-;10019:9;:18;10029:7;10019:18;;;;;;;;;;;;;;;:50;;;;10111:1;10085:36;;10094:7;10085:36;;;10115:5;10085:36;;;;;;;;;;;;;;;;;;9860:269;;:::o;25792:244::-;25899:1;25880:21;;:7;:21;;;;25872:30;;;;;;25913:22;25927:7;25913:9;:13;;:22;;;;:::i;:::-;25975:16;25946:17;:26;25964:7;25946:26;;;;;;;;;;;;;;;;:45;;;;;;;;;;;;;;;;;;26020:7;26007:21;;;;;;;;;;;;25792:244;;:::o;17959:170::-;18045:1;18026:21;;:7;:21;;;;18018:30;;;;;;18059:24;18075:7;18059:8;:15;;:24;;;;:::i;:::-;18113:7;18099:22;;;;;;;;;;;;17959:170;:::o;35481:138::-;35550:7;35577:17;:26;35595:7;35577:26;;;;;;;;;;;;;;;:34;;;;;;;;;;;;35570:41;;35481:138;;;:::o;34256:1217::-;34430:7;34591:1;34580:8;:12;;;:42;;;;;31221:3;31028:6;31199:25;;;;;;;;34596:26;;:8;:26;;;;34580:42;:83;;;;;34655:8;34639:24;;:13;:24;;;34580:83;:113;;;;;34692:1;34680:8;:13;;;;34580:113;34558:187;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34922:1;34910:8;34899:19;;:8;:19;;;;;;;;:24;;;:57;;;;;34955:1;34943:8;34927:24;;:13;:24;;;;;;;;:29;;;34899:57;34877:142;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;35121:130;;;;;;;;35151:4;35121:130;;;;;;35181:11;35121:130;;;;;;35207:13;35121:130;;;;;;35222:8;35121:130;;;;;;35232:8;35121:130;;;;;35084:17;:34;35102:15;35084:34;;;;;;;;;;;;;;;:167;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;35431:11;35316:127;;35398:8;35316:127;;35353:15;35316:127;;;35383:13;35408:8;35316:127;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;35461:4;35454:11;;34256:1217;;;;;;;:::o;11055:182::-;11126:21;11132:7;11141:5;11126;:21::i;:::-;11158:71;11167:7;11176:10;11188:40;11222:5;11188:8;:17;11197:7;11188:17;;;;;;;;;;;;;;;:29;11206:10;11188:29;;;;;;;;;;;;;;;;:33;;:40;;;;:::i;:::-;11158:8;:71::i;:::-;11055:182;;:::o;17789:162::-;17872:1;17853:21;;:7;:21;;;;17845:30;;;;;;17886:21;17899:7;17886:8;:12;;:21;;;;:::i;:::-;17935:7;17923:20;;;;;;;;;;;;17789:162;:::o;8302:213::-;8387:4;8404:81;8413:10;8425:7;8434:50;8468:15;8434:8;:20;8443:10;8434:20;;;;;;;;;;;;;;;:29;8455:7;8434:29;;;;;;;;;;;;;;;;:33;;:50;;;;:::i;:::-;8404:8;:81::i;:::-;8503:4;8496:11;;8302:213;;;;:::o;20500:132::-;20575:4;19700:7;;;;;;;;;;;19699:8;19691:17;;;;;;20599:25;20614:2;20618:5;20599:14;:25::i;:::-;20592:32;;20500:132;;;;:::o;2754:172::-;2812:7;2845:1;2840;:6;;2832:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2880:9;2896:1;2892;:5;2880:17;;2917:1;2910:8;;;2754:172;;;;:::o;23711:144::-;23783:8;22522:23;22537:7;22522:14;:23::i;:::-;22514:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13900:9;:7;:9::i;:::-;13892:18;;;;;;23814:33;23838:8;23814:23;:33::i;:::-;23711:144;;:::o;45905:283::-;45992:23;46028:19;46050:22;46060:11;46050:9;:22::i;:::-;46028:44;;46083:14;46100:56;46116:39;46136:11;46149:5;46116:19;:39::i;:::-;46100:11;:15;;:56;;;;:::i;:::-;46083:73;;46174:6;46167:13;;;;45905:283;;;;:::o;6193:148::-;6258:4;6275:36;6284:10;6296:7;6305:5;6275:8;:36::i;:::-;6329:4;6322:11;;6193:148;;;;:::o;42924:153::-;42991:16;43043:1;43027:12;:17;;;:42;;43057:12;43027:42;;;43047:7;:5;:7::i;:::-;43027:42;43020:49;;42924:153;;;:::o;1745:433::-;1803:7;2052:1;2047;:6;2043:47;;;2077:1;2070:8;;;;2043:47;2102:9;2118:1;2114;:5;2102:17;;2147:1;2142;2138;:5;;;;;;:10;2130:19;;;;;;2169:1;2162:8;;;1745:433;;;;;:::o;2313:303::-;2371:7;2470:1;2466;:5;2458:14;;;;;;2483:9;2499:1;2495;:5;;;;;;2483:17;;2607:1;2600:8;;;2313:303;;;;:::o;8743:262::-;8845:1;8831:16;;:2;:16;;;;8823:25;;;;;;8879:26;8899:5;8879:9;:15;8889:4;8879:15;;;;;;;;;;;;;;;;:19;;:26;;;;:::i;:::-;8861:9;:15;8871:4;8861:15;;;;;;;;;;;;;;;:44;;;;8932:24;8950:5;8932:9;:13;8942:2;8932:13;;;;;;;;;;;;;;;;:17;;:24;;;;:::i;:::-;8916:9;:13;8926:2;8916:13;;;;;;;;;;;;;;;:40;;;;8987:2;8972:25;;8981:4;8972:25;;;8991:5;8972:25;;;;;;;;;;;;;;;;;;8743:262;;;:::o;15747:146::-;15827:18;15831:4;15837:7;15827:3;:18::i;:::-;15819:27;;;;;;15880:5;15857:4;:11;;:20;15869:7;15857:20;;;;;;;;;;;;;;;;:28;;;;;;;;;;;;;;;;;;15747:146;;:::o;3014:150::-;3072:7;3092:9;3108:1;3104;:5;3092:17;;3133:1;3128;:6;;3120:15;;;;;;3155:1;3148:8;;;3014:150;;;;:::o;15524:143::-;15602:18;15606:4;15612:7;15602:3;:18::i;:::-;15601:19;15593:28;;;;;;15655:4;15632;:11;;:20;15644:7;15632:20;;;;;;;;;;;;;;;;:27;;;;;;;;;;;;;;;;;;15524:143;;:::o;5406:140::-;5467:4;5484:32;5494:10;5506:2;5510:5;5484:9;:32::i;:::-;5534:4;5527:11;;5406:140;;;;:::o;18834:181::-;13900:9;:7;:9::i;:::-;13892:18;;;;;;18907:25;18921:10;18907:13;:25::i;:::-;18943:33;18967:8;18943:23;:33::i;:::-;18987:20;18998:8;18987:10;:20::i;:::-;18834:181;:::o;14795:109::-;13900:9;:7;:9::i;:::-;13892:18;;;;;;14868:28;14887:8;14868:18;:28::i;:::-;14795:109;:::o;15054:187::-;15148:1;15128:22;;:8;:22;;;;15120:31;;;;;;15196:8;15167:38;;15188:6;;;;;;;;;;;15167:38;;;;;;;;;;;;15225:8;15216:6;;:17;;;;;;;;;;;;;;;;;;15054:187;:::o;62112:2065::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o

Swarm Source

bzzr://d649a15d4562c80ee725bf10910265b540c343bfc9ac6c5ae7465332b2b54a1e
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.