ETH Price: $2,972.02 (-1.60%)
Gas: 2 Gwei

Token

Genius (GENI)
 

Overview

Max Total Supply

103,967,784,072.393005175 GENI

Holders

1,910 (0.00%)

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 9 Decimals)

Balance
2,220,400 GENI

Value
$0.00
0x84448a56465af257c4481738b6861208ac5b8888
Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

Genius encapsulates human attention and intentions (ie. commitments and promises) to create a Store of Value utility token for traders and savers.

# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
Genius

Compiler Version
v0.8.4+commit.c7e474f2

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, None license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2022-12-31
*/

// SPDX-License-Identifier: UNLICENSED
// Genius is NOT LICENSED FOR COPYING.
// Genius (C) 2022. All Rights Reserved.
//
// Telegram: https://t.me/genicrypto
// Twitter: https://twitter.com/genicrypto
// White Paper: https://geni.to/smartcontract
//
// First DAPP: https://start.geni.app
// Community Website: https://thegeniustoken.com
// Development Telegram: https://t.me/genicryptodev
//
// Buy $GENI here:
// * Ethereum: https://geni.to/ethereum
// * Binance: https://geni.to/binance
// * Polygon: https://geni.to/polygon
// * Avalanche: https://geni.to/avalanche
//
// Third-Party Security Reviews:
// * Gleipnir: https://www.gleipnirsecurity.com/_files/ugd/a4dd88_02edf4a4aeef4e6d950db85175488ebb.pdf
// * CertiK: https://www.certik.com/projects/genius

// Sources flattened with hardhat v2.9.9 https://hardhat.org

// File @openzeppelin/contracts/token/ERC20/[email protected]

// License: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @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);

    /**
     * @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 `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, 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 `from` to `to` 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 from,
        address to,
        uint256 amount
    ) external returns (bool);
}


// File @openzeppelin/contracts/utils/[email protected]

// License: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)

pragma solidity ^0.8.0;

/**
 * @title Counters
 * @author Matt Condon (@shrugs)
 * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
 * of elements in a mapping, issuing ERC721 ids, or counting request ids.
 *
 * Include with `using Counters for Counters.Counter;`
 */
library Counters {
    struct Counter {
        // This variable should never be directly accessed by users of the library: interactions must be restricted to
        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
        // this feature: see https://github.com/ethereum/solidity/issues/4637
        uint256 _value; // default: 0
    }

    function current(Counter storage counter) internal view returns (uint256) {
        return counter._value;
    }

    function increment(Counter storage counter) internal {
        unchecked {
            counter._value += 1;
        }
    }

    function decrement(Counter storage counter) internal {
        uint256 value = counter._value;
        require(value > 0, "Counter: decrement overflow");
        unchecked {
            counter._value = value - 1;
        }
    }

    function reset(Counter storage counter) internal {
        counter._value = 0;
    }
}


// File @openzeppelin/contracts/security/[email protected]

// License: MIT
// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;

        _;

        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}


// File @openzeppelin/contracts/token/ERC20/extensions/[email protected]

// License: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}


// File @openzeppelin/contracts/utils/[email protected]

// License: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @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 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 Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

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


// File @openzeppelin/contracts/token/ERC20/[email protected]

// License: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.0;



/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20, IERC20Metadata {
    mapping(address => uint256) private _balances;

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * The default value of {decimals} is 18. To select a different value for
     * {decimals} you should overload it.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

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

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5.05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless this function is
     * overridden;
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual override returns (uint8) {
        return 18;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address to, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
     * `transferFrom`. This is semantically equivalent to an infinite approval.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * NOTE: Does not update the allowance if the current allowance
     * is the maximum `uint256`.
     *
     * Requirements:
     *
     * - `from` and `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `amount`.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public virtual override returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, amount);
        _transfer(from, to, amount);
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, allowance(owner, spender) + addedValue);
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        address owner = _msgSender();
        uint256 currentAllowance = allowance(owner, spender);
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        unchecked {
            _approve(owner, spender, currentAllowance - subtractedValue);
        }

        return true;
    }

    /**
     * @dev Moves `amount` of tokens from `sender` to `recipient`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     */
    function _transfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(from, to, amount);

        uint256 fromBalance = _balances[from];
        require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[from] = fromBalance - amount;
        }
        _balances[to] += amount;

        emit Transfer(from, to, amount);

        _afterTokenTransfer(from, to, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply += amount;
        _balances[account] += amount;
        emit Transfer(address(0), account, amount);

        _afterTokenTransfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
        }
        _totalSupply -= amount;

        emit Transfer(account, address(0), amount);

        _afterTokenTransfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

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

    /**
     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.
     *
     * Does not update the allowance amount in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Might emit an {Approval} event.
     */
    function _spendAllowance(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance != type(uint256).max) {
            require(currentAllowance >= amount, "ERC20: insufficient allowance");
            unchecked {
                _approve(owner, spender, currentAllowance - amount);
            }
        }
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}

    /**
     * @dev Hook that is called after any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * has been transferred to `to`.
     * - when `from` is zero, `amount` tokens have been minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}
}


// File @openzeppelin/contracts/token/ERC20/extensions/[email protected]

// License: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}


// File @openzeppelin/contracts/utils/[email protected]

// License: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)

pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }
}


// File @openzeppelin/contracts/utils/cryptography/[email protected]

// License: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.0;

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS,
        InvalidSignatureV
    }

    function _throwError(RecoverError error) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert("ECDSA: invalid signature");
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert("ECDSA: invalid signature length");
        } else if (error == RecoverError.InvalidSignatureS) {
            revert("ECDSA: invalid signature 's' value");
        } else if (error == RecoverError.InvalidSignatureV) {
            revert("ECDSA: invalid signature 'v' value");
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature` or error string. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
        // Check the signature length
        // - case 65: r,s,v signature (standard)
        // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else if (signature.length == 64) {
            bytes32 r;
            bytes32 vs;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            assembly {
                r := mload(add(signature, 0x20))
                vs := mload(add(signature, 0x40))
            }
            return tryRecover(hash, r, vs);
        } else {
            return (address(0), RecoverError.InvalidSignatureLength);
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, signature);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address, RecoverError) {
        bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
        uint8 v = uint8((uint256(vs) >> 255) + 27);
        return tryRecover(hash, v, r, s);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     *
     * _Available since v4.2._
     */
    function recover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, r, vs);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address, RecoverError) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return (address(0), RecoverError.InvalidSignatureS);
        }
        if (v != 27 && v != 28) {
            return (address(0), RecoverError.InvalidSignatureV);
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature);
        }

        return (signer, RecoverError.NoError);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from `s`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
    }

    /**
     * @dev Returns an Ethereum Signed Typed Data, created from a
     * `domainSeparator` and a `structHash`. This produces hash corresponding
     * to the one signed with the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
     * JSON-RPC method as part of EIP-712.
     *
     * See {recover}.
     */
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
    }
}


// File @openzeppelin/contracts/utils/cryptography/[email protected]

// License: MIT
// OpenZeppelin Contracts v4.4.1 (utils/cryptography/draft-EIP712.sol)

pragma solidity ^0.8.0;

/**
 * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.
 *
 * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,
 * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding
 * they need in their contracts using a combination of `abi.encode` and `keccak256`.
 *
 * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding
 * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA
 * ({_hashTypedDataV4}).
 *
 * The implementation of the domain separator was designed to be as efficient as possible while still properly updating
 * the chain id to protect against replay attacks on an eventual fork of the chain.
 *
 * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method
 * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].
 *
 * _Available since v3.4._
 */
abstract contract EIP712 {
    /* solhint-disable var-name-mixedcase */
    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to
    // invalidate the cached domain separator if the chain id changes.
    bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;
    uint256 private immutable _CACHED_CHAIN_ID;
    address private immutable _CACHED_THIS;

    bytes32 private immutable _HASHED_NAME;
    bytes32 private immutable _HASHED_VERSION;
    bytes32 private immutable _TYPE_HASH;

    /* solhint-enable var-name-mixedcase */

    /**
     * @dev Initializes the domain separator and parameter caches.
     *
     * The meaning of `name` and `version` is specified in
     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:
     *
     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.
     * - `version`: the current major version of the signing domain.
     *
     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart
     * contract upgrade].
     */
    constructor(string memory name, string memory version) {
        bytes32 hashedName = keccak256(bytes(name));
        bytes32 hashedVersion = keccak256(bytes(version));
        bytes32 typeHash = keccak256(
            "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
        );
        _HASHED_NAME = hashedName;
        _HASHED_VERSION = hashedVersion;
        _CACHED_CHAIN_ID = block.chainid;
        _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);
        _CACHED_THIS = address(this);
        _TYPE_HASH = typeHash;
    }

    /**
     * @dev Returns the domain separator for the current chain.
     */
    function _domainSeparatorV4() internal view returns (bytes32) {
        if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {
            return _CACHED_DOMAIN_SEPARATOR;
        } else {
            return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);
        }
    }

    function _buildDomainSeparator(
        bytes32 typeHash,
        bytes32 nameHash,
        bytes32 versionHash
    ) private view returns (bytes32) {
        return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));
    }

    /**
     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
     * function returns the hash of the fully encoded EIP712 message for this domain.
     *
     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
     *
     * ```solidity
     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
     *     keccak256("Mail(address to,string contents)"),
     *     mailTo,
     *     keccak256(bytes(mailContents))
     * )));
     * address signer = ECDSA.recover(digest, signature);
     * ```
     */
    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {
        return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);
    }
}


// File @openzeppelin/contracts/token/ERC20/extensions/[email protected]

// License: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/extensions/draft-ERC20Permit.sol)

pragma solidity ^0.8.0;





/**
 * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 *
 * _Available since v3.4._
 */
abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {
    using Counters for Counters.Counter;

    mapping(address => Counters.Counter) private _nonces;

    // solhint-disable-next-line var-name-mixedcase
    bytes32 private constant _PERMIT_TYPEHASH =
        keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
    /**
     * @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`.
     * However, to ensure consistency with the upgradeable transpiler, we will continue
     * to reserve a slot.
     * @custom:oz-renamed-from _PERMIT_TYPEHASH
     */
    // solhint-disable-next-line var-name-mixedcase
    bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT;

    /**
     * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `"1"`.
     *
     * It's a good idea to use the same `name` that is defined as the ERC20 token name.
     */
    constructor(string memory name) EIP712(name, "1") {}

    /**
     * @dev See {IERC20Permit-permit}.
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual override {
        require(block.timestamp <= deadline, "ERC20Permit: expired deadline");

        bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));

        bytes32 hash = _hashTypedDataV4(structHash);

        address signer = ECDSA.recover(hash, v, r, s);
        require(signer == owner, "ERC20Permit: invalid signature");

        _approve(owner, spender, value);
    }

    /**
     * @dev See {IERC20Permit-nonces}.
     */
    function nonces(address owner) public view virtual override returns (uint256) {
        return _nonces[owner].current();
    }

    /**
     * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view override returns (bytes32) {
        return _domainSeparatorV4();
    }

    /**
     * @dev "Consume a nonce": return the current value and increment.
     *
     * _Available since v4.1._
     */
    function _useNonce(address owner) internal virtual returns (uint256 current) {
        Counters.Counter storage nonce = _nonces[owner];
        current = nonce.current();
        nonce.increment();
    }
}


// File @openzeppelin/contracts/utils/cryptography/[email protected]

// License: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (utils/cryptography/MerkleProof.sol)

pragma solidity ^0.8.0;

/**
 * @dev These functions deal with verification of Merkle Trees proofs.
 *
 * The proofs can be generated using the JavaScript library
 * https://github.com/miguelmota/merkletreejs[merkletreejs].
 * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.
 *
 * See `test/utils/cryptography/MerkleProof.test.js` for some examples.
 *
 * WARNING: You should avoid using leaf values that are 64 bytes long prior to
 * hashing, or use a hash function other than keccak256 for hashing leaves.
 * This is because the concatenation of a sorted pair of internal nodes in
 * the merkle tree could be reinterpreted as a leaf value.
 */
library MerkleProof {
    /**
     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
     * defined by `root`. For this, a `proof` must be provided, containing
     * sibling hashes on the branch from the leaf to the root of the tree. Each
     * pair of leaves and each pair of pre-images are assumed to be sorted.
     */
    function verify(
        bytes32[] memory proof,
        bytes32 root,
        bytes32 leaf
    ) internal pure returns (bool) {
        return processProof(proof, leaf) == root;
    }

    /**
     * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
     * hash matches the root of the tree. When processing the proof, the pairs
     * of leafs & pre-images are assumed to be sorted.
     *
     * _Available since v4.4._
     */
    function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            bytes32 proofElement = proof[i];
            if (computedHash <= proofElement) {
                // Hash(current computed hash + current element of the proof)
                computedHash = _efficientHash(computedHash, proofElement);
            } else {
                // Hash(current element of the proof + current computed hash)
                computedHash = _efficientHash(proofElement, computedHash);
            }
        }
        return computedHash;
    }

    function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
        assembly {
            mstore(0x00, a)
            mstore(0x20, b)
            value := keccak256(0x00, 0x40)
        }
    }
}


// File contracts/Utilities.sol

// License: UNLICENSED
// Genius is NOT LICENSED FOR COPYING.
// Genius (C) 2022. All Rights Reserved.
pragma solidity 0.8.4;

interface IPenalty {
    function setMinersContract(address _minersAddress) external;
    function increasePenaltyCounter(uint256 principal) external;
    function redistribution(bool minerPolicy, uint256 principalPenalties, uint256 rewardPenalties) external
        returns (uint256 oaReceivingAmount, uint256 redistributedPenalties);
    function decMinerPopulation(uint256 genitos) external;
    function incMinerPopulation(uint256 genitos) external;
    function getMaxOrder() external view returns (uint256 maxOrder);
    function counter() external view returns (uint256);
    function calcLemClaimed(Utilities.MinerCache memory miner) external view returns(uint256);
    function endMinerPenalties(Utilities.MinerCache calldata miner, uint256 servedDays,
        uint256 currentGeniusDay, uint256 rewards) external
        returns (Utilities.PenaltyData memory ptData);
    function minerWeight(uint256 weight) external view returns (uint256);
}

interface IGeniusAuction {
    struct AuctionCache {
        uint256 totalBids;
        uint256 firstBid;
        address highestBidder;
        uint256 minerIndex;
        uint256 highestBid;
        address owner;
        bool active;
        uint256 end;
    }

    function getGeniusAuctionState(address owner, uint256 minerIndex)
        external
        returns (AuctionCache memory);

    function cancelAuction(address owner, uint256 minerIndex) external;

    function verifyAuctionNoBid(address owner, uint256 minerIndex)
        external
        returns (bool);

    function setPenaltyAddress(address panlty) external;

    function setMinersContract(address _minersAddress) external;

    function setCalendarContract(address _calendarAddress) external;

    function setGnftContract(address _gnftAddress) external;

}

interface IStabilityPool {

    struct CollateralMiner {
        address collateralToken;
    }

    function getMinerColAddress(address owner, uint256 minerIndex) external returns (address);

    function clearGeniusDebt(
        Utilities.MinerCache calldata miner,
        address minerOwner,
        uint256 minerIndex,
        address beneficiary,
        uint256 currentGeniusDay,
        bool benevolent
    ) external returns (uint256);

    function settleGeniusDebt(address beneficiary, address token,
        uint256 amount, uint256 settlementFeeDays, bool mintNft) external returns (uint256);

    function setOaGrantor(address grantor) external;

    function setOaBeneficiary(address beneficiary) external;

    function genitosRequiredToClear(address collateralAddress, uint256 principal) external returns (uint256);

    function setPenaltyContract(address penaltyContract) external;

    function setMinersContract(address minersContract) external;

    function setGnftContract(address _gnftAddress) external;

    function setAuctionContract(address auctionAddress) external;
}

interface IGeniusCalendar {
    struct GeniusDaySummaryStore {
        uint256 newInflation;
        uint256 redistribution;
        uint256 basicShares;
        uint256 advShares;
    }

    function getDaySummary(uint256 localGeniusDay)
        external
        view
        returns (GeniusDaySummaryStore memory summary);

    function makeGeniusDaySummary(uint256 _summarizeLimit) external;

    function decreaseBurnedSupply(uint256 _amount) external;

    function increaseBurnedSupply(uint256 _amount) external;

    function burnedSupply() external view returns (uint256);

    function calcDayBasicPayout(uint256 _geniusDay)
        external
        view
        returns (uint256);

    function calcDayAdvPayout(uint256 _geniusDay, uint256 _basicPayout)
        external
        view
        returns (uint256);

    function decAdvShares(uint256 _amount) external;

    function decBasicShares(uint256 _amount) external;

    function shareRate() external view returns (uint256);

    function localSummarizeGeniusDay(
        uint256 _summarizeLimit,
        address _summarizer,
        bool mintNft
    ) external returns(uint256 itCount);

    function local10daySummary(uint256 _summarizeLimit, address _summarizer, bool mintNft) external returns(uint256 itCount);

    function local100daySummary(uint256 _summarizeLimit, address _summarizer, bool mintNft) external returns(uint256 itCount);

    function local1000daySummary(uint256 _summarizeLimit, address _summarizer, bool mintNft) external returns(uint256 itCount);

    function incAdvSharesNext(uint256 _amount) external;

    function incBasicSharesNext(uint256 _amount) external;

    function geniusDay() external view returns (uint256);

    function setShareRate(uint256 _shareRate) external;

    function minerTotalPps(uint256 startDay, uint256 lastServedDay, bool minerPolicy) external view returns(uint256);

    function setPenaltyContract(address _penaltyAddress) external;

    function setMinersContract(address _minersAddress) external;

    function setHexodusContract(address _hexodus) external;

    function incDailyPenalties(uint256 _amount) external;

    function setGnftContract(address _gnftAddress) external;

    function summarizeServedDays(address beneficiary, uint256 startDay,
        uint256 promiseDays, bool mintNft) external;
}

interface IMiners {
    function minerStore(address owner, uint256 minerIndex) external view returns(Utilities.MinerCache memory miner);
    function minerStoreLength(address owner) external view returns (uint256 length);
    function getMiners(address owner) external view returns(Utilities.MinerCache[] memory miners);
    function setMinerEnded(address owner, uint256 minerIndex, uint256 ended) external;
    function setMinerStoreLemClaimDay(address owner, uint256 minerIndex, uint256 lemClaimDay) external;
    function setHexodusContract(address _hexodus) external;
    function setGnftContract(address _gnftAddress) external;
    function checkMinerForEnd(
        Utilities.MinerCache memory miner,
        address owner,
        uint256 minerIndex,
        uint256 currentDay,
        uint256 servedDays
    ) external;
}

interface IGnft {
    function mintNft(address to, uint256 nextSalt) external;
}


contract Utilities {

    // Revert Errors
    error NoClaimExists();
    error CannotShutdown();
    error UnauthorizedLostBonusClaiming();

    /** PHI Constants
     * @notice all of the above constants (PHI & GENIUS_RATIO) have 21 decimals of precision
     */
    /* ~ CONSTANTS ~ */
    // PHI = 1.618033988749894848205
    uint256 internal constant PHI = 1618033988749894848204586834;
    // PHI^-2 = 0.38196601125010515179541316563436188227969082019424
    uint256 internal constant PHI_NPOW_2 = 381966011250105151795413165;
    // PHI^-3 = 0.23606797749978969640917366873127623544061835961153
    uint256 internal constant PHI_NPOW_3 = 236067977499789696409173668;
    // PHI^-3.5 = 0.18558516575586807029616916594610619486184991016702
    uint256 internal constant PHI_NPOW_35 = 185585165755868070296169165;
    // PHI^2 = 2.6180339887498948482045868343656381177203091798058
    uint256 internal constant PHI_POW_2 = 2618033988749894848204586834;
    // PHI^PHI = 2.1784575679375991473725457028712458518070433016933
    uint256 internal constant PHI_POW_PHI = 2178457567937599147372545702;

    uint256 internal constant PHI_PRECISION = 1000000000000000000000000000;

    uint256 internal constant GENIUS_PRECISION = 1000000000;

    address internal constant LGENI_OA = 0x66eCa275200015DCD0C2Eaa6E48d4eED3092cDD6;

    uint8 internal constant GENIUS_DECIMALS = 9;

    // Tue Dec 13 2022 20:44:06 GMT+0000
    // Tue Dec 13 2022 13:44:06 GMT-0700 (Mountain Standard Time)
    // Tue Dec 13 2022 14:44:06 PM CST GMT-0600 (Central Standard)
    uint256 public constant LAUNCH_TIMESTAMP = 1670964246;

    // 10 ** 18
    uint256 internal constant SHARE_PRECISION = 1000000000000000000;

    // Penalty Counter Precision: 10 ** 12
    uint256 internal constant PENALTY_COUNTER_PRECISION = 1000000000000;

    // claims root for airdrop
    /** @notice MAKE CONSTANT FOR PRODUCTION */
    bytes32 internal constant MERKLE_ROOT =
        0xcad71776a60b1a4ca80bfa5452bfc50beeb645b7f64e97f5c464ef45a41d548d;

    /* ~ Variables ~ */

    uint256 public advLockedSupply;
    uint256 public basicLockedSupply;

    address public stabilityPoolAddress;
    IStabilityPool stabilityPoolContract;

    address public auctionAddress;
    IGeniusAuction auctionHouse;

    address public calendarAddress;
    IGeniusCalendar calendar;

    address public penaltyAddress;
    IPenalty penaltyContract;

    address public minersAddress;
    IMiners minersContract;

    address public hexodusAddress;
    address public gnftAddress;
    IGnft _gnftContract;

    // Origin Address Wallet
    address public oaGrantor;
    address public oaBeneficiary;

    /** Sacrifice merkle claims tracker */
    mapping(address => bool) public claimed;

    uint256 public oaMintableBalance;

    /* ~ DATA STRUCTS ~ */
    struct MinerCache {
        bool policy;
        bool auctioned;
        bool exodus;
        uint256 startDay;
        uint256 promiseDays;
        uint256 lemClaimDay;
        uint256 rewardShares;
        uint256 penaltyDelta;
        bool nonTransferable;
        uint256 ended;
        uint256 principal; // in genitos (10^9)
        uint256 debtIssueRate;
    }

    struct PenaltyData {
        uint256 eemRewardFee;
        uint256 eemPrincipalFee;
        uint256 eemPenalty;
        uint256 lemRewardFee;
        uint256 lemPrincipalFee;
        uint256 lemPenalty;
    }

    /* ~ EVENTS STRUCTS ~ */
    event Claim(
        address sender,
        address claimant,
        uint256 amount
    );

    event LemRewardsClaim(
        address indexed executorRewardAddress,
        address owner,
        uint256 minerIndex,
        uint256 executorReward
    );

    /**
     * @param  owner        the account that owned the miner at the time of end.
     * @param  minerIndex   the account's index for the miner struct.
     * @param  benevolence  whether this "end" action was for community
     *                      benevolence.
     *
     * @param  principalPayout    The amount of Principal that was returned to
     *                            the owner minus principal penalties.
     * @param  totalMinerRewards  The total amount of rewards--will always be
     *                            the Total PPS multiplied by the Shares.
     * @param  rewardsPayout      The actual amount of rewards paid to the owner
     *                            minus penalties on the rewards.
     * @param  penaltyToMiners    From ending, this amount of penalties was
     *                            redistributed to other Advanced Miners.
     */
    event EndMiner(address indexed owner, uint256 minerIndex, bool benevolence,
        uint256 principalPayout, uint256 totalMinerRewards,
        uint256 rewardsPayout, uint256 penaltyToMiners, Utilities.MinerCache miner);

    event ShutdownMiner(address indexed minerAddress, uint256 minerIndex,
        address indexed executorRewardAddress, uint256 executorReward,
        uint256 performanceRewards, uint256 redistributedPenalties,
        uint256 toOa, uint256 burnedForever, Utilities.MinerCache miner);

    event ChangeOaGrantor(address newOaGrantor, uint256 updated);

    event ChangeOaBeneficiary(address newOaBeneficiary, uint256 updated);
}


// File contracts/Genius.sol

// License: UNLICENSED
// Genius is NOT LICENSED FOR COPYING.
// Genius (C) 2022. All Rights Reserved.
pragma solidity 0.8.4;





contract Genius is ERC20, ERC20Permit, Utilities, ReentrancyGuard {

    error ErrorNullAddress();
    error ErrorUnauthorized();
    error ErrorCannotReleaseShares();
    error ErrorCannotReleaseAuctionedShares();
    error ErrorNotLaunchedYet();

    struct ShutdownDataCache {
        uint256 principalToRedistribute;
        uint256 rewardsToRedistribute;
        uint256 txPrincipalRewards;
        uint256 txPerformanceRewards;
    }

    constructor(
        address _oaGrantor,
        address _oaBeneficiary
    ) ERC20("Genius", "GENI") ERC20Permit("Genius") {
        if (_oaGrantor == address(0) || _oaBeneficiary == address(0)) {
            revert ErrorNullAddress();
        }
        oaGrantor = _oaGrantor;
        oaBeneficiary = _oaBeneficiary;
        _mint(address(this), 240000000000000000000);
    }

    /**
     * @notice public facing pure, returns decimal precision value of genius
     */
    function decimals() public pure override returns (uint8) {
        return GENIUS_DECIMALS;
    }

    /**
     * @dev only callable by oaGrantor, set oaBeneficiary address
     */
    function changeOaBeneficiary(address _oaBeneficiary) external {
        if (_oaBeneficiary == address(0)) revert ErrorNullAddress();
        if (msg.sender != oaGrantor) revert ErrorUnauthorized();
        oaBeneficiary = _oaBeneficiary;
        stabilityPoolContract.setOaBeneficiary(_oaBeneficiary);
        emit ChangeOaBeneficiary(_oaBeneficiary, block.timestamp);
    }

    /**
     * @dev only callable by oaGrantor, change oaGrantor
     */
    function changeOaGrantor(address _newOaGrantor) external {
        if (_newOaGrantor == address(0)) revert ErrorNullAddress();
        if (msg.sender != oaGrantor) revert ErrorUnauthorized();
        oaGrantor = _newOaGrantor;
        stabilityPoolContract.setOaGrantor(_newOaGrantor);
        emit ChangeOaGrantor(_newOaGrantor, block.timestamp);
    }

    /**
     * @notice public facing, shielded. Only OA can set the auction.
     * @notice auction house must be set before auction functions are operable
     */
    function setAuctionContract(address _auction) external {
// NOTE: OA Grantor check removed because deployment will include these "set"
// functions.  The actual gate that will prevent the Auction Contract being
// set again is the requirement that auctionAddress is not yet set.
//        require(msg.sender == oaGrantor && auctionAddress == address(0), "u");
        if (_auction == address(0)) revert ErrorNullAddress();
        if (auctionAddress != address(0)) revert ErrorUnauthorized();
        auctionAddress = _auction;
        auctionHouse = IGeniusAuction(_auction);
        stabilityPoolContract.setAuctionContract(_auction);
    }

    /**
     * @dev only callable by oaGrantor, set stability pool address (only callable once)
     */
    function setStabilityPoolAddress(address _stabilityPool) external {
// NOTE: this prevents Stability Pool from being set again AFTER deployment
// by ensuring that the contract address has not already been set.
//        require(msg.sender == oaGrantor && stabilityPoolAddress == address(0), "u");
        if (_stabilityPool == address(0)) revert ErrorNullAddress();
        if (stabilityPoolAddress != address(0)) revert ErrorUnauthorized();
        stabilityPoolAddress = _stabilityPool;
        stabilityPoolContract = IStabilityPool(_stabilityPool);
        // NOTE: to prevent a circular dependency, the OA Grantor will need to
        // call this separately.
        //auctionHouse.setStabilityContract(_stabilityPool);
    }

    /**
     * @dev only callable by oaGrantor, set calendar address and calls setters on calendar and auction (only callable once)
     */
    function setCalendarContract(address _calendar) external {
// NOTE: this prevents Calendar from being set again AFTER deployment by
// ensuring that the contract address has not already been set.
        if (_calendar == address(0)) revert ErrorNullAddress();
        if (calendarAddress != address(0)) revert ErrorUnauthorized();
        calendarAddress = _calendar;
        calendar = IGeniusCalendar(_calendar);
        auctionHouse.setCalendarContract(_calendar);
    }

    /**
     * @dev only callable by oaGrantor, set penalty address and calls setters on calendar, stability pool and auction (only callable once)
     */
    function setPenaltyContract(address _pcAddress) external {
// NOTE: this prevents Penalty from being set again AFTER deployment by
// ensuring that the contract address has not already been set.  The deploy
// scripts manage and ensure that this is set at launch.
        if (_pcAddress == address(0)) revert ErrorNullAddress();
        if (penaltyAddress != address(0)) revert ErrorUnauthorized();
//        require(
//            msg.sender == oaGrantor &&
//            penaltyAddress == address(0) &&
//            calendarAddress != address(0) &&
//            stabilityPoolAddress != address(0) &&
//            auctionAddress != address(0)
//        , "u");

// NOTE: combining these saves 0.111 KB.
//        require(msg.sender == oaGrantor && penaltyAddress == address(0), "u");
//        require(calendarAddress != address(0), "1");
//        require(stabilityPoolAddress != address(0), "2");
//        require(auctionAddress != address(0), "3");
        penaltyContract = IPenalty(_pcAddress);
        penaltyAddress = _pcAddress;
        calendar.setPenaltyContract(_pcAddress);
        stabilityPoolContract.setPenaltyContract(_pcAddress);
        auctionHouse.setPenaltyAddress(_pcAddress);
    }

    /**
     * @dev only callable by oaGrantor, sets miners address and calls setters on auction, calendar and stability pool (only callable once)
     */
    function setMinersContract(address _minersAddress) external {
// NOTE: this prevents Miners from being set again AFTER deployment by
// ensuring that the contract address has not already been set.  The deploy
// scripts manage and ensure that this is set at launch.
//        require(msg.sender == oaGrantor && minersAddress == address(0), "u");
        if (_minersAddress == address(0)) revert ErrorNullAddress();
        if (minersAddress != address(0)) revert ErrorUnauthorized();
        minersAddress = _minersAddress;
        minersContract = IMiners(_minersAddress);
        auctionHouse.setMinersContract(_minersAddress);
        calendar.setMinersContract(_minersAddress);
        stabilityPoolContract.setMinersContract(_minersAddress);
        penaltyContract.setMinersContract(_minersAddress);
    }

    function setHexodusContract(address _hexodus) external {
        if (_hexodus == address(0)) revert ErrorNullAddress();
        if (msg.sender != oaGrantor || hexodusAddress != address(0)) {
            revert ErrorUnauthorized();
        }
        hexodusAddress = _hexodus;
        minersContract.setHexodusContract(_hexodus);
        calendar.setHexodusContract(_hexodus);
    }

    /**
     * @notice set up Genius NFT controller
     * @dev allowed only by OA grantor or deployer
     * @param _gnftAddress address of genius NFT controller
     */
    function setGnftContract(address _gnftAddress) external {
// NOTE: GNFT will be launched after the core Genius contracts, and therefore,
// it is necessary to also gate the setting of GNFT's address by limiting this
// action to the OA Grantor.
        if (_gnftAddress == address(0)) revert ErrorNullAddress();
        if (msg.sender != oaGrantor || gnftAddress != address(0)) {
            revert ErrorUnauthorized();
        }
        gnftAddress = _gnftAddress;
        _gnftContract = IGnft(_gnftAddress);

        auctionHouse.setGnftContract(_gnftAddress);
        calendar.setGnftContract(_gnftAddress);
        minersContract.setGnftContract(_gnftAddress);
        stabilityPoolContract.setGnftContract(_gnftAddress);
    }

    function _currentGeniusDay() internal view returns (uint256) {
        if (block.timestamp < LAUNCH_TIMESTAMP) revert ErrorNotLaunchedYet();
        unchecked {
            return (block.timestamp - LAUNCH_TIMESTAMP) / 1 days;
        }
    }

    /**
     * @dev PUBLIC FACING VIEW, view function that returns the total reserved supply accounting
     */
    function reserveSupply() external view returns (uint256) {
        unchecked {
            return totalSupply() + calendar.burnedSupply() + advLockedSupply + basicLockedSupply;
        }
    }

    /**
     * @dev Claims for initial GENI distribution
     * @param destination is the claimant, based on off chain data
     * @param amount claimant's amount of GENI to distribute
     * @param merkleProof array of hashes up the merkleTree
     * @param mintNft  The EOA's preference of whether or not to spend gas for
     *                 the chance of minting an NFT.
     */
    function claimGenius(
        address destination,
        uint256 amount,
        bytes32[] calldata merkleProof,
        bool mintNft
    ) external nonReentrant {
//        require(canClaim(destination, amount, merkleProof), "I");
        if (!canClaim(destination, amount, merkleProof)) {
            revert NoClaimExists();
        }

        claimed[destination] = true;

        if (destination == msg.sender || _currentGeniusDay() < 181 ||
            (block.timestamp < LAUNCH_TIMESTAMP && destination == LGENI_OA))
        {
            ERC20(address(this)).transfer(destination, amount);
            if (mintNft) {
                _gnftContract.mintNft(destination, 0);
            }
            emit Claim(msg.sender, destination, amount);
            return;
        }

        // Sender may get an NFT if they opted-into minting :)
        if (mintNft && _probability(msg.sender, PHI_NPOW_2, PHI_PRECISION, 0, 0)) {
            _gnftContract.mintNft(msg.sender, 1);
        }

        unchecked {
            // the msg.sender will receive 100 GENI, and the remainder goes to the
            // lazy owner of the claim :)
            ERC20(address(this)).transfer(msg.sender, 100000000000);
            ERC20(address(this)).transfer(destination, amount - 100000000000);
        }
        emit Claim(msg.sender, destination, amount);
    }

    /**
     * @dev helper for validating if an address has GENI to claim
     * @return true if claimant has not already claimed and the data is valid, false otherwise
     */
    function canClaim(
        address destination,
        uint256 amount,
        bytes32[] calldata merkleProof
    ) public view returns (bool) {
        bytes32 node = keccak256(abi.encodePacked(destination, amount));
        return
            !claimed[destination] &&
            MerkleProof.verify(merkleProof, MERKLE_ROOT, node);
    }

    /**
     * @dev only callable by auction contract.  Mints Genius token.
     */
    function mint(address owner, uint256 amount) external {
        if (msg.sender != auctionAddress) revert ErrorUnauthorized();
        _mint(owner, amount);
    }

    /**
     * @dev only callable by stability pool, auction, miners, or hexodus.
     *      Burns Genius token.
     */
    function burn(address owner, uint256 amount) external {
        if (
            msg.sender != stabilityPoolAddress &&
            msg.sender != auctionAddress &&
            msg.sender != minersAddress &&
            msg.sender != hexodusAddress
        ) {
            revert ErrorUnauthorized();
        }
        _burn(owner, amount);
    }


    /**
     * @dev INTERNAL, calculates new share rate based on eem payout
     */
    function _newShareRate(MinerCache memory miner, uint256 neemPayout) internal view returns(uint256 newShareRate) {
        unchecked {
            newShareRate = (neemPayout * PHI_PRECISION +
                _min(
                    neemPayout * PHI_POW_PHI,
                    (neemPayout *
                        _min(
                            4444 * PHI_PRECISION,
                            _ceiling(
                                miner.promiseDays *
                                    (PHI_PRECISION + PHI_NPOW_3),
                                PHI_PRECISION
                            ) - PHI_PRECISION
                        )) /
                        1456
                ) +
                neemPayout * _min(neemPayout * PHI_PRECISION, PHI * 10**17) / 10**18) /
                miner.rewardShares /
                PHI_PRECISION;
            return newShareRate;
        }
    }

    /**
     * @dev manage share rate calculations for end miner functionality
     */
    function _manageSystemShares(
        MinerCache memory miner,
        uint256 currentGeniusDay,
        uint256 eemPenalty,
        uint256 lemPenalty,
        uint256 rewards
    ) internal {
        if (miner.lemClaimDay == 0) {
            if (!miner.policy) {
                calendar.decBasicShares(miner.rewardShares);
            } else {
                calendar.decAdvShares(miner.rewardShares);
            }
        }
        unchecked {
            uint256 neemPayout = miner.principal + rewards -
                (currentGeniusDay < miner.startDay + miner.promiseDays ? eemPenalty : 0);
    //        uint256 neemPayout = _neemPayout(
    //            miner.principal,
    //            rewards,
    //            currentGeniusDay,
    //            miner.startDay + miner.promiseDays,
    //            eemPenalty
    //        ); // NEEMP - Non-Early End Mining Payout

            if (neemPayout >= miner.principal) {
                // calculate new Share Rate
                calendar.setShareRate(_newShareRate(miner, neemPayout));
            }
        }
    }

    /**
     * @dev send collateral miner payouts for ended miners
     */
    function _manageCollateralMinerPayouts(
        address owner,
        uint256 netPrincipalPayout,
        uint256 netRewardsPayout,
        bool benevolence
    ) internal {
        if (!benevolence) {
            // if net principal payout > 0:
            //      mint ( principal + rewards )
            if (netPrincipalPayout > 0) {
                unchecked {
                    _mint(owner, netPrincipalPayout + netRewardsPayout);
                }
            }

            // if net rewards payout > 0:
            //      decrease burned supply ( net rewards payout )
            if (netRewardsPayout > 0) {
                calendar.decreaseBurnedSupply(netRewardsPayout);
            }
        }
    }

    /**
     * @dev send miner payouts foe ended miners
     */
    function _manageMinerPayouts(
        MinerCache memory miner,
        address owner,
        uint256 eemPrincipalFee,
        uint256 lemPrincipalFee,
        uint256 eemRewardFee,
        uint256 lemRewardFee,
        uint256 rewards,
        bool benevolence
    ) internal returns (uint256 netPrincipalPayout, uint256 netRewardsPayout) {
        unchecked {
            uint256 principalPenalties = _max(eemPrincipalFee, lemPrincipalFee + penaltyContract.calcLemClaimed(miner));
            uint256 rewardPenalties = _max(eemRewardFee, lemRewardFee);
            netPrincipalPayout = miner.principal > principalPenalties ? miner.principal - principalPenalties : 0;
            netRewardsPayout = rewards > rewardPenalties ? rewards - rewardPenalties : 0;

            if (miner.lemClaimDay == 0) {
                // NOTE: the Release Shares function is responsible for moving the
                // entire principal out of the Locked Supply--because that principal
                // is no-longer "locked".  However, when LEM Claim Day is not set,
                // then the Release Shares function was not called, and the miner's
                // principal must be completely removed from the locked supply.

                if (miner.policy) {
                    // NOTE: the Principal Penalties will STILL be removed from
                    // the locked supply.  In other words, the entire principal
                    // must be removed.  The Lucid Chart specs were wrong;
                    // remove the entire supply.
                    advLockedSupply -= miner.principal;
                } else {
                    // NOTE: the entire principal should be removed from any of
                    // the Locked supplies because the principal is no-longer
                    // "locked".  Of course, any principal that does not get
                    // "minted" to the EOA or OA will need to be added to the
                    // Burned Supply.
                    basicLockedSupply -= miner.principal;
                }

                if (netRewardsPayout > 0 && !benevolence) {
                    calendar.decreaseBurnedSupply(netRewardsPayout);
                }

                // NOTE: if this is Benevolence, then is the entire principal must
                // be moved over to the Burned Supply.
                if (benevolence) {
                    calendar.increaseBurnedSupply(miner.principal);
                }
                else {
                    // But when the miner was not ended benevolently, then we will
                    // increase the burned supply by only the principal penalties,
                    // which *will not* include the LEM Claim Reward.  That reward
                    // will not be included in the 'principalPenalties' calculation
                    // because the lemClaimDay property is 0 :)
                    calendar.increaseBurnedSupply(principalPenalties);
                }
            } else {
                // WARNING: in this scope, the shares were released by the Release
                // Shares function, and therefore, all principal (minus the LEM
                // Claim Reward) was already moved over to the Burned Supply.

                // THEREFORE: we will not increase the Burned Supply here.  We will
                // only decrease the burned supply by the amount of principal and
                // rewards that get removed from the Burned Supply.

                // NOTE: When a non-collateral miner ends, if the shares were
                // released, like in this conditional scope, then the entire
                // principal was already unlocked and moved over to the burned
                // supply.  Therefore, we need to remove any principal (and rewards)
                // that will be minted out of the Burned Supply.
                calendar.decreaseBurnedSupply(netPrincipalPayout + netRewardsPayout);
            }

            // NOTE: all "penalized principal" must move over to the Burned Supply,
            // except for the LEM Claim Reward, because that was given to the EOA
            // that called the Release Shares function.  Furthermore, the payout
            // accounting is handled automatically by _mint -- Total Supply will be
            // increased, and the amount increased was already removed, or not added
            // to, the Burned Supply in the scope, above.

            if (!benevolence && netPrincipalPayout + netRewardsPayout > 0) {
                _mint(owner, netPrincipalPayout + netRewardsPayout);
            }
        }
    }

    /**
     * @dev extended logic for endMiner() function
     * @param  owner  the owner of the miner -- it is the responsibility of the
     *                external functions that call this function to provide end
     *                user security.  Only the msg sender can end a miner.
     * @param  minerIndex   miner index
     * @param  rewards      all performance rewards earned during this miner's
     *                      serving period.
     * @param  benevolence  is this miner ending for the sake of benevolence?
     *                      then anything minted will be burned.
     * @param  mintNft      end user opt-in to spend gas and possibly get an NFT
     */
    function _endMinerDeep(address owner, uint256 minerIndex, uint256 rewards, bool benevolence, bool mintNft) internal
        returns (
            uint256 netPrincipalPayout, uint256 netRewardsPayout, uint256 penaltyToMiners
        ) {
        MinerCache memory miner = minersContract.minerStore(owner, minerIndex);
        unchecked {
            uint256 currentGeniusDay = _currentGeniusDay();
            uint256 servedDays = (
                currentGeniusDay < (miner.startDay + miner.promiseDays)
                    ? currentGeniusDay
                    : (miner.startDay + miner.promiseDays)
                ) - miner.startDay;

            // EM_03
            PenaltyData memory ptData = penaltyContract.endMinerPenalties(miner, servedDays, currentGeniusDay, rewards);

            // EM_04
            if (servedDays < miner.promiseDays) {
                // @dev miner is ending early.
                penaltyToMiners = _redistribution(miner, rewards, ptData.eemPrincipalFee, ptData.eemRewardFee);

                if (mintNft) {
                    if (_probability(owner, PHI / (miner.policy ? 10 : 100),
                        PHI_PRECISION, miner.principal, 0))
                    {
                        _gnftContract.mintNft(owner, 1);
                    }
                    else if (benevolence &&
                        _probability(owner, PHI_PRECISION, PHI_PRECISION, miner.principal, 2))
                    {
                        _gnftContract.mintNft(owner, 1);
                    }
                }
            } else {
                if (currentGeniusDay > miner.startDay + miner.promiseDays + 7) {
                    // @dev miner ended late and will serve late penalties.
                    penaltyToMiners = _redistribution(miner, rewards, ptData.lemPrincipalFee, ptData.lemRewardFee);

                    if (mintNft) {
                        bool minted = false;
                        if (benevolence) {
                            if (_probability(owner, PHI / 10, PHI_PRECISION, miner.principal, 10)) {
                                _gnftContract.mintNft(owner, 11);
                                minted = true;
                            }
                        }

                        if (!minted) {
                            if (_probability(owner, PHI / (miner.policy ? 10 : 100),
                                PHI_PRECISION, miner.principal, 0))
                            {
                                _gnftContract.mintNft(owner, 1);
                            }
                        }
                    }
                } else {
                    // @dev miner ended on time, as promised by the EOA.

                    // if the EOA opted-in to mint an NFT...
                    if (mintNft) {
                        // if this miner had 90 or more promise days...
                        if (miner.promiseDays > 89) {
                            // NOTE: if someone created a BASIC miner w/ 89 Promise
                            // Days on Day 0, then they get a free day and free NFT
                            // ...lucky!! :D
                            if (_probability(owner, PHI_PRECISION, PHI_PRECISION,
                                miner.principal, 0))
                            {
                                _gnftContract.mintNft(owner, 1);
                            }

                            // ALSO NOTE: if this end is a result of benevolence,
                            // then there will be another round of chance.
                            if (benevolence) {
                                if (_probability(owner, PHI_PRECISION, PHI_PRECISION,
                                    miner.principal, 3))
                                {
                                    _gnftContract.mintNft(owner, 4);
                                }
                            }
                        }
                        else if (_probability(owner, PHI / 100, PHI_PRECISION,
                            miner.principal, 0))
                        {
                            // Promise days will be < 90, and therefore this must be a
                            // Basic Miner.
                            _gnftContract.mintNft(owner, 1);
                        }
                        else if (benevolence && _probability(
                            owner, PHI_PRECISION, PHI_PRECISION, miner.principal, 20))
                        {
                            // if this condition is met, then this is a basic miner
                            // that was Proof Of Benevolence'd.
                            _gnftContract.mintNft(owner, 1);
                        }
                    }
                }
            }

            // EM_05 Manage System Shares
            _manageSystemShares(
                miner,
                currentGeniusDay,
                ptData.eemPenalty,
                ptData.lemPenalty,
                rewards
            );

            if (miner.debtIssueRate > 0) {
                // EM_06B Manage Collateral Payouts
                (netPrincipalPayout, netRewardsPayout) = _manageCollateralPayouts(
                    miner, owner, minerIndex, rewards,
                    ptData.lemPrincipalFee, ptData.lemRewardFee, benevolence);
            } else {
                // EM_06A Manage Payouts
                // uint256 principalPenalties = _max(eemPrincipalFee, lemPrincipalFee + lemClaimed);
                // address localOwner = owner;
                uint256 rewards = rewards;
                bool benevolence = benevolence;
                (netPrincipalPayout, netRewardsPayout) = _manageMinerPayouts(
                    miner,
                    owner,
                    ptData.eemPrincipalFee,
                    ptData.lemPrincipalFee,
                    ptData.eemRewardFee,
                    ptData.lemRewardFee,
                    rewards,
                    benevolence
                );
            }
        }
    }

    function _manageCollateralPayouts(
        MinerCache memory _miner,
        address _owner,
        uint256 _minerIndex,
        uint256 _rewards,
        uint256 _principalPenalties,
        uint256 _rewardPenalties,
        bool _benevolence
    ) internal returns (uint256 netPrincipalPayout, uint256 netRewardsPayout) {

        unchecked {
            uint256 rewardPenalties = _min(_rewards, _principalPenalties + _rewardPenalties);
            uint256 currentGeniusDay = _currentGeniusDay();

            // EM_06B
            if (_miner.lemClaimDay == 0) {
                advLockedSupply -= _miner.principal;
            }

            /*
                Utilities.MinerCache calldata miner,
                address minerOwner,
                uint256 minerIndex,
                address beneficiary,
                uint256 currentGeniusDay,
                bool benevolent
            */
            address owner = _owner;
            uint256 minerSettlementAmount = stabilityPoolContract.clearGeniusDebt(
                _miner, owner, _minerIndex, owner,
                currentGeniusDay, _benevolence);
    //        netPrincipalPayout = availablePrincipal > minerSettlementAmount ? availablePrincipal - minerSettlementAmount : 0;
            netPrincipalPayout = _miner.principal > minerSettlementAmount ?
                _miner.principal - minerSettlementAmount : 0;

            // NOTE: _rewardPenalties is what was passed as a parameter, it is NOT
            // the recalculated local variable.  Use the local variable that was a
            // recalculation of the Reward Penalties.
            netRewardsPayout = _rewards - rewardPenalties;
            _manageCollateralMinerPayouts(owner, netPrincipalPayout, netRewardsPayout, _benevolence);
        }
    }

    /**
     * @dev handle miner end functionalities
     * @param  minerIndex   index of the miner
     * @param  benevolence  is the miner benevolenced?
     * @param  mintNft      end user opt-in to spend gas and possibly get an NFT
     */
    function endMiner(
        uint256 minerIndex,
        bool benevolence,
        bool mintNft
    ) external nonReentrant {
        MinerCache memory miner = minersContract.minerStore(msg.sender, minerIndex);
        unchecked {
            uint256 currentGeniusDay = _currentGeniusDay();

            // Promise End Day = miner.startDay + miner.promiseDays
            // Served Days = MIN(Current Genius Day, Promise End Day) - miner.startDay
            // NOTE: if the miner index is invalid, then the "servedDays" value will
            // result in 0.
            uint256 servedDays = (
                currentGeniusDay < (miner.startDay + miner.promiseDays)
                    ? currentGeniusDay
                    : (miner.startDay + miner.promiseDays)
            ) - miner.startDay;

            // Start EM_01
            minersContract.checkMinerForEnd(
                miner,
                msg.sender,
                minerIndex,
                currentGeniusDay,
                servedDays
            );

            // Start Phase EM_02 Summarize Served Days
            //uint256 lastServedDay = miner.startDay + servedDays - 1;
            uint256 lastSummarizedDay = calendar.geniusDay() - 1;

            // if the miner is ending early OR the miner is ending beyond the grace period...
            if (servedDays < miner.promiseDays || miner.startDay + miner.promiseDays + 7 <= currentGeniusDay) {
                //calendar.localSummarizeGeniusDay(_currentGeniusDay() - lastServedDay, msg.sender);
                //calendar.localSummarizeGeniusDay(_currentGeniusDay() - (miner.startDay + servedDays - 1), msg.sender);

                calendar.localSummarizeGeniusDay(0, msg.sender, mintNft);
                calendar.local10daySummary(0, msg.sender, mintNft);
                calendar.local100daySummary(0, msg.sender, mintNft);
                calendar.local1000daySummary(0, msg.sender, mintNft);
            }
            else {
                // NOTE: when the miner ends "on-time", we won't catch-up and
                // summarize every single day, 10-day, 100-day, and 1,000-day
                // period summary.  Instead, since the owner of the miner was a
                // "good end user" and did the "good thing" by ending on-time, we
                // will only summarize the days and periods that enclose the days
                // served.
                //
                // Therefore, we must do this before we calculate the Total PPS and
                // rewards:
                //
                // 1) summarize all single-day summaries: only summarize the served
                //    days that have not yet been summarized.
                //if (lastServedDay > lastSummarizedDay) {
                uint256 lastServedDay = miner.startDay + servedDays - 1;
                if (lastServedDay > lastSummarizedDay) {
                    //calendar.localSummarizeGeniusDay(lastServedDay - lastSummarizedDay, msg.sender);
                    calendar.localSummarizeGeniusDay(
                        lastServedDay - lastSummarizedDay,
                        msg.sender,
                        mintNft
                    );
                }

                // 2) Summarize all full 10-day periods within the SERVED DAYS.
                //    Therefore, if the miner served all days (including) 100-415
                //    and we realize that the only 10-day summaries that exist are
                //    for all days prior to 390, then we must create the 10-day
                //    summary for 390-399 (index 39) and 400-409 (index 40).
                //    Summary 410-419 (index 41) WILL NOT BE CREATED because the
                //    miner did not serve the entire period of days 410-419; that
                //    miner only served days 410-415.  We also won't summarize the
                //    index 41 to save the end user gas :)  And because the end user
                //    does not need index 41 to calculate their Total PPS.
                    // Dai Proving the calculation of index and full period
                    // Summaring example and index and period change
                    // startDay = 0, servedDays = 10, lastServedDay = 9 =>
                    //      10summary index 0, period 1
                    //      100summary index 0, period 1
                    //      1000summary index 0, period 1
                    // startDay = 0, servedDays = 100, lastServedDay = 99 =>
                    //      10summary index 9, period 10
                    //      100summary index 9, period 0
                    //      1000summary index 9, period 0
                    // ... ...
                    // start day = 100, servedDays = 316 lastServedDay = startDay + servedDays - 1 = 415 =>
                    //      10summary index 41, period 42
                    //      100summary index 4, period 5
                    //      1000summary index 0, period 0
                    // Generalizing....
                    // maxXIndex = (miner.startDay +servedDays - 1) / X-days;
                    // maxXPeriod = max10Index + 1 = (miner.startDay +servedDays - 1) / X-days + 1;
                    // actualXPeriod = maxXPeriod - 1 = (miner.startDay +servedDays - 1) / X-days + 1 - 1 = (miner.startDay +servedDays - 1) / X-days
                    calendar.local10daySummary(lastServedDay / 10, msg.sender, mintNft);

                // 3) Just like with the 10-day periods, we must summarize all
                //    100-day periods that the miner needs to calculate the Total
                //    PPS / rewards, properly.
                    calendar.local100daySummary(lastServedDay / 100, msg.sender, mintNft);

                // 4) And then, finally, we must make sure that all 1,000-day
                //    periods within the SERVED DAYS are summarized.
                    calendar.local1000daySummary(lastServedDay / 1000, msg.sender, mintNft);
            }

            //calendar.minerTotalPps(miner.startDay, lastServedDay, miner.policy)
            uint256 totalMinerPps = calendar.minerTotalPps(miner.startDay, (miner.startDay + servedDays - 1), miner.policy);
            uint256 rewards = miner.rewardShares * totalMinerPps / SHARE_PRECISION;

            // End Phase EM_02
            (
                uint256 netPrincipalPayout,
                uint256 netRewardsPayout,
                uint256 penaltyToMiners
            )
            = _endMinerDeep(msg.sender, minerIndex, rewards, benevolence, mintNft);
            MinerCache memory miner2 = miner;
            emit EndMiner(msg.sender, minerIndex, benevolence,
                netPrincipalPayout, rewards,
                netRewardsPayout, penaltyToMiners, miner2);
        }
    }

    /**
     * @dev calculates late end mining penalties
     */
    function _penaltiesLem(
        uint256 geniusDay,
        uint256 promiseEndDay,
        uint256 principal,
        uint256 penalties,
        bool policy
    ) internal pure returns (uint256) {
        unchecked {
            uint256 lateDays = geniusDay - promiseEndDay - 7;
            uint256 min;

            if (!policy) {
                uint256 ceil = (principal * PHI * 100) / (7 * PHI_PRECISION);
                ceil =
                    ((ceil + GENIUS_PRECISION) - GENIUS_PRECISION) *
                    GENIUS_PRECISION;
                min = ceil > principal ? principal : ceil;
            } else {
                uint256 ceil = (principal * PHI_POW_2 * 100) / (7 * PHI_PRECISION);
                ceil =
                    ((ceil + GENIUS_PRECISION) - GENIUS_PRECISION) *
                    GENIUS_PRECISION;
                min = ceil > principal ? principal : ceil;
            }
            return (penalties / 1000) - (lateDays * min);
        }
    }

    /**
     * @dev mint amount stored in oaMintableBalance to the oaBeneficiary
     */
    function claimLostMintBonus() external nonReentrant {
// NOTE: converting this to a revert saves ... only 2 bytes :(
//        require(
//            msg.sender == oaGrantor &&
//            _currentGeniusDay() > 31 &&
//            oaMintableBalance > 0
//        , "u");
        if (msg.sender != oaGrantor ||
            _currentGeniusDay() < 32 ||
            oaMintableBalance == 0)
        {
            revert UnauthorizedLostBonusClaiming();
        }

// NOTE: combining these saves 0.039 KB
//        require(msg.sender == oaGrantor, "u");
//        require(_currentGeniusDay() > 31 && oaMintableBalance > 0, "o");
        _mint(oaBeneficiary, oaMintableBalance);
        oaMintableBalance = 0;
    }

    /**
     * @dev only callable by miners, increase oaMintableBalance
     */
    function incOaMintableBalance(uint256 bonusLostForever) external {
        if (msg.sender != minersAddress) revert ErrorUnauthorized();
        oaMintableBalance += bonusLostForever;
    }

    /**
     * @dev PUBLIC FACING, executes releaseShares core functionality (releases shares from pool)
     * @param  owner    owner of the miner that has the shares to be released.
     * @param  minerId  the INDEX of the owner's miner
     * @param  mintNft  end user opt-in to spend gas and possibly get an NFT
     */
    function releaseShares(address owner, uint256 minerId, bool mintNft) external nonReentrant {
        /*
            Inspect the lucid chart spec carefully, and be sure to update the flow and implementation of the RED TEXT AREAS.
            https://lucid.app/lucidchart/f1a1439e-e956-4a2c-be2f-e5dba66cc6a5/edit?view_items=0ccNMa7ilC91&invitationId=inv_5b23c2b2-e19b-434c-b6a4-9fcc5f90496c#

            For accounting references, check out the "Release Shares Burning Principal" sub-sheet.
            https://docs.google.com/spreadsheets/d/16JXDzM2PwEOQD-324uwTPVYQbhWbUWnavtKcusaWjzs/edit?usp=sharing
         */
        // Require: Miner Ended is False
        MinerCache memory miner = minersContract.minerStore(owner, minerId);
        unchecked {
    // NOTE: combining the 3 requires below saves 0.078 KB.
    //        require(miner.ended == 0, "f");

            // Require: Miner LEM Claim Day == 0
    //        require(miner.lemClaimDay == 0, "L");

            uint256 promiseEndDay = miner.startDay + miner.promiseDays;
            uint256 cgd = _currentGeniusDay();

            // Require: CGD >= Promise End Day
    //        require(cgd >= promiseEndDay, "E");
            if (miner.auctioned && miner.nonTransferable) {
                revert ErrorCannotReleaseAuctionedShares();
            }
            if (
                miner.ended > 0 ||
                miner.lemClaimDay > 0 ||
                cgd < promiseEndDay ||
                miner.promiseDays == 0
            ) {
                revert ErrorCannotReleaseShares();
            }

            // Set the Miner LEM Claim Day to CGD
            minersContract.setMinerStoreLemClaimDay(owner, minerId, cgd);

            // Calculate Daily Late Fee
            uint256 ceil;
            if (miner.policy) {
                // Need to consider PHI precision
                ceil = _ceiling(miner.principal * PHI_POW_2 / 7 / 100, PHI_PRECISION) / PHI_PRECISION;
            } else {
                // Need to consider PHI precision
                ceil = _ceiling(miner.principal * PHI / 7 / 100, PHI_PRECISION) / PHI_PRECISION;
            }

            // Calculate the LEM Release Reward

            // lemReleaseReward = MIN(principal, lateDayCount * dailyLateFee)
            // NOTE: dailyLateFee = MIN(principal, CEILING(calculation here))
            uint256 lemReleaseReward = _min(miner.principal, (cgd > promiseEndDay + 7 ? cgd - promiseEndDay - 7 : 0)
                * _min(miner.principal, ceil));

            // Check if the miner is under auction and the auction has zero bids.
            if (miner.auctioned) {
                if (auctionHouse.verifyAuctionNoBid(owner, minerId)) {
                    auctionHouse.cancelAuction(owner, minerId);
                }
            }

            // Enforce that at least the first day of the miner was summarized.
            // This prevents a possible underflow when removing the shares from the
            // calendar's share pool.
            uint256 gDay = calendar.geniusDay();
            if (gDay < miner.startDay + 1) {
                calendar.localSummarizeGeniusDay(miner.startDay + 1 - gDay, msg.sender, mintNft);
            }

            if (miner.policy) {
                advLockedSupply -= miner.principal;
                calendar.decAdvShares(miner.rewardShares);
            } else {
                basicLockedSupply -= miner.principal;
                calendar.decBasicShares(miner.rewardShares);
            }

            uint256 minerSettlementAmount;
            if (miner.debtIssueRate > 0) {
                if (lemReleaseReward > 0) {
                    address colToken = stabilityPoolContract.getMinerColAddress(owner, minerId);
                    minerSettlementAmount =
                        stabilityPoolContract.settleGeniusDebt(msg.sender, colToken, lemReleaseReward, cgd - miner.startDay, false);
                    lemReleaseReward = _min(minerSettlementAmount, lemReleaseReward);
                }
            } else {
                calendar.increaseBurnedSupply(miner.principal > lemReleaseReward ? miner.principal - lemReleaseReward : 0);
                if (lemReleaseReward > 0) {
                    _mint(msg.sender, lemReleaseReward);
                }
            }

            if (mintNft && _probability(msg.sender, PHI_NPOW_3, PHI_PRECISION, 0, 0)) {
                _gnftContract.mintNft(msg.sender, 1);
            }

            // By checking the event param, we can have people know that if there is no debt to settle, they actually get no reward.
            emit LemRewardsClaim(msg.sender, owner, minerId, lemReleaseReward);
        }
    }

    /**
     * @dev round up or ceil a number with the precision specified.
     * @param a number to be rounded up or ceiled
     * @param m precision (10^x, where x >= 0) of ceiling the number
     * @return ceiled value
     */
    function _ceiling(uint256 a, uint256 m) internal pure returns (uint256) {
        //return ((a + m - 1) / m) * m;
        unchecked {
            return (a / m + (a % m == 0 ? 0 : 1)) * m;
        }
    }

    /**
     * @dev compare two numbers and return smaller one.
     * @param a number a
     * @param b number b
     * @return smaller value
     */
    function _min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev compare two numbers and return greater one.
     * @param a number a
     * @param b number b
     * @return greater value
     */
    function _max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev PUBLIC FACING, executes shutdownMiner core functionality
     * @param owner owner of the miner
     * @param minerId ID(index) of the miner
     */
    function shutdownMiner(address owner, uint256 minerId, bool mintNft)
        external nonReentrant
    {
        MinerCache memory miner = minersContract.minerStore(owner, minerId);
        unchecked {
            // First Late Day = Start Day + Promise Days + 7
            uint256 forcedShutdownDay = miner.policy ?
                miner.startDay + miner.promiseDays + 275 :
                miner.startDay + miner.promiseDays + 440;

            if (
                _currentGeniusDay() < forcedShutdownDay ||
                miner.ended > 0 ||
                miner.auctioned ||
                miner.promiseDays == 0
            ) {
                revert CannotShutdown();
            }

            ShutdownDataCache memory shutdownData =
                _shutdownMiner(miner, owner, minerId, forcedShutdownDay, mintNft);

            if (mintNft && _probability(msg.sender, PHI_NPOW_3, PHI_PRECISION, 0, 0)) {
                _gnftContract.mintNft(msg.sender, 1);
            }

            _mintTokenToOa(owner, minerId, shutdownData.principalToRedistribute,
                shutdownData.rewardsToRedistribute, shutdownData.txPrincipalRewards,
                shutdownData.txPerformanceRewards, miner);
        }
    }

    function _shutdownMiner(
        MinerCache memory miner,
        address owner,
        uint256 minerId,
        uint256 forcedShutdownDay,
        bool mintNft
    ) private returns (ShutdownDataCache memory shutdownData) {
        // Set Miner "ended" to the current time
        minersContract.setMinerEnded(owner, minerId, block.timestamp);
        miner.ended = block.timestamp;
        penaltyContract.decMinerPopulation(miner.principal);
        uint256 lemClaimed = penaltyContract.calcLemClaimed(miner);

        // Before we calculate the rewards, we need to be sure that all
        // SERVED DAYS are Summarized.
        //
        // Then we must make sure all 10-day periods within the SERVED DAYS
        // are also summarized.
        //
        // Then we must make sure all 100-day periods within the SERVED DAYS
        // are summarized.
        //
        // And then, finally, we must make sure that all 1,000-day periods
        // within the SERVED DAYS are summarized.
        calendar.summarizeServedDays(msg.sender, miner.startDay,
            miner.promiseDays, mintNft);
        unchecked {
            uint256 netPrincipal = miner.principal > lemClaimed ? miner.principal - lemClaimed : 0;
            uint256 rewards = miner.rewardShares *
                calendar.minerTotalPps(miner.startDay, miner.startDay + miner.promiseDays - 1, miner.policy)
                / SHARE_PRECISION;
            uint256 netPayout = netPrincipal + rewards;

            // Start Phase EM_04
            _manageShutdownMinerShares(miner, forcedShutdownDay, rewards);
            // End Phase EM_04

            uint256 maxTxRewards = netPayout * PHI_NPOW_3 / PHI_PRECISION;
            shutdownData.txPrincipalRewards = _min(netPrincipal, maxTxRewards);

            if (miner.debtIssueRate > 0) {
                /*
                    Utilities.MinerCache calldata miner,
                    address minerOwner,
                    uint256 minerIndex,
                    address beneficiary,
                    uint256 currentGeniusDay,
                    bool benevolent
                */

                MinerCache memory miner2  = miner;
                bool mintNft2 = mintNft;
                address owner2 = owner;
                uint256 minerId2 = minerId;

                uint256 txSettledRewards = stabilityPoolContract.settleGeniusDebt(
                    msg.sender,
                    stabilityPoolContract.getMinerColAddress(owner2, minerId2),
                    shutdownData.txPrincipalRewards,
                    _currentGeniusDay() - miner2.startDay,
                    mintNft2
                );

                uint256 minerDebtCleared = stabilityPoolContract.clearGeniusDebt(
                    miner2, owner2, minerId2, address(0),
                    _currentGeniusDay(), true);

                shutdownData.txPerformanceRewards = maxTxRewards > txSettledRewards ? maxTxRewards - txSettledRewards : 0;
                shutdownData.txPrincipalRewards -= txSettledRewards;
                // shutdownData.principalToRedistribute = netPrincipal - txSettledRewards - minerDebtCleared -
                // (shutdownData.txPrincipalRewards - txSettledRewards)
                // = netPrincipal - minerDebtCleared - shutdownData.txPrincipalRewards
                // it might be underflow
                uint256 totalSub = txSettledRewards + minerDebtCleared + shutdownData.txPrincipalRewards;
                if (netPrincipal > totalSub) {
                    shutdownData.principalToRedistribute = netPrincipal - totalSub;
                    calendar.increaseBurnedSupply(shutdownData.principalToRedistribute);
                } else {
                    shutdownData.principalToRedistribute = 0;
                }
                shutdownData.rewardsToRedistribute = rewards > shutdownData.txPerformanceRewards ? rewards - shutdownData.txPerformanceRewards : 0;

                if (miner2.lemClaimDay == 0) {
                    if (miner2.policy) {
                        advLockedSupply -= miner2.principal;
                    } else {
                        basicLockedSupply -= miner2.principal;
                    }
                }
            } else { // Debt Issue Rate == 0
                shutdownData.txPerformanceRewards = maxTxRewards > netPrincipal ? maxTxRewards - netPrincipal : 0;
                shutdownData.principalToRedistribute = netPrincipal > shutdownData.txPrincipalRewards ? netPrincipal - shutdownData.txPrincipalRewards : 0;
                shutdownData.rewardsToRedistribute = rewards > shutdownData.txPerformanceRewards ? rewards - shutdownData.txPerformanceRewards : 0;

                if (miner.lemClaimDay == 0)  {
                    calendar.increaseBurnedSupply(miner.principal);
                    if (miner.policy) {
                        advLockedSupply -= miner.principal;
                    } else {
                        basicLockedSupply -= miner.principal;
                    }
                }
            }
        }

    }

    function _mintTokenToOa(
        address owner,
        uint256 minerId,
        uint256 principalToRedistribute,
        uint256 rewardsToRedistribute,
        uint256 txPrincipalRewards,
        uint256 txPerformanceRewards,
        MinerCache memory miner
    ) private {
        unchecked {
            uint256 totalPenalties = principalToRedistribute + rewardsToRedistribute;
            uint256 redistributedPenalties = totalPenalties * PHI_PRECISION / PHI;
            calendar.incDailyPenalties(redistributedPenalties);
            uint256 toOa = totalPenalties - redistributedPenalties - (totalPenalties * PHI_NPOW_3 / PHI_PRECISION);
            uint256 resurrection = toOa + txPrincipalRewards + txPerformanceRewards;

            if (resurrection > 0) {
                calendar.decreaseBurnedSupply(resurrection);
            }

            if (toOa > 0) {
                _mint(oaBeneficiary, toOa);
            }

            // we will not check if txPerf + txPrinc is > 0 because if this is the
            // case, then the miner was likely a stale, "dust" miner with not much
            // principal and likely zero earnings.
            _mint(msg.sender, txPerformanceRewards + txPrincipalRewards);

            emit ShutdownMiner(owner, minerId, msg.sender,
                txPrincipalRewards, txPerformanceRewards,
                redistributedPenalties, toOa, (totalPenalties * PHI_NPOW_3 / PHI_PRECISION),
                miner
            );
        }
    }

    /**
     * @dev INTERNAL, helper function used in shutdownMiner()
     */
    function _manageShutdownMinerShares(
        MinerCache memory miner, uint256 forcedShutdownDay, uint256 rewards
    ) internal {
        if (miner.lemClaimDay == 0) {
            if (!miner.policy) {
                calendar.decBasicShares(miner.rewardShares);
            } else {
                calendar.decAdvShares(miner.rewardShares);
            }
        }
        unchecked {
            calendar.setShareRate(_newShareRate(miner, miner.principal + rewards));
        }
    }

    /**
     * @dev only callable by calendar, mint summary rewards calculated by
     * summarize functions in calendar.
     */
    function mintSummaryReward(address _to, uint256 _amount) external {
        if (msg.sender != calendarAddress) {
            revert ErrorUnauthorized();
        }
        _mint(_to, _amount);
    }

    /**
     * @dev only callable by Penalty contract, advLockedSupply accounting.
     */
    function decAdvLockedSupply(uint256 _amount) external {
        if (msg.sender != penaltyAddress) revert ErrorUnauthorized();
        unchecked { advLockedSupply -= _amount; }
    }

    /**
     * @dev only callable by Penalty contract, basicLockedSupply accounting.
     */
    function decBasicLockedSupply(uint256 _amount) external {
        if (msg.sender != penaltyAddress) revert ErrorUnauthorized();
        unchecked { basicLockedSupply -= _amount; }
    }

    /**
     * @dev only callable by Miners contract, advLockedSupply accounting.
     */
    function incAdvLockedSupply(uint256 _amount) external {
        if (msg.sender != minersAddress) revert ErrorUnauthorized();
        unchecked { advLockedSupply += _amount; }
    }

    /**
     * @dev only callable by Miners contract, basicLockedSupply accounting.
     */
    function incBasicLockedSupply(uint256 _amount) external {
        if (msg.sender != minersAddress) revert ErrorUnauthorized();
        unchecked { basicLockedSupply += _amount; }
    }

    /**
     * @dev only called by the End Miner functionality; this redistributes
     * fees incurrred for ending the miner.
     * @param rewards the performance earnings of the miner.
     * @param principalPenalties penalties applied to the principal.
     * @param rewardPenalties penalties applied to the rewards.
     * @return redistributedPenalties the amount of penalties that will be
     * redistributed to Advanced Miners that are currently active.
     */
    function _redistribution(
        MinerCache memory miner,
        uint256 rewards,
        uint256 principalPenalties,
        uint256 rewardPenalties
    ) internal returns (uint256 redistributedPenalties) {
        unchecked {
            uint256 totalPenalties;
            if (miner.debtIssueRate > 0) {
                totalPenalties = _min(rewards, principalPenalties + rewardPenalties);
                rewardPenalties = totalPenalties;
                principalPenalties = 0;
            } else {
                if (miner.lemClaimDay == 0) {
                    if (miner.policy) {
                        advLockedSupply -= principalPenalties;
                    } else {
                        basicLockedSupply -= principalPenalties;
                    }
                    calendar.increaseBurnedSupply(principalPenalties);
                }
                totalPenalties = principalPenalties + rewardPenalties;
            }

            redistributedPenalties = totalPenalties * PHI_PRECISION / PHI;
            calendar.incDailyPenalties(redistributedPenalties);
            uint256 oaReceivingAmount = totalPenalties - redistributedPenalties
                - totalPenalties * PHI_NPOW_3 / PHI_PRECISION;

            _mint(oaBeneficiary, oaReceivingAmount);
            calendar.decreaseBurnedSupply(oaReceivingAmount);
        }
    }

    /**
     * @dev   Calculates a secure-ish random 256-bit number for GENFTs.
     *        These are the motivations and purposes behind each parameter to
     *        calculate the random number:
     *
     *        1. salt: each function that initially invokes the first
     *           _probability / _random functions will originate with its own
     *           unique 'salt'.  This is to ensure that when multiple functions
     *           are called by the EOA within the same transaction, the EOA will
     *           have equally-random chances to yield a completely different
     *           GENFT.  The block timestamp is added to salt to make it more
     *           difficult for an end user to predict which GENFT they'll mint.
     *
     *        2. blockhash: the only EOAs that can reasonably use this to their
     *           advantage without adding significant costs for the transaction,
     *           such as the capital required to create a miner with a weight of
     *           1 or greater, are EOAs that run the function to "claim" their
     *           sacrifie tokens and EOAs that run the function to summarize
     *           a Genius Calendar period.  That is because these functions have
     *           a 100% chance to mint a GENFT.
     *
     *           However, the "claim" function can only be run once per EOA that
     *           participated in the Genius Sacrifice Event.  Therefore, this
     *           will not be useful for the EOA, even if they have the ability
     *           to influence the block hash.  See: https://sacrifice.to
     *
     *           In regards to the Calendar summarize functions, the EOA cannot
     *           waste time figuring out their best chances because if they are
     *           not the first EOA to run the function, then they lose the
     *           ability to run the function for the day/period.
     *
     *           For every other function, the EOA is prevented from spamming
     *           these functions not only from the blockchain's gas fee, but
     *           spam is additional prevented because every other function
     *           has one of the following qualities:
     *              a. It is a "first-come, first-to-benefit" function, e.g. the
     *                 functions to claimAuction, releaseShares, etc.
     *              b. The function is necessary for "cleaning up" or updating
     *                 Genius' environment, active shares, etc., and therefore,
     *                 the EOA should be rewarded as they wish.
     *              c. The EOA had to have input something of value to the
     *                 network, i.e. they had to put up a significant, non-dust
     *                 amount of GENI capital, which ultimately benefitted the
     *                 Genius end users.
     *
     *           Therefore, if it is worth it for the EOA to exert the position-
     *           ing and effort to influence random numbers for their purpose,
     *           then this action is also not guaranteed, and its repeated
     *           action is designed to benefit the Genius end user.  Since the
     *           purpose of GENFTs is purely as collectibles and *not* for
     *           significant financial value, it is perfectly acceptable for
     *           EOAs to "game" the possibilities of yielding the GENFT that
     *           they desire.
     *
     *        3. account: used so that different EOAs running the same GENFT
     *           minting functions within the same block will not generate the
     *           same GENFTs.  Likewise, if different accounts are unpacking
     *           booster/ultimate packs within the same transaction, this will
     *           ensure that the end users do not unpack the same GENFTs.
     *
     *        Finally, it should be noted that the GENFT controller prevents
     *        EOAs from minting GENFTs with the same randomization salt or
     *        unpacking to mint multiple GENFTs within the same block.  This is
     *        done to prevent the end user from duplicating multiple copies of
     *        the same GENFTs.
     *
     * @param account address used to generate a random number
     * @param salt  when multiple random numbers are necessary, this is used
     *                to add some randomness.  This is important because within
     *                a single transaction, the random number will be exactly
     *                the same without this _salt.
     */
    function _random(address account, uint256 salt) internal view returns (uint256) {
        unchecked {
            return uint256(
                keccak256(
                    abi.encodePacked(
                        salt + block.timestamp,
                        blockhash(block.number),
                        account
                    )
                )
            );
        }
    }

    /**
     * @dev     You tell the function the "probability" that something will
     *          happen, and this function tells you if it happened :)
     * @param   account address used for the calculation
     * @param   chances How many chances of successes will there be out of the entire...
     * @param   totals ...range of precision totals?
     * @param   weight will the weight be based on?  Use "0" for no weight.
     * @param   nonce "nonce" so that if this function is called multiple times
     *          within a transaction, the random number will be different each
     *          time this function is invoked.
     * @return  Whether the probability test was succcessful :)
     */
    function _probability(address account, uint256 chances, uint256 totals, uint256 weight, uint256 nonce)
        internal view returns (bool)
    {
        unchecked {
            // STEP 1: increase the weight of the chances if necessary.
            if (weight > 0) {
                chances = chances * penaltyContract.minerWeight(weight)
                    / PENALTY_COUNTER_PRECISION;
            }

            if (chances >= totals) {
                return true;
            }

            // NOTE: beyond this point, chances < totals, and therefore, it is not
            // possible for chances to be equal to or greater than totals, resulting
            // in an overflow.

            // STEP 2: Find a random number between 0 and the totals.
            uint256 random = _random(account, nonce) % totals;

            // STEP 3: Is the random number within the probability range of chance?
            // The minimum that (totals - chances) will be is 1, so therefore, if
            // the random number is 0, then the return value will be false.  In the
            // situation where this is a "1 in X" chance, "random" must be 0 in
            // order for the logical expression (below) to be true.
            return random >= totals - chances;
        }
    }

}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_oaGrantor","type":"address"},{"internalType":"address","name":"_oaBeneficiary","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CannotShutdown","type":"error"},{"inputs":[],"name":"ErrorCannotReleaseAuctionedShares","type":"error"},{"inputs":[],"name":"ErrorCannotReleaseShares","type":"error"},{"inputs":[],"name":"ErrorNotLaunchedYet","type":"error"},{"inputs":[],"name":"ErrorNullAddress","type":"error"},{"inputs":[],"name":"ErrorUnauthorized","type":"error"},{"inputs":[],"name":"NoClaimExists","type":"error"},{"inputs":[],"name":"UnauthorizedLostBonusClaiming","type":"error"},{"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":false,"internalType":"address","name":"newOaBeneficiary","type":"address"},{"indexed":false,"internalType":"uint256","name":"updated","type":"uint256"}],"name":"ChangeOaBeneficiary","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOaGrantor","type":"address"},{"indexed":false,"internalType":"uint256","name":"updated","type":"uint256"}],"name":"ChangeOaGrantor","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"claimant","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Claim","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"minerIndex","type":"uint256"},{"indexed":false,"internalType":"bool","name":"benevolence","type":"bool"},{"indexed":false,"internalType":"uint256","name":"principalPayout","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalMinerRewards","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rewardsPayout","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"penaltyToMiners","type":"uint256"},{"components":[{"internalType":"bool","name":"policy","type":"bool"},{"internalType":"bool","name":"auctioned","type":"bool"},{"internalType":"bool","name":"exodus","type":"bool"},{"internalType":"uint256","name":"startDay","type":"uint256"},{"internalType":"uint256","name":"promiseDays","type":"uint256"},{"internalType":"uint256","name":"lemClaimDay","type":"uint256"},{"internalType":"uint256","name":"rewardShares","type":"uint256"},{"internalType":"uint256","name":"penaltyDelta","type":"uint256"},{"internalType":"bool","name":"nonTransferable","type":"bool"},{"internalType":"uint256","name":"ended","type":"uint256"},{"internalType":"uint256","name":"principal","type":"uint256"},{"internalType":"uint256","name":"debtIssueRate","type":"uint256"}],"indexed":false,"internalType":"struct Utilities.MinerCache","name":"miner","type":"tuple"}],"name":"EndMiner","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"executorRewardAddress","type":"address"},{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"minerIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"executorReward","type":"uint256"}],"name":"LemRewardsClaim","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"minerAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"minerIndex","type":"uint256"},{"indexed":true,"internalType":"address","name":"executorRewardAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"executorReward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"performanceRewards","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"redistributedPenalties","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toOa","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"burnedForever","type":"uint256"},{"components":[{"internalType":"bool","name":"policy","type":"bool"},{"internalType":"bool","name":"auctioned","type":"bool"},{"internalType":"bool","name":"exodus","type":"bool"},{"internalType":"uint256","name":"startDay","type":"uint256"},{"internalType":"uint256","name":"promiseDays","type":"uint256"},{"internalType":"uint256","name":"lemClaimDay","type":"uint256"},{"internalType":"uint256","name":"rewardShares","type":"uint256"},{"internalType":"uint256","name":"penaltyDelta","type":"uint256"},{"internalType":"bool","name":"nonTransferable","type":"bool"},{"internalType":"uint256","name":"ended","type":"uint256"},{"internalType":"uint256","name":"principal","type":"uint256"},{"internalType":"uint256","name":"debtIssueRate","type":"uint256"}],"indexed":false,"internalType":"struct Utilities.MinerCache","name":"miner","type":"tuple"}],"name":"ShutdownMiner","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"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LAUNCH_TIMESTAMP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"advLockedSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":[],"name":"auctionAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"basicLockedSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"calendarAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"destination","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"name":"canClaim","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_oaBeneficiary","type":"address"}],"name":"changeOaBeneficiary","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newOaGrantor","type":"address"}],"name":"changeOaGrantor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"destination","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"},{"internalType":"bool","name":"mintNft","type":"bool"}],"name":"claimGenius","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimLostMintBonus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"claimed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"decAdvLockedSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"decBasicLockedSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"minerIndex","type":"uint256"},{"internalType":"bool","name":"benevolence","type":"bool"},{"internalType":"bool","name":"mintNft","type":"bool"}],"name":"endMiner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"gnftAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hexodusAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"incAdvLockedSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"incBasicLockedSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"bonusLostForever","type":"uint256"}],"name":"incOaMintableBalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"minersAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mintSummaryReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oaBeneficiary","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oaGrantor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oaMintableBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"penaltyAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"minerId","type":"uint256"},{"internalType":"bool","name":"mintNft","type":"bool"}],"name":"releaseShares","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"reserveSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_auction","type":"address"}],"name":"setAuctionContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_calendar","type":"address"}],"name":"setCalendarContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_gnftAddress","type":"address"}],"name":"setGnftContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_hexodus","type":"address"}],"name":"setHexodusContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_minersAddress","type":"address"}],"name":"setMinersContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pcAddress","type":"address"}],"name":"setPenaltyContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_stabilityPool","type":"address"}],"name":"setStabilityPoolAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"minerId","type":"uint256"},{"internalType":"bool","name":"mintNft","type":"bool"}],"name":"shutdownMiner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stabilityPoolAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]

6101406040523480156200001257600080fd5b50604051620062a1380380620062a18339810160408190526200003591620003ab565b6040518060400160405280600681526020016547656e69757360d01b81525080604051806040016040528060018152602001603160f81b8152506040518060400160405280600681526020016547656e69757360d01b8152506040518060400160405280600481526020016347454e4960e01b8152508160039080519060200190620000c3929190620002e8565b508051620000d9906004906020840190620002e8565b5050825160208085019190912083518483012060e08290526101008190524660a0818152604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81880181905281830187905260608201869052608082019490945230818401528151808203909301835260c0019052805194019390932091935091906080523060601b60c0526101205250506001601a555050506001600160a01b03821615806200019457506001600160a01b038116155b15620001b3576040516342bec4df60e01b815260040160405180910390fd5b601680546001600160a01b038085166001600160a01b0319928316179092556017805492841692909116919091179055620001f830680d02ab486cedc0000062000200565b505062000444565b6001600160a01b0382166200025b5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640160405180910390fd5b80600260008282546200026f9190620003e2565b90915550506001600160a01b038216600090815260208190526040812080548392906200029e908490620003e2565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b828054620002f69062000407565b90600052602060002090601f0160209004810192826200031a576000855562000365565b82601f106200033557805160ff191683800117855562000365565b8280016001018555821562000365579182015b828111156200036557825182559160200191906001019062000348565b506200037392915062000377565b5090565b5b8082111562000373576000815560010162000378565b80516001600160a01b0381168114620003a657600080fd5b919050565b60008060408385031215620003be578182fd5b620003c9836200038e565b9150620003d9602084016200038e565b90509250929050565b600082198211156200040257634e487b7160e01b81526011600452602481fd5b500190565b600181811c908216806200041c57607f821691505b602082108114156200043e57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160601c60e0516101005161012051615e0a6200049760003960006134a9015260006134f8015260006134d30152600061342c01526000613456015260006134800152615e0a6000f3fe608060405234801561001057600080fd5b506004361061030c5760003560e01c806360f1edf71161019d578063a9059cbb116100e9578063d505accf116100a2578063dfcad7ea1161007c578063dfcad7ea146106ad578063e09f0817146106c0578063e954f41d146106d3578063e9c4239b146106de57600080fd5b8063d505accf14610674578063dc38bdb514610687578063dd62ed3e1461069a57600080fd5b8063a9059cbb146105f2578063ad09d65814610605578063b074d2f614610618578063c884ef831461062b578063cb01454b1461064e578063d11d01db1461066157600080fd5b806376df7c321161015657806395d89b411161013057806395d89b41146105b157806396cc563f146105b95780639dc29fac146105cc578063a457c2d7146105df57600080fd5b806376df7c32146105785780637ecebe001461058b578063873f0a331461059e57600080fd5b806360f1edf7146104f057806360f6c4d61461050357806363fcd08a146105165780636f72995f1461052957806370a082311461053c57806372fb9c551461056557600080fd5b806323b872dd1161025c578063379b2c1311610215578063445c101f116101ef578063445c101f146104ae5780634bd0cd42146104b75780635476ea9e146104ca57806357ec85dd146104dd57600080fd5b8063379b2c1314610475578063395093511461048857806340c10f191461049b57600080fd5b806323b872dd1461041c578063269858651461042f5780632c265c88146104425780632ceaaf281461044b578063313ce5671461045e5780633644e5151461046d57600080fd5b80630c6eae62116102c9578063197162be116102a3578063197162be146103e55780631ad03156146103f85780631bf803391461040b578063238bf8e01461041457600080fd5b80630c6eae62146103b757806315df1fca146103ca57806318160ddd146103dd57600080fd5b8063023924c71461031157806303d41eb61461032657806306fdde0314610341578063095ea7b314610356578063096ff58a146103795780630b622ab21461038c575b600080fd5b61032461031f36600461562d565b6106f1565b005b61032e6107c7565b6040519081526020015b60405180910390f35b610349610860565b6040516103389190615b18565b610369610364366004615752565b6108f2565b6040519015158152602001610338565b61032461038736600461562d565b61090c565b60095461039f906001600160a01b031681565b6040516001600160a01b039091168152602001610338565b6103246103c536600461562d565b610ae6565b60115461039f906001600160a01b031681565b60025461032e565b6103246103f33660046159e0565b610bea565b600d5461039f906001600160a01b031681565b61032e60075481565b610324610c21565b61036961042a36600461569d565b610cc1565b61032461043d3660046157d7565b610ce5565b61032e60085481565b60165461039f906001600160a01b031681565b60405160098152602001610338565b61032e6110c4565b60135461039f906001600160a01b031681565b610369610496366004615752565b6110d3565b6103246104a9366004615752565b6110f5565b61032e60195481565b6103246104c536600461562d565b61112e565b600b5461039f906001600160a01b031681565b6103246104eb366004615a10565b6112f0565b6103246104fe36600461562d565b611a95565b61032461051136600461562d565b611b8e565b60175461039f906001600160a01b031681565b61032461053736600461562d565b611c33565b61032e61054a36600461562d565b6001600160a01b031660009081526020819052604090205490565b6103246105733660046159e0565b611d44565b6103246105863660046159e0565b611d7a565b61032e61059936600461562d565b611dbf565b60145461039f906001600160a01b031681565b610349611ddd565b6103246105c736600461562d565b611dec565b6103246105da366004615752565b611f4f565b6103696105ed366004615752565b611fcb565b610369610600366004615752565b612046565b61032461061336600461562d565b612054565b600f5461039f906001600160a01b031681565b61036961063936600461562d565b60186020526000908152604090205460ff1681565b61032461065c3660046159e0565b6120d1565b61032461066f366004615849565b612107565b6103246106823660046156dd565b61230b565b61036961069536600461577d565b61246f565b61032e6106a8366004615665565b612541565b6103246106bb366004615752565b61256c565b6103246106ce3660046159e0565b612597565b61032e636398e41681565b6103246106ec366004615849565b6125ce565b6001600160a01b038116610718576040516342bec4df60e01b815260040160405180910390fd5b600b546001600160a01b03161561074257604051631d0b184b60e21b815260040160405180910390fd5b600b80546001600160a01b038381166001600160a01b03199283168117909355600c80549092168317909155600a5460405163023924c760e01b81526004810193909352169063023924c7906024015b600060405180830381600087803b1580156107ac57600080fd5b505af11580156107c0573d6000803e3d6000fd5b5050505050565b6000600854600754600e60009054906101000a90046001600160a01b03166001600160a01b03166355d0a1d06040518163ffffffff1660e01b815260040160206040518083038186803b15801561081d57600080fd5b505afa158015610831573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061085591906159f8565b600254010101905090565b60606003805461086f90615d4b565b80601f016020809104026020016040519081016040528092919081815260200182805461089b90615d4b565b80156108e85780601f106108bd576101008083540402835291602001916108e8565b820191906000526020600020905b8154815290600101906020018083116108cb57829003601f168201915b5050505050905090565b600033610900818585612ea5565b60019150505b92915050565b6001600160a01b038116610933576040516342bec4df60e01b815260040160405180910390fd5b6016546001600160a01b03163314158061095757506014546001600160a01b031615155b1561097557604051631d0b184b60e21b815260040160405180910390fd5b601480546001600160a01b038381166001600160a01b03199283168117909355601580549092168317909155600c546040516304b7fac560e11b81526004810193909352169063096ff58a90602401600060405180830381600087803b1580156109de57600080fd5b505af11580156109f2573d6000803e3d6000fd5b5050600e546040516304b7fac560e11b81526001600160a01b038581166004830152909116925063096ff58a9150602401600060405180830381600087803b158015610a3d57600080fd5b505af1158015610a51573d6000803e3d6000fd5b50506012546040516304b7fac560e11b81526001600160a01b038581166004830152909116925063096ff58a9150602401600060405180830381600087803b158015610a9c57600080fd5b505af1158015610ab0573d6000803e3d6000fd5b5050600a546040516304b7fac560e11b81526001600160a01b038581166004830152909116925063096ff58a9150602401610792565b6001600160a01b038116610b0d576040516342bec4df60e01b815260040160405180910390fd5b6016546001600160a01b03163314610b3857604051631d0b184b60e21b815260040160405180910390fd5b601780546001600160a01b0319166001600160a01b03838116918217909255600a54604051637827d56160e01b8152600481019290925290911690637827d56190602401600060405180830381600087803b158015610b9657600080fd5b505af1158015610baa573d6000803e3d6000fd5b505050507fdd475012ca9bbf511d7eb2d3c4f7709ade7f0e3910b847b5dcda58b16684d7518142604051610bdf929190615ade565b60405180910390a150565b600f546001600160a01b03163314610c1557604051631d0b184b60e21b815260040160405180910390fd5b60078054919091039055565b6002601a541415610c4d5760405162461bcd60e51b8152600401610c4490615b6b565b60405180910390fd5b6002601a556016546001600160a01b031633141580610c7357506020610c71612fca565b105b80610c7e5750601954155b15610c9c576040516390172c2b60e01b815260040160405180910390fd5b601754601954610cb5916001600160a01b031690613002565b60006019556001601a55565b600033610ccf8582856130e1565b610cda85858561315b565b506001949350505050565b6002601a541415610d085760405162461bcd60e51b8152600401610c4490615b6b565b6002601a55610d198585858561246f565b610d3657604051633d9a544f60e21b815260040160405180910390fd5b6001600160a01b0385166000818152601860205260409020805460ff19166001179055331480610d6d575060b5610d6b612fca565b105b80610da25750636398e41642108015610da257506001600160a01b0385167366eca275200015dcd0c2eaa6e48d4eed3092cdd6145b15610ed95760405163a9059cbb60e01b8152309063a9059cbb90610dcc9088908890600401615ade565b602060405180830381600087803b158015610de657600080fd5b505af1158015610dfa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1e919061588a565b508015610e8b5760155460405163d1194e2b60e01b81526001600160a01b039091169063d1194e2b90610e58908890600090600401615ade565b600060405180830381600087803b158015610e7257600080fd5b505af1158015610e86573d6000803e3d6000fd5b505050505b604080513381526001600160a01b03871660208201529081018590527f70eb43c4a8ae8c40502dcf22436c509c28d6ff421cf07c491be56984bd9870689060600160405180910390a16110b8565b808015610f065750610f06336b013bf472f5ed1d56574ec0ad676765c793fa10079d601b1b600080613329565b15610f715760155460405163d1194e2b60e01b81526001600160a01b039091169063d1194e2b90610f3e903390600190600401615ade565b600060405180830381600087803b158015610f5857600080fd5b505af1158015610f6c573d6000803e3d6000fd5b505050505b60405163a9059cbb60e01b8152309063a9059cbb90610f9b90339064174876e80090600401615ade565b602060405180830381600087803b158015610fb557600080fd5b505af1158015610fc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fed919061588a565b5060405163a9059cbb60e01b8152309063a9059cbb9061101b90889064174876e7ff19890190600401615ade565b602060405180830381600087803b15801561103557600080fd5b505af1158015611049573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061106d919061588a565b50604080513381526001600160a01b03871660208201529081018590527f70eb43c4a8ae8c40502dcf22436c509c28d6ff421cf07c491be56984bd9870689060600160405180910390a15b50506001601a55505050565b60006110ce61341f565b905090565b6000336109008185856110e68383612541565b6110f09190615d1c565b612ea5565b600b546001600160a01b0316331461112057604051631d0b184b60e21b815260040160405180910390fd5b61112a8282613002565b5050565b6001600160a01b038116611155576040516342bec4df60e01b815260040160405180910390fd5b6011546001600160a01b03161561117f57604051631d0b184b60e21b815260040160405180910390fd5b601180546001600160a01b038381166001600160a01b03199283168117909355601280549092168317909155600c546040516325e866a160e11b815260048101939093521690634bd0cd4290602401600060405180830381600087803b1580156111e857600080fd5b505af11580156111fc573d6000803e3d6000fd5b5050600e546040516325e866a160e11b81526001600160a01b0385811660048301529091169250634bd0cd429150602401600060405180830381600087803b15801561124757600080fd5b505af115801561125b573d6000803e3d6000fd5b5050600a546040516325e866a160e11b81526001600160a01b0385811660048301529091169250634bd0cd429150602401600060405180830381600087803b1580156112a657600080fd5b505af11580156112ba573d6000803e3d6000fd5b50506010546040516325e866a160e11b81526001600160a01b0385811660048301529091169250634bd0cd429150602401610792565b6002601a5414156113135760405162461bcd60e51b8152600401610c4490615b6b565b6002601a55601254604051631f11d95360e01b81526000916001600160a01b031690631f11d9539061134b9033908890600401615ade565b6101806040518083038186803b15801561136457600080fd5b505afa158015611378573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139c91906158a6565b905060006113a8612fca565b60608301516080840151919250600091810183106113d05783608001518460600151016113d2565b825b60125460405163f139dfb760e01b81529290910392506001600160a01b03169063f139dfb79061140e90869033908b9088908890600401615bfc565b600060405180830381600087803b15801561142857600080fd5b505af115801561143c573d6000803e3d6000fd5b5050505060006001600e60009054906101000a90046001600160a01b03166001600160a01b0316630f90e0076040518163ffffffff1660e01b815260040160206040518083038186803b15801561149257600080fd5b505afa1580156114a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ca91906159f8565b03905083608001518210806114ec575082846080015185606001510160070111155b1561171657600e546040516348d62c6d60e11b81526001600160a01b03909116906391ac58da906115269060009033908a90600401615af7565b602060405180830381600087803b15801561154057600080fd5b505af1158015611554573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157891906159f8565b50600e54604051633b30762f60e11b81526001600160a01b0390911690637660ec5e906115ae9060009033908a90600401615af7565b602060405180830381600087803b1580156115c857600080fd5b505af11580156115dc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061160091906159f8565b50600e5460405163ab18a02760e01b81526001600160a01b039091169063ab18a027906116369060009033908a90600401615af7565b602060405180830381600087803b15801561165057600080fd5b505af1158015611664573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061168891906159f8565b50600e54604051637c6d493160e11b81526001600160a01b039091169063f8da9262906116be9060009033908a90600401615af7565b602060405180830381600087803b1580156116d857600080fd5b505af11580156116ec573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061171091906159f8565b5061194e565b6060840151820160001901818111156117b357600e546040516348d62c6d60e11b81526001600160a01b03909116906391ac58da9061175f908585039033908b90600401615af7565b602060405180830381600087803b15801561177957600080fd5b505af115801561178d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117b191906159f8565b505b600e546001600160a01b0316637660ec5e600a830433896040518463ffffffff1660e01b81526004016117e893929190615af7565b602060405180830381600087803b15801561180257600080fd5b505af1158015611816573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061183a91906159f8565b50600e546001600160a01b031663ab18a0276064830433896040518463ffffffff1660e01b815260040161187093929190615af7565b602060405180830381600087803b15801561188a57600080fd5b505af115801561189e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118c291906159f8565b50600e546001600160a01b031663f8da92626103e8830433896040518463ffffffff1660e01b81526004016118f993929190615af7565b602060405180830381600087803b15801561191357600080fd5b505af1158015611927573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061194b91906159f8565b50505b600e5460608501518551604051634c29019760e11b815260048101839052918501600019016024830152151560448201526000916001600160a01b031690639852032e9060640160206040518083038186803b1580156119ad57600080fd5b505afa1580156119c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119e591906159f8565b90506000670de0b6b3a7640000828760c001510281611a1457634e487b7160e01b600052601260045260246000fd5b0490506000806000611a29338d868e8e613546565b9250925092506000899050336001600160a01b03167fe16ef2c5ff376e78191b54a217db16e2ca4eca7cb451d282f7dd8a75c492df498e8e8789888888604051611a799796959493929190615c68565b60405180910390a250506001601a555050505050505050505050565b6001600160a01b038116611abc576040516342bec4df60e01b815260040160405180910390fd5b6016546001600160a01b03163314611ae757604051631d0b184b60e21b815260040160405180910390fd5b601680546001600160a01b0319166001600160a01b03838116918217909255600a54604051637e98d42960e11b815260048101929092529091169063fd31a85290602401600060405180830381600087803b158015611b4557600080fd5b505af1158015611b59573d6000803e3d6000fd5b505050507fd535651a5590e21c663adfebb2eb6431447c10dccf3eee90c4c4d8bf7983c14a8142604051610bdf929190615ade565b6001600160a01b038116611bb5576040516342bec4df60e01b815260040160405180910390fd5b600d546001600160a01b031615611bdf57604051631d0b184b60e21b815260040160405180910390fd5b600d80546001600160a01b038381166001600160a01b03199283168117909355600e80549092168317909155600c5460405163307b626b60e11b8152600481019390935216906360f6c4d690602401610792565b6001600160a01b038116611c5a576040516342bec4df60e01b815260040160405180910390fd5b6016546001600160a01b031633141580611c7e57506013546001600160a01b031615155b15611c9c57604051631d0b184b60e21b815260040160405180910390fd5b601380546001600160a01b0319166001600160a01b03838116918217909255601254604051636f72995f60e01b8152600481019290925290911690636f72995f90602401600060405180830381600087803b158015611cfa57600080fd5b505af1158015611d0e573d6000803e3d6000fd5b5050600e54604051636f72995f60e01b81526001600160a01b0385811660048301529091169250636f72995f9150602401610792565b6011546001600160a01b03163314611d6f57604051631d0b184b60e21b815260040160405180910390fd5b600780549091019055565b6011546001600160a01b03163314611da557604051631d0b184b60e21b815260040160405180910390fd5b8060196000828254611db79190615d1c565b909155505050565b6001600160a01b038116600090815260056020526040812054610906565b60606004805461086f90615d4b565b6001600160a01b038116611e13576040516342bec4df60e01b815260040160405180910390fd5b600f546001600160a01b031615611e3d57604051631d0b184b60e21b815260040160405180910390fd5b601080546001600160a01b038381166001600160a01b03199283168117909355600f80549092168317909155600e546040516396cc563f60e01b8152600481019390935216906396cc563f90602401600060405180830381600087803b158015611ea657600080fd5b505af1158015611eba573d6000803e3d6000fd5b5050600a546040516396cc563f60e01b81526001600160a01b03858116600483015290911692506396cc563f9150602401600060405180830381600087803b158015611f0557600080fd5b505af1158015611f19573d6000803e3d6000fd5b5050600c54604051632e8098c560e01b81526001600160a01b0385811660048301529091169250632e8098c59150602401610792565b6009546001600160a01b03163314801590611f755750600b546001600160a01b03163314155b8015611f8c57506011546001600160a01b03163314155b8015611fa357506013546001600160a01b03163314155b15611fc157604051631d0b184b60e21b815260040160405180910390fd5b61112a8282613c21565b60003381611fd98286612541565b9050838110156120395760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610c44565b610cda8286868403612ea5565b60003361090081858561315b565b6001600160a01b03811661207b576040516342bec4df60e01b815260040160405180910390fd5b6009546001600160a01b0316156120a557604051631d0b184b60e21b815260040160405180910390fd5b600980546001600160a01b039092166001600160a01b03199283168117909155600a8054909216179055565b6011546001600160a01b031633146120fc57604051631d0b184b60e21b815260040160405180910390fd5b600880549091019055565b6002601a54141561212a5760405162461bcd60e51b8152600401610c4490615b6b565b6002601a55601254604051631f11d95360e01b81526000916001600160a01b031690631f11d953906121629087908790600401615ade565b6101806040518083038186803b15801561217b57600080fd5b505afa15801561218f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121b391906158a6565b9050600081600001516121d45781608001518260600151016101b8016121e4565b8160800151826060015101610113015b9050806121ef612fca565b108061220057506000826101200151115b8061220c575081602001515b8061221957506080820151155b156122375760405163270b039d60e21b815260040160405180910390fd5b60006122468387878588613d67565b90508380156122745750612274336ac34556b3f6459039627ea4676765c793fa10079d601b1b600080613329565b156122df5760155460405163d1194e2b60e01b81526001600160a01b039091169063d1194e2b906122ac903390600190600401615ade565b600060405180830381600087803b1580156122c657600080fd5b505af11580156122da573d6000803e3d6000fd5b505050505b6122fe868683600001518460200151856040015186606001518961447c565b50506001601a5550505050565b8342111561235b5760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e650000006044820152606401610c44565b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c988888861238a8c614643565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e00160405160208183030381529060405280519060200120905060006123e58261466b565b905060006123f5828787876146b9565b9050896001600160a01b0316816001600160a01b0316146124585760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e617475726500006044820152606401610c44565b6124638a8a8a612ea5565b50505050505050505050565b6040516bffffffffffffffffffffffff19606086901b16602082015260348101849052600090819060540160408051601f1981840301815291815281516020928301206001600160a01b0389166000908152601890935291205490915060ff1615801561253757506125378484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507fcad71776a60b1a4ca80bfa5452bfc50beeb645b7f64e97f5c464ef45a41d548d92508591506146e19050565b9695505050505050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b600d546001600160a01b0316331461112057604051631d0b184b60e21b815260040160405180910390fd5b600f546001600160a01b031633146125c257604051631d0b184b60e21b815260040160405180910390fd5b60088054919091039055565b6002601a5414156125f15760405162461bcd60e51b8152600401610c4490615b6b565b6002601a55601254604051631f11d95360e01b81526000916001600160a01b031690631f11d953906126299087908790600401615ade565b6101806040518083038186803b15801561264257600080fd5b505afa158015612656573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061267a91906158a6565b60808101516060820151919250016000612692612fca565b9050826020015180156126a757508261010001515b156126c557604051635ad8888f60e01b815260040160405180910390fd5b600083610120015111806126dd575060008360a00151115b806126e757508181105b806126f457506080830151155b15612712576040516301ddf13b60e61b815260040160405180910390fd5b601254604051632fd96bfd60e11b81526001600160a01b038881166004830152602482018890526044820184905290911690635fb2d7fa90606401600060405180830381600087803b15801561276757600080fd5b505af115801561277b573d6000803e3d6000fd5b50505050600083600001511561281e57676765c793fa10079d601b1b6127fb606460076b08759642e984636060b13f5288610140015102816127cd57634e487b7160e01b600052601260045260246000fd5b04816127e957634e487b7160e01b600052601260045260246000fd5b04676765c793fa10079d601b1b6146f7565b8161281657634e487b7160e01b600052601260045260246000fd5b04905061287f565b676765c793fa10079d601b1b612860606460076b053a680649b3e32378b13f5288610140015102816127cd57634e487b7160e01b600052601260045260246000fd5b8161287b57634e487b7160e01b600052601260045260246000fd5b0490505b6101408401516000906128b4906128968185614751565b8660070186116128a75760006128ae565b6007878703035b02614751565b90508460200151156129ae57600c546040516303f9f6f560e61b81526001600160a01b039091169063fe7dbd40906128f2908b908b90600401615ade565b602060405180830381600087803b15801561290c57600080fd5b505af1158015612920573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612944919061588a565b156129ae57600c546040516342cdcbff60e11b81526001600160a01b039091169063859b97fe9061297b908b908b90600401615ade565b600060405180830381600087803b15801561299557600080fd5b505af11580156129a9573d6000803e3d6000fd5b505050505b600e5460408051630f90e00760e01b815290516000926001600160a01b031691630f90e007916004808301926020929190829003018186803b1580156129f357600080fd5b505afa158015612a07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a2b91906159f8565b90508560600151600101811015612acf57600e5460608701516040516348d62c6d60e11b81526001600160a01b03909216916391ac58da91612a7b91908590036001019033908c90600401615af7565b602060405180830381600087803b158015612a9557600080fd5b505af1158015612aa9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612acd91906159f8565b505b855115612b545761014086015160078054919091039055600e5460c08701516040516310d6833b60e31b81526001600160a01b03909216916386b419d891612b1d9160040190815260200190565b600060405180830381600087803b158015612b3757600080fd5b505af1158015612b4b573d6000803e3d6000fd5b50505050612bce565b61014086015160088054919091039055600e5460c0870151604051633f9d44fd60e01b81526001600160a01b0390921691633f9d44fd91612b9b9160040190815260200190565b600060405180830381600087803b158015612bb557600080fd5b505af1158015612bc9573d6000803e3d6000fd5b505050505b61016086015160009015612d1d578215612d1857600a546040516317858ab160e31b81526000916001600160a01b03169063bc2c558890612c15908e908e90600401615ade565b602060405180830381600087803b158015612c2f57600080fd5b505af1158015612c43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c679190615649565b600a5460608a0151604051631898636d60e31b81523360048201526001600160a01b03808516602483015260448201899052918a03606482015260006084820152929350169063c4c31b689060a401602060405180830381600087803b158015612cd057600080fd5b505af1158015612ce4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d0891906159f8565b9150612d148285614751565b9350505b612db1565b600e546101408801516001600160a01b0390911690631ce2ed86908510612d45576000612d4e565b84896101400151035b6040518263ffffffff1660e01b8152600401612d6c91815260200190565b600060405180830381600087803b158015612d8657600080fd5b505af1158015612d9a573d6000803e3d6000fd5b505050506000831115612db157612db13384613002565b878015612ddd5750612ddd336ac34556b3f6459039627ea4676765c793fa10079d601b1b600080613329565b15612e485760155460405163d1194e2b60e01b81526001600160a01b039091169063d1194e2b90612e15903390600190600401615ade565b600060405180830381600087803b158015612e2f57600080fd5b505af1158015612e43573d6000803e3d6000fd5b505050505b604080516001600160a01b038c168152602081018b905290810184905233907f0d6b33a90fd9ff440fc1c724f3f3d492e7c2fc1c629b5a8aacf5c76c2ecbcdbe9060600160405180910390a250506001601a555050505050505050565b6001600160a01b038316612f075760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610c44565b6001600160a01b038216612f685760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610c44565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6000636398e416421015612ff157604051633c109e6160e11b815260040160405180910390fd5b506201518042636398e41519010490565b6001600160a01b0382166130585760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610c44565b806002600082825461306a9190615d1c565b90915550506001600160a01b03821660009081526020819052604081208054839290613097908490615d1c565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b60006130ed8484612541565b9050600019811461315557818110156131485760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610c44565b6131558484848403612ea5565b50505050565b6001600160a01b0383166131bf5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610c44565b6001600160a01b0382166132215760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610c44565b6001600160a01b038316600090815260208190526040902054818110156132995760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610c44565b6001600160a01b038085166000908152602081905260408082208585039055918516815290812080548492906132d0908490615d1c565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161331c91815260200190565b60405180910390a3613155565b600082156133d357601054604051631f8ee6fb60e11b81526004810185905264e8d4a51000916001600160a01b031690633f1dcdf69060240160206040518083038186803b15801561337a57600080fd5b505afa15801561338e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133b291906159f8565b8602816133cf57634e487b7160e01b600052601260045260246000fd5b0494505b8385106133e257506001613416565b6000846133ef8885614769565b8161340a57634e487b7160e01b600052601260045260246000fd5b87870391900610159150505b95945050505050565b6000306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614801561347857507f000000000000000000000000000000000000000000000000000000000000000046145b156134a257507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b601254604051631f11d95360e01b81526000918291829182916001600160a01b0390911690631f11d95390613581908c908c90600401615ade565b6101806040518083038186803b15801561359a57600080fd5b505afa1580156135ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135d291906158a6565b905060006135de612fca565b6060830151608084015191925060009181018310613606578360800151846060015101613608565b825b0390506000601060009054906101000a90046001600160a01b03166001600160a01b031663e4c2a4d68584868e6040518563ffffffff1660e01b81526004016136549493929190615c3b565b60c060405180830381600087803b15801561366e57600080fd5b505af1158015613682573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136a6919061595b565b905083608001518210156137fe576136c8848b836020015184600001516147c5565b945087156137f95761372c8c85600001516136e45760646136e7565b600a5b60ff166b053a680649b3e32378b13f528161371257634e487b7160e01b600052601260045260246000fd5b04676765c793fa10079d601b1b8761014001516000613329565b1561379b5760155460405163d1194e2b60e01b81526001600160a01b039091169063d1194e2b90613764908f90600190600401615ade565b600060405180830381600087803b15801561377e57600080fd5b505af1158015613792573d6000803e3d6000fd5b50505050613b9f565b8880156137c157506137c18c676765c793fa10079d601b1b808761014001516002613329565b156137f95760155460405163d1194e2b60e01b81526001600160a01b039091169063d1194e2b90613764908f90600190600401615ade565b613b9f565b83608001518460600151016007018311156139c757613827848b836080015184606001516147c5565b945087156137f957600089156138e4576138648d600a6b053a680649b3e32378b13f5204676765c793fa10079d601b1b886101400151600a613329565b156138e457601560009054906101000a90046001600160a01b03166001600160a01b031663d1194e2b8e600b6040518363ffffffff1660e01b81526004016138ad929190615ade565b600060405180830381600087803b1580156138c757600080fd5b505af11580156138db573d6000803e3d6000fd5b50505050600190505b806139c1576139458d86600001516138fd576064613900565b600a5b60ff166b053a680649b3e32378b13f528161392b57634e487b7160e01b600052601260045260246000fd5b04676765c793fa10079d601b1b8861014001516000613329565b156139c157601560009054906101000a90046001600160a01b03166001600160a01b031663d1194e2b8e60016040518363ffffffff1660e01b815260040161398e929190615ade565b600060405180830381600087803b1580156139a857600080fd5b505af11580156139bc573d6000803e3d6000fd5b505050505b50613b9f565b8715613b9f57605984608001511115613abe576139f88c676765c793fa10079d601b1b808761014001516000613329565b15613a635760155460405163d1194e2b60e01b81526001600160a01b039091169063d1194e2b90613a30908f90600190600401615ade565b600060405180830381600087803b158015613a4a57600080fd5b505af1158015613a5e573d6000803e3d6000fd5b505050505b88156137f957613a878c676765c793fa10079d601b1b808761014001516003613329565b156137f95760155460405163d1194e2b60e01b81526001600160a01b039091169063d1194e2b90613764908f906004908101615ade565b613ad68c60646b053a680649b3e32378b13f52613712565b15613b0e5760155460405163d1194e2b60e01b81526001600160a01b039091169063d1194e2b90613764908f90600190600401615ade565b888015613b345750613b348c676765c793fa10079d601b1b808761014001516014613329565b15613b9f5760155460405163d1194e2b60e01b81526001600160a01b039091169063d1194e2b90613b6c908f90600190600401615ade565b600060405180830381600087803b158015613b8657600080fd5b505af1158015613b9a573d6000803e3d6000fd5b505050505b613bb4848483604001518460a001518e6149b6565b61016084015115613be057613bd6848d8d8d856080015186606001518f614b3f565b9097509550613c12565b60008a905060008a9050613c0a868f85602001518660800151876000015188606001518888614c61565b909950975050505b50505050955095509592505050565b6001600160a01b038216613c815760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610c44565b6001600160a01b03821660009081526020819052604090205481811015613cf55760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610c44565b6001600160a01b0383166000908152602081905260408120838303905560028054849290613d24908490615d34565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612fbd565b613d926040518060800160405280600081526020016000815260200160008152602001600081525090565b6012546040516365892b4960e01b81526001600160a01b03878116600483015260248201879052426044830152909116906365892b4990606401600060405180830381600087803b158015613de657600080fd5b505af1158015613dfa573d6000803e3d6000fd5b50504261012089015250506010546101408701516040516336a34f2760e01b81526001600160a01b03909216916336a34f2791613e3d9160040190815260200190565b600060405180830381600087803b158015613e5757600080fd5b505af1158015613e6b573d6000803e3d6000fd5b50506010546040516303e2f69160e11b8152600093506001600160a01b0390911691506307c5ed2290613ea2908a90600401615ba2565b60206040518083038186803b158015613eba57600080fd5b505afa158015613ece573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ef291906159f8565b600e54606089015160808a0151604051635d070d7f60e11b81523360048201526024810192909252604482015285151560648201529192506001600160a01b03169063ba0e1afe90608401600060405180830381600087803b158015613f5757600080fd5b505af1158015613f6b573d6000803e3d6000fd5b5050505060008188610140015111613f84576000613f8d565b81886101400151035b600e5460608a015160808b01518b51604051634c29019760e11b815260048101849052919092016000190160248201529015156044820152919250600091670de0b6b3a7640000916001600160a01b031690639852032e9060640160206040518083038186803b15801561400057600080fd5b505afa158015614014573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061403891906159f8565b8a60c00151028161405957634e487b7160e01b600052601260045260246000fd5b04905081810161406a8a8884614f26565b676765c793fa10079d601b1b6ac34556b3f6459039627ea482020461408f8482614751565b60408701526101608b01511561437957600a546040516317858ab160e31b81528c9189918d918d916000916001600160a01b03169063c4c31b68903390839063bc2c5588906140e49089908990600401615ade565b602060405180830381600087803b1580156140fe57600080fd5b505af1158015614112573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141369190615649565b8e604001518960600151614148612fca565b6040516001600160e01b031960e088901b1681526001600160a01b039586166004820152949093166024850152604484019190915290036064820152861515608482015260a401602060405180830381600087803b1580156141a957600080fd5b505af11580156141bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141e191906159f8565b600a549091506000906001600160a01b03166354f4758f87868685614204612fca565b60016040518763ffffffff1660e01b815260040161422796959493929190615bb1565b602060405180830381600087803b15801561424157600080fd5b505af1158015614255573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061427991906159f8565b905081871161428957600061428d565b8187035b60608d015260408c0180518390039081905281830101808b111561431357808b03808e52600e54604051630e7176c360e11b815260048101929092526001600160a01b031690631ce2ed8690602401600060405180830381600087803b1580156142f657600080fd5b505af115801561430a573d6000803e3d6000fd5b50505050614318565b60008d525b8c606001518a1161432a576000614332565b8c606001518a035b60208e015260a087015161436d5786511561435c576101408701516007805491909103905561436d565b610140870151600880549190910390555b5050505050505061446e565b83811161438757600061438b565b8381035b6060870152604086015184116143a25760006143aa565b856040015184035b8652606086015183116143be5760006143c6565b856060015183035b602087015260a08b015161446e57600e546101408c0151604051630e7176c360e11b81526001600160a01b0390921691631ce2ed869161440c9160040190815260200190565b600060405180830381600087803b15801561442657600080fd5b505af115801561443a573d6000803e3d6000fd5b505050508a600001511561445d576101408b01516007805491909103905561446e565b6101408b0151600880549190910390555b505050505095945050505050565b84840160006b053a680649b3e32378b13f52676765c793fa10079d601b1b8302600e546040516339dbe92160e21b8152929091046004830181905292506001600160a01b03169063e76fa48490602401600060405180830381600087803b1580156144e657600080fd5b505af11580156144fa573d6000803e3d6000fd5b505050506000676765c793fa10079d601b1b6ac34556b3f6459039627ea484028161453557634e487b7160e01b600052601260045260246000fd5b04828403039050858101850180156145a657600e5460405163c0c8835760e01b8152600481018390526001600160a01b039091169063c0c8835790602401600060405180830381600087803b15801561458d57600080fd5b505af11580156145a1573d6000803e3d6000fd5b505050505b81156145c2576017546145c2906001600160a01b031683613002565b6145ce33888801613002565b336001600160a01b038c167f3d7c224e9ad9e12f013ba8a086e40c61608308a8810a12b8fa970887f0feb6aa8c8a8a8888676765c793fa10079d601b1b6ac34556b3f6459039627ea48d02048d60405161462e9796959493929190615cad565b60405180910390a35050505050505050505050565b6001600160a01b03811660009081526005602052604090208054600181018255905b50919050565b600061090661467861341f565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006146ca8787878761508a565b915091506146d781615177565b5095945050505050565b6000826146ee858461537b565b14949350505050565b60008182848161471757634e487b7160e01b600052601260045260246000fd5b0615614724576001614727565b60005b60ff1683858161474757634e487b7160e01b600052601260045260246000fd5b0401029392505050565b60008183106147605781614762565b825b9392505050565b60004282014340846040516020016147a693929190928352602083019190915260601b6bffffffffffffffffffffffff1916604082015260540190565b60408051601f1981840301815291905280516020909101209392505050565b600080600086610160015111156147f0576147e285848601614751565b90508092506000935061487c565b60a08601516148775785511561480e57600780548590039055614818565b6008805485900390555b600e54604051630e7176c360e11b8152600481018690526001600160a01b0390911690631ce2ed8690602401600060405180830381600087803b15801561485e57600080fd5b505af1158015614872573d6000803e3d6000fd5b505050505b508282015b600e546040516339dbe92160e21b81526b053a680649b3e32378b13f52676765c793fa10079d601b1b8402046004820181905293506001600160a01b039091169063e76fa48490602401600060405180830381600087803b1580156148e057600080fd5b505af11580156148f4573d6000803e3d6000fd5b505050506000676765c793fa10079d601b1b6ac34556b3f6459039627ea483028161492f57634e487b7160e01b600052601260045260246000fd5b60175491900484840303915061494e906001600160a01b031682613002565b600e5460405163c0c8835760e01b8152600481018390526001600160a01b039091169063c0c8835790602401600060405180830381600087803b15801561499457600080fd5b505af11580156149a8573d6000803e3d6000fd5b505050505050949350505050565b60a0850151614a9d578451614a3357600e5460c0860151604051633f9d44fd60e01b81526001600160a01b0390921691633f9d44fd916149fc9160040190815260200190565b600060405180830381600087803b158015614a1657600080fd5b505af1158015614a2a573d6000803e3d6000fd5b50505050614a9d565b600e5460c08601516040516310d6833b60e31b81526001600160a01b03909216916386b419d891614a6a9160040190815260200190565b600060405180830381600087803b158015614a8457600080fd5b505af1158015614a98573d6000803e3d6000fd5b505050505b600085608001518660600151018510614ab7576000614ab9565b835b82876101400151010390508561014001518110614b3757600e546001600160a01b03166365407202614aeb88846153fd565b6040518263ffffffff1660e01b8152600401614b0991815260200190565b600060405180830381600087803b158015614b2357600080fd5b505af1158015612463573d6000803e3d6000fd5b505050505050565b6000806000614b5087868801614751565b90506000614b5c612fca565b90508a60a0015160001415614b7c576101408b0151600780549190910390555b60008a90506000600a60009054906101000a90046001600160a01b03166001600160a01b03166354f4758f8e848e86888d6040518763ffffffff1660e01b8152600401614bce96959493929190615bb1565b602060405180830381600087803b158015614be857600080fd5b505af1158015614bfc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614c2091906159f8565b9050808d610140015111614c35576000614c3e565b808d6101400151035b9550838a039450614c518287878a615543565b5050505097509795505050505050565b6000806000614d0289601060009054906101000a90046001600160a01b03166001600160a01b03166307c5ed228e6040518263ffffffff1660e01b8152600401614cab9190615ba2565b60206040518083038186803b158015614cc357600080fd5b505afa158015614cd7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614cfb91906159f8565b8a016155c4565b90506000614d1088886155c4565b9050818c610140015111614d25576000614d2e565b818c6101400151035b9350808611614d3e576000614d42565b8086035b92508b60a0015160001415614e96578b5115614d6d576101408c015160078054919091039055614d7e565b6101408c0151600880549190910390555b600083118015614d8c575084155b15614df057600e5460405163c0c8835760e01b8152600481018590526001600160a01b039091169063c0c8835790602401600060405180830381600087803b158015614dd757600080fd5b505af1158015614deb573d6000803e3d6000fd5b505050505b8415614e6557600e546101408d0151604051630e7176c360e11b81526001600160a01b0390921691631ce2ed8691614e2e9160040190815260200190565b600060405180830381600087803b158015614e4857600080fd5b505af1158015614e5c573d6000803e3d6000fd5b50505050614ef6565b600e54604051630e7176c360e11b8152600481018490526001600160a01b0390911690631ce2ed8690602401614e2e565b600e5460405163c0c8835760e01b815284860160048201526001600160a01b039091169063c0c8835790602401600060405180830381600087803b158015614edd57600080fd5b505af1158015614ef1573d6000803e3d6000fd5b505050505b84158015614f0657506000838501115b15614f1757614f178b848601613002565b50509850989650505050505050565b60a083015161500d578251614fa357600e5460c0840151604051633f9d44fd60e01b81526001600160a01b0390921691633f9d44fd91614f6c9160040190815260200190565b600060405180830381600087803b158015614f8657600080fd5b505af1158015614f9a573d6000803e3d6000fd5b5050505061500d565b600e5460c08401516040516310d6833b60e31b81526001600160a01b03909216916386b419d891614fda9160040190815260200190565b600060405180830381600087803b158015614ff457600080fd5b505af1158015615008573d6000803e3d6000fd5b505050505b600e546101408401516001600160a01b039091169063654072029061503590869085016153fd565b6040518263ffffffff1660e01b815260040161505391815260200190565b600060405180830381600087803b15801561506d57600080fd5b505af1158015615081573d6000803e3d6000fd5b50505050505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156150c1575060009050600361516e565b8460ff16601b141580156150d957508460ff16601c14155b156150ea575060009050600461516e565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561513e573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166151675760006001925092505061516e565b9150600090505b94509492505050565b600081600481111561519957634e487b7160e01b600052602160045260246000fd5b14156151a25750565b60018160048111156151c457634e487b7160e01b600052602160045260246000fd5b14156152125760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610c44565b600281600481111561523457634e487b7160e01b600052602160045260246000fd5b14156152825760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610c44565b60038160048111156152a457634e487b7160e01b600052602160045260246000fd5b14156152fd5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610c44565b600481600481111561531f57634e487b7160e01b600052602160045260246000fd5b14156153785760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610c44565b50565b600081815b84518110156153f55760008582815181106153ab57634e487b7160e01b600052603260045260246000fd5b602002602001015190508083116153d157600083815260208290526040902092506153e2565b600081815260208490526040902092505b50806153ed81615d80565b915050615380565b509392505050565b6000676765c793fa10079d601b1b8360c00151670de0b6b3a7640000615446676765c793fa10079d601b1b86026b053a680649b3e32378b13f5267016345785d8a000002614751565b85028161546357634e487b7160e01b600052601260045260246000fd5b046154f46b0709fa55642a614ae4f586a686026105b06154d1676765c793fa10079d601b1b61115c02676765c793fa10079d601b1b6154cb6ac34556b3f6459039627ea4676765c793fa10079d601b1b018d6080015102676765c793fa10079d601b1b6146f7565b03614751565b8802816154ee57634e487b7160e01b600052601260045260246000fd5b04614751565b676765c793fa10079d601b1b860201018161551f57634e487b7160e01b600052601260045260246000fd5b048161553b57634e487b7160e01b600052601260045260246000fd5b049392505050565b8061315557821561555a5761555a84838501613002565b811561315557600e5460405163c0c8835760e01b8152600481018490526001600160a01b039091169063c0c8835790602401600060405180830381600087803b1580156155a657600080fd5b505af11580156155ba573d6000803e3d6000fd5b5050505050505050565b60008183116147605781614762565b60008083601f8401126155e4578182fd5b50813567ffffffffffffffff8111156155fb578182fd5b6020830191508360208260051b850101111561561657600080fd5b9250929050565b805161562881615dc6565b919050565b60006020828403121561563e578081fd5b813561476281615db1565b60006020828403121561565a578081fd5b815161476281615db1565b60008060408385031215615677578081fd5b823561568281615db1565b9150602083013561569281615db1565b809150509250929050565b6000806000606084860312156156b1578081fd5b83356156bc81615db1565b925060208401356156cc81615db1565b929592945050506040919091013590565b600080600080600080600060e0888a0312156156f7578283fd5b873561570281615db1565b9650602088013561571281615db1565b95506040880135945060608801359350608088013560ff81168114615735578384fd5b9699959850939692959460a0840135945060c09093013592915050565b60008060408385031215615764578182fd5b823561576f81615db1565b946020939093013593505050565b60008060008060608587031215615792578384fd5b843561579d81615db1565b935060208501359250604085013567ffffffffffffffff8111156157bf578283fd5b6157cb878288016155d3565b95989497509550505050565b6000806000806000608086880312156157ee578081fd5b85356157f981615db1565b945060208601359350604086013567ffffffffffffffff81111561581b578182fd5b615827888289016155d3565b909450925050606086013561583b81615dc6565b809150509295509295909350565b60008060006060848603121561585d578081fd5b833561586881615db1565b925060208401359150604084013561587f81615dc6565b809150509250925092565b60006020828403121561589b578081fd5b815161476281615dc6565b600061018082840312156158b8578081fd5b6158c0615ce4565b6158c98361561d565b81526158d76020840161561d565b60208201526158e86040840161561d565b6040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e082015261010061592d81850161561d565b9082015261012083810151908201526101408084015190820152610160928301519281019290925250919050565b600060c0828403121561596c578081fd5b60405160c0810181811067ffffffffffffffff8211171561599b57634e487b7160e01b83526041600452602483fd5b8060405250825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a08201528091505092915050565b6000602082840312156159f1578081fd5b5035919050565b600060208284031215615a09578081fd5b5051919050565b600080600060608486031215615a24578081fd5b833592506020840135615a3681615dc6565b9150604084013561587f81615dc6565b8051151582526020810151615a5f602084018215159052565b506040810151615a73604084018215159052565b50606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e083015261010080820151615aba8285018215159052565b50506101208181015190830152610140808201519083015261016090810151910152565b6001600160a01b03929092168252602082015260400190565b9283526001600160a01b039190911660208301521515604082015260600190565b6000602080835283518082850152825b81811015615b4457858101830151858201604001528201615b28565b81811115615b555783604083870101525b50601f01601f1916929092016040019392505050565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b61018081016109068284615a46565b6102208101615bc08289615a46565b6001600160a01b039687166101808301526101a0820195909552929094166101c08301526101e082015291151561020090920191909152919050565b6102008101615c0b8288615a46565b6001600160a01b03959095166101808201526101a08101939093526101c08301919091526101e090910152919050565b6101e08101615c4a8287615a46565b84610180830152836101a0830152826101c083015295945050505050565b60006102408201905088825287151560208301528660408301528560608301528460808301528360a0830152615ca160c0830184615a46565b98975050505050505050565b6000610240820190508882528760208301528660408301528560608301528460808301528360a0830152615ca160c0830184615a46565b604051610180810167ffffffffffffffff81118282101715615d1657634e487b7160e01b600052604160045260246000fd5b60405290565b60008219821115615d2f57615d2f615d9b565b500190565b600082821015615d4657615d46615d9b565b500390565b600181811c90821680615d5f57607f821691505b6020821081141561466557634e487b7160e01b600052602260045260246000fd5b6000600019821415615d9457615d94615d9b565b5060010190565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b038116811461537857600080fd5b801515811461537857600080fdfea2646970667358221220cf7fec9b990305171b472ea11addeeab57dabb8532cd6cde4b8907984b8c951864736f6c63430008040033000000000000000000000000dca40b6fb95e9c1c4511f7758bc6f3aec7474444000000000000000000000000f2ebcc36ecbbf57bcf7d7531fe24f137afc4c555

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061030c5760003560e01c806360f1edf71161019d578063a9059cbb116100e9578063d505accf116100a2578063dfcad7ea1161007c578063dfcad7ea146106ad578063e09f0817146106c0578063e954f41d146106d3578063e9c4239b146106de57600080fd5b8063d505accf14610674578063dc38bdb514610687578063dd62ed3e1461069a57600080fd5b8063a9059cbb146105f2578063ad09d65814610605578063b074d2f614610618578063c884ef831461062b578063cb01454b1461064e578063d11d01db1461066157600080fd5b806376df7c321161015657806395d89b411161013057806395d89b41146105b157806396cc563f146105b95780639dc29fac146105cc578063a457c2d7146105df57600080fd5b806376df7c32146105785780637ecebe001461058b578063873f0a331461059e57600080fd5b806360f1edf7146104f057806360f6c4d61461050357806363fcd08a146105165780636f72995f1461052957806370a082311461053c57806372fb9c551461056557600080fd5b806323b872dd1161025c578063379b2c1311610215578063445c101f116101ef578063445c101f146104ae5780634bd0cd42146104b75780635476ea9e146104ca57806357ec85dd146104dd57600080fd5b8063379b2c1314610475578063395093511461048857806340c10f191461049b57600080fd5b806323b872dd1461041c578063269858651461042f5780632c265c88146104425780632ceaaf281461044b578063313ce5671461045e5780633644e5151461046d57600080fd5b80630c6eae62116102c9578063197162be116102a3578063197162be146103e55780631ad03156146103f85780631bf803391461040b578063238bf8e01461041457600080fd5b80630c6eae62146103b757806315df1fca146103ca57806318160ddd146103dd57600080fd5b8063023924c71461031157806303d41eb61461032657806306fdde0314610341578063095ea7b314610356578063096ff58a146103795780630b622ab21461038c575b600080fd5b61032461031f36600461562d565b6106f1565b005b61032e6107c7565b6040519081526020015b60405180910390f35b610349610860565b6040516103389190615b18565b610369610364366004615752565b6108f2565b6040519015158152602001610338565b61032461038736600461562d565b61090c565b60095461039f906001600160a01b031681565b6040516001600160a01b039091168152602001610338565b6103246103c536600461562d565b610ae6565b60115461039f906001600160a01b031681565b60025461032e565b6103246103f33660046159e0565b610bea565b600d5461039f906001600160a01b031681565b61032e60075481565b610324610c21565b61036961042a36600461569d565b610cc1565b61032461043d3660046157d7565b610ce5565b61032e60085481565b60165461039f906001600160a01b031681565b60405160098152602001610338565b61032e6110c4565b60135461039f906001600160a01b031681565b610369610496366004615752565b6110d3565b6103246104a9366004615752565b6110f5565b61032e60195481565b6103246104c536600461562d565b61112e565b600b5461039f906001600160a01b031681565b6103246104eb366004615a10565b6112f0565b6103246104fe36600461562d565b611a95565b61032461051136600461562d565b611b8e565b60175461039f906001600160a01b031681565b61032461053736600461562d565b611c33565b61032e61054a36600461562d565b6001600160a01b031660009081526020819052604090205490565b6103246105733660046159e0565b611d44565b6103246105863660046159e0565b611d7a565b61032e61059936600461562d565b611dbf565b60145461039f906001600160a01b031681565b610349611ddd565b6103246105c736600461562d565b611dec565b6103246105da366004615752565b611f4f565b6103696105ed366004615752565b611fcb565b610369610600366004615752565b612046565b61032461061336600461562d565b612054565b600f5461039f906001600160a01b031681565b61036961063936600461562d565b60186020526000908152604090205460ff1681565b61032461065c3660046159e0565b6120d1565b61032461066f366004615849565b612107565b6103246106823660046156dd565b61230b565b61036961069536600461577d565b61246f565b61032e6106a8366004615665565b612541565b6103246106bb366004615752565b61256c565b6103246106ce3660046159e0565b612597565b61032e636398e41681565b6103246106ec366004615849565b6125ce565b6001600160a01b038116610718576040516342bec4df60e01b815260040160405180910390fd5b600b546001600160a01b03161561074257604051631d0b184b60e21b815260040160405180910390fd5b600b80546001600160a01b038381166001600160a01b03199283168117909355600c80549092168317909155600a5460405163023924c760e01b81526004810193909352169063023924c7906024015b600060405180830381600087803b1580156107ac57600080fd5b505af11580156107c0573d6000803e3d6000fd5b5050505050565b6000600854600754600e60009054906101000a90046001600160a01b03166001600160a01b03166355d0a1d06040518163ffffffff1660e01b815260040160206040518083038186803b15801561081d57600080fd5b505afa158015610831573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061085591906159f8565b600254010101905090565b60606003805461086f90615d4b565b80601f016020809104026020016040519081016040528092919081815260200182805461089b90615d4b565b80156108e85780601f106108bd576101008083540402835291602001916108e8565b820191906000526020600020905b8154815290600101906020018083116108cb57829003601f168201915b5050505050905090565b600033610900818585612ea5565b60019150505b92915050565b6001600160a01b038116610933576040516342bec4df60e01b815260040160405180910390fd5b6016546001600160a01b03163314158061095757506014546001600160a01b031615155b1561097557604051631d0b184b60e21b815260040160405180910390fd5b601480546001600160a01b038381166001600160a01b03199283168117909355601580549092168317909155600c546040516304b7fac560e11b81526004810193909352169063096ff58a90602401600060405180830381600087803b1580156109de57600080fd5b505af11580156109f2573d6000803e3d6000fd5b5050600e546040516304b7fac560e11b81526001600160a01b038581166004830152909116925063096ff58a9150602401600060405180830381600087803b158015610a3d57600080fd5b505af1158015610a51573d6000803e3d6000fd5b50506012546040516304b7fac560e11b81526001600160a01b038581166004830152909116925063096ff58a9150602401600060405180830381600087803b158015610a9c57600080fd5b505af1158015610ab0573d6000803e3d6000fd5b5050600a546040516304b7fac560e11b81526001600160a01b038581166004830152909116925063096ff58a9150602401610792565b6001600160a01b038116610b0d576040516342bec4df60e01b815260040160405180910390fd5b6016546001600160a01b03163314610b3857604051631d0b184b60e21b815260040160405180910390fd5b601780546001600160a01b0319166001600160a01b03838116918217909255600a54604051637827d56160e01b8152600481019290925290911690637827d56190602401600060405180830381600087803b158015610b9657600080fd5b505af1158015610baa573d6000803e3d6000fd5b505050507fdd475012ca9bbf511d7eb2d3c4f7709ade7f0e3910b847b5dcda58b16684d7518142604051610bdf929190615ade565b60405180910390a150565b600f546001600160a01b03163314610c1557604051631d0b184b60e21b815260040160405180910390fd5b60078054919091039055565b6002601a541415610c4d5760405162461bcd60e51b8152600401610c4490615b6b565b60405180910390fd5b6002601a556016546001600160a01b031633141580610c7357506020610c71612fca565b105b80610c7e5750601954155b15610c9c576040516390172c2b60e01b815260040160405180910390fd5b601754601954610cb5916001600160a01b031690613002565b60006019556001601a55565b600033610ccf8582856130e1565b610cda85858561315b565b506001949350505050565b6002601a541415610d085760405162461bcd60e51b8152600401610c4490615b6b565b6002601a55610d198585858561246f565b610d3657604051633d9a544f60e21b815260040160405180910390fd5b6001600160a01b0385166000818152601860205260409020805460ff19166001179055331480610d6d575060b5610d6b612fca565b105b80610da25750636398e41642108015610da257506001600160a01b0385167366eca275200015dcd0c2eaa6e48d4eed3092cdd6145b15610ed95760405163a9059cbb60e01b8152309063a9059cbb90610dcc9088908890600401615ade565b602060405180830381600087803b158015610de657600080fd5b505af1158015610dfa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1e919061588a565b508015610e8b5760155460405163d1194e2b60e01b81526001600160a01b039091169063d1194e2b90610e58908890600090600401615ade565b600060405180830381600087803b158015610e7257600080fd5b505af1158015610e86573d6000803e3d6000fd5b505050505b604080513381526001600160a01b03871660208201529081018590527f70eb43c4a8ae8c40502dcf22436c509c28d6ff421cf07c491be56984bd9870689060600160405180910390a16110b8565b808015610f065750610f06336b013bf472f5ed1d56574ec0ad676765c793fa10079d601b1b600080613329565b15610f715760155460405163d1194e2b60e01b81526001600160a01b039091169063d1194e2b90610f3e903390600190600401615ade565b600060405180830381600087803b158015610f5857600080fd5b505af1158015610f6c573d6000803e3d6000fd5b505050505b60405163a9059cbb60e01b8152309063a9059cbb90610f9b90339064174876e80090600401615ade565b602060405180830381600087803b158015610fb557600080fd5b505af1158015610fc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fed919061588a565b5060405163a9059cbb60e01b8152309063a9059cbb9061101b90889064174876e7ff19890190600401615ade565b602060405180830381600087803b15801561103557600080fd5b505af1158015611049573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061106d919061588a565b50604080513381526001600160a01b03871660208201529081018590527f70eb43c4a8ae8c40502dcf22436c509c28d6ff421cf07c491be56984bd9870689060600160405180910390a15b50506001601a55505050565b60006110ce61341f565b905090565b6000336109008185856110e68383612541565b6110f09190615d1c565b612ea5565b600b546001600160a01b0316331461112057604051631d0b184b60e21b815260040160405180910390fd5b61112a8282613002565b5050565b6001600160a01b038116611155576040516342bec4df60e01b815260040160405180910390fd5b6011546001600160a01b03161561117f57604051631d0b184b60e21b815260040160405180910390fd5b601180546001600160a01b038381166001600160a01b03199283168117909355601280549092168317909155600c546040516325e866a160e11b815260048101939093521690634bd0cd4290602401600060405180830381600087803b1580156111e857600080fd5b505af11580156111fc573d6000803e3d6000fd5b5050600e546040516325e866a160e11b81526001600160a01b0385811660048301529091169250634bd0cd429150602401600060405180830381600087803b15801561124757600080fd5b505af115801561125b573d6000803e3d6000fd5b5050600a546040516325e866a160e11b81526001600160a01b0385811660048301529091169250634bd0cd429150602401600060405180830381600087803b1580156112a657600080fd5b505af11580156112ba573d6000803e3d6000fd5b50506010546040516325e866a160e11b81526001600160a01b0385811660048301529091169250634bd0cd429150602401610792565b6002601a5414156113135760405162461bcd60e51b8152600401610c4490615b6b565b6002601a55601254604051631f11d95360e01b81526000916001600160a01b031690631f11d9539061134b9033908890600401615ade565b6101806040518083038186803b15801561136457600080fd5b505afa158015611378573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139c91906158a6565b905060006113a8612fca565b60608301516080840151919250600091810183106113d05783608001518460600151016113d2565b825b60125460405163f139dfb760e01b81529290910392506001600160a01b03169063f139dfb79061140e90869033908b9088908890600401615bfc565b600060405180830381600087803b15801561142857600080fd5b505af115801561143c573d6000803e3d6000fd5b5050505060006001600e60009054906101000a90046001600160a01b03166001600160a01b0316630f90e0076040518163ffffffff1660e01b815260040160206040518083038186803b15801561149257600080fd5b505afa1580156114a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ca91906159f8565b03905083608001518210806114ec575082846080015185606001510160070111155b1561171657600e546040516348d62c6d60e11b81526001600160a01b03909116906391ac58da906115269060009033908a90600401615af7565b602060405180830381600087803b15801561154057600080fd5b505af1158015611554573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157891906159f8565b50600e54604051633b30762f60e11b81526001600160a01b0390911690637660ec5e906115ae9060009033908a90600401615af7565b602060405180830381600087803b1580156115c857600080fd5b505af11580156115dc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061160091906159f8565b50600e5460405163ab18a02760e01b81526001600160a01b039091169063ab18a027906116369060009033908a90600401615af7565b602060405180830381600087803b15801561165057600080fd5b505af1158015611664573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061168891906159f8565b50600e54604051637c6d493160e11b81526001600160a01b039091169063f8da9262906116be9060009033908a90600401615af7565b602060405180830381600087803b1580156116d857600080fd5b505af11580156116ec573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061171091906159f8565b5061194e565b6060840151820160001901818111156117b357600e546040516348d62c6d60e11b81526001600160a01b03909116906391ac58da9061175f908585039033908b90600401615af7565b602060405180830381600087803b15801561177957600080fd5b505af115801561178d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117b191906159f8565b505b600e546001600160a01b0316637660ec5e600a830433896040518463ffffffff1660e01b81526004016117e893929190615af7565b602060405180830381600087803b15801561180257600080fd5b505af1158015611816573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061183a91906159f8565b50600e546001600160a01b031663ab18a0276064830433896040518463ffffffff1660e01b815260040161187093929190615af7565b602060405180830381600087803b15801561188a57600080fd5b505af115801561189e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118c291906159f8565b50600e546001600160a01b031663f8da92626103e8830433896040518463ffffffff1660e01b81526004016118f993929190615af7565b602060405180830381600087803b15801561191357600080fd5b505af1158015611927573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061194b91906159f8565b50505b600e5460608501518551604051634c29019760e11b815260048101839052918501600019016024830152151560448201526000916001600160a01b031690639852032e9060640160206040518083038186803b1580156119ad57600080fd5b505afa1580156119c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119e591906159f8565b90506000670de0b6b3a7640000828760c001510281611a1457634e487b7160e01b600052601260045260246000fd5b0490506000806000611a29338d868e8e613546565b9250925092506000899050336001600160a01b03167fe16ef2c5ff376e78191b54a217db16e2ca4eca7cb451d282f7dd8a75c492df498e8e8789888888604051611a799796959493929190615c68565b60405180910390a250506001601a555050505050505050505050565b6001600160a01b038116611abc576040516342bec4df60e01b815260040160405180910390fd5b6016546001600160a01b03163314611ae757604051631d0b184b60e21b815260040160405180910390fd5b601680546001600160a01b0319166001600160a01b03838116918217909255600a54604051637e98d42960e11b815260048101929092529091169063fd31a85290602401600060405180830381600087803b158015611b4557600080fd5b505af1158015611b59573d6000803e3d6000fd5b505050507fd535651a5590e21c663adfebb2eb6431447c10dccf3eee90c4c4d8bf7983c14a8142604051610bdf929190615ade565b6001600160a01b038116611bb5576040516342bec4df60e01b815260040160405180910390fd5b600d546001600160a01b031615611bdf57604051631d0b184b60e21b815260040160405180910390fd5b600d80546001600160a01b038381166001600160a01b03199283168117909355600e80549092168317909155600c5460405163307b626b60e11b8152600481019390935216906360f6c4d690602401610792565b6001600160a01b038116611c5a576040516342bec4df60e01b815260040160405180910390fd5b6016546001600160a01b031633141580611c7e57506013546001600160a01b031615155b15611c9c57604051631d0b184b60e21b815260040160405180910390fd5b601380546001600160a01b0319166001600160a01b03838116918217909255601254604051636f72995f60e01b8152600481019290925290911690636f72995f90602401600060405180830381600087803b158015611cfa57600080fd5b505af1158015611d0e573d6000803e3d6000fd5b5050600e54604051636f72995f60e01b81526001600160a01b0385811660048301529091169250636f72995f9150602401610792565b6011546001600160a01b03163314611d6f57604051631d0b184b60e21b815260040160405180910390fd5b600780549091019055565b6011546001600160a01b03163314611da557604051631d0b184b60e21b815260040160405180910390fd5b8060196000828254611db79190615d1c565b909155505050565b6001600160a01b038116600090815260056020526040812054610906565b60606004805461086f90615d4b565b6001600160a01b038116611e13576040516342bec4df60e01b815260040160405180910390fd5b600f546001600160a01b031615611e3d57604051631d0b184b60e21b815260040160405180910390fd5b601080546001600160a01b038381166001600160a01b03199283168117909355600f80549092168317909155600e546040516396cc563f60e01b8152600481019390935216906396cc563f90602401600060405180830381600087803b158015611ea657600080fd5b505af1158015611eba573d6000803e3d6000fd5b5050600a546040516396cc563f60e01b81526001600160a01b03858116600483015290911692506396cc563f9150602401600060405180830381600087803b158015611f0557600080fd5b505af1158015611f19573d6000803e3d6000fd5b5050600c54604051632e8098c560e01b81526001600160a01b0385811660048301529091169250632e8098c59150602401610792565b6009546001600160a01b03163314801590611f755750600b546001600160a01b03163314155b8015611f8c57506011546001600160a01b03163314155b8015611fa357506013546001600160a01b03163314155b15611fc157604051631d0b184b60e21b815260040160405180910390fd5b61112a8282613c21565b60003381611fd98286612541565b9050838110156120395760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610c44565b610cda8286868403612ea5565b60003361090081858561315b565b6001600160a01b03811661207b576040516342bec4df60e01b815260040160405180910390fd5b6009546001600160a01b0316156120a557604051631d0b184b60e21b815260040160405180910390fd5b600980546001600160a01b039092166001600160a01b03199283168117909155600a8054909216179055565b6011546001600160a01b031633146120fc57604051631d0b184b60e21b815260040160405180910390fd5b600880549091019055565b6002601a54141561212a5760405162461bcd60e51b8152600401610c4490615b6b565b6002601a55601254604051631f11d95360e01b81526000916001600160a01b031690631f11d953906121629087908790600401615ade565b6101806040518083038186803b15801561217b57600080fd5b505afa15801561218f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121b391906158a6565b9050600081600001516121d45781608001518260600151016101b8016121e4565b8160800151826060015101610113015b9050806121ef612fca565b108061220057506000826101200151115b8061220c575081602001515b8061221957506080820151155b156122375760405163270b039d60e21b815260040160405180910390fd5b60006122468387878588613d67565b90508380156122745750612274336ac34556b3f6459039627ea4676765c793fa10079d601b1b600080613329565b156122df5760155460405163d1194e2b60e01b81526001600160a01b039091169063d1194e2b906122ac903390600190600401615ade565b600060405180830381600087803b1580156122c657600080fd5b505af11580156122da573d6000803e3d6000fd5b505050505b6122fe868683600001518460200151856040015186606001518961447c565b50506001601a5550505050565b8342111561235b5760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e650000006044820152606401610c44565b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c988888861238a8c614643565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e00160405160208183030381529060405280519060200120905060006123e58261466b565b905060006123f5828787876146b9565b9050896001600160a01b0316816001600160a01b0316146124585760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e617475726500006044820152606401610c44565b6124638a8a8a612ea5565b50505050505050505050565b6040516bffffffffffffffffffffffff19606086901b16602082015260348101849052600090819060540160408051601f1981840301815291815281516020928301206001600160a01b0389166000908152601890935291205490915060ff1615801561253757506125378484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507fcad71776a60b1a4ca80bfa5452bfc50beeb645b7f64e97f5c464ef45a41d548d92508591506146e19050565b9695505050505050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b600d546001600160a01b0316331461112057604051631d0b184b60e21b815260040160405180910390fd5b600f546001600160a01b031633146125c257604051631d0b184b60e21b815260040160405180910390fd5b60088054919091039055565b6002601a5414156125f15760405162461bcd60e51b8152600401610c4490615b6b565b6002601a55601254604051631f11d95360e01b81526000916001600160a01b031690631f11d953906126299087908790600401615ade565b6101806040518083038186803b15801561264257600080fd5b505afa158015612656573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061267a91906158a6565b60808101516060820151919250016000612692612fca565b9050826020015180156126a757508261010001515b156126c557604051635ad8888f60e01b815260040160405180910390fd5b600083610120015111806126dd575060008360a00151115b806126e757508181105b806126f457506080830151155b15612712576040516301ddf13b60e61b815260040160405180910390fd5b601254604051632fd96bfd60e11b81526001600160a01b038881166004830152602482018890526044820184905290911690635fb2d7fa90606401600060405180830381600087803b15801561276757600080fd5b505af115801561277b573d6000803e3d6000fd5b50505050600083600001511561281e57676765c793fa10079d601b1b6127fb606460076b08759642e984636060b13f5288610140015102816127cd57634e487b7160e01b600052601260045260246000fd5b04816127e957634e487b7160e01b600052601260045260246000fd5b04676765c793fa10079d601b1b6146f7565b8161281657634e487b7160e01b600052601260045260246000fd5b04905061287f565b676765c793fa10079d601b1b612860606460076b053a680649b3e32378b13f5288610140015102816127cd57634e487b7160e01b600052601260045260246000fd5b8161287b57634e487b7160e01b600052601260045260246000fd5b0490505b6101408401516000906128b4906128968185614751565b8660070186116128a75760006128ae565b6007878703035b02614751565b90508460200151156129ae57600c546040516303f9f6f560e61b81526001600160a01b039091169063fe7dbd40906128f2908b908b90600401615ade565b602060405180830381600087803b15801561290c57600080fd5b505af1158015612920573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612944919061588a565b156129ae57600c546040516342cdcbff60e11b81526001600160a01b039091169063859b97fe9061297b908b908b90600401615ade565b600060405180830381600087803b15801561299557600080fd5b505af11580156129a9573d6000803e3d6000fd5b505050505b600e5460408051630f90e00760e01b815290516000926001600160a01b031691630f90e007916004808301926020929190829003018186803b1580156129f357600080fd5b505afa158015612a07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a2b91906159f8565b90508560600151600101811015612acf57600e5460608701516040516348d62c6d60e11b81526001600160a01b03909216916391ac58da91612a7b91908590036001019033908c90600401615af7565b602060405180830381600087803b158015612a9557600080fd5b505af1158015612aa9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612acd91906159f8565b505b855115612b545761014086015160078054919091039055600e5460c08701516040516310d6833b60e31b81526001600160a01b03909216916386b419d891612b1d9160040190815260200190565b600060405180830381600087803b158015612b3757600080fd5b505af1158015612b4b573d6000803e3d6000fd5b50505050612bce565b61014086015160088054919091039055600e5460c0870151604051633f9d44fd60e01b81526001600160a01b0390921691633f9d44fd91612b9b9160040190815260200190565b600060405180830381600087803b158015612bb557600080fd5b505af1158015612bc9573d6000803e3d6000fd5b505050505b61016086015160009015612d1d578215612d1857600a546040516317858ab160e31b81526000916001600160a01b03169063bc2c558890612c15908e908e90600401615ade565b602060405180830381600087803b158015612c2f57600080fd5b505af1158015612c43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c679190615649565b600a5460608a0151604051631898636d60e31b81523360048201526001600160a01b03808516602483015260448201899052918a03606482015260006084820152929350169063c4c31b689060a401602060405180830381600087803b158015612cd057600080fd5b505af1158015612ce4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d0891906159f8565b9150612d148285614751565b9350505b612db1565b600e546101408801516001600160a01b0390911690631ce2ed86908510612d45576000612d4e565b84896101400151035b6040518263ffffffff1660e01b8152600401612d6c91815260200190565b600060405180830381600087803b158015612d8657600080fd5b505af1158015612d9a573d6000803e3d6000fd5b505050506000831115612db157612db13384613002565b878015612ddd5750612ddd336ac34556b3f6459039627ea4676765c793fa10079d601b1b600080613329565b15612e485760155460405163d1194e2b60e01b81526001600160a01b039091169063d1194e2b90612e15903390600190600401615ade565b600060405180830381600087803b158015612e2f57600080fd5b505af1158015612e43573d6000803e3d6000fd5b505050505b604080516001600160a01b038c168152602081018b905290810184905233907f0d6b33a90fd9ff440fc1c724f3f3d492e7c2fc1c629b5a8aacf5c76c2ecbcdbe9060600160405180910390a250506001601a555050505050505050565b6001600160a01b038316612f075760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610c44565b6001600160a01b038216612f685760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610c44565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6000636398e416421015612ff157604051633c109e6160e11b815260040160405180910390fd5b506201518042636398e41519010490565b6001600160a01b0382166130585760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610c44565b806002600082825461306a9190615d1c565b90915550506001600160a01b03821660009081526020819052604081208054839290613097908490615d1c565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b60006130ed8484612541565b9050600019811461315557818110156131485760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610c44565b6131558484848403612ea5565b50505050565b6001600160a01b0383166131bf5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610c44565b6001600160a01b0382166132215760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610c44565b6001600160a01b038316600090815260208190526040902054818110156132995760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610c44565b6001600160a01b038085166000908152602081905260408082208585039055918516815290812080548492906132d0908490615d1c565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161331c91815260200190565b60405180910390a3613155565b600082156133d357601054604051631f8ee6fb60e11b81526004810185905264e8d4a51000916001600160a01b031690633f1dcdf69060240160206040518083038186803b15801561337a57600080fd5b505afa15801561338e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133b291906159f8565b8602816133cf57634e487b7160e01b600052601260045260246000fd5b0494505b8385106133e257506001613416565b6000846133ef8885614769565b8161340a57634e487b7160e01b600052601260045260246000fd5b87870391900610159150505b95945050505050565b6000306001600160a01b037f000000000000000000000000444444444444c1a66f394025ac839a535246fcc81614801561347857507f000000000000000000000000000000000000000000000000000000000000000146145b156134a257507fd951a38113188a785d6753c8c4b58034c16acb79f12f2984aaf2450160fe2feb90565b50604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091527f0a66c77ba3b0497bc9ceb34460a870cd59906d00eaa03ff7f53a58db8b994326828401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b601254604051631f11d95360e01b81526000918291829182916001600160a01b0390911690631f11d95390613581908c908c90600401615ade565b6101806040518083038186803b15801561359a57600080fd5b505afa1580156135ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135d291906158a6565b905060006135de612fca565b6060830151608084015191925060009181018310613606578360800151846060015101613608565b825b0390506000601060009054906101000a90046001600160a01b03166001600160a01b031663e4c2a4d68584868e6040518563ffffffff1660e01b81526004016136549493929190615c3b565b60c060405180830381600087803b15801561366e57600080fd5b505af1158015613682573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136a6919061595b565b905083608001518210156137fe576136c8848b836020015184600001516147c5565b945087156137f95761372c8c85600001516136e45760646136e7565b600a5b60ff166b053a680649b3e32378b13f528161371257634e487b7160e01b600052601260045260246000fd5b04676765c793fa10079d601b1b8761014001516000613329565b1561379b5760155460405163d1194e2b60e01b81526001600160a01b039091169063d1194e2b90613764908f90600190600401615ade565b600060405180830381600087803b15801561377e57600080fd5b505af1158015613792573d6000803e3d6000fd5b50505050613b9f565b8880156137c157506137c18c676765c793fa10079d601b1b808761014001516002613329565b156137f95760155460405163d1194e2b60e01b81526001600160a01b039091169063d1194e2b90613764908f90600190600401615ade565b613b9f565b83608001518460600151016007018311156139c757613827848b836080015184606001516147c5565b945087156137f957600089156138e4576138648d600a6b053a680649b3e32378b13f5204676765c793fa10079d601b1b886101400151600a613329565b156138e457601560009054906101000a90046001600160a01b03166001600160a01b031663d1194e2b8e600b6040518363ffffffff1660e01b81526004016138ad929190615ade565b600060405180830381600087803b1580156138c757600080fd5b505af11580156138db573d6000803e3d6000fd5b50505050600190505b806139c1576139458d86600001516138fd576064613900565b600a5b60ff166b053a680649b3e32378b13f528161392b57634e487b7160e01b600052601260045260246000fd5b04676765c793fa10079d601b1b8861014001516000613329565b156139c157601560009054906101000a90046001600160a01b03166001600160a01b031663d1194e2b8e60016040518363ffffffff1660e01b815260040161398e929190615ade565b600060405180830381600087803b1580156139a857600080fd5b505af11580156139bc573d6000803e3d6000fd5b505050505b50613b9f565b8715613b9f57605984608001511115613abe576139f88c676765c793fa10079d601b1b808761014001516000613329565b15613a635760155460405163d1194e2b60e01b81526001600160a01b039091169063d1194e2b90613a30908f90600190600401615ade565b600060405180830381600087803b158015613a4a57600080fd5b505af1158015613a5e573d6000803e3d6000fd5b505050505b88156137f957613a878c676765c793fa10079d601b1b808761014001516003613329565b156137f95760155460405163d1194e2b60e01b81526001600160a01b039091169063d1194e2b90613764908f906004908101615ade565b613ad68c60646b053a680649b3e32378b13f52613712565b15613b0e5760155460405163d1194e2b60e01b81526001600160a01b039091169063d1194e2b90613764908f90600190600401615ade565b888015613b345750613b348c676765c793fa10079d601b1b808761014001516014613329565b15613b9f5760155460405163d1194e2b60e01b81526001600160a01b039091169063d1194e2b90613b6c908f90600190600401615ade565b600060405180830381600087803b158015613b8657600080fd5b505af1158015613b9a573d6000803e3d6000fd5b505050505b613bb4848483604001518460a001518e6149b6565b61016084015115613be057613bd6848d8d8d856080015186606001518f614b3f565b9097509550613c12565b60008a905060008a9050613c0a868f85602001518660800151876000015188606001518888614c61565b909950975050505b50505050955095509592505050565b6001600160a01b038216613c815760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610c44565b6001600160a01b03821660009081526020819052604090205481811015613cf55760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610c44565b6001600160a01b0383166000908152602081905260408120838303905560028054849290613d24908490615d34565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612fbd565b613d926040518060800160405280600081526020016000815260200160008152602001600081525090565b6012546040516365892b4960e01b81526001600160a01b03878116600483015260248201879052426044830152909116906365892b4990606401600060405180830381600087803b158015613de657600080fd5b505af1158015613dfa573d6000803e3d6000fd5b50504261012089015250506010546101408701516040516336a34f2760e01b81526001600160a01b03909216916336a34f2791613e3d9160040190815260200190565b600060405180830381600087803b158015613e5757600080fd5b505af1158015613e6b573d6000803e3d6000fd5b50506010546040516303e2f69160e11b8152600093506001600160a01b0390911691506307c5ed2290613ea2908a90600401615ba2565b60206040518083038186803b158015613eba57600080fd5b505afa158015613ece573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ef291906159f8565b600e54606089015160808a0151604051635d070d7f60e11b81523360048201526024810192909252604482015285151560648201529192506001600160a01b03169063ba0e1afe90608401600060405180830381600087803b158015613f5757600080fd5b505af1158015613f6b573d6000803e3d6000fd5b5050505060008188610140015111613f84576000613f8d565b81886101400151035b600e5460608a015160808b01518b51604051634c29019760e11b815260048101849052919092016000190160248201529015156044820152919250600091670de0b6b3a7640000916001600160a01b031690639852032e9060640160206040518083038186803b15801561400057600080fd5b505afa158015614014573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061403891906159f8565b8a60c00151028161405957634e487b7160e01b600052601260045260246000fd5b04905081810161406a8a8884614f26565b676765c793fa10079d601b1b6ac34556b3f6459039627ea482020461408f8482614751565b60408701526101608b01511561437957600a546040516317858ab160e31b81528c9189918d918d916000916001600160a01b03169063c4c31b68903390839063bc2c5588906140e49089908990600401615ade565b602060405180830381600087803b1580156140fe57600080fd5b505af1158015614112573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141369190615649565b8e604001518960600151614148612fca565b6040516001600160e01b031960e088901b1681526001600160a01b039586166004820152949093166024850152604484019190915290036064820152861515608482015260a401602060405180830381600087803b1580156141a957600080fd5b505af11580156141bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141e191906159f8565b600a549091506000906001600160a01b03166354f4758f87868685614204612fca565b60016040518763ffffffff1660e01b815260040161422796959493929190615bb1565b602060405180830381600087803b15801561424157600080fd5b505af1158015614255573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061427991906159f8565b905081871161428957600061428d565b8187035b60608d015260408c0180518390039081905281830101808b111561431357808b03808e52600e54604051630e7176c360e11b815260048101929092526001600160a01b031690631ce2ed8690602401600060405180830381600087803b1580156142f657600080fd5b505af115801561430a573d6000803e3d6000fd5b50505050614318565b60008d525b8c606001518a1161432a576000614332565b8c606001518a035b60208e015260a087015161436d5786511561435c576101408701516007805491909103905561436d565b610140870151600880549190910390555b5050505050505061446e565b83811161438757600061438b565b8381035b6060870152604086015184116143a25760006143aa565b856040015184035b8652606086015183116143be5760006143c6565b856060015183035b602087015260a08b015161446e57600e546101408c0151604051630e7176c360e11b81526001600160a01b0390921691631ce2ed869161440c9160040190815260200190565b600060405180830381600087803b15801561442657600080fd5b505af115801561443a573d6000803e3d6000fd5b505050508a600001511561445d576101408b01516007805491909103905561446e565b6101408b0151600880549190910390555b505050505095945050505050565b84840160006b053a680649b3e32378b13f52676765c793fa10079d601b1b8302600e546040516339dbe92160e21b8152929091046004830181905292506001600160a01b03169063e76fa48490602401600060405180830381600087803b1580156144e657600080fd5b505af11580156144fa573d6000803e3d6000fd5b505050506000676765c793fa10079d601b1b6ac34556b3f6459039627ea484028161453557634e487b7160e01b600052601260045260246000fd5b04828403039050858101850180156145a657600e5460405163c0c8835760e01b8152600481018390526001600160a01b039091169063c0c8835790602401600060405180830381600087803b15801561458d57600080fd5b505af11580156145a1573d6000803e3d6000fd5b505050505b81156145c2576017546145c2906001600160a01b031683613002565b6145ce33888801613002565b336001600160a01b038c167f3d7c224e9ad9e12f013ba8a086e40c61608308a8810a12b8fa970887f0feb6aa8c8a8a8888676765c793fa10079d601b1b6ac34556b3f6459039627ea48d02048d60405161462e9796959493929190615cad565b60405180910390a35050505050505050505050565b6001600160a01b03811660009081526005602052604090208054600181018255905b50919050565b600061090661467861341f565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006146ca8787878761508a565b915091506146d781615177565b5095945050505050565b6000826146ee858461537b565b14949350505050565b60008182848161471757634e487b7160e01b600052601260045260246000fd5b0615614724576001614727565b60005b60ff1683858161474757634e487b7160e01b600052601260045260246000fd5b0401029392505050565b60008183106147605781614762565b825b9392505050565b60004282014340846040516020016147a693929190928352602083019190915260601b6bffffffffffffffffffffffff1916604082015260540190565b60408051601f1981840301815291905280516020909101209392505050565b600080600086610160015111156147f0576147e285848601614751565b90508092506000935061487c565b60a08601516148775785511561480e57600780548590039055614818565b6008805485900390555b600e54604051630e7176c360e11b8152600481018690526001600160a01b0390911690631ce2ed8690602401600060405180830381600087803b15801561485e57600080fd5b505af1158015614872573d6000803e3d6000fd5b505050505b508282015b600e546040516339dbe92160e21b81526b053a680649b3e32378b13f52676765c793fa10079d601b1b8402046004820181905293506001600160a01b039091169063e76fa48490602401600060405180830381600087803b1580156148e057600080fd5b505af11580156148f4573d6000803e3d6000fd5b505050506000676765c793fa10079d601b1b6ac34556b3f6459039627ea483028161492f57634e487b7160e01b600052601260045260246000fd5b60175491900484840303915061494e906001600160a01b031682613002565b600e5460405163c0c8835760e01b8152600481018390526001600160a01b039091169063c0c8835790602401600060405180830381600087803b15801561499457600080fd5b505af11580156149a8573d6000803e3d6000fd5b505050505050949350505050565b60a0850151614a9d578451614a3357600e5460c0860151604051633f9d44fd60e01b81526001600160a01b0390921691633f9d44fd916149fc9160040190815260200190565b600060405180830381600087803b158015614a1657600080fd5b505af1158015614a2a573d6000803e3d6000fd5b50505050614a9d565b600e5460c08601516040516310d6833b60e31b81526001600160a01b03909216916386b419d891614a6a9160040190815260200190565b600060405180830381600087803b158015614a8457600080fd5b505af1158015614a98573d6000803e3d6000fd5b505050505b600085608001518660600151018510614ab7576000614ab9565b835b82876101400151010390508561014001518110614b3757600e546001600160a01b03166365407202614aeb88846153fd565b6040518263ffffffff1660e01b8152600401614b0991815260200190565b600060405180830381600087803b158015614b2357600080fd5b505af1158015612463573d6000803e3d6000fd5b505050505050565b6000806000614b5087868801614751565b90506000614b5c612fca565b90508a60a0015160001415614b7c576101408b0151600780549190910390555b60008a90506000600a60009054906101000a90046001600160a01b03166001600160a01b03166354f4758f8e848e86888d6040518763ffffffff1660e01b8152600401614bce96959493929190615bb1565b602060405180830381600087803b158015614be857600080fd5b505af1158015614bfc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614c2091906159f8565b9050808d610140015111614c35576000614c3e565b808d6101400151035b9550838a039450614c518287878a615543565b5050505097509795505050505050565b6000806000614d0289601060009054906101000a90046001600160a01b03166001600160a01b03166307c5ed228e6040518263ffffffff1660e01b8152600401614cab9190615ba2565b60206040518083038186803b158015614cc357600080fd5b505afa158015614cd7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614cfb91906159f8565b8a016155c4565b90506000614d1088886155c4565b9050818c610140015111614d25576000614d2e565b818c6101400151035b9350808611614d3e576000614d42565b8086035b92508b60a0015160001415614e96578b5115614d6d576101408c015160078054919091039055614d7e565b6101408c0151600880549190910390555b600083118015614d8c575084155b15614df057600e5460405163c0c8835760e01b8152600481018590526001600160a01b039091169063c0c8835790602401600060405180830381600087803b158015614dd757600080fd5b505af1158015614deb573d6000803e3d6000fd5b505050505b8415614e6557600e546101408d0151604051630e7176c360e11b81526001600160a01b0390921691631ce2ed8691614e2e9160040190815260200190565b600060405180830381600087803b158015614e4857600080fd5b505af1158015614e5c573d6000803e3d6000fd5b50505050614ef6565b600e54604051630e7176c360e11b8152600481018490526001600160a01b0390911690631ce2ed8690602401614e2e565b600e5460405163c0c8835760e01b815284860160048201526001600160a01b039091169063c0c8835790602401600060405180830381600087803b158015614edd57600080fd5b505af1158015614ef1573d6000803e3d6000fd5b505050505b84158015614f0657506000838501115b15614f1757614f178b848601613002565b50509850989650505050505050565b60a083015161500d578251614fa357600e5460c0840151604051633f9d44fd60e01b81526001600160a01b0390921691633f9d44fd91614f6c9160040190815260200190565b600060405180830381600087803b158015614f8657600080fd5b505af1158015614f9a573d6000803e3d6000fd5b5050505061500d565b600e5460c08401516040516310d6833b60e31b81526001600160a01b03909216916386b419d891614fda9160040190815260200190565b600060405180830381600087803b158015614ff457600080fd5b505af1158015615008573d6000803e3d6000fd5b505050505b600e546101408401516001600160a01b039091169063654072029061503590869085016153fd565b6040518263ffffffff1660e01b815260040161505391815260200190565b600060405180830381600087803b15801561506d57600080fd5b505af1158015615081573d6000803e3d6000fd5b50505050505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156150c1575060009050600361516e565b8460ff16601b141580156150d957508460ff16601c14155b156150ea575060009050600461516e565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561513e573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166151675760006001925092505061516e565b9150600090505b94509492505050565b600081600481111561519957634e487b7160e01b600052602160045260246000fd5b14156151a25750565b60018160048111156151c457634e487b7160e01b600052602160045260246000fd5b14156152125760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610c44565b600281600481111561523457634e487b7160e01b600052602160045260246000fd5b14156152825760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610c44565b60038160048111156152a457634e487b7160e01b600052602160045260246000fd5b14156152fd5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610c44565b600481600481111561531f57634e487b7160e01b600052602160045260246000fd5b14156153785760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610c44565b50565b600081815b84518110156153f55760008582815181106153ab57634e487b7160e01b600052603260045260246000fd5b602002602001015190508083116153d157600083815260208290526040902092506153e2565b600081815260208490526040902092505b50806153ed81615d80565b915050615380565b509392505050565b6000676765c793fa10079d601b1b8360c00151670de0b6b3a7640000615446676765c793fa10079d601b1b86026b053a680649b3e32378b13f5267016345785d8a000002614751565b85028161546357634e487b7160e01b600052601260045260246000fd5b046154f46b0709fa55642a614ae4f586a686026105b06154d1676765c793fa10079d601b1b61115c02676765c793fa10079d601b1b6154cb6ac34556b3f6459039627ea4676765c793fa10079d601b1b018d6080015102676765c793fa10079d601b1b6146f7565b03614751565b8802816154ee57634e487b7160e01b600052601260045260246000fd5b04614751565b676765c793fa10079d601b1b860201018161551f57634e487b7160e01b600052601260045260246000fd5b048161553b57634e487b7160e01b600052601260045260246000fd5b049392505050565b8061315557821561555a5761555a84838501613002565b811561315557600e5460405163c0c8835760e01b8152600481018490526001600160a01b039091169063c0c8835790602401600060405180830381600087803b1580156155a657600080fd5b505af11580156155ba573d6000803e3d6000fd5b5050505050505050565b60008183116147605781614762565b60008083601f8401126155e4578182fd5b50813567ffffffffffffffff8111156155fb578182fd5b6020830191508360208260051b850101111561561657600080fd5b9250929050565b805161562881615dc6565b919050565b60006020828403121561563e578081fd5b813561476281615db1565b60006020828403121561565a578081fd5b815161476281615db1565b60008060408385031215615677578081fd5b823561568281615db1565b9150602083013561569281615db1565b809150509250929050565b6000806000606084860312156156b1578081fd5b83356156bc81615db1565b925060208401356156cc81615db1565b929592945050506040919091013590565b600080600080600080600060e0888a0312156156f7578283fd5b873561570281615db1565b9650602088013561571281615db1565b95506040880135945060608801359350608088013560ff81168114615735578384fd5b9699959850939692959460a0840135945060c09093013592915050565b60008060408385031215615764578182fd5b823561576f81615db1565b946020939093013593505050565b60008060008060608587031215615792578384fd5b843561579d81615db1565b935060208501359250604085013567ffffffffffffffff8111156157bf578283fd5b6157cb878288016155d3565b95989497509550505050565b6000806000806000608086880312156157ee578081fd5b85356157f981615db1565b945060208601359350604086013567ffffffffffffffff81111561581b578182fd5b615827888289016155d3565b909450925050606086013561583b81615dc6565b809150509295509295909350565b60008060006060848603121561585d578081fd5b833561586881615db1565b925060208401359150604084013561587f81615dc6565b809150509250925092565b60006020828403121561589b578081fd5b815161476281615dc6565b600061018082840312156158b8578081fd5b6158c0615ce4565b6158c98361561d565b81526158d76020840161561d565b60208201526158e86040840161561d565b6040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e082015261010061592d81850161561d565b9082015261012083810151908201526101408084015190820152610160928301519281019290925250919050565b600060c0828403121561596c578081fd5b60405160c0810181811067ffffffffffffffff8211171561599b57634e487b7160e01b83526041600452602483fd5b8060405250825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a08201528091505092915050565b6000602082840312156159f1578081fd5b5035919050565b600060208284031215615a09578081fd5b5051919050565b600080600060608486031215615a24578081fd5b833592506020840135615a3681615dc6565b9150604084013561587f81615dc6565b8051151582526020810151615a5f602084018215159052565b506040810151615a73604084018215159052565b50606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e083015261010080820151615aba8285018215159052565b50506101208181015190830152610140808201519083015261016090810151910152565b6001600160a01b03929092168252602082015260400190565b9283526001600160a01b039190911660208301521515604082015260600190565b6000602080835283518082850152825b81811015615b4457858101830151858201604001528201615b28565b81811115615b555783604083870101525b50601f01601f1916929092016040019392505050565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b61018081016109068284615a46565b6102208101615bc08289615a46565b6001600160a01b039687166101808301526101a0820195909552929094166101c08301526101e082015291151561020090920191909152919050565b6102008101615c0b8288615a46565b6001600160a01b03959095166101808201526101a08101939093526101c08301919091526101e090910152919050565b6101e08101615c4a8287615a46565b84610180830152836101a0830152826101c083015295945050505050565b60006102408201905088825287151560208301528660408301528560608301528460808301528360a0830152615ca160c0830184615a46565b98975050505050505050565b6000610240820190508882528760208301528660408301528560608301528460808301528360a0830152615ca160c0830184615a46565b604051610180810167ffffffffffffffff81118282101715615d1657634e487b7160e01b600052604160045260246000fd5b60405290565b60008219821115615d2f57615d2f615d9b565b500190565b600082821015615d4657615d46615d9b565b500390565b600181811c90821680615d5f57607f821691505b6020821081141561466557634e487b7160e01b600052602260045260246000fd5b6000600019821415615d9457615d94615d9b565b5060010190565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b038116811461537857600080fd5b801515811461537857600080fdfea2646970667358221220cf7fec9b990305171b472ea11addeeab57dabb8532cd6cde4b8907984b8c951864736f6c63430008040033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000dca40b6fb95e9c1c4511f7758bc6f3aec7474444000000000000000000000000f2ebcc36ecbbf57bcf7d7531fe24f137afc4c555

-----Decoded View---------------
Arg [0] : _oaGrantor (address): 0xDCA40B6FB95e9C1C4511F7758Bc6f3aec7474444
Arg [1] : _oaBeneficiary (address): 0xf2EbcC36ecbbF57BCf7D7531FE24f137Afc4C555

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000dca40b6fb95e9c1c4511f7758bc6f3aec7474444
Arg [1] : 000000000000000000000000f2ebcc36ecbbf57bcf7d7531fe24f137afc4c555


Deployed Bytecode Sourcemap

59440:62722:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;61581:652;;;;;;:::i;:::-;;:::i;:::-;;67819:196;;;:::i;:::-;;;14255:25:1;;;14243:2;14228:18;67819:196:0;;;;;;;;11857:100;;;:::i;:::-;;;;;;;:::i;14208:201::-;;;;;;:::i;:::-;;:::i;:::-;;;14082:14:1;;14075:22;14057:41;;14045:2;14030:18;14208:201:0;14012:92:1;66694:747:0;;;;;;:::i;:::-;;:::i;56061:35::-;;;;;-1:-1:-1;;;;;56061:35:0;;;;;;-1:-1:-1;;;;;10451:32:1;;;10433:51;;10421:2;10406:18;56061:35:0;10388:102:1;60582:380:0;;;;;;:::i;:::-;;:::i;56359:28::-;;;;;-1:-1:-1;;;;;56359:28:0;;;12977:108;13065:12;;12977:108;;112172:184;;;;;;:::i;:::-;;:::i;56220:30::-;;;;;-1:-1:-1;;;;;56220:30:0;;;55983;;;;;;95920:729;;;:::i;14989:295::-;;;;;;:::i;:::-;;:::i;68416:1388::-;;;;;;:::i;:::-;;:::i;56020:32::-;;;;;;56552:24;;;;;-1:-1:-1;;;;;56552:24:0;;;60391:98;;;55293:1;27718:36:1;;27706:2;27691:18;60391:98:0;27673:87:1;44234:115:0;;;:::i;56425:29::-;;;;;-1:-1:-1;;;;;56425:29:0;;;15693:238;;;;;;:::i;:::-;;:::i;70437:164::-;;;;;;:::i;:::-;;:::i;56712:32::-;;;;;;65289:824;;;;;;:::i;:::-;;:::i;56148:29::-;;;;;-1:-1:-1;;;;;56148:29:0;;;87855:6884;;;;;;:::i;:::-;;:::i;61046:359::-;;;;;;:::i;:::-;;:::i;63242:481::-;;;;;;:::i;:::-;;:::i;56583:28::-;;;;;-1:-1:-1;;;;;56583:28:0;;;66121:389;;;;;;:::i;:::-;;:::i;13148:127::-;;;;;;:::i;:::-;-1:-1:-1;;;;;13249:18:0;13222:7;13249:18;;;;;;;;;;;;13148:127;112749:183;;;;;;:::i;:::-;;:::i;96740:191::-;;;;;;:::i;:::-;;:::i;43976:128::-;;;;;;:::i;:::-;;:::i;56461:26::-;;;;;-1:-1:-1;;;;;56461:26:0;;;12076:104;;;:::i;63889:1234::-;;;;;;:::i;:::-;;:::i;70735:354::-;;;;;;:::i;:::-;;:::i;16434:436::-;;;;;;:::i;:::-;;:::i;13481:193::-;;;;;;:::i;:::-;;:::i;62348:743::-;;;;;;:::i;:::-;;:::i;56290:29::-;;;;;-1:-1:-1;;;;;56290:29:0;;;56664:39;;;;;;:::i;:::-;;;;;;;;;;;;;;;;113035:187;;;;;;:::i;:::-;;:::i;103205:1256::-;;;;;;:::i;:::-;;:::i;43265:645::-;;;;;;:::i;:::-;;:::i;69993:349::-;;;;;;:::i;:::-;;:::i;13737:151::-;;;;;;:::i;:::-;;:::i;111868:202::-;;;;;;:::i;:::-;;:::i;112460:188::-;;;;;;:::i;:::-;;:::i;55480:53::-;;55523:10;55480:53;;97269:4756;;;;;;:::i;:::-;;:::i;61581:652::-;-1:-1:-1;;;;;61958:22:0;;61954:53;;61989:18;;-1:-1:-1;;;61989:18:0;;;;;;;;;;;61954:53;62022:14;;-1:-1:-1;;;;;62022:14:0;:28;62018:60;;62059:19;;-1:-1:-1;;;62059:19:0;;;;;;;;;;;62018:60;62089:14;:25;;-1:-1:-1;;;;;62089:25:0;;;-1:-1:-1;;;;;;62089:25:0;;;;;;;;62125:12;:39;;;;;;;;;;62175:21;;:50;;-1:-1:-1;;;62175:50:0;;;;;10433:51:1;;;;62175:21:0;;:40;;10406:18:1;;62175:50:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;61581:652;:::o;67819:196::-;67867:7;67979:17;;67961:15;;67935:8;;;;;;;;;-1:-1:-1;;;;;67935:8:0;-1:-1:-1;;;;;67935:21:0;;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;13065:12;;67919:39;:57;:77;67912:84;;67819:196;:::o;11857:100::-;11911:13;11944:5;11937:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11857:100;:::o;14208:201::-;14291:4;9556:10;14347:32;9556:10;14363:7;14372:6;14347:8;:32::i;:::-;14397:4;14390:11;;;14208:201;;;;;:::o;66694:747::-;-1:-1:-1;;;;;66955:26:0;;66951:57;;66990:18;;-1:-1:-1;;;66990:18:0;;;;;;;;;;;66951:57;67037:9;;-1:-1:-1;;;;;67037:9:0;67023:10;:23;;;:52;;-1:-1:-1;67050:11:0;;-1:-1:-1;;;;;67050:11:0;:25;;67023:52;67019:111;;;67099:19;;-1:-1:-1;;;67099:19:0;;;;;;;;;;;67019:111;67140:11;:26;;-1:-1:-1;;;;;67140:26:0;;;-1:-1:-1;;;;;;67140:26:0;;;;;;;;67177:13;:35;;;;;;;;;;67225:12;;:42;;-1:-1:-1;;;67225:42:0;;;;;10433:51:1;;;;67225:12:0;;:28;;10406:18:1;;67225:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;67278:8:0;;:38;;-1:-1:-1;;;67278:38:0;;-1:-1:-1;;;;;10451:32:1;;;67278:38:0;;;10433:51:1;67278:8:0;;;;-1:-1:-1;67278:24:0;;-1:-1:-1;10406:18:1;;67278:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;67327:14:0;;:44;;-1:-1:-1;;;67327:44:0;;-1:-1:-1;;;;;10451:32:1;;;67327:44:0;;;10433:51:1;67327:14:0;;;;-1:-1:-1;67327:30:0;;-1:-1:-1;10406:18:1;;67327:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;67382:21:0;;:51;;-1:-1:-1;;;67382:51:0;;-1:-1:-1;;;;;10451:32:1;;;67382:51:0;;;10433::1;67382:21:0;;;;-1:-1:-1;67382:37:0;;-1:-1:-1;10406:18:1;;67382:51:0;10388:102:1;60582:380:0;-1:-1:-1;;;;;60659:28:0;;60655:59;;60696:18;;-1:-1:-1;;;60696:18:0;;;;;;;;;;;60655:59;60743:9;;-1:-1:-1;;;;;60743:9:0;60729:10;:23;60725:55;;60761:19;;-1:-1:-1;;;60761:19:0;;;;;;;;;;;60725:55;60791:13;:30;;-1:-1:-1;;;;;;60791:30:0;-1:-1:-1;;;;;60791:30:0;;;;;;;;;60832:21;;:54;;-1:-1:-1;;;60832:54:0;;;;;10433:51:1;;;;60832:21:0;;;;:38;;10406:18:1;;60832:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;60902:52;60922:14;60938:15;60902:52;;;;;;;:::i;:::-;;;;;;;;60582:380;:::o;112172:184::-;112255:14;;-1:-1:-1;;;;;112255:14:0;112241:10;:28;112237:60;;112278:19;;-1:-1:-1;;;112278:19:0;;;;;;;;;;;112237:60;112320:15;:26;;;;;;;;112172:184::o;95920:729::-;7071:1;7669:7;;:19;;7661:63;;;;-1:-1:-1;;;7661:63:0;;;;;;;:::i;:::-;;;;;;;;;7071:1;7802:7;:18;96226:9:::1;::::0;-1:-1:-1;;;;;96226:9:0::1;96212:10;:23;;::::0;:64:::1;;;96274:2;96252:19;:17;:19::i;:::-;:24;96212:64;:103;;;-1:-1:-1::0;96293:17:0::1;::::0;:22;96212:103:::1;96208:183;;;96348:31;;-1:-1:-1::0;;;96348:31:0::1;;;;;;;;;;;96208:183;96576:13;::::0;96591:17:::1;::::0;96570:39:::1;::::0;-1:-1:-1;;;;;96576:13:0::1;::::0;96570:5:::1;:39::i;:::-;96640:1;96620:17;:21:::0;7027:1;7981:7;:22;95920:729::o;14989:295::-;15120:4;9556:10;15178:38;15194:4;9556:10;15209:6;15178:15;:38::i;:::-;15227:27;15237:4;15243:2;15247:6;15227:9;:27::i;:::-;-1:-1:-1;15272:4:0;;14989:295;-1:-1:-1;;;;14989:295:0:o;68416:1388::-;7071:1;7669:7;;:19;;7661:63;;;;-1:-1:-1;;;7661:63:0;;;;;;;:::i;:::-;7071:1;7802:7;:18;68670:42:::1;68679:11:::0;68692:6;68700:11;;68670:8:::1;:42::i;:::-;68665:98;;68736:15;;-1:-1:-1::0;;;68736:15:0::1;;;;;;;;;;;68665:98;-1:-1:-1::0;;;;;68775:20:0;::::1;;::::0;;;:7:::1;:20;::::0;;;;:27;;-1:-1:-1;;68775:27:0::1;68798:4;68775:27;::::0;;68834:10:::1;68819:25;::::0;:54:::1;;;68870:3;68848:19;:17;:19::i;:::-;:25;68819:54;:134;;;;55523:10;68891:15;:34;:61;;;;-1:-1:-1::0;;;;;;68929:23:0;::::1;55200:42;68929:23;68891:61;68815:404;;;68979:50;::::0;-1:-1:-1;;;68979:50:0;;68993:4:::1;::::0;68979:29:::1;::::0;:50:::1;::::0;69009:11;;69022:6;;68979:50:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;69048:7;69044:85;;;69076:13;::::0;:37:::1;::::0;-1:-1:-1;;;69076:37:0;;-1:-1:-1;;;;;69076:13:0;;::::1;::::0;:21:::1;::::0;:37:::1;::::0;69098:11;;69076:13:::1;::::0;:37:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;69044:85;69148:38;::::0;;69154:10:::1;10735:34:1::0;;-1:-1:-1;;;;;10805:15:1;;10800:2;10785:18;;10778:43;10837:18;;;10830:34;;;69148:38:0::1;::::0;10685:2:1;10670:18;69148:38:0::1;;;;;;;69201:7;;68815:404;69299:7;:68;;;;;69310:57;69323:10;54409:27;-1:-1:-1::0;;;69362:1:0::1;69365::::0;69310:12:::1;:57::i;:::-;69295:137;;;69384:13;::::0;:36:::1;::::0;-1:-1:-1;;;69384:36:0;;-1:-1:-1;;;;;69384:13:0;;::::1;::::0;:21:::1;::::0;:36:::1;::::0;69406:10:::1;::::0;69384:13;;:36:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;69295:137;69596:55;::::0;-1:-1:-1;;;69596:55:0;;69610:4:::1;::::0;69596:29:::1;::::0;:55:::1;::::0;69626:10:::1;::::0;69638:12:::1;::::0;69596:55:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;69666:65:0::1;::::0;-1:-1:-1;;;69666:65:0;;69680:4:::1;::::0;69666:29:::1;::::0;:65:::1;::::0;69696:11;;-1:-1:-1;;69709:21:0;;;69666:65:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;69758:38:0::1;::::0;;69764:10:::1;10735:34:1::0;;-1:-1:-1;;;;;10805:15:1;;10800:2;10785:18;;10778:43;10837:18;;;10830:34;;;69758:38:0::1;::::0;10685:2:1;10670:18;69758:38:0::1;;;;;;;7833:1;-1:-1:-1::0;;7027:1:0;7981:7;:22;-1:-1:-1;;;68416:1388:0:o;44234:115::-;44294:7;44321:20;:18;:20::i;:::-;44314:27;;44234:115;:::o;15693:238::-;15781:4;9556:10;15837:64;9556:10;15853:7;15890:10;15862:25;9556:10;15853:7;15862:9;:25::i;:::-;:38;;;;:::i;:::-;15837:8;:64::i;70437:164::-;70520:14;;-1:-1:-1;;;;;70520:14:0;70506:10;:28;70502:60;;70543:19;;-1:-1:-1;;;70543:19:0;;;;;;;;;;;70502:60;70573:20;70579:5;70586:6;70573:5;:20::i;:::-;70437:164;;:::o;65289:824::-;-1:-1:-1;;;;;65652:28:0;;65648:59;;65689:18;;-1:-1:-1;;;65689:18:0;;;;;;;;;;;65648:59;65722:13;;-1:-1:-1;;;;;65722:13:0;:27;65718:59;;65758:19;;-1:-1:-1;;;65758:19:0;;;;;;;;;;;65718:59;65788:13;:30;;-1:-1:-1;;;;;65788:30:0;;;-1:-1:-1;;;;;;65788:30:0;;;;;;;;65829:14;:40;;;;;;;;;;65880:12;;:46;;-1:-1:-1;;;65880:46:0;;;;;10433:51:1;;;;65880:12:0;;:30;;10406:18:1;;65880:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;65937:8:0;;:42;;-1:-1:-1;;;65937:42:0;;-1:-1:-1;;;;;10451:32:1;;;65937:42:0;;;10433:51:1;65937:8:0;;;;-1:-1:-1;65937:26:0;;-1:-1:-1;10406:18:1;;65937:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;65990:21:0;;:55;;-1:-1:-1;;;65990:55:0;;-1:-1:-1;;;;;10451:32:1;;;65990:55:0;;;10433:51:1;65990:21:0;;;;-1:-1:-1;65990:39:0;;-1:-1:-1;10406:18:1;;65990:55:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;66056:15:0;;:49;;-1:-1:-1;;;66056:49:0;;-1:-1:-1;;;;;10451:32:1;;;66056:49:0;;;10433:51:1;66056:15:0;;;;-1:-1:-1;66056:33:0;;-1:-1:-1;10406:18:1;;66056:49:0;10388:102:1;87855:6884:0;7071:1;7669:7;;:19;;7661:63;;;;-1:-1:-1;;;7661:63:0;;;;;;;:::i;:::-;7071:1;7802:7;:18;88018:14:::1;::::0;:49:::1;::::0;-1:-1:-1;;;88018:49:0;;87992:23:::1;::::0;-1:-1:-1;;;;;88018:14:0::1;::::0;:25:::1;::::0;:49:::1;::::0;88044:10:::1;::::0;88056;;88018:49:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;87992:75;;88103:24;88130:19;:17;:19::i;:::-;88651:14;::::0;::::1;::::0;88515:17:::1;::::0;::::1;::::0;88103:46;;-1:-1:-1;88438:18:0::1;::::0;88498:34;::::1;88478:55:::0;::::1;:155;;88615:5;:17;;;88598:5;:14;;;:34;88478:155;;;88557:16;88478:155;88710:14;::::0;:192:::1;::::0;-1:-1:-1;;;88710:192:0;;88459:206;;;::::1;::::0;-1:-1:-1;;;;;;88710:14:0::1;::::0;:31:::1;::::0;:192:::1;::::0;88760:5;;88784:10:::1;::::0;88813;;88842:16;;88459:206;;88710:192:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;89047:25;89098:1;89075:8;;;;;;;;;-1:-1:-1::0;;;;;89075:8:0::1;-1:-1:-1::0;;;;;89075:18:0::1;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:24;89047:52;;89228:5;:17;;;89215:10;:30;:92;;;;89291:16;89266:5;:17;;;89249:5;:14;;;:34;89286:1;89249:38;:58;;89215:92;89211:4718;;;89554:8;::::0;:56:::1;::::0;-1:-1:-1;;;89554:56:0;;-1:-1:-1;;;;;89554:8:0;;::::1;::::0;:32:::1;::::0;:56:::1;::::0;:8:::1;::::0;89590:10:::1;::::0;89602:7;;89554:56:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;89629:8:0::1;::::0;:50:::1;::::0;-1:-1:-1;;;89629:50:0;;-1:-1:-1;;;;;89629:8:0;;::::1;::::0;:26:::1;::::0;:50:::1;::::0;:8:::1;::::0;89659:10:::1;::::0;89671:7;;89629:50:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;89698:8:0::1;::::0;:51:::1;::::0;-1:-1:-1;;;89698:51:0;;-1:-1:-1;;;;;89698:8:0;;::::1;::::0;:27:::1;::::0;:51:::1;::::0;:8:::1;::::0;89729:10:::1;::::0;89741:7;;89698:51:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;89768:8:0::1;::::0;:52:::1;::::0;-1:-1:-1;;;89768:52:0;;-1:-1:-1;;;;;89768:8:0;;::::1;::::0;:28:::1;::::0;:52:::1;::::0;:8:::1;::::0;89800:10:::1;::::0;89812:7;;89768:52:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;89211:4718;;;90693:14;::::0;::::1;::::0;:27;::::1;-1:-1:-1::0;;90693:31:0;90747:33;;::::1;90743:372;;;90909:8;::::0;:186:::1;::::0;-1:-1:-1;;;90909:186:0;;-1:-1:-1;;;;;90909:8:0;;::::1;::::0;:32:::1;::::0;:186:::1;::::0;90968:33;;::::1;::::0;91028:10:::1;::::0;91065:7;;90909:186:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;90743:372;93296:8;::::0;-1:-1:-1;;;;;93296:8:0::1;:26;93339:2;93323:13:::0;:18:::1;93343:10;93355:7;93296:67;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;93599:8:0::1;::::0;-1:-1:-1;;;;;93599:8:0::1;:27;93643:3;93627:13:::0;:19:::1;93648:10;93660:7;93599:69;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;93842:8:0::1;::::0;-1:-1:-1;;;;;93842:8:0::1;:28;93887:4;93871:13:::0;:20:::1;93893:10;93905:7;93842:71;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;89211:4718;;94052:8;::::0;94075:14:::1;::::0;::::1;::::0;94126:12;;94052:87:::1;::::0;-1:-1:-1;;;94052:87:0;;::::1;::::0;::::1;26748:25:1::0;;;94092:27:0;;::::1;-1:-1:-1::0;;94092:31:0;26789:18:1;;;26782:34;26859:14;26852:22;26832:18;;;26825:50;94028:21:0::1;::::0;-1:-1:-1;;;;;94052:8:0::1;::::0;:22:::1;::::0;26721:18:1;;94052:87:0::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;94028:111;;94154:15;55603:19;94193:13;94172:5;:18;;;:34;:52;;;-1:-1:-1::0;;;94172:52:0::1;;;;;;;;;;94154:70;;94292:26;94337:24:::0;94380:23:::1;94434:68;94448:10;94460;94472:7;94481:11;94494:7;94434:13;:68::i;:::-;94273:229;;;;;;94517:24;94544:5;94517:32;;94578:10;-1:-1:-1::0;;;;;94569:151:0::1;;94590:10;94602:11;94632:18;94652:7;94678:16;94696:15;94713:6;94569:151;;;;;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1::0;;7027:1:0;7981:7;:22;-1:-1:-1;;;;;;;;;;;87855:6884:0:o;61046:359::-;-1:-1:-1;;;;;61118:27:0;;61114:58;;61154:18;;-1:-1:-1;;;61154:18:0;;;;;;;;;;;61114:58;61201:9;;-1:-1:-1;;;;;61201:9:0;61187:10;:23;61183:55;;61219:19;;-1:-1:-1;;;61219:19:0;;;;;;;;;;;61183:55;61249:9;:25;;-1:-1:-1;;;;;;61249:25:0;-1:-1:-1;;;;;61249:25:0;;;;;;;;;61285:21;;:49;;-1:-1:-1;;;61285:49:0;;;;;10433:51:1;;;;61285:21:0;;;;:34;;10406:18:1;;61285:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;61350:47;61366:13;61381:15;61350:47;;;;;;;:::i;63242:481::-;-1:-1:-1;;;;;63453:23:0;;63449:54;;63485:18;;-1:-1:-1;;;63485:18:0;;;;;;;;;;;63449:54;63518:15;;-1:-1:-1;;;;;63518:15:0;:29;63514:61;;63556:19;;-1:-1:-1;;;63556:19:0;;;;;;;;;;;63514:61;63586:15;:27;;-1:-1:-1;;;;;63586:27:0;;;-1:-1:-1;;;;;;63586:27:0;;;;;;;;63624:8;:37;;;;;;;;;;63672:12;;:43;;-1:-1:-1;;;63672:43:0;;;;;10433:51:1;;;;63672:12:0;;:32;;10406:18:1;;63672:43:0;10388:102:1;66121:389:0;-1:-1:-1;;;;;66191:22:0;;66187:53;;66222:18;;-1:-1:-1;;;66222:18:0;;;;;;;;;;;66187:53;66269:9;;-1:-1:-1;;;;;66269:9:0;66255:10;:23;;;:55;;-1:-1:-1;66282:14:0;;-1:-1:-1;;;;;66282:14:0;:28;;66255:55;66251:114;;;66334:19;;-1:-1:-1;;;66334:19:0;;;;;;;;;;;66251:114;66375:14;:25;;-1:-1:-1;;;;;;66375:25:0;-1:-1:-1;;;;;66375:25:0;;;;;;;;;66411:14;;:43;;-1:-1:-1;;;66411:43:0;;;;;10433:51:1;;;;66411:14:0;;;;:33;;10406:18:1;;66411:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;66465:8:0;;:37;;-1:-1:-1;;;66465:37:0;;-1:-1:-1;;;;;10451:32:1;;;66465:37:0;;;10433:51:1;66465:8:0;;;;-1:-1:-1;66465:27:0;;-1:-1:-1;10406:18:1;;66465:37:0;10388:102:1;112749:183:0;112832:13;;-1:-1:-1;;;;;112832:13:0;112818:10;:27;112814:59;;112854:19;;-1:-1:-1;;;112854:19:0;;;;;;;;;;;112814:59;112896:15;:26;;;;;;;112749:183::o;96740:191::-;96834:13;;-1:-1:-1;;;;;96834:13:0;96820:10;:27;96816:59;;96856:19;;-1:-1:-1;;;96856:19:0;;;;;;;;;;;96816:59;96907:16;96886:17;;:37;;;;;;;:::i;:::-;;;;-1:-1:-1;;;96740:191:0:o;43976:128::-;-1:-1:-1;;;;;44072:14:0;;44045:7;44072:14;;;:7;:14;;;;;4735;44072:24;4643:114;12076:104;12132:13;12165:7;12158:14;;;;;:::i;63889:1234::-;-1:-1:-1;;;;;64169:24:0;;64165:55;;64202:18;;-1:-1:-1;;;64202:18:0;;;;;;;;;;;64165:55;64235:14;;-1:-1:-1;;;;;64235:14:0;:28;64231:60;;64272:19;;-1:-1:-1;;;64272:19:0;;;;;;;;;;;64231:60;64873:15;:38;;-1:-1:-1;;;;;64873:38:0;;;-1:-1:-1;;;;;;64873:38:0;;;;;;;;64922:14;:27;;;;;;;;;;64960:8;;:39;;-1:-1:-1;;;64960:39:0;;;;;10433:51:1;;;;64960:8:0;;:27;;10406:18:1;;64960:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;65010:21:0;;:52;;-1:-1:-1;;;65010:52:0;;-1:-1:-1;;;;;10451:32:1;;;65010:52:0;;;10433:51:1;65010:21:0;;;;-1:-1:-1;65010:40:0;;-1:-1:-1;10406:18:1;;65010:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;65073:12:0;;:42;;-1:-1:-1;;;65073:42:0;;-1:-1:-1;;;;;10451:32:1;;;65073:42:0;;;10433:51:1;65073:12:0;;;;-1:-1:-1;65073:30:0;;-1:-1:-1;10406:18:1;;65073:42:0;10388:102:1;70735:354:0;70832:20;;-1:-1:-1;;;;;70832:20:0;70818:10;:34;;;;:79;;-1:-1:-1;70883:14:0;;-1:-1:-1;;;;;70883:14:0;70869:10;:28;;70818:79;:123;;;;-1:-1:-1;70928:13:0;;-1:-1:-1;;;;;70928:13:0;70914:10;:27;;70818:123;:168;;;;-1:-1:-1;70972:14:0;;-1:-1:-1;;;;;70972:14:0;70958:10;:28;;70818:168;70800:251;;;71020:19;;-1:-1:-1;;;71020:19:0;;;;;;;;;;;70800:251;71061:20;71067:5;71074:6;71061:5;:20::i;16434:436::-;16527:4;9556:10;16527:4;16610:25;9556:10;16627:7;16610:9;:25::i;:::-;16583:52;;16674:15;16654:16;:35;;16646:85;;;;-1:-1:-1;;;16646:85:0;;22746:2:1;16646:85:0;;;22728:21:1;22785:2;22765:18;;;22758:30;22824:34;22804:18;;;22797:62;-1:-1:-1;;;22875:18:1;;;22868:35;22920:19;;16646:85:0;22718:227:1;16646:85:0;16767:60;16776:5;16783:7;16811:15;16792:16;:34;16767:8;:60::i;13481:193::-;13560:4;9556:10;13616:28;9556:10;13633:2;13637:6;13616:9;:28::i;62348:743::-;-1:-1:-1;;;;;62662:28:0;;62658:59;;62699:18;;-1:-1:-1;;;62699:18:0;;;;;;;;;;;62658:59;62732:20;;-1:-1:-1;;;;;62732:20:0;:34;62728:66;;62775:19;;-1:-1:-1;;;62775:19:0;;;;;;;;;;;62728:66;62805:20;:37;;-1:-1:-1;;;;;62805:37:0;;;-1:-1:-1;;;;;;62805:37:0;;;;;;;;62853:21;:54;;;;;;;;62348:743::o;113035:187::-;113120:13;;-1:-1:-1;;;;;113120:13:0;113106:10;:27;113102:59;;113142:19;;-1:-1:-1;;;113142:19:0;;;;;;;;;;;113102:59;113184:17;:28;;;;;;;113035:187::o;103205:1256::-;7071:1;7669:7;;:19;;7661:63;;;;-1:-1:-1;;;7661:63:0;;;;;;;:::i;:::-;7071:1;7802:7;:18;103347:14:::1;::::0;:41:::1;::::0;-1:-1:-1;;;103347:41:0;;103321:23:::1;::::0;-1:-1:-1;;;;;103347:14:0::1;::::0;:25:::1;::::0;:41:::1;::::0;103373:5;;103380:7;;103347:41:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;103321:67;;103486:25;103514:5;:12;;;:132;;103623:5;:17;;;103606:5;:14;;;:34;103643:3;103606:40;103514:132;;;103563:5;:17;;;103546:5;:14;;;:34;103583:3;103546:40;103514:132;103486:160;;103707:17;103685:19;:17;:19::i;:::-;:39;:75;;;;103759:1;103745:5;:11;;;:15;103685:75;:111;;;;103781:5;:15;;;103685:111;:154;;;-1:-1:-1::0;103817:17:0::1;::::0;::::1;::::0;:22;103685:154:::1;103663:250;;;103881:16;;-1:-1:-1::0;;;103881:16:0::1;;;;;;;;;;;103663:250;103929:37;103986:65;104001:5;104008;104015:7;104024:17;104043:7;103986:14;:65::i;:::-;103929:122;;104072:7;:68;;;;;104083:57;104096:10;54552:27;-1:-1:-1::0;;;104135:1:0::1;104138::::0;104083:12:::1;:57::i;:::-;104068:145;;;104161:13;::::0;:36:::1;::::0;-1:-1:-1;;;104161:36:0;;-1:-1:-1;;;;;104161:13:0;;::::1;::::0;:21:::1;::::0;:36:::1;::::0;104183:10:::1;::::0;104161:13;;:36:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;104068:145;104229:213;104244:5;104251:7;104260:12;:36;;;104315:12;:34;;;104351:12;:31;;;104401:12;:33;;;104436:5;104229:14;:213::i;:::-;-1:-1:-1::0;;7027:1:0;7981:7;:22;-1:-1:-1;;;;103205:1256:0:o;43265:645::-;43509:8;43490:15;:27;;43482:69;;;;-1:-1:-1;;;43482:69:0;;19243:2:1;43482:69:0;;;19225:21:1;19282:2;19262:18;;;19255:30;19321:31;19301:18;;;19294:59;19370:18;;43482:69:0;19215:179:1;43482:69:0;43564:18;42440:95;43624:5;43631:7;43640:5;43647:16;43657:5;43647:9;:16::i;:::-;43595:79;;;;;;14578:25:1;;;;-1:-1:-1;;;;;14677:15:1;;;14657:18;;;14650:43;14729:15;;;;14709:18;;;14702:43;14761:18;;;14754:34;14804:19;;;14797:35;14848:19;;;14841:35;;;14550:19;;43595:79:0;;;;;;;;;;;;43585:90;;;;;;43564:111;;43688:12;43703:28;43720:10;43703:16;:28::i;:::-;43688:43;;43744:14;43761:28;43775:4;43781:1;43784;43787;43761:13;:28::i;:::-;43744:45;;43818:5;-1:-1:-1;;;;;43808:15:0;:6;-1:-1:-1;;;;;43808:15:0;;43800:58;;;;-1:-1:-1;;;43800:58:0;;20814:2:1;43800:58:0;;;20796:21:1;20853:2;20833:18;;;20826:30;20892:32;20872:18;;;20865:60;20942:18;;43800:58:0;20786:180:1;43800:58:0;43871:31;43880:5;43887:7;43896:5;43871:8;:31::i;:::-;43265:645;;;;;;;;;;:::o;69993:349::-;70177:37;;-1:-1:-1;;9404:2:1;9400:15;;;9396:53;70177:37:0;;;9384:66:1;9466:12;;;9459:28;;;70135:4:0;;;;9503:12:1;;70177:37:0;;;-1:-1:-1;;70177:37:0;;;;;;;;;70167:48;;70177:37;70167:48;;;;-1:-1:-1;;;;;70247:20:0;;;;;;:7;:20;;;;;;70167:48;;-1:-1:-1;70247:20:0;;70246:21;:88;;;;;70284:50;70303:11;;70284:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;55881:66:0;;-1:-1:-1;70329:4:0;;-1:-1:-1;70284:18:0;;-1:-1:-1;70284:50:0:i;:::-;70226:108;69993:349;-1:-1:-1;;;;;;69993:349:0:o;13737:151::-;-1:-1:-1;;;;;13853:18:0;;;13826:7;13853:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;13737:151::o;111868:202::-;111963:15;;-1:-1:-1;;;;;111963:15:0;111949:10;:29;111945:88;;112002:19;;-1:-1:-1;;;112002:19:0;;;;;;;;;;;112460:188;112545:14;;-1:-1:-1;;;;;112545:14:0;112531:10;:28;112527:60;;112568:19;;-1:-1:-1;;;112568:19:0;;;;;;;;;;;112527:60;112610:17;:28;;;;;;;;112460:188::o;97269:4756::-;7071:1;7669:7;;:19;;7661:63;;;;-1:-1:-1;;;7661:63:0;;;;;;;:::i;:::-;7071:1;7802:7;:18;97969:14:::1;::::0;:41:::1;::::0;-1:-1:-1;;;97969:41:0;;97943:23:::1;::::0;-1:-1:-1;;;;;97969:14:0::1;::::0;:25:::1;::::0;:41:::1;::::0;97995:5;;98002:7;;97969:41:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;98302:17;::::0;::::1;::::0;98285:14:::1;::::0;::::1;::::0;97943:67;;-1:-1:-1;98285:34:0::1;98261:21;98348:19;:17;:19::i;:::-;98334:33;;98487:5;:15;;;:40;;;;;98506:5;:21;;;98487:40;98483:123;;;98555:35;;-1:-1:-1::0;;;98555:35:0::1;;;;;;;;;;;98483:123;98656:1;98642:5;:11;;;:15;:57;;;;98698:1;98678:5;:17;;;:21;98642:57;:97;;;;98726:13;98720:3;:19;98642:97;:140;;;-1:-1:-1::0;98760:17:0::1;::::0;::::1;::::0;:22;98642:140:::1;98620:246;;;98824:26;;-1:-1:-1::0;;;98824:26:0::1;;;;;;;;;;;98620:246;98933:14;::::0;:60:::1;::::0;-1:-1:-1;;;98933:60:0;;-1:-1:-1;;;;;13355:32:1;;;98933:60:0::1;::::0;::::1;13337:51:1::0;13404:18;;;13397:34;;;13447:18;;;13440:34;;;98933:14:0;;::::1;::::0;:39:::1;::::0;13310:18:1;;98933:60:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;99051:12;99082:5;:12;;;99078:360;;;-1:-1:-1::0;;;99173:62:0::1;99216:3;99212:1;54838:28;99182:5;:15;;;:27;:31;;;-1:-1:-1::0;;;99182:31:0::1;;;;;;;;;;:37;;;-1:-1:-1::0;;;99182:37:0::1;;;;;;;;;;-1:-1:-1::0;;;99173:8:0::1;:62::i;:::-;:78;;;-1:-1:-1::0;;;99173:78:0::1;;;;;;;;;;99166:85;;99078:360;;;-1:-1:-1::0;;;99350:56:0::1;99387:3;99383:1;54265:28;99359:5;:15;;;:21;:25;;;-1:-1:-1::0;;;99359:25:0::1;;;;;;;;99350:56;:72;;;-1:-1:-1::0;;;99350:72:0::1;;;;;;;;;;99343:79;;99078:360;99695:15;::::0;::::1;::::0;99663:24:::1;::::0;99690:125:::1;::::0;99787:27:::1;99695:15:::0;99809:4;99787::::1;:27::i;:::-;99719:13;99735:1;99719:17;99713:3;:23;:53;;99765:1;99713:53;;;99761:1;99745:13;99739:3;:19;:23;99713:53;99712:102;99690:4;:125::i;:::-;99663:152;;99919:5;:15;;;99915:193;;;99959:12;::::0;:47:::1;::::0;-1:-1:-1;;;99959:47:0;;-1:-1:-1;;;;;99959:12:0;;::::1;::::0;:31:::1;::::0;:47:::1;::::0;99991:5;;99998:7;;99959:47:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;99955:138;;;100031:12;::::0;:42:::1;::::0;-1:-1:-1;;;100031:42:0;;-1:-1:-1;;;;;100031:12:0;;::::1;::::0;:26:::1;::::0;:42:::1;::::0;100058:5;;100065:7;;100031:42:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;99955:138;100344:8;::::0;:20:::1;::::0;;-1:-1:-1;;;100344:20:0;;;;100329:12:::1;::::0;-1:-1:-1;;;;;100344:8:0::1;::::0;:18:::1;::::0;:20:::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;:8;:20;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;100329:35;;100390:5;:14;;;100407:1;100390:18;100383:4;:25;100379:146;;;100429:8;::::0;100462:14:::1;::::0;::::1;::::0;100429:80:::1;::::0;-1:-1:-1;;;100429:80:0;;-1:-1:-1;;;;;100429:8:0;;::::1;::::0;:32:::1;::::0;:80:::1;::::0;100462:25;;;;100429:8;100462:25;;100489:10:::1;::::0;100501:7;;100429:80:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;100379:146;100545:12:::0;;100541:286:::1;;;100597:15;::::0;::::1;::::0;100578::::1;:34:::0;;;;;::::1;::::0;;100631:8:::1;::::0;100653:18:::1;::::0;::::1;::::0;100631:41:::1;::::0;-1:-1:-1;;;100631:41:0;;-1:-1:-1;;;;;100631:8:0;;::::1;::::0;:21:::1;::::0;:41:::1;::::0;::::1;;14255:25:1::0;;;14243:2;14228:18;;14210:76;100631:41:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;100541:286;;;100734:15;::::0;::::1;::::0;100713:17:::1;:36:::0;;;;;::::1;::::0;;100768:8:::1;::::0;100792:18:::1;::::0;::::1;::::0;100768:43:::1;::::0;-1:-1:-1;;;100768:43:0;;-1:-1:-1;;;;;100768:8:0;;::::1;::::0;:23:::1;::::0;:43:::1;::::0;::::1;;14255:25:1::0;;;14243:2;14228:18;;14210:76;100768:43:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;100541:286;100891:19;::::0;::::1;::::0;100843:29:::1;::::0;100891:23;100887:742:::1;;100939:20:::0;;100935:410:::1;;101003:21;::::0;:56:::1;::::0;-1:-1:-1;;;101003:56:0;;100984:16:::1;::::0;-1:-1:-1;;;;;101003:21:0::1;::::0;:40:::1;::::0;:56:::1;::::0;101044:5;;101051:7;;101003:56:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;101131:21;::::0;101216:14:::1;::::0;::::1;::::0;101131:107:::1;::::0;-1:-1:-1;;;101131:107:0;;101170:10:::1;101131:107;::::0;::::1;11166:34:1::0;-1:-1:-1;;;;;11236:15:1;;;11216:18;;;11209:43;11268:18;;;11261:34;;;101210:20:0;;::::1;11311:18:1::0;;;11304:34;101131:21:0::1;11354:19:1::0;;;11347:51;100984:75:0;;-1:-1:-1;101131:21:0::1;::::0;:38:::1;::::0;11100:19:1;;101131:107:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;101082:156;;101280:45;101285:21;101308:16;101280:4;:45::i;:::-;101261:64;;100935:410;;100887:742;;;101385:8;::::0;101415:15:::1;::::0;::::1;::::0;-1:-1:-1;;;;;101385:8:0;;::::1;::::0;:29:::1;::::0;101415:34;-1:-1:-1;101415:75:0::1;;101489:1;101415:75;;;101470:16;101452:5;:15;;;:34;101415:75;101385:106;;;;;;;;;;;;;14255:25:1::0;;14243:2;14228:18;;14210:76;101385:106:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;101533:1;101514:16;:20;101510:104;;;101559:35;101565:10;101577:16;101559:5;:35::i;:::-;101649:7;:68;;;;;101660:57;101673:10;54552:27;-1:-1:-1::0;;;101712:1:0::1;101715::::0;101660:12:::1;:57::i;:::-;101645:145;;;101738:13;::::0;:36:::1;::::0;-1:-1:-1;;;101738:36:0;;-1:-1:-1;;;;;101738:13:0;;::::1;::::0;:21:::1;::::0;:36:::1;::::0;101760:10:::1;::::0;101738:13;;:36:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;101645:145;101945:61;::::0;;-1:-1:-1;;;;;13355:32:1;;13337:51;;13419:2;13404:18;;13397:34;;;13447:18;;;13440:34;;;101961:10:0::1;::::0;101945:61:::1;::::0;13325:2:1;13310:18;101945:61:0::1;;;;;;;-1:-1:-1::0;;7027:1:0;7981:7;:22;-1:-1:-1;;;;;;;;97269:4756:0:o;20068:380::-;-1:-1:-1;;;;;20204:19:0;;20196:68;;;;-1:-1:-1;;;20196:68:0;;21981:2:1;20196:68:0;;;21963:21:1;22020:2;22000:18;;;21993:30;22059:34;22039:18;;;22032:62;-1:-1:-1;;;22110:18:1;;;22103:34;22154:19;;20196:68:0;21953:226:1;20196:68:0;-1:-1:-1;;;;;20283:21:0;;20275:68;;;;-1:-1:-1;;;20275:68:0;;18482:2:1;20275:68:0;;;18464:21:1;18521:2;18501:18;;;18494:30;18560:34;18540:18;;;18533:62;-1:-1:-1;;;18611:18:1;;;18604:32;18653:19;;20275:68:0;18454:224:1;20275:68:0;-1:-1:-1;;;;;20356:18:0;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;20408:32;;14255:25:1;;;20408:32:0;;14228:18:1;20408:32:0;;;;;;;;20068:380;;;:::o;67449:247::-;67501:7;55523:10;67525:15;:34;67521:68;;;67568:21;;-1:-1:-1;;;67568:21:0;;;;;;;;;;;67521:68;-1:-1:-1;67671:6:0;67633:15;-1:-1:-1;;67633:34:0;67632:45;;67449:247::o;18307:399::-;-1:-1:-1;;;;;18391:21:0;;18383:65;;;;-1:-1:-1;;;18383:65:0;;23152:2:1;18383:65:0;;;23134:21:1;23191:2;23171:18;;;23164:30;23230:33;23210:18;;;23203:61;23281:18;;18383:65:0;23124:181:1;18383:65:0;18539:6;18523:12;;:22;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;;;18556:18:0;;:9;:18;;;;;;;;;;:28;;18578:6;;18556:9;:28;;18578:6;;18556:28;:::i;:::-;;;;-1:-1:-1;;18600:37:0;;14255:25:1;;;-1:-1:-1;;;;;18600:37:0;;;18617:1;;18600:37;;14243:2:1;14228:18;18600:37:0;;;;;;;70437:164;;:::o;20739:453::-;20874:24;20901:25;20911:5;20918:7;20901:9;:25::i;:::-;20874:52;;-1:-1:-1;;20941:16:0;:37;20937:248;;21023:6;21003:16;:26;;20995:68;;;;-1:-1:-1;;;20995:68:0;;18885:2:1;20995:68:0;;;18867:21:1;18924:2;18904:18;;;18897:30;18963:31;18943:18;;;18936:59;19012:18;;20995:68:0;18857:179:1;20995:68:0;21107:51;21116:5;21123:7;21151:6;21132:16;:25;21107:8;:51::i;:::-;20739:453;;;;:::o;17349:671::-;-1:-1:-1;;;;;17480:18:0;;17472:68;;;;-1:-1:-1;;;17472:68:0;;21575:2:1;17472:68:0;;;21557:21:1;21614:2;21594:18;;;21587:30;21653:34;21633:18;;;21626:62;-1:-1:-1;;;21704:18:1;;;21697:35;21749:19;;17472:68:0;21547:227:1;17472:68:0;-1:-1:-1;;;;;17559:16:0;;17551:64;;;;-1:-1:-1;;;17551:64:0;;17315:2:1;17551:64:0;;;17297:21:1;17354:2;17334:18;;;17327:30;17393:34;17373:18;;;17366:62;-1:-1:-1;;;17444:18:1;;;17437:33;17487:19;;17551:64:0;17287:225:1;17551:64:0;-1:-1:-1;;;;;17701:15:0;;17679:19;17701:15;;;;;;;;;;;17735:21;;;;17727:72;;;;-1:-1:-1;;;17727:72:0;;19601:2:1;17727:72:0;;;19583:21:1;19640:2;19620:18;;;19613:30;19679:34;19659:18;;;19652:62;-1:-1:-1;;;19730:18:1;;;19723:36;19776:19;;17727:72:0;19573:228:1;17727:72:0;-1:-1:-1;;;;;17835:15:0;;;:9;:15;;;;;;;;;;;17853:20;;;17835:38;;17895:13;;;;;;;;:23;;17867:6;;17835:9;17895:23;;17867:6;;17895:23;:::i;:::-;;;;;;;;17951:2;-1:-1:-1;;;;;17936:26:0;17945:4;-1:-1:-1;;;;;17936:26:0;;17955:6;17936:26;;;;14255:25:1;;14243:2;14228:18;;14210:76;17936:26:0;;;;;;;;17975:37;19039:591;120850:1307;120985:4;121109:10;;121105:155;;121160:15;;:35;;-1:-1:-1;;;121160:35:0;;;;;14255:25:1;;;55729:13:0;;-1:-1:-1;;;;;121160:15:0;;:27;;14228:18:1;;121160:35:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;121150:7;:45;:94;;;-1:-1:-1;;;121150:94:0;;;;;;;;;;121140:104;;121105:155;121291:6;121280:7;:17;121276:69;;-1:-1:-1;121325:4:0;121318:11;;121276:69;121636:14;121679:6;121653:23;121661:7;121670:5;121653:7;:23::i;:::-;:32;;;-1:-1:-1;;;121653:32:0;;;;;;;;;122122:16;;;121653:32;;;122112:26;;;-1:-1:-1;;120850:1307:0;;;;;;;;:::o;39993:314::-;40046:7;40078:4;-1:-1:-1;;;;;40087:12:0;40070:29;;:66;;;;;40120:16;40103:13;:33;40070:66;40066:234;;;-1:-1:-1;40160:24:0;;39993:314::o;40066:234::-;-1:-1:-1;40496:73:0;;;40246:10;40496:73;;;;15146:25:1;;;;40258:12:0;15187:18:1;;;15180:34;40272:15:0;15230:18:1;;;15223:34;40540:13:0;15273:18:1;;;15266:34;40563:4:0;15316:19:1;;;;15309:61;;;;40496:73:0;;;;;;;;;;15118:19:1;;;;40496:73:0;;;40486:84;;;;;;44234:115::o;79604:6162::-;79878:14;;:44;;-1:-1:-1;;;79878:44:0;;79752:26;;;;;;;;-1:-1:-1;;;;;79878:14:0;;;;:25;;:44;;79904:5;;79911:10;;79878:44;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;79852:70;;79958:24;79985:19;:17;:19::i;:::-;80236:14;;;;80096:17;;;;79958:46;;-1:-1:-1;80019:18:0;;80079:34;;80059:55;;:155;;80196:5;:17;;;80179:5;:14;;;:34;80059:155;;;80138:16;80059:155;80040:210;80019:231;;80289:25;80317:15;;;;;;;;;-1:-1:-1;;;;;80317:15:0;-1:-1:-1;;;;;80317:33:0;;80351:5;80358:10;80370:16;80388:7;80317:79;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;80289:107;;80452:5;:17;;;80439:10;:30;80435:4029;;;80556:76;80572:5;80579:7;80588:6;:22;;;80612:6;:19;;;80556:15;:76::i;:::-;80538:94;;80657:7;80653:521;;;80693:112;80706:5;80720;:12;;;:23;;80740:3;80720:23;;;80735:2;80720:23;80713:31;;54265:28;80713:31;;;-1:-1:-1;;;80713:31:0;;;;;;;;;;-1:-1:-1;;;80786:5:0;:15;;;80803:1;80693:12;:112::i;:::-;80689:466;;;80855:13;;:31;;-1:-1:-1;;;80855:31:0;;-1:-1:-1;;;;;80855:13:0;;;;:21;;:31;;80877:5;;80855:13;;:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;80435:4029;;80689:466;80941:11;:109;;;;;80981:69;80994:5;-1:-1:-1;;;55062:28:0;81031:5;:15;;;81048:1;80981:12;:69::i;:::-;80937:218;;;81100:13;;:31;;-1:-1:-1;;;81100:31:0;;-1:-1:-1;;;;;81100:13:0;;;;:21;;:31;;81122:5;;81100:13;;:31;;;:::i;80937:218::-;80435:4029;;;81254:5;:17;;;81237:5;:14;;;:34;81274:1;81237:38;81218:16;:57;81214:3235;;;81395:76;81411:5;81418:7;81427:6;:22;;;81451:6;:19;;;81395:15;:76::i;:::-;81377:94;;81500:7;81496:754;;;81536:11;81586;81582:293;;;81634:65;81647:5;81660:2;54265:28;81654:8;-1:-1:-1;;;81679:5:0;:15;;;81696:2;81634:12;:65::i;:::-;81630:218;;;81736:13;;;;;;;;;-1:-1:-1;;;;;81736:13:0;-1:-1:-1;;;;;81736:21:0;;81758:5;81765:2;81736:32;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;81812:4;81803:13;;81630:218;81908:6;81903:324;;81951:120;81964:5;81978;:12;;;:23;;81998:3;81978:23;;;81993:2;81978:23;81971:31;;54265:28;81971:31;;;-1:-1:-1;;;81971:31:0;;;;;;;;;;-1:-1:-1;;;82052:5:0;:15;;;82069:1;81951:12;:120::i;:::-;81947:253;;;82137:13;;;;;;;;;-1:-1:-1;;;;;82137:13:0;-1:-1:-1;;;;;82137:21:0;;82159:5;82166:1;82137:31;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;81947:253;81496:754;81214:3235;;;82440:7;82436:1994;;;82573:2;82553:5;:17;;;:22;82549:1858;;;82828:102;82841:5;-1:-1:-1;;;55062:28:0;82911:5;:15;;;82928:1;82828:12;:102::i;:::-;82824:235;;;82996:13;;:31;;-1:-1:-1;;;82996:31:0;;-1:-1:-1;;;;;82996:13:0;;;;:21;;:31;;83018:5;;82996:13;;:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;82824:235;83254:11;83250:334;;;83306:106;83319:5;-1:-1:-1;;;55062:28:0;83393:5;:15;;;83410:1;83306:12;:106::i;:::-;83302:251;;;83486:13;;:31;;-1:-1:-1;;;83486:31:0;;-1:-1:-1;;;;;83486:13:0;;;;:21;;:31;;83508:5;;83515:1;;83486:31;;;:::i;82549:1858::-;83646:94;83659:5;83672:3;54265:28;83666:9;;83646:94;83642:765;;;83931:13;;:31;;-1:-1:-1;;;83931:31:0;;-1:-1:-1;;;;;83931:13:0;;;;:21;;:31;;83953:5;;83931:13;;:31;;;:::i;83642:765::-;84025:11;:115;;;;;84040:100;84083:5;-1:-1:-1;;;55062:28:0;84120:5;:15;;;84137:2;84040:12;:100::i;:::-;84021:386;;;84348:13;;:31;;-1:-1:-1;;;84348:31:0;;-1:-1:-1;;;;;84348:13:0;;;;:21;;:31;;84370:5;;84348:13;;:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;84021:386;84523:191;84561:5;84585:16;84620:6;:17;;;84656:6;:17;;;84692:7;84523:19;:191::i;:::-;84735:19;;;;:23;84731:1017;;84873:160;84920:5;84927;84934:10;84946:7;84976:6;:22;;;85000:6;:19;;;85021:11;84873:24;:160::i;:::-;84832:201;;-1:-1:-1;84832:201:0;-1:-1:-1;84731:1017:0;;;85266:15;85284:7;85266:25;;85310:16;85329:11;85310:30;;85400:332;85442:5;85470;85498:6;:22;;;85543:6;:22;;;85588:6;:19;;;85630:6;:19;;;85672:7;85702:11;85400:19;:332::i;:::-;85359:373;;-1:-1:-1;85359:373:0;-1:-1:-1;;;84731:1017:0;79604:6162;;;;;;;;;;;;;:::o;19039:591::-;-1:-1:-1;;;;;19123:21:0;;19115:67;;;;-1:-1:-1;;;19115:67:0;;21173:2:1;19115:67:0;;;21155:21:1;21212:2;21192:18;;;21185:30;21251:34;21231:18;;;21224:62;-1:-1:-1;;;21302:18:1;;;21295:31;21343:19;;19115:67:0;21145:223:1;19115:67:0;-1:-1:-1;;;;;19282:18:0;;19257:22;19282:18;;;;;;;;;;;19319:24;;;;19311:71;;;;-1:-1:-1;;;19311:71:0;;17719:2:1;19311:71:0;;;17701:21:1;17758:2;17738:18;;;17731:30;17797:34;17777:18;;;17770:62;-1:-1:-1;;;17848:18:1;;;17841:32;17890:19;;19311:71:0;17691:224:1;19311:71:0;-1:-1:-1;;;;;19418:18:0;;:9;:18;;;;;;;;;;19439:23;;;19418:44;;19484:12;:22;;19456:6;;19418:9;19484:22;;19456:6;;19484:22;:::i;:::-;;;;-1:-1:-1;;19524:37:0;;14255:25:1;;;19550:1:0;;-1:-1:-1;;;;;19524:37:0;;;;;14243:2:1;14228:18;19524:37:0;14210:76:1;104469:5144:0;104660:37;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;104660:37:0;104760:14;;:61;;-1:-1:-1;;;104760:61:0;;-1:-1:-1;;;;;13355:32:1;;;104760:61:0;;;13337:51:1;13404:18;;;13397:34;;;104805:15:0;13447:18:1;;;13440:34;104760:14:0;;;;:28;;13310:18:1;;104760:61:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;104846:15:0;104832:11;;;:29;-1:-1:-1;;104872:15:0;;104907;;;;104872:51;;-1:-1:-1;;;104872:51:0;;-1:-1:-1;;;;;104872:15:0;;;;:34;;:51;;;;14255:25:1;;;14243:2;14228:18;;14210:76;104872:51:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;104955:15:0;;:37;;-1:-1:-1;;;104955:37:0;;104934:18;;-1:-1:-1;;;;;;104955:15:0;;;;-1:-1:-1;104955:30:0;;:37;;104986:5;;104955:37;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;105497:8;;105538:14;;;;105567:17;;;;105497:97;;-1:-1:-1;;;105497:97:0;;105526:10;105497:97;;;13710:51:1;13777:18;;;13770:34;;;;13820:18;;;13813:34;13890:14;;13883:22;13863:18;;;13856:50;104934:58:0;;-1:-1:-1;;;;;;105497:8:0;;:28;;13682:19:1;;105497:97:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;105630:20;105671:10;105653:5;:15;;;:28;:63;;105715:1;105653:63;;;105702:10;105684:5;:15;;;:28;105653:63;105787:8;;105810:14;;;;105843:17;;;;105866:12;;105787:92;;-1:-1:-1;;;105787:92:0;;;;;26748:25:1;;;105826:34:0;;;;-1:-1:-1;;105826:38:0;26789:18:1;;;26782:34;26859:14;;26852:22;26832:18;;;26825:50;105630:86:0;;-1:-1:-1;105731:15:0;;55603:19;;-1:-1:-1;;;;;105787:8:0;;:22;;26721:18:1;;105787:92:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;105749:5;:18;;;:130;:165;;;-1:-1:-1;;;105749:165:0;;;;;;;;;;;-1:-1:-1;105949:22:0;;;106022:61;106049:5;106056:17;105749:165;106022:26;:61::i;:::-;-1:-1:-1;;;54552:27:0;106155:22;;:38;106242:32;106247:12;106155:38;106242:4;:32::i;:::-;106208:31;;;:66;106295:19;;;;:23;106291:3302;;106856:21;;106950:58;;-1:-1:-1;;;106950:58:0;;106675:5;;106715:7;;106758:5;;106801:7;;106647:24;;-1:-1:-1;;;;;106856:21:0;;:38;;106917:10;;106856:21;;106950:40;;:58;;106758:5;;106801:7;;106950:58;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;107031:12;:31;;;107107:6;:15;;;107085:19;:17;:19::i;:::-;106856:316;;-1:-1:-1;;;;;;106856:316:0;;;;;;;-1:-1:-1;;;;;11184:15:1;;;106856:316:0;;;11166:34:1;11236:15;;;;11216:18;;;11209:43;11268:18;;;11261:34;;;;107085:37:0;;11311:18:1;;;11304:34;11382:14;;11375:22;11354:19;;;11347:51;11100:19;;106856:316:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;107220:21;;106829:343;;-1:-1:-1;107193:24:0;;-1:-1:-1;;;;;107220:21:0;:37;107280:6;107288;107296:8;107193:24;107339:19;:17;:19::i;:::-;107360:4;107220:145;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;107193:172;;107437:16;107422:12;:31;:69;;107490:1;107422:69;;;107471:16;107456:12;:31;107422:69;107386:33;;;:105;107510:31;;;:51;;;;;;;;;107914:35;;;:69;108006:23;;;108002:313;;;108093:23;;;108054:62;;;108139:8;;:67;;-1:-1:-1;;;108139:67:0;;;;;14255:25:1;;;;-1:-1:-1;;;;;108139:8:0;;:29;;14228:18:1;;108139:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;108002:313;;;108294:1;108255:40;;108002:313;108380:12;:33;;;108370:7;:43;:93;;108462:1;108370:93;;;108426:12;:33;;;108416:7;:43;108370:93;108333:34;;;:130;108488:18;;;;108484:270;;108540:13;;108536:199;;;108601:16;;;;108582:15;:35;;;;;;;;108536:199;;;108695:16;;;;108674:17;:37;;;;;;;;108536:199;106291:3302;;;;;;;;;;108869:12;108854;:27;:61;;108914:1;108854:61;;;108899:12;108884;:27;108854:61;108818:33;;;:97;108988:31;;;;108973:46;;:99;;109071:1;108973:99;;;109037:12;:31;;;109022:12;:46;108973:99;108934:138;;109138:33;;;;109128:43;;:93;;109220:1;109128:93;;;109184:12;:33;;;109174:7;:43;109128:93;109091:34;;;:130;109246:17;;;;109242:336;;109294:8;;109324:15;;;;109294:46;;-1:-1:-1;;;109294:46:0;;-1:-1:-1;;;;;109294:8:0;;;;:29;;:46;;;;14255:25:1;;;14243:2;14228:18;;14210:76;109294:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;109367:5;:12;;;109363:196;;;109427:15;;;;109408;:34;;;;;;;;109363:196;;;109520:15;;;;109499:17;:36;;;;;;;;109363:196;104469:5144;;;;;;;;;;;;:::o;109621:1518::-;109963:47;;;109938:22;54265:28;-1:-1:-1;;;110058:30:0;;110109:8;;:50;;-1:-1:-1;;;110109:50:0;;110058:36;;;;110109:50;;;14255:25:1;;;110058:36:0;-1:-1:-1;;;;;;110109:8:0;;:26;;14228:18:1;;110109:50:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;110174:12;-1:-1:-1;;;54552:27:0;110232:14;:27;:43;;;-1:-1:-1;;;110232:43:0;;;;;;;;;;110189:39;;;:87;;-1:-1:-1;110314:25:0;;;:48;;110383:16;;110379:100;;110420:8;;:43;;-1:-1:-1;;;110420:43:0;;;;;14255:25:1;;;-1:-1:-1;;;;;110420:8:0;;;;:29;;14228:18:1;;110420:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;110379:100;110499:8;;110495:75;;110534:13;;110528:26;;-1:-1:-1;;;;;110534:13:0;110549:4;110528:5;:26::i;:::-;110806:60;110812:10;110847:18;110824:20;:41;110806:5;:60::i;:::-;110918:10;-1:-1:-1;;;;;110888:232:0;;;110909:7;110947:18;110967:20;111006:22;111030:4;-1:-1:-1;;;54552:27:0;111037;;:43;111100:5;110888:232;;;;;;;;;;;;:::i;:::-;;;;;;;;109621:1518;;;;;;;;;;;:::o;44487:207::-;-1:-1:-1;;;;;44608:14:0;;44547:15;44608:14;;;:7;:14;;;;;4735;;4872:1;4854:19;;;;4735:14;44669:17;44487:207;;;;:::o;41220:167::-;41297:7;41324:55;41346:20;:18;:20::i;:::-;41368:10;36669:57;;-1:-1:-1;;;36669:57:0;;;9784:27:1;9827:11;;;9820:27;;;9863:12;;;9856:28;;;36632:7:0;;9900:12:1;;36669:57:0;;;;;;;;;;;;36659:68;;;;;;36652:75;;36539:196;;;;;34848:279;34976:7;34997:17;35016:18;35038:25;35049:4;35055:1;35058;35061;35038:10;:25::i;:::-;34996:67;;;;35074:18;35086:5;35074:11;:18::i;:::-;-1:-1:-1;35110:9:0;34848:279;-1:-1:-1;;;;;34848:279:0:o;45944:190::-;46069:4;46122;46093:25;46106:5;46113:4;46093:12;:25::i;:::-;:33;;45944:190;-1:-1:-1;;;;45944:190:0:o;102270:209::-;102333:7;102459:1;102440;102436;:5;;;-1:-1:-1;;;102436:5:0;;;;;;;;;;:10;:18;;102453:1;102436:18;;;102449:1;102436:18;102427:28;;102431:1;102427;:5;;;-1:-1:-1;;;102427:5:0;;;;;;;;;;:28;102426:34;;102270:209;-1:-1:-1;;;102270:209:0:o;102644:107::-;102703:7;102734:1;102730;:5;:13;;102742:1;102730:13;;;102738:1;102730:13;102723:20;102644:107;-1:-1:-1;;;102644:107:0:o;119717:406::-;119788:7;119948:15;119941:4;:22;120000:12;119990:23;120040:7;119898:172;;;;;;;;;10108:19:1;;;10152:2;10143:12;;10136:28;;;;10202:2;10198:15;-1:-1:-1;;10194:53:1;10189:2;10180:12;;10173:75;10273:2;10264:12;;10098:184;119898:172:0;;;;-1:-1:-1;;119898:172:0;;;;;;;;;119866:223;;119898:172;119866:223;;;;;119717:406;-1:-1:-1;;;119717:406:0:o;113710:1391::-;113891:30;113959:22;114022:1;114000:5;:19;;;:23;113996:680;;;114061:51;114066:7;114096:15;114075:18;:36;114061:4;:51::i;:::-;114044:68;;114149:14;114131:32;;114203:1;114182:22;;113996:680;;;114249:17;;;;114245:344;;114300:12;;114296:202;;;114341:15;:37;;;;;;;114296:202;;;114435:17;:39;;;;;;;114296:202;114520:8;;:49;;-1:-1:-1;;;114520:49:0;;;;;14255:25:1;;;-1:-1:-1;;;;;114520:8:0;;;;:29;;14228:18:1;;114520:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;114245:344;-1:-1:-1;114624:36:0;;;113996:680;114768:8;;:50;;-1:-1:-1;;;114768:50:0;;54265:28;-1:-1:-1;;;114717:30:0;;:36;114768:50;;;14255:25:1;;;114717:36:0;-1:-1:-1;;;;;;114768:8:0;;;;:26;;14228:18:1;;114768:50:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;114833:25;-1:-1:-1;;;54552:27:0;114920:14;:27;:43;;;-1:-1:-1;;;114920:43:0;;;;;;;;;114986:13;;114920:43;;;114861:39;;;:102;;-1:-1:-1;114980:39:0;;-1:-1:-1;;;;;114986:13:0;114861:102;114980:5;:39::i;:::-;115034:8;;:48;;-1:-1:-1;;;115034:48:0;;;;;14255:25:1;;;-1:-1:-1;;;;;115034:8:0;;;;:29;;14228:18:1;;115034:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;113710:1391;;;;;;;;:::o;72208:1112::-;72421:17;;;;72417:233;;72465:12;;72460:179;;72498:8;;72522:18;;;;72498:43;;-1:-1:-1;;;72498:43:0;;-1:-1:-1;;;;;72498:8:0;;;;:23;;:43;;;;14255:25:1;;;14243:2;14228:18;;14210:76;72498:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;72460:179;;;72582:8;;72604:18;;;;72582:41;;-1:-1:-1;;;72582:41:0;;-1:-1:-1;;;;;72582:8:0;;;;:21;;:41;;;;14255:25:1;;;14243:2;14228:18;;14210:76;72582:41:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;72460:179;72685:18;72788:5;:17;;;72771:5;:14;;;:34;72752:16;:53;:70;;72821:1;72752:70;;;72808:10;72752:70;72724:7;72706:5;:15;;;:25;:117;72685:138;;73150:5;:15;;;73136:10;:29;73132:170;;73231:8;;-1:-1:-1;;;;;73231:8:0;:21;73253:32;73267:5;73274:10;73253:13;:32::i;:::-;73231:55;;;;;;;;;;;;;14255:25:1;;14243:2;14228:18;;14210:76;73231:55:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;73132:170;72208:1112;;;;;;:::o;85774:1823::-;86051:26;86079:24;86143:23;86169:54;86174:8;86206:16;86184:19;:38;86169:4;:54::i;:::-;86143:80;;86238:24;86265:19;:17;:19::i;:::-;86238:46;;86328:6;:18;;;86350:1;86328:23;86324:99;;;86391:16;;;;86372:15;:35;;;;;;;;86324:99;86713:13;86729:6;86713:22;;86750:29;86782:21;;;;;;;;;-1:-1:-1;;;;;86782:21:0;-1:-1:-1;;;;;86782:37:0;;86838:6;86846:5;86853:11;86866:5;86890:16;86908:12;86782:139;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;86750:171;;87105:21;87086:6;:16;;;:40;:104;;87189:1;87086:104;;;87165:21;87146:6;:16;;;:40;87086:104;87065:125;;87460:15;87449:8;:26;87430:45;;87490:88;87520:5;87527:18;87547:16;87565:12;87490:29;:88::i;:::-;85774:1823;;;;;;;;;;;;;;:::o;74216:4679::-;74511:26;74539:24;74601:26;74630:78;74635:15;74670;;;;;;;;;-1:-1:-1;;;;;74670:15:0;-1:-1:-1;;;;;74670:30:0;;74701:5;74670:37;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;74652:15;:55;74630:4;:78::i;:::-;74601:107;;74723:23;74749:32;74754:12;74768;74749:4;:32::i;:::-;74723:58;;74835:18;74817:5;:15;;;:36;:79;;74895:1;74817:79;;;74874:18;74856:5;:15;;;:36;74817:79;74796:100;;74940:15;74930:7;:25;:57;;74986:1;74930:57;;;74968:15;74958:7;:25;74930:57;74911:76;;75008:5;:17;;;75029:1;75008:22;75004:3226;;;75477:12;;75473:824;;;75821:15;;;;75802;:34;;;;;;;;75473:824;;;76262:15;;;;76241:17;:36;;;;;;;;75473:824;76340:1;76321:16;:20;:36;;;;;76346:11;76345:12;76321:36;76317:132;;;76382:8;;:47;;-1:-1:-1;;;76382:47:0;;;;;14255:25:1;;;-1:-1:-1;;;;;76382:8:0;;;;:29;;14228:18:1;;76382:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;76317:132;76613:11;76609:623;;;76649:8;;76679:15;;;;76649:46;;-1:-1:-1;;;76649:46:0;;-1:-1:-1;;;;;76649:8:0;;;;:29;;:46;;;;14255:25:1;;;14243:2;14228:18;;14210:76;76649:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;75004:3226;;76609:623;77163:8;;:49;;-1:-1:-1;;;77163:49:0;;;;;14255:25:1;;;-1:-1:-1;;;;;77163:8:0;;;;:29;;14228:18:1;;77163:49:0;14210:76:1;75004:3226:0;78146:8;;:68;;-1:-1:-1;;;78146:68:0;;78176:37;;;78146:68;;;14255:25:1;-1:-1:-1;;;;;78146:8:0;;;;:29;;14228:18:1;;78146:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;75004:3226;78733:11;78732:12;:57;;;;;78788:1;78769:16;78748:18;:37;:41;78732:57;78728:149;;;78810:51;78816:5;78844:16;78823:18;:37;78810:5;:51::i;:::-;74216:4679;;;;;;;;;;;;;:::o;111228:498::-;111373:17;;;;111369:233;;111417:12;;111412:179;;111450:8;;111474:18;;;;111450:43;;-1:-1:-1;;;111450:43:0;;-1:-1:-1;;;;;111450:8:0;;;;:23;;:43;;;;14255:25:1;;;14243:2;14228:18;;14210:76;111450:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;111412:179;;;111534:8;;111556:18;;;;111534:41;;-1:-1:-1;;;111534:41:0;;-1:-1:-1;;;;;111534:8:0;;;;:21;;:41;;;;14255:25:1;;;14243:2;14228:18;;14210:76;111534:41:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;111412:179;111637:8;;111680:15;;;;-1:-1:-1;;;;;111637:8:0;;;;:21;;111659:47;;111673:5;;111680:25;;111659:13;:47::i;:::-;111637:70;;;;;;;;;;;;;14255:25:1;;14243:2;14228:18;;14210:76;111637:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;111228:498;;;:::o;33077:1632::-;33208:7;;34142:66;34129:79;;34125:163;;;-1:-1:-1;34241:1:0;;-1:-1:-1;34245:30:0;34225:51;;34125:163;34302:1;:7;;34307:2;34302:7;;:18;;;;;34313:1;:7;;34318:2;34313:7;;34302:18;34298:102;;;-1:-1:-1;34353:1:0;;-1:-1:-1;34357:30:0;34337:51;;34298:102;34514:24;;;34497:14;34514:24;;;;;;;;;15608:25:1;;;15681:4;15669:17;;15649:18;;;15642:45;;;;15703:18;;;15696:34;;;15746:18;;;15739:34;;;34514:24:0;;15580:19:1;;34514:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;34514:24:0;;-1:-1:-1;;34514:24:0;;;-1:-1:-1;;;;;;;34553:20:0;;34549:103;;34606:1;34610:29;34590:50;;;;;;;34549:103;34672:6;-1:-1:-1;34680:20:0;;-1:-1:-1;33077:1632:0;;;;;;;;:::o;27786:643::-;27864:20;27855:5;:29;;;;;;-1:-1:-1;;;27855:29:0;;;;;;;;;;27851:571;;;27786:643;:::o;27851:571::-;27962:29;27953:5;:38;;;;;;-1:-1:-1;;;27953:38:0;;;;;;;;;;27949:473;;;28008:34;;-1:-1:-1;;;28008:34:0;;16962:2:1;28008:34:0;;;16944:21:1;17001:2;16981:18;;;16974:30;17040:26;17020:18;;;17013:54;17084:18;;28008:34:0;16934:174:1;27949:473:0;28073:35;28064:5;:44;;;;;;-1:-1:-1;;;28064:44:0;;;;;;;;;;28060:362;;;28125:41;;-1:-1:-1;;;28125:41:0;;18122:2:1;28125:41:0;;;18104:21:1;18161:2;18141:18;;;18134:30;18200:33;18180:18;;;18173:61;18251:18;;28125:41:0;18094:181:1;28060:362:0;28197:30;28188:5;:39;;;;;;-1:-1:-1;;;28188:39:0;;;;;;;;;;28184:238;;;28244:44;;-1:-1:-1;;;28244:44:0;;20008:2:1;28244:44:0;;;19990:21:1;20047:2;20027:18;;;20020:30;20086:34;20066:18;;;20059:62;-1:-1:-1;;;20137:18:1;;;20130:32;20179:19;;28244:44:0;19980:224:1;28184:238:0;28319:30;28310:5;:39;;;;;;-1:-1:-1;;;28310:39:0;;;;;;;;;;28306:116;;;28366:44;;-1:-1:-1;;;28366:44:0;;20411:2:1;28366:44:0;;;20393:21:1;20450:2;20430:18;;;20423:30;20489:34;20469:18;;;20462:62;-1:-1:-1;;;20540:18:1;;;20533:32;20582:19;;28366:44:0;20383:224:1;28306:116:0;27786:643;:::o;46495:675::-;46578:7;46621:4;46578:7;46636:497;46660:5;:12;46656:1;:16;46636:497;;;46694:20;46717:5;46723:1;46717:8;;;;;;-1:-1:-1;;;46717:8:0;;;;;;;;;;;;;;;46694:31;;46760:12;46744;:28;46740:382;;47246:13;47296:15;;;47332:4;47325:15;;;47379:4;47363:21;;46872:57;;46740:382;;;47246:13;47296:15;;;47332:4;47325:15;;;47379:4;47363:21;;47049:57;;46740:382;-1:-1:-1;46674:3:0;;;;:::i;:::-;;;;46636:497;;;-1:-1:-1;47150:12:0;46495:675;-1:-1:-1;;;46495:675:0:o;71186:924::-;71276:20;-1:-1:-1;;;72006:5:0;:18;;;71979:6;71930:46;-1:-1:-1;;;71935:10:0;:26;54265:28;71969:6;71963:12;71930:4;:46::i;:::-;71917:10;:59;:68;;;-1:-1:-1;;;71917:68:0;;;;;;;;;;71396:501;54983:28;71423:10;:24;71874:4;71509:336;-1:-1:-1;;;71544:4:0;:20;-1:-1:-1;;;71595:207:0;54552:27;-1:-1:-1;;;71696:26:0;71638:5;:17;;;:85;-1:-1:-1;;;71595:8:0;:207::i;:::-;:223;71509:4;:336::i;:::-;71471:10;:374;71470:408;;;-1:-1:-1;;;71470:408:0;;;;;;;;;;71396:4;:501::i;:::-;-1:-1:-1;;;71350:10:0;:26;:547;:635;71349:675;;;-1:-1:-1;;;71349:675:0;;;;;;;;;;:708;;;-1:-1:-1;;;71349:708:0;;;;;;;;;;;71186:924;-1:-1:-1;;;71186:924:0:o;73406:735::-;73600:11;73595:539;;73727:22;;73723:166;;73803:51;73809:5;73837:16;73816:18;:37;73803:5;:51::i;:::-;74019:20;;74015:108;;74060:8;;:47;;-1:-1:-1;;;74060:47:0;;;;;14255:25:1;;;-1:-1:-1;;;;;74060:8:0;;;;:29;;14228:18:1;;74060:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;73406:735;;;;:::o;102916:107::-;102975:7;103006:1;103002;:5;:13;;103014:1;103002:13;;14:395:1;77:8;87:6;141:3;134:4;126:6;122:17;118:27;108:2;;166:8;156;149:26;108:2;-1:-1:-1;196:20:1;;239:18;228:30;;225:2;;;278:8;268;261:26;225:2;322:4;314:6;310:17;298:29;;382:3;375:4;365:6;362:1;358:14;350:6;346:27;342:38;339:47;336:2;;;399:1;396;389:12;336:2;98:311;;;;;:::o;414:132::-;490:13;;512:28;490:13;512:28;:::i;:::-;471:75;;;:::o;551:257::-;610:6;663:2;651:9;642:7;638:23;634:32;631:2;;;684:6;676;669:22;631:2;728:9;715:23;747:31;772:5;747:31;:::i;813:261::-;883:6;936:2;924:9;915:7;911:23;907:32;904:2;;;957:6;949;942:22;904:2;994:9;988:16;1013:31;1038:5;1013:31;:::i;1079:398::-;1147:6;1155;1208:2;1196:9;1187:7;1183:23;1179:32;1176:2;;;1229:6;1221;1214:22;1176:2;1273:9;1260:23;1292:31;1317:5;1292:31;:::i;:::-;1342:5;-1:-1:-1;1399:2:1;1384:18;;1371:32;1412:33;1371:32;1412:33;:::i;:::-;1464:7;1454:17;;;1166:311;;;;;:::o;1482:466::-;1559:6;1567;1575;1628:2;1616:9;1607:7;1603:23;1599:32;1596:2;;;1649:6;1641;1634:22;1596:2;1693:9;1680:23;1712:31;1737:5;1712:31;:::i;:::-;1762:5;-1:-1:-1;1819:2:1;1804:18;;1791:32;1832:33;1791:32;1832:33;:::i;:::-;1586:362;;1884:7;;-1:-1:-1;;;1938:2:1;1923:18;;;;1910:32;;1586:362::o;1953:849::-;2064:6;2072;2080;2088;2096;2104;2112;2165:3;2153:9;2144:7;2140:23;2136:33;2133:2;;;2187:6;2179;2172:22;2133:2;2231:9;2218:23;2250:31;2275:5;2250:31;:::i;:::-;2300:5;-1:-1:-1;2357:2:1;2342:18;;2329:32;2370:33;2329:32;2370:33;:::i;:::-;2422:7;-1:-1:-1;2476:2:1;2461:18;;2448:32;;-1:-1:-1;2527:2:1;2512:18;;2499:32;;-1:-1:-1;2583:3:1;2568:19;;2555:33;2632:4;2619:18;;2607:31;;2597:2;;2657:6;2649;2642:22;2597:2;2123:679;;;;-1:-1:-1;2123:679:1;;;;2685:7;2739:3;2724:19;;2711:33;;-1:-1:-1;2791:3:1;2776:19;;;2763:33;;2123:679;-1:-1:-1;;2123:679:1:o;2807:325::-;2875:6;2883;2936:2;2924:9;2915:7;2911:23;2907:32;2904:2;;;2957:6;2949;2942:22;2904:2;3001:9;2988:23;3020:31;3045:5;3020:31;:::i;:::-;3070:5;3122:2;3107:18;;;;3094:32;;-1:-1:-1;;;2894:238:1:o;3137:660::-;3241:6;3249;3257;3265;3318:2;3306:9;3297:7;3293:23;3289:32;3286:2;;;3339:6;3331;3324:22;3286:2;3383:9;3370:23;3402:31;3427:5;3402:31;:::i;:::-;3452:5;-1:-1:-1;3504:2:1;3489:18;;3476:32;;-1:-1:-1;3559:2:1;3544:18;;3531:32;3586:18;3575:30;;3572:2;;;3623:6;3615;3608:22;3572:2;3667:70;3729:7;3720:6;3709:9;3705:22;3667:70;:::i;:::-;3276:521;;;;-1:-1:-1;3756:8:1;-1:-1:-1;;;;3276:521:1:o;3802:796::-;3912:6;3920;3928;3936;3944;3997:3;3985:9;3976:7;3972:23;3968:33;3965:2;;;4019:6;4011;4004:22;3965:2;4063:9;4050:23;4082:31;4107:5;4082:31;:::i;:::-;4132:5;-1:-1:-1;4184:2:1;4169:18;;4156:32;;-1:-1:-1;4239:2:1;4224:18;;4211:32;4266:18;4255:30;;4252:2;;;4303:6;4295;4288:22;4252:2;4347:70;4409:7;4400:6;4389:9;4385:22;4347:70;:::i;:::-;4436:8;;-1:-1:-1;4321:96:1;-1:-1:-1;;4523:2:1;4508:18;;4495:32;4536:30;4495:32;4536:30;:::i;:::-;4585:7;4575:17;;;3955:643;;;;;;;;:::o;4603:460::-;4677:6;4685;4693;4746:2;4734:9;4725:7;4721:23;4717:32;4714:2;;;4767:6;4759;4752:22;4714:2;4811:9;4798:23;4830:31;4855:5;4830:31;:::i;:::-;4880:5;-1:-1:-1;4932:2:1;4917:18;;4904:32;;-1:-1:-1;4988:2:1;4973:18;;4960:32;5001:30;4960:32;5001:30;:::i;:::-;5050:7;5040:17;;;4704:359;;;;;:::o;5068:255::-;5135:6;5188:2;5176:9;5167:7;5163:23;5159:32;5156:2;;;5209:6;5201;5194:22;5156:2;5246:9;5240:16;5265:28;5287:5;5265:28;:::i;5328:1109::-;5426:6;5479:3;5467:9;5458:7;5454:23;5450:33;5447:2;;;5501:6;5493;5486:22;5447:2;5532:17;;:::i;:::-;5572:37;5599:9;5572:37;:::i;:::-;5565:5;5558:52;5642:46;5684:2;5673:9;5669:18;5642:46;:::i;:::-;5637:2;5630:5;5626:14;5619:70;5721:46;5763:2;5752:9;5748:18;5721:46;:::i;:::-;5716:2;5709:5;5705:14;5698:70;5821:2;5810:9;5806:18;5800:25;5795:2;5788:5;5784:14;5777:49;5880:3;5869:9;5865:19;5859:26;5853:3;5846:5;5842:15;5835:51;5940:3;5929:9;5925:19;5919:26;5913:3;5906:5;5902:15;5895:51;6000:3;5989:9;5985:19;5979:26;5973:3;5966:5;5962:15;5955:51;6060:3;6049:9;6045:19;6039:26;6033:3;6026:5;6022:15;6015:51;6085:3;6120:46;6162:2;6151:9;6147:18;6120:46;:::i;:::-;6104:14;;;6097:70;6186:3;6227:18;;;6221:25;6205:14;;;6198:49;6266:3;6307:18;;;6301:25;6285:14;;;6278:49;6346:3;6387:18;;;6381:25;6365:14;;;6358:49;;;;-1:-1:-1;6108:5:1;5437:1000;-1:-1:-1;5437:1000:1:o;6442:864::-;6541:6;6594:3;6582:9;6573:7;6569:23;6565:33;6562:2;;;6616:6;6608;6601:22;6562:2;6654;6648:9;6696:3;6688:6;6684:16;6766:6;6754:10;6751:22;6730:18;6718:10;6715:34;6712:62;6709:2;;;-1:-1:-1;;;6797:36:1;;6856:4;6853:1;6846:15;6889:4;6804:6;6874:20;6709:2;6924:10;6920:2;6913:22;;6965:9;6959:16;6951:6;6944:32;7030:2;7019:9;7015:18;7009:25;7004:2;6996:6;6992:15;6985:50;7089:2;7078:9;7074:18;7068:25;7063:2;7055:6;7051:15;7044:50;7148:2;7137:9;7133:18;7127:25;7122:2;7114:6;7110:15;7103:50;7208:3;7197:9;7193:19;7187:26;7181:3;7173:6;7169:16;7162:52;7269:3;7258:9;7254:19;7248:26;7242:3;7234:6;7230:16;7223:52;7294:6;7284:16;;;6552:754;;;;:::o;7311:190::-;7370:6;7423:2;7411:9;7402:7;7398:23;7394:32;7391:2;;;7444:6;7436;7429:22;7391:2;-1:-1:-1;7472:23:1;;7381:120;-1:-1:-1;7381:120:1:o;7506:194::-;7576:6;7629:2;7617:9;7608:7;7604:23;7600:32;7597:2;;;7650:6;7642;7635:22;7597:2;-1:-1:-1;7678:16:1;;7587:113;-1:-1:-1;7587:113:1:o;7705:454::-;7776:6;7784;7792;7845:2;7833:9;7824:7;7820:23;7816:32;7813:2;;;7866:6;7858;7851:22;7813:2;7907:9;7894:23;7884:33;;7967:2;7956:9;7952:18;7939:32;7980:28;8002:5;7980:28;:::i;:::-;8027:5;-1:-1:-1;8084:2:1;8069:18;;8056:32;8097:30;8056:32;8097:30;:::i;8260:962::-;8340:12;;8234:13;8227:21;8215:34;;8404:4;8397:5;8393:16;8387:23;8419:45;8458:4;8453:3;8449:14;8435:12;8234:13;8227:21;8215:34;;8205:50;8419:45;;8512:4;8505:5;8501:16;8495:23;8527:47;8568:4;8563:3;8559:14;8543;8234:13;8227:21;8215:34;;8205:50;8527:47;;8623:4;8616:5;8612:16;8606:23;8599:4;8594:3;8590:14;8583:47;8679:4;8672:5;8668:16;8662:23;8655:4;8650:3;8646:14;8639:47;8735:4;8728:5;8724:16;8718:23;8711:4;8706:3;8702:14;8695:47;8791:4;8784:5;8780:16;8774:23;8767:4;8762:3;8758:14;8751:47;8847:4;8840:5;8836:16;8830:23;8823:4;8818:3;8814:14;8807:47;8873:6;8927:2;8920:5;8916:14;8910:21;8940:45;8981:2;8976:3;8972:12;8956:14;8234:13;8227:21;8215:34;;8205:50;8940:45;-1:-1:-1;;9004:6:1;9046:14;;;9040:21;9026:12;;;9019:43;9081:6;9123:14;;;9117:21;9103:12;;;9096:43;9158:6;9200:14;;;9194:21;9180:12;;9173:43;8314:908::o;11409:282::-;-1:-1:-1;;;;;11609:32:1;;;;11591:51;;11673:2;11658:18;;11651:34;11579:2;11564:18;;11546:145::o;15784:363::-;15988:25;;;-1:-1:-1;;;;;16049:32:1;;;;16044:2;16029:18;;16022:60;16125:14;16118:22;16113:2;16098:18;;16091:50;15976:2;15961:18;;15943:204::o;16152:603::-;16264:4;16293:2;16322;16311:9;16304:21;16354:6;16348:13;16397:6;16392:2;16381:9;16377:18;16370:34;16422:4;16435:140;16449:6;16446:1;16443:13;16435:140;;;16544:14;;;16540:23;;16534:30;16510:17;;;16529:2;16506:26;16499:66;16464:10;;16435:140;;;16593:6;16590:1;16587:13;16584:2;;;16663:4;16658:2;16649:6;16638:9;16634:22;16630:31;16623:45;16584:2;-1:-1:-1;16739:2:1;16718:15;-1:-1:-1;;16714:29:1;16699:45;;;;16746:2;16695:54;;16273:482;-1:-1:-1;;;16273:482:1:o;22184:355::-;22386:2;22368:21;;;22425:2;22405:18;;;22398:30;22464:33;22459:2;22444:18;;22437:61;22530:2;22515:18;;22358:181::o;23310:256::-;23500:3;23485:19;;23513:47;23489:9;23542:6;23513:47;:::i;23571:682::-;23895:3;23880:19;;23908:47;23884:9;23937:6;23908:47;:::i;:::-;-1:-1:-1;;;;;24030:15:1;;;24024:3;24009:19;;24002:44;24077:3;24062:19;;24055:35;;;;24127:15;;;;24121:3;24106:19;;24099:44;24174:3;24159:19;;24152:35;24231:14;;24224:22;24218:3;24203:19;;;24196:51;;;;23862:391;;-1:-1:-1;23862:391:1:o;24258:570::-;24560:3;24545:19;;24573:47;24549:9;24602:6;24573:47;:::i;:::-;-1:-1:-1;;;;;24657:32:1;;;;24651:3;24636:19;;24629:61;24721:3;24706:19;;24699:35;;;;24765:3;24750:19;;24743:35;;;;24809:3;24794:19;;;24787:35;24527:301;;-1:-1:-1;24527:301:1:o;24833:472::-;25107:3;25092:19;;25120:47;25096:9;25149:6;25120:47;:::i;:::-;25204:6;25198:3;25187:9;25183:19;25176:35;25248:6;25242:3;25231:9;25227:19;25220:35;25292:6;25286:3;25275:9;25271:19;25264:35;25074:231;;;;;;;:::o;25852:695::-;26162:4;26204:3;26193:9;26189:19;26181:27;;26235:6;26224:9;26217:25;26292:6;26285:14;26278:22;26273:2;26262:9;26258:18;26251:50;26337:6;26332:2;26321:9;26317:18;26310:34;26380:6;26375:2;26364:9;26360:18;26353:34;26424:6;26418:3;26407:9;26403:19;26396:35;26468:6;26462:3;26451:9;26447:19;26440:35;26484:57;26536:3;26525:9;26521:19;26513:6;26484:57;:::i;:::-;26171:376;;;;;;;;;;:::o;26886:685::-;27202:4;27244:3;27233:9;27229:19;27221:27;;27275:6;27264:9;27257:25;27318:6;27313:2;27302:9;27298:18;27291:34;27361:6;27356:2;27345:9;27341:18;27334:34;27404:6;27399:2;27388:9;27384:18;27377:34;27448:6;27442:3;27431:9;27427:19;27420:35;27492:6;27486:3;27475:9;27471:19;27464:35;27508:57;27560:3;27549:9;27545:19;27537:6;27508:57;:::i;27765:344::-;27832:2;27826:9;27874:3;27862:16;;27908:18;27893:34;;27929:22;;;27890:62;27887:2;;;27994:10;27989:3;27985:20;27982:1;27975:31;28029:4;28026:1;28019:15;28057:4;28054:1;28047:15;27887:2;28088;28081:22;27806:303;:::o;28114:128::-;28154:3;28185:1;28181:6;28178:1;28175:13;28172:2;;;28191:18;;:::i;:::-;-1:-1:-1;28227:9:1;;28162:80::o;28247:125::-;28287:4;28315:1;28312;28309:8;28306:2;;;28320:18;;:::i;:::-;-1:-1:-1;28357:9:1;;28296:76::o;28377:380::-;28456:1;28452:12;;;;28499;;;28520:2;;28574:4;28566:6;28562:17;28552:27;;28520:2;28627;28619:6;28616:14;28596:18;28593:38;28590:2;;;28673:10;28668:3;28664:20;28661:1;28654:31;28708:4;28705:1;28698:15;28736:4;28733:1;28726:15;28762:135;28801:3;-1:-1:-1;;28822:17:1;;28819:2;;;28842:18;;:::i;:::-;-1:-1:-1;28889:1:1;28878:13;;28809:88::o;28902:127::-;28963:10;28958:3;28954:20;28951:1;28944:31;28994:4;28991:1;28984:15;29018:4;29015:1;29008:15;29034:131;-1:-1:-1;;;;;29109:31:1;;29099:42;;29089:2;;29155:1;29152;29145:12;29170:118;29256:5;29249:13;29242:21;29235:5;29232:32;29222:2;;29278:1;29275;29268:12

Swarm Source

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