ETH Price: $3,347.57 (+0.69%)

Token

SudoGovernor ()
 

Overview

Max Total Supply

0 SudoGovernor

Holders

0

Total Transfers

-

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 0 Decimals)

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:
SudoGovernor

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

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

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

// OpenZeppelin Contracts (last updated v4.8.0) (governance/Governor.sol)

// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)

/**
 * @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);
}

// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)

// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

/**
 * @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);
}

/**
 * @dev _Available since v3.1._
 */
interface IERC1155Receiver is IERC165 {
    /**
     * @dev Handles the receipt of a single ERC1155 token type. This function is
     * called at the end of a `safeTransferFrom` after the balance has been updated.
     *
     * NOTE: To accept the transfer, this must return
     * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
     * (i.e. 0xf23a6e61, or its own function selector).
     *
     * @param operator The address which initiated the transfer (i.e. msg.sender)
     * @param from The address which previously owned the token
     * @param id The ID of the token being transferred
     * @param value The amount of tokens being transferred
     * @param data Additional data with no specified format
     * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
     */
    function onERC1155Received(
        address operator,
        address from,
        uint256 id,
        uint256 value,
        bytes calldata data
    ) external returns (bytes4);

    /**
     * @dev Handles the receipt of a multiple ERC1155 token types. This function
     * is called at the end of a `safeBatchTransferFrom` after the balances have
     * been updated.
     *
     * NOTE: To accept the transfer(s), this must return
     * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
     * (i.e. 0xbc197c81, or its own function selector).
     *
     * @param operator The address which initiated the batch transfer (i.e. msg.sender)
     * @param from The address which previously owned the token
     * @param ids An array containing ids of each token being transferred (order and length must match values array)
     * @param values An array containing amounts of each token being transferred (order and length must match ids array)
     * @param data Additional data with no specified format
     * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
     */
    function onERC1155BatchReceived(
        address operator,
        address from,
        uint256[] calldata ids,
        uint256[] calldata values,
        bytes calldata data
    ) external returns (bytes4);
}

// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)

// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)

// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)

/**
 * @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);
        }
    }
}

/**
 * @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);
    }
}

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

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

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

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

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

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

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

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

        return (signer, RecoverError.NoError);
    }

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

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

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

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

// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)

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

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

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

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

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

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

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

// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

/**
 * @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;
    }
}

// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.

/**
 * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
 * checks.
 *
 * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
 * easily result in undesired exploitation or bugs, since developers usually
 * assume that overflows raise errors. `SafeCast` restores this intuition by
 * reverting the transaction when such an operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 *
 * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
 * all math on `uint256` and `int256` and then downcasting.
 */
library SafeCast {
    /**
     * @dev Returns the downcasted uint248 from uint256, reverting on
     * overflow (when the input is greater than largest uint248).
     *
     * Counterpart to Solidity's `uint248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     *
     * _Available since v4.7._
     */
    function toUint248(uint256 value) internal pure returns (uint248) {
        require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits");
        return uint248(value);
    }

    /**
     * @dev Returns the downcasted uint240 from uint256, reverting on
     * overflow (when the input is greater than largest uint240).
     *
     * Counterpart to Solidity's `uint240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     *
     * _Available since v4.7._
     */
    function toUint240(uint256 value) internal pure returns (uint240) {
        require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits");
        return uint240(value);
    }

    /**
     * @dev Returns the downcasted uint232 from uint256, reverting on
     * overflow (when the input is greater than largest uint232).
     *
     * Counterpart to Solidity's `uint232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     *
     * _Available since v4.7._
     */
    function toUint232(uint256 value) internal pure returns (uint232) {
        require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits");
        return uint232(value);
    }

    /**
     * @dev Returns the downcasted uint224 from uint256, reverting on
     * overflow (when the input is greater than largest uint224).
     *
     * Counterpart to Solidity's `uint224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     *
     * _Available since v4.2._
     */
    function toUint224(uint256 value) internal pure returns (uint224) {
        require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits");
        return uint224(value);
    }

    /**
     * @dev Returns the downcasted uint216 from uint256, reverting on
     * overflow (when the input is greater than largest uint216).
     *
     * Counterpart to Solidity's `uint216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     *
     * _Available since v4.7._
     */
    function toUint216(uint256 value) internal pure returns (uint216) {
        require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits");
        return uint216(value);
    }

    /**
     * @dev Returns the downcasted uint208 from uint256, reverting on
     * overflow (when the input is greater than largest uint208).
     *
     * Counterpart to Solidity's `uint208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     *
     * _Available since v4.7._
     */
    function toUint208(uint256 value) internal pure returns (uint208) {
        require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits");
        return uint208(value);
    }

    /**
     * @dev Returns the downcasted uint200 from uint256, reverting on
     * overflow (when the input is greater than largest uint200).
     *
     * Counterpart to Solidity's `uint200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     *
     * _Available since v4.7._
     */
    function toUint200(uint256 value) internal pure returns (uint200) {
        require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits");
        return uint200(value);
    }

    /**
     * @dev Returns the downcasted uint192 from uint256, reverting on
     * overflow (when the input is greater than largest uint192).
     *
     * Counterpart to Solidity's `uint192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     *
     * _Available since v4.7._
     */
    function toUint192(uint256 value) internal pure returns (uint192) {
        require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits");
        return uint192(value);
    }

    /**
     * @dev Returns the downcasted uint184 from uint256, reverting on
     * overflow (when the input is greater than largest uint184).
     *
     * Counterpart to Solidity's `uint184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     *
     * _Available since v4.7._
     */
    function toUint184(uint256 value) internal pure returns (uint184) {
        require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits");
        return uint184(value);
    }

    /**
     * @dev Returns the downcasted uint176 from uint256, reverting on
     * overflow (when the input is greater than largest uint176).
     *
     * Counterpart to Solidity's `uint176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     *
     * _Available since v4.7._
     */
    function toUint176(uint256 value) internal pure returns (uint176) {
        require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits");
        return uint176(value);
    }

    /**
     * @dev Returns the downcasted uint168 from uint256, reverting on
     * overflow (when the input is greater than largest uint168).
     *
     * Counterpart to Solidity's `uint168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     *
     * _Available since v4.7._
     */
    function toUint168(uint256 value) internal pure returns (uint168) {
        require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits");
        return uint168(value);
    }

    /**
     * @dev Returns the downcasted uint160 from uint256, reverting on
     * overflow (when the input is greater than largest uint160).
     *
     * Counterpart to Solidity's `uint160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     *
     * _Available since v4.7._
     */
    function toUint160(uint256 value) internal pure returns (uint160) {
        require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits");
        return uint160(value);
    }

    /**
     * @dev Returns the downcasted uint152 from uint256, reverting on
     * overflow (when the input is greater than largest uint152).
     *
     * Counterpart to Solidity's `uint152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     *
     * _Available since v4.7._
     */
    function toUint152(uint256 value) internal pure returns (uint152) {
        require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits");
        return uint152(value);
    }

    /**
     * @dev Returns the downcasted uint144 from uint256, reverting on
     * overflow (when the input is greater than largest uint144).
     *
     * Counterpart to Solidity's `uint144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     *
     * _Available since v4.7._
     */
    function toUint144(uint256 value) internal pure returns (uint144) {
        require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits");
        return uint144(value);
    }

    /**
     * @dev Returns the downcasted uint136 from uint256, reverting on
     * overflow (when the input is greater than largest uint136).
     *
     * Counterpart to Solidity's `uint136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     *
     * _Available since v4.7._
     */
    function toUint136(uint256 value) internal pure returns (uint136) {
        require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits");
        return uint136(value);
    }

    /**
     * @dev Returns the downcasted uint128 from uint256, reverting on
     * overflow (when the input is greater than largest uint128).
     *
     * Counterpart to Solidity's `uint128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     *
     * _Available since v2.5._
     */
    function toUint128(uint256 value) internal pure returns (uint128) {
        require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits");
        return uint128(value);
    }

    /**
     * @dev Returns the downcasted uint120 from uint256, reverting on
     * overflow (when the input is greater than largest uint120).
     *
     * Counterpart to Solidity's `uint120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     *
     * _Available since v4.7._
     */
    function toUint120(uint256 value) internal pure returns (uint120) {
        require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits");
        return uint120(value);
    }

    /**
     * @dev Returns the downcasted uint112 from uint256, reverting on
     * overflow (when the input is greater than largest uint112).
     *
     * Counterpart to Solidity's `uint112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     *
     * _Available since v4.7._
     */
    function toUint112(uint256 value) internal pure returns (uint112) {
        require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits");
        return uint112(value);
    }

    /**
     * @dev Returns the downcasted uint104 from uint256, reverting on
     * overflow (when the input is greater than largest uint104).
     *
     * Counterpart to Solidity's `uint104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     *
     * _Available since v4.7._
     */
    function toUint104(uint256 value) internal pure returns (uint104) {
        require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits");
        return uint104(value);
    }

    /**
     * @dev Returns the downcasted uint96 from uint256, reverting on
     * overflow (when the input is greater than largest uint96).
     *
     * Counterpart to Solidity's `uint96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     *
     * _Available since v4.2._
     */
    function toUint96(uint256 value) internal pure returns (uint96) {
        require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits");
        return uint96(value);
    }

    /**
     * @dev Returns the downcasted uint88 from uint256, reverting on
     * overflow (when the input is greater than largest uint88).
     *
     * Counterpart to Solidity's `uint88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     *
     * _Available since v4.7._
     */
    function toUint88(uint256 value) internal pure returns (uint88) {
        require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits");
        return uint88(value);
    }

    /**
     * @dev Returns the downcasted uint80 from uint256, reverting on
     * overflow (when the input is greater than largest uint80).
     *
     * Counterpart to Solidity's `uint80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     *
     * _Available since v4.7._
     */
    function toUint80(uint256 value) internal pure returns (uint80) {
        require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits");
        return uint80(value);
    }

    /**
     * @dev Returns the downcasted uint72 from uint256, reverting on
     * overflow (when the input is greater than largest uint72).
     *
     * Counterpart to Solidity's `uint72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     *
     * _Available since v4.7._
     */
    function toUint72(uint256 value) internal pure returns (uint72) {
        require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits");
        return uint72(value);
    }

    /**
     * @dev Returns the downcasted uint64 from uint256, reverting on
     * overflow (when the input is greater than largest uint64).
     *
     * Counterpart to Solidity's `uint64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     *
     * _Available since v2.5._
     */
    function toUint64(uint256 value) internal pure returns (uint64) {
        require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits");
        return uint64(value);
    }

    /**
     * @dev Returns the downcasted uint56 from uint256, reverting on
     * overflow (when the input is greater than largest uint56).
     *
     * Counterpart to Solidity's `uint56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     *
     * _Available since v4.7._
     */
    function toUint56(uint256 value) internal pure returns (uint56) {
        require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits");
        return uint56(value);
    }

    /**
     * @dev Returns the downcasted uint48 from uint256, reverting on
     * overflow (when the input is greater than largest uint48).
     *
     * Counterpart to Solidity's `uint48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     *
     * _Available since v4.7._
     */
    function toUint48(uint256 value) internal pure returns (uint48) {
        require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits");
        return uint48(value);
    }

    /**
     * @dev Returns the downcasted uint40 from uint256, reverting on
     * overflow (when the input is greater than largest uint40).
     *
     * Counterpart to Solidity's `uint40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     *
     * _Available since v4.7._
     */
    function toUint40(uint256 value) internal pure returns (uint40) {
        require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits");
        return uint40(value);
    }

    /**
     * @dev Returns the downcasted uint32 from uint256, reverting on
     * overflow (when the input is greater than largest uint32).
     *
     * Counterpart to Solidity's `uint32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     *
     * _Available since v2.5._
     */
    function toUint32(uint256 value) internal pure returns (uint32) {
        require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits");
        return uint32(value);
    }

    /**
     * @dev Returns the downcasted uint24 from uint256, reverting on
     * overflow (when the input is greater than largest uint24).
     *
     * Counterpart to Solidity's `uint24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     *
     * _Available since v4.7._
     */
    function toUint24(uint256 value) internal pure returns (uint24) {
        require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits");
        return uint24(value);
    }

    /**
     * @dev Returns the downcasted uint16 from uint256, reverting on
     * overflow (when the input is greater than largest uint16).
     *
     * Counterpart to Solidity's `uint16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     *
     * _Available since v2.5._
     */
    function toUint16(uint256 value) internal pure returns (uint16) {
        require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits");
        return uint16(value);
    }

    /**
     * @dev Returns the downcasted uint8 from uint256, reverting on
     * overflow (when the input is greater than largest uint8).
     *
     * Counterpart to Solidity's `uint8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     *
     * _Available since v2.5._
     */
    function toUint8(uint256 value) internal pure returns (uint8) {
        require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits");
        return uint8(value);
    }

    /**
     * @dev Converts a signed int256 into an unsigned uint256.
     *
     * Requirements:
     *
     * - input must be greater than or equal to 0.
     *
     * _Available since v3.0._
     */
    function toUint256(int256 value) internal pure returns (uint256) {
        require(value >= 0, "SafeCast: value must be positive");
        return uint256(value);
    }

    /**
     * @dev Returns the downcasted int248 from int256, reverting on
     * overflow (when the input is less than smallest int248 or
     * greater than largest int248).
     *
     * Counterpart to Solidity's `int248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     *
     * _Available since v4.7._
     */
    function toInt248(int256 value) internal pure returns (int248 downcasted) {
        downcasted = int248(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 248 bits");
    }

    /**
     * @dev Returns the downcasted int240 from int256, reverting on
     * overflow (when the input is less than smallest int240 or
     * greater than largest int240).
     *
     * Counterpart to Solidity's `int240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     *
     * _Available since v4.7._
     */
    function toInt240(int256 value) internal pure returns (int240 downcasted) {
        downcasted = int240(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 240 bits");
    }

    /**
     * @dev Returns the downcasted int232 from int256, reverting on
     * overflow (when the input is less than smallest int232 or
     * greater than largest int232).
     *
     * Counterpart to Solidity's `int232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     *
     * _Available since v4.7._
     */
    function toInt232(int256 value) internal pure returns (int232 downcasted) {
        downcasted = int232(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 232 bits");
    }

    /**
     * @dev Returns the downcasted int224 from int256, reverting on
     * overflow (when the input is less than smallest int224 or
     * greater than largest int224).
     *
     * Counterpart to Solidity's `int224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     *
     * _Available since v4.7._
     */
    function toInt224(int256 value) internal pure returns (int224 downcasted) {
        downcasted = int224(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 224 bits");
    }

    /**
     * @dev Returns the downcasted int216 from int256, reverting on
     * overflow (when the input is less than smallest int216 or
     * greater than largest int216).
     *
     * Counterpart to Solidity's `int216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     *
     * _Available since v4.7._
     */
    function toInt216(int256 value) internal pure returns (int216 downcasted) {
        downcasted = int216(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 216 bits");
    }

    /**
     * @dev Returns the downcasted int208 from int256, reverting on
     * overflow (when the input is less than smallest int208 or
     * greater than largest int208).
     *
     * Counterpart to Solidity's `int208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     *
     * _Available since v4.7._
     */
    function toInt208(int256 value) internal pure returns (int208 downcasted) {
        downcasted = int208(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 208 bits");
    }

    /**
     * @dev Returns the downcasted int200 from int256, reverting on
     * overflow (when the input is less than smallest int200 or
     * greater than largest int200).
     *
     * Counterpart to Solidity's `int200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     *
     * _Available since v4.7._
     */
    function toInt200(int256 value) internal pure returns (int200 downcasted) {
        downcasted = int200(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 200 bits");
    }

    /**
     * @dev Returns the downcasted int192 from int256, reverting on
     * overflow (when the input is less than smallest int192 or
     * greater than largest int192).
     *
     * Counterpart to Solidity's `int192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     *
     * _Available since v4.7._
     */
    function toInt192(int256 value) internal pure returns (int192 downcasted) {
        downcasted = int192(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 192 bits");
    }

    /**
     * @dev Returns the downcasted int184 from int256, reverting on
     * overflow (when the input is less than smallest int184 or
     * greater than largest int184).
     *
     * Counterpart to Solidity's `int184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     *
     * _Available since v4.7._
     */
    function toInt184(int256 value) internal pure returns (int184 downcasted) {
        downcasted = int184(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 184 bits");
    }

    /**
     * @dev Returns the downcasted int176 from int256, reverting on
     * overflow (when the input is less than smallest int176 or
     * greater than largest int176).
     *
     * Counterpart to Solidity's `int176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     *
     * _Available since v4.7._
     */
    function toInt176(int256 value) internal pure returns (int176 downcasted) {
        downcasted = int176(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 176 bits");
    }

    /**
     * @dev Returns the downcasted int168 from int256, reverting on
     * overflow (when the input is less than smallest int168 or
     * greater than largest int168).
     *
     * Counterpart to Solidity's `int168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     *
     * _Available since v4.7._
     */
    function toInt168(int256 value) internal pure returns (int168 downcasted) {
        downcasted = int168(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 168 bits");
    }

    /**
     * @dev Returns the downcasted int160 from int256, reverting on
     * overflow (when the input is less than smallest int160 or
     * greater than largest int160).
     *
     * Counterpart to Solidity's `int160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     *
     * _Available since v4.7._
     */
    function toInt160(int256 value) internal pure returns (int160 downcasted) {
        downcasted = int160(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 160 bits");
    }

    /**
     * @dev Returns the downcasted int152 from int256, reverting on
     * overflow (when the input is less than smallest int152 or
     * greater than largest int152).
     *
     * Counterpart to Solidity's `int152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     *
     * _Available since v4.7._
     */
    function toInt152(int256 value) internal pure returns (int152 downcasted) {
        downcasted = int152(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 152 bits");
    }

    /**
     * @dev Returns the downcasted int144 from int256, reverting on
     * overflow (when the input is less than smallest int144 or
     * greater than largest int144).
     *
     * Counterpart to Solidity's `int144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     *
     * _Available since v4.7._
     */
    function toInt144(int256 value) internal pure returns (int144 downcasted) {
        downcasted = int144(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 144 bits");
    }

    /**
     * @dev Returns the downcasted int136 from int256, reverting on
     * overflow (when the input is less than smallest int136 or
     * greater than largest int136).
     *
     * Counterpart to Solidity's `int136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     *
     * _Available since v4.7._
     */
    function toInt136(int256 value) internal pure returns (int136 downcasted) {
        downcasted = int136(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 136 bits");
    }

    /**
     * @dev Returns the downcasted int128 from int256, reverting on
     * overflow (when the input is less than smallest int128 or
     * greater than largest int128).
     *
     * Counterpart to Solidity's `int128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     *
     * _Available since v3.1._
     */
    function toInt128(int256 value) internal pure returns (int128 downcasted) {
        downcasted = int128(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 128 bits");
    }

    /**
     * @dev Returns the downcasted int120 from int256, reverting on
     * overflow (when the input is less than smallest int120 or
     * greater than largest int120).
     *
     * Counterpart to Solidity's `int120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     *
     * _Available since v4.7._
     */
    function toInt120(int256 value) internal pure returns (int120 downcasted) {
        downcasted = int120(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 120 bits");
    }

    /**
     * @dev Returns the downcasted int112 from int256, reverting on
     * overflow (when the input is less than smallest int112 or
     * greater than largest int112).
     *
     * Counterpart to Solidity's `int112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     *
     * _Available since v4.7._
     */
    function toInt112(int256 value) internal pure returns (int112 downcasted) {
        downcasted = int112(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 112 bits");
    }

    /**
     * @dev Returns the downcasted int104 from int256, reverting on
     * overflow (when the input is less than smallest int104 or
     * greater than largest int104).
     *
     * Counterpart to Solidity's `int104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     *
     * _Available since v4.7._
     */
    function toInt104(int256 value) internal pure returns (int104 downcasted) {
        downcasted = int104(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 104 bits");
    }

    /**
     * @dev Returns the downcasted int96 from int256, reverting on
     * overflow (when the input is less than smallest int96 or
     * greater than largest int96).
     *
     * Counterpart to Solidity's `int96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     *
     * _Available since v4.7._
     */
    function toInt96(int256 value) internal pure returns (int96 downcasted) {
        downcasted = int96(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 96 bits");
    }

    /**
     * @dev Returns the downcasted int88 from int256, reverting on
     * overflow (when the input is less than smallest int88 or
     * greater than largest int88).
     *
     * Counterpart to Solidity's `int88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     *
     * _Available since v4.7._
     */
    function toInt88(int256 value) internal pure returns (int88 downcasted) {
        downcasted = int88(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 88 bits");
    }

    /**
     * @dev Returns the downcasted int80 from int256, reverting on
     * overflow (when the input is less than smallest int80 or
     * greater than largest int80).
     *
     * Counterpart to Solidity's `int80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     *
     * _Available since v4.7._
     */
    function toInt80(int256 value) internal pure returns (int80 downcasted) {
        downcasted = int80(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 80 bits");
    }

    /**
     * @dev Returns the downcasted int72 from int256, reverting on
     * overflow (when the input is less than smallest int72 or
     * greater than largest int72).
     *
     * Counterpart to Solidity's `int72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     *
     * _Available since v4.7._
     */
    function toInt72(int256 value) internal pure returns (int72 downcasted) {
        downcasted = int72(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 72 bits");
    }

    /**
     * @dev Returns the downcasted int64 from int256, reverting on
     * overflow (when the input is less than smallest int64 or
     * greater than largest int64).
     *
     * Counterpart to Solidity's `int64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     *
     * _Available since v3.1._
     */
    function toInt64(int256 value) internal pure returns (int64 downcasted) {
        downcasted = int64(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 64 bits");
    }

    /**
     * @dev Returns the downcasted int56 from int256, reverting on
     * overflow (when the input is less than smallest int56 or
     * greater than largest int56).
     *
     * Counterpart to Solidity's `int56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     *
     * _Available since v4.7._
     */
    function toInt56(int256 value) internal pure returns (int56 downcasted) {
        downcasted = int56(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 56 bits");
    }

    /**
     * @dev Returns the downcasted int48 from int256, reverting on
     * overflow (when the input is less than smallest int48 or
     * greater than largest int48).
     *
     * Counterpart to Solidity's `int48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     *
     * _Available since v4.7._
     */
    function toInt48(int256 value) internal pure returns (int48 downcasted) {
        downcasted = int48(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 48 bits");
    }

    /**
     * @dev Returns the downcasted int40 from int256, reverting on
     * overflow (when the input is less than smallest int40 or
     * greater than largest int40).
     *
     * Counterpart to Solidity's `int40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     *
     * _Available since v4.7._
     */
    function toInt40(int256 value) internal pure returns (int40 downcasted) {
        downcasted = int40(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 40 bits");
    }

    /**
     * @dev Returns the downcasted int32 from int256, reverting on
     * overflow (when the input is less than smallest int32 or
     * greater than largest int32).
     *
     * Counterpart to Solidity's `int32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     *
     * _Available since v3.1._
     */
    function toInt32(int256 value) internal pure returns (int32 downcasted) {
        downcasted = int32(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 32 bits");
    }

    /**
     * @dev Returns the downcasted int24 from int256, reverting on
     * overflow (when the input is less than smallest int24 or
     * greater than largest int24).
     *
     * Counterpart to Solidity's `int24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     *
     * _Available since v4.7._
     */
    function toInt24(int256 value) internal pure returns (int24 downcasted) {
        downcasted = int24(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 24 bits");
    }

    /**
     * @dev Returns the downcasted int16 from int256, reverting on
     * overflow (when the input is less than smallest int16 or
     * greater than largest int16).
     *
     * Counterpart to Solidity's `int16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     *
     * _Available since v3.1._
     */
    function toInt16(int256 value) internal pure returns (int16 downcasted) {
        downcasted = int16(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 16 bits");
    }

    /**
     * @dev Returns the downcasted int8 from int256, reverting on
     * overflow (when the input is less than smallest int8 or
     * greater than largest int8).
     *
     * Counterpart to Solidity's `int8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     *
     * _Available since v3.1._
     */
    function toInt8(int256 value) internal pure returns (int8 downcasted) {
        downcasted = int8(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 8 bits");
    }

    /**
     * @dev Converts an unsigned uint256 into a signed int256.
     *
     * Requirements:
     *
     * - input must be less than or equal to maxInt256.
     *
     * _Available since v3.0._
     */
    function toInt256(uint256 value) internal pure returns (int256) {
        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
        require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
        return int256(value);
    }
}

// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)

/**
 * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of
 * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and
 * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that
 * the existing queue contents are left in storage.
 *
 * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be
 * used in storage, and not in memory.
 * ```
 * DoubleEndedQueue.Bytes32Deque queue;
 * ```
 *
 * _Available since v4.6._
 */
library DoubleEndedQueue {
    /**
     * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.
     */
    error Empty();

    /**
     * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.
     */
    error OutOfBounds();

    /**
     * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end
     * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely
     * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.
     *
     * Struct members have an underscore prefix indicating that they are "private" and should not be read or written to
     * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and
     * lead to unexpected behavior.
     *
     * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at
     * data[end - 1].
     */
    struct Bytes32Deque {
        int128 _begin;
        int128 _end;
        mapping(int128 => bytes32) _data;
    }

    /**
     * @dev Inserts an item at the end of the queue.
     */
    function pushBack(Bytes32Deque storage deque, bytes32 value) internal {
        int128 backIndex = deque._end;
        deque._data[backIndex] = value;
        unchecked {
            deque._end = backIndex + 1;
        }
    }

    /**
     * @dev Removes the item at the end of the queue and returns it.
     *
     * Reverts with `Empty` if the queue is empty.
     */
    function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {
        if (empty(deque)) revert Empty();
        int128 backIndex;
        unchecked {
            backIndex = deque._end - 1;
        }
        value = deque._data[backIndex];
        delete deque._data[backIndex];
        deque._end = backIndex;
    }

    /**
     * @dev Inserts an item at the beginning of the queue.
     */
    function pushFront(Bytes32Deque storage deque, bytes32 value) internal {
        int128 frontIndex;
        unchecked {
            frontIndex = deque._begin - 1;
        }
        deque._data[frontIndex] = value;
        deque._begin = frontIndex;
    }

    /**
     * @dev Removes the item at the beginning of the queue and returns it.
     *
     * Reverts with `Empty` if the queue is empty.
     */
    function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {
        if (empty(deque)) revert Empty();
        int128 frontIndex = deque._begin;
        value = deque._data[frontIndex];
        delete deque._data[frontIndex];
        unchecked {
            deque._begin = frontIndex + 1;
        }
    }

    /**
     * @dev Returns the item at the beginning of the queue.
     *
     * Reverts with `Empty` if the queue is empty.
     */
    function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {
        if (empty(deque)) revert Empty();
        int128 frontIndex = deque._begin;
        return deque._data[frontIndex];
    }

    /**
     * @dev Returns the item at the end of the queue.
     *
     * Reverts with `Empty` if the queue is empty.
     */
    function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {
        if (empty(deque)) revert Empty();
        int128 backIndex;
        unchecked {
            backIndex = deque._end - 1;
        }
        return deque._data[backIndex];
    }

    /**
     * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at
     * `length(deque) - 1`.
     *
     * Reverts with `OutOfBounds` if the index is out of bounds.
     */
    function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {
        // int256(deque._begin) is a safe upcast
        int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));
        if (idx >= deque._end) revert OutOfBounds();
        return deque._data[idx];
    }

    /**
     * @dev Resets the queue back to being empty.
     *
     * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses
     * out on potential gas refunds.
     */
    function clear(Bytes32Deque storage deque) internal {
        deque._begin = 0;
        deque._end = 0;
    }

    /**
     * @dev Returns the number of items in the queue.
     */
    function length(Bytes32Deque storage deque) internal view returns (uint256) {
        // The interface preserves the invariant that begin <= end so we assume this will not overflow.
        // We also assume there are at most int256.max items in the queue.
        unchecked {
            return uint256(int256(deque._end) - int256(deque._begin));
        }
    }

    /**
     * @dev Returns true if the queue is empty.
     */
    function empty(Bytes32Deque storage deque) internal view returns (bool) {
        return deque._end <= deque._begin;
    }
}

// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)

/**
 * @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);
        }
    }
}

// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

/**
 * @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;
    }
}

// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)

/**
 * @dev Tooling for timepoints, timers and delays
 */
library Timers {
    struct Timestamp {
        uint64 _deadline;
    }

    function getDeadline(Timestamp memory timer) internal pure returns (uint64) {
        return timer._deadline;
    }

    function setDeadline(Timestamp storage timer, uint64 timestamp) internal {
        timer._deadline = timestamp;
    }

    function reset(Timestamp storage timer) internal {
        timer._deadline = 0;
    }

    function isUnset(Timestamp memory timer) internal pure returns (bool) {
        return timer._deadline == 0;
    }

    function isStarted(Timestamp memory timer) internal pure returns (bool) {
        return timer._deadline > 0;
    }

    function isPending(Timestamp memory timer) internal view returns (bool) {
        return timer._deadline > block.timestamp;
    }

    function isExpired(Timestamp memory timer) internal view returns (bool) {
        return isStarted(timer) && timer._deadline <= block.timestamp;
    }

    struct BlockNumber {
        uint64 _deadline;
    }

    function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {
        return timer._deadline;
    }

    function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {
        timer._deadline = timestamp;
    }

    function reset(BlockNumber storage timer) internal {
        timer._deadline = 0;
    }

    function isUnset(BlockNumber memory timer) internal pure returns (bool) {
        return timer._deadline == 0;
    }

    function isStarted(BlockNumber memory timer) internal pure returns (bool) {
        return timer._deadline > 0;
    }

    function isPending(BlockNumber memory timer) internal view returns (bool) {
        return timer._deadline > block.number;
    }

    function isExpired(BlockNumber memory timer) internal view returns (bool) {
        return isStarted(timer) && timer._deadline <= block.number;
    }
}

// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)

/**
 * @dev Interface of the {Governor} core.
 *
 * _Available since v4.3._
 */
abstract contract IGovernor is IERC165 {
    enum ProposalState {
        Pending,
        Active,
        Canceled,
        Defeated,
        Succeeded,
        Queued,
        Expired,
        Executed
    }

    /**
     * @dev Emitted when a proposal is created.
     */
    event ProposalCreated(
        uint256 proposalId,
        address proposer,
        address[] targets,
        uint256[] values,
        string[] signatures,
        bytes[] calldatas,
        uint256 startBlock,
        uint256 endBlock,
        string description
    );

    /**
     * @dev Emitted when a proposal is canceled.
     */
    event ProposalCanceled(uint256 proposalId);

    /**
     * @dev Emitted when a proposal is executed.
     */
    event ProposalExecuted(uint256 proposalId);

    /**
     * @dev Emitted when a vote is cast without params.
     *
     * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.
     */
    event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);

    /**
     * @dev Emitted when a vote is cast with params.
     *
     * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.
     * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.
     */
    event VoteCastWithParams(
        address indexed voter,
        uint256 proposalId,
        uint8 support,
        uint256 weight,
        string reason,
        bytes params
    );

    /**
     * @notice module:core
     * @dev Name of the governor instance (used in building the ERC712 domain separator).
     */
    function name() public view virtual returns (string memory);

    /**
     * @notice module:core
     * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: "1"
     */
    function version() public view virtual returns (string memory);

    /**
     * @notice module:voting
     * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to
     * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of
     * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.
     *
     * There are 2 standard keys: `support` and `quorum`.
     *
     * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.
     * - `quorum=bravo` means that only For votes are counted towards quorum.
     * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.
     *
     * If a counting module makes use of encoded `params`, it should  include this under a `params` key with a unique
     * name that describes the behavior. For example:
     *
     * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.
     * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.
     *
     * NOTE: The string can be decoded by the standard
     * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]
     * JavaScript class.
     */
    // solhint-disable-next-line func-name-mixedcase
    function COUNTING_MODE() public pure virtual returns (string memory);

    /**
     * @notice module:core
     * @dev Hashing function used to (re)build the proposal id from the proposal details..
     */
    function hashProposal(
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory calldatas,
        bytes32 descriptionHash
    ) public pure virtual returns (uint256);

    /**
     * @notice module:core
     * @dev Current state of a proposal, following Compound's convention
     */
    function state(uint256 proposalId) public view virtual returns (ProposalState);

    /**
     * @notice module:core
     * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's
     * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the
     * beginning of the following block.
     */
    function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);

    /**
     * @notice module:core
     * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote
     * during this block.
     */
    function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);

    /**
     * @notice module:user-config
     * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to
     * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.
     */
    function votingDelay() public view virtual returns (uint256);

    /**
     * @notice module:user-config
     * @dev Delay, in number of blocks, between the vote start and vote ends.
     *
     * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting
     * duration compared to the voting delay.
     */
    function votingPeriod() public view virtual returns (uint256);

    /**
     * @notice module:user-config
     * @dev Minimum number of cast voted required for a proposal to be successful.
     *
     * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the
     * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).
     */
    function quorum(uint256 blockNumber) public view virtual returns (uint256);

    /**
     * @notice module:reputation
     * @dev Voting power of an `account` at a specific `blockNumber`.
     *
     * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or
     * multiple), {ERC20Votes} tokens.
     */
    function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);

    /**
     * @notice module:reputation
     * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.
     */
    function getVotesWithParams(
        address account,
        uint256 blockNumber,
        bytes memory params
    ) public view virtual returns (uint256);

    /**
     * @notice module:voting
     * @dev Returns whether `account` has cast a vote on `proposalId`.
     */
    function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);

    /**
     * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends
     * {IGovernor-votingPeriod} blocks after the voting starts.
     *
     * Emits a {ProposalCreated} event.
     */
    function propose(
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory calldatas,
        string memory description
    ) public virtual returns (uint256 proposalId);

    /**
     * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the
     * deadline to be reached.
     *
     * Emits a {ProposalExecuted} event.
     *
     * Note: some module can modify the requirements for execution, for example by adding an additional timelock.
     */
    function execute(
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory calldatas,
        bytes32 descriptionHash
    ) public payable virtual returns (uint256 proposalId);

    /**
     * @dev Cast a vote
     *
     * Emits a {VoteCast} event.
     */
    function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);

    /**
     * @dev Cast a vote with a reason
     *
     * Emits a {VoteCast} event.
     */
    function castVoteWithReason(
        uint256 proposalId,
        uint8 support,
        string calldata reason
    ) public virtual returns (uint256 balance);

    /**
     * @dev Cast a vote with a reason and additional encoded parameters
     *
     * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.
     */
    function castVoteWithReasonAndParams(
        uint256 proposalId,
        uint8 support,
        string calldata reason,
        bytes memory params
    ) public virtual returns (uint256 balance);

    /**
     * @dev Cast a vote using the user's cryptographic signature.
     *
     * Emits a {VoteCast} event.
     */
    function castVoteBySig(
        uint256 proposalId,
        uint8 support,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual returns (uint256 balance);

    /**
     * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.
     *
     * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.
     */
    function castVoteWithReasonAndParamsBySig(
        uint256 proposalId,
        uint8 support,
        string calldata reason,
        bytes memory params,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual returns (uint256 balance);
}

/**
 * @dev Core of the governance system, designed to be extended though various modules.
 *
 * This contract is abstract and requires several function to be implemented in various modules:
 *
 * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}
 * - A voting module must implement {_getVotes}
 * - Additionanly, the {votingPeriod} must also be implemented
 *
 * _Available since v4.3._
 */
abstract contract Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {
    using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;
    using SafeCast for uint256;
    using Timers for Timers.BlockNumber;

    bytes32 public constant BALLOT_TYPEHASH = keccak256("Ballot(uint256 proposalId,uint8 support)");
    bytes32 public constant EXTENDED_BALLOT_TYPEHASH =
        keccak256("ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)");

    struct ProposalCore {
        Timers.BlockNumber voteStart;
        Timers.BlockNumber voteEnd;
        bool executed;
        bool canceled;
    }

    string private _name;

    mapping(uint256 => ProposalCore) private _proposals;

    // This queue keeps track of the governor operating on itself. Calls to functions protected by the
    // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},
    // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the
    // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.
    DoubleEndedQueue.Bytes32Deque private _governanceCall;

    /**
     * @dev Restricts a function so it can only be executed through governance proposals. For example, governance
     * parameter setters in {GovernorSettings} are protected using this modifier.
     *
     * The governance executing address may be different from the Governor's own address, for example it could be a
     * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these
     * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,
     * for example, additional timelock proposers are not able to change governance parameters without going through the
     * governance protocol (since v4.6).
     */
    modifier onlyGovernance() {
        require(_msgSender() == _executor(), "Governor: onlyGovernance");
        if (_executor() != address(this)) {
            bytes32 msgDataHash = keccak256(_msgData());
            // loop until popping the expected operation - throw if deque is empty (operation not authorized)
            while (_governanceCall.popFront() != msgDataHash) {}
        }
        _;
    }

    /**
     * @dev Sets the value for {name} and {version}
     */
    constructor(string memory name_) EIP712(name_, version()) {
        _name = name_;
    }

    /**
     * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)
     */
    receive() external payable virtual {
        require(_executor() == address(this));
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {
        // In addition to the current interfaceId, also support previous version of the interfaceId that did not
        // include the castVoteWithReasonAndParams() function as standard
        return
            interfaceId ==
            (type(IGovernor).interfaceId ^
                this.castVoteWithReasonAndParams.selector ^
                this.castVoteWithReasonAndParamsBySig.selector ^
                this.getVotesWithParams.selector) ||
            interfaceId == type(IGovernor).interfaceId ||
            interfaceId == type(IERC1155Receiver).interfaceId ||
            super.supportsInterface(interfaceId);
    }

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

    /**
     * @dev See {IGovernor-version}.
     */
    function version() public view virtual override returns (string memory) {
        return "1";
    }

    /**
     * @dev See {IGovernor-hashProposal}.
     *
     * The proposal id is produced by hashing the ABI encoded `targets` array, the `values` array, the `calldatas` array
     * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id
     * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in
     * advance, before the proposal is submitted.
     *
     * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the
     * same proposal (with same operation and same description) will have the same id if submitted on multiple governors
     * across multiple networks. This also means that in order to execute the same operation twice (on the same
     * governor) the proposer will have to change the description in order to avoid proposal id conflicts.
     */
    function hashProposal(
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory calldatas,
        bytes32 descriptionHash
    ) public pure virtual override returns (uint256) {
        return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));
    }

    /**
     * @dev See {IGovernor-state}.
     */
    function state(uint256 proposalId) public view virtual override returns (ProposalState) {
        ProposalCore storage proposal = _proposals[proposalId];

        if (proposal.executed) {
            return ProposalState.Executed;
        }

        if (proposal.canceled) {
            return ProposalState.Canceled;
        }

        uint256 snapshot = proposalSnapshot(proposalId);

        if (snapshot == 0) {
            revert("Governor: unknown proposal id");
        }

        if (snapshot >= block.number) {
            return ProposalState.Pending;
        }

        uint256 deadline = proposalDeadline(proposalId);

        if (deadline >= block.number) {
            return ProposalState.Active;
        }

        if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {
            return ProposalState.Succeeded;
        } else {
            return ProposalState.Defeated;
        }
    }

    /**
     * @dev See {IGovernor-proposalSnapshot}.
     */
    function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {
        return _proposals[proposalId].voteStart.getDeadline();
    }

    /**
     * @dev See {IGovernor-proposalDeadline}.
     */
    function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {
        return _proposals[proposalId].voteEnd.getDeadline();
    }

    /**
     * @dev Part of the Governor Bravo's interface: _"The number of votes required in order for a voter to become a proposer"_.
     */
    function proposalThreshold() public view virtual returns (uint256) {
        return 0;
    }

    /**
     * @dev Amount of votes already cast passes the threshold limit.
     */
    function _quorumReached(uint256 proposalId) internal view virtual returns (bool);

    /**
     * @dev Is the proposal successful or not.
     */
    function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);

    /**
     * @dev Get the voting weight of `account` at a specific `blockNumber`, for a vote as described by `params`.
     */
    function _getVotes(
        address account,
        uint256 blockNumber,
        bytes memory params
    ) internal view virtual returns (uint256);

    /**
     * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.
     *
     * Note: Support is generic and can represent various things depending on the voting system used.
     */
    function _countVote(
        uint256 proposalId,
        address account,
        uint8 support,
        uint256 weight,
        bytes memory params
    ) internal virtual;

    /**
     * @dev Default additional encoded parameters used by castVote methods that don't include them
     *
     * Note: Should be overridden by specific implementations to use an appropriate value, the
     * meaning of the additional params, in the context of that implementation
     */
    function _defaultParams() internal view virtual returns (bytes memory) {
        return "";
    }

    /**
     * @dev See {IGovernor-propose}.
     */
    function propose(
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory calldatas,
        string memory description
    ) public virtual override returns (uint256) {
        require(
            getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),
            "Governor: proposer votes below proposal threshold"
        );

        uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));

        require(targets.length == values.length, "Governor: invalid proposal length");
        require(targets.length == calldatas.length, "Governor: invalid proposal length");
        require(targets.length > 0, "Governor: empty proposal");

        ProposalCore storage proposal = _proposals[proposalId];
        require(proposal.voteStart.isUnset(), "Governor: proposal already exists");

        uint64 snapshot = block.number.toUint64() + votingDelay().toUint64();
        uint64 deadline = snapshot + votingPeriod().toUint64();

        proposal.voteStart.setDeadline(snapshot);
        proposal.voteEnd.setDeadline(deadline);

        emit ProposalCreated(
            proposalId,
            _msgSender(),
            targets,
            values,
            new string[](targets.length),
            calldatas,
            snapshot,
            deadline,
            description
        );

        return proposalId;
    }

    /**
     * @dev See {IGovernor-execute}.
     */
    function execute(
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory calldatas,
        bytes32 descriptionHash
    ) public payable virtual override returns (uint256) {
        uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);

        ProposalState status = state(proposalId);
        require(
            status == ProposalState.Succeeded || status == ProposalState.Queued,
            "Governor: proposal not successful"
        );
        _proposals[proposalId].executed = true;

        emit ProposalExecuted(proposalId);

        _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);
        _execute(proposalId, targets, values, calldatas, descriptionHash);
        _afterExecute(proposalId, targets, values, calldatas, descriptionHash);

        return proposalId;
    }

    /**
     * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism
     */
    function _execute(
        uint256, /* proposalId */
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory calldatas,
        bytes32 /*descriptionHash*/
    ) internal virtual {
        string memory errorMessage = "Governor: call reverted without message";
        for (uint256 i = 0; i < targets.length; ++i) {
            (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);
            Address.verifyCallResult(success, returndata, errorMessage);
        }
    }

    /**
     * @dev Hook before execution is triggered.
     */
    function _beforeExecute(
        uint256, /* proposalId */
        address[] memory targets,
        uint256[] memory, /* values */
        bytes[] memory calldatas,
        bytes32 /*descriptionHash*/
    ) internal virtual {
        if (_executor() != address(this)) {
            for (uint256 i = 0; i < targets.length; ++i) {
                if (targets[i] == address(this)) {
                    _governanceCall.pushBack(keccak256(calldatas[i]));
                }
            }
        }
    }

    /**
     * @dev Hook after execution is triggered.
     */
    function _afterExecute(
        uint256, /* proposalId */
        address[] memory, /* targets */
        uint256[] memory, /* values */
        bytes[] memory, /* calldatas */
        bytes32 /*descriptionHash*/
    ) internal virtual {
        if (_executor() != address(this)) {
            if (!_governanceCall.empty()) {
                _governanceCall.clear();
            }
        }
    }

    /**
     * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as
     * canceled to allow distinguishing it from executed proposals.
     *
     * Emits a {IGovernor-ProposalCanceled} event.
     */
    function _cancel(
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory calldatas,
        bytes32 descriptionHash
    ) internal virtual returns (uint256) {
        uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);
        ProposalState status = state(proposalId);

        require(
            status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,
            "Governor: proposal not active"
        );
        _proposals[proposalId].canceled = true;

        emit ProposalCanceled(proposalId);

        return proposalId;
    }

    /**
     * @dev See {IGovernor-getVotes}.
     */
    function getVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) {
        return _getVotes(account, blockNumber, _defaultParams());
    }

    /**
     * @dev See {IGovernor-getVotesWithParams}.
     */
    function getVotesWithParams(
        address account,
        uint256 blockNumber,
        bytes memory params
    ) public view virtual override returns (uint256) {
        return _getVotes(account, blockNumber, params);
    }

    /**
     * @dev See {IGovernor-castVote}.
     */
    function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {
        address voter = _msgSender();
        return _castVote(proposalId, voter, support, "");
    }

    /**
     * @dev See {IGovernor-castVoteWithReason}.
     */
    function castVoteWithReason(
        uint256 proposalId,
        uint8 support,
        string calldata reason
    ) public virtual override returns (uint256) {
        address voter = _msgSender();
        return _castVote(proposalId, voter, support, reason);
    }

    /**
     * @dev See {IGovernor-castVoteWithReasonAndParams}.
     */
    function castVoteWithReasonAndParams(
        uint256 proposalId,
        uint8 support,
        string calldata reason,
        bytes memory params
    ) public virtual override returns (uint256) {
        address voter = _msgSender();
        return _castVote(proposalId, voter, support, reason, params);
    }

    /**
     * @dev See {IGovernor-castVoteBySig}.
     */
    function castVoteBySig(
        uint256 proposalId,
        uint8 support,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual override returns (uint256) {
        address voter = ECDSA.recover(
            _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),
            v,
            r,
            s
        );
        return _castVote(proposalId, voter, support, "");
    }

    /**
     * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.
     */
    function castVoteWithReasonAndParamsBySig(
        uint256 proposalId,
        uint8 support,
        string calldata reason,
        bytes memory params,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual override returns (uint256) {
        address voter = ECDSA.recover(
            _hashTypedDataV4(
                keccak256(
                    abi.encode(
                        EXTENDED_BALLOT_TYPEHASH,
                        proposalId,
                        support,
                        keccak256(bytes(reason)),
                        keccak256(params)
                    )
                )
            ),
            v,
            r,
            s
        );

        return _castVote(proposalId, voter, support, reason, params);
    }

    /**
     * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve
     * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().
     *
     * Emits a {IGovernor-VoteCast} event.
     */
    function _castVote(
        uint256 proposalId,
        address account,
        uint8 support,
        string memory reason
    ) internal virtual returns (uint256) {
        return _castVote(proposalId, account, support, reason, _defaultParams());
    }

    /**
     * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve
     * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.
     *
     * Emits a {IGovernor-VoteCast} event.
     */
    function _castVote(
        uint256 proposalId,
        address account,
        uint8 support,
        string memory reason,
        bytes memory params
    ) internal virtual returns (uint256) {
        ProposalCore storage proposal = _proposals[proposalId];
        require(state(proposalId) == ProposalState.Active, "Governor: vote not currently active");

        uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);
        _countVote(proposalId, account, support, weight, params);

        if (params.length == 0) {
            emit VoteCast(account, proposalId, support, weight, reason);
        } else {
            emit VoteCastWithParams(account, proposalId, support, weight, reason, params);
        }

        return weight;
    }

    /**
     * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor
     * is some contract other than the governor itself, like when using a timelock, this function can be invoked
     * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.
     * Note that if the executor is simply the governor itself, use of `relay` is redundant.
     */
    function relay(
        address target,
        uint256 value,
        bytes calldata data
    ) external payable virtual onlyGovernance {
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        Address.verifyCallResult(success, returndata, "Governor: relay reverted without message");
    }

    /**
     * @dev Address through which the governor executes action. Will be overloaded by module that execute actions
     * through another contract such as a timelock.
     */
    function _executor() internal view virtual returns (address) {
        return address(this);
    }

    /**
     * @dev See {IERC721Receiver-onERC721Received}.
     */
    function onERC721Received(
        address,
        address,
        uint256,
        bytes memory
    ) public virtual override returns (bytes4) {
        return this.onERC721Received.selector;
    }

    /**
     * @dev See {IERC1155Receiver-onERC1155Received}.
     */
    function onERC1155Received(
        address,
        address,
        uint256,
        uint256,
        bytes memory
    ) public virtual override returns (bytes4) {
        return this.onERC1155Received.selector;
    }

    /**
     * @dev See {IERC1155Receiver-onERC1155BatchReceived}.
     */
    function onERC1155BatchReceived(
        address,
        address,
        uint256[] memory,
        uint256[] memory,
        bytes memory
    ) public virtual override returns (bytes4) {
        return this.onERC1155BatchReceived.selector;
    }
}

// OpenZeppelin Contracts v4.4.1 (governance/extensions/GovernorSettings.sol)

/**
 * @dev Extension of {Governor} for settings updatable through governance.
 *
 * _Available since v4.4._
 */
abstract contract GovernorSettings is Governor {
    uint256 private _votingDelay;
    uint256 private _votingPeriod;
    uint256 private _proposalThreshold;

    event VotingDelaySet(uint256 oldVotingDelay, uint256 newVotingDelay);
    event VotingPeriodSet(uint256 oldVotingPeriod, uint256 newVotingPeriod);
    event ProposalThresholdSet(uint256 oldProposalThreshold, uint256 newProposalThreshold);

    /**
     * @dev Initialize the governance parameters.
     */
    constructor(
        uint256 initialVotingDelay,
        uint256 initialVotingPeriod,
        uint256 initialProposalThreshold
    ) {
        _setVotingDelay(initialVotingDelay);
        _setVotingPeriod(initialVotingPeriod);
        _setProposalThreshold(initialProposalThreshold);
    }

    /**
     * @dev See {IGovernor-votingDelay}.
     */
    function votingDelay() public view virtual override returns (uint256) {
        return _votingDelay;
    }

    /**
     * @dev See {IGovernor-votingPeriod}.
     */
    function votingPeriod() public view virtual override returns (uint256) {
        return _votingPeriod;
    }

    /**
     * @dev See {Governor-proposalThreshold}.
     */
    function proposalThreshold() public view virtual override returns (uint256) {
        return _proposalThreshold;
    }

    /**
     * @dev Update the voting delay. This operation can only be performed through a governance proposal.
     *
     * Emits a {VotingDelaySet} event.
     */
    function setVotingDelay(uint256 newVotingDelay) public virtual onlyGovernance {
        _setVotingDelay(newVotingDelay);
    }

    /**
     * @dev Update the voting period. This operation can only be performed through a governance proposal.
     *
     * Emits a {VotingPeriodSet} event.
     */
    function setVotingPeriod(uint256 newVotingPeriod) public virtual onlyGovernance {
        _setVotingPeriod(newVotingPeriod);
    }

    /**
     * @dev Update the proposal threshold. This operation can only be performed through a governance proposal.
     *
     * Emits a {ProposalThresholdSet} event.
     */
    function setProposalThreshold(uint256 newProposalThreshold) public virtual onlyGovernance {
        _setProposalThreshold(newProposalThreshold);
    }

    /**
     * @dev Internal setter for the voting delay.
     *
     * Emits a {VotingDelaySet} event.
     */
    function _setVotingDelay(uint256 newVotingDelay) internal virtual {
        emit VotingDelaySet(_votingDelay, newVotingDelay);
        _votingDelay = newVotingDelay;
    }

    /**
     * @dev Internal setter for the voting period.
     *
     * Emits a {VotingPeriodSet} event.
     */
    function _setVotingPeriod(uint256 newVotingPeriod) internal virtual {
        // voting period must be at least one block long
        require(newVotingPeriod > 0, "GovernorSettings: voting period too low");
        emit VotingPeriodSet(_votingPeriod, newVotingPeriod);
        _votingPeriod = newVotingPeriod;
    }

    /**
     * @dev Internal setter for the proposal threshold.
     *
     * Emits a {ProposalThresholdSet} event.
     */
    function _setProposalThreshold(uint256 newProposalThreshold) internal virtual {
        emit ProposalThresholdSet(_proposalThreshold, newProposalThreshold);
        _proposalThreshold = newProposalThreshold;
    }
}

// OpenZeppelin Contracts (last updated v4.8.0) (governance/extensions/GovernorCountingSimple.sol)

/**
 * @dev Extension of {Governor} for simple, 3 options, vote counting.
 *
 * _Available since v4.3._
 */
abstract contract GovernorCountingSimple is Governor {
    /**
     * @dev Supported vote types. Matches Governor Bravo ordering.
     */
    enum VoteType {
        Against,
        For,
        Abstain
    }

    struct ProposalVote {
        uint256 againstVotes;
        uint256 forVotes;
        uint256 abstainVotes;
        mapping(address => bool) hasVoted;
    }

    mapping(uint256 => ProposalVote) private _proposalVotes;

    /**
     * @dev See {IGovernor-COUNTING_MODE}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function COUNTING_MODE() public pure virtual override returns (string memory) {
        return "support=bravo&quorum=for,abstain";
    }

    /**
     * @dev See {IGovernor-hasVoted}.
     */
    function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {
        return _proposalVotes[proposalId].hasVoted[account];
    }

    /**
     * @dev Accessor to the internal vote counts.
     */
    function proposalVotes(uint256 proposalId)
        public
        view
        virtual
        returns (
            uint256 againstVotes,
            uint256 forVotes,
            uint256 abstainVotes
        )
    {
        ProposalVote storage proposalVote = _proposalVotes[proposalId];
        return (proposalVote.againstVotes, proposalVote.forVotes, proposalVote.abstainVotes);
    }

    /**
     * @dev See {Governor-_quorumReached}.
     */
    function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {
        ProposalVote storage proposalVote = _proposalVotes[proposalId];

        return quorum(proposalSnapshot(proposalId)) <= proposalVote.forVotes + proposalVote.abstainVotes;
    }

    /**
     * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.
     */
    function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {
        ProposalVote storage proposalVote = _proposalVotes[proposalId];

        return proposalVote.forVotes > proposalVote.againstVotes;
    }

    /**
     * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).
     */
    function _countVote(
        uint256 proposalId,
        address account,
        uint8 support,
        uint256 weight,
        bytes memory // params
    ) internal virtual override {
        ProposalVote storage proposalVote = _proposalVotes[proposalId];

        require(!proposalVote.hasVoted[account], "GovernorVotingSimple: vote already cast");
        proposalVote.hasVoted[account] = true;

        if (support == uint8(VoteType.Against)) {
            proposalVote.againstVotes += weight;
        } else if (support == uint8(VoteType.For)) {
            proposalVote.forVotes += weight;
        } else if (support == uint8(VoteType.Abstain)) {
            proposalVote.abstainVotes += weight;
        } else {
            revert("GovernorVotingSimple: invalid value for enum VoteType");
        }
    }
}

// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotesComp.sol)

// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20VotesComp.sol)

// OpenZeppelin Contracts (last updated v4.8.1) (token/ERC20/extensions/ERC20Votes.sol)

// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/extensions/draft-ERC20Permit.sol)

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

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

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

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

// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol)

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

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

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

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

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

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

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

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

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

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

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

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

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

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

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

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

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

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

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

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

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

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

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

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

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

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

        return true;
    }

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

        _beforeTokenTransfer(from, to, amount);

        uint256 fromBalance = _balances[from];
        require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[from] = fromBalance - amount;
            // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
            // decrementing then incrementing.
            _balances[to] += amount;
        }

        emit Transfer(from, to, amount);

        _afterTokenTransfer(from, to, amount);
    }

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

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

        _totalSupply += amount;
        unchecked {
            // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
            _balances[account] += amount;
        }
        emit Transfer(address(0), account, amount);

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

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

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

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
            // Overflow not possible: amount <= accountBalance <= totalSupply.
            _totalSupply -= amount;
        }

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

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

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

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

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

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

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

// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)

/**
 * @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;
    }
}

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

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

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

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

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

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

        bytes32 hash = _hashTypedDataV4(structHash);

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

        _approve(owner, spender, value);
    }

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

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

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

// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)

/**
 * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.
 *
 * _Available since v4.5._
 */
interface IVotes {
    /**
     * @dev Emitted when an account changes their delegate.
     */
    event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);

    /**
     * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.
     */
    event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);

    /**
     * @dev Returns the current amount of votes that `account` has.
     */
    function getVotes(address account) external view returns (uint256);

    /**
     * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).
     */
    function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);

    /**
     * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).
     *
     * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.
     * Votes that have not been delegated are still part of total supply, even though they would not participate in a
     * vote.
     */
    function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);

    /**
     * @dev Returns the delegate that `account` has chosen.
     */
    function delegates(address account) external view returns (address);

    /**
     * @dev Delegates votes from the sender to `delegatee`.
     */
    function delegate(address delegatee) external;

    /**
     * @dev Delegates votes from signer to `delegatee`.
     */
    function delegateBySig(
        address delegatee,
        uint256 nonce,
        uint256 expiry,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;
}

/**
 * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's,
 * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1.
 *
 * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module.
 *
 * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either
 * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting
 * power can be queried through the public accessors {getVotes} and {getPastVotes}.
 *
 * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it
 * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked.
 *
 * _Available since v4.2._
 */
abstract contract ERC20Votes is IVotes, ERC20Permit {
    struct Checkpoint {
        uint32 fromBlock;
        uint224 votes;
    }

    bytes32 private constant _DELEGATION_TYPEHASH =
        keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)");

    mapping(address => address) private _delegates;
    mapping(address => Checkpoint[]) private _checkpoints;
    Checkpoint[] private _totalSupplyCheckpoints;

    /**
     * @dev Get the `pos`-th checkpoint for `account`.
     */
    function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) {
        return _checkpoints[account][pos];
    }

    /**
     * @dev Get number of checkpoints for `account`.
     */
    function numCheckpoints(address account) public view virtual returns (uint32) {
        return SafeCast.toUint32(_checkpoints[account].length);
    }

    /**
     * @dev Get the address `account` is currently delegating to.
     */
    function delegates(address account) public view virtual override returns (address) {
        return _delegates[account];
    }

    /**
     * @dev Gets the current votes balance for `account`
     */
    function getVotes(address account) public view virtual override returns (uint256) {
        uint256 pos = _checkpoints[account].length;
        return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes;
    }

    /**
     * @dev Retrieve the number of votes for `account` at the end of `blockNumber`.
     *
     * Requirements:
     *
     * - `blockNumber` must have been already mined
     */
    function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) {
        require(blockNumber < block.number, "ERC20Votes: block not yet mined");
        return _checkpointsLookup(_checkpoints[account], blockNumber);
    }

    /**
     * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances.
     * It is but NOT the sum of all the delegated votes!
     *
     * Requirements:
     *
     * - `blockNumber` must have been already mined
     */
    function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) {
        require(blockNumber < block.number, "ERC20Votes: block not yet mined");
        return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber);
    }

    /**
     * @dev Lookup a value in a list of (sorted) checkpoints.
     */
    function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) {
        // We run a binary search to look for the earliest checkpoint taken after `blockNumber`.
        //
        // Initially we check if the block is recent to narrow the search range.
        // During the loop, the index of the wanted checkpoint remains in the range [low-1, high).
        // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant.
        // - If the middle checkpoint is after `blockNumber`, we look in [low, mid)
        // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high)
        // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not
        // out of bounds (in which case we're looking too far in the past and the result is 0).
        // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is
        // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out
        // the same.
        uint256 length = ckpts.length;

        uint256 low = 0;
        uint256 high = length;

        if (length > 5) {
            uint256 mid = length - Math.sqrt(length);
            if (_unsafeAccess(ckpts, mid).fromBlock > blockNumber) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }

        while (low < high) {
            uint256 mid = Math.average(low, high);
            if (_unsafeAccess(ckpts, mid).fromBlock > blockNumber) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }

        return high == 0 ? 0 : _unsafeAccess(ckpts, high - 1).votes;
    }

    /**
     * @dev Delegate votes from the sender to `delegatee`.
     */
    function delegate(address delegatee) public virtual override {
        _delegate(_msgSender(), delegatee);
    }

    /**
     * @dev Delegates votes from signer to `delegatee`
     */
    function delegateBySig(
        address delegatee,
        uint256 nonce,
        uint256 expiry,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual override {
        require(block.timestamp <= expiry, "ERC20Votes: signature expired");
        address signer = ECDSA.recover(
            _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))),
            v,
            r,
            s
        );
        require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce");
        _delegate(signer, delegatee);
    }

    /**
     * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1).
     */
    function _maxSupply() internal view virtual returns (uint224) {
        return type(uint224).max;
    }

    /**
     * @dev Snapshots the totalSupply after it has been increased.
     */
    function _mint(address account, uint256 amount) internal virtual override {
        super._mint(account, amount);
        require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes");

        _writeCheckpoint(_totalSupplyCheckpoints, _add, amount);
    }

    /**
     * @dev Snapshots the totalSupply after it has been decreased.
     */
    function _burn(address account, uint256 amount) internal virtual override {
        super._burn(account, amount);

        _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount);
    }

    /**
     * @dev Move voting power when tokens are transferred.
     *
     * Emits a {IVotes-DelegateVotesChanged} event.
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual override {
        super._afterTokenTransfer(from, to, amount);

        _moveVotingPower(delegates(from), delegates(to), amount);
    }

    /**
     * @dev Change delegation for `delegator` to `delegatee`.
     *
     * Emits events {IVotes-DelegateChanged} and {IVotes-DelegateVotesChanged}.
     */
    function _delegate(address delegator, address delegatee) internal virtual {
        address currentDelegate = delegates(delegator);
        uint256 delegatorBalance = balanceOf(delegator);
        _delegates[delegator] = delegatee;

        emit DelegateChanged(delegator, currentDelegate, delegatee);

        _moveVotingPower(currentDelegate, delegatee, delegatorBalance);
    }

    function _moveVotingPower(
        address src,
        address dst,
        uint256 amount
    ) private {
        if (src != dst && amount > 0) {
            if (src != address(0)) {
                (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount);
                emit DelegateVotesChanged(src, oldWeight, newWeight);
            }

            if (dst != address(0)) {
                (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount);
                emit DelegateVotesChanged(dst, oldWeight, newWeight);
            }
        }
    }

    function _writeCheckpoint(
        Checkpoint[] storage ckpts,
        function(uint256, uint256) view returns (uint256) op,
        uint256 delta
    ) private returns (uint256 oldWeight, uint256 newWeight) {
        uint256 pos = ckpts.length;

        Checkpoint memory oldCkpt = pos == 0 ? Checkpoint(0, 0) : _unsafeAccess(ckpts, pos - 1);

        oldWeight = oldCkpt.votes;
        newWeight = op(oldWeight, delta);

        if (pos > 0 && oldCkpt.fromBlock == block.number) {
            _unsafeAccess(ckpts, pos - 1).votes = SafeCast.toUint224(newWeight);
        } else {
            ckpts.push(Checkpoint({fromBlock: SafeCast.toUint32(block.number), votes: SafeCast.toUint224(newWeight)}));
        }
    }

    function _add(uint256 a, uint256 b) private pure returns (uint256) {
        return a + b;
    }

    function _subtract(uint256 a, uint256 b) private pure returns (uint256) {
        return a - b;
    }

    /**
     * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds.
     */
    function _unsafeAccess(Checkpoint[] storage ckpts, uint256 pos) private pure returns (Checkpoint storage result) {
        assembly {
            mstore(0, ckpts.slot)
            result.slot := add(keccak256(0, 0x20), pos)
        }
    }
}

/**
 * @dev Extension of ERC20 to support Compound's voting and delegation. This version exactly matches Compound's
 * interface, with the drawback of only supporting supply up to (2^96^ - 1).
 *
 * NOTE: You should use this contract if you need exact compatibility with COMP (for example in order to use your token
 * with Governor Alpha or Bravo) and if you are sure the supply cap of 2^96^ is enough for you. Otherwise, use the
 * {ERC20Votes} variant of this module.
 *
 * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either
 * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting
 * power can be queried through the public accessors {getCurrentVotes} and {getPriorVotes}.
 *
 * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it
 * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked.
 *
 * _Available since v4.2._
 */
abstract contract ERC20VotesComp is ERC20Votes {
    /**
     * @dev Comp version of the {getVotes} accessor, with `uint96` return type.
     */
    function getCurrentVotes(address account) external view virtual returns (uint96) {
        return SafeCast.toUint96(getVotes(account));
    }

    /**
     * @dev Comp version of the {getPastVotes} accessor, with `uint96` return type.
     */
    function getPriorVotes(address account, uint256 blockNumber) external view virtual returns (uint96) {
        return SafeCast.toUint96(getPastVotes(account, blockNumber));
    }

    /**
     * @dev Maximum token supply. Reduced to `type(uint96).max` (2^96^ - 1) to fit COMP interface.
     */
    function _maxSupply() internal view virtual override returns (uint224) {
        return type(uint96).max;
    }
}

/**
 * @dev Extension of {Governor} for voting weight extraction from a Comp token.
 *
 * _Available since v4.3._
 */
abstract contract GovernorVotesComp is Governor {
    ERC20VotesComp public immutable token;

    constructor(ERC20VotesComp token_) {
        token = token_;
    }

    /**
     * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).
     */
    function _getVotes(
        address account,
        uint256 blockNumber,
        bytes memory /*params*/
    ) internal view virtual override returns (uint256) {
        return token.getPriorVotes(account, blockNumber);
    }
}

contract SudoGovernor is Governor, GovernorSettings, GovernorCountingSimple, GovernorVotesComp {
    constructor(ERC20VotesComp _token)
        Governor("SudoGovernor")
        GovernorSettings(14400 /* 2 days */, 21600 /* 3 days */, 300000e18)
        GovernorVotesComp(_token)
    {}

    function quorum(uint256) public pure override returns (uint256) {
        return 2400000e18;
    }

    // The following functions are overrides required by Solidity.

    function votingDelay()
        public
        view
        override(IGovernor, GovernorSettings)
        returns (uint256)
    {
        return super.votingDelay();
    }

    function votingPeriod()
        public
        view
        override(IGovernor, GovernorSettings)
        returns (uint256)
    {
        return super.votingPeriod();
    }

    function proposalThreshold()
        public
        view
        override(Governor, GovernorSettings)
        returns (uint256)
    {
        return super.proposalThreshold();
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"contract ERC20VotesComp","name":"_token","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"Empty","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"ProposalCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":false,"internalType":"address","name":"proposer","type":"address"},{"indexed":false,"internalType":"address[]","name":"targets","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"},{"indexed":false,"internalType":"string[]","name":"signatures","type":"string[]"},{"indexed":false,"internalType":"bytes[]","name":"calldatas","type":"bytes[]"},{"indexed":false,"internalType":"uint256","name":"startBlock","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endBlock","type":"uint256"},{"indexed":false,"internalType":"string","name":"description","type":"string"}],"name":"ProposalCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"ProposalExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldProposalThreshold","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newProposalThreshold","type":"uint256"}],"name":"ProposalThresholdSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"support","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"weight","type":"uint256"},{"indexed":false,"internalType":"string","name":"reason","type":"string"}],"name":"VoteCast","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"support","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"weight","type":"uint256"},{"indexed":false,"internalType":"string","name":"reason","type":"string"},{"indexed":false,"internalType":"bytes","name":"params","type":"bytes"}],"name":"VoteCastWithParams","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldVotingDelay","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newVotingDelay","type":"uint256"}],"name":"VotingDelaySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldVotingPeriod","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newVotingPeriod","type":"uint256"}],"name":"VotingPeriodSet","type":"event"},{"inputs":[],"name":"BALLOT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"COUNTING_MODE","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"EXTENDED_BALLOT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint8","name":"support","type":"uint8"}],"name":"castVote","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint8","name":"support","type":"uint8"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"castVoteBySig","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint8","name":"support","type":"uint8"},{"internalType":"string","name":"reason","type":"string"}],"name":"castVoteWithReason","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint8","name":"support","type":"uint8"},{"internalType":"string","name":"reason","type":"string"},{"internalType":"bytes","name":"params","type":"bytes"}],"name":"castVoteWithReasonAndParams","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint8","name":"support","type":"uint8"},{"internalType":"string","name":"reason","type":"string"},{"internalType":"bytes","name":"params","type":"bytes"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"castVoteWithReasonAndParamsBySig","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes[]","name":"calldatas","type":"bytes[]"},{"internalType":"bytes32","name":"descriptionHash","type":"bytes32"}],"name":"execute","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"getVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"bytes","name":"params","type":"bytes"}],"name":"getVotesWithParams","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"address","name":"account","type":"address"}],"name":"hasVoted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes[]","name":"calldatas","type":"bytes[]"},{"internalType":"bytes32","name":"descriptionHash","type":"bytes32"}],"name":"hashProposal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"proposalDeadline","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"proposalSnapshot","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proposalThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"proposalVotes","outputs":[{"internalType":"uint256","name":"againstVotes","type":"uint256"},{"internalType":"uint256","name":"forVotes","type":"uint256"},{"internalType":"uint256","name":"abstainVotes","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes[]","name":"calldatas","type":"bytes[]"},{"internalType":"string","name":"description","type":"string"}],"name":"propose","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"quorum","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"relay","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newProposalThreshold","type":"uint256"}],"name":"setProposalThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newVotingDelay","type":"uint256"}],"name":"setVotingDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newVotingPeriod","type":"uint256"}],"name":"setVotingPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"state","outputs":[{"internalType":"enum IGovernor.ProposalState","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"contract ERC20VotesComp","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"votingDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"votingPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

6101606040523480156200001257600080fd5b5060405162005861380380620058618339818101604052810190620000389190620003db565b80613840615460693f870857a3e0e38000006040518060400160405280600c81526020017f5375646f476f7665726e6f7200000000000000000000000000000000000000008152508062000091620001c960201b60201c565b60008280519060200120905060008280519060200120905060007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f90508260e081815250508161010081815250504660a08181525050620000fa8184846200020660201b60201c565b608081815250503073ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff16815250508061012081815250505050505050806000908162000154919062000687565b505062000167836200024260201b60201c565b62000178826200028960201b60201c565b62000189816200031660201b60201c565b5050508073ffffffffffffffffffffffffffffffffffffffff166101408173ffffffffffffffffffffffffffffffffffffffff16815250505050620008de565b60606040518060400160405280600181526020017f3100000000000000000000000000000000000000000000000000000000000000815250905090565b6000838383463060405160200162000223959493929190620007ab565b6040516020818303038152906040528051906020012090509392505050565b7fc565b045403dc03c2eea82b81a0465edad9e2e7fc4d97e11421c209da93d7a93600454826040516200027792919062000808565b60405180910390a18060048190555050565b60008111620002cf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620002c690620008bc565b60405180910390fd5b7f7e3f7f0708a84de9203036abaa450dccc85ad5ff52f78c170f3edb55cf5e8828600554826040516200030492919062000808565b60405180910390a18060058190555050565b7fccb45da8d5717e6c4544694297c4ba5cf151d455c9bb0ed4fc7a38411bc05461600654826040516200034b92919062000808565b60405180910390a18060068190555050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200038f8262000362565b9050919050565b6000620003a38262000382565b9050919050565b620003b58162000396565b8114620003c157600080fd5b50565b600081519050620003d581620003aa565b92915050565b600060208284031215620003f457620003f36200035d565b5b60006200040484828501620003c4565b91505092915050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200048f57607f821691505b602082108103620004a557620004a462000447565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026200050f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82620004d0565b6200051b8683620004d0565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b600062000568620005626200055c8462000533565b6200053d565b62000533565b9050919050565b6000819050919050565b620005848362000547565b6200059c62000593826200056f565b848454620004dd565b825550505050565b600090565b620005b3620005a4565b620005c081848462000579565b505050565b5b81811015620005e857620005dc600082620005a9565b600181019050620005c6565b5050565b601f82111562000637576200060181620004ab565b6200060c84620004c0565b810160208510156200061c578190505b620006346200062b85620004c0565b830182620005c5565b50505b505050565b600082821c905092915050565b60006200065c600019846008026200063c565b1980831691505092915050565b600062000677838362000649565b9150826002028217905092915050565b62000692826200040d565b67ffffffffffffffff811115620006ae57620006ad62000418565b5b620006ba825462000476565b620006c7828285620005ec565b600060209050601f831160018114620006ff5760008415620006ea578287015190505b620006f6858262000669565b86555062000766565b601f1984166200070f86620004ab565b60005b82811015620007395784890151825560018201915060208501945060208101905062000712565b8683101562000759578489015162000755601f89168262000649565b8355505b6001600288020188555050505b505050505050565b6000819050919050565b62000783816200076e565b82525050565b620007948162000533565b82525050565b620007a58162000382565b82525050565b600060a082019050620007c2600083018862000778565b620007d1602083018762000778565b620007e0604083018662000778565b620007ef606083018562000789565b620007fe60808301846200079a565b9695505050505050565b60006040820190506200081f600083018562000789565b6200082e602083018462000789565b9392505050565b600082825260208201905092915050565b7f476f7665726e6f7253657474696e67733a20766f74696e6720706572696f642060008201527f746f6f206c6f7700000000000000000000000000000000000000000000000000602082015250565b6000620008a460278362000835565b9150620008b18262000846565b604082019050919050565b60006020820190508181036000830152620008d78162000895565b9050919050565b60805160a05160c05160e051610100516101205161014051614f216200094060003960008181611a8801526121f00152600061245f015260006124a101526000612480015260006123b50152600061240b015260006124340152614f216000f3fe6080604052600436106101f25760003560e01c806370b0f6601161010d578063c59057e4116100a0578063eb9019d41161006f578063eb9019d414610805578063ece40cc114610842578063f23a6e611461086b578063f8ce560a146108a8578063fc0c546a146108e557610238565b8063c59057e414610749578063dd4e2ba514610786578063deaaa7cc146107b1578063ea0217cf146107dc57610238565b8063b58131b0116100dc578063b58131b014610688578063bc197c81146106b3578063c01f9e37146106f0578063c28bc2fa1461072d57610238565b806370b0f660146105a85780637b3c71d3146105d15780637d5e81e21461060e5780639a802a6d1461064b57610238565b80633932abb111610185578063544ffc9c11610154578063544ffc9c146104c457806354fd4d5014610503578063567813881461052e5780635f398a141461056b57610238565b80633932abb1146103e25780633bccf4fd1461040d5780633e4f49e61461044a578063438596321461048757610238565b8063150b7a02116101c1578063150b7a021461030d5780632656227d1461034a5780632d63f6931461037a5780632fe3e261146103b757610238565b806301ffc9a71461023d57806302a251a31461027a57806303420181146102a557806306fdde03146102e257610238565b36610238573073ffffffffffffffffffffffffffffffffffffffff16610216610910565b73ffffffffffffffffffffffffffffffffffffffff161461023657600080fd5b005b600080fd5b34801561024957600080fd5b50610264600480360381019061025f9190612b72565b610918565b6040516102719190612bba565b60405180910390f35b34801561028657600080fd5b5061028f610a7d565b60405161029c9190612bee565b60405180910390f35b3480156102b157600080fd5b506102cc60048036038101906102c79190612e4a565b610a8c565b6040516102d99190612bee565b60405180910390f35b3480156102ee57600080fd5b506102f7610b71565b6040516103049190612fa7565b60405180910390f35b34801561031957600080fd5b50610334600480360381019061032f9190613027565b610c03565b60405161034191906130b9565b60405180910390f35b610364600480360381019061035f919061333b565b610c17565b6040516103719190612bee565b60405180910390f35b34801561038657600080fd5b506103a1600480360381019061039c91906133f6565b610d64565b6040516103ae9190612bee565b60405180910390f35b3480156103c357600080fd5b506103cc610dd2565b6040516103d99190613432565b60405180910390f35b3480156103ee57600080fd5b506103f7610df6565b6040516104049190612bee565b60405180910390f35b34801561041957600080fd5b50610434600480360381019061042f919061344d565b610e05565b6040516104419190612bee565b60405180910390f35b34801561045657600080fd5b50610471600480360381019061046c91906133f6565b610e8f565b60405161047e919061353f565b60405180910390f35b34801561049357600080fd5b506104ae60048036038101906104a9919061355a565b610fa3565b6040516104bb9190612bba565b60405180910390f35b3480156104d057600080fd5b506104eb60048036038101906104e691906133f6565b61100e565b6040516104fa9392919061359a565b60405180910390f35b34801561050f57600080fd5b50610518611046565b6040516105259190612fa7565b60405180910390f35b34801561053a57600080fd5b50610555600480360381019061055091906135d1565b611083565b6040516105629190612bee565b60405180910390f35b34801561057757600080fd5b50610592600480360381019061058d9190613611565b6110b4565b60405161059f9190612bee565b60405180910390f35b3480156105b457600080fd5b506105cf60048036038101906105ca91906133f6565b61111e565b005b3480156105dd57600080fd5b506105f860048036038101906105f391906136b5565b611215565b6040516106059190612bee565b60405180910390f35b34801561061a57600080fd5b50610635600480360381019061063091906137ca565b61127d565b6040516106429190612bee565b60405180910390f35b34801561065757600080fd5b50610672600480360381019061066d91906138a1565b611584565b60405161067f9190612bee565b60405180910390f35b34801561069457600080fd5b5061069d61159a565b6040516106aa9190612bee565b60405180910390f35b3480156106bf57600080fd5b506106da60048036038101906106d59190613910565b6115a9565b6040516106e791906130b9565b60405180910390f35b3480156106fc57600080fd5b50610717600480360381019061071291906133f6565b6115be565b6040516107249190612bee565b60405180910390f35b61074760048036038101906107429190613a35565b61162c565b005b34801561075557600080fd5b50610770600480360381019061076b919061333b565b6117b5565b60405161077d9190612bee565b60405180910390f35b34801561079257600080fd5b5061079b6117f1565b6040516107a89190612fa7565b60405180910390f35b3480156107bd57600080fd5b506107c661182e565b6040516107d39190613432565b60405180910390f35b3480156107e857600080fd5b5061080360048036038101906107fe91906133f6565b611852565b005b34801561081157600080fd5b5061082c60048036038101906108279190613aa9565b611949565b6040516108399190612bee565b60405180910390f35b34801561084e57600080fd5b50610869600480360381019061086491906133f6565b611965565b005b34801561087757600080fd5b50610892600480360381019061088d9190613ae9565b611a5c565b60405161089f91906130b9565b60405180910390f35b3480156108b457600080fd5b506108cf60048036038101906108ca91906133f6565b611a71565b6040516108dc9190612bee565b60405180910390f35b3480156108f157600080fd5b506108fa611a86565b6040516109079190613bdf565b60405180910390f35b600030905090565b6000639a802a6d60e01b630342018160e01b635f398a1460e01b7f79dd796f000000000000000000000000000000000000000000000000000000001818187bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806109fe57507f79dd796f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610a6657507f4e2312e0000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610a765750610a7582611aaa565b5b9050919050565b6000610a87611b14565b905090565b600080610b0f610b077fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c604051610ac8929190613c2a565b60405180910390208b80519060200120604051602001610aec959493929190613c52565b60405160208183030381529060405280519060200120611b1e565b868686611b38565b9050610b628a828b8b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508a611b63565b91505098975050505050505050565b606060008054610b8090613cd4565b80601f0160208091040260200160405190810160405280929190818152602001828054610bac90613cd4565b8015610bf95780601f10610bce57610100808354040283529160200191610bf9565b820191906000526020600020905b815481529060010190602001808311610bdc57829003601f168201915b5050505050905090565b600063150b7a0260e01b9050949350505050565b600080610c26868686866117b5565b90506000610c3382610e8f565b905060046007811115610c4957610c486134c8565b5b816007811115610c5c57610c5b6134c8565b5b1480610c8c575060056007811115610c7757610c766134c8565b5b816007811115610c8a57610c896134c8565b5b145b610ccb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cc290613d77565b60405180910390fd5b600180600084815260200190815260200160002060020160006101000a81548160ff0219169083151502179055507f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f82604051610d289190612bee565b60405180910390a1610d3d8288888888611d1f565b610d4a8288888888611e02565b610d578288888888611f11565b8192505050949350505050565b6000610dc1600160008481526020019081526020016000206000016040518060200160405290816000820160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681525050611f6c565b67ffffffffffffffff169050919050565b7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b6000610e00611f7a565b905090565b600080610e66610e5e7f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f8989604051602001610e4393929190613d97565b60405160208183030381529060405280519060200120611b1e565b868686611b38565b9050610e8387828860405180602001604052806000815250611f84565b91505095945050505050565b6000806001600084815260200190815260200160002090508060020160009054906101000a900460ff1615610ec8576007915050610f9e565b8060020160019054906101000a900460ff1615610ee9576002915050610f9e565b6000610ef484610d64565b905060008103610f39576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f3090613e1a565b60405180910390fd5b438110610f4b57600092505050610f9e565b6000610f56856115be565b9050438110610f6b5760019350505050610f9e565b610f7485611fa4565b8015610f855750610f8485611feb565b5b15610f965760049350505050610f9e565b600393505050505b919050565b60006007600084815260200190815260200160002060030160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b600080600080600760008681526020019081526020016000209050806000015481600101548260020154935093509350509193909250565b60606040518060400160405280600181526020017f3100000000000000000000000000000000000000000000000000000000000000815250905090565b60008061108e612016565b90506110ab84828560405180602001604052806000815250611f84565b91505092915050565b6000806110bf612016565b905061111287828888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505087611b63565b91505095945050505050565b611126610910565b73ffffffffffffffffffffffffffffffffffffffff16611144612016565b73ffffffffffffffffffffffffffffffffffffffff161461119a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119190613e86565b60405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff166111b9610910565b73ffffffffffffffffffffffffffffffffffffffff16146112095760006111de61201e565b6040516111ec929190613c2a565b604051809103902090505b80611202600261202b565b036111f757505b61121281612107565b50565b600080611220612016565b905061127286828787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050611f84565b915050949350505050565b600061128761159a565b6112a4611292612016565b60014361129f9190613ed5565b611949565b10156112e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112dc90613f7b565b60405180910390fd5b60006112fa86868686805190602001206117b5565b90508451865114611340576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113379061400d565b60405180910390fd5b8351865114611384576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161137b9061400d565b60405180910390fd5b60008651116113c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113bf90614079565b60405180910390fd5b6000600160008381526020019081526020016000209050611428816000016040518060200160405290816000820160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff168152505061214c565b611467576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161145e9061410b565b60405180910390fd5b6000611479611474610df6565b612166565b61148243612166565b61148c919061413f565b905060006114a061149b610a7d565b612166565b826114ab919061413f565b90506114c382846000016121bd90919063ffffffff16565b6114d981846001016121bd90919063ffffffff16565b7f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084611503612016565b8b8b8d5167ffffffffffffffff8111156115205761151f612ce9565b5b60405190808252806020026020018201604052801561155357816020015b606081526020019060019003908161153e5790505b508c88888e60405161156d9998979695949392919061455a565b60405180910390a183945050505050949350505050565b60006115918484846121ec565b90509392505050565b60006115a46122a1565b905090565b600063bc197c8160e01b905095945050505050565b600061161b600160008481526020019081526020016000206001016040518060200160405290816000820160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681525050611f6c565b67ffffffffffffffff169050919050565b611634610910565b73ffffffffffffffffffffffffffffffffffffffff16611652612016565b73ffffffffffffffffffffffffffffffffffffffff16146116a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161169f90613e86565b60405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff166116c7610910565b73ffffffffffffffffffffffffffffffffffffffff16146117175760006116ec61201e565b6040516116fa929190613c2a565b604051809103902090505b80611710600261202b565b0361170557505b6000808573ffffffffffffffffffffffffffffffffffffffff16858585604051611742929190613c2a565b60006040518083038185875af1925050503d806000811461177f576040519150601f19603f3d011682016040523d82523d6000602084013e611784565b606091505b50915091506117ac8282604051806060016040528060288152602001614e9d602891396122ab565b50505050505050565b6000848484846040516020016117ce949392919061460a565b6040516020818303038152906040528051906020012060001c9050949350505050565b60606040518060400160405280602081526020017f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e815250905090565b7f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b61185a610910565b73ffffffffffffffffffffffffffffffffffffffff16611878612016565b73ffffffffffffffffffffffffffffffffffffffff16146118ce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118c590613e86565b60405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff166118ed610910565b73ffffffffffffffffffffffffffffffffffffffff161461193d57600061191261201e565b604051611920929190613c2a565b604051809103902090505b80611936600261202b565b0361192b57505b611946816122cd565b50565b600061195d8383611958612355565b6121ec565b905092915050565b61196d610910565b73ffffffffffffffffffffffffffffffffffffffff1661198b612016565b73ffffffffffffffffffffffffffffffffffffffff16146119e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119d890613e86565b60405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16611a00610910565b73ffffffffffffffffffffffffffffffffffffffff1614611a50576000611a2561201e565b604051611a33929190613c2a565b604051809103902090505b80611a49600261202b565b03611a3e57505b611a598161236c565b50565b600063f23a6e6160e01b905095945050505050565b60006a01fc3842bd1f071c0000009050919050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6000600554905090565b6000611b31611b2b6123b1565b836124cb565b9050919050565b6000806000611b49878787876124fe565b91509150611b56816125e0565b8192505050949350505050565b60008060016000888152602001908152602001600020905060016007811115611b8f57611b8e6134c8565b5b611b9888610e8f565b6007811115611baa57611ba96134c8565b5b14611bea576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611be1906146d6565b60405180910390fd5b6000611c4987611c39846000016040518060200160405290816000820160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681525050611f6c565b67ffffffffffffffff16866121ec565b9050611c588888888488612746565b6000845103611cba578673ffffffffffffffffffffffffffffffffffffffff167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda489888489604051611cad94939291906146f6565b60405180910390a2611d11565b8673ffffffffffffffffffffffffffffffffffffffff167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611d0895949392919061478c565b60405180910390a25b809250505095945050505050565b3073ffffffffffffffffffffffffffffffffffffffff16611d3e610910565b73ffffffffffffffffffffffffffffffffffffffff1614611dfb5760005b8451811015611df9573073ffffffffffffffffffffffffffffffffffffffff16858281518110611d8f57611d8e6147ed565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603611de857611de7838281518110611dc857611dc76147ed565b5b602002602001015180519060200120600261294a90919063ffffffff16565b5b80611df29061481c565b9050611d5c565b505b5050505050565b6000604051806060016040528060278152602001614ec560279139905060005b8551811015611f0857600080878381518110611e4157611e406147ed565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff16878481518110611e7257611e716147ed565b5b6020026020010151878581518110611e8d57611e8c6147ed565b5b6020026020010151604051611ea29190614895565b60006040518083038185875af1925050503d8060008114611edf576040519150601f19603f3d011682016040523d82523d6000602084013e611ee4565b606091505b5091509150611ef48282866122ab565b50505080611f019061481c565b9050611e22565b50505050505050565b3073ffffffffffffffffffffffffffffffffffffffff16611f30610910565b73ffffffffffffffffffffffffffffffffffffffff1614611f6557611f5560026129c6565b611f6457611f6360026129fb565b5b5b5050505050565b600081600001519050919050565b6000600454905090565b6000611f9a85858585611f95612355565b611b63565b9050949350505050565b60008060076000848152602001908152602001600020905080600201548160010154611fd091906148ac565b611fe1611fdc85610d64565b611a71565b1115915050919050565b6000806007600084815260200190815260200160002090508060000154816001015411915050919050565b600033905090565b3660008036915091509091565b6000612036826129c6565b1561206d576040517f3db2a12a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008260000160009054906101000a9004600f0b905082600101600082600f0b600f0b815260200190815260200160002054915082600101600082600f0b600f0b815260200190815260200160002060009055600181018360000160006101000a8154816fffffffffffffffffffffffffffffffff0219169083600f0b6fffffffffffffffffffffffffffffffff16021790555050919050565b7fc565b045403dc03c2eea82b81a0465edad9e2e7fc4d97e11421c209da93d7a936004548260405161213a9291906148e0565b60405180910390a18060048190555050565b600080826000015167ffffffffffffffff16149050919050565b600067ffffffffffffffff80168211156121b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121ac9061497b565b60405180910390fd5b819050919050565b808260000160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663782d6fe185856040518363ffffffff1660e01b815260040161224992919061499b565b602060405180830381865afa158015612266573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061228a9190614a08565b6bffffffffffffffffffffffff1690509392505050565b6000600654905090565b606083156122bb578290506122c6565b6122c58383612a7c565b5b9392505050565b60008111612310576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161230790614aa7565b60405180910390fd5b7f7e3f7f0708a84de9203036abaa450dccc85ad5ff52f78c170f3edb55cf5e8828600554826040516123439291906148e0565b60405180910390a18060058190555050565b606060405180602001604052806000815250905090565b7fccb45da8d5717e6c4544694297c4ba5cf151d455c9bb0ed4fc7a38411bc054616006548260405161239f9291906148e0565b60405180910390a18060068190555050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1614801561242d57507f000000000000000000000000000000000000000000000000000000000000000046145b1561245a577f000000000000000000000000000000000000000000000000000000000000000090506124c8565b6124c57f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000612acc565b90505b90565b600082826040516020016124e0929190614b3f565b60405160208183030381529060405280519060200120905092915050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08360001c11156125395760006003915091506125d7565b60006001878787876040516000815260200160405260405161255e9493929190614b76565b6020604051602081039080840390855afa158015612580573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036125ce576000600192509250506125d7565b80600092509250505b94509492505050565b600060048111156125f4576125f36134c8565b5b816004811115612607576126066134c8565b5b03156127435760016004811115612621576126206134c8565b5b816004811115612634576126336134c8565b5b03612674576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161266b90614c07565b60405180910390fd5b60026004811115612688576126876134c8565b5b81600481111561269b5761269a6134c8565b5b036126db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126d290614c73565b60405180910390fd5b600360048111156126ef576126ee6134c8565b5b816004811115612702576127016134c8565b5b03612742576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161273990614d05565b60405180910390fd5b5b50565b60006007600087815260200190815260200160002090508060030160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156127ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127e390614d97565b60405180910390fd5b60018160030160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506000600281111561285a576128596134c8565b5b60ff168460ff1603612886578281600001600082825461287a91906148ac565b92505081905550612942565b6001600281111561289a576128996134c8565b5b60ff168460ff16036128c657828160010160008282546128ba91906148ac565b92505081905550612941565b6002808111156128d9576128d86134c8565b5b60ff168460ff160361290557828160020160008282546128f991906148ac565b92505081905550612940565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161293790614e29565b60405180910390fd5b5b5b505050505050565b60008260000160109054906101000a9004600f0b90508183600101600083600f0b600f0b815260200190815260200160002081905550600181018360000160106101000a8154816fffffffffffffffffffffffffffffffff0219169083600f0b6fffffffffffffffffffffffffffffffff160217905550505050565b60008160000160009054906101000a9004600f0b600f0b8260000160109054906101000a9004600f0b600f0b13159050919050565b60008160000160006101000a8154816fffffffffffffffffffffffffffffffff0219169083600f0b6fffffffffffffffffffffffffffffffff16021790555060008160000160106101000a8154816fffffffffffffffffffffffffffffffff0219169083600f0b6fffffffffffffffffffffffffffffffff16021790555050565b600082511115612a8f5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ac39190612fa7565b60405180910390fd5b60008383834630604051602001612ae7959493929190614e49565b6040516020818303038152906040528051906020012090509392505050565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612b4f81612b1a565b8114612b5a57600080fd5b50565b600081359050612b6c81612b46565b92915050565b600060208284031215612b8857612b87612b10565b5b6000612b9684828501612b5d565b91505092915050565b60008115159050919050565b612bb481612b9f565b82525050565b6000602082019050612bcf6000830184612bab565b92915050565b6000819050919050565b612be881612bd5565b82525050565b6000602082019050612c036000830184612bdf565b92915050565b612c1281612bd5565b8114612c1d57600080fd5b50565b600081359050612c2f81612c09565b92915050565b600060ff82169050919050565b612c4b81612c35565b8114612c5657600080fd5b50565b600081359050612c6881612c42565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f840112612c9357612c92612c6e565b5b8235905067ffffffffffffffff811115612cb057612caf612c73565b5b602083019150836001820283011115612ccc57612ccb612c78565b5b9250929050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612d2182612cd8565b810181811067ffffffffffffffff82111715612d4057612d3f612ce9565b5b80604052505050565b6000612d53612b06565b9050612d5f8282612d18565b919050565b600067ffffffffffffffff821115612d7f57612d7e612ce9565b5b612d8882612cd8565b9050602081019050919050565b82818337600083830152505050565b6000612db7612db284612d64565b612d49565b905082815260208101848484011115612dd357612dd2612cd3565b5b612dde848285612d95565b509392505050565b600082601f830112612dfb57612dfa612c6e565b5b8135612e0b848260208601612da4565b91505092915050565b6000819050919050565b612e2781612e14565b8114612e3257600080fd5b50565b600081359050612e4481612e1e565b92915050565b60008060008060008060008060e0898b031215612e6a57612e69612b10565b5b6000612e788b828c01612c20565b9850506020612e898b828c01612c59565b975050604089013567ffffffffffffffff811115612eaa57612ea9612b15565b5b612eb68b828c01612c7d565b9650965050606089013567ffffffffffffffff811115612ed957612ed8612b15565b5b612ee58b828c01612de6565b9450506080612ef68b828c01612c59565b93505060a0612f078b828c01612e35565b92505060c0612f188b828c01612e35565b9150509295985092959890939650565b600081519050919050565b600082825260208201905092915050565b60005b83811015612f62578082015181840152602081019050612f47565b60008484015250505050565b6000612f7982612f28565b612f838185612f33565b9350612f93818560208601612f44565b612f9c81612cd8565b840191505092915050565b60006020820190508181036000830152612fc18184612f6e565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612ff482612fc9565b9050919050565b61300481612fe9565b811461300f57600080fd5b50565b60008135905061302181612ffb565b92915050565b6000806000806080858703121561304157613040612b10565b5b600061304f87828801613012565b945050602061306087828801613012565b935050604061307187828801612c20565b925050606085013567ffffffffffffffff81111561309257613091612b15565b5b61309e87828801612de6565b91505092959194509250565b6130b381612b1a565b82525050565b60006020820190506130ce60008301846130aa565b92915050565b600067ffffffffffffffff8211156130ef576130ee612ce9565b5b602082029050602081019050919050565b600061311361310e846130d4565b612d49565b9050808382526020820190506020840283018581111561313657613135612c78565b5b835b8181101561315f578061314b8882613012565b845260208401935050602081019050613138565b5050509392505050565b600082601f83011261317e5761317d612c6e565b5b813561318e848260208601613100565b91505092915050565b600067ffffffffffffffff8211156131b2576131b1612ce9565b5b602082029050602081019050919050565b60006131d66131d184613197565b612d49565b905080838252602082019050602084028301858111156131f9576131f8612c78565b5b835b81811015613222578061320e8882612c20565b8452602084019350506020810190506131fb565b5050509392505050565b600082601f83011261324157613240612c6e565b5b81356132518482602086016131c3565b91505092915050565b600067ffffffffffffffff82111561327557613274612ce9565b5b602082029050602081019050919050565b60006132996132948461325a565b612d49565b905080838252602082019050602084028301858111156132bc576132bb612c78565b5b835b8181101561330357803567ffffffffffffffff8111156132e1576132e0612c6e565b5b8086016132ee8982612de6565b855260208501945050506020810190506132be565b5050509392505050565b600082601f83011261332257613321612c6e565b5b8135613332848260208601613286565b91505092915050565b6000806000806080858703121561335557613354612b10565b5b600085013567ffffffffffffffff81111561337357613372612b15565b5b61337f87828801613169565b945050602085013567ffffffffffffffff8111156133a05761339f612b15565b5b6133ac8782880161322c565b935050604085013567ffffffffffffffff8111156133cd576133cc612b15565b5b6133d98782880161330d565b92505060606133ea87828801612e35565b91505092959194509250565b60006020828403121561340c5761340b612b10565b5b600061341a84828501612c20565b91505092915050565b61342c81612e14565b82525050565b60006020820190506134476000830184613423565b92915050565b600080600080600060a0868803121561346957613468612b10565b5b600061347788828901612c20565b955050602061348888828901612c59565b945050604061349988828901612c59565b93505060606134aa88828901612e35565b92505060806134bb88828901612e35565b9150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60088110613508576135076134c8565b5b50565b6000819050613519826134f7565b919050565b60006135298261350b565b9050919050565b6135398161351e565b82525050565b60006020820190506135546000830184613530565b92915050565b6000806040838503121561357157613570612b10565b5b600061357f85828601612c20565b925050602061359085828601613012565b9150509250929050565b60006060820190506135af6000830186612bdf565b6135bc6020830185612bdf565b6135c96040830184612bdf565b949350505050565b600080604083850312156135e8576135e7612b10565b5b60006135f685828601612c20565b925050602061360785828601612c59565b9150509250929050565b60008060008060006080868803121561362d5761362c612b10565b5b600061363b88828901612c20565b955050602061364c88828901612c59565b945050604086013567ffffffffffffffff81111561366d5761366c612b15565b5b61367988828901612c7d565b9350935050606086013567ffffffffffffffff81111561369c5761369b612b15565b5b6136a888828901612de6565b9150509295509295909350565b600080600080606085870312156136cf576136ce612b10565b5b60006136dd87828801612c20565b94505060206136ee87828801612c59565b935050604085013567ffffffffffffffff81111561370f5761370e612b15565b5b61371b87828801612c7d565b925092505092959194509250565b600067ffffffffffffffff82111561374457613743612ce9565b5b61374d82612cd8565b9050602081019050919050565b600061376d61376884613729565b612d49565b90508281526020810184848401111561378957613788612cd3565b5b613794848285612d95565b509392505050565b600082601f8301126137b1576137b0612c6e565b5b81356137c184826020860161375a565b91505092915050565b600080600080608085870312156137e4576137e3612b10565b5b600085013567ffffffffffffffff81111561380257613801612b15565b5b61380e87828801613169565b945050602085013567ffffffffffffffff81111561382f5761382e612b15565b5b61383b8782880161322c565b935050604085013567ffffffffffffffff81111561385c5761385b612b15565b5b6138688782880161330d565b925050606085013567ffffffffffffffff81111561388957613888612b15565b5b6138958782880161379c565b91505092959194509250565b6000806000606084860312156138ba576138b9612b10565b5b60006138c886828701613012565b93505060206138d986828701612c20565b925050604084013567ffffffffffffffff8111156138fa576138f9612b15565b5b61390686828701612de6565b9150509250925092565b600080600080600060a0868803121561392c5761392b612b10565b5b600061393a88828901613012565b955050602061394b88828901613012565b945050604086013567ffffffffffffffff81111561396c5761396b612b15565b5b6139788882890161322c565b935050606086013567ffffffffffffffff81111561399957613998612b15565b5b6139a58882890161322c565b925050608086013567ffffffffffffffff8111156139c6576139c5612b15565b5b6139d288828901612de6565b9150509295509295909350565b60008083601f8401126139f5576139f4612c6e565b5b8235905067ffffffffffffffff811115613a1257613a11612c73565b5b602083019150836001820283011115613a2e57613a2d612c78565b5b9250929050565b60008060008060608587031215613a4f57613a4e612b10565b5b6000613a5d87828801613012565b9450506020613a6e87828801612c20565b935050604085013567ffffffffffffffff811115613a8f57613a8e612b15565b5b613a9b878288016139df565b925092505092959194509250565b60008060408385031215613ac057613abf612b10565b5b6000613ace85828601613012565b9250506020613adf85828601612c20565b9150509250929050565b600080600080600060a08688031215613b0557613b04612b10565b5b6000613b1388828901613012565b9550506020613b2488828901613012565b9450506040613b3588828901612c20565b9350506060613b4688828901612c20565b925050608086013567ffffffffffffffff811115613b6757613b66612b15565b5b613b7388828901612de6565b9150509295509295909350565b6000819050919050565b6000613ba5613ba0613b9b84612fc9565b613b80565b612fc9565b9050919050565b6000613bb782613b8a565b9050919050565b6000613bc982613bac565b9050919050565b613bd981613bbe565b82525050565b6000602082019050613bf46000830184613bd0565b92915050565b600081905092915050565b6000613c118385613bfa565b9350613c1e838584612d95565b82840190509392505050565b6000613c37828486613c05565b91508190509392505050565b613c4c81612c35565b82525050565b600060a082019050613c676000830188613423565b613c746020830187612bdf565b613c816040830186613c43565b613c8e6060830185613423565b613c9b6080830184613423565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680613cec57607f821691505b602082108103613cff57613cfe613ca5565b5b50919050565b7f476f7665726e6f723a2070726f706f73616c206e6f742073756363657373667560008201527f6c00000000000000000000000000000000000000000000000000000000000000602082015250565b6000613d61602183612f33565b9150613d6c82613d05565b604082019050919050565b60006020820190508181036000830152613d9081613d54565b9050919050565b6000606082019050613dac6000830186613423565b613db96020830185612bdf565b613dc66040830184613c43565b949350505050565b7f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c206964000000600082015250565b6000613e04601d83612f33565b9150613e0f82613dce565b602082019050919050565b60006020820190508181036000830152613e3381613df7565b9050919050565b7f476f7665726e6f723a206f6e6c79476f7665726e616e63650000000000000000600082015250565b6000613e70601883612f33565b9150613e7b82613e3a565b602082019050919050565b60006020820190508181036000830152613e9f81613e63565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000613ee082612bd5565b9150613eeb83612bd5565b9250828203905081811115613f0357613f02613ea6565b5b92915050565b7f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f77207060008201527f726f706f73616c207468726573686f6c64000000000000000000000000000000602082015250565b6000613f65603183612f33565b9150613f7082613f09565b604082019050919050565b60006020820190508181036000830152613f9481613f58565b9050919050565b7f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e677460008201527f6800000000000000000000000000000000000000000000000000000000000000602082015250565b6000613ff7602183612f33565b915061400282613f9b565b604082019050919050565b6000602082019050818103600083015261402681613fea565b9050919050565b7f476f7665726e6f723a20656d7074792070726f706f73616c0000000000000000600082015250565b6000614063601883612f33565b915061406e8261402d565b602082019050919050565b6000602082019050818103600083015261409281614056565b9050919050565b7f476f7665726e6f723a2070726f706f73616c20616c726561647920657869737460008201527f7300000000000000000000000000000000000000000000000000000000000000602082015250565b60006140f5602183612f33565b915061410082614099565b604082019050919050565b60006020820190508181036000830152614124816140e8565b9050919050565b600067ffffffffffffffff82169050919050565b600061414a8261412b565b91506141558361412b565b9250828201905067ffffffffffffffff81111561417557614174613ea6565b5b92915050565b61418481612fe9565b82525050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6141bf81612fe9565b82525050565b60006141d183836141b6565b60208301905092915050565b6000602082019050919050565b60006141f58261418a565b6141ff8185614195565b935061420a836141a6565b8060005b8381101561423b57815161422288826141c5565b975061422d836141dd565b92505060018101905061420e565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61427d81612bd5565b82525050565b600061428f8383614274565b60208301905092915050565b6000602082019050919050565b60006142b382614248565b6142bd8185614253565b93506142c883614264565b8060005b838110156142f95781516142e08882614283565b97506142eb8361429b565b9250506001810190506142cc565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600082825260208201905092915050565b600061434e82612f28565b6143588185614332565b9350614368818560208601612f44565b61437181612cd8565b840191505092915050565b60006143888383614343565b905092915050565b6000602082019050919050565b60006143a882614306565b6143b28185614311565b9350836020820285016143c485614322565b8060005b8581101561440057848403895281516143e1858261437c565b94506143ec83614390565b925060208a019950506001810190506143c8565b50829750879550505050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b60006144658261443e565b61446f8185614449565b935061447f818560208601612f44565b61448881612cd8565b840191505092915050565b600061449f838361445a565b905092915050565b6000602082019050919050565b60006144bf82614412565b6144c9818561441d565b9350836020820285016144db8561442e565b8060005b8581101561451757848403895281516144f88582614493565b9450614503836144a7565b925060208a019950506001810190506144df565b50829750879550505050505092915050565b600061454461453f61453a8461412b565b613b80565b612bd5565b9050919050565b61455481614529565b82525050565b600061012082019050614570600083018c612bdf565b61457d602083018b61417b565b818103604083015261458f818a6141ea565b905081810360608301526145a381896142a8565b905081810360808301526145b7818861439d565b905081810360a08301526145cb81876144b4565b90506145da60c083018661454b565b6145e760e083018561454b565b8181036101008301526145fa8184612f6e565b90509a9950505050505050505050565b6000608082019050818103600083015261462481876141ea565b9050818103602083015261463881866142a8565b9050818103604083015261464c81856144b4565b905061465b6060830184613423565b95945050505050565b7f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460008201527f6976650000000000000000000000000000000000000000000000000000000000602082015250565b60006146c0602383612f33565b91506146cb82614664565b604082019050919050565b600060208201905081810360008301526146ef816146b3565b9050919050565b600060808201905061470b6000830187612bdf565b6147186020830186613c43565b6147256040830185612bdf565b81810360608301526147378184612f6e565b905095945050505050565b600082825260208201905092915050565b600061475e8261443e565b6147688185614742565b9350614778818560208601612f44565b61478181612cd8565b840191505092915050565b600060a0820190506147a16000830188612bdf565b6147ae6020830187613c43565b6147bb6040830186612bdf565b81810360608301526147cd8185612f6e565b905081810360808301526147e18184614753565b90509695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600061482782612bd5565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361485957614858613ea6565b5b600182019050919050565b600061486f8261443e565b6148798185613bfa565b9350614889818560208601612f44565b80840191505092915050565b60006148a18284614864565b915081905092915050565b60006148b782612bd5565b91506148c283612bd5565b92508282019050808211156148da576148d9613ea6565b5b92915050565b60006040820190506148f56000830185612bdf565b6149026020830184612bdf565b9392505050565b7f53616665436173743a2076616c756520646f65736e27742066697420696e203660008201527f3420626974730000000000000000000000000000000000000000000000000000602082015250565b6000614965602683612f33565b915061497082614909565b604082019050919050565b6000602082019050818103600083015261499481614958565b9050919050565b60006040820190506149b0600083018561417b565b6149bd6020830184612bdf565b9392505050565b60006bffffffffffffffffffffffff82169050919050565b6149e5816149c4565b81146149f057600080fd5b50565b600081519050614a02816149dc565b92915050565b600060208284031215614a1e57614a1d612b10565b5b6000614a2c848285016149f3565b91505092915050565b7f476f7665726e6f7253657474696e67733a20766f74696e6720706572696f642060008201527f746f6f206c6f7700000000000000000000000000000000000000000000000000602082015250565b6000614a91602783612f33565b9150614a9c82614a35565b604082019050919050565b60006020820190508181036000830152614ac081614a84565b9050919050565b600081905092915050565b7f1901000000000000000000000000000000000000000000000000000000000000600082015250565b6000614b08600283614ac7565b9150614b1382614ad2565b600282019050919050565b6000819050919050565b614b39614b3482612e14565b614b1e565b82525050565b6000614b4a82614afb565b9150614b568285614b28565b602082019150614b668284614b28565b6020820191508190509392505050565b6000608082019050614b8b6000830187613423565b614b986020830186613c43565b614ba56040830185613423565b614bb26060830184613423565b95945050505050565b7f45434453413a20696e76616c6964207369676e61747572650000000000000000600082015250565b6000614bf1601883612f33565b9150614bfc82614bbb565b602082019050919050565b60006020820190508181036000830152614c2081614be4565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265206c656e67746800600082015250565b6000614c5d601f83612f33565b9150614c6882614c27565b602082019050919050565b60006020820190508181036000830152614c8c81614c50565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265202773272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b6000614cef602283612f33565b9150614cfa82614c93565b604082019050919050565b60006020820190508181036000830152614d1e81614ce2565b9050919050565b7f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c72656160008201527f6479206361737400000000000000000000000000000000000000000000000000602082015250565b6000614d81602783612f33565b9150614d8c82614d25565b604082019050919050565b60006020820190508181036000830152614db081614d74565b9050919050565b7f476f7665726e6f72566f74696e6753696d706c653a20696e76616c696420766160008201527f6c756520666f7220656e756d20566f7465547970650000000000000000000000602082015250565b6000614e13603583612f33565b9150614e1e82614db7565b604082019050919050565b60006020820190508181036000830152614e4281614e06565b9050919050565b600060a082019050614e5e6000830188613423565b614e6b6020830187613423565b614e786040830186613423565b614e856060830185612bdf565b614e92608083018461417b565b969550505050505056fe476f7665726e6f723a2072656c617920726576657274656420776974686f7574206d657373616765476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765a264697066735822122007d0065dfa1b0b6d01e855d84d3bda7886cec984eb729e8e1da32f15f3ffd0d564736f6c634300081100330000000000000000000000003446dd70b2d52a6bf4a5a192d9b0a161295ab7f9

Deployed Bytecode

0x6080604052600436106101f25760003560e01c806370b0f6601161010d578063c59057e4116100a0578063eb9019d41161006f578063eb9019d414610805578063ece40cc114610842578063f23a6e611461086b578063f8ce560a146108a8578063fc0c546a146108e557610238565b8063c59057e414610749578063dd4e2ba514610786578063deaaa7cc146107b1578063ea0217cf146107dc57610238565b8063b58131b0116100dc578063b58131b014610688578063bc197c81146106b3578063c01f9e37146106f0578063c28bc2fa1461072d57610238565b806370b0f660146105a85780637b3c71d3146105d15780637d5e81e21461060e5780639a802a6d1461064b57610238565b80633932abb111610185578063544ffc9c11610154578063544ffc9c146104c457806354fd4d5014610503578063567813881461052e5780635f398a141461056b57610238565b80633932abb1146103e25780633bccf4fd1461040d5780633e4f49e61461044a578063438596321461048757610238565b8063150b7a02116101c1578063150b7a021461030d5780632656227d1461034a5780632d63f6931461037a5780632fe3e261146103b757610238565b806301ffc9a71461023d57806302a251a31461027a57806303420181146102a557806306fdde03146102e257610238565b36610238573073ffffffffffffffffffffffffffffffffffffffff16610216610910565b73ffffffffffffffffffffffffffffffffffffffff161461023657600080fd5b005b600080fd5b34801561024957600080fd5b50610264600480360381019061025f9190612b72565b610918565b6040516102719190612bba565b60405180910390f35b34801561028657600080fd5b5061028f610a7d565b60405161029c9190612bee565b60405180910390f35b3480156102b157600080fd5b506102cc60048036038101906102c79190612e4a565b610a8c565b6040516102d99190612bee565b60405180910390f35b3480156102ee57600080fd5b506102f7610b71565b6040516103049190612fa7565b60405180910390f35b34801561031957600080fd5b50610334600480360381019061032f9190613027565b610c03565b60405161034191906130b9565b60405180910390f35b610364600480360381019061035f919061333b565b610c17565b6040516103719190612bee565b60405180910390f35b34801561038657600080fd5b506103a1600480360381019061039c91906133f6565b610d64565b6040516103ae9190612bee565b60405180910390f35b3480156103c357600080fd5b506103cc610dd2565b6040516103d99190613432565b60405180910390f35b3480156103ee57600080fd5b506103f7610df6565b6040516104049190612bee565b60405180910390f35b34801561041957600080fd5b50610434600480360381019061042f919061344d565b610e05565b6040516104419190612bee565b60405180910390f35b34801561045657600080fd5b50610471600480360381019061046c91906133f6565b610e8f565b60405161047e919061353f565b60405180910390f35b34801561049357600080fd5b506104ae60048036038101906104a9919061355a565b610fa3565b6040516104bb9190612bba565b60405180910390f35b3480156104d057600080fd5b506104eb60048036038101906104e691906133f6565b61100e565b6040516104fa9392919061359a565b60405180910390f35b34801561050f57600080fd5b50610518611046565b6040516105259190612fa7565b60405180910390f35b34801561053a57600080fd5b50610555600480360381019061055091906135d1565b611083565b6040516105629190612bee565b60405180910390f35b34801561057757600080fd5b50610592600480360381019061058d9190613611565b6110b4565b60405161059f9190612bee565b60405180910390f35b3480156105b457600080fd5b506105cf60048036038101906105ca91906133f6565b61111e565b005b3480156105dd57600080fd5b506105f860048036038101906105f391906136b5565b611215565b6040516106059190612bee565b60405180910390f35b34801561061a57600080fd5b50610635600480360381019061063091906137ca565b61127d565b6040516106429190612bee565b60405180910390f35b34801561065757600080fd5b50610672600480360381019061066d91906138a1565b611584565b60405161067f9190612bee565b60405180910390f35b34801561069457600080fd5b5061069d61159a565b6040516106aa9190612bee565b60405180910390f35b3480156106bf57600080fd5b506106da60048036038101906106d59190613910565b6115a9565b6040516106e791906130b9565b60405180910390f35b3480156106fc57600080fd5b50610717600480360381019061071291906133f6565b6115be565b6040516107249190612bee565b60405180910390f35b61074760048036038101906107429190613a35565b61162c565b005b34801561075557600080fd5b50610770600480360381019061076b919061333b565b6117b5565b60405161077d9190612bee565b60405180910390f35b34801561079257600080fd5b5061079b6117f1565b6040516107a89190612fa7565b60405180910390f35b3480156107bd57600080fd5b506107c661182e565b6040516107d39190613432565b60405180910390f35b3480156107e857600080fd5b5061080360048036038101906107fe91906133f6565b611852565b005b34801561081157600080fd5b5061082c60048036038101906108279190613aa9565b611949565b6040516108399190612bee565b60405180910390f35b34801561084e57600080fd5b50610869600480360381019061086491906133f6565b611965565b005b34801561087757600080fd5b50610892600480360381019061088d9190613ae9565b611a5c565b60405161089f91906130b9565b60405180910390f35b3480156108b457600080fd5b506108cf60048036038101906108ca91906133f6565b611a71565b6040516108dc9190612bee565b60405180910390f35b3480156108f157600080fd5b506108fa611a86565b6040516109079190613bdf565b60405180910390f35b600030905090565b6000639a802a6d60e01b630342018160e01b635f398a1460e01b7f79dd796f000000000000000000000000000000000000000000000000000000001818187bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806109fe57507f79dd796f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610a6657507f4e2312e0000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610a765750610a7582611aaa565b5b9050919050565b6000610a87611b14565b905090565b600080610b0f610b077fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c604051610ac8929190613c2a565b60405180910390208b80519060200120604051602001610aec959493929190613c52565b60405160208183030381529060405280519060200120611b1e565b868686611b38565b9050610b628a828b8b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508a611b63565b91505098975050505050505050565b606060008054610b8090613cd4565b80601f0160208091040260200160405190810160405280929190818152602001828054610bac90613cd4565b8015610bf95780601f10610bce57610100808354040283529160200191610bf9565b820191906000526020600020905b815481529060010190602001808311610bdc57829003601f168201915b5050505050905090565b600063150b7a0260e01b9050949350505050565b600080610c26868686866117b5565b90506000610c3382610e8f565b905060046007811115610c4957610c486134c8565b5b816007811115610c5c57610c5b6134c8565b5b1480610c8c575060056007811115610c7757610c766134c8565b5b816007811115610c8a57610c896134c8565b5b145b610ccb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cc290613d77565b60405180910390fd5b600180600084815260200190815260200160002060020160006101000a81548160ff0219169083151502179055507f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f82604051610d289190612bee565b60405180910390a1610d3d8288888888611d1f565b610d4a8288888888611e02565b610d578288888888611f11565b8192505050949350505050565b6000610dc1600160008481526020019081526020016000206000016040518060200160405290816000820160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681525050611f6c565b67ffffffffffffffff169050919050565b7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b6000610e00611f7a565b905090565b600080610e66610e5e7f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f8989604051602001610e4393929190613d97565b60405160208183030381529060405280519060200120611b1e565b868686611b38565b9050610e8387828860405180602001604052806000815250611f84565b91505095945050505050565b6000806001600084815260200190815260200160002090508060020160009054906101000a900460ff1615610ec8576007915050610f9e565b8060020160019054906101000a900460ff1615610ee9576002915050610f9e565b6000610ef484610d64565b905060008103610f39576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f3090613e1a565b60405180910390fd5b438110610f4b57600092505050610f9e565b6000610f56856115be565b9050438110610f6b5760019350505050610f9e565b610f7485611fa4565b8015610f855750610f8485611feb565b5b15610f965760049350505050610f9e565b600393505050505b919050565b60006007600084815260200190815260200160002060030160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b600080600080600760008681526020019081526020016000209050806000015481600101548260020154935093509350509193909250565b60606040518060400160405280600181526020017f3100000000000000000000000000000000000000000000000000000000000000815250905090565b60008061108e612016565b90506110ab84828560405180602001604052806000815250611f84565b91505092915050565b6000806110bf612016565b905061111287828888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505087611b63565b91505095945050505050565b611126610910565b73ffffffffffffffffffffffffffffffffffffffff16611144612016565b73ffffffffffffffffffffffffffffffffffffffff161461119a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119190613e86565b60405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff166111b9610910565b73ffffffffffffffffffffffffffffffffffffffff16146112095760006111de61201e565b6040516111ec929190613c2a565b604051809103902090505b80611202600261202b565b036111f757505b61121281612107565b50565b600080611220612016565b905061127286828787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050611f84565b915050949350505050565b600061128761159a565b6112a4611292612016565b60014361129f9190613ed5565b611949565b10156112e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112dc90613f7b565b60405180910390fd5b60006112fa86868686805190602001206117b5565b90508451865114611340576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113379061400d565b60405180910390fd5b8351865114611384576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161137b9061400d565b60405180910390fd5b60008651116113c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113bf90614079565b60405180910390fd5b6000600160008381526020019081526020016000209050611428816000016040518060200160405290816000820160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff168152505061214c565b611467576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161145e9061410b565b60405180910390fd5b6000611479611474610df6565b612166565b61148243612166565b61148c919061413f565b905060006114a061149b610a7d565b612166565b826114ab919061413f565b90506114c382846000016121bd90919063ffffffff16565b6114d981846001016121bd90919063ffffffff16565b7f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e084611503612016565b8b8b8d5167ffffffffffffffff8111156115205761151f612ce9565b5b60405190808252806020026020018201604052801561155357816020015b606081526020019060019003908161153e5790505b508c88888e60405161156d9998979695949392919061455a565b60405180910390a183945050505050949350505050565b60006115918484846121ec565b90509392505050565b60006115a46122a1565b905090565b600063bc197c8160e01b905095945050505050565b600061161b600160008481526020019081526020016000206001016040518060200160405290816000820160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681525050611f6c565b67ffffffffffffffff169050919050565b611634610910565b73ffffffffffffffffffffffffffffffffffffffff16611652612016565b73ffffffffffffffffffffffffffffffffffffffff16146116a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161169f90613e86565b60405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff166116c7610910565b73ffffffffffffffffffffffffffffffffffffffff16146117175760006116ec61201e565b6040516116fa929190613c2a565b604051809103902090505b80611710600261202b565b0361170557505b6000808573ffffffffffffffffffffffffffffffffffffffff16858585604051611742929190613c2a565b60006040518083038185875af1925050503d806000811461177f576040519150601f19603f3d011682016040523d82523d6000602084013e611784565b606091505b50915091506117ac8282604051806060016040528060288152602001614e9d602891396122ab565b50505050505050565b6000848484846040516020016117ce949392919061460a565b6040516020818303038152906040528051906020012060001c9050949350505050565b60606040518060400160405280602081526020017f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e815250905090565b7f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b61185a610910565b73ffffffffffffffffffffffffffffffffffffffff16611878612016565b73ffffffffffffffffffffffffffffffffffffffff16146118ce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118c590613e86565b60405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff166118ed610910565b73ffffffffffffffffffffffffffffffffffffffff161461193d57600061191261201e565b604051611920929190613c2a565b604051809103902090505b80611936600261202b565b0361192b57505b611946816122cd565b50565b600061195d8383611958612355565b6121ec565b905092915050565b61196d610910565b73ffffffffffffffffffffffffffffffffffffffff1661198b612016565b73ffffffffffffffffffffffffffffffffffffffff16146119e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119d890613e86565b60405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16611a00610910565b73ffffffffffffffffffffffffffffffffffffffff1614611a50576000611a2561201e565b604051611a33929190613c2a565b604051809103902090505b80611a49600261202b565b03611a3e57505b611a598161236c565b50565b600063f23a6e6160e01b905095945050505050565b60006a01fc3842bd1f071c0000009050919050565b7f0000000000000000000000003446dd70b2d52a6bf4a5a192d9b0a161295ab7f981565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6000600554905090565b6000611b31611b2b6123b1565b836124cb565b9050919050565b6000806000611b49878787876124fe565b91509150611b56816125e0565b8192505050949350505050565b60008060016000888152602001908152602001600020905060016007811115611b8f57611b8e6134c8565b5b611b9888610e8f565b6007811115611baa57611ba96134c8565b5b14611bea576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611be1906146d6565b60405180910390fd5b6000611c4987611c39846000016040518060200160405290816000820160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681525050611f6c565b67ffffffffffffffff16866121ec565b9050611c588888888488612746565b6000845103611cba578673ffffffffffffffffffffffffffffffffffffffff167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda489888489604051611cad94939291906146f6565b60405180910390a2611d11565b8673ffffffffffffffffffffffffffffffffffffffff167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87128988848989604051611d0895949392919061478c565b60405180910390a25b809250505095945050505050565b3073ffffffffffffffffffffffffffffffffffffffff16611d3e610910565b73ffffffffffffffffffffffffffffffffffffffff1614611dfb5760005b8451811015611df9573073ffffffffffffffffffffffffffffffffffffffff16858281518110611d8f57611d8e6147ed565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603611de857611de7838281518110611dc857611dc76147ed565b5b602002602001015180519060200120600261294a90919063ffffffff16565b5b80611df29061481c565b9050611d5c565b505b5050505050565b6000604051806060016040528060278152602001614ec560279139905060005b8551811015611f0857600080878381518110611e4157611e406147ed565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff16878481518110611e7257611e716147ed565b5b6020026020010151878581518110611e8d57611e8c6147ed565b5b6020026020010151604051611ea29190614895565b60006040518083038185875af1925050503d8060008114611edf576040519150601f19603f3d011682016040523d82523d6000602084013e611ee4565b606091505b5091509150611ef48282866122ab565b50505080611f019061481c565b9050611e22565b50505050505050565b3073ffffffffffffffffffffffffffffffffffffffff16611f30610910565b73ffffffffffffffffffffffffffffffffffffffff1614611f6557611f5560026129c6565b611f6457611f6360026129fb565b5b5b5050505050565b600081600001519050919050565b6000600454905090565b6000611f9a85858585611f95612355565b611b63565b9050949350505050565b60008060076000848152602001908152602001600020905080600201548160010154611fd091906148ac565b611fe1611fdc85610d64565b611a71565b1115915050919050565b6000806007600084815260200190815260200160002090508060000154816001015411915050919050565b600033905090565b3660008036915091509091565b6000612036826129c6565b1561206d576040517f3db2a12a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008260000160009054906101000a9004600f0b905082600101600082600f0b600f0b815260200190815260200160002054915082600101600082600f0b600f0b815260200190815260200160002060009055600181018360000160006101000a8154816fffffffffffffffffffffffffffffffff0219169083600f0b6fffffffffffffffffffffffffffffffff16021790555050919050565b7fc565b045403dc03c2eea82b81a0465edad9e2e7fc4d97e11421c209da93d7a936004548260405161213a9291906148e0565b60405180910390a18060048190555050565b600080826000015167ffffffffffffffff16149050919050565b600067ffffffffffffffff80168211156121b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121ac9061497b565b60405180910390fd5b819050919050565b808260000160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505050565b60007f0000000000000000000000003446dd70b2d52a6bf4a5a192d9b0a161295ab7f973ffffffffffffffffffffffffffffffffffffffff1663782d6fe185856040518363ffffffff1660e01b815260040161224992919061499b565b602060405180830381865afa158015612266573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061228a9190614a08565b6bffffffffffffffffffffffff1690509392505050565b6000600654905090565b606083156122bb578290506122c6565b6122c58383612a7c565b5b9392505050565b60008111612310576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161230790614aa7565b60405180910390fd5b7f7e3f7f0708a84de9203036abaa450dccc85ad5ff52f78c170f3edb55cf5e8828600554826040516123439291906148e0565b60405180910390a18060058190555050565b606060405180602001604052806000815250905090565b7fccb45da8d5717e6c4544694297c4ba5cf151d455c9bb0ed4fc7a38411bc054616006548260405161239f9291906148e0565b60405180910390a18060068190555050565b60007f0000000000000000000000006853f8865ba8e9fbd9c8cce3155ce5023fb7eeb073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1614801561242d57507f000000000000000000000000000000000000000000000000000000000000000146145b1561245a577f300060c9d892e6d51e095a16f1194a0d0ef16625ff2ec3f2465507a9f0b34e3b90506124c8565b6124c57f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7fe2308e69d0715b6d261e3647a1a534cb74640542db10ec1be3fc0e26621b55027fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6612acc565b90505b90565b600082826040516020016124e0929190614b3f565b60405160208183030381529060405280519060200120905092915050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08360001c11156125395760006003915091506125d7565b60006001878787876040516000815260200160405260405161255e9493929190614b76565b6020604051602081039080840390855afa158015612580573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036125ce576000600192509250506125d7565b80600092509250505b94509492505050565b600060048111156125f4576125f36134c8565b5b816004811115612607576126066134c8565b5b03156127435760016004811115612621576126206134c8565b5b816004811115612634576126336134c8565b5b03612674576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161266b90614c07565b60405180910390fd5b60026004811115612688576126876134c8565b5b81600481111561269b5761269a6134c8565b5b036126db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126d290614c73565b60405180910390fd5b600360048111156126ef576126ee6134c8565b5b816004811115612702576127016134c8565b5b03612742576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161273990614d05565b60405180910390fd5b5b50565b60006007600087815260200190815260200160002090508060030160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156127ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127e390614d97565b60405180910390fd5b60018160030160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506000600281111561285a576128596134c8565b5b60ff168460ff1603612886578281600001600082825461287a91906148ac565b92505081905550612942565b6001600281111561289a576128996134c8565b5b60ff168460ff16036128c657828160010160008282546128ba91906148ac565b92505081905550612941565b6002808111156128d9576128d86134c8565b5b60ff168460ff160361290557828160020160008282546128f991906148ac565b92505081905550612940565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161293790614e29565b60405180910390fd5b5b5b505050505050565b60008260000160109054906101000a9004600f0b90508183600101600083600f0b600f0b815260200190815260200160002081905550600181018360000160106101000a8154816fffffffffffffffffffffffffffffffff0219169083600f0b6fffffffffffffffffffffffffffffffff160217905550505050565b60008160000160009054906101000a9004600f0b600f0b8260000160109054906101000a9004600f0b600f0b13159050919050565b60008160000160006101000a8154816fffffffffffffffffffffffffffffffff0219169083600f0b6fffffffffffffffffffffffffffffffff16021790555060008160000160106101000a8154816fffffffffffffffffffffffffffffffff0219169083600f0b6fffffffffffffffffffffffffffffffff16021790555050565b600082511115612a8f5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ac39190612fa7565b60405180910390fd5b60008383834630604051602001612ae7959493929190614e49565b6040516020818303038152906040528051906020012090509392505050565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612b4f81612b1a565b8114612b5a57600080fd5b50565b600081359050612b6c81612b46565b92915050565b600060208284031215612b8857612b87612b10565b5b6000612b9684828501612b5d565b91505092915050565b60008115159050919050565b612bb481612b9f565b82525050565b6000602082019050612bcf6000830184612bab565b92915050565b6000819050919050565b612be881612bd5565b82525050565b6000602082019050612c036000830184612bdf565b92915050565b612c1281612bd5565b8114612c1d57600080fd5b50565b600081359050612c2f81612c09565b92915050565b600060ff82169050919050565b612c4b81612c35565b8114612c5657600080fd5b50565b600081359050612c6881612c42565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f840112612c9357612c92612c6e565b5b8235905067ffffffffffffffff811115612cb057612caf612c73565b5b602083019150836001820283011115612ccc57612ccb612c78565b5b9250929050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612d2182612cd8565b810181811067ffffffffffffffff82111715612d4057612d3f612ce9565b5b80604052505050565b6000612d53612b06565b9050612d5f8282612d18565b919050565b600067ffffffffffffffff821115612d7f57612d7e612ce9565b5b612d8882612cd8565b9050602081019050919050565b82818337600083830152505050565b6000612db7612db284612d64565b612d49565b905082815260208101848484011115612dd357612dd2612cd3565b5b612dde848285612d95565b509392505050565b600082601f830112612dfb57612dfa612c6e565b5b8135612e0b848260208601612da4565b91505092915050565b6000819050919050565b612e2781612e14565b8114612e3257600080fd5b50565b600081359050612e4481612e1e565b92915050565b60008060008060008060008060e0898b031215612e6a57612e69612b10565b5b6000612e788b828c01612c20565b9850506020612e898b828c01612c59565b975050604089013567ffffffffffffffff811115612eaa57612ea9612b15565b5b612eb68b828c01612c7d565b9650965050606089013567ffffffffffffffff811115612ed957612ed8612b15565b5b612ee58b828c01612de6565b9450506080612ef68b828c01612c59565b93505060a0612f078b828c01612e35565b92505060c0612f188b828c01612e35565b9150509295985092959890939650565b600081519050919050565b600082825260208201905092915050565b60005b83811015612f62578082015181840152602081019050612f47565b60008484015250505050565b6000612f7982612f28565b612f838185612f33565b9350612f93818560208601612f44565b612f9c81612cd8565b840191505092915050565b60006020820190508181036000830152612fc18184612f6e565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612ff482612fc9565b9050919050565b61300481612fe9565b811461300f57600080fd5b50565b60008135905061302181612ffb565b92915050565b6000806000806080858703121561304157613040612b10565b5b600061304f87828801613012565b945050602061306087828801613012565b935050604061307187828801612c20565b925050606085013567ffffffffffffffff81111561309257613091612b15565b5b61309e87828801612de6565b91505092959194509250565b6130b381612b1a565b82525050565b60006020820190506130ce60008301846130aa565b92915050565b600067ffffffffffffffff8211156130ef576130ee612ce9565b5b602082029050602081019050919050565b600061311361310e846130d4565b612d49565b9050808382526020820190506020840283018581111561313657613135612c78565b5b835b8181101561315f578061314b8882613012565b845260208401935050602081019050613138565b5050509392505050565b600082601f83011261317e5761317d612c6e565b5b813561318e848260208601613100565b91505092915050565b600067ffffffffffffffff8211156131b2576131b1612ce9565b5b602082029050602081019050919050565b60006131d66131d184613197565b612d49565b905080838252602082019050602084028301858111156131f9576131f8612c78565b5b835b81811015613222578061320e8882612c20565b8452602084019350506020810190506131fb565b5050509392505050565b600082601f83011261324157613240612c6e565b5b81356132518482602086016131c3565b91505092915050565b600067ffffffffffffffff82111561327557613274612ce9565b5b602082029050602081019050919050565b60006132996132948461325a565b612d49565b905080838252602082019050602084028301858111156132bc576132bb612c78565b5b835b8181101561330357803567ffffffffffffffff8111156132e1576132e0612c6e565b5b8086016132ee8982612de6565b855260208501945050506020810190506132be565b5050509392505050565b600082601f83011261332257613321612c6e565b5b8135613332848260208601613286565b91505092915050565b6000806000806080858703121561335557613354612b10565b5b600085013567ffffffffffffffff81111561337357613372612b15565b5b61337f87828801613169565b945050602085013567ffffffffffffffff8111156133a05761339f612b15565b5b6133ac8782880161322c565b935050604085013567ffffffffffffffff8111156133cd576133cc612b15565b5b6133d98782880161330d565b92505060606133ea87828801612e35565b91505092959194509250565b60006020828403121561340c5761340b612b10565b5b600061341a84828501612c20565b91505092915050565b61342c81612e14565b82525050565b60006020820190506134476000830184613423565b92915050565b600080600080600060a0868803121561346957613468612b10565b5b600061347788828901612c20565b955050602061348888828901612c59565b945050604061349988828901612c59565b93505060606134aa88828901612e35565b92505060806134bb88828901612e35565b9150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60088110613508576135076134c8565b5b50565b6000819050613519826134f7565b919050565b60006135298261350b565b9050919050565b6135398161351e565b82525050565b60006020820190506135546000830184613530565b92915050565b6000806040838503121561357157613570612b10565b5b600061357f85828601612c20565b925050602061359085828601613012565b9150509250929050565b60006060820190506135af6000830186612bdf565b6135bc6020830185612bdf565b6135c96040830184612bdf565b949350505050565b600080604083850312156135e8576135e7612b10565b5b60006135f685828601612c20565b925050602061360785828601612c59565b9150509250929050565b60008060008060006080868803121561362d5761362c612b10565b5b600061363b88828901612c20565b955050602061364c88828901612c59565b945050604086013567ffffffffffffffff81111561366d5761366c612b15565b5b61367988828901612c7d565b9350935050606086013567ffffffffffffffff81111561369c5761369b612b15565b5b6136a888828901612de6565b9150509295509295909350565b600080600080606085870312156136cf576136ce612b10565b5b60006136dd87828801612c20565b94505060206136ee87828801612c59565b935050604085013567ffffffffffffffff81111561370f5761370e612b15565b5b61371b87828801612c7d565b925092505092959194509250565b600067ffffffffffffffff82111561374457613743612ce9565b5b61374d82612cd8565b9050602081019050919050565b600061376d61376884613729565b612d49565b90508281526020810184848401111561378957613788612cd3565b5b613794848285612d95565b509392505050565b600082601f8301126137b1576137b0612c6e565b5b81356137c184826020860161375a565b91505092915050565b600080600080608085870312156137e4576137e3612b10565b5b600085013567ffffffffffffffff81111561380257613801612b15565b5b61380e87828801613169565b945050602085013567ffffffffffffffff81111561382f5761382e612b15565b5b61383b8782880161322c565b935050604085013567ffffffffffffffff81111561385c5761385b612b15565b5b6138688782880161330d565b925050606085013567ffffffffffffffff81111561388957613888612b15565b5b6138958782880161379c565b91505092959194509250565b6000806000606084860312156138ba576138b9612b10565b5b60006138c886828701613012565b93505060206138d986828701612c20565b925050604084013567ffffffffffffffff8111156138fa576138f9612b15565b5b61390686828701612de6565b9150509250925092565b600080600080600060a0868803121561392c5761392b612b10565b5b600061393a88828901613012565b955050602061394b88828901613012565b945050604086013567ffffffffffffffff81111561396c5761396b612b15565b5b6139788882890161322c565b935050606086013567ffffffffffffffff81111561399957613998612b15565b5b6139a58882890161322c565b925050608086013567ffffffffffffffff8111156139c6576139c5612b15565b5b6139d288828901612de6565b9150509295509295909350565b60008083601f8401126139f5576139f4612c6e565b5b8235905067ffffffffffffffff811115613a1257613a11612c73565b5b602083019150836001820283011115613a2e57613a2d612c78565b5b9250929050565b60008060008060608587031215613a4f57613a4e612b10565b5b6000613a5d87828801613012565b9450506020613a6e87828801612c20565b935050604085013567ffffffffffffffff811115613a8f57613a8e612b15565b5b613a9b878288016139df565b925092505092959194509250565b60008060408385031215613ac057613abf612b10565b5b6000613ace85828601613012565b9250506020613adf85828601612c20565b9150509250929050565b600080600080600060a08688031215613b0557613b04612b10565b5b6000613b1388828901613012565b9550506020613b2488828901613012565b9450506040613b3588828901612c20565b9350506060613b4688828901612c20565b925050608086013567ffffffffffffffff811115613b6757613b66612b15565b5b613b7388828901612de6565b9150509295509295909350565b6000819050919050565b6000613ba5613ba0613b9b84612fc9565b613b80565b612fc9565b9050919050565b6000613bb782613b8a565b9050919050565b6000613bc982613bac565b9050919050565b613bd981613bbe565b82525050565b6000602082019050613bf46000830184613bd0565b92915050565b600081905092915050565b6000613c118385613bfa565b9350613c1e838584612d95565b82840190509392505050565b6000613c37828486613c05565b91508190509392505050565b613c4c81612c35565b82525050565b600060a082019050613c676000830188613423565b613c746020830187612bdf565b613c816040830186613c43565b613c8e6060830185613423565b613c9b6080830184613423565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680613cec57607f821691505b602082108103613cff57613cfe613ca5565b5b50919050565b7f476f7665726e6f723a2070726f706f73616c206e6f742073756363657373667560008201527f6c00000000000000000000000000000000000000000000000000000000000000602082015250565b6000613d61602183612f33565b9150613d6c82613d05565b604082019050919050565b60006020820190508181036000830152613d9081613d54565b9050919050565b6000606082019050613dac6000830186613423565b613db96020830185612bdf565b613dc66040830184613c43565b949350505050565b7f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c206964000000600082015250565b6000613e04601d83612f33565b9150613e0f82613dce565b602082019050919050565b60006020820190508181036000830152613e3381613df7565b9050919050565b7f476f7665726e6f723a206f6e6c79476f7665726e616e63650000000000000000600082015250565b6000613e70601883612f33565b9150613e7b82613e3a565b602082019050919050565b60006020820190508181036000830152613e9f81613e63565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000613ee082612bd5565b9150613eeb83612bd5565b9250828203905081811115613f0357613f02613ea6565b5b92915050565b7f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f77207060008201527f726f706f73616c207468726573686f6c64000000000000000000000000000000602082015250565b6000613f65603183612f33565b9150613f7082613f09565b604082019050919050565b60006020820190508181036000830152613f9481613f58565b9050919050565b7f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e677460008201527f6800000000000000000000000000000000000000000000000000000000000000602082015250565b6000613ff7602183612f33565b915061400282613f9b565b604082019050919050565b6000602082019050818103600083015261402681613fea565b9050919050565b7f476f7665726e6f723a20656d7074792070726f706f73616c0000000000000000600082015250565b6000614063601883612f33565b915061406e8261402d565b602082019050919050565b6000602082019050818103600083015261409281614056565b9050919050565b7f476f7665726e6f723a2070726f706f73616c20616c726561647920657869737460008201527f7300000000000000000000000000000000000000000000000000000000000000602082015250565b60006140f5602183612f33565b915061410082614099565b604082019050919050565b60006020820190508181036000830152614124816140e8565b9050919050565b600067ffffffffffffffff82169050919050565b600061414a8261412b565b91506141558361412b565b9250828201905067ffffffffffffffff81111561417557614174613ea6565b5b92915050565b61418481612fe9565b82525050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6141bf81612fe9565b82525050565b60006141d183836141b6565b60208301905092915050565b6000602082019050919050565b60006141f58261418a565b6141ff8185614195565b935061420a836141a6565b8060005b8381101561423b57815161422288826141c5565b975061422d836141dd565b92505060018101905061420e565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61427d81612bd5565b82525050565b600061428f8383614274565b60208301905092915050565b6000602082019050919050565b60006142b382614248565b6142bd8185614253565b93506142c883614264565b8060005b838110156142f95781516142e08882614283565b97506142eb8361429b565b9250506001810190506142cc565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600082825260208201905092915050565b600061434e82612f28565b6143588185614332565b9350614368818560208601612f44565b61437181612cd8565b840191505092915050565b60006143888383614343565b905092915050565b6000602082019050919050565b60006143a882614306565b6143b28185614311565b9350836020820285016143c485614322565b8060005b8581101561440057848403895281516143e1858261437c565b94506143ec83614390565b925060208a019950506001810190506143c8565b50829750879550505050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b60006144658261443e565b61446f8185614449565b935061447f818560208601612f44565b61448881612cd8565b840191505092915050565b600061449f838361445a565b905092915050565b6000602082019050919050565b60006144bf82614412565b6144c9818561441d565b9350836020820285016144db8561442e565b8060005b8581101561451757848403895281516144f88582614493565b9450614503836144a7565b925060208a019950506001810190506144df565b50829750879550505050505092915050565b600061454461453f61453a8461412b565b613b80565b612bd5565b9050919050565b61455481614529565b82525050565b600061012082019050614570600083018c612bdf565b61457d602083018b61417b565b818103604083015261458f818a6141ea565b905081810360608301526145a381896142a8565b905081810360808301526145b7818861439d565b905081810360a08301526145cb81876144b4565b90506145da60c083018661454b565b6145e760e083018561454b565b8181036101008301526145fa8184612f6e565b90509a9950505050505050505050565b6000608082019050818103600083015261462481876141ea565b9050818103602083015261463881866142a8565b9050818103604083015261464c81856144b4565b905061465b6060830184613423565b95945050505050565b7f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460008201527f6976650000000000000000000000000000000000000000000000000000000000602082015250565b60006146c0602383612f33565b91506146cb82614664565b604082019050919050565b600060208201905081810360008301526146ef816146b3565b9050919050565b600060808201905061470b6000830187612bdf565b6147186020830186613c43565b6147256040830185612bdf565b81810360608301526147378184612f6e565b905095945050505050565b600082825260208201905092915050565b600061475e8261443e565b6147688185614742565b9350614778818560208601612f44565b61478181612cd8565b840191505092915050565b600060a0820190506147a16000830188612bdf565b6147ae6020830187613c43565b6147bb6040830186612bdf565b81810360608301526147cd8185612f6e565b905081810360808301526147e18184614753565b90509695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600061482782612bd5565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361485957614858613ea6565b5b600182019050919050565b600061486f8261443e565b6148798185613bfa565b9350614889818560208601612f44565b80840191505092915050565b60006148a18284614864565b915081905092915050565b60006148b782612bd5565b91506148c283612bd5565b92508282019050808211156148da576148d9613ea6565b5b92915050565b60006040820190506148f56000830185612bdf565b6149026020830184612bdf565b9392505050565b7f53616665436173743a2076616c756520646f65736e27742066697420696e203660008201527f3420626974730000000000000000000000000000000000000000000000000000602082015250565b6000614965602683612f33565b915061497082614909565b604082019050919050565b6000602082019050818103600083015261499481614958565b9050919050565b60006040820190506149b0600083018561417b565b6149bd6020830184612bdf565b9392505050565b60006bffffffffffffffffffffffff82169050919050565b6149e5816149c4565b81146149f057600080fd5b50565b600081519050614a02816149dc565b92915050565b600060208284031215614a1e57614a1d612b10565b5b6000614a2c848285016149f3565b91505092915050565b7f476f7665726e6f7253657474696e67733a20766f74696e6720706572696f642060008201527f746f6f206c6f7700000000000000000000000000000000000000000000000000602082015250565b6000614a91602783612f33565b9150614a9c82614a35565b604082019050919050565b60006020820190508181036000830152614ac081614a84565b9050919050565b600081905092915050565b7f1901000000000000000000000000000000000000000000000000000000000000600082015250565b6000614b08600283614ac7565b9150614b1382614ad2565b600282019050919050565b6000819050919050565b614b39614b3482612e14565b614b1e565b82525050565b6000614b4a82614afb565b9150614b568285614b28565b602082019150614b668284614b28565b6020820191508190509392505050565b6000608082019050614b8b6000830187613423565b614b986020830186613c43565b614ba56040830185613423565b614bb26060830184613423565b95945050505050565b7f45434453413a20696e76616c6964207369676e61747572650000000000000000600082015250565b6000614bf1601883612f33565b9150614bfc82614bbb565b602082019050919050565b60006020820190508181036000830152614c2081614be4565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265206c656e67746800600082015250565b6000614c5d601f83612f33565b9150614c6882614c27565b602082019050919050565b60006020820190508181036000830152614c8c81614c50565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265202773272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b6000614cef602283612f33565b9150614cfa82614c93565b604082019050919050565b60006020820190508181036000830152614d1e81614ce2565b9050919050565b7f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c72656160008201527f6479206361737400000000000000000000000000000000000000000000000000602082015250565b6000614d81602783612f33565b9150614d8c82614d25565b604082019050919050565b60006020820190508181036000830152614db081614d74565b9050919050565b7f476f7665726e6f72566f74696e6753696d706c653a20696e76616c696420766160008201527f6c756520666f7220656e756d20566f7465547970650000000000000000000000602082015250565b6000614e13603583612f33565b9150614e1e82614db7565b604082019050919050565b60006020820190508181036000830152614e4281614e06565b9050919050565b600060a082019050614e5e6000830188613423565b614e6b6020830187613423565b614e786040830186613423565b614e856060830185612bdf565b614e92608083018461417b565b969550505050505056fe476f7665726e6f723a2072656c617920726576657274656420776974686f7574206d657373616765476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765a264697066735822122007d0065dfa1b0b6d01e855d84d3bda7886cec984eb729e8e1da32f15f3ffd0d564736f6c63430008110033

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

0000000000000000000000003446dd70b2d52a6bf4a5a192d9b0a161295ab7f9

-----Decoded View---------------
Arg [0] : _token (address): 0x3446Dd70B2D52A6Bf4a5a192D9b0A161295aB7F9

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000003446dd70b2d52a6bf4a5a192d9b0a161295ab7f9


Deployed Bytecode Sourcemap

163765:1039:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;100897:4;100874:28;;:11;:9;:11::i;:::-;:28;;;100866:37;;;;;;163765:1039;;;;;100983:750;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;164426:179;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;113859:811;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;101794:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;117493:207;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;108108:889;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;104415:165;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;98438:148;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;164241:177;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;113329:441;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;103396:946;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;122950:169;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;123196:401;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;101958:101;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;112306:201;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;112939:320;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;120065:128;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;112582:273;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;106597:1447;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;112008:233;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;164613:188;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;118094:255;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;104653:163;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;116787:333;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;103019:315;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;122747:138;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;98336:95;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;120375:132;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;111755:178;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;120699:152;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;117781:227;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;164063:100;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;163282:37;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;117314:100;117366:7;117401:4;117386:20;;117314:100;:::o;100983:750::-;101085:4;101514:32;;;101448:46;;;101387:41;;;101340:27;:88;:154;:206;101311:236;;;:11;:236;;;;:295;;;;101579:27;101564:42;;;:11;:42;;;;101311:295;:361;;;;101638:34;101623:49;;;:11;:49;;;;101311:361;:414;;;;101689:36;101713:11;101689:23;:36::i;:::-;101311:414;101291:434;;100983:750;;;:::o;164426:179::-;164545:7;164577:20;:18;:20::i;:::-;164570:27;;164426:179;:::o;113859:811::-;114115:7;114135:13;114151:438;114179:351;98498:88;114334:10;114371:7;114421:6;;114405:24;;;;;;;:::i;:::-;;;;;;;;114466:6;114456:17;;;;;;114246:250;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;114214:301;;;;;;114179:16;:351::i;:::-;114545:1;114561;114577;114151:13;:438::i;:::-;114135:454;;114609:53;114619:10;114631:5;114638:7;114647:6;;114609:53;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;114655:6;114609:9;:53::i;:::-;114602:60;;;113859:811;;;;;;;;;;:::o;101794:100::-;101848:13;101881:5;101874:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;101794:100;:::o;117493:207::-;117636:6;117662:30;;;117655:37;;117493:207;;;;;;:::o;108108:889::-;108311:7;108331:18;108352:57;108365:7;108374:6;108382:9;108393:15;108352:12;:57::i;:::-;108331:78;;108422:20;108445:17;108451:10;108445:5;:17::i;:::-;108422:40;;108505:23;108495:33;;;;;;;;:::i;:::-;;:6;:33;;;;;;;;:::i;:::-;;;:67;;;;108542:20;108532:30;;;;;;;;:::i;:::-;;:6;:30;;;;;;;;:::i;:::-;;;108495:67;108473:150;;;;;;;;;;;;:::i;:::-;;;;;;;;;108668:4;108634:10;:22;108645:10;108634:22;;;;;;;;;;;:31;;;:38;;;;;;;;;;;;;;;;;;108690:28;108707:10;108690:28;;;;;;:::i;:::-;;;;;;;;108731:71;108746:10;108758:7;108767:6;108775:9;108786:15;108731:14;:71::i;:::-;108813:65;108822:10;108834:7;108843:6;108851:9;108862:15;108813:8;:65::i;:::-;108889:70;108903:10;108915:7;108924:6;108932:9;108943:15;108889:13;:70::i;:::-;108979:10;108972:17;;;;108108:889;;;;;;:::o;104415:165::-;104499:7;104526:46;:10;:22;104537:10;104526:22;;;;;;;;;;;:32;;:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:46::i;:::-;104519:53;;;;104415:165;;;:::o;98438:148::-;98498:88;98438:148;:::o;164241:177::-;164359:7;164391:19;:17;:19::i;:::-;164384:26;;164241:177;:::o;113329:441::-;113503:7;113523:13;113539:164;113567:77;98378:53;113622:10;113634:7;113594:48;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;113584:59;;;;;;113567:16;:77::i;:::-;113659:1;113675;113691;113539:13;:164::i;:::-;113523:180;;113721:41;113731:10;113743:5;113750:7;113721:41;;;;;;;;;;;;:9;:41::i;:::-;113714:48;;;113329:441;;;;;;;:::o;103396:946::-;103469:13;103495:29;103527:10;:22;103538:10;103527:22;;;;;;;;;;;103495:54;;103566:8;:17;;;;;;;;;;;;103562:79;;;103607:22;103600:29;;;;;103562:79;103657:8;:17;;;;;;;;;;;;103653:79;;;103698:22;103691:29;;;;;103653:79;103744:16;103763:28;103780:10;103763:16;:28::i;:::-;103744:47;;103820:1;103808:8;:13;103804:85;;103838:39;;;;;;;;;;:::i;:::-;;;;;;;;103804:85;103917:12;103905:8;:24;103901:85;;103953:21;103946:28;;;;;;103901:85;103998:16;104017:28;104034:10;104017:16;:28::i;:::-;103998:47;;104074:12;104062:8;:24;104058:84;;104110:20;104103:27;;;;;;;104058:84;104158:26;104173:10;104158:14;:26::i;:::-;:56;;;;;104188:26;104203:10;104188:14;:26::i;:::-;104158:56;104154:181;;;104238:23;104231:30;;;;;;;104154:181;104301:22;104294:29;;;;;103396:946;;;;:::o;122950:169::-;123043:4;123067:14;:26;123082:10;123067:26;;;;;;;;;;;:35;;:44;123103:7;123067:44;;;;;;;;;;;;;;;;;;;;;;;;;123060:51;;122950:169;;;;:::o;123196:401::-;123318:20;123353:16;123384:20;123432:33;123468:14;:26;123483:10;123468:26;;;;;;;;;;;123432:62;;123513:12;:25;;;123540:12;:21;;;123563:12;:25;;;123505:84;;;;;;;123196:401;;;;;:::o;101958:101::-;102015:13;102041:10;;;;;;;;;;;;;;;;;;;101958:101;:::o;112306:201::-;112392:7;112412:13;112428:12;:10;:12::i;:::-;112412:28;;112458:41;112468:10;112480:5;112487:7;112458:41;;;;;;;;;;;;:9;:41::i;:::-;112451:48;;;112306:201;;;;:::o;112939:320::-;113132:7;113152:13;113168:12;:10;:12::i;:::-;113152:28;;113198:53;113208:10;113220:5;113227:7;113236:6;;113198:53;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;113244:6;113198:9;:53::i;:::-;113191:60;;;112939:320;;;;;;;:::o;120065:128::-;100151:11;:9;:11::i;:::-;100135:27;;:12;:10;:12::i;:::-;:27;;;100127:64;;;;;;;;;;;;:::i;:::-;;;;;;;;;100229:4;100206:28;;:11;:9;:11::i;:::-;:28;;;100202:281;;100251:19;100283:10;:8;:10::i;:::-;100273:21;;;;;;;:::i;:::-;;;;;;;;100251:43;;100420:52;100457:11;100427:26;:15;:24;:26::i;:::-;:41;100420:52;;100236:247;100202:281;120154:31:::1;120170:14;120154:15;:31::i;:::-;120065:128:::0;:::o;112582:273::-;112736:7;112756:13;112772:12;:10;:12::i;:::-;112756:28;;112802:45;112812:10;112824:5;112831:7;112840:6;;112802:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:9;:45::i;:::-;112795:52;;;112582:273;;;;;;:::o;106597:1447::-;106794:7;106880:19;:17;:19::i;:::-;106836:40;106845:12;:10;:12::i;:::-;106874:1;106859:12;:16;;;;:::i;:::-;106836:8;:40::i;:::-;:63;;106814:162;;;;;;;;;;;;:::i;:::-;;;;;;;;;106989:18;107010:71;107023:7;107032:6;107040:9;107067:11;107051:29;;;;;;107010:12;:71::i;:::-;106989:92;;107120:6;:13;107102:7;:14;:31;107094:77;;;;;;;;;;;;:::i;:::-;;;;;;;;;107208:9;:16;107190:7;:14;:34;107182:80;;;;;;;;;;;;:::i;:::-;;;;;;;;;107298:1;107281:7;:14;:18;107273:55;;;;;;;;;;;;:::i;:::-;;;;;;;;;107341:29;107373:10;:22;107384:10;107373:22;;;;;;;;;;;107341:54;;107414:28;:8;:18;;:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:28::i;:::-;107406:74;;;;;;;;;;;;:::i;:::-;;;;;;;;;107493:15;107537:24;:13;:11;:13::i;:::-;:22;:24::i;:::-;107511:23;:12;:21;:23::i;:::-;:50;;;;:::i;:::-;107493:68;;107572:15;107601:25;:14;:12;:14::i;:::-;:23;:25::i;:::-;107590:8;:36;;;;:::i;:::-;107572:54;;107639:40;107670:8;107639;:18;;:30;;:40;;;;:::i;:::-;107690:38;107719:8;107690;:16;;:28;;:38;;;;:::i;:::-;107746:260;107776:10;107801:12;:10;:12::i;:::-;107828:7;107850:6;107884:7;:14;107871:28;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;107914:9;107938:8;107961;107984:11;107746:260;;;;;;;;;;;;;;:::i;:::-;;;;;;;;108026:10;108019:17;;;;;;106597:1447;;;;;;:::o;112008:233::-;112167:7;112194:39;112204:7;112213:11;112226:6;112194:9;:39::i;:::-;112187:46;;112008:233;;;;;:::o;164613:188::-;164736:7;164768:25;:23;:25::i;:::-;164761:32;;164613:188;:::o;118094:255::-;118279:6;118305:36;;;118298:43;;118094:255;;;;;;;:::o;104653:163::-;104737:7;104764:44;:10;:22;104775:10;104764:22;;;;;;;;;;;:30;;:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:44::i;:::-;104757:51;;;;104653:163;;;:::o;116787:333::-;100151:11;:9;:11::i;:::-;100135:27;;:12;:10;:12::i;:::-;:27;;;100127:64;;;;;;;;;;;;:::i;:::-;;;;;;;;;100229:4;100206:28;;:11;:9;:11::i;:::-;:28;;;100202:281;;100251:19;100283:10;:8;:10::i;:::-;100273:21;;;;;;;:::i;:::-;;;;;;;;100251:43;;100420:52;100457:11;100427:26;:15;:24;:26::i;:::-;:41;100420:52;;100236:247;100202:281;116940:12:::1;116954:23:::0;116981:6:::1;:11;;117000:5;117007:4;;116981:31;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;116939:73;;;;117023:89;117048:7;117057:10;117023:89;;;;;;;;;;;;;;;;;:24;:89::i;:::-;;116928:192;;116787:333:::0;;;;:::o;103019:315::-;103224:7;103280;103289:6;103297:9;103308:15;103269:55;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;103259:66;;;;;;103251:75;;103244:82;;103019:315;;;;;;:::o;122747:138::-;122810:13;122836:41;;;;;;;;;;;;;;;;;;;122747:138;:::o;98336:95::-;98378:53;98336:95;:::o;120375:132::-;100151:11;:9;:11::i;:::-;100135:27;;:12;:10;:12::i;:::-;:27;;;100127:64;;;;;;;;;;;;:::i;:::-;;;;;;;;;100229:4;100206:28;;:11;:9;:11::i;:::-;:28;;;100202:281;;100251:19;100283:10;:8;:10::i;:::-;100273:21;;;;;;;:::i;:::-;;;;;;;;100251:43;;100420:52;100457:11;100427:26;:15;:24;:26::i;:::-;:41;100420:52;;100236:247;100202:281;120466:33:::1;120483:15;120466:16;:33::i;:::-;120375:132:::0;:::o;111755:178::-;111849:7;111876:49;111886:7;111895:11;111908:16;:14;:16::i;:::-;111876:9;:49::i;:::-;111869:56;;111755:178;;;;:::o;120699:152::-;100151:11;:9;:11::i;:::-;100135:27;;:12;:10;:12::i;:::-;:27;;;100127:64;;;;;;;;;;;;:::i;:::-;;;;;;;;;100229:4;100206:28;;:11;:9;:11::i;:::-;:28;;;100202:281;;100251:19;100283:10;:8;:10::i;:::-;100273:21;;;;;;;:::i;:::-;;;;;;;;100251:43;;100420:52;100457:11;100427:26;:15;:24;:26::i;:::-;:41;100420:52;;100236:247;100202:281;120800:43:::1;120822:20;120800:21;:43::i;:::-;120699:152:::0;:::o;117781:227::-;117943:6;117969:31;;;117962:38;;117781:227;;;;;;;:::o;164063:100::-;164118:7;164145:10;164138:17;;164063:100;;;:::o;163282:37::-;;;:::o;33362:157::-;33447:4;33486:25;33471:40;;;:11;:40;;;;33464:47;;33362:157;;;:::o;119582:110::-;119644:7;119671:13;;119664:20;;119582:110;:::o;32421:167::-;32498:7;32525:55;32547:20;:18;:20::i;:::-;32569:10;32525:21;:55::i;:::-;32518:62;;32421:167;;;:::o;26164:279::-;26292:7;26313:17;26332:18;26354:25;26365:4;26371:1;26374;26377;26354:10;:25::i;:::-;26312:67;;;;26390:18;26402:5;26390:11;:18::i;:::-;26426:9;26419:16;;;;26164:279;;;;;;:::o;115539:789::-;115731:7;115751:29;115783:10;:22;115794:10;115783:22;;;;;;;;;;;115751:54;;115845:20;115824:41;;;;;;;;:::i;:::-;;:17;115830:10;115824:5;:17::i;:::-;:41;;;;;;;;:::i;:::-;;;115816:89;;;;;;;;;;;;:::i;:::-;;;;;;;;;115918:14;115935:60;115945:7;115954:32;:8;:18;;:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:32::i;:::-;115935:60;;115988:6;115935:9;:60::i;:::-;115918:77;;116006:56;116017:10;116029:7;116038;116047:6;116055;116006:10;:56::i;:::-;116096:1;116079:6;:13;:18;116075:220;;116128:7;116119:54;;;116137:10;116149:7;116158:6;116166;116119:54;;;;;;;;;:::i;:::-;;;;;;;;116075:220;;;116230:7;116211:72;;;116239:10;116251:7;116260:6;116268;116276;116211:72;;;;;;;;;;:::i;:::-;;;;;;;;116075:220;116314:6;116307:13;;;;115539:789;;;;;;;:::o;109755:513::-;110024:4;110001:28;;:11;:9;:11::i;:::-;:28;;;109997:264;;110051:9;110046:204;110070:7;:14;110066:1;:18;110046:204;;;110136:4;110114:27;;:7;110122:1;110114:10;;;;;;;;:::i;:::-;;;;;;;;:27;;;110110:125;;110166:49;110201:9;110211:1;110201:12;;;;;;;;:::i;:::-;;;;;;;;110191:23;;;;;;110166:15;:24;;:49;;;;:::i;:::-;110110:125;110086:3;;;;:::i;:::-;;;110046:204;;;;109997:264;109755:513;;;;;:::o;109127:553::-;109357:26;:70;;;;;;;;;;;;;;;;;;;109443:9;109438:235;109462:7;:14;109458:1;:18;109438:235;;;109499:12;109513:23;109540:7;109548:1;109540:10;;;;;;;;:::i;:::-;;;;;;;;:15;;109563:6;109570:1;109563:9;;;;;;;;:::i;:::-;;;;;;;;109574;109584:1;109574:12;;;;;;;;:::i;:::-;;;;;;;;109540:47;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;109498:89;;;;109602:59;109627:7;109636:10;109648:12;109602:24;:59::i;:::-;;109483:190;;109478:3;;;;:::i;:::-;;;109438:235;;;;109346:334;109127:553;;;;;:::o;110342:408::-;110622:4;110599:28;;:11;:9;:11::i;:::-;:28;;;110595:148;;110649:23;:15;:21;:23::i;:::-;110644:88;;110693:23;:15;:21;:23::i;:::-;110644:88;110595:148;110342:408;;;;;:::o;86977:119::-;87047:6;87073:5;:15;;;87066:22;;86977:119;;;:::o;119405:108::-;119466:7;119493:12;;119486:19;;119405:108;:::o;114987:262::-;115149:7;115176:65;115186:10;115198:7;115207;115216:6;115224:16;:14;:16::i;:::-;115176:9;:65::i;:::-;115169:72;;114987:262;;;;;;:::o;123667:280::-;123751:4;123768:33;123804:14;:26;123819:10;123804:26;;;;;;;;;;;123768:62;;123914:12;:25;;;123890:12;:21;;;:49;;;;:::i;:::-;123850:36;123857:28;123874:10;123857:16;:28::i;:::-;123850:6;:36::i;:::-;:89;;123843:96;;;123667:280;;;:::o;124086:240::-;124170:4;124187:33;124223:14;:26;124238:10;124223:26;;;;;;;;;;;124187:62;;124293:12;:25;;;124269:12;:21;;;:49;124262:56;;;124086:240;;;:::o;85608:98::-;85661:7;85688:10;85681:17;;85608:98;:::o;85714:101::-;85765:14;;85799:8;;85792:15;;;;85714:101;;:::o;72973:332::-;73037:13;73067:12;73073:5;73067;:12::i;:::-;73063:32;;;73088:7;;;;;;;;;;;;;;73063:32;73106:17;73126:5;:12;;;;;;;;;;;;73106:32;;73157:5;:11;;:23;73169:10;73157:23;;;;;;;;;;;;;;;;73149:31;;73198:5;:11;;:23;73210:10;73198:23;;;;;;;;;;;;;;;73191:30;;;73285:1;73272:10;:14;73257:5;:12;;;:29;;;;;;;;;;;;;;;;;;;;73052:253;72973:332;;;:::o;120976:174::-;121058:44;121073:12;;121087:14;121058:44;;;;;;;:::i;:::-;;;;;;;;121128:14;121113:12;:29;;;;120976:174;:::o;87330:118::-;87396:4;87439:1;87420:5;:15;;;:20;;;87413:27;;87330:118;;;:::o;47107:190::-;47163:6;47199:16;47190:25;;:5;:25;;47182:76;;;;;;;;;;;;:::i;:::-;;;;;;;;;47283:5;47269:20;;47107:190;;;:::o;87104:121::-;87208:9;87190:5;:15;;;:27;;;;;;;;;;;;;;;;;;87104:121;;:::o;163526:232::-;163682:7;163709:5;:19;;;163729:7;163738:11;163709:41;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;163702:48;;;;163526:232;;;;;:::o;119765:120::-;119832:7;119859:18;;119852:25;;119765:120;:::o;84140:305::-;84290:12;84319:7;84315:123;;;84350:10;84343:17;;;;84315:123;84393:33;84401:10;84413:12;84393:7;:33::i;:::-;84140:305;;;;;;:::o;121277:321::-;121440:1;121422:15;:19;121414:71;;;;;;;;;;;;:::i;:::-;;;;;;;;;121501:47;121517:13;;121532:15;121501:47;;;;;;;:::i;:::-;;;;;;;;121575:15;121559:13;:31;;;;121277:321;:::o;106434:99::-;106491:12;106516:9;;;;;;;;;;;;;;106434:99;:::o;121735:216::-;121829:62;121850:18;;121870:20;121829:62;;;;;;;:::i;:::-;;;;;;;;121923:20;121902:18;:41;;;;121735:216;:::o;31194:314::-;31247:7;31288:12;31271:29;;31279:4;31271:29;;;:66;;;;;31321:16;31304:13;:33;31271:66;31267:234;;;31361:24;31354:31;;;;31267:234;31425:64;31447:10;31459:12;31473:15;31425:21;:64::i;:::-;31418:71;;31194:314;;:::o;27855:196::-;27948:7;28014:15;28031:10;27985:57;;;;;;;;;:::i;:::-;;;;;;;;;;;;;27975:68;;;;;;27968:75;;27855:196;;;;:::o;24505:1520::-;24636:7;24645:12;25570:66;25565:1;25557:10;;:79;25553:163;;;25669:1;25673:30;25653:51;;;;;;25553:163;25813:14;25830:24;25840:4;25846:1;25849;25852;25830:24;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;25813:41;;25887:1;25869:20;;:6;:20;;;25865:103;;25922:1;25926:29;25906:50;;;;;;;25865:103;25988:6;25996:20;25980:37;;;;;24505:1520;;;;;;;;:::o;19897:521::-;19975:20;19966:29;;;;;;;;:::i;:::-;;:5;:29;;;;;;;;:::i;:::-;;;19962:449;20012:7;19962:449;20073:29;20064:38;;;;;;;;:::i;:::-;;:5;:38;;;;;;;;:::i;:::-;;;20060:351;;20119:34;;;;;;;;;;:::i;:::-;;;;;;;;20060:351;20184:35;20175:44;;;;;;;;:::i;:::-;;:5;:44;;;;;;;;:::i;:::-;;;20171:240;;20236:41;;;;;;;;;;:::i;:::-;;;;;;;;20171:240;20308:30;20299:39;;;;;;;;:::i;:::-;;:5;:39;;;;;;;;:::i;:::-;;;20295:116;;20355:44;;;;;;;;;;:::i;:::-;;;;;;;;20295:116;19897:521;;:::o;124471:833::-;124672:33;124708:14;:26;124723:10;124708:26;;;;;;;;;;;124672:62;;124756:12;:21;;:30;124778:7;124756:30;;;;;;;;;;;;;;;;;;;;;;;;;124755:31;124747:83;;;;;;;;;;;;:::i;:::-;;;;;;;;;124874:4;124841:12;:21;;:30;124863:7;124841:30;;;;;;;;;;;;;;;;:37;;;;;;;;;;;;;;;;;;124912:16;124906:23;;;;;;;;:::i;:::-;;124895:34;;:7;:34;;;124891:406;;124975:6;124946:12;:25;;;:35;;;;;;;:::i;:::-;;;;;;;;124891:406;;;125020:12;125014:19;;;;;;;;:::i;:::-;;125003:30;;:7;:30;;;124999:298;;125075:6;125050:12;:21;;;:31;;;;;;;:::i;:::-;;;;;;;;124999:298;;;125120:16;125114:23;;;;;;;;:::i;:::-;;125103:34;;:7;:34;;;125099:198;;125183:6;125154:12;:25;;;:35;;;;;;;:::i;:::-;;;;;;;;125099:198;;;125222:63;;;;;;;;;;:::i;:::-;;;;;;;;125099:198;124999:298;124891:406;124661:643;124471:833;;;;;:::o;71733:232::-;71814:16;71833:5;:10;;;;;;;;;;;;71814:29;;71879:5;71854;:11;;:22;71866:9;71854:22;;;;;;;;;;;;;;;:30;;;;71945:1;71933:9;:13;71920:5;:10;;;:26;;;;;;;;;;;;;;;;;;;;71803:162;71733:232;;:::o;75536:124::-;75602:4;75640:5;:12;;;;;;;;;;;;75626:26;;:5;:10;;;;;;;;;;;;:26;;;;75619:33;;75536:124;;;:::o;74899:112::-;74977:1;74962:5;:12;;;:16;;;;;;;;;;;;;;;;;;;;75002:1;74989:5;:10;;;:14;;;;;;;;;;;;;;;;;;;;74899:112;:::o;84453:552::-;84634:1;84614:10;:17;:21;84610:388;;;84846:10;84840:17;84903:15;84890:10;84886:2;84882:19;84875:44;84610:388;84973:12;84966:20;;;;;;;;;;;:::i;:::-;;;;;;;;31516:263;31660:7;31708:8;31718;31728:11;31741:13;31764:4;31697:73;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;31687:84;;;;;;31680:91;;31516:263;;;;;:::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:77::-;1555:7;1584:5;1573:16;;1518:77;;;:::o;1601:118::-;1688:24;1706:5;1688:24;:::i;:::-;1683:3;1676:37;1601:118;;:::o;1725:222::-;1818:4;1856:2;1845:9;1841:18;1833:26;;1869:71;1937:1;1926:9;1922:17;1913:6;1869:71;:::i;:::-;1725:222;;;;:::o;1953:122::-;2026:24;2044:5;2026:24;:::i;:::-;2019:5;2016:35;2006:63;;2065:1;2062;2055:12;2006:63;1953:122;:::o;2081:139::-;2127:5;2165:6;2152:20;2143:29;;2181:33;2208:5;2181:33;:::i;:::-;2081:139;;;;:::o;2226:86::-;2261:7;2301:4;2294:5;2290:16;2279:27;;2226:86;;;:::o;2318:118::-;2389:22;2405:5;2389:22;:::i;:::-;2382:5;2379:33;2369:61;;2426:1;2423;2416:12;2369:61;2318:118;:::o;2442:135::-;2486:5;2524:6;2511:20;2502:29;;2540:31;2565:5;2540:31;:::i;:::-;2442:135;;;;:::o;2583:117::-;2692:1;2689;2682:12;2706:117;2815:1;2812;2805:12;2829:117;2938:1;2935;2928:12;2966:553;3024:8;3034:6;3084:3;3077:4;3069:6;3065:17;3061:27;3051:122;;3092:79;;:::i;:::-;3051:122;3205:6;3192:20;3182:30;;3235:18;3227:6;3224:30;3221:117;;;3257:79;;:::i;:::-;3221:117;3371:4;3363:6;3359:17;3347:29;;3425:3;3417:4;3409:6;3405:17;3395:8;3391:32;3388:41;3385:128;;;3432:79;;:::i;:::-;3385:128;2966:553;;;;;:::o;3525:117::-;3634:1;3631;3624:12;3648:102;3689:6;3740:2;3736:7;3731:2;3724:5;3720:14;3716:28;3706:38;;3648:102;;;:::o;3756:180::-;3804:77;3801:1;3794:88;3901:4;3898:1;3891:15;3925:4;3922:1;3915:15;3942:281;4025:27;4047:4;4025:27;:::i;:::-;4017:6;4013:40;4155:6;4143:10;4140:22;4119:18;4107:10;4104:34;4101:62;4098:88;;;4166:18;;:::i;:::-;4098:88;4206:10;4202:2;4195:22;3985:238;3942:281;;:::o;4229:129::-;4263:6;4290:20;;:::i;:::-;4280:30;;4319:33;4347:4;4339:6;4319:33;:::i;:::-;4229:129;;;:::o;4364:307::-;4425:4;4515:18;4507:6;4504:30;4501:56;;;4537:18;;:::i;:::-;4501:56;4575:29;4597:6;4575:29;:::i;:::-;4567:37;;4659:4;4653;4649:15;4641:23;;4364:307;;;:::o;4677:146::-;4774:6;4769:3;4764;4751:30;4815:1;4806:6;4801:3;4797:16;4790:27;4677:146;;;:::o;4829:423::-;4906:5;4931:65;4947:48;4988:6;4947:48;:::i;:::-;4931:65;:::i;:::-;4922:74;;5019:6;5012:5;5005:21;5057:4;5050:5;5046:16;5095:3;5086:6;5081:3;5077:16;5074:25;5071:112;;;5102:79;;:::i;:::-;5071:112;5192:54;5239:6;5234:3;5229;5192:54;:::i;:::-;4912:340;4829:423;;;;;:::o;5271:338::-;5326:5;5375:3;5368:4;5360:6;5356:17;5352:27;5342:122;;5383:79;;:::i;:::-;5342:122;5500:6;5487:20;5525:78;5599:3;5591:6;5584:4;5576:6;5572:17;5525:78;:::i;:::-;5516:87;;5332:277;5271:338;;;;:::o;5615:77::-;5652:7;5681:5;5670:16;;5615:77;;;:::o;5698:122::-;5771:24;5789:5;5771:24;:::i;:::-;5764:5;5761:35;5751:63;;5810:1;5807;5800:12;5751:63;5698:122;:::o;5826:139::-;5872:5;5910:6;5897:20;5888:29;;5926:33;5953:5;5926:33;:::i;:::-;5826:139;;;;:::o;5971:1573::-;6101:6;6109;6117;6125;6133;6141;6149;6157;6206:3;6194:9;6185:7;6181:23;6177:33;6174:120;;;6213:79;;:::i;:::-;6174:120;6333:1;6358:53;6403:7;6394:6;6383:9;6379:22;6358:53;:::i;:::-;6348:63;;6304:117;6460:2;6486:51;6529:7;6520:6;6509:9;6505:22;6486:51;:::i;:::-;6476:61;;6431:116;6614:2;6603:9;6599:18;6586:32;6645:18;6637:6;6634:30;6631:117;;;6667:79;;:::i;:::-;6631:117;6780:65;6837:7;6828:6;6817:9;6813:22;6780:65;:::i;:::-;6762:83;;;;6557:298;6922:2;6911:9;6907:18;6894:32;6953:18;6945:6;6942:30;6939:117;;;6975:79;;:::i;:::-;6939:117;7080:62;7134:7;7125:6;7114:9;7110:22;7080:62;:::i;:::-;7070:72;;6865:287;7191:3;7218:51;7261:7;7252:6;7241:9;7237:22;7218:51;:::i;:::-;7208:61;;7162:117;7318:3;7345:53;7390:7;7381:6;7370:9;7366:22;7345:53;:::i;:::-;7335:63;;7289:119;7447:3;7474:53;7519:7;7510:6;7499:9;7495:22;7474:53;:::i;:::-;7464:63;;7418:119;5971:1573;;;;;;;;;;;:::o;7550:99::-;7602:6;7636:5;7630:12;7620:22;;7550:99;;;:::o;7655:169::-;7739:11;7773:6;7768:3;7761:19;7813:4;7808:3;7804:14;7789:29;;7655:169;;;;:::o;7830:246::-;7911:1;7921:113;7935:6;7932:1;7929:13;7921:113;;;8020:1;8015:3;8011:11;8005:18;8001:1;7996:3;7992:11;7985:39;7957:2;7954:1;7950:10;7945:15;;7921:113;;;8068:1;8059:6;8054:3;8050:16;8043:27;7892:184;7830:246;;;:::o;8082:377::-;8170:3;8198:39;8231:5;8198:39;:::i;:::-;8253:71;8317:6;8312:3;8253:71;:::i;:::-;8246:78;;8333:65;8391:6;8386:3;8379:4;8372:5;8368:16;8333:65;:::i;:::-;8423:29;8445:6;8423:29;:::i;:::-;8418:3;8414:39;8407:46;;8174:285;8082:377;;;;:::o;8465:313::-;8578:4;8616:2;8605:9;8601:18;8593:26;;8665:9;8659:4;8655:20;8651:1;8640:9;8636:17;8629:47;8693:78;8766:4;8757:6;8693:78;:::i;:::-;8685:86;;8465:313;;;;:::o;8784:126::-;8821:7;8861:42;8854:5;8850:54;8839:65;;8784:126;;;:::o;8916:96::-;8953:7;8982:24;9000:5;8982:24;:::i;:::-;8971:35;;8916:96;;;:::o;9018:122::-;9091:24;9109:5;9091:24;:::i;:::-;9084:5;9081:35;9071:63;;9130:1;9127;9120:12;9071:63;9018:122;:::o;9146:139::-;9192:5;9230:6;9217:20;9208:29;;9246:33;9273:5;9246:33;:::i;:::-;9146:139;;;;:::o;9291:943::-;9386:6;9394;9402;9410;9459:3;9447:9;9438:7;9434:23;9430:33;9427:120;;;9466:79;;:::i;:::-;9427:120;9586:1;9611:53;9656:7;9647:6;9636:9;9632:22;9611:53;:::i;:::-;9601:63;;9557:117;9713:2;9739:53;9784:7;9775:6;9764:9;9760:22;9739:53;:::i;:::-;9729:63;;9684:118;9841:2;9867:53;9912:7;9903:6;9892:9;9888:22;9867:53;:::i;:::-;9857:63;;9812:118;9997:2;9986:9;9982:18;9969:32;10028:18;10020:6;10017:30;10014:117;;;10050:79;;:::i;:::-;10014:117;10155:62;10209:7;10200:6;10189:9;10185:22;10155:62;:::i;:::-;10145:72;;9940:287;9291:943;;;;;;;:::o;10240:115::-;10325:23;10342:5;10325:23;:::i;:::-;10320:3;10313:36;10240:115;;:::o;10361:218::-;10452:4;10490:2;10479:9;10475:18;10467:26;;10503:69;10569:1;10558:9;10554:17;10545:6;10503:69;:::i;:::-;10361:218;;;;:::o;10585:311::-;10662:4;10752:18;10744:6;10741:30;10738:56;;;10774:18;;:::i;:::-;10738:56;10824:4;10816:6;10812:17;10804:25;;10884:4;10878;10874:15;10866:23;;10585:311;;;:::o;10919:710::-;11015:5;11040:81;11056:64;11113:6;11056:64;:::i;:::-;11040:81;:::i;:::-;11031:90;;11141:5;11170:6;11163:5;11156:21;11204:4;11197:5;11193:16;11186:23;;11257:4;11249:6;11245:17;11237:6;11233:30;11286:3;11278:6;11275:15;11272:122;;;11305:79;;:::i;:::-;11272:122;11420:6;11403:220;11437:6;11432:3;11429:15;11403:220;;;11512:3;11541:37;11574:3;11562:10;11541:37;:::i;:::-;11536:3;11529:50;11608:4;11603:3;11599:14;11592:21;;11479:144;11463:4;11458:3;11454:14;11447:21;;11403:220;;;11407:21;11021:608;;10919:710;;;;;:::o;11652:370::-;11723:5;11772:3;11765:4;11757:6;11753:17;11749:27;11739:122;;11780:79;;:::i;:::-;11739:122;11897:6;11884:20;11922:94;12012:3;12004:6;11997:4;11989:6;11985:17;11922:94;:::i;:::-;11913:103;;11729:293;11652:370;;;;:::o;12028:311::-;12105:4;12195:18;12187:6;12184:30;12181:56;;;12217:18;;:::i;:::-;12181:56;12267:4;12259:6;12255:17;12247:25;;12327:4;12321;12317:15;12309:23;;12028:311;;;:::o;12362:710::-;12458:5;12483:81;12499:64;12556:6;12499:64;:::i;:::-;12483:81;:::i;:::-;12474:90;;12584:5;12613:6;12606:5;12599:21;12647:4;12640:5;12636:16;12629:23;;12700:4;12692:6;12688:17;12680:6;12676:30;12729:3;12721:6;12718:15;12715:122;;;12748:79;;:::i;:::-;12715:122;12863:6;12846:220;12880:6;12875:3;12872:15;12846:220;;;12955:3;12984:37;13017:3;13005:10;12984:37;:::i;:::-;12979:3;12972:50;13051:4;13046:3;13042:14;13035:21;;12922:144;12906:4;12901:3;12897:14;12890:21;;12846:220;;;12850:21;12464:608;;12362:710;;;;;:::o;13095:370::-;13166:5;13215:3;13208:4;13200:6;13196:17;13192:27;13182:122;;13223:79;;:::i;:::-;13182:122;13340:6;13327:20;13365:94;13455:3;13447:6;13440:4;13432:6;13428:17;13365:94;:::i;:::-;13356:103;;13172:293;13095:370;;;;:::o;13471:320::-;13557:4;13647:18;13639:6;13636:30;13633:56;;;13669:18;;:::i;:::-;13633:56;13719:4;13711:6;13707:17;13699:25;;13779:4;13773;13769:15;13761:23;;13471:320;;;:::o;13812:942::-;13917:5;13942:90;13958:73;14024:6;13958:73;:::i;:::-;13942:90;:::i;:::-;13933:99;;14052:5;14081:6;14074:5;14067:21;14115:4;14108:5;14104:16;14097:23;;14168:4;14160:6;14156:17;14148:6;14144:30;14197:3;14189:6;14186:15;14183:122;;;14216:79;;:::i;:::-;14183:122;14331:6;14314:434;14348:6;14343:3;14340:15;14314:434;;;14437:3;14424:17;14473:18;14460:11;14457:35;14454:122;;;14495:79;;:::i;:::-;14454:122;14619:11;14611:6;14607:24;14657:46;14699:3;14687:10;14657:46;:::i;:::-;14652:3;14645:59;14733:4;14728:3;14724:14;14717:21;;14390:358;;14374:4;14369:3;14365:14;14358:21;;14314:434;;;14318:21;13923:831;;13812:942;;;;;:::o;14775:388::-;14855:5;14904:3;14897:4;14889:6;14885:17;14881:27;14871:122;;14912:79;;:::i;:::-;14871:122;15029:6;15016:20;15054:103;15153:3;15145:6;15138:4;15130:6;15126:17;15054:103;:::i;:::-;15045:112;;14861:302;14775:388;;;;:::o;15169:1413::-;15339:6;15347;15355;15363;15412:3;15400:9;15391:7;15387:23;15383:33;15380:120;;;15419:79;;:::i;:::-;15380:120;15567:1;15556:9;15552:17;15539:31;15597:18;15589:6;15586:30;15583:117;;;15619:79;;:::i;:::-;15583:117;15724:78;15794:7;15785:6;15774:9;15770:22;15724:78;:::i;:::-;15714:88;;15510:302;15879:2;15868:9;15864:18;15851:32;15910:18;15902:6;15899:30;15896:117;;;15932:79;;:::i;:::-;15896:117;16037:78;16107:7;16098:6;16087:9;16083:22;16037:78;:::i;:::-;16027:88;;15822:303;16192:2;16181:9;16177:18;16164:32;16223:18;16215:6;16212:30;16209:117;;;16245:79;;:::i;:::-;16209:117;16350:87;16429:7;16420:6;16409:9;16405:22;16350:87;:::i;:::-;16340:97;;16135:312;16486:2;16512:53;16557:7;16548:6;16537:9;16533:22;16512:53;:::i;:::-;16502:63;;16457:118;15169:1413;;;;;;;:::o;16588:329::-;16647:6;16696:2;16684:9;16675:7;16671:23;16667:32;16664:119;;;16702:79;;:::i;:::-;16664:119;16822:1;16847:53;16892:7;16883:6;16872:9;16868:22;16847:53;:::i;:::-;16837:63;;16793:117;16588:329;;;;:::o;16923:118::-;17010:24;17028:5;17010:24;:::i;:::-;17005:3;16998:37;16923:118;;:::o;17047:222::-;17140:4;17178:2;17167:9;17163:18;17155:26;;17191:71;17259:1;17248:9;17244:17;17235:6;17191:71;:::i;:::-;17047:222;;;;:::o;17275:903::-;17366:6;17374;17382;17390;17398;17447:3;17435:9;17426:7;17422:23;17418:33;17415:120;;;17454:79;;:::i;:::-;17415:120;17574:1;17599:53;17644:7;17635:6;17624:9;17620:22;17599:53;:::i;:::-;17589:63;;17545:117;17701:2;17727:51;17770:7;17761:6;17750:9;17746:22;17727:51;:::i;:::-;17717:61;;17672:116;17827:2;17853:51;17896:7;17887:6;17876:9;17872:22;17853:51;:::i;:::-;17843:61;;17798:116;17953:2;17979:53;18024:7;18015:6;18004:9;18000:22;17979:53;:::i;:::-;17969:63;;17924:118;18081:3;18108:53;18153:7;18144:6;18133:9;18129:22;18108:53;:::i;:::-;18098:63;;18052:119;17275:903;;;;;;;;:::o;18184:180::-;18232:77;18229:1;18222:88;18329:4;18326:1;18319:15;18353:4;18350:1;18343:15;18370:123;18461:1;18454:5;18451:12;18441:46;;18467:18;;:::i;:::-;18441:46;18370:123;:::o;18499:147::-;18554:7;18583:5;18572:16;;18589:51;18634:5;18589:51;:::i;:::-;18499:147;;;:::o;18652:::-;18718:9;18751:42;18787:5;18751:42;:::i;:::-;18738:55;;18652:147;;;:::o;18805:163::-;18908:53;18955:5;18908:53;:::i;:::-;18903:3;18896:66;18805:163;;:::o;18974:254::-;19083:4;19121:2;19110:9;19106:18;19098:26;;19134:87;19218:1;19207:9;19203:17;19194:6;19134:87;:::i;:::-;18974:254;;;;:::o;19234:474::-;19302:6;19310;19359:2;19347:9;19338:7;19334:23;19330:32;19327:119;;;19365:79;;:::i;:::-;19327:119;19485:1;19510:53;19555:7;19546:6;19535:9;19531:22;19510:53;:::i;:::-;19500:63;;19456:117;19612:2;19638:53;19683:7;19674:6;19663:9;19659:22;19638:53;:::i;:::-;19628:63;;19583:118;19234:474;;;;;:::o;19714:442::-;19863:4;19901:2;19890:9;19886:18;19878:26;;19914:71;19982:1;19971:9;19967:17;19958:6;19914:71;:::i;:::-;19995:72;20063:2;20052:9;20048:18;20039:6;19995:72;:::i;:::-;20077;20145:2;20134:9;20130:18;20121:6;20077:72;:::i;:::-;19714:442;;;;;;:::o;20162:470::-;20228:6;20236;20285:2;20273:9;20264:7;20260:23;20256:32;20253:119;;;20291:79;;:::i;:::-;20253:119;20411:1;20436:53;20481:7;20472:6;20461:9;20457:22;20436:53;:::i;:::-;20426:63;;20382:117;20538:2;20564:51;20607:7;20598:6;20587:9;20583:22;20564:51;:::i;:::-;20554:61;;20509:116;20162:470;;;;;:::o;20638:1139::-;20743:6;20751;20759;20767;20775;20824:3;20812:9;20803:7;20799:23;20795:33;20792:120;;;20831:79;;:::i;:::-;20792:120;20951:1;20976:53;21021:7;21012:6;21001:9;20997:22;20976:53;:::i;:::-;20966:63;;20922:117;21078:2;21104:51;21147:7;21138:6;21127:9;21123:22;21104:51;:::i;:::-;21094:61;;21049:116;21232:2;21221:9;21217:18;21204:32;21263:18;21255:6;21252:30;21249:117;;;21285:79;;:::i;:::-;21249:117;21398:65;21455:7;21446:6;21435:9;21431:22;21398:65;:::i;:::-;21380:83;;;;21175:298;21540:2;21529:9;21525:18;21512:32;21571:18;21563:6;21560:30;21557:117;;;21593:79;;:::i;:::-;21557:117;21698:62;21752:7;21743:6;21732:9;21728:22;21698:62;:::i;:::-;21688:72;;21483:287;20638:1139;;;;;;;;:::o;21783:815::-;21870:6;21878;21886;21894;21943:2;21931:9;21922:7;21918:23;21914:32;21911:119;;;21949:79;;:::i;:::-;21911:119;22069:1;22094:53;22139:7;22130:6;22119:9;22115:22;22094:53;:::i;:::-;22084:63;;22040:117;22196:2;22222:51;22265:7;22256:6;22245:9;22241:22;22222:51;:::i;:::-;22212:61;;22167:116;22350:2;22339:9;22335:18;22322:32;22381:18;22373:6;22370:30;22367:117;;;22403:79;;:::i;:::-;22367:117;22516:65;22573:7;22564:6;22553:9;22549:22;22516:65;:::i;:::-;22498:83;;;;22293:298;21783:815;;;;;;;:::o;22604:308::-;22666:4;22756:18;22748:6;22745:30;22742:56;;;22778:18;;:::i;:::-;22742:56;22816:29;22838:6;22816:29;:::i;:::-;22808:37;;22900:4;22894;22890:15;22882:23;;22604:308;;;:::o;22918:425::-;22996:5;23021:66;23037:49;23079:6;23037:49;:::i;:::-;23021:66;:::i;:::-;23012:75;;23110:6;23103:5;23096:21;23148:4;23141:5;23137:16;23186:3;23177:6;23172:3;23168:16;23165:25;23162:112;;;23193:79;;:::i;:::-;23162:112;23283:54;23330:6;23325:3;23320;23283:54;:::i;:::-;23002:341;22918:425;;;;;:::o;23363:340::-;23419:5;23468:3;23461:4;23453:6;23449:17;23445:27;23435:122;;23476:79;;:::i;:::-;23435:122;23593:6;23580:20;23618:79;23693:3;23685:6;23678:4;23670:6;23666:17;23618:79;:::i;:::-;23609:88;;23425:278;23363:340;;;;:::o;23709:1593::-;23889:6;23897;23905;23913;23962:3;23950:9;23941:7;23937:23;23933:33;23930:120;;;23969:79;;:::i;:::-;23930:120;24117:1;24106:9;24102:17;24089:31;24147:18;24139:6;24136:30;24133:117;;;24169:79;;:::i;:::-;24133:117;24274:78;24344:7;24335:6;24324:9;24320:22;24274:78;:::i;:::-;24264:88;;24060:302;24429:2;24418:9;24414:18;24401:32;24460:18;24452:6;24449:30;24446:117;;;24482:79;;:::i;:::-;24446:117;24587:78;24657:7;24648:6;24637:9;24633:22;24587:78;:::i;:::-;24577:88;;24372:303;24742:2;24731:9;24727:18;24714:32;24773:18;24765:6;24762:30;24759:117;;;24795:79;;:::i;:::-;24759:117;24900:87;24979:7;24970:6;24959:9;24955:22;24900:87;:::i;:::-;24890:97;;24685:312;25064:2;25053:9;25049:18;25036:32;25095:18;25087:6;25084:30;25081:117;;;25117:79;;:::i;:::-;25081:117;25222:63;25277:7;25268:6;25257:9;25253:22;25222:63;:::i;:::-;25212:73;;25007:288;23709:1593;;;;;;;:::o;25308:797::-;25394:6;25402;25410;25459:2;25447:9;25438:7;25434:23;25430:32;25427:119;;;25465:79;;:::i;:::-;25427:119;25585:1;25610:53;25655:7;25646:6;25635:9;25631:22;25610:53;:::i;:::-;25600:63;;25556:117;25712:2;25738:53;25783:7;25774:6;25763:9;25759:22;25738:53;:::i;:::-;25728:63;;25683:118;25868:2;25857:9;25853:18;25840:32;25899:18;25891:6;25888:30;25885:117;;;25921:79;;:::i;:::-;25885:117;26026:62;26080:7;26071:6;26060:9;26056:22;26026:62;:::i;:::-;26016:72;;25811:287;25308:797;;;;;:::o;26111:1509::-;26265:6;26273;26281;26289;26297;26346:3;26334:9;26325:7;26321:23;26317:33;26314:120;;;26353:79;;:::i;:::-;26314:120;26473:1;26498:53;26543:7;26534:6;26523:9;26519:22;26498:53;:::i;:::-;26488:63;;26444:117;26600:2;26626:53;26671:7;26662:6;26651:9;26647:22;26626:53;:::i;:::-;26616:63;;26571:118;26756:2;26745:9;26741:18;26728:32;26787:18;26779:6;26776:30;26773:117;;;26809:79;;:::i;:::-;26773:117;26914:78;26984:7;26975:6;26964:9;26960:22;26914:78;:::i;:::-;26904:88;;26699:303;27069:2;27058:9;27054:18;27041:32;27100:18;27092:6;27089:30;27086:117;;;27122:79;;:::i;:::-;27086:117;27227:78;27297:7;27288:6;27277:9;27273:22;27227:78;:::i;:::-;27217:88;;27012:303;27382:3;27371:9;27367:19;27354:33;27414:18;27406:6;27403:30;27400:117;;;27436:79;;:::i;:::-;27400:117;27541:62;27595:7;27586:6;27575:9;27571:22;27541:62;:::i;:::-;27531:72;;27325:288;26111:1509;;;;;;;;:::o;27639:552::-;27696:8;27706:6;27756:3;27749:4;27741:6;27737:17;27733:27;27723:122;;27764:79;;:::i;:::-;27723:122;27877:6;27864:20;27854:30;;27907:18;27899:6;27896:30;27893:117;;;27929:79;;:::i;:::-;27893:117;28043:4;28035:6;28031:17;28019:29;;28097:3;28089:4;28081:6;28077:17;28067:8;28063:32;28060:41;28057:128;;;28104:79;;:::i;:::-;28057:128;27639:552;;;;;:::o;28197:817::-;28285:6;28293;28301;28309;28358:2;28346:9;28337:7;28333:23;28329:32;28326:119;;;28364:79;;:::i;:::-;28326:119;28484:1;28509:53;28554:7;28545:6;28534:9;28530:22;28509:53;:::i;:::-;28499:63;;28455:117;28611:2;28637:53;28682:7;28673:6;28662:9;28658:22;28637:53;:::i;:::-;28627:63;;28582:118;28767:2;28756:9;28752:18;28739:32;28798:18;28790:6;28787:30;28784:117;;;28820:79;;:::i;:::-;28784:117;28933:64;28989:7;28980:6;28969:9;28965:22;28933:64;:::i;:::-;28915:82;;;;28710:297;28197:817;;;;;;;:::o;29020:474::-;29088:6;29096;29145:2;29133:9;29124:7;29120:23;29116:32;29113:119;;;29151:79;;:::i;:::-;29113:119;29271:1;29296:53;29341:7;29332:6;29321:9;29317:22;29296:53;:::i;:::-;29286:63;;29242:117;29398:2;29424:53;29469:7;29460:6;29449:9;29445:22;29424:53;:::i;:::-;29414:63;;29369:118;29020:474;;;;;:::o;29500:1089::-;29604:6;29612;29620;29628;29636;29685:3;29673:9;29664:7;29660:23;29656:33;29653:120;;;29692:79;;:::i;:::-;29653:120;29812:1;29837:53;29882:7;29873:6;29862:9;29858:22;29837:53;:::i;:::-;29827:63;;29783:117;29939:2;29965:53;30010:7;30001:6;29990:9;29986:22;29965:53;:::i;:::-;29955:63;;29910:118;30067:2;30093:53;30138:7;30129:6;30118:9;30114:22;30093:53;:::i;:::-;30083:63;;30038:118;30195:2;30221:53;30266:7;30257:6;30246:9;30242:22;30221:53;:::i;:::-;30211:63;;30166:118;30351:3;30340:9;30336:19;30323:33;30383:18;30375:6;30372:30;30369:117;;;30405:79;;:::i;:::-;30369:117;30510:62;30564:7;30555:6;30544:9;30540:22;30510:62;:::i;:::-;30500:72;;30294:288;29500:1089;;;;;;;;:::o;30595:60::-;30623:3;30644:5;30637:12;;30595:60;;;:::o;30661:142::-;30711:9;30744:53;30762:34;30771:24;30789:5;30771:24;:::i;:::-;30762:34;:::i;:::-;30744:53;:::i;:::-;30731:66;;30661:142;;;:::o;30809:126::-;30859:9;30892:37;30923:5;30892:37;:::i;:::-;30879:50;;30809:126;;;:::o;30941:149::-;31014:9;31047:37;31078:5;31047:37;:::i;:::-;31034:50;;30941:149;;;:::o;31096:177::-;31206:60;31260:5;31206:60;:::i;:::-;31201:3;31194:73;31096:177;;:::o;31279:268::-;31395:4;31433:2;31422:9;31418:18;31410:26;;31446:94;31537:1;31526:9;31522:17;31513:6;31446:94;:::i;:::-;31279:268;;;;:::o;31553:147::-;31654:11;31691:3;31676:18;;31553:147;;;;:::o;31728:327::-;31842:3;31863:88;31944:6;31939:3;31863:88;:::i;:::-;31856:95;;31961:56;32010:6;32005:3;31998:5;31961:56;:::i;:::-;32042:6;32037:3;32033:16;32026:23;;31728:327;;;;;:::o;32061:291::-;32201:3;32223:103;32322:3;32313:6;32305;32223:103;:::i;:::-;32216:110;;32343:3;32336:10;;32061:291;;;;;:::o;32358:112::-;32441:22;32457:5;32441:22;:::i;:::-;32436:3;32429:35;32358:112;;:::o;32476:656::-;32677:4;32715:3;32704:9;32700:19;32692:27;;32729:71;32797:1;32786:9;32782:17;32773:6;32729:71;:::i;:::-;32810:72;32878:2;32867:9;32863:18;32854:6;32810:72;:::i;:::-;32892:68;32956:2;32945:9;32941:18;32932:6;32892:68;:::i;:::-;32970:72;33038:2;33027:9;33023:18;33014:6;32970:72;:::i;:::-;33052:73;33120:3;33109:9;33105:19;33096:6;33052:73;:::i;:::-;32476:656;;;;;;;;:::o;33138:180::-;33186:77;33183:1;33176:88;33283:4;33280:1;33273:15;33307:4;33304:1;33297:15;33324:320;33368:6;33405:1;33399:4;33395:12;33385:22;;33452:1;33446:4;33442:12;33473:18;33463:81;;33529:4;33521:6;33517:17;33507:27;;33463:81;33591:2;33583:6;33580:14;33560:18;33557:38;33554:84;;33610:18;;:::i;:::-;33554:84;33375:269;33324:320;;;:::o;33650:220::-;33790:34;33786:1;33778:6;33774:14;33767:58;33859:3;33854:2;33846:6;33842:15;33835:28;33650:220;:::o;33876:366::-;34018:3;34039:67;34103:2;34098:3;34039:67;:::i;:::-;34032:74;;34115:93;34204:3;34115:93;:::i;:::-;34233:2;34228:3;34224:12;34217:19;;33876:366;;;:::o;34248:419::-;34414:4;34452:2;34441:9;34437:18;34429:26;;34501:9;34495:4;34491:20;34487:1;34476:9;34472:17;34465:47;34529:131;34655:4;34529:131;:::i;:::-;34521:139;;34248:419;;;:::o;34673:434::-;34818:4;34856:2;34845:9;34841:18;34833:26;;34869:71;34937:1;34926:9;34922:17;34913:6;34869:71;:::i;:::-;34950:72;35018:2;35007:9;35003:18;34994:6;34950:72;:::i;:::-;35032:68;35096:2;35085:9;35081:18;35072:6;35032:68;:::i;:::-;34673:434;;;;;;:::o;35113:179::-;35253:31;35249:1;35241:6;35237:14;35230:55;35113:179;:::o;35298:366::-;35440:3;35461:67;35525:2;35520:3;35461:67;:::i;:::-;35454:74;;35537:93;35626:3;35537:93;:::i;:::-;35655:2;35650:3;35646:12;35639:19;;35298:366;;;:::o;35670:419::-;35836:4;35874:2;35863:9;35859:18;35851:26;;35923:9;35917:4;35913:20;35909:1;35898:9;35894:17;35887:47;35951:131;36077:4;35951:131;:::i;:::-;35943:139;;35670:419;;;:::o;36095:174::-;36235:26;36231:1;36223:6;36219:14;36212:50;36095:174;:::o;36275:366::-;36417:3;36438:67;36502:2;36497:3;36438:67;:::i;:::-;36431:74;;36514:93;36603:3;36514:93;:::i;:::-;36632:2;36627:3;36623:12;36616:19;;36275:366;;;:::o;36647:419::-;36813:4;36851:2;36840:9;36836:18;36828:26;;36900:9;36894:4;36890:20;36886:1;36875:9;36871:17;36864:47;36928:131;37054:4;36928:131;:::i;:::-;36920:139;;36647:419;;;:::o;37072:180::-;37120:77;37117:1;37110:88;37217:4;37214:1;37207:15;37241:4;37238:1;37231:15;37258:194;37298:4;37318:20;37336:1;37318:20;:::i;:::-;37313:25;;37352:20;37370:1;37352:20;:::i;:::-;37347:25;;37396:1;37393;37389:9;37381:17;;37420:1;37414:4;37411:11;37408:37;;;37425:18;;:::i;:::-;37408:37;37258:194;;;;:::o;37458:236::-;37598:34;37594:1;37586:6;37582:14;37575:58;37667:19;37662:2;37654:6;37650:15;37643:44;37458:236;:::o;37700:366::-;37842:3;37863:67;37927:2;37922:3;37863:67;:::i;:::-;37856:74;;37939:93;38028:3;37939:93;:::i;:::-;38057:2;38052:3;38048:12;38041:19;;37700:366;;;:::o;38072:419::-;38238:4;38276:2;38265:9;38261:18;38253:26;;38325:9;38319:4;38315:20;38311:1;38300:9;38296:17;38289:47;38353:131;38479:4;38353:131;:::i;:::-;38345:139;;38072:419;;;:::o;38497:220::-;38637:34;38633:1;38625:6;38621:14;38614:58;38706:3;38701:2;38693:6;38689:15;38682:28;38497:220;:::o;38723:366::-;38865:3;38886:67;38950:2;38945:3;38886:67;:::i;:::-;38879:74;;38962:93;39051:3;38962:93;:::i;:::-;39080:2;39075:3;39071:12;39064:19;;38723:366;;;:::o;39095:419::-;39261:4;39299:2;39288:9;39284:18;39276:26;;39348:9;39342:4;39338:20;39334:1;39323:9;39319:17;39312:47;39376:131;39502:4;39376:131;:::i;:::-;39368:139;;39095:419;;;:::o;39520:174::-;39660:26;39656:1;39648:6;39644:14;39637:50;39520:174;:::o;39700:366::-;39842:3;39863:67;39927:2;39922:3;39863:67;:::i;:::-;39856:74;;39939:93;40028:3;39939:93;:::i;:::-;40057:2;40052:3;40048:12;40041:19;;39700:366;;;:::o;40072:419::-;40238:4;40276:2;40265:9;40261:18;40253:26;;40325:9;40319:4;40315:20;40311:1;40300:9;40296:17;40289:47;40353:131;40479:4;40353:131;:::i;:::-;40345:139;;40072:419;;;:::o;40497:220::-;40637:34;40633:1;40625:6;40621:14;40614:58;40706:3;40701:2;40693:6;40689:15;40682:28;40497:220;:::o;40723:366::-;40865:3;40886:67;40950:2;40945:3;40886:67;:::i;:::-;40879:74;;40962:93;41051:3;40962:93;:::i;:::-;41080:2;41075:3;41071:12;41064:19;;40723:366;;;:::o;41095:419::-;41261:4;41299:2;41288:9;41284:18;41276:26;;41348:9;41342:4;41338:20;41334:1;41323:9;41319:17;41312:47;41376:131;41502:4;41376:131;:::i;:::-;41368:139;;41095:419;;;:::o;41520:101::-;41556:7;41596:18;41589:5;41585:30;41574:41;;41520:101;;;:::o;41627:205::-;41666:3;41685:19;41702:1;41685:19;:::i;:::-;41680:24;;41718:19;41735:1;41718:19;:::i;:::-;41713:24;;41760:1;41757;41753:9;41746:16;;41783:18;41778:3;41775:27;41772:53;;;41805:18;;:::i;:::-;41772:53;41627:205;;;;:::o;41838:118::-;41925:24;41943:5;41925:24;:::i;:::-;41920:3;41913:37;41838:118;;:::o;41962:114::-;42029:6;42063:5;42057:12;42047:22;;41962:114;;;:::o;42082:184::-;42181:11;42215:6;42210:3;42203:19;42255:4;42250:3;42246:14;42231:29;;42082:184;;;;:::o;42272:132::-;42339:4;42362:3;42354:11;;42392:4;42387:3;42383:14;42375:22;;42272:132;;;:::o;42410:108::-;42487:24;42505:5;42487:24;:::i;:::-;42482:3;42475:37;42410:108;;:::o;42524:179::-;42593:10;42614:46;42656:3;42648:6;42614:46;:::i;:::-;42692:4;42687:3;42683:14;42669:28;;42524:179;;;;:::o;42709:113::-;42779:4;42811;42806:3;42802:14;42794:22;;42709:113;;;:::o;42858:732::-;42977:3;43006:54;43054:5;43006:54;:::i;:::-;43076:86;43155:6;43150:3;43076:86;:::i;:::-;43069:93;;43186:56;43236:5;43186:56;:::i;:::-;43265:7;43296:1;43281:284;43306:6;43303:1;43300:13;43281:284;;;43382:6;43376:13;43409:63;43468:3;43453:13;43409:63;:::i;:::-;43402:70;;43495:60;43548:6;43495:60;:::i;:::-;43485:70;;43341:224;43328:1;43325;43321:9;43316:14;;43281:284;;;43285:14;43581:3;43574:10;;42982:608;;;42858:732;;;;:::o;43596:114::-;43663:6;43697:5;43691:12;43681:22;;43596:114;;;:::o;43716:184::-;43815:11;43849:6;43844:3;43837:19;43889:4;43884:3;43880:14;43865:29;;43716:184;;;;:::o;43906:132::-;43973:4;43996:3;43988:11;;44026:4;44021:3;44017:14;44009:22;;43906:132;;;:::o;44044:108::-;44121:24;44139:5;44121:24;:::i;:::-;44116:3;44109:37;44044:108;;:::o;44158:179::-;44227:10;44248:46;44290:3;44282:6;44248:46;:::i;:::-;44326:4;44321:3;44317:14;44303:28;;44158:179;;;;:::o;44343:113::-;44413:4;44445;44440:3;44436:14;44428:22;;44343:113;;;:::o;44492:732::-;44611:3;44640:54;44688:5;44640:54;:::i;:::-;44710:86;44789:6;44784:3;44710:86;:::i;:::-;44703:93;;44820:56;44870:5;44820:56;:::i;:::-;44899:7;44930:1;44915:284;44940:6;44937:1;44934:13;44915:284;;;45016:6;45010:13;45043:63;45102:3;45087:13;45043:63;:::i;:::-;45036:70;;45129:60;45182:6;45129:60;:::i;:::-;45119:70;;44975:224;44962:1;44959;44955:9;44950:14;;44915:284;;;44919:14;45215:3;45208:10;;44616:608;;;44492:732;;;;:::o;45230:124::-;45307:6;45341:5;45335:12;45325:22;;45230:124;;;:::o;45360:194::-;45469:11;45503:6;45498:3;45491:19;45543:4;45538:3;45534:14;45519:29;;45360:194;;;;:::o;45560:142::-;45637:4;45660:3;45652:11;;45690:4;45685:3;45681:14;45673:22;;45560:142;;;:::o;45708:159::-;45782:11;45816:6;45811:3;45804:19;45856:4;45851:3;45847:14;45832:29;;45708:159;;;;:::o;45873:357::-;45951:3;45979:39;46012:5;45979:39;:::i;:::-;46034:61;46088:6;46083:3;46034:61;:::i;:::-;46027:68;;46104:65;46162:6;46157:3;46150:4;46143:5;46139:16;46104:65;:::i;:::-;46194:29;46216:6;46194:29;:::i;:::-;46189:3;46185:39;46178:46;;45955:275;45873:357;;;;:::o;46236:196::-;46325:10;46360:66;46422:3;46414:6;46360:66;:::i;:::-;46346:80;;46236:196;;;;:::o;46438:123::-;46518:4;46550;46545:3;46541:14;46533:22;;46438:123;;;:::o;46595:991::-;46734:3;46763:64;46821:5;46763:64;:::i;:::-;46843:96;46932:6;46927:3;46843:96;:::i;:::-;46836:103;;46965:3;47010:4;47002:6;46998:17;46993:3;46989:27;47040:66;47100:5;47040:66;:::i;:::-;47129:7;47160:1;47145:396;47170:6;47167:1;47164:13;47145:396;;;47241:9;47235:4;47231:20;47226:3;47219:33;47292:6;47286:13;47320:84;47399:4;47384:13;47320:84;:::i;:::-;47312:92;;47427:70;47490:6;47427:70;:::i;:::-;47417:80;;47526:4;47521:3;47517:14;47510:21;;47205:336;47192:1;47189;47185:9;47180:14;;47145:396;;;47149:14;47557:4;47550:11;;47577:3;47570:10;;46739:847;;;;;46595:991;;;;:::o;47592:123::-;47668:6;47702:5;47696:12;47686:22;;47592:123;;;:::o;47721:193::-;47829:11;47863:6;47858:3;47851:19;47903:4;47898:3;47894:14;47879:29;;47721:193;;;;:::o;47920:141::-;47996:4;48019:3;48011:11;;48049:4;48044:3;48040:14;48032:22;;47920:141;;;:::o;48067:98::-;48118:6;48152:5;48146:12;48136:22;;48067:98;;;:::o;48171:158::-;48244:11;48278:6;48273:3;48266:19;48318:4;48313:3;48309:14;48294:29;;48171:158;;;;:::o;48335:353::-;48411:3;48439:38;48471:5;48439:38;:::i;:::-;48493:60;48546:6;48541:3;48493:60;:::i;:::-;48486:67;;48562:65;48620:6;48615:3;48608:4;48601:5;48597:16;48562:65;:::i;:::-;48652:29;48674:6;48652:29;:::i;:::-;48647:3;48643:39;48636:46;;48415:273;48335:353;;;;:::o;48694:192::-;48781:10;48816:64;48876:3;48868:6;48816:64;:::i;:::-;48802:78;;48694:192;;;;:::o;48892:122::-;48971:4;49003;48998:3;48994:14;48986:22;;48892:122;;;:::o;49046:983::-;49183:3;49212:63;49269:5;49212:63;:::i;:::-;49291:95;49379:6;49374:3;49291:95;:::i;:::-;49284:102;;49412:3;49457:4;49449:6;49445:17;49440:3;49436:27;49487:65;49546:5;49487:65;:::i;:::-;49575:7;49606:1;49591:393;49616:6;49613:1;49610:13;49591:393;;;49687:9;49681:4;49677:20;49672:3;49665:33;49738:6;49732:13;49766:82;49843:4;49828:13;49766:82;:::i;:::-;49758:90;;49871:69;49933:6;49871:69;:::i;:::-;49861:79;;49969:4;49964:3;49960:14;49953:21;;49651:333;49638:1;49635;49631:9;49626:14;;49591:393;;;49595:14;50000:4;49993:11;;50020:3;50013:10;;49188:841;;;;;49046:983;;;;:::o;50035:140::-;50084:9;50117:52;50135:33;50144:23;50161:5;50144:23;:::i;:::-;50135:33;:::i;:::-;50117:52;:::i;:::-;50104:65;;50035:140;;;:::o;50181:129::-;50267:36;50297:5;50267:36;:::i;:::-;50262:3;50255:49;50181:129;;:::o;50316:1875::-;50889:4;50927:3;50916:9;50912:19;50904:27;;50941:71;51009:1;50998:9;50994:17;50985:6;50941:71;:::i;:::-;51022:72;51090:2;51079:9;51075:18;51066:6;51022:72;:::i;:::-;51141:9;51135:4;51131:20;51126:2;51115:9;51111:18;51104:48;51169:108;51272:4;51263:6;51169:108;:::i;:::-;51161:116;;51324:9;51318:4;51314:20;51309:2;51298:9;51294:18;51287:48;51352:108;51455:4;51446:6;51352:108;:::i;:::-;51344:116;;51508:9;51502:4;51498:20;51492:3;51481:9;51477:19;51470:49;51536:128;51659:4;51650:6;51536:128;:::i;:::-;51528:136;;51712:9;51706:4;51702:20;51696:3;51685:9;51681:19;51674:49;51740:126;51861:4;51852:6;51740:126;:::i;:::-;51732:134;;51876:72;51943:3;51932:9;51928:19;51919:6;51876:72;:::i;:::-;51958;52025:3;52014:9;52010:19;52001:6;51958:72;:::i;:::-;52078:9;52072:4;52068:20;52062:3;52051:9;52047:19;52040:49;52106:78;52179:4;52170:6;52106:78;:::i;:::-;52098:86;;50316:1875;;;;;;;;;;;;:::o;52197:1042::-;52542:4;52580:3;52569:9;52565:19;52557:27;;52630:9;52624:4;52620:20;52616:1;52605:9;52601:17;52594:47;52658:108;52761:4;52752:6;52658:108;:::i;:::-;52650:116;;52813:9;52807:4;52803:20;52798:2;52787:9;52783:18;52776:48;52841:108;52944:4;52935:6;52841:108;:::i;:::-;52833:116;;52996:9;52990:4;52986:20;52981:2;52970:9;52966:18;52959:48;53024:126;53145:4;53136:6;53024:126;:::i;:::-;53016:134;;53160:72;53228:2;53217:9;53213:18;53204:6;53160:72;:::i;:::-;52197:1042;;;;;;;:::o;53245:222::-;53385:34;53381:1;53373:6;53369:14;53362:58;53454:5;53449:2;53441:6;53437:15;53430:30;53245:222;:::o;53473:366::-;53615:3;53636:67;53700:2;53695:3;53636:67;:::i;:::-;53629:74;;53712:93;53801:3;53712:93;:::i;:::-;53830:2;53825:3;53821:12;53814:19;;53473:366;;;:::o;53845:419::-;54011:4;54049:2;54038:9;54034:18;54026:26;;54098:9;54092:4;54088:20;54084:1;54073:9;54069:17;54062:47;54126:131;54252:4;54126:131;:::i;:::-;54118:139;;53845:419;;;:::o;54270:636::-;54463:4;54501:3;54490:9;54486:19;54478:27;;54515:71;54583:1;54572:9;54568:17;54559:6;54515:71;:::i;:::-;54596:68;54660:2;54649:9;54645:18;54636:6;54596:68;:::i;:::-;54674:72;54742:2;54731:9;54727:18;54718:6;54674:72;:::i;:::-;54793:9;54787:4;54783:20;54778:2;54767:9;54763:18;54756:48;54821:78;54894:4;54885:6;54821:78;:::i;:::-;54813:86;;54270:636;;;;;;;:::o;54912:168::-;54995:11;55029:6;55024:3;55017:19;55069:4;55064:3;55060:14;55045:29;;54912:168;;;;:::o;55086:373::-;55172:3;55200:38;55232:5;55200:38;:::i;:::-;55254:70;55317:6;55312:3;55254:70;:::i;:::-;55247:77;;55333:65;55391:6;55386:3;55379:4;55372:5;55368:16;55333:65;:::i;:::-;55423:29;55445:6;55423:29;:::i;:::-;55418:3;55414:39;55407:46;;55176:283;55086:373;;;;:::o;55465:834::-;55704:4;55742:3;55731:9;55727:19;55719:27;;55756:71;55824:1;55813:9;55809:17;55800:6;55756:71;:::i;:::-;55837:68;55901:2;55890:9;55886:18;55877:6;55837:68;:::i;:::-;55915:72;55983:2;55972:9;55968:18;55959:6;55915:72;:::i;:::-;56034:9;56028:4;56024:20;56019:2;56008:9;56004:18;55997:48;56062:78;56135:4;56126:6;56062:78;:::i;:::-;56054:86;;56188:9;56182:4;56178:20;56172:3;56161:9;56157:19;56150:49;56216:76;56287:4;56278:6;56216:76;:::i;:::-;56208:84;;55465:834;;;;;;;;:::o;56305:180::-;56353:77;56350:1;56343:88;56450:4;56447:1;56440:15;56474:4;56471:1;56464:15;56491:233;56530:3;56553:24;56571:5;56553:24;:::i;:::-;56544:33;;56599:66;56592:5;56589:77;56586:103;;56669:18;;:::i;:::-;56586:103;56716:1;56709:5;56705:13;56698:20;;56491:233;;;:::o;56730:386::-;56834:3;56862:38;56894:5;56862:38;:::i;:::-;56916:88;56997:6;56992:3;56916:88;:::i;:::-;56909:95;;57013:65;57071:6;57066:3;57059:4;57052:5;57048:16;57013:65;:::i;:::-;57103:6;57098:3;57094:16;57087:23;;56838:278;56730:386;;;;:::o;57122:271::-;57252:3;57274:93;57363:3;57354:6;57274:93;:::i;:::-;57267:100;;57384:3;57377:10;;57122:271;;;;:::o;57399:191::-;57439:3;57458:20;57476:1;57458:20;:::i;:::-;57453:25;;57492:20;57510:1;57492:20;:::i;:::-;57487:25;;57535:1;57532;57528:9;57521:16;;57556:3;57553:1;57550:10;57547:36;;;57563:18;;:::i;:::-;57547:36;57399:191;;;;:::o;57596:332::-;57717:4;57755:2;57744:9;57740:18;57732:26;;57768:71;57836:1;57825:9;57821:17;57812:6;57768:71;:::i;:::-;57849:72;57917:2;57906:9;57902:18;57893:6;57849:72;:::i;:::-;57596:332;;;;;:::o;57934:225::-;58074:34;58070:1;58062:6;58058:14;58051:58;58143:8;58138:2;58130:6;58126:15;58119:33;57934:225;:::o;58165:366::-;58307:3;58328:67;58392:2;58387:3;58328:67;:::i;:::-;58321:74;;58404:93;58493:3;58404:93;:::i;:::-;58522:2;58517:3;58513:12;58506:19;;58165:366;;;:::o;58537:419::-;58703:4;58741:2;58730:9;58726:18;58718:26;;58790:9;58784:4;58780:20;58776:1;58765:9;58761:17;58754:47;58818:131;58944:4;58818:131;:::i;:::-;58810:139;;58537:419;;;:::o;58962:332::-;59083:4;59121:2;59110:9;59106:18;59098:26;;59134:71;59202:1;59191:9;59187:17;59178:6;59134:71;:::i;:::-;59215:72;59283:2;59272:9;59268:18;59259:6;59215:72;:::i;:::-;58962:332;;;;;:::o;59300:109::-;59336:7;59376:26;59369:5;59365:38;59354:49;;59300:109;;;:::o;59415:120::-;59487:23;59504:5;59487:23;:::i;:::-;59480:5;59477:34;59467:62;;59525:1;59522;59515:12;59467:62;59415:120;:::o;59541:141::-;59597:5;59628:6;59622:13;59613:22;;59644:32;59670:5;59644:32;:::i;:::-;59541:141;;;;:::o;59688:349::-;59757:6;59806:2;59794:9;59785:7;59781:23;59777:32;59774:119;;;59812:79;;:::i;:::-;59774:119;59932:1;59957:63;60012:7;60003:6;59992:9;59988:22;59957:63;:::i;:::-;59947:73;;59903:127;59688:349;;;;:::o;60043:226::-;60183:34;60179:1;60171:6;60167:14;60160:58;60252:9;60247:2;60239:6;60235:15;60228:34;60043:226;:::o;60275:366::-;60417:3;60438:67;60502:2;60497:3;60438:67;:::i;:::-;60431:74;;60514:93;60603:3;60514:93;:::i;:::-;60632:2;60627:3;60623:12;60616:19;;60275:366;;;:::o;60647:419::-;60813:4;60851:2;60840:9;60836:18;60828:26;;60900:9;60894:4;60890:20;60886:1;60875:9;60871:17;60864:47;60928:131;61054:4;60928:131;:::i;:::-;60920:139;;60647:419;;;:::o;61072:148::-;61174:11;61211:3;61196:18;;61072:148;;;;:::o;61226:214::-;61366:66;61362:1;61354:6;61350:14;61343:90;61226:214;:::o;61446:400::-;61606:3;61627:84;61709:1;61704:3;61627:84;:::i;:::-;61620:91;;61720:93;61809:3;61720:93;:::i;:::-;61838:1;61833:3;61829:11;61822:18;;61446:400;;;:::o;61852:79::-;61891:7;61920:5;61909:16;;61852:79;;;:::o;61937:157::-;62042:45;62062:24;62080:5;62062:24;:::i;:::-;62042:45;:::i;:::-;62037:3;62030:58;61937:157;;:::o;62100:663::-;62341:3;62363:148;62507:3;62363:148;:::i;:::-;62356:155;;62521:75;62592:3;62583:6;62521:75;:::i;:::-;62621:2;62616:3;62612:12;62605:19;;62634:75;62705:3;62696:6;62634:75;:::i;:::-;62734:2;62729:3;62725:12;62718:19;;62754:3;62747:10;;62100:663;;;;;:::o;62769:545::-;62942:4;62980:3;62969:9;62965:19;62957:27;;62994:71;63062:1;63051:9;63047:17;63038:6;62994:71;:::i;:::-;63075:68;63139:2;63128:9;63124:18;63115:6;63075:68;:::i;:::-;63153:72;63221:2;63210:9;63206:18;63197:6;63153:72;:::i;:::-;63235;63303:2;63292:9;63288:18;63279:6;63235:72;:::i;:::-;62769:545;;;;;;;:::o;63320:174::-;63460:26;63456:1;63448:6;63444:14;63437:50;63320:174;:::o;63500:366::-;63642:3;63663:67;63727:2;63722:3;63663:67;:::i;:::-;63656:74;;63739:93;63828:3;63739:93;:::i;:::-;63857:2;63852:3;63848:12;63841:19;;63500:366;;;:::o;63872:419::-;64038:4;64076:2;64065:9;64061:18;64053:26;;64125:9;64119:4;64115:20;64111:1;64100:9;64096:17;64089:47;64153:131;64279:4;64153:131;:::i;:::-;64145:139;;63872:419;;;:::o;64297:181::-;64437:33;64433:1;64425:6;64421:14;64414:57;64297:181;:::o;64484:366::-;64626:3;64647:67;64711:2;64706:3;64647:67;:::i;:::-;64640:74;;64723:93;64812:3;64723:93;:::i;:::-;64841:2;64836:3;64832:12;64825:19;;64484:366;;;:::o;64856:419::-;65022:4;65060:2;65049:9;65045:18;65037:26;;65109:9;65103:4;65099:20;65095:1;65084:9;65080:17;65073:47;65137:131;65263:4;65137:131;:::i;:::-;65129:139;;64856:419;;;:::o;65281:221::-;65421:34;65417:1;65409:6;65405:14;65398:58;65490:4;65485:2;65477:6;65473:15;65466:29;65281:221;:::o;65508:366::-;65650:3;65671:67;65735:2;65730:3;65671:67;:::i;:::-;65664:74;;65747:93;65836:3;65747:93;:::i;:::-;65865:2;65860:3;65856:12;65849:19;;65508:366;;;:::o;65880:419::-;66046:4;66084:2;66073:9;66069:18;66061:26;;66133:9;66127:4;66123:20;66119:1;66108:9;66104:17;66097:47;66161:131;66287:4;66161:131;:::i;:::-;66153:139;;65880:419;;;:::o;66305:226::-;66445:34;66441:1;66433:6;66429:14;66422:58;66514:9;66509:2;66501:6;66497:15;66490:34;66305:226;:::o;66537:366::-;66679:3;66700:67;66764:2;66759:3;66700:67;:::i;:::-;66693:74;;66776:93;66865:3;66776:93;:::i;:::-;66894:2;66889:3;66885:12;66878:19;;66537:366;;;:::o;66909:419::-;67075:4;67113:2;67102:9;67098:18;67090:26;;67162:9;67156:4;67152:20;67148:1;67137:9;67133:17;67126:47;67190:131;67316:4;67190:131;:::i;:::-;67182:139;;66909:419;;;:::o;67334:240::-;67474:34;67470:1;67462:6;67458:14;67451:58;67543:23;67538:2;67530:6;67526:15;67519:48;67334:240;:::o;67580:366::-;67722:3;67743:67;67807:2;67802:3;67743:67;:::i;:::-;67736:74;;67819:93;67908:3;67819:93;:::i;:::-;67937:2;67932:3;67928:12;67921:19;;67580:366;;;:::o;67952:419::-;68118:4;68156:2;68145:9;68141:18;68133:26;;68205:9;68199:4;68195:20;68191:1;68180:9;68176:17;68169:47;68233:131;68359:4;68233:131;:::i;:::-;68225:139;;67952:419;;;:::o;68377:664::-;68582:4;68620:3;68609:9;68605:19;68597:27;;68634:71;68702:1;68691:9;68687:17;68678:6;68634:71;:::i;:::-;68715:72;68783:2;68772:9;68768:18;68759:6;68715:72;:::i;:::-;68797;68865:2;68854:9;68850:18;68841:6;68797:72;:::i;:::-;68879;68947:2;68936:9;68932:18;68923:6;68879:72;:::i;:::-;68961:73;69029:3;69018:9;69014:19;69005:6;68961:73;:::i;:::-;68377:664;;;;;;;;:::o

Swarm Source

ipfs://07d0065dfa1b0b6d01e855d84d3bda7886cec984eb729e8e1da32f15f3ffd0d5
Loading...
Loading
Loading...
Loading
[ 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.