ETH Price: $2,237.88 (-6.45%)

Token

Vested AKRO (vAKRO)
 

Overview

Max Total Supply

3,721,213.648090336437763202 vAKRO

Holders

33

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Filtered by Token Holder
awestin.eth
Balance
20,807.486752083333333333 vAKRO

Value
$0.00
0xe86A383f599eB082F0Dd6187dC144E22893220F6
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
VestedAkro

Compiler Version
v0.6.12+commit.27d51765

Optimization Enabled:
Yes with 99999 runs

Other Settings:
default evmVersion, GNU AGPLv3 license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2021-07-09
*/

// SPDX-License-Identifier: AGPL V3.0

pragma solidity 0.6.12;



// Part: AddressUpgradeable

/**
 * @dev Collection of functions related to the address type
 */
library AddressUpgradeable {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (bool success, ) = recipient.call{ value: amount }("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain`call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
      return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: value }(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

// Part: IERC20Upgradeable

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20Upgradeable {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: 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
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

// Part: Initializable

/**
 * @title Initializable
 *
 * @dev Helper contract to support initializer functions. To use it, replace
 * the constructor with a function that has the `initializer` modifier.
 * WARNING: Unlike constructors, initializer functions must be manually
 * invoked. This applies both to deploying an Initializable contract, as well
 * as extending an Initializable contract via inheritance.
 * WARNING: When used with inheritance, manual care must be taken to not invoke
 * a parent initializer twice, or ensure that all initializers are idempotent,
 * because this is not dealt with automatically as with constructors.
 */
contract Initializable {
    /**
     * @dev Indicates that the contract has been initialized.
     */
    bool private initialized;

    /**
     * @dev Indicates that the contract is in the process of being initialized.
     */
    bool private initializing;

    /**
     * @dev Modifier to use in the initializer function of a contract.
     */
    modifier initializer() {
        require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized");

        bool isTopLevelCall = !initializing;
        if (isTopLevelCall) {
            initializing = true;
            initialized = true;
        }

        _;

        if (isTopLevelCall) {
            initializing = false;
        }
    }

    /// @dev Returns true if and only if the function is running in the constructor
    function isConstructor() private view returns (bool) {
        // extcodesize checks the size of the code stored in an address, and
        // address returns the current address. Since the code is still not
        // deployed when running a constructor, any checks on its code size will
        // yield zero, making it an effective way to detect if a contract is
        // under construction or not.
        address self = address(this);
        uint256 cs;
        assembly {
            cs := extcodesize(self)
        }
        return cs == 0;
    }

    // Reserved storage space to allow for layout changes in the future.
    uint256[50] private ______gap;
}

// Part: Roles

/**
 * @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), "Roles: account already has role");
        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), "Roles: account does not have role");
        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), "Roles: account is the zero address");
        return role.bearer[account];
    }
}

// Part: SafeMathUpgradeable

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMathUpgradeable {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot 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-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

// Part: ContextUpgradeable

/*
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with GSN meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract ContextUpgradeable is Initializable {
    function __Context_init() internal initializer {
        __Context_init_unchained();
    }

    function __Context_init_unchained() internal initializer {
    }
    function _msgSender() internal view virtual returns (address payable) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
    uint256[50] private __gap;
}

// Part: SafeERC20Upgradeable

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20Upgradeable {
    using SafeMathUpgradeable for uint256;
    using AddressUpgradeable for address;

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

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

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        // solhint-disable-next-line max-line-length
        require((value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).add(value);
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) { // Return data is optional
            // solhint-disable-next-line max-line-length
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

// Part: MinterRole

contract MinterRole is Initializable, ContextUpgradeable {
    using Roles for Roles.Role;

    event MinterAdded(address indexed account);
    event MinterRemoved(address indexed account);

    Roles.Role private _minters;

    function initialize(address sender) public virtual initializer {
        __Context_init_unchained();
        if (!isMinter(sender)) {
            _addMinter(sender);
        }
    }

    modifier onlyMinter() {
        require(isMinter(_msgSender()), "MinterRole: caller does not have the Minter role");
        _;
    }

    function isMinter(address account) public view returns (bool) {
        return _minters.has(account);
    }

    function addMinter(address account) public onlyMinter {
        _addMinter(account);
    }

    function renounceMinter() public {
        _removeMinter(_msgSender());
    }

    function _addMinter(address account) internal {
        _minters.add(account);
        emit MinterAdded(account);
    }

    function _removeMinter(address account) internal {
        _minters.remove(account);
        emit MinterRemoved(account);
    }

    uint256[50] private ______gap;
}

// Part: OwnableUpgradeable

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

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    function __Ownable_init() internal initializer {
        __Context_init_unchained();
        __Ownable_init_unchained();
    }

    function __Ownable_init_unchained() internal initializer {
        address msgSender = _msgSender();
        _owner = msgSender;
        emit OwnershipTransferred(address(0), msgSender);
    }

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

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

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

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

// Part: VestedAkroSenderRole

contract VestedAkroSenderRole is Initializable, ContextUpgradeable {
    using Roles for Roles.Role;

    event SenderAdded(address indexed account);
    event SenderRemoved(address indexed account);

    Roles.Role private _senders;

    function initialize(address sender) public virtual initializer {
        __Context_init_unchained();
        if (!isSender(sender)) {
            _addSender(sender);
        }
    }

    modifier onlySender() {
        require(isSender(_msgSender()), "SenderRole: caller does not have the Sender role");
        _;
    }

    function isSender(address account) public view returns (bool) {
        return _senders.has(account);
    }

    function addSender(address account) public onlySender {
        _addSender(account);
    }

    function renounceSender() public {
        _removeSender(_msgSender());
    }

    function _addSender(address account) internal {
        _senders.add(account);
        emit SenderAdded(account);
    }

    function _removeSender(address account) internal {
        _senders.remove(account);
        emit SenderRemoved(account);
    }

    uint256[50] private ______gap;
}

// File: VestedAkro.sol

/**
 * @notice VestedAkro token represents AKRO token vested for a vestingPeriod set by owner of this VestedAkro token.
 * Generic holders of this token CAN NOT transfer it. They only can redeem AKRO from unlocked vAKRO.
 * Minters can mint unlocked vAKRO from AKRO to special VestedAkroSenders.
 * VestedAkroSender can send his unlocked vAKRO to generic holders, and this vAKRO will be vested. He can not redeem AKRO himself.
 */
contract VestedAkro is OwnableUpgradeable, IERC20Upgradeable, MinterRole, VestedAkroSenderRole {
    using SafeMathUpgradeable for uint256;
    using SafeERC20Upgradeable for IERC20Upgradeable;

    event Locked(address indexed holder, uint256 amount);
    event Unlocked(address indexed holder, uint256 amount);
    event AkroAdded(uint256 amount);

    struct VestedBatch {
        uint256 amount; // Full amount of vAKRO vested in this batch
        uint256 start; // Vesting start time;
        uint256 end; // Vesting end time
        uint256 claimed; // vAKRO already claimed from this batch to unlocked balance of holder
    }

    struct Balance {
        VestedBatch[] batches; // Array of vesting batches
        uint256 locked; // Amount locked in batches
        uint256 unlocked; // Amount of unlocked vAKRO (which either was previously claimed, or received from Minter)
        uint256 firstUnclaimedBatch; // First batch which is not fully claimed
    }

    string private _name;
    string private _symbol;
    uint8 private _decimals;

    uint256 public override totalSupply;
    IERC20Upgradeable public akro;
    uint256 public vestingPeriod; //set by owner of this VestedAkro token
    uint256 public vestingStart; //set by owner, default value 01 May 2021, 00:00:00 GMT+0
    uint256 public vestingCliff; //set by owner, cliff for akro unlock, 1 month by default
    mapping(address => mapping(address => uint256)) private allowances;
    mapping(address => Balance) private holders;

    uint256 public swapToAkroRateNumerator; //Amount of 1 vAkro for 1 AKRO - 1 by default
    uint256 public swapToAkroRateDenominator;

    function initialize(address _akro, uint256 _vestingPeriod) public initializer {
        __Ownable_init();
        MinterRole.initialize(_msgSender());
        VestedAkroSenderRole.initialize(_msgSender());

        _name = "Vested AKRO";
        _symbol = "vAKRO";
        _decimals = 18;

        akro = IERC20Upgradeable(_akro);
        require(_vestingPeriod > 0, "VestedAkro: vestingPeriod should be > 0");
        vestingPeriod = _vestingPeriod;
        vestingStart = 1619827200; //01 May 2021, 00:00:00 GMT+0
        vestingCliff = 31 * 24 * 60 * 60; //1 month - 31 day in May

        swapToAkroRateNumerator = 1;
        swapToAkroRateDenominator = 1;
    }

    // Stub for compiler purposes only
    function initialize(address sender) public override(MinterRole, VestedAkroSenderRole) {}

    function name() public view returns (string memory) {
        return _name;
    }

    function symbol() public view returns (string memory) {
        return _symbol;
    }

    function decimals() public view returns (uint8) {
        return _decimals;
    }

    function allowance(address owner, address spender) public view override returns (uint256) {
        return allowances[owner][spender];
    }

    function approve(address spender, uint256 amount) public override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) public override onlySender returns (bool) {
        // We require both sender and _msgSender() to have VestedAkroSender role
        // to prevent sender from redeem and prevent unauthorized transfers via transferFrom.
        require(isSender(sender), "VestedAkro: sender should have VestedAkroSender role");

        _transfer(sender, recipient, amount);
        _approve(sender, _msgSender(), allowances[sender][_msgSender()].sub(amount, "VestedAkro: transfer amount exceeds allowance"));
        return true;
    }

    function transfer(address recipient, uint256 amount) public override onlySender returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    function setVestingPeriod(uint256 _vestingPeriod) public onlyOwner {
        require(_vestingPeriod > 0, "VestedAkro: vestingPeriod should be > 0");
        vestingPeriod = _vestingPeriod;
    }

    /**
     * @notice Sets vesting start date (as unix timestamp). Owner only
     * @param _vestingStart Unix timestamp.
     */
    function setVestingStart(uint256 _vestingStart) public onlyOwner {
        require(_vestingStart > 0, "VestedAkro: vestingStart should be > 0");
        vestingStart = _vestingStart;
    }

    /**
     * @notice Sets vesting start date (as unix timestamp). Owner only
     * @param _vestingCliff Cliff in seconds (1 month by default)
     */
    function setVestingCliff(uint256 _vestingCliff) public onlyOwner {
        vestingCliff = _vestingCliff;
    }

    /**
     * @notice Sets the rate of ADEL to vAKRO swap: 1 ADEL = _swapRateNumerator/_swapRateDenominator vAKRO
     * @notice By default is set to 0, that means that swap is disabled
     * @param _swapRateNumerator Numerator for Adel converting. Can be set to 0 - that stops the swap.
     * @param _swapRateDenominator Denominator for Adel converting. Can't be set to 0
     */
    function setSwapRate(uint256 _swapRateNumerator, uint256 _swapRateDenominator) external onlyOwner {
        require(_swapRateDenominator > 0, "Incorrect value");
        swapToAkroRateNumerator = _swapRateNumerator;
        swapToAkroRateDenominator = _swapRateDenominator;
    }

    function mint(address beneficiary, uint256 amount) public onlyMinter {
        totalSupply = totalSupply.add(amount);
        holders[beneficiary].unlocked = holders[beneficiary].unlocked.add(amount);
        emit Transfer(address(0), beneficiary, amount);
    }

    /**
     * @notice Burns locked token from the user by the Minter
     * @param sender User to burn tokens from
     * @param amount Amount to burn
     */
    function burnFrom(address sender, uint256 amount) public onlyMinter {
        require(amount > 0, "Incorrect amount");
        require(sender != address(0), "Zero address");

        require(block.timestamp <= vestingStart, "Vesting has started");

        Balance storage b = holders[sender];

        require(b.locked >= amount, "Insufficient vAkro");
        require(b.batches.length > 0 || b.firstUnclaimedBatch < b.batches.length, "Nothing to burn");

        totalSupply = totalSupply.sub(amount);
        b.locked = b.locked.sub(amount);

        uint256 batchAmount = b.batches[b.firstUnclaimedBatch].amount;
        b.batches[b.firstUnclaimedBatch].amount = batchAmount.sub(amount);

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

    /**
     * @notice Adds AKRO liquidity to the swap contract
     * @param _amount Amout of AKRO added to the contract.
     */
    function addAkroLiquidity(uint256 _amount) public onlyMinter {
        require(_amount > 0, "Incorrect amount");

        IERC20Upgradeable(akro).safeTransferFrom(_msgSender(), address(this), _amount);

        emit AkroAdded(_amount);
    }

    /**
     * @notice Unlocks all avilable vAKRO for a holder
     * @param holder Whose funds to unlock
     * @return total unlocked amount awailable for redeem
     */
    function unlockAvailable(address holder) public returns (uint256) {
        require(holders[holder].batches.length > 0, "VestedAkro: nothing to unlock");
        claimAllFromBatches(holder);
        return holders[holder].unlocked;
    }

    /**
     * @notice Unlock all available vAKRO and redeem it
     * @return Amount redeemed
     */
    function unlockAndRedeemAll() public returns (uint256) {
        address beneficiary = _msgSender();
        claimAllFromBatches(beneficiary);
        return redeemAllUnlocked();
    }

    /**
     * @notice Redeem all already unlocked vAKRO. Sends AKRO by the set up rate
     * @return Amount vAkro redeemed
     */
    function redeemAllUnlocked() public returns (uint256) {
        address beneficiary = _msgSender();
        require(!isSender(beneficiary), "VestedAkro: VestedAkroSender is not allowed to redeem");
        uint256 amount = holders[beneficiary].unlocked;
        if (amount == 0) return 0;

        uint256 akroAmount = amount.mul(swapToAkroRateNumerator).div(swapToAkroRateDenominator);
        require(akro.balanceOf(address(this)) >= akroAmount, "Not enough AKRO");

        holders[beneficiary].unlocked = 0;
        totalSupply = totalSupply.sub(amount);

        akro.safeTransfer(beneficiary, akroAmount);

        emit Transfer(beneficiary, address(0), amount);
        return amount;
    }

    /**
     * @notice Calculates AKRO amount according to vAkro
     * @param account Whose funds to get balance
     * @return Akro amount recalculated
     */
    function balanceOfAkro(address account) public view returns (uint256) {
        Balance storage b = holders[account];
        uint256 amount = b.locked.add(b.unlocked);
        uint256 akroAmount = amount.mul(swapToAkroRateNumerator).div(swapToAkroRateDenominator);
        return akroAmount;
    }

    function balanceOf(address account) public view override returns (uint256) {
        Balance storage b = holders[account];
        return b.locked.add(b.unlocked);
    }

    function balanceInfoOf(address account)
        public
        view
        returns (
            uint256 locked,
            uint256 unlocked,
            uint256 unlockable
        )
    {
        Balance storage b = holders[account];
        return (b.locked, b.unlocked, calculateClaimableFromBatches(account));
    }

    function batchesInfoOf(address account) public view returns (uint256 firstUnclaimedBatch, uint256 totalBatches) {
        Balance storage b = holders[account];
        return (b.firstUnclaimedBatch, b.batches.length);
    }

    function batchInfo(address account, uint256 batch)
        public
        view
        returns (
            uint256 amount,
            uint256 start,
            uint256 end,
            uint256 claimed,
            uint256 claimable
        )
    {
        VestedBatch storage vb = holders[account].batches[batch];
        (claimable, ) = calculateClaimableFromBatch(vb);
        return (vb.amount, vestingStart, vestingStart.add(vestingPeriod), vb.claimed, claimable);
    }

    function _approve(
        address owner,
        address spender,
        uint256 amount
    ) internal {
        require(owner != address(0), "VestedAkro: approve from the zero address");
        require(spender != address(0), "VestedAkro: approve to the zero address");

        allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    function _transfer(
        address sender,
        address recipient,
        uint256 amount
    ) internal {
        require(sender != address(0), "VestedAkro: transfer from the zero address");
        require(recipient != address(0), "VestedAkro: transfer to the zero address");

        holders[sender].unlocked = holders[sender].unlocked.sub(amount, "VestedAkro: transfer amount exceeds unlocked balance");
        createOrModifyBatch(recipient, amount);

        emit Transfer(sender, recipient, amount);
    }

    function createOrModifyBatch(address holder, uint256 amount) internal {
        Balance storage b = holders[holder];

        if (b.batches.length == 0 || b.firstUnclaimedBatch == b.batches.length) {
            b.batches.push(VestedBatch({amount: amount, start: vestingStart, end: vestingStart.add(vestingPeriod), claimed: 0}));
        } else {
            uint256 batchAmount = b.batches[b.firstUnclaimedBatch].amount;
            b.batches[b.firstUnclaimedBatch].amount = batchAmount.add(amount);
        }
        b.locked = b.locked.add(amount);
        emit Locked(holder, amount);
    }

    function claimAllFromBatches(address holder) internal {
        claimAllFromBatches(holder, holders[holder].batches.length);
    }

    function claimAllFromBatches(address holder, uint256 tillBatch) internal {
        Balance storage b = holders[holder];
        bool firstUnclaimedFound;
        uint256 claiming;
        for (uint256 i = b.firstUnclaimedBatch; i < tillBatch; i++) {
            (uint256 claimable, bool fullyClaimable) = calculateClaimableFromBatch(b.batches[i]);
            if (claimable > 0) {
                b.batches[i].claimed = b.batches[i].claimed.add(claimable);
                claiming = claiming.add(claimable);
            }
            if (!fullyClaimable && !firstUnclaimedFound) {
                b.firstUnclaimedBatch = i;
                firstUnclaimedFound = true;
            }
        }
        if (!firstUnclaimedFound) {
            b.firstUnclaimedBatch = b.batches.length;
        }
        if (claiming > 0) {
            b.locked = b.locked.sub(claiming);
            b.unlocked = b.unlocked.add(claiming);
            emit Unlocked(holder, claiming);
        }
    }

    /**
     * @notice Calculates claimable amount from all batches
     * @param holder pointer to a batch
     * @return claimable amount
     */
    function calculateClaimableFromBatches(address holder) internal view returns (uint256) {
        Balance storage b = holders[holder];
        uint256 claiming;
        for (uint256 i = b.firstUnclaimedBatch; i < b.batches.length; i++) {
            (uint256 claimable, ) = calculateClaimableFromBatch(b.batches[i]);
            claiming = claiming.add(claimable);
        }
        return claiming;
    }

    /**
     * @notice Calculates one batch
     * @param vb pointer to a batch
     * @return claimable amount and bool which is true if batch is fully claimable
     */
    function calculateClaimableFromBatch(VestedBatch storage vb) internal view returns (uint256, bool) {
        if (now < vestingStart.add(vestingCliff)) {
            return (0, false); // No unlcoks before cliff period is over
        }
        if (now >= vestingStart.add(vestingPeriod)) {
            return (vb.amount.sub(vb.claimed), true);
        }
        uint256 claimable = (vb.amount.mul(now.sub(vestingStart)).div(vestingPeriod)).sub(vb.claimed);
        return (claimable, false);
    }
}

Contract Security Audit

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"AkroAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"holder","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Locked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"MinterAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"MinterRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"SenderAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"SenderRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"holder","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Unlocked","type":"event"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"addAkroLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addSender","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"akro","outputs":[{"internalType":"contract IERC20Upgradeable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceInfoOf","outputs":[{"internalType":"uint256","name":"locked","type":"uint256"},{"internalType":"uint256","name":"unlocked","type":"uint256"},{"internalType":"uint256","name":"unlockable","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOfAkro","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"batch","type":"uint256"}],"name":"batchInfo","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"end","type":"uint256"},{"internalType":"uint256","name":"claimed","type":"uint256"},{"internalType":"uint256","name":"claimable","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"batchesInfoOf","outputs":[{"internalType":"uint256","name":"firstUnclaimedBatch","type":"uint256"},{"internalType":"uint256","name":"totalBatches","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_akro","type":"address"},{"internalType":"uint256","name":"_vestingPeriod","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isMinter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isSender","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"beneficiary","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"redeemAllUnlocked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceSender","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_swapRateNumerator","type":"uint256"},{"internalType":"uint256","name":"_swapRateDenominator","type":"uint256"}],"name":"setSwapRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vestingCliff","type":"uint256"}],"name":"setVestingCliff","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vestingPeriod","type":"uint256"}],"name":"setVestingPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vestingStart","type":"uint256"}],"name":"setVestingStart","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapToAkroRateDenominator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"swapToAkroRateNumerator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unlockAndRedeemAll","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"holder","type":"address"}],"name":"unlockAvailable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vestingCliff","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vestingPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vestingStart","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

608060405234801561001057600080fd5b50613d5f806100206000396000f3fe608060405234801561001057600080fd5b50600436106102c85760003560e01c806395d89b411161017b578063c2bae8c6116100d8578063e38434631161008c578063f2fde38b11610071578063f2fde38b146108cf578063f3640e7414610902578063f8c20b9b1461090a576102c8565b8063e384346314610869578063ed391c1c1461089c576102c8565b8063cd6dc687116100bd578063cd6dc687146107ed578063d922017114610826578063dd62ed3e1461082e576102c8565b8063c2bae8c61461079d578063c4d66de8146107ba576102c8565b8063aa271e1a1161012f578063b24f925c11610114578063b24f925c14610716578063b697f5311461071e578063c1ca99f814610751576102c8565b8063aa271e1a146106c0578063af6caba8146106f3576102c8565b806398650275116101605780639865027514610677578063a22dda181461067f578063a9059cbb14610687576102c8565b806395d89b411461063c578063983b2d5614610644576102c8565b806355111a59116102295780637313ee5a116101dd57806379476823116101c257806379476823146105f357806379cc6790146105fb5780638da5cb5b14610634576102c8565b80637313ee5a146105b85780637886be28146105c0576102c8565b806363f781e41161020e57806363f781e41461051957806370a082311461057d578063715018a6146105b0576102c8565b806355111a5914610497578063580ad06f146104c8576102c8565b806323b872dd11610280578063313ce56711610265578063313ce5671461042357806340bee0ed1461044157806340c10f191461045e576102c8565b806323b872dd146103d8578063254800d41461041b576102c8565b8063095ea7b3116102b1578063095ea7b314610364578063126f854d146103b157806318160ddd146103d0576102c8565b806306fdde03146102cd57806308a926fb1461034a575b600080fd5b6102d5610927565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561030f5781810151838201526020016102f7565b50505050905090810190601f16801561033c5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103526109dc565b60408051918252519081900360200190f35b61039d6004803603604081101561037a57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356109e3565b604080519115158252519081900360200190f35b6103ce600480360360208110156103c757600080fd5b5035610a01565b005b610352610af1565b61039d600480360360608110156103ee57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060400135610af8565b610352610c5e565b61042b610c65565b6040805160ff9092168252519081900360200190f35b6103ce6004803603602081101561045757600080fd5b5035610c6d565b6103ce6004803603604081101561047457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610d5d565b61049f610e71565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6104fb600480360360208110156104de57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610e8e565b60408051938452602084019290925282820152519081900360600190f35b6105526004803603604081101561052f57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610edb565b6040805195865260208601949094528484019290925260608401526080830152519081900360a00190f35b6103526004803603602081101561059357600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610f64565b6103ce610f9d565b61035261109d565b610352600480360360208110156105d657600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166110a4565b610352611110565b6103ce6004803603604081101561061157600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135611117565b61049f6114dc565b6102d56114f8565b6103ce6004803603602081101561065a57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611577565b6103ce6115e3565b6103526115f5565b61039d6004803603604081101561069d57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135611619565b61039d600480360360208110156106d657600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661168d565b6103ce6004803603604081101561070957600080fd5b508035906020013561169a565b6103ce6117a7565b6103ce6004803603602081101561073457600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166117b7565b6107846004803603602081101561076757600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611820565b6040805192835260208301919091528051918290030190f35b6103ce600480360360208110156107b357600080fd5b5035611853565b6103ce600480360360208110156107d057600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166115e0565b6103ce6004803603604081101561080357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356118ea565b610352611b99565b6103526004803603604081101561084457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516611e24565b61039d6004803603602081101561087f57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611e5d565b610352600480360360208110156108b257600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611e6a565b6103ce600480360360208110156108e557600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611f32565b6103526120bd565b6103ce6004803603602081101561092057600080fd5b50356120c4565b60fd8054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156109d15780601f106109a6576101008083540402835291602001916109d1565b820191906000526020600020905b8154815290600101906020018083116109b457829003601f168201915b505050505090505b90565b6101085481565b60006109f76109f06121f6565b84846121fa565b5060015b92915050565b610a096121f6565b60655473ffffffffffffffffffffffffffffffffffffffff908116911614610a9257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60008111610aeb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180613d046026913960400191505060405180910390fd5b61010355565b6101005481565b6000610b0a610b056121f6565b611e5d565b610b5f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180613a096030913960400191505060405180910390fd5b610b6884611e5d565b610bbd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526034815260200180613c716034913960400191505060405180910390fd5b610bc8848484612342565b610c5384610bd46121f6565b610c4e856040518060600160405280602d8152602001613bf4602d913973ffffffffffffffffffffffffffffffffffffffff8a1660009081526101056020526040812090610c206121f6565b73ffffffffffffffffffffffffffffffffffffffff1681526020810191909152604001600020549190612506565b6121fa565b5060015b9392505050565b6101035481565b60ff80541690565b610c756121f6565b60655473ffffffffffffffffffffffffffffffffffffffff908116911614610cfe57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60008111610d57576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526027815260200180613bac6027913960400191505060405180910390fd5b61010255565b610d6d610d686121f6565b61168d565b610dc2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180613b5b6030913960400191505060405180910390fd5b61010054610dd090826125b7565b6101005573ffffffffffffffffffffffffffffffffffffffff821660009081526101066020526040902060020154610e0890826125b7565b73ffffffffffffffffffffffffffffffffffffffff83166000818152610106602090815260408083206002019490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6101015473ffffffffffffffffffffffffffffffffffffffff1681565b73ffffffffffffffffffffffffffffffffffffffff811660009081526101066020526040812060018101546002820154839283929091610ecd8761262b565b935093509350509193909250565b73ffffffffffffffffffffffffffffffffffffffff82166000908152610106602052604081208054829182918291829182919088908110610f1857fe5b90600052602060002090600402019050610f31816126a9565b50815461010354610102549294509091610f4c9082906125b7565b83600301549550955095509550509295509295909350565b73ffffffffffffffffffffffffffffffffffffffff811660009081526101066020526040812060028101546001820154610c57916125b7565b610fa56121f6565b60655473ffffffffffffffffffffffffffffffffffffffff90811691161461102e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60655460405160009173ffffffffffffffffffffffffffffffffffffffff16907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3606580547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b6101025481565b73ffffffffffffffffffffffffffffffffffffffff81166000908152610106602052604081206002810154600182015483916110e091906125b7565b9050600061110761010854611101610107548561274c90919063ffffffff16565b906127bf565b95945050505050565b6101075481565b611122610d686121f6565b611177576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180613b5b6030913960400191505060405180910390fd5b600081116111e657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f496e636f727265637420616d6f756e7400000000000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff821661126857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f5a65726f20616464726573730000000000000000000000000000000000000000604482015290519081900360640190fd5b610103544211156112da57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f56657374696e6720686173207374617274656400000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8216600090815261010660205260409020600181015482111561137357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f496e73756666696369656e742076416b726f0000000000000000000000000000604482015290519081900360640190fd5b8054151580611386575080546003820154105b6113f157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f4e6f7468696e6720746f206275726e0000000000000000000000000000000000604482015290519081900360640190fd5b610100546113ff9083612801565b6101005560018101546114129083612801565b6001820155600381015481546000918391811061142b57fe5b600091825260209091206004909102015490506114488184612801565b8260000183600301548154811061145b57fe5b906000526020600020906004020160000181905550600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a350505050565b60655473ffffffffffffffffffffffffffffffffffffffff1690565b60fe8054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156109d15780601f106109a6576101008083540402835291602001916109d1565b611582610d686121f6565b6115d7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180613b5b6030913960400191505060405180910390fd5b6115e081612843565b50565b6115f36115ee6121f6565b612892565b565b6000806116006121f6565b905061160b816128e1565b611613611b99565b91505090565b6000611626610b056121f6565b61167b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180613a096030913960400191505060405180910390fd5b6109f76116866121f6565b8484612342565b60006109fb609783612913565b6116a26121f6565b60655473ffffffffffffffffffffffffffffffffffffffff90811691161461172b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6000811161179a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f496e636f72726563742076616c75650000000000000000000000000000000000604482015290519081900360640190fd5b6101079190915561010855565b6115f36117b26121f6565b6129ae565b6117c2610b056121f6565b611817576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180613a096030913960400191505060405180910390fd5b6115e0816129fd565b73ffffffffffffffffffffffffffffffffffffffff8116600090815261010660205260409020600381015490545b915091565b61185b6121f6565b60655473ffffffffffffffffffffffffffffffffffffffff9081169116146118e457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b61010455565b600054610100900460ff16806119035750611903612a4c565b80611911575060005460ff16155b611966576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180613c43602e913960400191505060405180910390fd5b600054610100900460ff161580156119cc57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff909116610100171660011790555b6119d4612a52565b6119e46119df6121f6565b612b75565b6119f46119ef6121f6565b612ca8565b60408051808201909152600b8082527f56657374656420414b524f0000000000000000000000000000000000000000006020909201918252611a389160fd91613975565b506040805180820190915260058082527f76414b524f0000000000000000000000000000000000000000000000000000006020909201918252611a7d9160fe91613975565b5060ff80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166012179055610101805473ffffffffffffffffffffffffffffffffffffffff85167fffffffffffffffffffffffff000000000000000000000000000000000000000090911617905581611b42576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526027815260200180613bac6027913960400191505060405180910390fd5b61010282905563608c9a00610103556228de80610104556001610107819055610108558015611b9457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1690555b505050565b600080611ba46121f6565b9050611baf81611e5d565b15611c05576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526035815260200180613ca56035913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000908152610106602052604090206002015480611c3f576000925050506109d9565b6000611c5e61010854611101610107548561274c90919063ffffffff16565b61010154604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051929350839273ffffffffffffffffffffffffffffffffffffffff909216916370a0823191602480820192602092909190829003018186803b158015611cd557600080fd5b505afa158015611ce9573d6000803e3d6000fd5b505050506040513d6020811015611cff57600080fd5b50511015611d6e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f4e6f7420656e6f75676820414b524f0000000000000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff83166000908152610106602052604081206002015561010054611da69083612801565b6101005561010154611dcf9073ffffffffffffffffffffffffffffffffffffffff168483612da8565b60408051838152905160009173ffffffffffffffffffffffffffffffffffffffff8616917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35091505090565b73ffffffffffffffffffffffffffffffffffffffff91821660009081526101056020908152604080832093909416825291909152205490565b60006109fb60ca83612913565b73ffffffffffffffffffffffffffffffffffffffff811660009081526101066020526040812054611efc57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f566573746564416b726f3a206e6f7468696e6720746f20756e6c6f636b000000604482015290519081900360640190fd5b611f05826128e1565b5073ffffffffffffffffffffffffffffffffffffffff166000908152610106602052604090206002015490565b611f3a6121f6565b60655473ffffffffffffffffffffffffffffffffffffffff908116911614611fc357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff811661202f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180613a626026913960400191505060405180910390fd5b60655460405173ffffffffffffffffffffffffffffffffffffffff8084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3606580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6101045481565b6120cf610d686121f6565b612124576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180613b5b6030913960400191505060405180910390fd5b6000811161219357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f496e636f727265637420616d6f756e7400000000000000000000000000000000604482015290519081900360640190fd5b6121c061219e6121f6565b6101015473ffffffffffffffffffffffffffffffffffffffff16903084612e35565b6040805182815290517f553d28c3c527fdb6b88ada7783469dbb0211d13d4ae0db85df4174cd0a381ae09181900360200190a150565b3390565b73ffffffffffffffffffffffffffffffffffffffff8316612266576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180613a396029913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166122d2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526027815260200180613b006027913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff80841660008181526101056020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b73ffffffffffffffffffffffffffffffffffffffff83166123ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180613ad6602a913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821661241a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180613a886028913960400191505060405180910390fd5b61246881604051806060016040528060348152602001613b276034913973ffffffffffffffffffffffffffffffffffffffff8616600090815261010660205260409020600201549190612506565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610106602052604090206002015561249c8282612ed0565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b600081848411156125af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561257457818101518382015260200161255c565b50505050905090810190601f1680156125a15780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600082820183811015610c5757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116600090815261010660205260408120600381015482905b82548110156126a157600061268984600001838154811061267657fe5b90600052602060002090600402016126a9565b50905061269683826125b7565b925050600101612659565b509392505050565b6000806126c561010454610103546125b790919063ffffffff16565b4210156126d75750600090508061184e565b61010254610103546126e8916125b7565b421061270957600383015483546126fe91612801565b60019150915061184e565b6000612741846003015461273b61010254611101612733610103544261280190919063ffffffff16565b89549061274c565b90612801565b946000945092505050565b60008261275b575060006109fb565b8282028284828161276857fe5b0414610c57576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180613bd36021913960400191505060405180910390fd5b6000610c5783836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061303f565b6000610c5783836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612506565b61284e6097826130be565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f690600090a250565b61289d609782613184565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb6669290600090a250565b73ffffffffffffffffffffffffffffffffffffffff8116600090815261010660205260409020546115e0908290613230565b600073ffffffffffffffffffffffffffffffffffffffff8216612981576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180613c216022913960400191505060405180910390fd5b5073ffffffffffffffffffffffffffffffffffffffff166000908152602091909152604090205460ff1690565b6129b960ca82613184565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f384859c5ef5fafac31e8bc92ce7fb48b1f2c74c4dd5e212eb84ec202fa5d9fad90600090a250565b612a0860ca826130be565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fd65eca5d561d3a4568c87b9b13ced4ab52a69edadfdfdb22d76bc595f36d7d8790600090a250565b303b1590565b600054610100900460ff1680612a6b5750612a6b612a4c565b80612a79575060005460ff16155b612ace576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180613c43602e913960400191505060405180910390fd5b600054610100900460ff16158015612b3457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff909116610100171660011790555b612b3c6133a3565b612b446134b5565b80156115e057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905550565b600054610100900460ff1680612b8e5750612b8e612a4c565b80612b9c575060005460ff16155b612bf1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180613c43602e913960400191505060405180910390fd5b600054610100900460ff16158015612c5757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff909116610100171660011790555b612c5f6133a3565b612c688261168d565b612c7557612c7582612843565b8015612ca457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1690555b5050565b600054610100900460ff1680612cc15750612cc1612a4c565b80612ccf575060005460ff16155b612d24576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180613c43602e913960400191505060405180910390fd5b600054610100900460ff16158015612d8a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff909116610100171660011790555b612d926133a3565b612d9b82611e5d565b612c7557612c75826129fd565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052611b94908490613645565b6040805173ffffffffffffffffffffffffffffffffffffffff80861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052612eca908590613645565b50505050565b73ffffffffffffffffffffffffffffffffffffffff821660009081526101066020526040902080541580612f08575080546003820154145b15612f8257604080516080810182528381526101035460208201819052610102548493830191612f37916125b7565b81526000602091820181905283546001818101865594825290829020835160049092020190815590820151928101929092556040810151600283015560600151600390910155612fda565b600081600001826003015481548110612f9757fe5b60009182526020909120600490910201549050612fb481846125b7565b82600001836003015481548110612fc757fe5b6000918252602090912060049091020155505b6001810154612fe990836125b7565b600182015560408051838152905173ffffffffffffffffffffffffffffffffffffffff8516917f9f1ec8c880f76798e7b793325d625e9b60e4082a553c98f42b6cda368dd60008919081900360200190a2505050565b600081836130a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181815283516024840152835190928392604490910191908501908083836000831561257457818101518382015260200161255c565b5060008385816130b457fe5b0495945050505050565b6130c88282612913565b1561313457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f526f6c65733a206163636f756e7420616c72656164792068617320726f6c6500604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff1660009081526020919091526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b61318e8282612913565b6131e3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180613b8b6021913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff1660009081526020919091526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b73ffffffffffffffffffffffffffffffffffffffff8216600090815261010660205260408120600381015490919081905b848110156133135760008061327e86600001848154811061267657fe5b909250905081156132ec576132bc8287600001858154811061329c57fe5b9060005260206000209060040201600301546125b790919063ffffffff16565b8660000184815481106132cb57fe5b60009182526020909120600360049092020101556132e984836125b7565b93505b801580156132f8575084155b156133095760038601839055600194505b5050600101613261565b508161332157825460038401555b801561339c5760018301546133369082612801565b6001840155600283015461334a90826125b7565b600284015560408051828152905173ffffffffffffffffffffffffffffffffffffffff8716917f0f0bc5b519ddefdd8e5f9e6423433aa2b869738de2ae34d58ebc796fc749fa0d919081900360200190a25b5050505050565b600054610100900460ff16806133bc57506133bc612a4c565b806133ca575060005460ff16155b61341f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180613c43602e913960400191505060405180910390fd5b600054610100900460ff16158015612b4457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff9091166101001716600117905580156115e057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905550565b600054610100900460ff16806134ce57506134ce612a4c565b806134dc575060005460ff16155b613531576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180613c43602e913960400191505060405180910390fd5b600054610100900460ff1615801561359757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff909116610100171660011790555b60006135a16121f6565b606580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35080156115e057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905550565b60606136a7826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661371d9092919063ffffffff16565b805190915015611b94578080602001905160208110156136c657600080fd5b5051611b94576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180613cda602a913960400191505060405180910390fd5b606061372c8484600085613734565b949350505050565b60608247101561378f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180613ab06026913960400191505060405180910390fd5b613798856138ef565b61380357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b6020831061386d57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613830565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146138cf576040519150601f19603f3d011682016040523d82523d6000602084013e6138d4565b606091505b50915091506138e48282866138f5565b979650505050505050565b3b151590565b60608315613904575081610c57565b8251156139145782518084602001fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181815284516024840152845185939192839260440191908501908083836000831561257457818101518382015260200161255c565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106139b657805160ff19168380011785556139e3565b828001600101855582156139e3579182015b828111156139e35782518255916020019190600101906139c8565b506139ef9291506139f3565b5090565b5b808211156139ef57600081556001016139f456fe53656e646572526f6c653a2063616c6c657220646f6573206e6f742068617665207468652053656e64657220726f6c65566573746564416b726f3a20617070726f76652066726f6d20746865207a65726f20616464726573734f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373566573746564416b726f3a207472616e7366657220746f20746865207a65726f2061646472657373416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c566573746564416b726f3a207472616e736665722066726f6d20746865207a65726f2061646472657373566573746564416b726f3a20617070726f766520746f20746865207a65726f2061646472657373566573746564416b726f3a207472616e7366657220616d6f756e74206578636565647320756e6c6f636b65642062616c616e63654d696e746572526f6c653a2063616c6c657220646f6573206e6f74206861766520746865204d696e74657220726f6c65526f6c65733a206163636f756e7420646f6573206e6f74206861766520726f6c65566573746564416b726f3a2076657374696e67506572696f642073686f756c64206265203e2030536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77566573746564416b726f3a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e6365526f6c65733a206163636f756e7420697320746865207a65726f2061646472657373436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564566573746564416b726f3a2073656e6465722073686f756c64206861766520566573746564416b726f53656e64657220726f6c65566573746564416b726f3a20566573746564416b726f53656e646572206973206e6f7420616c6c6f77656420746f2072656465656d5361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564566573746564416b726f3a2076657374696e6753746172742073686f756c64206265203e2030a2646970667358221220e816e816f1b75d82f423f81835efbad5d8189b3fd1fa97f102859da8ba51f4eb64736f6c634300060c0033

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106102c85760003560e01c806395d89b411161017b578063c2bae8c6116100d8578063e38434631161008c578063f2fde38b11610071578063f2fde38b146108cf578063f3640e7414610902578063f8c20b9b1461090a576102c8565b8063e384346314610869578063ed391c1c1461089c576102c8565b8063cd6dc687116100bd578063cd6dc687146107ed578063d922017114610826578063dd62ed3e1461082e576102c8565b8063c2bae8c61461079d578063c4d66de8146107ba576102c8565b8063aa271e1a1161012f578063b24f925c11610114578063b24f925c14610716578063b697f5311461071e578063c1ca99f814610751576102c8565b8063aa271e1a146106c0578063af6caba8146106f3576102c8565b806398650275116101605780639865027514610677578063a22dda181461067f578063a9059cbb14610687576102c8565b806395d89b411461063c578063983b2d5614610644576102c8565b806355111a59116102295780637313ee5a116101dd57806379476823116101c257806379476823146105f357806379cc6790146105fb5780638da5cb5b14610634576102c8565b80637313ee5a146105b85780637886be28146105c0576102c8565b806363f781e41161020e57806363f781e41461051957806370a082311461057d578063715018a6146105b0576102c8565b806355111a5914610497578063580ad06f146104c8576102c8565b806323b872dd11610280578063313ce56711610265578063313ce5671461042357806340bee0ed1461044157806340c10f191461045e576102c8565b806323b872dd146103d8578063254800d41461041b576102c8565b8063095ea7b3116102b1578063095ea7b314610364578063126f854d146103b157806318160ddd146103d0576102c8565b806306fdde03146102cd57806308a926fb1461034a575b600080fd5b6102d5610927565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561030f5781810151838201526020016102f7565b50505050905090810190601f16801561033c5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103526109dc565b60408051918252519081900360200190f35b61039d6004803603604081101561037a57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356109e3565b604080519115158252519081900360200190f35b6103ce600480360360208110156103c757600080fd5b5035610a01565b005b610352610af1565b61039d600480360360608110156103ee57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060400135610af8565b610352610c5e565b61042b610c65565b6040805160ff9092168252519081900360200190f35b6103ce6004803603602081101561045757600080fd5b5035610c6d565b6103ce6004803603604081101561047457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610d5d565b61049f610e71565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6104fb600480360360208110156104de57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610e8e565b60408051938452602084019290925282820152519081900360600190f35b6105526004803603604081101561052f57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610edb565b6040805195865260208601949094528484019290925260608401526080830152519081900360a00190f35b6103526004803603602081101561059357600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610f64565b6103ce610f9d565b61035261109d565b610352600480360360208110156105d657600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166110a4565b610352611110565b6103ce6004803603604081101561061157600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135611117565b61049f6114dc565b6102d56114f8565b6103ce6004803603602081101561065a57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611577565b6103ce6115e3565b6103526115f5565b61039d6004803603604081101561069d57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135611619565b61039d600480360360208110156106d657600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661168d565b6103ce6004803603604081101561070957600080fd5b508035906020013561169a565b6103ce6117a7565b6103ce6004803603602081101561073457600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166117b7565b6107846004803603602081101561076757600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611820565b6040805192835260208301919091528051918290030190f35b6103ce600480360360208110156107b357600080fd5b5035611853565b6103ce600480360360208110156107d057600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166115e0565b6103ce6004803603604081101561080357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356118ea565b610352611b99565b6103526004803603604081101561084457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516611e24565b61039d6004803603602081101561087f57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611e5d565b610352600480360360208110156108b257600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611e6a565b6103ce600480360360208110156108e557600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611f32565b6103526120bd565b6103ce6004803603602081101561092057600080fd5b50356120c4565b60fd8054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156109d15780601f106109a6576101008083540402835291602001916109d1565b820191906000526020600020905b8154815290600101906020018083116109b457829003601f168201915b505050505090505b90565b6101085481565b60006109f76109f06121f6565b84846121fa565b5060015b92915050565b610a096121f6565b60655473ffffffffffffffffffffffffffffffffffffffff908116911614610a9257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60008111610aeb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180613d046026913960400191505060405180910390fd5b61010355565b6101005481565b6000610b0a610b056121f6565b611e5d565b610b5f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180613a096030913960400191505060405180910390fd5b610b6884611e5d565b610bbd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526034815260200180613c716034913960400191505060405180910390fd5b610bc8848484612342565b610c5384610bd46121f6565b610c4e856040518060600160405280602d8152602001613bf4602d913973ffffffffffffffffffffffffffffffffffffffff8a1660009081526101056020526040812090610c206121f6565b73ffffffffffffffffffffffffffffffffffffffff1681526020810191909152604001600020549190612506565b6121fa565b5060015b9392505050565b6101035481565b60ff80541690565b610c756121f6565b60655473ffffffffffffffffffffffffffffffffffffffff908116911614610cfe57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60008111610d57576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526027815260200180613bac6027913960400191505060405180910390fd5b61010255565b610d6d610d686121f6565b61168d565b610dc2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180613b5b6030913960400191505060405180910390fd5b61010054610dd090826125b7565b6101005573ffffffffffffffffffffffffffffffffffffffff821660009081526101066020526040902060020154610e0890826125b7565b73ffffffffffffffffffffffffffffffffffffffff83166000818152610106602090815260408083206002019490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6101015473ffffffffffffffffffffffffffffffffffffffff1681565b73ffffffffffffffffffffffffffffffffffffffff811660009081526101066020526040812060018101546002820154839283929091610ecd8761262b565b935093509350509193909250565b73ffffffffffffffffffffffffffffffffffffffff82166000908152610106602052604081208054829182918291829182919088908110610f1857fe5b90600052602060002090600402019050610f31816126a9565b50815461010354610102549294509091610f4c9082906125b7565b83600301549550955095509550509295509295909350565b73ffffffffffffffffffffffffffffffffffffffff811660009081526101066020526040812060028101546001820154610c57916125b7565b610fa56121f6565b60655473ffffffffffffffffffffffffffffffffffffffff90811691161461102e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60655460405160009173ffffffffffffffffffffffffffffffffffffffff16907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3606580547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b6101025481565b73ffffffffffffffffffffffffffffffffffffffff81166000908152610106602052604081206002810154600182015483916110e091906125b7565b9050600061110761010854611101610107548561274c90919063ffffffff16565b906127bf565b95945050505050565b6101075481565b611122610d686121f6565b611177576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180613b5b6030913960400191505060405180910390fd5b600081116111e657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f496e636f727265637420616d6f756e7400000000000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff821661126857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f5a65726f20616464726573730000000000000000000000000000000000000000604482015290519081900360640190fd5b610103544211156112da57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f56657374696e6720686173207374617274656400000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8216600090815261010660205260409020600181015482111561137357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f496e73756666696369656e742076416b726f0000000000000000000000000000604482015290519081900360640190fd5b8054151580611386575080546003820154105b6113f157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f4e6f7468696e6720746f206275726e0000000000000000000000000000000000604482015290519081900360640190fd5b610100546113ff9083612801565b6101005560018101546114129083612801565b6001820155600381015481546000918391811061142b57fe5b600091825260209091206004909102015490506114488184612801565b8260000183600301548154811061145b57fe5b906000526020600020906004020160000181905550600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a350505050565b60655473ffffffffffffffffffffffffffffffffffffffff1690565b60fe8054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156109d15780601f106109a6576101008083540402835291602001916109d1565b611582610d686121f6565b6115d7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180613b5b6030913960400191505060405180910390fd5b6115e081612843565b50565b6115f36115ee6121f6565b612892565b565b6000806116006121f6565b905061160b816128e1565b611613611b99565b91505090565b6000611626610b056121f6565b61167b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180613a096030913960400191505060405180910390fd5b6109f76116866121f6565b8484612342565b60006109fb609783612913565b6116a26121f6565b60655473ffffffffffffffffffffffffffffffffffffffff90811691161461172b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6000811161179a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f496e636f72726563742076616c75650000000000000000000000000000000000604482015290519081900360640190fd5b6101079190915561010855565b6115f36117b26121f6565b6129ae565b6117c2610b056121f6565b611817576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180613a096030913960400191505060405180910390fd5b6115e0816129fd565b73ffffffffffffffffffffffffffffffffffffffff8116600090815261010660205260409020600381015490545b915091565b61185b6121f6565b60655473ffffffffffffffffffffffffffffffffffffffff9081169116146118e457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b61010455565b600054610100900460ff16806119035750611903612a4c565b80611911575060005460ff16155b611966576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180613c43602e913960400191505060405180910390fd5b600054610100900460ff161580156119cc57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff909116610100171660011790555b6119d4612a52565b6119e46119df6121f6565b612b75565b6119f46119ef6121f6565b612ca8565b60408051808201909152600b8082527f56657374656420414b524f0000000000000000000000000000000000000000006020909201918252611a389160fd91613975565b506040805180820190915260058082527f76414b524f0000000000000000000000000000000000000000000000000000006020909201918252611a7d9160fe91613975565b5060ff80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166012179055610101805473ffffffffffffffffffffffffffffffffffffffff85167fffffffffffffffffffffffff000000000000000000000000000000000000000090911617905581611b42576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526027815260200180613bac6027913960400191505060405180910390fd5b61010282905563608c9a00610103556228de80610104556001610107819055610108558015611b9457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1690555b505050565b600080611ba46121f6565b9050611baf81611e5d565b15611c05576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526035815260200180613ca56035913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000908152610106602052604090206002015480611c3f576000925050506109d9565b6000611c5e61010854611101610107548561274c90919063ffffffff16565b61010154604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051929350839273ffffffffffffffffffffffffffffffffffffffff909216916370a0823191602480820192602092909190829003018186803b158015611cd557600080fd5b505afa158015611ce9573d6000803e3d6000fd5b505050506040513d6020811015611cff57600080fd5b50511015611d6e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f4e6f7420656e6f75676820414b524f0000000000000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff83166000908152610106602052604081206002015561010054611da69083612801565b6101005561010154611dcf9073ffffffffffffffffffffffffffffffffffffffff168483612da8565b60408051838152905160009173ffffffffffffffffffffffffffffffffffffffff8616917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35091505090565b73ffffffffffffffffffffffffffffffffffffffff91821660009081526101056020908152604080832093909416825291909152205490565b60006109fb60ca83612913565b73ffffffffffffffffffffffffffffffffffffffff811660009081526101066020526040812054611efc57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f566573746564416b726f3a206e6f7468696e6720746f20756e6c6f636b000000604482015290519081900360640190fd5b611f05826128e1565b5073ffffffffffffffffffffffffffffffffffffffff166000908152610106602052604090206002015490565b611f3a6121f6565b60655473ffffffffffffffffffffffffffffffffffffffff908116911614611fc357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff811661202f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180613a626026913960400191505060405180910390fd5b60655460405173ffffffffffffffffffffffffffffffffffffffff8084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3606580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6101045481565b6120cf610d686121f6565b612124576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180613b5b6030913960400191505060405180910390fd5b6000811161219357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f496e636f727265637420616d6f756e7400000000000000000000000000000000604482015290519081900360640190fd5b6121c061219e6121f6565b6101015473ffffffffffffffffffffffffffffffffffffffff16903084612e35565b6040805182815290517f553d28c3c527fdb6b88ada7783469dbb0211d13d4ae0db85df4174cd0a381ae09181900360200190a150565b3390565b73ffffffffffffffffffffffffffffffffffffffff8316612266576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180613a396029913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166122d2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526027815260200180613b006027913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff80841660008181526101056020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b73ffffffffffffffffffffffffffffffffffffffff83166123ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180613ad6602a913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821661241a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180613a886028913960400191505060405180910390fd5b61246881604051806060016040528060348152602001613b276034913973ffffffffffffffffffffffffffffffffffffffff8616600090815261010660205260409020600201549190612506565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610106602052604090206002015561249c8282612ed0565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b600081848411156125af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561257457818101518382015260200161255c565b50505050905090810190601f1680156125a15780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600082820183811015610c5757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116600090815261010660205260408120600381015482905b82548110156126a157600061268984600001838154811061267657fe5b90600052602060002090600402016126a9565b50905061269683826125b7565b925050600101612659565b509392505050565b6000806126c561010454610103546125b790919063ffffffff16565b4210156126d75750600090508061184e565b61010254610103546126e8916125b7565b421061270957600383015483546126fe91612801565b60019150915061184e565b6000612741846003015461273b61010254611101612733610103544261280190919063ffffffff16565b89549061274c565b90612801565b946000945092505050565b60008261275b575060006109fb565b8282028284828161276857fe5b0414610c57576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180613bd36021913960400191505060405180910390fd5b6000610c5783836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061303f565b6000610c5783836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612506565b61284e6097826130be565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f690600090a250565b61289d609782613184565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb6669290600090a250565b73ffffffffffffffffffffffffffffffffffffffff8116600090815261010660205260409020546115e0908290613230565b600073ffffffffffffffffffffffffffffffffffffffff8216612981576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180613c216022913960400191505060405180910390fd5b5073ffffffffffffffffffffffffffffffffffffffff166000908152602091909152604090205460ff1690565b6129b960ca82613184565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f384859c5ef5fafac31e8bc92ce7fb48b1f2c74c4dd5e212eb84ec202fa5d9fad90600090a250565b612a0860ca826130be565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fd65eca5d561d3a4568c87b9b13ced4ab52a69edadfdfdb22d76bc595f36d7d8790600090a250565b303b1590565b600054610100900460ff1680612a6b5750612a6b612a4c565b80612a79575060005460ff16155b612ace576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180613c43602e913960400191505060405180910390fd5b600054610100900460ff16158015612b3457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff909116610100171660011790555b612b3c6133a3565b612b446134b5565b80156115e057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905550565b600054610100900460ff1680612b8e5750612b8e612a4c565b80612b9c575060005460ff16155b612bf1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180613c43602e913960400191505060405180910390fd5b600054610100900460ff16158015612c5757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff909116610100171660011790555b612c5f6133a3565b612c688261168d565b612c7557612c7582612843565b8015612ca457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1690555b5050565b600054610100900460ff1680612cc15750612cc1612a4c565b80612ccf575060005460ff16155b612d24576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180613c43602e913960400191505060405180910390fd5b600054610100900460ff16158015612d8a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff909116610100171660011790555b612d926133a3565b612d9b82611e5d565b612c7557612c75826129fd565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052611b94908490613645565b6040805173ffffffffffffffffffffffffffffffffffffffff80861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052612eca908590613645565b50505050565b73ffffffffffffffffffffffffffffffffffffffff821660009081526101066020526040902080541580612f08575080546003820154145b15612f8257604080516080810182528381526101035460208201819052610102548493830191612f37916125b7565b81526000602091820181905283546001818101865594825290829020835160049092020190815590820151928101929092556040810151600283015560600151600390910155612fda565b600081600001826003015481548110612f9757fe5b60009182526020909120600490910201549050612fb481846125b7565b82600001836003015481548110612fc757fe5b6000918252602090912060049091020155505b6001810154612fe990836125b7565b600182015560408051838152905173ffffffffffffffffffffffffffffffffffffffff8516917f9f1ec8c880f76798e7b793325d625e9b60e4082a553c98f42b6cda368dd60008919081900360200190a2505050565b600081836130a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181815283516024840152835190928392604490910191908501908083836000831561257457818101518382015260200161255c565b5060008385816130b457fe5b0495945050505050565b6130c88282612913565b1561313457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f526f6c65733a206163636f756e7420616c72656164792068617320726f6c6500604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff1660009081526020919091526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b61318e8282612913565b6131e3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180613b8b6021913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff1660009081526020919091526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b73ffffffffffffffffffffffffffffffffffffffff8216600090815261010660205260408120600381015490919081905b848110156133135760008061327e86600001848154811061267657fe5b909250905081156132ec576132bc8287600001858154811061329c57fe5b9060005260206000209060040201600301546125b790919063ffffffff16565b8660000184815481106132cb57fe5b60009182526020909120600360049092020101556132e984836125b7565b93505b801580156132f8575084155b156133095760038601839055600194505b5050600101613261565b508161332157825460038401555b801561339c5760018301546133369082612801565b6001840155600283015461334a90826125b7565b600284015560408051828152905173ffffffffffffffffffffffffffffffffffffffff8716917f0f0bc5b519ddefdd8e5f9e6423433aa2b869738de2ae34d58ebc796fc749fa0d919081900360200190a25b5050505050565b600054610100900460ff16806133bc57506133bc612a4c565b806133ca575060005460ff16155b61341f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180613c43602e913960400191505060405180910390fd5b600054610100900460ff16158015612b4457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff9091166101001716600117905580156115e057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905550565b600054610100900460ff16806134ce57506134ce612a4c565b806134dc575060005460ff16155b613531576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180613c43602e913960400191505060405180910390fd5b600054610100900460ff1615801561359757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff909116610100171660011790555b60006135a16121f6565b606580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35080156115e057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905550565b60606136a7826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661371d9092919063ffffffff16565b805190915015611b94578080602001905160208110156136c657600080fd5b5051611b94576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180613cda602a913960400191505060405180910390fd5b606061372c8484600085613734565b949350505050565b60608247101561378f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180613ab06026913960400191505060405180910390fd5b613798856138ef565b61380357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b6020831061386d57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613830565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146138cf576040519150601f19603f3d011682016040523d82523d6000602084013e6138d4565b606091505b50915091506138e48282866138f5565b979650505050505050565b3b151590565b60608315613904575081610c57565b8251156139145782518084602001fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181815284516024840152845185939192839260440191908501908083836000831561257457818101518382015260200161255c565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106139b657805160ff19168380011785556139e3565b828001600101855582156139e3579182015b828111156139e35782518255916020019190600101906139c8565b506139ef9291506139f3565b5090565b5b808211156139ef57600081556001016139f456fe53656e646572526f6c653a2063616c6c657220646f6573206e6f742068617665207468652053656e64657220726f6c65566573746564416b726f3a20617070726f76652066726f6d20746865207a65726f20616464726573734f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373566573746564416b726f3a207472616e7366657220746f20746865207a65726f2061646472657373416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c566573746564416b726f3a207472616e736665722066726f6d20746865207a65726f2061646472657373566573746564416b726f3a20617070726f766520746f20746865207a65726f2061646472657373566573746564416b726f3a207472616e7366657220616d6f756e74206578636565647320756e6c6f636b65642062616c616e63654d696e746572526f6c653a2063616c6c657220646f6573206e6f74206861766520746865204d696e74657220726f6c65526f6c65733a206163636f756e7420646f6573206e6f74206861766520726f6c65566573746564416b726f3a2076657374696e67506572696f642073686f756c64206265203e2030536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77566573746564416b726f3a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e6365526f6c65733a206163636f756e7420697320746865207a65726f2061646472657373436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564566573746564416b726f3a2073656e6465722073686f756c64206861766520566573746564416b726f53656e64657220726f6c65566573746564416b726f3a20566573746564416b726f53656e646572206973206e6f7420616c6c6f77656420746f2072656465656d5361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564566573746564416b726f3a2076657374696e6753746172742073686f756c64206265203e2030a2646970667358221220e816e816f1b75d82f423f81835efbad5d8189b3fd1fa97f102859da8ba51f4eb64736f6c634300060c0033

Deployed Bytecode Sourcemap

28666:14302:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31179:83;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30303:40;;;:::i;:::-;;;;;;;;;;;;;;;;31606:161;;;;;;;;;;;;;;;;-1:-1:-1;31606:161:0;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;32942:191;;;;;;;;;;;;;;;;-1:-1:-1;32942:191:0;;:::i;:::-;;29750:35;;;:::i;31775:633::-;;;;;;;;;;;;;;;;-1:-1:-1;31775:633:0;;;;;;;;;;;;;;;;;;:::i;29903:27::-;;;:::i;31365:83::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;32602:197;;;;;;;;;;;;;;;;-1:-1:-1;32602:197:0;;:::i;34099:266::-;;;;;;;;;;;;;;;;-1:-1:-1;34099:266:0;;;;;;;;;:::i;29792:29::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;37948:332;;;;;;;;;;;;;;;;-1:-1:-1;37948:332:0;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;38522:492;;;;;;;;;;;;;;;;-1:-1:-1;38522:492:0;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;37768:172;;;;;;;;;;;;;;;;-1:-1:-1;37768:172:0;;;;:::i;26389:148::-;;;:::i;29828:28::-;;;:::i;37457:303::-;;;;;;;;;;;;;;;;-1:-1:-1;37457:303:0;;;;:::i;30212:38::-;;;:::i;34538:767::-;;;;;;;;;;;;;;;;-1:-1:-1;34538:767:0;;;;;;;;;:::i;25747:79::-;;;:::i;31270:87::-;;;:::i;24000:92::-;;;;;;;;;;;;;;;;-1:-1:-1;24000:92:0;;;;:::i;24100:79::-;;;:::i;36236:188::-;;;:::i;32416:178::-;;;;;;;;;;;;;;;;-1:-1:-1;32416:178:0;;;;;;;;;:::i;23883:109::-;;;;;;;;;;;;;;;;-1:-1:-1;23883:109:0;;;;:::i;33808:283::-;;;;;;;;;;;;;;;;-1:-1:-1;33808:283:0;;;;;;;:::i;27810:79::-;;;:::i;27710:92::-;;;;;;;;;;;;;;;;-1:-1:-1;27710:92:0;;;;:::i;38288:226::-;;;;;;;;;;;;;;;;-1:-1:-1;38288:226:0;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;33298:112;;;;;;;;;;;;;;;;-1:-1:-1;33298:112:0;;:::i;31083:88::-;;;;;;;;;;;;;;;;-1:-1:-1;31083:88:0;;;;:::i;30352:683::-;;;;;;;;;;;;;;;;-1:-1:-1;30352:683:0;;;;;;;;;:::i;36569:713::-;;;:::i;31456:142::-;;;;;;;;;;;;;;;;-1:-1:-1;31456:142:0;;;;;;;;;;;:::i;27593:109::-;;;;;;;;;;;;;;;;-1:-1:-1;27593:109:0;;;;:::i;35880:241::-;;;;;;;;;;;;;;;;-1:-1:-1;35880:241:0;;;;:::i;26692:244::-;;;;;;;;;;;;;;;;-1:-1:-1;26692:244:0;;;;:::i;29995:27::-;;;:::i;35448:247::-;;;;;;;;;;;;;;;;-1:-1:-1;35448:247:0;;:::i;31179:83::-;31249:5;31242:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31216:13;;31242:12;;31249:5;;31242:12;;31249:5;31242:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31179:83;;:::o;30303:40::-;;;;:::o;31606:161::-;31681:4;31698:39;31707:12;:10;:12::i;:::-;31721:7;31730:6;31698:8;:39::i;:::-;-1:-1:-1;31755:4:0;31606:161;;;;;:::o;32942:191::-;25969:12;:10;:12::i;:::-;25959:6;;:22;:6;;;:22;;;25951:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33042:1:::1;33026:13;:17;33018:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33097:12;:28:::0;32942:191::o;29750:35::-;;;;:::o;31775:633::-;31918:4;27490:22;27499:12;:10;:12::i;:::-;27490:8;:22::i;:::-;27482:83;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32120:16:::1;32129:6;32120:8;:16::i;:::-;32112:81;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32206:36;32216:6;32224:9;32235:6;32206:9;:36::i;:::-;32253:125;32262:6;32270:12;:10;:12::i;:::-;32284:93;32321:6;32284:93;;;;;;;;;;;;;;;;;:18;::::0;::::1;;::::0;;;:10:::1;:18;::::0;;;;;32303:12:::1;:10;:12::i;:::-;32284:32;;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;32284:32:0;;;:93;:36:::1;:93::i;:::-;32253:8;:125::i;:::-;-1:-1:-1::0;32396:4:0::1;27576:1;31775:633:::0;;;;;:::o;29903:27::-;;;;:::o;31365:83::-;31431:9;;;;31365:83;:::o;32602:197::-;25969:12;:10;:12::i;:::-;25959:6;;:22;:6;;;:22;;;25951:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32705:1:::1;32688:14;:18;32680:70;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32761:13;:30:::0;32602:197::o;34099:266::-;23780:22;23789:12;:10;:12::i;:::-;23780:8;:22::i;:::-;23772:83;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34193:11:::1;::::0;:23:::1;::::0;34209:6;34193:15:::1;:23::i;:::-;34179:11;:37:::0;34259:20:::1;::::0;::::1;;::::0;;;:7:::1;:20;::::0;;;;:29:::1;;::::0;:41:::1;::::0;34293:6;34259:33:::1;:41::i;:::-;34227:20;::::0;::::1;;::::0;;;:7:::1;:20;::::0;;;;;;;:29:::1;;:73:::0;;;;34316:41;;;;;;;34227:20;;;;34316:41:::1;::::0;;;;;;;;::::1;34099:266:::0;;:::o;29792:29::-;;;;;;:::o;37948:332::-;38176:16;;;38050:14;38176:16;;;:7;:16;;;;;38211:8;;;;38221:10;;;;38050:14;;;;38176:16;;38233:38;38184:7;38233:29;:38::i;:::-;38203:69;;;;;;;37948:332;;;;;:::o;38522:492::-;38818:16;;;38635:14;38818:16;;;:7;:16;;;;;:31;;38635:14;;;;;;;;;;38818:16;38843:5;;38818:31;;;;;;;;;;;;;;;;38793:56;;38876:31;38904:2;38876:27;:31::i;:::-;-1:-1:-1;38926:9:0;;38937:12;;38968:13;;38860:47;;-1:-1:-1;38926:9:0;;38951:31;;38937:12;;38951:16;:31::i;:::-;38984:2;:10;;;38918:88;;;;;;;;;38522:492;;;;;;;;:::o;37768:172::-;37874:16;;;37834:7;37874:16;;;:7;:16;;;;;37921:10;;;;37908:8;;;;:24;;:12;:24::i;26389:148::-;25969:12;:10;:12::i;:::-;25959:6;;:22;:6;;;:22;;;25951:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26480:6:::1;::::0;26459:40:::1;::::0;26496:1:::1;::::0;26459:40:::1;26480:6;::::0;26459:40:::1;::::0;26496:1;;26459:40:::1;26510:6;:19:::0;;;::::1;::::0;;26389:148::o;29828:28::-;;;;:::o;37457:303::-;37558:16;;;37518:7;37558:16;;;:7;:16;;;;;37615:10;;;;37602:8;;;;37518:7;;37602:24;;:8;:12;:24::i;:::-;37585:41;;37637:18;37658:66;37698:25;;37658:35;37669:23;;37658:6;:10;;:35;;;;:::i;:::-;:39;;:66::i;:::-;37637:87;37457:303;-1:-1:-1;;;;;37457:303:0:o;30212:38::-;;;;:::o;34538:767::-;23780:22;23789:12;:10;:12::i;23780:22::-;23772:83;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34634:1:::1;34625:6;:10;34617:39;;;::::0;;::::1;::::0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;34675:20;::::0;::::1;34667:45;;;::::0;;::::1;::::0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;34752:12;;34733:15;:31;;34725:63;;;::::0;;::::1;::::0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;34821:15;::::0;::::1;34801:17;34821:15:::0;;;:7:::1;:15;::::0;;;;34857:8:::1;::::0;::::1;::::0;:18;-1:-1:-1;34857:18:0::1;34849:49;;;::::0;;::::1;::::0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;34917:16:::0;;:20;;;:64:::1;;-1:-1:-1::0;34965:16:0;;34941:21:::1;::::0;::::1;::::0;:40:::1;34917:64;34909:92;;;::::0;;::::1;::::0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;35028:11;::::0;:23:::1;::::0;35044:6;35028:15:::1;:23::i;:::-;35014:11;:37:::0;35073:8:::1;::::0;::::1;::::0;:20:::1;::::0;35086:6;35073:12:::1;:20::i;:::-;35062:8;::::0;::::1;:31:::0;35138:21:::1;::::0;::::1;::::0;35128:32;;35106:19:::1;::::0;35062:1;;35128:32;::::1;;;;;;::::0;;;::::1;::::0;;;::::1;::::0;;::::1;;:39:::0;;-1:-1:-1;35220:23:0::1;35128:39:::0;35236:6;35220:15:::1;:23::i;:::-;35178:1;:9;;35188:1;:21;;;35178:32;;;;;;;;;;;;;;;;;;:39;;:65;;;;35286:1;35261:36;;35270:6;35261:36;;;35290:6;35261:36;;;;;;;;;;;;;;;;;;23866:1;;34538:767:::0;;:::o;25747:79::-;25812:6;;;;25747:79;:::o;31270:87::-;31342:7;31335:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31309:13;;31335:14;;31342:7;;31335:14;;31342:7;31335:14;;;;;;;;;;;;;;;;;;;;;;;;24000:92;23780:22;23789:12;:10;:12::i;23780:22::-;23772:83;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24065:19:::1;24076:7;24065:10;:19::i;:::-;24000:92:::0;:::o;24100:79::-;24144:27;24158:12;:10;:12::i;:::-;24144:13;:27::i;:::-;24100:79::o;36236:188::-;36282:7;36302:19;36324:12;:10;:12::i;:::-;36302:34;;36347:32;36367:11;36347:19;:32::i;:::-;36397:19;:17;:19::i;:::-;36390:26;;;36236:188;:::o;32416:178::-;32505:4;27490:22;27499:12;:10;:12::i;27490:22::-;27482:83;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32522:42:::1;32532:12;:10;:12::i;:::-;32546:9;32557:6;32522:9;:42::i;23883:109::-:0;23939:4;23963:21;:8;23976:7;23963:12;:21::i;33808:283::-;25969:12;:10;:12::i;:::-;25959:6;;:22;:6;;;:22;;;25951:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33948:1:::1;33925:20;:24;33917:52;;;::::0;;::::1;::::0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;33980:23;:44:::0;;;;34035:25:::1;:48:::0;33808:283::o;27810:79::-;27854:27;27868:12;:10;:12::i;:::-;27854:13;:27::i;27710:92::-;27490:22;27499:12;:10;:12::i;27490:22::-;27482:83;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27775:19:::1;27786:7;27775:10;:19::i;38288:226::-:0;38431:16;;;38349:27;38431:16;;;:7;:16;;;;;38466:21;;;;38489:16;;38288:226;;;;:::o;33298:112::-;25969:12;:10;:12::i;:::-;25959:6;;:22;:6;;;:22;;;25951:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33374:12:::1;:28:::0;33298:112::o;30352:683::-;10873:12;;;;;;;;:31;;;10889:15;:13;:15::i;:::-;10873:47;;;-1:-1:-1;10909:11:0;;;;10908:12;10873:47;10865:106;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10984:19;11007:12;;;;;;11006:13;11030:99;;;;11065:12;:19;;11099:18;11065:19;;;;;;11099:18;11080:4;11099:18;;;11030:99;30441:16:::1;:14;:16::i;:::-;30468:35;30490:12;:10;:12::i;:::-;30468:21;:35::i;:::-;30514:45;30546:12;:10;:12::i;:::-;30514:31;:45::i;:::-;30572:21;::::0;;;;::::1;::::0;;;::::1;::::0;;;::::1;;::::0;;::::1;::::0;;;::::1;::::0;:5:::1;::::0;:21:::1;:::i;:::-;-1:-1:-1::0;30604:17:0::1;::::0;;;;::::1;::::0;;;::::1;::::0;;;::::1;;::::0;;::::1;::::0;;;::::1;::::0;:7:::1;::::0;:17:::1;:::i;:::-;-1:-1:-1::0;30632:9:0::1;:14:::0;;;::::1;30644:2;30632:14;::::0;;30659:4:::1;:31:::0;;::::1;::::0;::::1;::::0;;;::::1;;::::0;;30709:18;30701:70:::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30782:13;:30:::0;;;30838:10:::1;30823:12;:25:::0;30904:17:::1;30889:12;:32:::0;30986:1:::1;30960:23;:27:::0;;;30998:25:::1;:29:::0;11155:67;;;;11205:5;11190:20;;;;;;11155:67;30352:683;;;:::o;36569:713::-;36614:7;36634:19;36656:12;:10;:12::i;:::-;36634:34;;36688:21;36697:11;36688:8;:21::i;:::-;36687:22;36679:88;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36795:20;;;36778:14;36795:20;;;:7;:20;;;;;:29;;;36839:11;36835:25;;36859:1;36852:8;;;;;;36835:25;36873:18;36894:66;36934:25;;36894:35;36905:23;;36894:6;:10;;:35;;;;:::i;:66::-;36979:4;;:29;;;;;;37002:4;36979:29;;;;;;36873:87;;-1:-1:-1;36873:87:0;;36979:4;;;;;:14;;:29;;;;;;;;;;;;;;;:4;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;36979:29:0;:43;;36971:71;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;37055:20;;;37087:1;37055:20;;;:7;:20;;;;;:29;;:33;37113:11;;:23;;37129:6;37113:15;:23::i;:::-;37099:11;:37;37149:4;;:42;;:4;;37167:11;37180:10;37149:17;:42::i;:::-;37209:41;;;;;;;;37239:1;;37209:41;;;;;;;;;;;;;-1:-1:-1;37268:6:0;-1:-1:-1;;36569:713:0;:::o;31456:142::-;31564:17;;;;31537:7;31564:17;;;:10;:17;;;;;;;;:26;;;;;;;;;;;;;31456:142::o;27593:109::-;27649:4;27673:21;:8;27686:7;27673:12;:21::i;35880:241::-;35965:15;;;35937:7;35965:15;;;:7;:15;;;;;:30;35957:76;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36044:27;36064:6;36044:19;:27::i;:::-;-1:-1:-1;36089:15:0;;;;;;:7;:15;;;;;:24;;;;35880:241::o;26692:244::-;25969:12;:10;:12::i;:::-;25959:6;;:22;:6;;;:22;;;25951:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26781:22:::1;::::0;::::1;26773:73;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26883:6;::::0;26862:38:::1;::::0;::::1;::::0;;::::1;::::0;26883:6:::1;::::0;26862:38:::1;::::0;26883:6:::1;::::0;26862:38:::1;26911:6;:17:::0;;;::::1;;::::0;;;::::1;::::0;;;::::1;::::0;;26692:244::o;29995:27::-;;;;:::o;35448:247::-;23780:22;23789:12;:10;:12::i;23780:22::-;23772:83;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;35538:1:::1;35528:7;:11;35520:40;;;::::0;;::::1;::::0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;35573:78;35614:12;:10;:12::i;:::-;35591:4;::::0;::::1;;::::0;35636::::1;35643:7:::0;35573:40:::1;:78::i;:::-;35669:18;::::0;;;;;;;::::1;::::0;;;;::::1;::::0;;::::1;35448:247:::0;:::o;19135:106::-;19223:10;19135:106;:::o;39022:381::-;39150:19;;;39142:73;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39234:21;;;39226:73;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39312:17;;;;;;;;:10;:17;;;;;;;;:26;;;;;;;;;;;;;:35;;;39363:32;;;;;;;;;;;;;;;;;39022:381;;;:::o;39411:528::-;39543:20;;;39535:75;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39629:23;;;39621:76;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39737:92;39766:6;39737:92;;;;;;;;;;;;;;;;;:15;;;;;;;:7;:15;;;;;:24;;;;:92;:28;:92::i;:::-;39710:15;;;;;;;:7;:15;;;;;:24;;:119;39840:38;39860:9;39871:6;39840:19;:38::i;:::-;39913:9;39896:35;;39905:6;39896:35;;;39924:6;39896:35;;;;;;;;;;;;;;;;;;39411:528;;;:::o;14805:192::-;14891:7;14927:12;14919:6;;;;14911:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;14963:5:0;;;14805:192::o;13902:181::-;13960:7;13992:5;;;14016:6;;;;14008:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;41863:412;41981:15;;;41941:7;41981:15;;;:7;:15;;;;;42051:21;;;;41941:7;;42034:208;42078:16;;42074:20;;42034:208;;;42117:17;42140:41;42168:1;:9;;42178:1;42168:12;;;;;;;;;;;;;;;;;;42140:27;:41::i;:::-;-1:-1:-1;42116:65:0;-1:-1:-1;42207:23:0;:8;42116:65;42207:12;:23::i;:::-;42196:34;-1:-1:-1;;42096:3:0;;42034:208;;;-1:-1:-1;42259:8:0;41863:412;-1:-1:-1;;;41863:412:0:o;42459:506::-;42543:7;42552:4;42579:30;42596:12;;42579;;:16;;:30;;;;:::i;:::-;42573:3;:36;42569:128;;;-1:-1:-1;42634:1:0;;-1:-1:-1;42634:1:0;42626:17;;42569:128;42735:13;;42718:12;;:31;;:16;:31::i;:::-;42711:3;:38;42707:111;;42788:10;;;;42774:9;;:25;;:13;:25::i;:::-;42801:4;42766:40;;;;;;42707:111;42828:17;42848:73;42910:2;:10;;;42849:55;42890:13;;42849:36;42863:21;42871:12;;42863:3;:7;;:21;;;;:::i;:::-;42849:9;;;:13;:36::i;:55::-;42848:61;;:73::i;:::-;42828:93;42951:5;;-1:-1:-1;42459:506:0;-1:-1:-1;;;42459:506:0:o;15256:471::-;15314:7;15559:6;15555:47;;-1:-1:-1;15589:1:0;15582:8;;15555:47;15626:5;;;15630:1;15626;:5;:1;15650:5;;;;;:10;15642:56;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;16203:132;16261:7;16288:39;16292:1;16295;16288:39;;;;;;;;;;;;;;;;;:3;:39::i;14366:136::-;14424:7;14451:43;14455:1;14458;14451:43;;;;;;;;;;;;;;;;;:3;:43::i;24187:122::-;24244:21;:8;24257:7;24244:12;:21::i;:::-;24281:20;;;;;;;;;;;24187:122;:::o;24317:130::-;24377:24;:8;24393:7;24377:15;:24::i;:::-;24417:22;;;;;;;;;;;24317:130;:::o;40560:132::-;40653:15;;;;;;;:7;:15;;;;;:30;40625:59;;40645:6;;40625:19;:59::i;12809:203::-;12881:4;12906:21;;;12898:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;12984:20:0;;:11;:20;;;;;;;;;;;;;;;12809:203::o;28027:130::-;28087:24;:8;28103:7;28087:15;:24::i;:::-;28127:22;;;;;;;;;;;28027:130;:::o;27897:122::-;27954:21;:8;27967:7;27954:12;:21::i;:::-;27991:20;;;;;;;;;;;27897:122;:::o;11322:568::-;11763:4;11830:17;11875:7;11322:568;:::o;25333:129::-;10873:12;;;;;;;;:31;;;10889:15;:13;:15::i;:::-;10873:47;;;-1:-1:-1;10909:11:0;;;;10908:12;10873:47;10865:106;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10984:19;11007:12;;;;;;11006:13;11030:99;;;;11065:12;:19;;11099:18;11065:19;;;;;;11099:18;11080:4;11099:18;;;11030:99;25391:26:::1;:24;:26::i;:::-;25428;:24;:26::i;:::-;11159:14:::0;11155:67;;;11205:5;11190:20;;;;;;25333:129;:::o;23545:186::-;10873:12;;;;;;;;:31;;;10889:15;:13;:15::i;:::-;10873:47;;;-1:-1:-1;10909:11:0;;;;10908:12;10873:47;10865:106;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10984:19;11007:12;;;;;;11006:13;11030:99;;;;11065:12;:19;;11099:18;11065:19;;;;;;11099:18;11080:4;11099:18;;;11030:99;23619:26:::1;:24;:26::i;:::-;23661:16;23670:6;23661:8;:16::i;:::-;23656:68;;23694:18;23705:6;23694:10;:18::i;:::-;11159:14:::0;11155:67;;;11205:5;11190:20;;;;;;11155:67;23545:186;;:::o;27255:::-;10873:12;;;;;;;;:31;;;10889:15;:13;:15::i;:::-;10873:47;;;-1:-1:-1;10909:11:0;;;;10908:12;10873:47;10865:106;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10984:19;11007:12;;;;;;11006:13;11030:99;;;;11065:12;:19;;11099:18;11065:19;;;;;;11099:18;11080:4;11099:18;;;11030:99;27329:26:::1;:24;:26::i;:::-;27371:16;27380:6;27371:8;:16::i;:::-;27366:68;;27404:18;27415:6;27404:10;:18::i;20146:188::-:0;20267:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20290:23;20267:58;;;20240:86;;20260:5;;20240:19;:86::i;20342:216::-;20481:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20504:27;20481:68;;;20454:96;;20474:5;;20454:19;:96::i;:::-;20342:216;;;;:::o;39947:605::-;40048:15;;;40028:17;40048:15;;;:7;:15;;;;;40080:16;;:21;;:66;;-1:-1:-1;40130:16:0;;40105:21;;;;:41;40080:66;40076:389;;;40178:100;;;;;;;;;;;40214:12;;40178:100;;;;;;40250:13;;40163:1;;40178:100;;;40233:31;;:16;:31::i;:::-;40178:100;;40275:1;40178:100;;;;;;;40163:116;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40076:389;;;40312:19;40334:1;:9;;40344:1;:21;;;40334:32;;;;;;;;;;;;;;;;;;;;;:39;;-1:-1:-1;40430:23:0;40334:39;40446:6;40430:15;:23::i;:::-;40388:1;:9;;40398:1;:21;;;40388:32;;;;;;;;;;;;;;;;;;;;;:65;-1:-1:-1;40076:389:0;40486:8;;;;:20;;40499:6;40486:12;:20::i;:::-;40475:8;;;:31;40522:22;;;;;;;;;;;;;;;;;;;;;;39947:605;;;:::o;16831:278::-;16917:7;16952:12;16945:5;16937:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;16976:9;16992:1;16988;:5;;;;;;;16831:278;-1:-1:-1;;;;;16831:278:0:o;12273:178::-;12351:18;12355:4;12361:7;12351:3;:18::i;:::-;12350:19;12342:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12416:20;;:11;:20;;;;;;;;;;;:27;;;;12439:4;12416:27;;;12273:178::o;12531:183::-;12611:18;12615:4;12621:7;12611:3;:18::i;:::-;12603:64;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12678:20;;12701:5;12678:20;;;;;;;;;;;:28;;;;;;12531:183::o;40700:1002::-;40804:15;;;40784:17;40804:15;;;:7;:15;;;;;40909:21;;;;40804:15;;40784:17;;;40892:514;40936:9;40932:1;:13;40892:514;;;40968:17;40987:19;41010:41;41038:1;:9;;41048:1;41038:12;;;;;;;41010:41;40967:84;;-1:-1:-1;40967:84:0;-1:-1:-1;41070:13:0;;41066:165;;41127:35;41152:9;41127:1;:9;;41137:1;41127:12;;;;;;;;;;;;;;;;;;:20;;;:24;;:35;;;;:::i;:::-;41104:1;:9;;41114:1;41104:12;;;;;;;;;;;;;;;;:20;:12;;;;;:20;:58;41192:23;:8;41205:9;41192:12;:23::i;:::-;41181:34;;41066:165;41250:14;41249:15;:39;;;;;41269:19;41268:20;41249:39;41245:150;;;41309:21;;;:25;;;41375:4;;-1:-1:-1;41245:150:0;-1:-1:-1;;40947:3:0;;40892:514;;;;41421:19;41416:93;;41481:16;;41457:21;;;:40;41416:93;41523:12;;41519:176;;41563:8;;;;:22;;41576:8;41563:12;:22::i;:::-;41552:8;;;:33;41613:10;;;;:24;;41628:8;41613:14;:24::i;:::-;41600:10;;;:37;41657:26;;;;;;;;;;;;;;;;;;;;;;41519:176;40700:1002;;;;;:::o;19064:65::-;10873:12;;;;;;;;:31;;;10889:15;:13;:15::i;:::-;10873:47;;;-1:-1:-1;10909:11:0;;;;10908:12;10873:47;10865:106;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10984:19;11007:12;;;;;;11006:13;11030:99;;;;11065:12;:19;;11099:18;11065:19;;;;;;11099:18;11080:4;11099:18;;;11159:14;11155:67;;;11205:5;11190:20;;;;;;19064:65;:::o;25470:196::-;10873:12;;;;;;;;:31;;;10889:15;:13;:15::i;:::-;10873:47;;;-1:-1:-1;10909:11:0;;;;10908:12;10873:47;10865:106;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10984:19;11007:12;;;;;;11006:13;11030:99;;;;11065:12;:19;;11099:18;11065:19;;;;;;11099:18;11080:4;11099:18;;;11030:99;25538:17:::1;25558:12;:10;:12::i;:::-;25581:6;:18:::0;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;;25615:43:::1;::::0;25581:18;;-1:-1:-1;25581:18:0;-1:-1:-1;;25615:43:0::1;::::0;-1:-1:-1;;25615:43:0::1;11141:1;11159:14:::0;11155:67;;;11205:5;11190:20;;;;;;25470:196;:::o;22506:772::-;22941:23;22967:69;22995:4;22967:69;;;;;;;;;;;;;;;;;22975:5;22967:27;;;;:69;;;;;:::i;:::-;23051:17;;22941:95;;-1:-1:-1;23051:21:0;23047:224;;23193:10;23182:30;;;;;;;;;;;;;;;-1:-1:-1;23182:30:0;23174:85;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3713:195;3816:12;3848:52;3870:6;3878:4;3884:1;3887:12;3848:21;:52::i;:::-;3841:59;3713:195;-1:-1:-1;;;;3713:195:0:o;4765:530::-;4892:12;4950:5;4925:21;:30;;4917:81;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5017:18;5028:6;5017:10;:18::i;:::-;5009:60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5143:12;5157:23;5184:6;:11;;5204:5;5212:4;5184:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5142:75;;;;5235:52;5253:7;5262:10;5274:12;5235:17;:52::i;:::-;5228:59;4765:530;-1:-1:-1;;;;;;;4765:530:0:o;795:422::-;1162:20;1201:8;;;795:422::o;6301:742::-;6416:12;6445:7;6441:595;;;-1:-1:-1;6476:10:0;6469:17;;6441:595;6590:17;;:21;6586:439;;6853:10;6847:17;6914:15;6901:10;6897:2;6893:19;6886:44;6801:148;6989:20;;;;;;;;;;;;;;;;;;;;6996:12;;6989:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;

Swarm Source

ipfs://e816e816f1b75d82f423f81835efbad5d8189b3fd1fa97f102859da8ba51f4eb
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.