ETH Price: $3,485.76 (+0.88%)

Token

Hasbulla Genesis Collection (HGC)
 

Overview

Max Total Supply

0 HGC

Holders

247

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Balance
1 HGC
0x1c21230D4A2E920d11655CC6AFE567eE38bFAcda
Loading...
Loading
Loading...
Loading
Loading...
Loading

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

Contract Source Code Verified (Exact Match)

Contract Name:
HasbullaGenesisCollection

Compiler Version
v0.8.15+commit.e14f2714

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2023-04-04
*/

// SPDX-License-Identifier: MIT
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;
    }
}

pragma solidity ^0.8.0;

/**
 * @dev External interface of AccessControl declared to support ERC165 detection.
 */
interface IAccessControl {
    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     *
     * _Available since v3.1._
     */
    event RoleAdminChanged(
        bytes32 indexed role,
        bytes32 indexed previousAdminRole,
        bytes32 indexed newAdminRole
    );

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {AccessControl-_setupRole}.
     */
    event RoleGranted(
        bytes32 indexed role,
        address indexed account,
        address indexed sender
    );

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(
        bytes32 indexed role,
        address indexed account,
        address indexed sender
    );

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account)
        external
        view
        returns (bool);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {AccessControl-_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) external;
}

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1);

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator,
        Rounding rounding
    ) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding)
        internal
        pure
        returns (uint256)
    {
        unchecked {
            uint256 result = sqrt(a);
            return
                result +
                (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding)
        internal
        pure
        returns (uint256)
    {
        unchecked {
            uint256 result = log2(value);
            return
                result +
                (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10**64) {
                value /= 10**64;
                result += 64;
            }
            if (value >= 10**32) {
                value /= 10**32;
                result += 32;
            }
            if (value >= 10**16) {
                value /= 10**16;
                result += 16;
            }
            if (value >= 10**8) {
                value /= 10**8;
                result += 8;
            }
            if (value >= 10**4) {
                value /= 10**4;
                result += 4;
            }
            if (value >= 10**2) {
                value /= 10**2;
                result += 2;
            }
            if (value >= 10**1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding)
        internal
        pure
        returns (uint256)
    {
        unchecked {
            uint256 result = log10(value);
            return
                result +
                (rounding == Rounding.Up && 10**result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding)
        internal
        pure
        returns (uint256)
    {
        unchecked {
            uint256 result = log256(value);
            return
                result +
                (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
        }
    }
}

pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _SYMBOLS = "0123456789abcdef";
    uint8 private constant _ADDRESS_LENGTH = 20;

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        unchecked {
            uint256 length = Math.log10(value) + 1;
            string memory buffer = new string(length);
            uint256 ptr;
            /// @solidity memory-safe-assembly
            assembly {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                /// @solidity memory-safe-assembly
                assembly {
                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        unchecked {
            return toHexString(value, Math.log256(value) + 1);
        }
    }

    /**
     * @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] = _SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
     */
    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
    }
}

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;
    }
}

pragma solidity ^0.8.0;

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor() {
        _paused = false;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        _requireNotPaused();
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        _requirePaused();
        _;
    }

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

    /**
     * @dev Throws if the contract is paused.
     */
    function _requireNotPaused() internal view virtual {
        require(!paused(), "Pausable: paused");
    }

    /**
     * @dev Throws if the contract is not paused.
     */
    function _requirePaused() internal view virtual {
        require(paused(), "Pausable: not paused");
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

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

        (bool success, ) = recipient.call{value: amount}("");
        require(
            success,
            "Address: unable to send value, recipient may have reverted"
        );
    }

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

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

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

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

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

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return
            verifyCallResultFromTarget(
                target,
                success,
                returndata,
                errorMessage
            );
    }

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

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return
            verifyCallResultFromTarget(
                target,
                success,
                returndata,
                errorMessage
            );
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage)
        private
        pure
    {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}

pragma solidity ^0.8.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
interface IERC721Receiver {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
     *
     * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

pragma solidity ^0.8.0;

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override
        returns (bool)
    {
        return interfaceId == type(IERC165).interfaceId;
    }
}

pragma solidity ^0.8.0;

/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms. This is a lightweight version that doesn't allow enumerating role
 * members except through off-chain means by accessing the contract event logs. Some
 * applications may benefit from on-chain enumerability, for those cases see
 * {AccessControlEnumerable}.
 *
 * Roles are referred to by their `bytes32` identifier. These should be exposed
 * in the external API and be unique. The best way to achieve this is by
 * using `public constant` hash digests:
 *
 * ```
 * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
 * ```
 *
 * Roles can be used to represent a set of permissions. To restrict access to a
 * function call, use {hasRole}:
 *
 * ```
 * function foo() public {
 *     require(hasRole(MY_ROLE, msg.sender));
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {_setRoleAdmin}.
 *
 * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
 * grant and revoke this role. Extra precautions should be taken to secure
 * accounts that have been granted it.
 */
abstract contract AccessControl is Context, IAccessControl, ERC165 {
    struct RoleData {
        mapping(address => bool) members;
        bytes32 adminRole;
    }

    mapping(bytes32 => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /**
     * @dev Modifier that checks that an account has a specific role. Reverts
     * with a standardized message including the required role.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     *
     * _Available since v4.1._
     */
    modifier onlyRole(bytes32 role) {
        _checkRole(role);
        _;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override
        returns (bool)
    {
        return
            interfaceId == type(IAccessControl).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account)
        public
        view
        virtual
        override
        returns (bool)
    {
        return _roles[role].members[account];
    }

    /**
     * @dev Revert with a standard message if `_msgSender()` is missing `role`.
     * Overriding this function changes the behavior of the {onlyRole} modifier.
     *
     * Format of the revert message is described in {_checkRole}.
     *
     * _Available since v4.6._
     */
    function _checkRole(bytes32 role) internal view virtual {
        _checkRole(role, _msgSender());
    }

    /**
     * @dev Revert with a standard message if `account` is missing `role`.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     */
    function _checkRole(bytes32 role, address account) internal view virtual {
        if (!hasRole(role, account)) {
            revert(
                string(
                    abi.encodePacked(
                        "AccessControl: account ",
                        Strings.toHexString(account),
                        " is missing role ",
                        Strings.toHexString(uint256(role), 32)
                    )
                )
            );
        }
    }

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role)
        public
        view
        virtual
        override
        returns (bytes32)
    {
        return _roles[role].adminRole;
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     *
     * May emit a {RoleGranted} event.
     */
    function grantRole(bytes32 role, address account)
        public
        virtual
        override
        onlyRole(getRoleAdmin(role))
    {
        _grantRole(role, account);
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     *
     * May emit a {RoleRevoked} event.
     */
    function revokeRole(bytes32 role, address account)
        public
        virtual
        override
        onlyRole(getRoleAdmin(role))
    {
        _revokeRole(role, account);
    }

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been revoked `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     *
     * May emit a {RoleRevoked} event.
     */
    function renounceRole(bytes32 role, address account)
        public
        virtual
        override
    {
        require(
            account == _msgSender(),
            "AccessControl: can only renounce roles for self"
        );

        _revokeRole(role, account);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event. Note that unlike {grantRole}, this function doesn't perform any
     * checks on the calling account.
     *
     * May emit a {RoleGranted} event.
     *
     * [WARNING]
     * ====
     * This function should only be called from the constructor when setting
     * up the initial roles for the system.
     *
     * Using this function in any other way is effectively circumventing the admin
     * system imposed by {AccessControl}.
     * ====
     *
     * NOTE: This function is deprecated in favor of {_grantRole}.
     */
    function _setupRole(bytes32 role, address account) internal virtual {
        _grantRole(role, account);
    }

    /**
     * @dev Sets `adminRole` as ``role``'s admin role.
     *
     * Emits a {RoleAdminChanged} event.
     */
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        bytes32 previousAdminRole = getRoleAdmin(role);
        _roles[role].adminRole = adminRole;
        emit RoleAdminChanged(role, previousAdminRole, adminRole);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleGranted} event.
     */
    function _grantRole(bytes32 role, address account) internal virtual {
        if (!hasRole(role, account)) {
            _roles[role].members[account] = true;
            emit RoleGranted(role, account, _msgSender());
        }
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleRevoked} event.
     */
    function _revokeRole(bytes32 role, address account) internal virtual {
        if (hasRole(role, account)) {
            _roles[role].members[account] = false;
            emit RoleRevoked(role, account, _msgSender());
        }
    }
}

pragma solidity ^0.8.0;

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(
        address indexed from,
        address indexed to,
        uint256 indexed tokenId
    );

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(
        address indexed owner,
        address indexed approved,
        uint256 indexed tokenId
    );

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(
        address indexed owner,
        address indexed operator,
        bool approved
    );

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external;

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
     * understand this adds an external call which potentially creates a reentrancy vulnerability.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId)
        external
        view
        returns (address operator);

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator)
        external
        view
        returns (bool);
}

pragma solidity ^0.8.0;

/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Metadata is IERC721 {
    /**
     * @dev Returns the token collection name.
     */
    function name() external view returns (string memory);

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

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId) external view returns (string memory);
}

pragma solidity ^0.8.0;

/**
 * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
 * the Metadata extension, but not including the Enumerable extension, which is available separately as
 * {ERC721Enumerable}.
 */
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
    using Address for address;
    using Strings for uint256;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Mapping from token ID to owner address
    mapping(uint256 => address) private _owners;

    // Mapping owner address to token count
    mapping(address => uint256) private _balances;

    // Mapping from token ID to approved address
    mapping(uint256 => address) private _tokenApprovals;

    // Mapping from owner to operator approvals
    mapping(address => mapping(address => bool)) private _operatorApprovals;

    /**
     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override(ERC165, IERC165)
        returns (bool)
    {
        return
            interfaceId == type(IERC721).interfaceId ||
            interfaceId == type(IERC721Metadata).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    /**
     * @dev See {IERC721-balanceOf}.
     */
    function balanceOf(address owner)
        public
        view
        virtual
        override
        returns (uint256)
    {
        require(
            owner != address(0),
            "ERC721: address zero is not a valid owner"
        );
        return _balances[owner];
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId)
        public
        view
        virtual
        override
        returns (address)
    {
        address owner = _ownerOf(tokenId);
        require(owner != address(0), "ERC721: invalid token ID");
        return owner;
    }

    /**
     * @dev See {IERC721Metadata-name}.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev See {IERC721Metadata-symbol}.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId)
        public
        view
        virtual
        override
        returns (string memory)
    {
        _requireMinted(tokenId);

        string memory baseURI = _baseURI();
        return
            bytes(baseURI).length > 0
                ? string(abi.encodePacked(baseURI, tokenId.toString()))
                : "";
    }

    /**
     * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
     * token will be the concatenation of the `baseURI` and the `tokenId`. Empty
     * by default, can be overridden in child contracts.
     */
    function _baseURI() internal view virtual returns (string memory) {
        return "";
    }

    /**
     * @dev See {IERC721-approve}.
     */
    function approve(address to, uint256 tokenId) public virtual override {
        address owner = ERC721.ownerOf(tokenId);
        require(to != owner, "ERC721: approval to current owner");

        require(
            _msgSender() == owner || isApprovedForAll(owner, _msgSender()),
            "ERC721: approve caller is not token owner or approved for all"
        );

        _approve(to, tokenId);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId)
        public
        view
        virtual
        override
        returns (address)
    {
        _requireMinted(tokenId);

        return _tokenApprovals[tokenId];
    }

    /**
     * @dev See {IERC721-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved)
        public
        virtual
        override
    {
        _setApprovalForAll(_msgSender(), operator, approved);
    }

    /**
     * @dev See {IERC721-isApprovedForAll}.
     */
    function isApprovedForAll(address owner, address operator)
        public
        view
        virtual
        override
        returns (bool)
    {
        return _operatorApprovals[owner][operator];
    }

    /**
     * @dev See {IERC721-transferFrom}.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        //solhint-disable-next-line max-line-length
        require(
            _isApprovedOrOwner(_msgSender(), tokenId),
            "ERC721: caller is not token owner or approved"
        );

        _transfer(from, to, tokenId);
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        safeTransferFrom(from, to, tokenId, "");
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) public virtual override {
        require(
            _isApprovedOrOwner(_msgSender(), tokenId),
            "ERC721: caller is not token owner or approved"
        );
        _safeTransfer(from, to, tokenId, data);
    }

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * `data` is additional data, it has no specified format and it is sent in call to `to`.
     *
     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
     * implement alternative mechanisms to perform token transfer, such as signature-based.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeTransfer(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) internal virtual {
        _transfer(from, to, tokenId);
        require(
            _checkOnERC721Received(from, to, tokenId, data),
            "ERC721: transfer to non ERC721Receiver implementer"
        );
    }

    /**
     * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist
     */
    function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
        return _owners[tokenId];
    }

    /**
     * @dev Returns whether `tokenId` exists.
     *
     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
     *
     * Tokens start existing when they are minted (`_mint`),
     * and stop existing when they are burned (`_burn`).
     */
    function _exists(uint256 tokenId) internal view virtual returns (bool) {
        return _ownerOf(tokenId) != address(0);
    }

    /**
     * @dev Returns whether `spender` is allowed to manage `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function _isApprovedOrOwner(address spender, uint256 tokenId)
        internal
        view
        virtual
        returns (bool)
    {
        address owner = ERC721.ownerOf(tokenId);
        return (spender == owner ||
            isApprovedForAll(owner, spender) ||
            getApproved(tokenId) == spender);
    }

    /**
     * @dev Safely mints `tokenId` and transfers it to `to`.
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeMint(address to, uint256 tokenId) internal virtual {
        _safeMint(to, tokenId, "");
    }

    /**
     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
     */
    function _safeMint(
        address to,
        uint256 tokenId,
        bytes memory data
    ) internal virtual {
        _mint(to, tokenId);
        require(
            _checkOnERC721Received(address(0), to, tokenId, data),
            "ERC721: transfer to non ERC721Receiver implementer"
        );
    }

    /**
     * @dev Mints `tokenId` and transfers it to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - `to` cannot be the zero address.
     *
     * Emits a {Transfer} event.
     */
    function _mint(address to, uint256 tokenId) internal virtual {
        require(to != address(0), "ERC721: mint to the zero address");
        require(!_exists(tokenId), "ERC721: token already minted");

        _beforeTokenTransfer(address(0), to, tokenId, 1);

        // Check that tokenId was not minted by `_beforeTokenTransfer` hook
        require(!_exists(tokenId), "ERC721: token already minted");

        unchecked {
            // Will not overflow unless all 2**256 token ids are minted to the same owner.
            // Given that tokens are minted one by one, it is impossible in practice that
            // this ever happens. Might change if we allow batch minting.
            // The ERC fails to describe this case.
            _balances[to] += 1;
        }

        _owners[tokenId] = to;

        emit Transfer(address(0), to, tokenId);

        _afterTokenTransfer(address(0), to, tokenId, 1);
    }

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     * This is an internal function that does not check if the sender is authorized to operate on the token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId) internal virtual {
        address owner = ERC721.ownerOf(tokenId);

        _beforeTokenTransfer(owner, address(0), tokenId, 1);

        // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook
        owner = ERC721.ownerOf(tokenId);

        // Clear approvals
        delete _tokenApprovals[tokenId];

        unchecked {
            // Cannot overflow, as that would require more tokens to be burned/transferred
            // out than the owner initially received through minting and transferring in.
            _balances[owner] -= 1;
        }
        delete _owners[tokenId];

        emit Transfer(owner, address(0), tokenId);

        _afterTokenTransfer(owner, address(0), tokenId, 1);
    }

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     *
     * Emits a {Transfer} event.
     */
    function _transfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {
        require(
            ERC721.ownerOf(tokenId) == from,
            "ERC721: transfer from incorrect owner"
        );
        require(to != address(0), "ERC721: transfer to the zero address");

        _beforeTokenTransfer(from, to, tokenId, 1);

        // Check that tokenId was not transferred by `_beforeTokenTransfer` hook
        require(
            ERC721.ownerOf(tokenId) == from,
            "ERC721: transfer from incorrect owner"
        );

        // Clear approvals from the previous owner
        delete _tokenApprovals[tokenId];

        unchecked {
            // `_balances[from]` cannot overflow for the same reason as described in `_burn`:
            // `from`'s balance is the number of token held, which is at least one before the current
            // transfer.
            // `_balances[to]` could overflow in the conditions described in `_mint`. That would require
            // all 2**256 token ids to be minted, which in practice is impossible.
            _balances[from] -= 1;
            _balances[to] += 1;
        }
        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);

        _afterTokenTransfer(from, to, tokenId, 1);
    }

    /**
     * @dev Approve `to` to operate on `tokenId`
     *
     * Emits an {Approval} event.
     */
    function _approve(address to, uint256 tokenId) internal virtual {
        _tokenApprovals[tokenId] = to;
        emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
    }

    /**
     * @dev Approve `operator` to operate on all of `owner` tokens
     *
     * Emits an {ApprovalForAll} event.
     */
    function _setApprovalForAll(
        address owner,
        address operator,
        bool approved
    ) internal virtual {
        require(owner != operator, "ERC721: approve to caller");
        _operatorApprovals[owner][operator] = approved;
        emit ApprovalForAll(owner, operator, approved);
    }

    /**
     * @dev Reverts if the `tokenId` has not been minted yet.
     */
    function _requireMinted(uint256 tokenId) internal view virtual {
        require(_exists(tokenId), "ERC721: invalid token ID");
    }

    /**
     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
     * The call is not executed if the target address is not a contract.
     *
     * @param from address representing the previous owner of the given token ID
     * @param to target address that will receive the tokens
     * @param tokenId uint256 ID of the token to be transferred
     * @param data bytes optional data to send along with the call
     * @return bool whether the call correctly returned the expected magic value
     */
    function _checkOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) private returns (bool) {
        if (to.isContract()) {
            try
                IERC721Receiver(to).onERC721Received(
                    _msgSender(),
                    from,
                    tokenId,
                    data
                )
            returns (bytes4 retval) {
                return retval == IERC721Receiver.onERC721Received.selector;
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert(
                        "ERC721: transfer to non ERC721Receiver implementer"
                    );
                } else {
                    /// @solidity memory-safe-assembly
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        } else {
            return true;
        }
    }

    /**
     * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is
     * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`.
     * - When `from` is zero, the tokens will be minted for `to`.
     * - When `to` is zero, ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     * - `batchSize` is non-zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256, /* firstTokenId */
        uint256 batchSize
    ) internal virtual {
        if (batchSize > 1) {
            if (from != address(0)) {
                _balances[from] -= batchSize;
            }
            if (to != address(0)) {
                _balances[to] += batchSize;
            }
        }
    }

    /**
     * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is
     * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.
     * - When `from` is zero, the tokens were minted for `to`.
     * - When `to` is zero, ``from``'s tokens were burned.
     * - `from` and `to` are never both zero.
     * - `batchSize` is non-zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 firstTokenId,
        uint256 batchSize
    ) internal virtual {}
}

pragma solidity ^0.8.0;

/**
 * @title ERC721 Burnable Token
 * @dev ERC721 Token that can be burned (destroyed).
 */
abstract contract ERC721Burnable is Context, ERC721 {
    /**
     * @dev Burns `tokenId`. See {ERC721-_burn}.
     *
     * Requirements:
     *
     * - The caller must own `tokenId` or be an approved operator.
     */
    function burn(uint256 tokenId) public virtual {
        //solhint-disable-next-line max-line-length
        require(
            _isApprovedOrOwner(_msgSender(), tokenId),
            "ERC721: caller is not token owner or approved"
        );
        _burn(tokenId);
    }
}

pragma solidity ^0.8.0;

/**
 * @dev ERC721 token with storage based token URI management.
 */
abstract contract ERC721URIStorage is ERC721 {
    using Strings for uint256;

    // Optional mapping for token URIs
    mapping(uint256 => string) private _tokenURIs;

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId)
        public
        view
        virtual
        override
        returns (string memory)
    {
        _requireMinted(tokenId);

        string memory _tokenURI = _tokenURIs[tokenId];
        string memory base = _baseURI();

        // If there is no base URI, return the token URI.
        if (bytes(base).length == 0) {
            return _tokenURI;
        }
        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).
        if (bytes(_tokenURI).length > 0) {
            return string(abi.encodePacked(base, _tokenURI));
        }

        return super.tokenURI(tokenId);
    }

    /**
     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function _setTokenURI(uint256 tokenId, string memory _tokenURI)
        internal
        virtual
    {
        require(
            _exists(tokenId),
            "ERC721URIStorage: URI set of nonexistent token"
        );
        _tokenURIs[tokenId] = _tokenURI;
    }

    /**
     * @dev See {ERC721-_burn}. This override additionally checks to see if a
     * token-specific URI was set for the token, and if so, it deletes the token URI from
     * the storage mapping.
     */
    function _burn(uint256 tokenId) internal virtual override {
        super._burn(tokenId);

        if (bytes(_tokenURIs[tokenId]).length != 0) {
            delete _tokenURIs[tokenId];
        }
    }
}

pragma solidity ^0.8.9;

contract HasbullaGenesisCollection is
    ERC721,
    ERC721URIStorage,
    Pausable,
    AccessControl,
    ERC721Burnable
{
    using Counters for Counters.Counter;

    bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
    Counters.Counter private _tokenIdCounter;

    constructor() ERC721("Hasbulla Genesis Collection", "HGC") {
        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
        _grantRole(PAUSER_ROLE, msg.sender);
        _grantRole(MINTER_ROLE, msg.sender);
    }

    function pause() public onlyRole(PAUSER_ROLE) {
        _pause();
    }

    function unpause() public onlyRole(PAUSER_ROLE) {
        _unpause();
    }

    function safeMintBatch(address[] memory to, string[] memory uris)
        public
        onlyRole(MINTER_ROLE)
    {
        uint256 tokenId = _tokenIdCounter.current();
        for (uint256 i = 0; i < uris.length; i++) {
            _tokenIdCounter.increment();
            _safeMint(to[i], tokenId + i);
            _setTokenURI(tokenId + i, uris[i]);
        }
    }

    function safeMint(address to, string memory uri)
        public
        onlyRole(MINTER_ROLE)
    {
        uint256 tokenId = _tokenIdCounter.current();
        _tokenIdCounter.increment();
        _safeMint(to, tokenId);
        _setTokenURI(tokenId, uri);
    }

    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId,
        uint256 batchSize
    ) internal override whenNotPaused {
        super._beforeTokenTransfer(from, to, tokenId, batchSize);
    }

    // The following functions are overrides required by Solidity.

    function _burn(uint256 tokenId)
        internal
        override(ERC721, ERC721URIStorage)
    {
        super._burn(tokenId);
    }

    function tokenURI(uint256 tokenId)
        public
        view
        override(ERC721, ERC721URIStorage)
        returns (string memory)
    {
        return super.tokenURI(tokenId);
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        override(ERC721, AccessControl)
        returns (bool)
    {
        return super.supportsInterface(interfaceId);
    }

    function setTokenURI(uint256 tokenId, string memory _tokenURI)
        public
        onlyRole(MINTER_ROLE)
    {
        _setTokenURI(tokenId, _tokenURI);
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"string","name":"uri","type":"string"}],"name":"safeMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"to","type":"address[]"},{"internalType":"string[]","name":"uris","type":"string[]"}],"name":"safeMintBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"_tokenURI","type":"string"}],"name":"setTokenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040523480156200001157600080fd5b506040518060400160405280601b81526020017f48617362756c6c612047656e6573697320436f6c6c656374696f6e00000000008152506040518060400160405280600381526020017f484743000000000000000000000000000000000000000000000000000000000081525081600090816200008f91906200051d565b508060019081620000a191906200051d565b5050506000600760006101000a81548160ff021916908315150217905550620000d46000801b336200013e60201b60201c565b620001067f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a336200013e60201b60201c565b620001387f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6336200013e60201b60201c565b62000604565b6200015082826200023060201b60201c565b6200022c5760016008600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550620001d16200029b60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b60006008600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b600033905090565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200032557607f821691505b6020821081036200033b576200033a620002dd565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302620003a57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262000366565b620003b1868362000366565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b6000620003fe620003f8620003f284620003c9565b620003d3565b620003c9565b9050919050565b6000819050919050565b6200041a83620003dd565b62000432620004298262000405565b84845462000373565b825550505050565b600090565b620004496200043a565b620004568184846200040f565b505050565b5b818110156200047e57620004726000826200043f565b6001810190506200045c565b5050565b601f821115620004cd57620004978162000341565b620004a28462000356565b81016020851015620004b2578190505b620004ca620004c18562000356565b8301826200045b565b50505b505050565b600082821c905092915050565b6000620004f260001984600802620004d2565b1980831691505092915050565b60006200050d8383620004df565b9150826002028217905092915050565b6200052882620002a3565b67ffffffffffffffff811115620005445762000543620002ae565b5b6200055082546200030c565b6200055d82828562000482565b600060209050601f83116001811462000595576000841562000580578287015190505b6200058c8582620004ff565b865550620005fc565b601f198416620005a58662000341565b60005b82811015620005cf57848901518255600182019150602085019450602081019050620005a8565b86831015620005ef5784890151620005eb601f891682620004df565b8355505b6001600288020188555050505b505050505050565b61426880620006146000396000f3fe608060405234801561001057600080fd5b50600436106101c45760003560e01c80636352211e116100f9578063b88d4fde11610097578063d539139311610071578063d5391393146104d9578063d547741f146104f7578063e63ab1e914610513578063e985e9c514610531576101c4565b8063b88d4fde14610471578063c87b56dd1461048d578063d204c45e146104bd576101c4565b806391d14854116100d357806391d14854146103e957806395d89b4114610419578063a217fddf14610437578063a22cb46514610455576101c4565b80636352211e1461037f57806370a08231146103af5780638456cb59146103df576101c4565b8063248a9ca3116101665780633f4ba83a116101405780633f4ba83a1461031f57806342842e0e1461032957806342966c68146103455780635c975abb14610361576101c4565b8063248a9ca3146102b75780632f2ff15d146102e757806336568abe14610303576101c4565b8063095ea7b3116101a2578063095ea7b314610247578063133898f314610263578063162094c41461027f57806323b872dd1461029b576101c4565b806301ffc9a7146101c957806306fdde03146101f9578063081812fc14610217575b600080fd5b6101e360048036038101906101de91906129a9565b610561565b6040516101f091906129f1565b60405180910390f35b610201610573565b60405161020e9190612aa5565b60405180910390f35b610231600480360381019061022c9190612afd565b610605565b60405161023e9190612b6b565b60405180910390f35b610261600480360381019061025c9190612bb2565b61064b565b005b61027d60048036038101906102789190612ed0565b610762565b005b61029960048036038101906102949190612f48565b610828565b005b6102b560048036038101906102b09190612fa4565b610861565b005b6102d160048036038101906102cc919061302d565b6108c1565b6040516102de9190613069565b60405180910390f35b61030160048036038101906102fc9190613084565b6108e1565b005b61031d60048036038101906103189190613084565b610902565b005b610327610985565b005b610343600480360381019061033e9190612fa4565b6109ba565b005b61035f600480360381019061035a9190612afd565b6109da565b005b610369610a36565b60405161037691906129f1565b60405180910390f35b61039960048036038101906103949190612afd565b610a4d565b6040516103a69190612b6b565b60405180910390f35b6103c960048036038101906103c491906130c4565b610ad3565b6040516103d69190613100565b60405180910390f35b6103e7610b8a565b005b61040360048036038101906103fe9190613084565b610bbf565b60405161041091906129f1565b60405180910390f35b610421610c2a565b60405161042e9190612aa5565b60405180910390f35b61043f610cbc565b60405161044c9190613069565b60405180910390f35b61046f600480360381019061046a9190613147565b610cc3565b005b61048b60048036038101906104869190613228565b610cd9565b005b6104a760048036038101906104a29190612afd565b610d3b565b6040516104b49190612aa5565b60405180910390f35b6104d760048036038101906104d291906132ab565b610d4d565b005b6104e1610da9565b6040516104ee9190613069565b60405180910390f35b610511600480360381019061050c9190613084565b610dcd565b005b61051b610dee565b6040516105289190613069565b60405180910390f35b61054b60048036038101906105469190613307565b610e12565b60405161055891906129f1565b60405180910390f35b600061056c82610ea6565b9050919050565b60606000805461058290613376565b80601f01602080910402602001604051908101604052809291908181526020018280546105ae90613376565b80156105fb5780601f106105d0576101008083540402835291602001916105fb565b820191906000526020600020905b8154815290600101906020018083116105de57829003601f168201915b5050505050905090565b600061061082610f20565b6004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b600061065682610a4d565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036106c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106bd90613419565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166106e5610f6b565b73ffffffffffffffffffffffffffffffffffffffff16148061071457506107138161070e610f6b565b610e12565b5b610753576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161074a906134ab565b60405180910390fd5b61075d8383610f73565b505050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a661078c8161102c565b60006107986009611040565b905060005b8351811015610821576107b0600961104e565b6107df8582815181106107c6576107c56134cb565b5b602002602001015182846107da9190613529565b611064565b61080e81836107ee9190613529565b858381518110610801576108006134cb565b5b6020026020010151611082565b80806108199061357f565b91505061079d565b5050505050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a66108528161102c565b61085c8383611082565b505050565b61087261086c610f6b565b826110ef565b6108b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108a890613639565b60405180910390fd5b6108bc838383611184565b505050565b600060086000838152602001908152602001600020600101549050919050565b6108ea826108c1565b6108f38161102c565b6108fd838361147d565b505050565b61090a610f6b565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610977576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161096e906136cb565b60405180910390fd5b610981828261155e565b5050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a6109af8161102c565b6109b7611640565b50565b6109d583838360405180602001604052806000815250610cd9565b505050565b6109eb6109e5610f6b565b826110ef565b610a2a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a2190613639565b60405180910390fd5b610a33816116a3565b50565b6000600760009054906101000a900460ff16905090565b600080610a59836116af565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610aca576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ac190613737565b60405180910390fd5b80915050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610b43576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b3a906137c9565b60405180910390fd5b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a610bb48161102c565b610bbc6116ec565b50565b60006008600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b606060018054610c3990613376565b80601f0160208091040260200160405190810160405280929190818152602001828054610c6590613376565b8015610cb25780601f10610c8757610100808354040283529160200191610cb2565b820191906000526020600020905b815481529060010190602001808311610c9557829003601f168201915b5050505050905090565b6000801b81565b610cd5610cce610f6b565b838361174f565b5050565b610cea610ce4610f6b565b836110ef565b610d29576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d2090613639565b60405180910390fd5b610d35848484846118bb565b50505050565b6060610d4682611917565b9050919050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6610d778161102c565b6000610d836009611040565b9050610d8f600961104e565b610d998482611064565b610da38184611082565b50505050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b610dd6826108c1565b610ddf8161102c565b610de9838361155e565b505050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b60007f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610f195750610f1882611a29565b5b9050919050565b610f2981611b0b565b610f68576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f5f90613737565b60405180910390fd5b50565b600033905090565b816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16610fe683610a4d565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b61103d81611038610f6b565b611b4c565b50565b600081600001549050919050565b6001816000016000828254019250508190555050565b61107e828260405180602001604052806000815250611bd1565b5050565b61108b82611b0b565b6110ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110c19061385b565b60405180910390fd5b806006600084815260200190815260200160002090816110ea9190613a27565b505050565b6000806110fb83610a4d565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16148061113d575061113c8185610e12565b5b8061117b57508373ffffffffffffffffffffffffffffffffffffffff1661116384610605565b73ffffffffffffffffffffffffffffffffffffffff16145b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff166111a482610a4d565b73ffffffffffffffffffffffffffffffffffffffff16146111fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111f190613b6b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611269576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161126090613bfd565b60405180910390fd5b6112768383836001611c2c565b8273ffffffffffffffffffffffffffffffffffffffff1661129682610a4d565b73ffffffffffffffffffffffffffffffffffffffff16146112ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112e390613b6b565b60405180910390fd5b6004600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46114788383836001611c46565b505050565b6114878282610bbf565b61155a5760016008600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506114ff610f6b565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b6115688282610bbf565b1561163c5760006008600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506115e1610f6b565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45b5050565b611648611c4c565b6000600760006101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa61168c610f6b565b6040516116999190612b6b565b60405180910390a1565b6116ac81611c95565b50565b60006002600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6116f4611ce8565b6001600760006101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611738610f6b565b6040516117459190612b6b565b60405180910390a1565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036117bd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117b490613c69565b60405180910390fd5b80600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516118ae91906129f1565b60405180910390a3505050565b6118c6848484611184565b6118d284848484611d32565b611911576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161190890613cfb565b60405180910390fd5b50505050565b606061192282610f20565b600060066000848152602001908152602001600020805461194290613376565b80601f016020809104026020016040519081016040528092919081815260200182805461196e90613376565b80156119bb5780601f10611990576101008083540402835291602001916119bb565b820191906000526020600020905b81548152906001019060200180831161199e57829003601f168201915b5050505050905060006119cc611eb9565b905060008151036119e1578192505050611a24565b600082511115611a165780826040516020016119fe929190613d57565b60405160208183030381529060405292505050611a24565b611a1f84611ed0565b925050505b919050565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611af457507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80611b045750611b0382611f38565b5b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff16611b2d836116af565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b611b568282610bbf565b611bcd57611b6381611fa2565b611b718360001c6020611fcf565b604051602001611b82929190613e13565b6040516020818303038152906040526040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bc49190612aa5565b60405180910390fd5b5050565b611bdb838361220b565b611be86000848484611d32565b611c27576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c1e90613cfb565b60405180910390fd5b505050565b611c34611ce8565b611c4084848484612428565b50505050565b50505050565b611c54610a36565b611c93576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c8a90613e99565b60405180910390fd5b565b611c9e8161254e565b6000600660008381526020019081526020016000208054611cbe90613376565b905014611ce557600660008281526020019081526020016000206000611ce491906128e0565b5b50565b611cf0610a36565b15611d30576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d2790613f05565b60405180910390fd5b565b6000611d538473ffffffffffffffffffffffffffffffffffffffff1661269c565b15611eac578373ffffffffffffffffffffffffffffffffffffffff1663150b7a02611d7c610f6b565b8786866040518563ffffffff1660e01b8152600401611d9e9493929190613f7a565b6020604051808303816000875af1925050508015611dda57506040513d601f19601f82011682018060405250810190611dd79190613fdb565b60015b611e5c573d8060008114611e0a576040519150601f19603f3d011682016040523d82523d6000602084013e611e0f565b606091505b506000815103611e54576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e4b90613cfb565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050611eb1565b600190505b949350505050565b606060405180602001604052806000815250905090565b6060611edb82610f20565b6000611ee5611eb9565b90506000815111611f055760405180602001604052806000815250611f30565b80611f0f846126bf565b604051602001611f20929190613d57565b6040516020818303038152906040525b915050919050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6060611fc88273ffffffffffffffffffffffffffffffffffffffff16601460ff16611fcf565b9050919050565b606060006002836002611fe29190614008565b611fec9190613529565b67ffffffffffffffff81111561200557612004612bf7565b5b6040519080825280601f01601f1916602001820160405280156120375781602001600182028036833780820191505090505b5090507f30000000000000000000000000000000000000000000000000000000000000008160008151811061206f5761206e6134cb565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f7800000000000000000000000000000000000000000000000000000000000000816001815181106120d3576120d26134cb565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600060018460026121139190614008565b61211d9190613529565b90505b60018111156121bd577f3031323334353637383961626364656600000000000000000000000000000000600f86166010811061215f5761215e6134cb565b5b1a60f81b828281518110612176576121756134cb565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600485901c9450806121b690614062565b9050612120565b5060008414612201576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121f8906140d7565b60405180910390fd5b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361227a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161227190614143565b60405180910390fd5b61228381611b0b565b156122c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122ba906141af565b60405180910390fd5b6122d1600083836001611c2c565b6122da81611b0b565b1561231a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612311906141af565b60405180910390fd5b6001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4612424600083836001611c46565b5050565b600181111561254857600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16146124bc5780600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546124b491906141cf565b925050819055505b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16146125475780600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461253f9190613529565b925050819055505b5b50505050565b600061255982610a4d565b9050612569816000846001611c2c565b61257282610a4d565b90506004600083815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506002600083815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905581600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4612698816000846001611c46565b5050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b6060600060016126ce8461278d565b01905060008167ffffffffffffffff8111156126ed576126ec612bf7565b5b6040519080825280601f01601f19166020018201604052801561271f5781602001600182028036833780820191505090505b509050600082602001820190505b600115612782578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a858161277657612775614203565b5b0494506000850361272d575b819350505050919050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106127eb577a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083816127e1576127e0614203565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310612828576d04ee2d6d415b85acef8100000000838161281e5761281d614203565b5b0492506020810190505b662386f26fc10000831061285757662386f26fc10000838161284d5761284c614203565b5b0492506010810190505b6305f5e1008310612880576305f5e100838161287657612875614203565b5b0492506008810190505b61271083106128a557612710838161289b5761289a614203565b5b0492506004810190505b606483106128c857606483816128be576128bd614203565b5b0492506002810190505b600a83106128d7576001810190505b80915050919050565b5080546128ec90613376565b6000825580601f106128fe575061291d565b601f01602090049060005260206000209081019061291c9190612920565b5b50565b5b80821115612939576000816000905550600101612921565b5090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61298681612951565b811461299157600080fd5b50565b6000813590506129a38161297d565b92915050565b6000602082840312156129bf576129be612947565b5b60006129cd84828501612994565b91505092915050565b60008115159050919050565b6129eb816129d6565b82525050565b6000602082019050612a0660008301846129e2565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612a46578082015181840152602081019050612a2b565b83811115612a55576000848401525b50505050565b6000601f19601f8301169050919050565b6000612a7782612a0c565b612a818185612a17565b9350612a91818560208601612a28565b612a9a81612a5b565b840191505092915050565b60006020820190508181036000830152612abf8184612a6c565b905092915050565b6000819050919050565b612ada81612ac7565b8114612ae557600080fd5b50565b600081359050612af781612ad1565b92915050565b600060208284031215612b1357612b12612947565b5b6000612b2184828501612ae8565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612b5582612b2a565b9050919050565b612b6581612b4a565b82525050565b6000602082019050612b806000830184612b5c565b92915050565b612b8f81612b4a565b8114612b9a57600080fd5b50565b600081359050612bac81612b86565b92915050565b60008060408385031215612bc957612bc8612947565b5b6000612bd785828601612b9d565b9250506020612be885828601612ae8565b9150509250929050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612c2f82612a5b565b810181811067ffffffffffffffff82111715612c4e57612c4d612bf7565b5b80604052505050565b6000612c6161293d565b9050612c6d8282612c26565b919050565b600067ffffffffffffffff821115612c8d57612c8c612bf7565b5b602082029050602081019050919050565b600080fd5b6000612cb6612cb184612c72565b612c57565b90508083825260208201905060208402830185811115612cd957612cd8612c9e565b5b835b81811015612d025780612cee8882612b9d565b845260208401935050602081019050612cdb565b5050509392505050565b600082601f830112612d2157612d20612bf2565b5b8135612d31848260208601612ca3565b91505092915050565b600067ffffffffffffffff821115612d5557612d54612bf7565b5b602082029050602081019050919050565b600080fd5b600067ffffffffffffffff821115612d8657612d85612bf7565b5b612d8f82612a5b565b9050602081019050919050565b82818337600083830152505050565b6000612dbe612db984612d6b565b612c57565b905082815260208101848484011115612dda57612dd9612d66565b5b612de5848285612d9c565b509392505050565b600082601f830112612e0257612e01612bf2565b5b8135612e12848260208601612dab565b91505092915050565b6000612e2e612e2984612d3a565b612c57565b90508083825260208201905060208402830185811115612e5157612e50612c9e565b5b835b81811015612e9857803567ffffffffffffffff811115612e7657612e75612bf2565b5b808601612e838982612ded565b85526020850194505050602081019050612e53565b5050509392505050565b600082601f830112612eb757612eb6612bf2565b5b8135612ec7848260208601612e1b565b91505092915050565b60008060408385031215612ee757612ee6612947565b5b600083013567ffffffffffffffff811115612f0557612f0461294c565b5b612f1185828601612d0c565b925050602083013567ffffffffffffffff811115612f3257612f3161294c565b5b612f3e85828601612ea2565b9150509250929050565b60008060408385031215612f5f57612f5e612947565b5b6000612f6d85828601612ae8565b925050602083013567ffffffffffffffff811115612f8e57612f8d61294c565b5b612f9a85828601612ded565b9150509250929050565b600080600060608486031215612fbd57612fbc612947565b5b6000612fcb86828701612b9d565b9350506020612fdc86828701612b9d565b9250506040612fed86828701612ae8565b9150509250925092565b6000819050919050565b61300a81612ff7565b811461301557600080fd5b50565b60008135905061302781613001565b92915050565b60006020828403121561304357613042612947565b5b600061305184828501613018565b91505092915050565b61306381612ff7565b82525050565b600060208201905061307e600083018461305a565b92915050565b6000806040838503121561309b5761309a612947565b5b60006130a985828601613018565b92505060206130ba85828601612b9d565b9150509250929050565b6000602082840312156130da576130d9612947565b5b60006130e884828501612b9d565b91505092915050565b6130fa81612ac7565b82525050565b600060208201905061311560008301846130f1565b92915050565b613124816129d6565b811461312f57600080fd5b50565b6000813590506131418161311b565b92915050565b6000806040838503121561315e5761315d612947565b5b600061316c85828601612b9d565b925050602061317d85828601613132565b9150509250929050565b600067ffffffffffffffff8211156131a2576131a1612bf7565b5b6131ab82612a5b565b9050602081019050919050565b60006131cb6131c684613187565b612c57565b9050828152602081018484840111156131e7576131e6612d66565b5b6131f2848285612d9c565b509392505050565b600082601f83011261320f5761320e612bf2565b5b813561321f8482602086016131b8565b91505092915050565b6000806000806080858703121561324257613241612947565b5b600061325087828801612b9d565b945050602061326187828801612b9d565b935050604061327287828801612ae8565b925050606085013567ffffffffffffffff8111156132935761329261294c565b5b61329f878288016131fa565b91505092959194509250565b600080604083850312156132c2576132c1612947565b5b60006132d085828601612b9d565b925050602083013567ffffffffffffffff8111156132f1576132f061294c565b5b6132fd85828601612ded565b9150509250929050565b6000806040838503121561331e5761331d612947565b5b600061332c85828601612b9d565b925050602061333d85828601612b9d565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061338e57607f821691505b6020821081036133a1576133a0613347565b5b50919050565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b6000613403602183612a17565b915061340e826133a7565b604082019050919050565b60006020820190508181036000830152613432816133f6565b9050919050565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60008201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c000000602082015250565b6000613495603d83612a17565b91506134a082613439565b604082019050919050565b600060208201905081810360008301526134c481613488565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061353482612ac7565b915061353f83612ac7565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115613574576135736134fa565b5b828201905092915050565b600061358a82612ac7565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036135bc576135bb6134fa565b5b600182019050919050565b7f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560008201527f72206f7220617070726f76656400000000000000000000000000000000000000602082015250565b6000613623602d83612a17565b915061362e826135c7565b604082019050919050565b6000602082019050818103600083015261365281613616565b9050919050565b7f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560008201527f20726f6c657320666f722073656c660000000000000000000000000000000000602082015250565b60006136b5602f83612a17565b91506136c082613659565b604082019050919050565b600060208201905081810360008301526136e4816136a8565b9050919050565b7f4552433732313a20696e76616c696420746f6b656e2049440000000000000000600082015250565b6000613721601883612a17565b915061372c826136eb565b602082019050919050565b6000602082019050818103600083015261375081613714565b9050919050565b7f4552433732313a2061646472657373207a65726f206973206e6f74206120766160008201527f6c6964206f776e65720000000000000000000000000000000000000000000000602082015250565b60006137b3602983612a17565b91506137be82613757565b604082019050919050565b600060208201905081810360008301526137e2816137a6565b9050919050565b7f45524337323155524953746f726167653a2055524920736574206f66206e6f6e60008201527f6578697374656e7420746f6b656e000000000000000000000000000000000000602082015250565b6000613845602e83612a17565b9150613850826137e9565b604082019050919050565b6000602082019050818103600083015261387481613838565b9050919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026138dd7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826138a0565b6138e786836138a0565b95508019841693508086168417925050509392505050565b6000819050919050565b600061392461391f61391a84612ac7565b6138ff565b612ac7565b9050919050565b6000819050919050565b61393e83613909565b61395261394a8261392b565b8484546138ad565b825550505050565b600090565b61396761395a565b613972818484613935565b505050565b5b818110156139965761398b60008261395f565b600181019050613978565b5050565b601f8211156139db576139ac8161387b565b6139b584613890565b810160208510156139c4578190505b6139d86139d085613890565b830182613977565b50505b505050565b600082821c905092915050565b60006139fe600019846008026139e0565b1980831691505092915050565b6000613a1783836139ed565b9150826002028217905092915050565b613a3082612a0c565b67ffffffffffffffff811115613a4957613a48612bf7565b5b613a538254613376565b613a5e82828561399a565b600060209050601f831160018114613a915760008415613a7f578287015190505b613a898582613a0b565b865550613af1565b601f198416613a9f8661387b565b60005b82811015613ac757848901518255600182019150602085019450602081019050613aa2565b86831015613ae45784890151613ae0601f8916826139ed565b8355505b6001600288020188555050505b505050505050565b7f4552433732313a207472616e736665722066726f6d20696e636f72726563742060008201527f6f776e6572000000000000000000000000000000000000000000000000000000602082015250565b6000613b55602583612a17565b9150613b6082613af9565b604082019050919050565b60006020820190508181036000830152613b8481613b48565b9050919050565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b6000613be7602483612a17565b9150613bf282613b8b565b604082019050919050565b60006020820190508181036000830152613c1681613bda565b9050919050565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b6000613c53601983612a17565b9150613c5e82613c1d565b602082019050919050565b60006020820190508181036000830152613c8281613c46565b9050919050565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b6000613ce5603283612a17565b9150613cf082613c89565b604082019050919050565b60006020820190508181036000830152613d1481613cd8565b9050919050565b600081905092915050565b6000613d3182612a0c565b613d3b8185613d1b565b9350613d4b818560208601612a28565b80840191505092915050565b6000613d638285613d26565b9150613d6f8284613d26565b91508190509392505050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000600082015250565b6000613db1601783613d1b565b9150613dbc82613d7b565b601782019050919050565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000600082015250565b6000613dfd601183613d1b565b9150613e0882613dc7565b601182019050919050565b6000613e1e82613da4565b9150613e2a8285613d26565b9150613e3582613df0565b9150613e418284613d26565b91508190509392505050565b7f5061757361626c653a206e6f7420706175736564000000000000000000000000600082015250565b6000613e83601483612a17565b9150613e8e82613e4d565b602082019050919050565b60006020820190508181036000830152613eb281613e76565b9050919050565b7f5061757361626c653a2070617573656400000000000000000000000000000000600082015250565b6000613eef601083612a17565b9150613efa82613eb9565b602082019050919050565b60006020820190508181036000830152613f1e81613ee2565b9050919050565b600081519050919050565b600082825260208201905092915050565b6000613f4c82613f25565b613f568185613f30565b9350613f66818560208601612a28565b613f6f81612a5b565b840191505092915050565b6000608082019050613f8f6000830187612b5c565b613f9c6020830186612b5c565b613fa960408301856130f1565b8181036060830152613fbb8184613f41565b905095945050505050565b600081519050613fd58161297d565b92915050565b600060208284031215613ff157613ff0612947565b5b6000613fff84828501613fc6565b91505092915050565b600061401382612ac7565b915061401e83612ac7565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615614057576140566134fa565b5b828202905092915050565b600061406d82612ac7565b9150600082036140805761407f6134fa565b5b600182039050919050565b7f537472696e67733a20686578206c656e67746820696e73756666696369656e74600082015250565b60006140c1602083612a17565b91506140cc8261408b565b602082019050919050565b600060208201905081810360008301526140f0816140b4565b9050919050565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b600061412d602083612a17565b9150614138826140f7565b602082019050919050565b6000602082019050818103600083015261415c81614120565b9050919050565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b6000614199601c83612a17565b91506141a482614163565b602082019050919050565b600060208201905081810360008301526141c88161418c565b9050919050565b60006141da82612ac7565b91506141e583612ac7565b9250828210156141f8576141f76134fa565b5b828203905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea26469706673582212207713a7d4cfa6d67248bf7396a9915beb007cb1d522fb7a2f792232ee197c3b8164736f6c634300080f0033

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101c45760003560e01c80636352211e116100f9578063b88d4fde11610097578063d539139311610071578063d5391393146104d9578063d547741f146104f7578063e63ab1e914610513578063e985e9c514610531576101c4565b8063b88d4fde14610471578063c87b56dd1461048d578063d204c45e146104bd576101c4565b806391d14854116100d357806391d14854146103e957806395d89b4114610419578063a217fddf14610437578063a22cb46514610455576101c4565b80636352211e1461037f57806370a08231146103af5780638456cb59146103df576101c4565b8063248a9ca3116101665780633f4ba83a116101405780633f4ba83a1461031f57806342842e0e1461032957806342966c68146103455780635c975abb14610361576101c4565b8063248a9ca3146102b75780632f2ff15d146102e757806336568abe14610303576101c4565b8063095ea7b3116101a2578063095ea7b314610247578063133898f314610263578063162094c41461027f57806323b872dd1461029b576101c4565b806301ffc9a7146101c957806306fdde03146101f9578063081812fc14610217575b600080fd5b6101e360048036038101906101de91906129a9565b610561565b6040516101f091906129f1565b60405180910390f35b610201610573565b60405161020e9190612aa5565b60405180910390f35b610231600480360381019061022c9190612afd565b610605565b60405161023e9190612b6b565b60405180910390f35b610261600480360381019061025c9190612bb2565b61064b565b005b61027d60048036038101906102789190612ed0565b610762565b005b61029960048036038101906102949190612f48565b610828565b005b6102b560048036038101906102b09190612fa4565b610861565b005b6102d160048036038101906102cc919061302d565b6108c1565b6040516102de9190613069565b60405180910390f35b61030160048036038101906102fc9190613084565b6108e1565b005b61031d60048036038101906103189190613084565b610902565b005b610327610985565b005b610343600480360381019061033e9190612fa4565b6109ba565b005b61035f600480360381019061035a9190612afd565b6109da565b005b610369610a36565b60405161037691906129f1565b60405180910390f35b61039960048036038101906103949190612afd565b610a4d565b6040516103a69190612b6b565b60405180910390f35b6103c960048036038101906103c491906130c4565b610ad3565b6040516103d69190613100565b60405180910390f35b6103e7610b8a565b005b61040360048036038101906103fe9190613084565b610bbf565b60405161041091906129f1565b60405180910390f35b610421610c2a565b60405161042e9190612aa5565b60405180910390f35b61043f610cbc565b60405161044c9190613069565b60405180910390f35b61046f600480360381019061046a9190613147565b610cc3565b005b61048b60048036038101906104869190613228565b610cd9565b005b6104a760048036038101906104a29190612afd565b610d3b565b6040516104b49190612aa5565b60405180910390f35b6104d760048036038101906104d291906132ab565b610d4d565b005b6104e1610da9565b6040516104ee9190613069565b60405180910390f35b610511600480360381019061050c9190613084565b610dcd565b005b61051b610dee565b6040516105289190613069565b60405180910390f35b61054b60048036038101906105469190613307565b610e12565b60405161055891906129f1565b60405180910390f35b600061056c82610ea6565b9050919050565b60606000805461058290613376565b80601f01602080910402602001604051908101604052809291908181526020018280546105ae90613376565b80156105fb5780601f106105d0576101008083540402835291602001916105fb565b820191906000526020600020905b8154815290600101906020018083116105de57829003601f168201915b5050505050905090565b600061061082610f20565b6004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b600061065682610a4d565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036106c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106bd90613419565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166106e5610f6b565b73ffffffffffffffffffffffffffffffffffffffff16148061071457506107138161070e610f6b565b610e12565b5b610753576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161074a906134ab565b60405180910390fd5b61075d8383610f73565b505050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a661078c8161102c565b60006107986009611040565b905060005b8351811015610821576107b0600961104e565b6107df8582815181106107c6576107c56134cb565b5b602002602001015182846107da9190613529565b611064565b61080e81836107ee9190613529565b858381518110610801576108006134cb565b5b6020026020010151611082565b80806108199061357f565b91505061079d565b5050505050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a66108528161102c565b61085c8383611082565b505050565b61087261086c610f6b565b826110ef565b6108b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108a890613639565b60405180910390fd5b6108bc838383611184565b505050565b600060086000838152602001908152602001600020600101549050919050565b6108ea826108c1565b6108f38161102c565b6108fd838361147d565b505050565b61090a610f6b565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610977576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161096e906136cb565b60405180910390fd5b610981828261155e565b5050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a6109af8161102c565b6109b7611640565b50565b6109d583838360405180602001604052806000815250610cd9565b505050565b6109eb6109e5610f6b565b826110ef565b610a2a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a2190613639565b60405180910390fd5b610a33816116a3565b50565b6000600760009054906101000a900460ff16905090565b600080610a59836116af565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610aca576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ac190613737565b60405180910390fd5b80915050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610b43576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b3a906137c9565b60405180910390fd5b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a610bb48161102c565b610bbc6116ec565b50565b60006008600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b606060018054610c3990613376565b80601f0160208091040260200160405190810160405280929190818152602001828054610c6590613376565b8015610cb25780601f10610c8757610100808354040283529160200191610cb2565b820191906000526020600020905b815481529060010190602001808311610c9557829003601f168201915b5050505050905090565b6000801b81565b610cd5610cce610f6b565b838361174f565b5050565b610cea610ce4610f6b565b836110ef565b610d29576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d2090613639565b60405180910390fd5b610d35848484846118bb565b50505050565b6060610d4682611917565b9050919050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6610d778161102c565b6000610d836009611040565b9050610d8f600961104e565b610d998482611064565b610da38184611082565b50505050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b610dd6826108c1565b610ddf8161102c565b610de9838361155e565b505050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b60007f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610f195750610f1882611a29565b5b9050919050565b610f2981611b0b565b610f68576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f5f90613737565b60405180910390fd5b50565b600033905090565b816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16610fe683610a4d565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b61103d81611038610f6b565b611b4c565b50565b600081600001549050919050565b6001816000016000828254019250508190555050565b61107e828260405180602001604052806000815250611bd1565b5050565b61108b82611b0b565b6110ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110c19061385b565b60405180910390fd5b806006600084815260200190815260200160002090816110ea9190613a27565b505050565b6000806110fb83610a4d565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16148061113d575061113c8185610e12565b5b8061117b57508373ffffffffffffffffffffffffffffffffffffffff1661116384610605565b73ffffffffffffffffffffffffffffffffffffffff16145b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff166111a482610a4d565b73ffffffffffffffffffffffffffffffffffffffff16146111fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111f190613b6b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611269576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161126090613bfd565b60405180910390fd5b6112768383836001611c2c565b8273ffffffffffffffffffffffffffffffffffffffff1661129682610a4d565b73ffffffffffffffffffffffffffffffffffffffff16146112ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112e390613b6b565b60405180910390fd5b6004600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46114788383836001611c46565b505050565b6114878282610bbf565b61155a5760016008600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506114ff610f6b565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b6115688282610bbf565b1561163c5760006008600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506115e1610f6b565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45b5050565b611648611c4c565b6000600760006101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa61168c610f6b565b6040516116999190612b6b565b60405180910390a1565b6116ac81611c95565b50565b60006002600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6116f4611ce8565b6001600760006101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611738610f6b565b6040516117459190612b6b565b60405180910390a1565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036117bd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117b490613c69565b60405180910390fd5b80600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516118ae91906129f1565b60405180910390a3505050565b6118c6848484611184565b6118d284848484611d32565b611911576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161190890613cfb565b60405180910390fd5b50505050565b606061192282610f20565b600060066000848152602001908152602001600020805461194290613376565b80601f016020809104026020016040519081016040528092919081815260200182805461196e90613376565b80156119bb5780601f10611990576101008083540402835291602001916119bb565b820191906000526020600020905b81548152906001019060200180831161199e57829003601f168201915b5050505050905060006119cc611eb9565b905060008151036119e1578192505050611a24565b600082511115611a165780826040516020016119fe929190613d57565b60405160208183030381529060405292505050611a24565b611a1f84611ed0565b925050505b919050565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611af457507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80611b045750611b0382611f38565b5b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff16611b2d836116af565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b611b568282610bbf565b611bcd57611b6381611fa2565b611b718360001c6020611fcf565b604051602001611b82929190613e13565b6040516020818303038152906040526040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bc49190612aa5565b60405180910390fd5b5050565b611bdb838361220b565b611be86000848484611d32565b611c27576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c1e90613cfb565b60405180910390fd5b505050565b611c34611ce8565b611c4084848484612428565b50505050565b50505050565b611c54610a36565b611c93576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c8a90613e99565b60405180910390fd5b565b611c9e8161254e565b6000600660008381526020019081526020016000208054611cbe90613376565b905014611ce557600660008281526020019081526020016000206000611ce491906128e0565b5b50565b611cf0610a36565b15611d30576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d2790613f05565b60405180910390fd5b565b6000611d538473ffffffffffffffffffffffffffffffffffffffff1661269c565b15611eac578373ffffffffffffffffffffffffffffffffffffffff1663150b7a02611d7c610f6b565b8786866040518563ffffffff1660e01b8152600401611d9e9493929190613f7a565b6020604051808303816000875af1925050508015611dda57506040513d601f19601f82011682018060405250810190611dd79190613fdb565b60015b611e5c573d8060008114611e0a576040519150601f19603f3d011682016040523d82523d6000602084013e611e0f565b606091505b506000815103611e54576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e4b90613cfb565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050611eb1565b600190505b949350505050565b606060405180602001604052806000815250905090565b6060611edb82610f20565b6000611ee5611eb9565b90506000815111611f055760405180602001604052806000815250611f30565b80611f0f846126bf565b604051602001611f20929190613d57565b6040516020818303038152906040525b915050919050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6060611fc88273ffffffffffffffffffffffffffffffffffffffff16601460ff16611fcf565b9050919050565b606060006002836002611fe29190614008565b611fec9190613529565b67ffffffffffffffff81111561200557612004612bf7565b5b6040519080825280601f01601f1916602001820160405280156120375781602001600182028036833780820191505090505b5090507f30000000000000000000000000000000000000000000000000000000000000008160008151811061206f5761206e6134cb565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f7800000000000000000000000000000000000000000000000000000000000000816001815181106120d3576120d26134cb565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600060018460026121139190614008565b61211d9190613529565b90505b60018111156121bd577f3031323334353637383961626364656600000000000000000000000000000000600f86166010811061215f5761215e6134cb565b5b1a60f81b828281518110612176576121756134cb565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600485901c9450806121b690614062565b9050612120565b5060008414612201576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121f8906140d7565b60405180910390fd5b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361227a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161227190614143565b60405180910390fd5b61228381611b0b565b156122c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122ba906141af565b60405180910390fd5b6122d1600083836001611c2c565b6122da81611b0b565b1561231a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612311906141af565b60405180910390fd5b6001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4612424600083836001611c46565b5050565b600181111561254857600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16146124bc5780600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546124b491906141cf565b925050819055505b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16146125475780600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461253f9190613529565b925050819055505b5b50505050565b600061255982610a4d565b9050612569816000846001611c2c565b61257282610a4d565b90506004600083815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506002600083815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905581600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4612698816000846001611c46565b5050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b6060600060016126ce8461278d565b01905060008167ffffffffffffffff8111156126ed576126ec612bf7565b5b6040519080825280601f01601f19166020018201604052801561271f5781602001600182028036833780820191505090505b509050600082602001820190505b600115612782578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a858161277657612775614203565b5b0494506000850361272d575b819350505050919050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106127eb577a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083816127e1576127e0614203565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310612828576d04ee2d6d415b85acef8100000000838161281e5761281d614203565b5b0492506020810190505b662386f26fc10000831061285757662386f26fc10000838161284d5761284c614203565b5b0492506010810190505b6305f5e1008310612880576305f5e100838161287657612875614203565b5b0492506008810190505b61271083106128a557612710838161289b5761289a614203565b5b0492506004810190505b606483106128c857606483816128be576128bd614203565b5b0492506002810190505b600a83106128d7576001810190505b80915050919050565b5080546128ec90613376565b6000825580601f106128fe575061291d565b601f01602090049060005260206000209081019061291c9190612920565b5b50565b5b80821115612939576000816000905550600101612921565b5090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61298681612951565b811461299157600080fd5b50565b6000813590506129a38161297d565b92915050565b6000602082840312156129bf576129be612947565b5b60006129cd84828501612994565b91505092915050565b60008115159050919050565b6129eb816129d6565b82525050565b6000602082019050612a0660008301846129e2565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612a46578082015181840152602081019050612a2b565b83811115612a55576000848401525b50505050565b6000601f19601f8301169050919050565b6000612a7782612a0c565b612a818185612a17565b9350612a91818560208601612a28565b612a9a81612a5b565b840191505092915050565b60006020820190508181036000830152612abf8184612a6c565b905092915050565b6000819050919050565b612ada81612ac7565b8114612ae557600080fd5b50565b600081359050612af781612ad1565b92915050565b600060208284031215612b1357612b12612947565b5b6000612b2184828501612ae8565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612b5582612b2a565b9050919050565b612b6581612b4a565b82525050565b6000602082019050612b806000830184612b5c565b92915050565b612b8f81612b4a565b8114612b9a57600080fd5b50565b600081359050612bac81612b86565b92915050565b60008060408385031215612bc957612bc8612947565b5b6000612bd785828601612b9d565b9250506020612be885828601612ae8565b9150509250929050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612c2f82612a5b565b810181811067ffffffffffffffff82111715612c4e57612c4d612bf7565b5b80604052505050565b6000612c6161293d565b9050612c6d8282612c26565b919050565b600067ffffffffffffffff821115612c8d57612c8c612bf7565b5b602082029050602081019050919050565b600080fd5b6000612cb6612cb184612c72565b612c57565b90508083825260208201905060208402830185811115612cd957612cd8612c9e565b5b835b81811015612d025780612cee8882612b9d565b845260208401935050602081019050612cdb565b5050509392505050565b600082601f830112612d2157612d20612bf2565b5b8135612d31848260208601612ca3565b91505092915050565b600067ffffffffffffffff821115612d5557612d54612bf7565b5b602082029050602081019050919050565b600080fd5b600067ffffffffffffffff821115612d8657612d85612bf7565b5b612d8f82612a5b565b9050602081019050919050565b82818337600083830152505050565b6000612dbe612db984612d6b565b612c57565b905082815260208101848484011115612dda57612dd9612d66565b5b612de5848285612d9c565b509392505050565b600082601f830112612e0257612e01612bf2565b5b8135612e12848260208601612dab565b91505092915050565b6000612e2e612e2984612d3a565b612c57565b90508083825260208201905060208402830185811115612e5157612e50612c9e565b5b835b81811015612e9857803567ffffffffffffffff811115612e7657612e75612bf2565b5b808601612e838982612ded565b85526020850194505050602081019050612e53565b5050509392505050565b600082601f830112612eb757612eb6612bf2565b5b8135612ec7848260208601612e1b565b91505092915050565b60008060408385031215612ee757612ee6612947565b5b600083013567ffffffffffffffff811115612f0557612f0461294c565b5b612f1185828601612d0c565b925050602083013567ffffffffffffffff811115612f3257612f3161294c565b5b612f3e85828601612ea2565b9150509250929050565b60008060408385031215612f5f57612f5e612947565b5b6000612f6d85828601612ae8565b925050602083013567ffffffffffffffff811115612f8e57612f8d61294c565b5b612f9a85828601612ded565b9150509250929050565b600080600060608486031215612fbd57612fbc612947565b5b6000612fcb86828701612b9d565b9350506020612fdc86828701612b9d565b9250506040612fed86828701612ae8565b9150509250925092565b6000819050919050565b61300a81612ff7565b811461301557600080fd5b50565b60008135905061302781613001565b92915050565b60006020828403121561304357613042612947565b5b600061305184828501613018565b91505092915050565b61306381612ff7565b82525050565b600060208201905061307e600083018461305a565b92915050565b6000806040838503121561309b5761309a612947565b5b60006130a985828601613018565b92505060206130ba85828601612b9d565b9150509250929050565b6000602082840312156130da576130d9612947565b5b60006130e884828501612b9d565b91505092915050565b6130fa81612ac7565b82525050565b600060208201905061311560008301846130f1565b92915050565b613124816129d6565b811461312f57600080fd5b50565b6000813590506131418161311b565b92915050565b6000806040838503121561315e5761315d612947565b5b600061316c85828601612b9d565b925050602061317d85828601613132565b9150509250929050565b600067ffffffffffffffff8211156131a2576131a1612bf7565b5b6131ab82612a5b565b9050602081019050919050565b60006131cb6131c684613187565b612c57565b9050828152602081018484840111156131e7576131e6612d66565b5b6131f2848285612d9c565b509392505050565b600082601f83011261320f5761320e612bf2565b5b813561321f8482602086016131b8565b91505092915050565b6000806000806080858703121561324257613241612947565b5b600061325087828801612b9d565b945050602061326187828801612b9d565b935050604061327287828801612ae8565b925050606085013567ffffffffffffffff8111156132935761329261294c565b5b61329f878288016131fa565b91505092959194509250565b600080604083850312156132c2576132c1612947565b5b60006132d085828601612b9d565b925050602083013567ffffffffffffffff8111156132f1576132f061294c565b5b6132fd85828601612ded565b9150509250929050565b6000806040838503121561331e5761331d612947565b5b600061332c85828601612b9d565b925050602061333d85828601612b9d565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061338e57607f821691505b6020821081036133a1576133a0613347565b5b50919050565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b6000613403602183612a17565b915061340e826133a7565b604082019050919050565b60006020820190508181036000830152613432816133f6565b9050919050565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60008201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c000000602082015250565b6000613495603d83612a17565b91506134a082613439565b604082019050919050565b600060208201905081810360008301526134c481613488565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061353482612ac7565b915061353f83612ac7565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115613574576135736134fa565b5b828201905092915050565b600061358a82612ac7565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036135bc576135bb6134fa565b5b600182019050919050565b7f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560008201527f72206f7220617070726f76656400000000000000000000000000000000000000602082015250565b6000613623602d83612a17565b915061362e826135c7565b604082019050919050565b6000602082019050818103600083015261365281613616565b9050919050565b7f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560008201527f20726f6c657320666f722073656c660000000000000000000000000000000000602082015250565b60006136b5602f83612a17565b91506136c082613659565b604082019050919050565b600060208201905081810360008301526136e4816136a8565b9050919050565b7f4552433732313a20696e76616c696420746f6b656e2049440000000000000000600082015250565b6000613721601883612a17565b915061372c826136eb565b602082019050919050565b6000602082019050818103600083015261375081613714565b9050919050565b7f4552433732313a2061646472657373207a65726f206973206e6f74206120766160008201527f6c6964206f776e65720000000000000000000000000000000000000000000000602082015250565b60006137b3602983612a17565b91506137be82613757565b604082019050919050565b600060208201905081810360008301526137e2816137a6565b9050919050565b7f45524337323155524953746f726167653a2055524920736574206f66206e6f6e60008201527f6578697374656e7420746f6b656e000000000000000000000000000000000000602082015250565b6000613845602e83612a17565b9150613850826137e9565b604082019050919050565b6000602082019050818103600083015261387481613838565b9050919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026138dd7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826138a0565b6138e786836138a0565b95508019841693508086168417925050509392505050565b6000819050919050565b600061392461391f61391a84612ac7565b6138ff565b612ac7565b9050919050565b6000819050919050565b61393e83613909565b61395261394a8261392b565b8484546138ad565b825550505050565b600090565b61396761395a565b613972818484613935565b505050565b5b818110156139965761398b60008261395f565b600181019050613978565b5050565b601f8211156139db576139ac8161387b565b6139b584613890565b810160208510156139c4578190505b6139d86139d085613890565b830182613977565b50505b505050565b600082821c905092915050565b60006139fe600019846008026139e0565b1980831691505092915050565b6000613a1783836139ed565b9150826002028217905092915050565b613a3082612a0c565b67ffffffffffffffff811115613a4957613a48612bf7565b5b613a538254613376565b613a5e82828561399a565b600060209050601f831160018114613a915760008415613a7f578287015190505b613a898582613a0b565b865550613af1565b601f198416613a9f8661387b565b60005b82811015613ac757848901518255600182019150602085019450602081019050613aa2565b86831015613ae45784890151613ae0601f8916826139ed565b8355505b6001600288020188555050505b505050505050565b7f4552433732313a207472616e736665722066726f6d20696e636f72726563742060008201527f6f776e6572000000000000000000000000000000000000000000000000000000602082015250565b6000613b55602583612a17565b9150613b6082613af9565b604082019050919050565b60006020820190508181036000830152613b8481613b48565b9050919050565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b6000613be7602483612a17565b9150613bf282613b8b565b604082019050919050565b60006020820190508181036000830152613c1681613bda565b9050919050565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b6000613c53601983612a17565b9150613c5e82613c1d565b602082019050919050565b60006020820190508181036000830152613c8281613c46565b9050919050565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b6000613ce5603283612a17565b9150613cf082613c89565b604082019050919050565b60006020820190508181036000830152613d1481613cd8565b9050919050565b600081905092915050565b6000613d3182612a0c565b613d3b8185613d1b565b9350613d4b818560208601612a28565b80840191505092915050565b6000613d638285613d26565b9150613d6f8284613d26565b91508190509392505050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000600082015250565b6000613db1601783613d1b565b9150613dbc82613d7b565b601782019050919050565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000600082015250565b6000613dfd601183613d1b565b9150613e0882613dc7565b601182019050919050565b6000613e1e82613da4565b9150613e2a8285613d26565b9150613e3582613df0565b9150613e418284613d26565b91508190509392505050565b7f5061757361626c653a206e6f7420706175736564000000000000000000000000600082015250565b6000613e83601483612a17565b9150613e8e82613e4d565b602082019050919050565b60006020820190508181036000830152613eb281613e76565b9050919050565b7f5061757361626c653a2070617573656400000000000000000000000000000000600082015250565b6000613eef601083612a17565b9150613efa82613eb9565b602082019050919050565b60006020820190508181036000830152613f1e81613ee2565b9050919050565b600081519050919050565b600082825260208201905092915050565b6000613f4c82613f25565b613f568185613f30565b9350613f66818560208601612a28565b613f6f81612a5b565b840191505092915050565b6000608082019050613f8f6000830187612b5c565b613f9c6020830186612b5c565b613fa960408301856130f1565b8181036060830152613fbb8184613f41565b905095945050505050565b600081519050613fd58161297d565b92915050565b600060208284031215613ff157613ff0612947565b5b6000613fff84828501613fc6565b91505092915050565b600061401382612ac7565b915061401e83612ac7565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615614057576140566134fa565b5b828202905092915050565b600061406d82612ac7565b9150600082036140805761407f6134fa565b5b600182039050919050565b7f537472696e67733a20686578206c656e67746820696e73756666696369656e74600082015250565b60006140c1602083612a17565b91506140cc8261408b565b602082019050919050565b600060208201905081810360008301526140f0816140b4565b9050919050565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b600061412d602083612a17565b9150614138826140f7565b602082019050919050565b6000602082019050818103600083015261415c81614120565b9050919050565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b6000614199601c83612a17565b91506141a482614163565b602082019050919050565b600060208201905081810360008301526141c88161418c565b9050919050565b60006141da82612ac7565b91506141e583612ac7565b9250828210156141f8576141f76134fa565b5b828203905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea26469706673582212207713a7d4cfa6d67248bf7396a9915beb007cb1d522fb7a2f792232ee197c3b8164736f6c634300080f0033

Deployed Bytecode Sourcemap

70437:2476:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;72527:209;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;52305:100;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;53914:221;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;53432:416;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;71191:379;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;72744:166;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;54746:372;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;40125:181;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;40616:188;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;41842:287;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;71106:77;;;:::i;:::-;;55189:185;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;68236:279;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;21978:86;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;51965:273;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;51609:294;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;71025:73;;;:::i;:::-;;38548:197;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;52474:104;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;37577:49;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;54207:187;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;55445:359;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;72323:196;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;71578:271;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;70687:62;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;41097:190;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;70618:62;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;54465:214;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;72527:209;72663:4;72692:36;72716:11;72692:23;:36::i;:::-;72685:43;;72527:209;;;:::o;52305:100::-;52359:13;52392:5;52385:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52305:100;:::o;53914:221::-;54035:7;54060:23;54075:7;54060:14;:23::i;:::-;54103:15;:24;54119:7;54103:24;;;;;;;;;;;;;;;;;;;;;54096:31;;53914:221;;;:::o;53432:416::-;53513:13;53529:23;53544:7;53529:14;:23::i;:::-;53513:39;;53577:5;53571:11;;:2;:11;;;53563:57;;;;;;;;;;;;:::i;:::-;;;;;;;;;53671:5;53655:21;;:12;:10;:12::i;:::-;:21;;;:62;;;;53680:37;53697:5;53704:12;:10;:12::i;:::-;53680:16;:37::i;:::-;53655:62;53633:173;;;;;;;;;;;;:::i;:::-;;;;;;;;;53819:21;53828:2;53832:7;53819:8;:21::i;:::-;53502:346;53432:416;;:::o;71191:379::-;70725:24;38068:16;38079:4;38068:10;:16::i;:::-;71320:15:::1;71338:25;:15;:23;:25::i;:::-;71320:43;;71379:9;71374:189;71398:4;:11;71394:1;:15;71374:189;;;71431:27;:15;:25;:27::i;:::-;71473:29;71483:2;71486:1;71483:5;;;;;;;;:::i;:::-;;;;;;;;71500:1;71490:7;:11;;;;:::i;:::-;71473:9;:29::i;:::-;71517:34;71540:1;71530:7;:11;;;;:::i;:::-;71543:4;71548:1;71543:7;;;;;;;;:::i;:::-;;;;;;;;71517:12;:34::i;:::-;71411:3;;;;;:::i;:::-;;;;71374:189;;;;71309:261;71191:379:::0;;;:::o;72744:166::-;70725:24;38068:16;38079:4;38068:10;:16::i;:::-;72870:32:::1;72883:7;72892:9;72870:12;:32::i;:::-;72744:166:::0;;;:::o;54746:372::-;54955:41;54974:12;:10;:12::i;:::-;54988:7;54955:18;:41::i;:::-;54933:136;;;;;;;;;;;;:::i;:::-;;;;;;;;;55082:28;55092:4;55098:2;55102:7;55082:9;:28::i;:::-;54746:372;;;:::o;40125:181::-;40244:7;40276:6;:12;40283:4;40276:12;;;;;;;;;;;:22;;;40269:29;;40125:181;;;:::o;40616:188::-;40735:18;40748:4;40735:12;:18::i;:::-;38068:16;38079:4;38068:10;:16::i;:::-;40771:25:::1;40782:4;40788:7;40771:10;:25::i;:::-;40616:188:::0;;;:::o;41842:287::-;41995:12;:10;:12::i;:::-;41984:23;;:7;:23;;;41962:120;;;;;;;;;;;;:::i;:::-;;;;;;;;;42095:26;42107:4;42113:7;42095:11;:26::i;:::-;41842:287;;:::o;71106:77::-;70656:24;38068:16;38079:4;38068:10;:16::i;:::-;71165:10:::1;:8;:10::i;:::-;71106:77:::0;:::o;55189:185::-;55327:39;55344:4;55350:2;55354:7;55327:39;;;;;;;;;;;;:16;:39::i;:::-;55189:185;;;:::o;68236:279::-;68368:41;68387:12;:10;:12::i;:::-;68401:7;68368:18;:41::i;:::-;68346:136;;;;;;;;;;;;:::i;:::-;;;;;;;;;68493:14;68499:7;68493:5;:14::i;:::-;68236:279;:::o;21978:86::-;22025:4;22049:7;;;;;;;;;;;22042:14;;21978:86;:::o;51965:273::-;52082:7;52107:13;52123:17;52132:7;52123:8;:17::i;:::-;52107:33;;52176:1;52159:19;;:5;:19;;;52151:56;;;;;;;;;;;;:::i;:::-;;;;;;;;;52225:5;52218:12;;;51965:273;;;:::o;51609:294::-;51726:7;51790:1;51773:19;;:5;:19;;;51751:110;;;;;;;;;;;;:::i;:::-;;;;;;;;;51879:9;:16;51889:5;51879:16;;;;;;;;;;;;;;;;51872:23;;51609:294;;;:::o;71025:73::-;70656:24;38068:16;38079:4;38068:10;:16::i;:::-;71082:8:::1;:6;:8::i;:::-;71025:73:::0;:::o;38548:197::-;38679:4;38708:6;:12;38715:4;38708:12;;;;;;;;;;;:20;;:29;38729:7;38708:29;;;;;;;;;;;;;;;;;;;;;;;;;38701:36;;38548:197;;;;:::o;52474:104::-;52530:13;52563:7;52556:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52474:104;:::o;37577:49::-;37622:4;37577:49;;;:::o;54207:187::-;54334:52;54353:12;:10;:12::i;:::-;54367:8;54377;54334:18;:52::i;:::-;54207:187;;:::o;55445:359::-;55633:41;55652:12;:10;:12::i;:::-;55666:7;55633:18;:41::i;:::-;55611:136;;;;;;;;;;;;:::i;:::-;;;;;;;;;55758:38;55772:4;55778:2;55782:7;55791:4;55758:13;:38::i;:::-;55445:359;;;;:::o;72323:196::-;72450:13;72488:23;72503:7;72488:14;:23::i;:::-;72481:30;;72323:196;;;:::o;71578:271::-;70725:24;38068:16;38079:4;38068:10;:16::i;:::-;71690:15:::1;71708:25;:15;:23;:25::i;:::-;71690:43;;71744:27;:15;:25;:27::i;:::-;71782:22;71792:2;71796:7;71782:9;:22::i;:::-;71815:26;71828:7;71837:3;71815:12;:26::i;:::-;71679:170;71578:271:::0;;;:::o;70687:62::-;70725:24;70687:62;:::o;41097:190::-;41217:18;41230:4;41217:12;:18::i;:::-;38068:16;38079:4;38068:10;:16::i;:::-;41253:26:::1;41265:4;41271:7;41253:11;:26::i;:::-;41097:190:::0;;;:::o;70618:62::-;70656:24;70618:62;:::o;54465:214::-;54607:4;54636:18;:25;54655:5;54636:25;;;;;;;;;;;;;;;:35;54662:8;54636:35;;;;;;;;;;;;;;;;;;;;;;;;;54629:42;;54465:214;;;;:::o;38176:280::-;38306:4;38363:32;38348:47;;;:11;:47;;;;:100;;;;38412:36;38436:11;38412:23;:36::i;:::-;38348:100;38328:120;;38176:280;;;:::o;64117:135::-;64199:16;64207:7;64199;:16::i;:::-;64191:53;;;;;;;;;;;;:::i;:::-;;;;;;;;;64117:135;:::o;20228:98::-;20281:7;20308:10;20301:17;;20228:98;:::o;63396:174::-;63498:2;63471:15;:24;63487:7;63471:24;;;;;;;;;;;;:29;;;;;;;;;;;;;;;;;;63554:7;63550:2;63516:46;;63525:23;63540:7;63525:14;:23::i;:::-;63516:46;;;;;;;;;;;;63396:174;;:::o;39049:105::-;39116:30;39127:4;39133:12;:10;:12::i;:::-;39116:10;:30::i;:::-;39049:105;:::o;791:114::-;856:7;883;:14;;;876:21;;791:114;;;:::o;913:127::-;1020:1;1002:7;:14;;;:19;;;;;;;;;;;913:127;:::o;58547:110::-;58623:26;58633:2;58637:7;58623:26;;;;;;;;;;;;:9;:26::i;:::-;58547:110;;:::o;69695:277::-;69832:16;69840:7;69832;:16::i;:::-;69810:112;;;;;;;;;;;;:::i;:::-;;;;;;;;;69955:9;69933:10;:19;69944:7;69933:19;;;;;;;;;;;:31;;;;;;:::i;:::-;;69695:277;;:::o;57874:331::-;58003:4;58025:13;58041:23;58056:7;58041:14;:23::i;:::-;58025:39;;58094:5;58083:16;;:7;:16;;;:65;;;;58116:32;58133:5;58140:7;58116:16;:32::i;:::-;58083:65;:113;;;;58189:7;58165:31;;:20;58177:7;58165:11;:20::i;:::-;:31;;;58083:113;58075:122;;;57874:331;;;;:::o;61940:1337::-;62113:4;62086:31;;:23;62101:7;62086:14;:23::i;:::-;:31;;;62064:118;;;;;;;;;;;;:::i;:::-;;;;;;;;;62215:1;62201:16;;:2;:16;;;62193:65;;;;;;;;;;;;:::i;:::-;;;;;;;;;62271:42;62292:4;62298:2;62302:7;62311:1;62271:20;:42::i;:::-;62457:4;62430:31;;:23;62445:7;62430:14;:23::i;:::-;:31;;;62408:118;;;;;;;;;;;;:::i;:::-;;;;;;;;;62598:15;:24;62614:7;62598:24;;;;;;;;;;;;62591:31;;;;;;;;;;;63093:1;63074:9;:15;63084:4;63074:15;;;;;;;;;;;;;;;;:20;;;;;;;;;;;63126:1;63109:9;:13;63119:2;63109:13;;;;;;;;;;;;;;;;:18;;;;;;;;;;;63168:2;63149:7;:16;63157:7;63149:16;;;;;;;;;;;;:21;;;;;;;;;;;;;;;;;;63207:7;63203:2;63188:27;;63197:4;63188:27;;;;;;;;;;;;63228:41;63248:4;63254:2;63258:7;63267:1;63228:19;:41::i;:::-;61940:1337;;;:::o;43508:238::-;43592:22;43600:4;43606:7;43592;:22::i;:::-;43587:152;;43663:4;43631:6;:12;43638:4;43631:12;;;;;;;;;;;:20;;:29;43652:7;43631:29;;;;;;;;;;;;;;;;:36;;;;;;;;;;;;;;;;;;43714:12;:10;:12::i;:::-;43687:40;;43705:7;43687:40;;43699:4;43687:40;;;;;;;;;;43587:152;43508:238;;:::o;43926:239::-;44010:22;44018:4;44024:7;44010;:22::i;:::-;44006:152;;;44081:5;44049:6;:12;44056:4;44049:12;;;;;;;;;;;:20;;:29;44070:7;44049:29;;;;;;;;;;;;;;;;:37;;;;;;;;;;;;;;;;;;44133:12;:10;:12::i;:::-;44106:40;;44124:7;44106:40;;44118:4;44106:40;;;;;;;;;;44006:152;43926:239;;:::o;22833:120::-;21842:16;:14;:16::i;:::-;22902:5:::1;22892:7;;:15;;;;;;;;;;;;;;;;;;22923:22;22932:12;:10;:12::i;:::-;22923:22;;;;;;:::i;:::-;;;;;;;;22833:120::o:0;72177:138::-;72287:20;72299:7;72287:11;:20::i;:::-;72177:138;:::o;57149:117::-;57215:7;57242;:16;57250:7;57242:16;;;;;;;;;;;;;;;;;;;;;57235:23;;57149:117;;;:::o;22574:118::-;21583:19;:17;:19::i;:::-;22644:4:::1;22634:7;;:14;;;;;;;;;;;;;;;;;;22664:20;22671:12;:10;:12::i;:::-;22664:20;;;;;;:::i;:::-;;;;;;;;22574:118::o:0;63713:315::-;63868:8;63859:17;;:5;:17;;;63851:55;;;;;;;;;;;;:::i;:::-;;;;;;;;;63955:8;63917:18;:25;63936:5;63917:25;;;;;;;;;;;;;;;:35;63943:8;63917:35;;;;;;;;;;;;;;;;:46;;;;;;;;;;;;;;;;;;64001:8;63979:41;;63994:5;63979:41;;;64011:8;63979:41;;;;;;:::i;:::-;;;;;;;;63713:315;;;:::o;56685:350::-;56841:28;56851:4;56857:2;56861:7;56841:9;:28::i;:::-;56902:47;56925:4;56931:2;56935:7;56944:4;56902:22;:47::i;:::-;56880:147;;;;;;;;;;;;:::i;:::-;;;;;;;;;56685:350;;;;:::o;68865:674::-;68983:13;69014:23;69029:7;69014:14;:23::i;:::-;69050;69076:10;:19;69087:7;69076:19;;;;;;;;;;;69050:45;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;69106:18;69127:10;:8;:10::i;:::-;69106:31;;69235:1;69219:4;69213:18;:23;69209:72;;69260:9;69253:16;;;;;;69209:72;69411:1;69391:9;69385:23;:27;69381:108;;;69460:4;69466:9;69443:33;;;;;;;;;:::i;:::-;;;;;;;;;;;;;69429:48;;;;;;69381:108;69508:23;69523:7;69508:14;:23::i;:::-;69501:30;;;;68865:674;;;;:::o;51190:355::-;51337:4;51394:25;51379:40;;;:11;:40;;;;:105;;;;51451:33;51436:48;;;:11;:48;;;;51379:105;:158;;;;51501:36;51525:11;51501:23;:36::i;:::-;51379:158;51359:178;;51190:355;;;:::o;57579:128::-;57644:4;57697:1;57668:31;;:17;57677:7;57668:8;:17::i;:::-;:31;;;;57661:38;;57579:128;;;:::o;39444:492::-;39533:22;39541:4;39547:7;39533;:22::i;:::-;39528:401;;39721:28;39741:7;39721:19;:28::i;:::-;39822:38;39850:4;39842:13;;39857:2;39822:19;:38::i;:::-;39626:257;;;;;;;;;:::i;:::-;;;;;;;;;;;;;39572:345;;;;;;;;;;;:::i;:::-;;;;;;;;39528:401;39444:492;;:::o;58884:319::-;59013:18;59019:2;59023:7;59013:5;:18::i;:::-;59064:53;59095:1;59099:2;59103:7;59112:4;59064:22;:53::i;:::-;59042:153;;;;;;;;;;;;:::i;:::-;;;;;;;;;58884:319;;;:::o;71857:242::-;21583:19;:17;:19::i;:::-;72035:56:::1;72062:4;72068:2;72072:7;72081:9;72035:26;:56::i;:::-;71857:242:::0;;;;:::o;67714:158::-;;;;;:::o;22322:108::-;22389:8;:6;:8::i;:::-;22381:41;;;;;;;;;;;;:::i;:::-;;;;;;;;;22322:108::o;70197:206::-;70266:20;70278:7;70266:11;:20::i;:::-;70340:1;70309:10;:19;70320:7;70309:19;;;;;;;;;;;70303:33;;;;;:::i;:::-;;;:38;70299:97;;70365:10;:19;70376:7;70365:19;;;;;;;;;;;;70358:26;;;;:::i;:::-;70299:97;70197:206;:::o;22137:108::-;22208:8;:6;:8::i;:::-;22207:9;22199:38;;;;;;;;;;;;:::i;:::-;;;;;;;;;22137:108::o;64816:1034::-;64970:4;64991:15;:2;:13;;;:15::i;:::-;64987:856;;;65060:2;65044:36;;;65103:12;:10;:12::i;:::-;65138:4;65165:7;65195:4;65044:174;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;65023:765;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;65418:1;65401:6;:13;:18;65397:376;;65444:108;;;;;;;;;;:::i;:::-;;;;;;;;65397:376;65723:6;65717:13;65708:6;65704:2;65700:15;65693:38;65023:765;65292:41;;;65282:51;;;:6;:51;;;;65275:58;;;;;64987:856;65827:4;65820:11;;64816:1034;;;;;;;:::o;53276:94::-;53327:13;53353:9;;;;;;;;;;;;;;53276:94;:::o;52649:378::-;52767:13;52798:23;52813:7;52798:14;:23::i;:::-;52834:21;52858:10;:8;:10::i;:::-;52834:34;;52923:1;52905:7;52899:21;:25;:120;;;;;;;;;;;;;;;;;52968:7;52977:18;:7;:16;:18::i;:::-;52951:45;;;;;;;;;:::i;:::-;;;;;;;;;;;;;52899:120;52879:140;;;52649:378;;;:::o;35534:207::-;35664:4;35708:25;35693:40;;;:11;:40;;;;35686:47;;35534:207;;;:::o;19503:151::-;19561:13;19594:52;19622:4;19606:22;;17626:2;19594:52;;:11;:52::i;:::-;19587:59;;19503:151;;;:::o;18867:479::-;18969:13;19000:19;19045:1;19036:6;19032:1;:10;;;;:::i;:::-;:14;;;;:::i;:::-;19022:25;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19000:47;;19058:15;:6;19065:1;19058:9;;;;;;;;:::i;:::-;;;;;:15;;;;;;;;;;;19084;:6;19091:1;19084:9;;;;;;;;:::i;:::-;;;;;:15;;;;;;;;;;;19115:9;19140:1;19131:6;19127:1;:10;;;;:::i;:::-;:14;;;;:::i;:::-;19115:26;;19110:131;19147:1;19143;:5;19110:131;;;19182:8;19199:3;19191:5;:11;19182:21;;;;;;;:::i;:::-;;;;;19170:6;19177:1;19170:9;;;;;;;;:::i;:::-;;;;;:33;;;;;;;;;;;19228:1;19218:11;;;;;19150:3;;;;:::i;:::-;;;19110:131;;;;19268:1;19259:5;:10;19251:55;;;;;;;;;;;;:::i;:::-;;;;;;;;;19331:6;19317:21;;;18867:479;;;;:::o;59539:942::-;59633:1;59619:16;;:2;:16;;;59611:61;;;;;;;;;;;;:::i;:::-;;;;;;;;;59692:16;59700:7;59692;:16::i;:::-;59691:17;59683:58;;;;;;;;;;;;:::i;:::-;;;;;;;;;59754:48;59783:1;59787:2;59791:7;59800:1;59754:20;:48::i;:::-;59901:16;59909:7;59901;:16::i;:::-;59900:17;59892:58;;;;;;;;;;;;:::i;:::-;;;;;;;;;60316:1;60299:9;:13;60309:2;60299:13;;;;;;;;;;;;;;;;:18;;;;;;;;;;;60360:2;60341:7;:16;60349:7;60341:16;;;;;;;;;;;;:21;;;;;;;;;;;;;;;;;;60405:7;60401:2;60380:33;;60397:1;60380:33;;;;;;;;;;;;60426:47;60454:1;60458:2;60462:7;60471:1;60426:19;:47::i;:::-;59539:942;;:::o;66582:410::-;66772:1;66760:9;:13;66756:229;;;66810:1;66794:18;;:4;:18;;;66790:87;;66852:9;66833;:15;66843:4;66833:15;;;;;;;;;;;;;;;;:28;;;;;;;:::i;:::-;;;;;;;;66790:87;66909:1;66895:16;;:2;:16;;;66891:83;;66949:9;66932;:13;66942:2;66932:13;;;;;;;;;;;;;;;;:26;;;;;;;:::i;:::-;;;;;;;;66891:83;66756:229;66582:410;;;;:::o;60820:783::-;60880:13;60896:23;60911:7;60896:14;:23::i;:::-;60880:39;;60932:51;60953:5;60968:1;60972:7;60981:1;60932:20;:51::i;:::-;61096:23;61111:7;61096:14;:23::i;:::-;61088:31;;61167:15;:24;61183:7;61167:24;;;;;;;;;;;;61160:31;;;;;;;;;;;61432:1;61412:9;:16;61422:5;61412:16;;;;;;;;;;;;;;;;:21;;;;;;;;;;;61462:7;:16;61470:7;61462:16;;;;;;;;;;;;61455:23;;;;;;;;;;;61524:7;61520:1;61496:36;;61505:5;61496:36;;;;;;;;;;;;61545:50;61565:5;61580:1;61584:7;61593:1;61545:19;:50::i;:::-;60869:734;60820:783;:::o;24066:326::-;24126:4;24383:1;24361:7;:19;;;:23;24354:30;;24066:326;;;:::o;17735:716::-;17791:13;17842:14;17879:1;17859:17;17870:5;17859:10;:17::i;:::-;:21;17842:38;;17895:20;17929:6;17918:18;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17895:41;;17951:11;18080:6;18076:2;18072:15;18064:6;18060:28;18053:35;;18117:288;18124:4;18117:288;;;18149:5;;;;;;;;18291:8;18286:2;18279:5;18275:14;18270:30;18265:3;18257:44;18347:2;18338:11;;;;;;:::i;:::-;;;;;18381:1;18372:5;:10;18117:288;18368:21;18117:288;18426:6;18419:13;;;;;17735:716;;;:::o;14598:922::-;14651:7;14671:14;14688:1;14671:18;;14738:6;14729:5;:15;14725:102;;14774:6;14765:15;;;;;;:::i;:::-;;;;;14809:2;14799:12;;;;14725:102;14854:6;14845:5;:15;14841:102;;14890:6;14881:15;;;;;;:::i;:::-;;;;;14925:2;14915:12;;;;14841:102;14970:6;14961:5;:15;14957:102;;15006:6;14997:15;;;;;;:::i;:::-;;;;;15041:2;15031:12;;;;14957:102;15086:5;15077;:14;15073:99;;15121:5;15112:14;;;;;;:::i;:::-;;;;;15155:1;15145:11;;;;15073:99;15199:5;15190;:14;15186:99;;15234:5;15225:14;;;;;;:::i;:::-;;;;;15268:1;15258:11;;;;15186:99;15312:5;15303;:14;15299:99;;15347:5;15338:14;;;;;;:::i;:::-;;;;;15381:1;15371:11;;;;15299:99;15425:5;15416;:14;15412:66;;15461:1;15451:11;;;;15412:66;15506:6;15499:13;;;14598:922;;;:::o;-1:-1:-1:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;:::o;7:75:1:-;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:149;370:7;410:66;403:5;399:78;388:89;;334:149;;;:::o;489:120::-;561:23;578:5;561:23;:::i;:::-;554:5;551:34;541:62;;599:1;596;589:12;541:62;489:120;:::o;615:137::-;660:5;698:6;685:20;676:29;;714:32;740:5;714:32;:::i;:::-;615:137;;;;:::o;758:327::-;816:6;865:2;853:9;844:7;840:23;836:32;833:119;;;871:79;;:::i;:::-;833:119;991:1;1016:52;1060:7;1051:6;1040:9;1036:22;1016:52;:::i;:::-;1006:62;;962:116;758:327;;;;:::o;1091:90::-;1125:7;1168:5;1161:13;1154:21;1143:32;;1091:90;;;:::o;1187:109::-;1268:21;1283:5;1268:21;:::i;:::-;1263:3;1256:34;1187:109;;:::o;1302:210::-;1389:4;1427:2;1416:9;1412:18;1404:26;;1440:65;1502:1;1491:9;1487:17;1478:6;1440:65;:::i;:::-;1302:210;;;;:::o;1518:99::-;1570:6;1604:5;1598:12;1588:22;;1518:99;;;:::o;1623:169::-;1707:11;1741:6;1736:3;1729:19;1781:4;1776:3;1772:14;1757:29;;1623:169;;;;:::o;1798:307::-;1866:1;1876:113;1890:6;1887:1;1884:13;1876:113;;;1975:1;1970:3;1966:11;1960:18;1956:1;1951:3;1947:11;1940:39;1912:2;1909:1;1905:10;1900:15;;1876:113;;;2007:6;2004:1;2001:13;1998:101;;;2087:1;2078:6;2073:3;2069:16;2062:27;1998:101;1847:258;1798:307;;;:::o;2111:102::-;2152:6;2203:2;2199:7;2194:2;2187:5;2183:14;2179:28;2169:38;;2111:102;;;:::o;2219:364::-;2307:3;2335:39;2368:5;2335:39;:::i;:::-;2390:71;2454:6;2449:3;2390:71;:::i;:::-;2383:78;;2470:52;2515:6;2510:3;2503:4;2496:5;2492:16;2470:52;:::i;:::-;2547:29;2569:6;2547:29;:::i;:::-;2542:3;2538:39;2531:46;;2311:272;2219:364;;;;:::o;2589:313::-;2702:4;2740:2;2729:9;2725:18;2717:26;;2789:9;2783:4;2779:20;2775:1;2764:9;2760:17;2753:47;2817:78;2890:4;2881:6;2817:78;:::i;:::-;2809:86;;2589:313;;;;:::o;2908:77::-;2945:7;2974:5;2963:16;;2908:77;;;:::o;2991:122::-;3064:24;3082:5;3064:24;:::i;:::-;3057:5;3054:35;3044:63;;3103:1;3100;3093:12;3044:63;2991:122;:::o;3119:139::-;3165:5;3203:6;3190:20;3181:29;;3219:33;3246:5;3219:33;:::i;:::-;3119:139;;;;:::o;3264:329::-;3323:6;3372:2;3360:9;3351:7;3347:23;3343:32;3340:119;;;3378:79;;:::i;:::-;3340:119;3498:1;3523:53;3568:7;3559:6;3548:9;3544:22;3523:53;:::i;:::-;3513:63;;3469:117;3264:329;;;;:::o;3599:126::-;3636:7;3676:42;3669:5;3665:54;3654:65;;3599:126;;;:::o;3731:96::-;3768:7;3797:24;3815:5;3797:24;:::i;:::-;3786:35;;3731:96;;;:::o;3833:118::-;3920:24;3938:5;3920:24;:::i;:::-;3915:3;3908:37;3833:118;;:::o;3957:222::-;4050:4;4088:2;4077:9;4073:18;4065:26;;4101:71;4169:1;4158:9;4154:17;4145:6;4101:71;:::i;:::-;3957:222;;;;:::o;4185:122::-;4258:24;4276:5;4258:24;:::i;:::-;4251:5;4248:35;4238:63;;4297:1;4294;4287:12;4238:63;4185:122;:::o;4313:139::-;4359:5;4397:6;4384:20;4375:29;;4413:33;4440:5;4413:33;:::i;:::-;4313:139;;;;:::o;4458:474::-;4526:6;4534;4583:2;4571:9;4562:7;4558:23;4554:32;4551:119;;;4589:79;;:::i;:::-;4551:119;4709:1;4734:53;4779:7;4770:6;4759:9;4755:22;4734:53;:::i;:::-;4724:63;;4680:117;4836:2;4862:53;4907:7;4898:6;4887:9;4883:22;4862:53;:::i;:::-;4852:63;;4807:118;4458:474;;;;;:::o;4938:117::-;5047:1;5044;5037:12;5061:180;5109:77;5106:1;5099:88;5206:4;5203:1;5196:15;5230:4;5227:1;5220:15;5247:281;5330:27;5352:4;5330:27;:::i;:::-;5322:6;5318:40;5460:6;5448:10;5445:22;5424:18;5412:10;5409:34;5406:62;5403:88;;;5471:18;;:::i;:::-;5403:88;5511:10;5507:2;5500:22;5290:238;5247:281;;:::o;5534:129::-;5568:6;5595:20;;:::i;:::-;5585:30;;5624:33;5652:4;5644:6;5624:33;:::i;:::-;5534:129;;;:::o;5669:311::-;5746:4;5836:18;5828:6;5825:30;5822:56;;;5858:18;;:::i;:::-;5822:56;5908:4;5900:6;5896:17;5888:25;;5968:4;5962;5958:15;5950:23;;5669:311;;;:::o;5986:117::-;6095:1;6092;6085:12;6126:710;6222:5;6247:81;6263:64;6320:6;6263:64;:::i;:::-;6247:81;:::i;:::-;6238:90;;6348:5;6377:6;6370:5;6363:21;6411:4;6404:5;6400:16;6393:23;;6464:4;6456:6;6452:17;6444:6;6440:30;6493:3;6485:6;6482:15;6479:122;;;6512:79;;:::i;:::-;6479:122;6627:6;6610:220;6644:6;6639:3;6636:15;6610:220;;;6719:3;6748:37;6781:3;6769:10;6748:37;:::i;:::-;6743:3;6736:50;6815:4;6810:3;6806:14;6799:21;;6686:144;6670:4;6665:3;6661:14;6654:21;;6610:220;;;6614:21;6228:608;;6126:710;;;;;:::o;6859:370::-;6930:5;6979:3;6972:4;6964:6;6960:17;6956:27;6946:122;;6987:79;;:::i;:::-;6946:122;7104:6;7091:20;7129:94;7219:3;7211:6;7204:4;7196:6;7192:17;7129:94;:::i;:::-;7120:103;;6936:293;6859:370;;;;:::o;7235:321::-;7322:4;7412:18;7404:6;7401:30;7398:56;;;7434:18;;:::i;:::-;7398:56;7484:4;7476:6;7472:17;7464:25;;7544:4;7538;7534:15;7526:23;;7235:321;;;:::o;7562:117::-;7671:1;7668;7661:12;7685:308;7747:4;7837:18;7829:6;7826:30;7823:56;;;7859:18;;:::i;:::-;7823:56;7897:29;7919:6;7897:29;:::i;:::-;7889:37;;7981:4;7975;7971:15;7963:23;;7685:308;;;:::o;7999:154::-;8083:6;8078:3;8073;8060:30;8145:1;8136:6;8131:3;8127:16;8120:27;7999:154;;;:::o;8159:412::-;8237:5;8262:66;8278:49;8320:6;8278:49;:::i;:::-;8262:66;:::i;:::-;8253:75;;8351:6;8344:5;8337:21;8389:4;8382:5;8378:16;8427:3;8418:6;8413:3;8409:16;8406:25;8403:112;;;8434:79;;:::i;:::-;8403:112;8524:41;8558:6;8553:3;8548;8524:41;:::i;:::-;8243:328;8159:412;;;;;:::o;8591:340::-;8647:5;8696:3;8689:4;8681:6;8677:17;8673:27;8663:122;;8704:79;;:::i;:::-;8663:122;8821:6;8808:20;8846:79;8921:3;8913:6;8906:4;8898:6;8894:17;8846:79;:::i;:::-;8837:88;;8653:278;8591:340;;;;:::o;8953:945::-;9059:5;9084:91;9100:74;9167:6;9100:74;:::i;:::-;9084:91;:::i;:::-;9075:100;;9195:5;9224:6;9217:5;9210:21;9258:4;9251:5;9247:16;9240:23;;9311:4;9303:6;9299:17;9291:6;9287:30;9340:3;9332:6;9329:15;9326:122;;;9359:79;;:::i;:::-;9326:122;9474:6;9457:435;9491:6;9486:3;9483:15;9457:435;;;9580:3;9567:17;9616:18;9603:11;9600:35;9597:122;;;9638:79;;:::i;:::-;9597:122;9762:11;9754:6;9750:24;9800:47;9843:3;9831:10;9800:47;:::i;:::-;9795:3;9788:60;9877:4;9872:3;9868:14;9861:21;;9533:359;;9517:4;9512:3;9508:14;9501:21;;9457:435;;;9461:21;9065:833;;8953:945;;;;;:::o;9920:390::-;10001:5;10050:3;10043:4;10035:6;10031:17;10027:27;10017:122;;10058:79;;:::i;:::-;10017:122;10175:6;10162:20;10200:104;10300:3;10292:6;10285:4;10277:6;10273:17;10200:104;:::i;:::-;10191:113;;10007:303;9920:390;;;;:::o;10316:914::-;10444:6;10452;10501:2;10489:9;10480:7;10476:23;10472:32;10469:119;;;10507:79;;:::i;:::-;10469:119;10655:1;10644:9;10640:17;10627:31;10685:18;10677:6;10674:30;10671:117;;;10707:79;;:::i;:::-;10671:117;10812:78;10882:7;10873:6;10862:9;10858:22;10812:78;:::i;:::-;10802:88;;10598:302;10967:2;10956:9;10952:18;10939:32;10998:18;10990:6;10987:30;10984:117;;;11020:79;;:::i;:::-;10984:117;11125:88;11205:7;11196:6;11185:9;11181:22;11125:88;:::i;:::-;11115:98;;10910:313;10316:914;;;;;:::o;11236:654::-;11314:6;11322;11371:2;11359:9;11350:7;11346:23;11342:32;11339:119;;;11377:79;;:::i;:::-;11339:119;11497:1;11522:53;11567:7;11558:6;11547:9;11543:22;11522:53;:::i;:::-;11512:63;;11468:117;11652:2;11641:9;11637:18;11624:32;11683:18;11675:6;11672:30;11669:117;;;11705:79;;:::i;:::-;11669:117;11810:63;11865:7;11856:6;11845:9;11841:22;11810:63;:::i;:::-;11800:73;;11595:288;11236:654;;;;;:::o;11896:619::-;11973:6;11981;11989;12038:2;12026:9;12017:7;12013:23;12009:32;12006:119;;;12044:79;;:::i;:::-;12006:119;12164:1;12189:53;12234:7;12225:6;12214:9;12210:22;12189:53;:::i;:::-;12179:63;;12135:117;12291:2;12317:53;12362:7;12353:6;12342:9;12338:22;12317:53;:::i;:::-;12307:63;;12262:118;12419:2;12445:53;12490:7;12481:6;12470:9;12466:22;12445:53;:::i;:::-;12435:63;;12390:118;11896:619;;;;;:::o;12521:77::-;12558:7;12587:5;12576:16;;12521:77;;;:::o;12604:122::-;12677:24;12695:5;12677:24;:::i;:::-;12670:5;12667:35;12657:63;;12716:1;12713;12706:12;12657:63;12604:122;:::o;12732:139::-;12778:5;12816:6;12803:20;12794:29;;12832:33;12859:5;12832:33;:::i;:::-;12732:139;;;;:::o;12877:329::-;12936:6;12985:2;12973:9;12964:7;12960:23;12956:32;12953:119;;;12991:79;;:::i;:::-;12953:119;13111:1;13136:53;13181:7;13172:6;13161:9;13157:22;13136:53;:::i;:::-;13126:63;;13082:117;12877:329;;;;:::o;13212:118::-;13299:24;13317:5;13299:24;:::i;:::-;13294:3;13287:37;13212:118;;:::o;13336:222::-;13429:4;13467:2;13456:9;13452:18;13444:26;;13480:71;13548:1;13537:9;13533:17;13524:6;13480:71;:::i;:::-;13336:222;;;;:::o;13564:474::-;13632:6;13640;13689:2;13677:9;13668:7;13664:23;13660:32;13657:119;;;13695:79;;:::i;:::-;13657:119;13815:1;13840:53;13885:7;13876:6;13865:9;13861:22;13840:53;:::i;:::-;13830:63;;13786:117;13942:2;13968:53;14013:7;14004:6;13993:9;13989:22;13968:53;:::i;:::-;13958:63;;13913:118;13564:474;;;;;:::o;14044:329::-;14103:6;14152:2;14140:9;14131:7;14127:23;14123:32;14120:119;;;14158:79;;:::i;:::-;14120:119;14278:1;14303:53;14348:7;14339:6;14328:9;14324:22;14303:53;:::i;:::-;14293:63;;14249:117;14044:329;;;;:::o;14379:118::-;14466:24;14484:5;14466:24;:::i;:::-;14461:3;14454:37;14379:118;;:::o;14503:222::-;14596:4;14634:2;14623:9;14619:18;14611:26;;14647:71;14715:1;14704:9;14700:17;14691:6;14647:71;:::i;:::-;14503:222;;;;:::o;14731:116::-;14801:21;14816:5;14801:21;:::i;:::-;14794:5;14791:32;14781:60;;14837:1;14834;14827:12;14781:60;14731:116;:::o;14853:133::-;14896:5;14934:6;14921:20;14912:29;;14950:30;14974:5;14950:30;:::i;:::-;14853:133;;;;:::o;14992:468::-;15057:6;15065;15114:2;15102:9;15093:7;15089:23;15085:32;15082:119;;;15120:79;;:::i;:::-;15082:119;15240:1;15265:53;15310:7;15301:6;15290:9;15286:22;15265:53;:::i;:::-;15255:63;;15211:117;15367:2;15393:50;15435:7;15426:6;15415:9;15411:22;15393:50;:::i;:::-;15383:60;;15338:115;14992:468;;;;;:::o;15466:307::-;15527:4;15617:18;15609:6;15606:30;15603:56;;;15639:18;;:::i;:::-;15603:56;15677:29;15699:6;15677:29;:::i;:::-;15669:37;;15761:4;15755;15751:15;15743:23;;15466:307;;;:::o;15779:410::-;15856:5;15881:65;15897:48;15938:6;15897:48;:::i;:::-;15881:65;:::i;:::-;15872:74;;15969:6;15962:5;15955:21;16007:4;16000:5;15996:16;16045:3;16036:6;16031:3;16027:16;16024:25;16021:112;;;16052:79;;:::i;:::-;16021:112;16142:41;16176:6;16171:3;16166;16142:41;:::i;:::-;15862:327;15779:410;;;;;:::o;16208:338::-;16263:5;16312:3;16305:4;16297:6;16293:17;16289:27;16279:122;;16320:79;;:::i;:::-;16279:122;16437:6;16424:20;16462:78;16536:3;16528:6;16521:4;16513:6;16509:17;16462:78;:::i;:::-;16453:87;;16269:277;16208:338;;;;:::o;16552:943::-;16647:6;16655;16663;16671;16720:3;16708:9;16699:7;16695:23;16691:33;16688:120;;;16727:79;;:::i;:::-;16688:120;16847:1;16872:53;16917:7;16908:6;16897:9;16893:22;16872:53;:::i;:::-;16862:63;;16818:117;16974:2;17000:53;17045:7;17036:6;17025:9;17021:22;17000:53;:::i;:::-;16990:63;;16945:118;17102:2;17128:53;17173:7;17164:6;17153:9;17149:22;17128:53;:::i;:::-;17118:63;;17073:118;17258:2;17247:9;17243:18;17230:32;17289:18;17281:6;17278:30;17275:117;;;17311:79;;:::i;:::-;17275:117;17416:62;17470:7;17461:6;17450:9;17446:22;17416:62;:::i;:::-;17406:72;;17201:287;16552:943;;;;;;;:::o;17501:654::-;17579:6;17587;17636:2;17624:9;17615:7;17611:23;17607:32;17604:119;;;17642:79;;:::i;:::-;17604:119;17762:1;17787:53;17832:7;17823:6;17812:9;17808:22;17787:53;:::i;:::-;17777:63;;17733:117;17917:2;17906:9;17902:18;17889:32;17948:18;17940:6;17937:30;17934:117;;;17970:79;;:::i;:::-;17934:117;18075:63;18130:7;18121:6;18110:9;18106:22;18075:63;:::i;:::-;18065:73;;17860:288;17501:654;;;;;:::o;18161:474::-;18229:6;18237;18286:2;18274:9;18265:7;18261:23;18257:32;18254:119;;;18292:79;;:::i;:::-;18254:119;18412:1;18437:53;18482:7;18473:6;18462:9;18458:22;18437:53;:::i;:::-;18427:63;;18383:117;18539:2;18565:53;18610:7;18601:6;18590:9;18586:22;18565:53;:::i;:::-;18555:63;;18510:118;18161:474;;;;;:::o;18641:180::-;18689:77;18686:1;18679:88;18786:4;18783:1;18776:15;18810:4;18807:1;18800:15;18827:320;18871:6;18908:1;18902:4;18898:12;18888:22;;18955:1;18949:4;18945:12;18976:18;18966:81;;19032:4;19024:6;19020:17;19010:27;;18966:81;19094:2;19086:6;19083:14;19063:18;19060:38;19057:84;;19113:18;;:::i;:::-;19057:84;18878:269;18827:320;;;:::o;19153:220::-;19293:34;19289:1;19281:6;19277:14;19270:58;19362:3;19357:2;19349:6;19345:15;19338:28;19153:220;:::o;19379:366::-;19521:3;19542:67;19606:2;19601:3;19542:67;:::i;:::-;19535:74;;19618:93;19707:3;19618:93;:::i;:::-;19736:2;19731:3;19727:12;19720:19;;19379:366;;;:::o;19751:419::-;19917:4;19955:2;19944:9;19940:18;19932:26;;20004:9;19998:4;19994:20;19990:1;19979:9;19975:17;19968:47;20032:131;20158:4;20032:131;:::i;:::-;20024:139;;19751:419;;;:::o;20176:248::-;20316:34;20312:1;20304:6;20300:14;20293:58;20385:31;20380:2;20372:6;20368:15;20361:56;20176:248;:::o;20430:366::-;20572:3;20593:67;20657:2;20652:3;20593:67;:::i;:::-;20586:74;;20669:93;20758:3;20669:93;:::i;:::-;20787:2;20782:3;20778:12;20771:19;;20430:366;;;:::o;20802:419::-;20968:4;21006:2;20995:9;20991:18;20983:26;;21055:9;21049:4;21045:20;21041:1;21030:9;21026:17;21019:47;21083:131;21209:4;21083:131;:::i;:::-;21075:139;;20802:419;;;:::o;21227:180::-;21275:77;21272:1;21265:88;21372:4;21369:1;21362:15;21396:4;21393:1;21386:15;21413:180;21461:77;21458:1;21451:88;21558:4;21555:1;21548:15;21582:4;21579:1;21572:15;21599:305;21639:3;21658:20;21676:1;21658:20;:::i;:::-;21653:25;;21692:20;21710:1;21692:20;:::i;:::-;21687:25;;21846:1;21778:66;21774:74;21771:1;21768:81;21765:107;;;21852:18;;:::i;:::-;21765:107;21896:1;21893;21889:9;21882:16;;21599:305;;;;:::o;21910:233::-;21949:3;21972:24;21990:5;21972:24;:::i;:::-;21963:33;;22018:66;22011:5;22008:77;22005:103;;22088:18;;:::i;:::-;22005:103;22135:1;22128:5;22124:13;22117:20;;21910:233;;;:::o;22149:232::-;22289:34;22285:1;22277:6;22273:14;22266:58;22358:15;22353:2;22345:6;22341:15;22334:40;22149:232;:::o;22387:366::-;22529:3;22550:67;22614:2;22609:3;22550:67;:::i;:::-;22543:74;;22626:93;22715:3;22626:93;:::i;:::-;22744:2;22739:3;22735:12;22728:19;;22387:366;;;:::o;22759:419::-;22925:4;22963:2;22952:9;22948:18;22940:26;;23012:9;23006:4;23002:20;22998:1;22987:9;22983:17;22976:47;23040:131;23166:4;23040:131;:::i;:::-;23032:139;;22759:419;;;:::o;23184:234::-;23324:34;23320:1;23312:6;23308:14;23301:58;23393:17;23388:2;23380:6;23376:15;23369:42;23184:234;:::o;23424:366::-;23566:3;23587:67;23651:2;23646:3;23587:67;:::i;:::-;23580:74;;23663:93;23752:3;23663:93;:::i;:::-;23781:2;23776:3;23772:12;23765:19;;23424:366;;;:::o;23796:419::-;23962:4;24000:2;23989:9;23985:18;23977:26;;24049:9;24043:4;24039:20;24035:1;24024:9;24020:17;24013:47;24077:131;24203:4;24077:131;:::i;:::-;24069:139;;23796:419;;;:::o;24221:174::-;24361:26;24357:1;24349:6;24345:14;24338:50;24221:174;:::o;24401:366::-;24543:3;24564:67;24628:2;24623:3;24564:67;:::i;:::-;24557:74;;24640:93;24729:3;24640:93;:::i;:::-;24758:2;24753:3;24749:12;24742:19;;24401:366;;;:::o;24773:419::-;24939:4;24977:2;24966:9;24962:18;24954:26;;25026:9;25020:4;25016:20;25012:1;25001:9;24997:17;24990:47;25054:131;25180:4;25054:131;:::i;:::-;25046:139;;24773:419;;;:::o;25198:228::-;25338:34;25334:1;25326:6;25322:14;25315:58;25407:11;25402:2;25394:6;25390:15;25383:36;25198:228;:::o;25432:366::-;25574:3;25595:67;25659:2;25654:3;25595:67;:::i;:::-;25588:74;;25671:93;25760:3;25671:93;:::i;:::-;25789:2;25784:3;25780:12;25773:19;;25432:366;;;:::o;25804:419::-;25970:4;26008:2;25997:9;25993:18;25985:26;;26057:9;26051:4;26047:20;26043:1;26032:9;26028:17;26021:47;26085:131;26211:4;26085:131;:::i;:::-;26077:139;;25804:419;;;:::o;26229:233::-;26369:34;26365:1;26357:6;26353:14;26346:58;26438:16;26433:2;26425:6;26421:15;26414:41;26229:233;:::o;26468:366::-;26610:3;26631:67;26695:2;26690:3;26631:67;:::i;:::-;26624:74;;26707:93;26796:3;26707:93;:::i;:::-;26825:2;26820:3;26816:12;26809:19;;26468:366;;;:::o;26840:419::-;27006:4;27044:2;27033:9;27029:18;27021:26;;27093:9;27087:4;27083:20;27079:1;27068:9;27064:17;27057:47;27121:131;27247:4;27121:131;:::i;:::-;27113:139;;26840:419;;;:::o;27265:141::-;27314:4;27337:3;27329:11;;27360:3;27357:1;27350:14;27394:4;27391:1;27381:18;27373:26;;27265:141;;;:::o;27412:93::-;27449:6;27496:2;27491;27484:5;27480:14;27476:23;27466:33;;27412:93;;;:::o;27511:107::-;27555:8;27605:5;27599:4;27595:16;27574:37;;27511:107;;;;:::o;27624:393::-;27693:6;27743:1;27731:10;27727:18;27766:97;27796:66;27785:9;27766:97;:::i;:::-;27884:39;27914:8;27903:9;27884:39;:::i;:::-;27872:51;;27956:4;27952:9;27945:5;27941:21;27932:30;;28005:4;27995:8;27991:19;27984:5;27981:30;27971:40;;27700:317;;27624:393;;;;;:::o;28023:60::-;28051:3;28072:5;28065:12;;28023:60;;;:::o;28089:142::-;28139:9;28172:53;28190:34;28199:24;28217:5;28199:24;:::i;:::-;28190:34;:::i;:::-;28172:53;:::i;:::-;28159:66;;28089:142;;;:::o;28237:75::-;28280:3;28301:5;28294:12;;28237:75;;;:::o;28318:269::-;28428:39;28459:7;28428:39;:::i;:::-;28489:91;28538:41;28562:16;28538:41;:::i;:::-;28530:6;28523:4;28517:11;28489:91;:::i;:::-;28483:4;28476:105;28394:193;28318:269;;;:::o;28593:73::-;28638:3;28593:73;:::o;28672:189::-;28749:32;;:::i;:::-;28790:65;28848:6;28840;28834:4;28790:65;:::i;:::-;28725:136;28672:189;;:::o;28867:186::-;28927:120;28944:3;28937:5;28934:14;28927:120;;;28998:39;29035:1;29028:5;28998:39;:::i;:::-;28971:1;28964:5;28960:13;28951:22;;28927:120;;;28867:186;;:::o;29059:543::-;29160:2;29155:3;29152:11;29149:446;;;29194:38;29226:5;29194:38;:::i;:::-;29278:29;29296:10;29278:29;:::i;:::-;29268:8;29264:44;29461:2;29449:10;29446:18;29443:49;;;29482:8;29467:23;;29443:49;29505:80;29561:22;29579:3;29561:22;:::i;:::-;29551:8;29547:37;29534:11;29505:80;:::i;:::-;29164:431;;29149:446;29059:543;;;:::o;29608:117::-;29662:8;29712:5;29706:4;29702:16;29681:37;;29608:117;;;;:::o;29731:169::-;29775:6;29808:51;29856:1;29852:6;29844:5;29841:1;29837:13;29808:51;:::i;:::-;29804:56;29889:4;29883;29879:15;29869:25;;29782:118;29731:169;;;;:::o;29905:295::-;29981:4;30127:29;30152:3;30146:4;30127:29;:::i;:::-;30119:37;;30189:3;30186:1;30182:11;30176:4;30173:21;30165:29;;29905:295;;;;:::o;30205:1395::-;30322:37;30355:3;30322:37;:::i;:::-;30424:18;30416:6;30413:30;30410:56;;;30446:18;;:::i;:::-;30410:56;30490:38;30522:4;30516:11;30490:38;:::i;:::-;30575:67;30635:6;30627;30621:4;30575:67;:::i;:::-;30669:1;30693:4;30680:17;;30725:2;30717:6;30714:14;30742:1;30737:618;;;;31399:1;31416:6;31413:77;;;31465:9;31460:3;31456:19;31450:26;31441:35;;31413:77;31516:67;31576:6;31569:5;31516:67;:::i;:::-;31510:4;31503:81;31372:222;30707:887;;30737:618;30789:4;30785:9;30777:6;30773:22;30823:37;30855:4;30823:37;:::i;:::-;30882:1;30896:208;30910:7;30907:1;30904:14;30896:208;;;30989:9;30984:3;30980:19;30974:26;30966:6;30959:42;31040:1;31032:6;31028:14;31018:24;;31087:2;31076:9;31072:18;31059:31;;30933:4;30930:1;30926:12;30921:17;;30896:208;;;31132:6;31123:7;31120:19;31117:179;;;31190:9;31185:3;31181:19;31175:26;31233:48;31275:4;31267:6;31263:17;31252:9;31233:48;:::i;:::-;31225:6;31218:64;31140:156;31117:179;31342:1;31338;31330:6;31326:14;31322:22;31316:4;31309:36;30744:611;;;30707:887;;30297:1303;;;30205:1395;;:::o;31606:224::-;31746:34;31742:1;31734:6;31730:14;31723:58;31815:7;31810:2;31802:6;31798:15;31791:32;31606:224;:::o;31836:366::-;31978:3;31999:67;32063:2;32058:3;31999:67;:::i;:::-;31992:74;;32075:93;32164:3;32075:93;:::i;:::-;32193:2;32188:3;32184:12;32177:19;;31836:366;;;:::o;32208:419::-;32374:4;32412:2;32401:9;32397:18;32389:26;;32461:9;32455:4;32451:20;32447:1;32436:9;32432:17;32425:47;32489:131;32615:4;32489:131;:::i;:::-;32481:139;;32208:419;;;:::o;32633:223::-;32773:34;32769:1;32761:6;32757:14;32750:58;32842:6;32837:2;32829:6;32825:15;32818:31;32633:223;:::o;32862:366::-;33004:3;33025:67;33089:2;33084:3;33025:67;:::i;:::-;33018:74;;33101:93;33190:3;33101:93;:::i;:::-;33219:2;33214:3;33210:12;33203:19;;32862:366;;;:::o;33234:419::-;33400:4;33438:2;33427:9;33423:18;33415:26;;33487:9;33481:4;33477:20;33473:1;33462:9;33458:17;33451:47;33515:131;33641:4;33515:131;:::i;:::-;33507:139;;33234:419;;;:::o;33659:175::-;33799:27;33795:1;33787:6;33783:14;33776:51;33659:175;:::o;33840:366::-;33982:3;34003:67;34067:2;34062:3;34003:67;:::i;:::-;33996:74;;34079:93;34168:3;34079:93;:::i;:::-;34197:2;34192:3;34188:12;34181:19;;33840:366;;;:::o;34212:419::-;34378:4;34416:2;34405:9;34401:18;34393:26;;34465:9;34459:4;34455:20;34451:1;34440:9;34436:17;34429:47;34493:131;34619:4;34493:131;:::i;:::-;34485:139;;34212:419;;;:::o;34637:237::-;34777:34;34773:1;34765:6;34761:14;34754:58;34846:20;34841:2;34833:6;34829:15;34822:45;34637:237;:::o;34880:366::-;35022:3;35043:67;35107:2;35102:3;35043:67;:::i;:::-;35036:74;;35119:93;35208:3;35119:93;:::i;:::-;35237:2;35232:3;35228:12;35221:19;;34880:366;;;:::o;35252:419::-;35418:4;35456:2;35445:9;35441:18;35433:26;;35505:9;35499:4;35495:20;35491:1;35480:9;35476:17;35469:47;35533:131;35659:4;35533:131;:::i;:::-;35525:139;;35252:419;;;:::o;35677:148::-;35779:11;35816:3;35801:18;;35677:148;;;;:::o;35831:377::-;35937:3;35965:39;35998:5;35965:39;:::i;:::-;36020:89;36102:6;36097:3;36020:89;:::i;:::-;36013:96;;36118:52;36163:6;36158:3;36151:4;36144:5;36140:16;36118:52;:::i;:::-;36195:6;36190:3;36186:16;36179:23;;35941:267;35831:377;;;;:::o;36214:435::-;36394:3;36416:95;36507:3;36498:6;36416:95;:::i;:::-;36409:102;;36528:95;36619:3;36610:6;36528:95;:::i;:::-;36521:102;;36640:3;36633:10;;36214:435;;;;;:::o;36655:173::-;36795:25;36791:1;36783:6;36779:14;36772:49;36655:173;:::o;36834:402::-;36994:3;37015:85;37097:2;37092:3;37015:85;:::i;:::-;37008:92;;37109:93;37198:3;37109:93;:::i;:::-;37227:2;37222:3;37218:12;37211:19;;36834:402;;;:::o;37242:167::-;37382:19;37378:1;37370:6;37366:14;37359:43;37242:167;:::o;37415:402::-;37575:3;37596:85;37678:2;37673:3;37596:85;:::i;:::-;37589:92;;37690:93;37779:3;37690:93;:::i;:::-;37808:2;37803:3;37799:12;37792:19;;37415:402;;;:::o;37823:967::-;38205:3;38227:148;38371:3;38227:148;:::i;:::-;38220:155;;38392:95;38483:3;38474:6;38392:95;:::i;:::-;38385:102;;38504:148;38648:3;38504:148;:::i;:::-;38497:155;;38669:95;38760:3;38751:6;38669:95;:::i;:::-;38662:102;;38781:3;38774:10;;37823:967;;;;;:::o;38796:170::-;38936:22;38932:1;38924:6;38920:14;38913:46;38796:170;:::o;38972:366::-;39114:3;39135:67;39199:2;39194:3;39135:67;:::i;:::-;39128:74;;39211:93;39300:3;39211:93;:::i;:::-;39329:2;39324:3;39320:12;39313:19;;38972:366;;;:::o;39344:419::-;39510:4;39548:2;39537:9;39533:18;39525:26;;39597:9;39591:4;39587:20;39583:1;39572:9;39568:17;39561:47;39625:131;39751:4;39625:131;:::i;:::-;39617:139;;39344:419;;;:::o;39769:166::-;39909:18;39905:1;39897:6;39893:14;39886:42;39769:166;:::o;39941:366::-;40083:3;40104:67;40168:2;40163:3;40104:67;:::i;:::-;40097:74;;40180:93;40269:3;40180:93;:::i;:::-;40298:2;40293:3;40289:12;40282:19;;39941:366;;;:::o;40313:419::-;40479:4;40517:2;40506:9;40502:18;40494:26;;40566:9;40560:4;40556:20;40552:1;40541:9;40537:17;40530:47;40594:131;40720:4;40594:131;:::i;:::-;40586:139;;40313:419;;;:::o;40738:98::-;40789:6;40823:5;40817:12;40807:22;;40738:98;;;:::o;40842:168::-;40925:11;40959:6;40954:3;40947:19;40999:4;40994:3;40990:14;40975:29;;40842:168;;;;:::o;41016:360::-;41102:3;41130:38;41162:5;41130:38;:::i;:::-;41184:70;41247:6;41242:3;41184:70;:::i;:::-;41177:77;;41263:52;41308:6;41303:3;41296:4;41289:5;41285:16;41263:52;:::i;:::-;41340:29;41362:6;41340:29;:::i;:::-;41335:3;41331:39;41324:46;;41106:270;41016:360;;;;:::o;41382:640::-;41577:4;41615:3;41604:9;41600:19;41592:27;;41629:71;41697:1;41686:9;41682:17;41673:6;41629:71;:::i;:::-;41710:72;41778:2;41767:9;41763:18;41754:6;41710:72;:::i;:::-;41792;41860:2;41849:9;41845:18;41836:6;41792:72;:::i;:::-;41911:9;41905:4;41901:20;41896:2;41885:9;41881:18;41874:48;41939:76;42010:4;42001:6;41939:76;:::i;:::-;41931:84;;41382:640;;;;;;;:::o;42028:141::-;42084:5;42115:6;42109:13;42100:22;;42131:32;42157:5;42131:32;:::i;:::-;42028:141;;;;:::o;42175:349::-;42244:6;42293:2;42281:9;42272:7;42268:23;42264:32;42261:119;;;42299:79;;:::i;:::-;42261:119;42419:1;42444:63;42499:7;42490:6;42479:9;42475:22;42444:63;:::i;:::-;42434:73;;42390:127;42175:349;;;;:::o;42530:348::-;42570:7;42593:20;42611:1;42593:20;:::i;:::-;42588:25;;42627:20;42645:1;42627:20;:::i;:::-;42622:25;;42815:1;42747:66;42743:74;42740:1;42737:81;42732:1;42725:9;42718:17;42714:105;42711:131;;;42822:18;;:::i;:::-;42711:131;42870:1;42867;42863:9;42852:20;;42530:348;;;;:::o;42884:171::-;42923:3;42946:24;42964:5;42946:24;:::i;:::-;42937:33;;42992:4;42985:5;42982:15;42979:41;;43000:18;;:::i;:::-;42979:41;43047:1;43040:5;43036:13;43029:20;;42884:171;;;:::o;43061:182::-;43201:34;43197:1;43189:6;43185:14;43178:58;43061:182;:::o;43249:366::-;43391:3;43412:67;43476:2;43471:3;43412:67;:::i;:::-;43405:74;;43488:93;43577:3;43488:93;:::i;:::-;43606:2;43601:3;43597:12;43590:19;;43249:366;;;:::o;43621:419::-;43787:4;43825:2;43814:9;43810:18;43802:26;;43874:9;43868:4;43864:20;43860:1;43849:9;43845:17;43838:47;43902:131;44028:4;43902:131;:::i;:::-;43894:139;;43621:419;;;:::o;44046:182::-;44186:34;44182:1;44174:6;44170:14;44163:58;44046:182;:::o;44234:366::-;44376:3;44397:67;44461:2;44456:3;44397:67;:::i;:::-;44390:74;;44473:93;44562:3;44473:93;:::i;:::-;44591:2;44586:3;44582:12;44575:19;;44234:366;;;:::o;44606:419::-;44772:4;44810:2;44799:9;44795:18;44787:26;;44859:9;44853:4;44849:20;44845:1;44834:9;44830:17;44823:47;44887:131;45013:4;44887:131;:::i;:::-;44879:139;;44606:419;;;:::o;45031:178::-;45171:30;45167:1;45159:6;45155:14;45148:54;45031:178;:::o;45215:366::-;45357:3;45378:67;45442:2;45437:3;45378:67;:::i;:::-;45371:74;;45454:93;45543:3;45454:93;:::i;:::-;45572:2;45567:3;45563:12;45556:19;;45215:366;;;:::o;45587:419::-;45753:4;45791:2;45780:9;45776:18;45768:26;;45840:9;45834:4;45830:20;45826:1;45815:9;45811:17;45804:47;45868:131;45994:4;45868:131;:::i;:::-;45860:139;;45587:419;;;:::o;46012:191::-;46052:4;46072:20;46090:1;46072:20;:::i;:::-;46067:25;;46106:20;46124:1;46106:20;:::i;:::-;46101:25;;46145:1;46142;46139:8;46136:34;;;46150:18;;:::i;:::-;46136:34;46195:1;46192;46188:9;46180:17;;46012:191;;;;:::o;46209:180::-;46257:77;46254:1;46247:88;46354:4;46351:1;46344:15;46378:4;46375:1;46368:15

Swarm Source

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