ETH Price: $3,330.84 (-4.67%)

Token

RareParadise (RareParadise)
 

Overview

Max Total Supply

5,000 RareParadise

Holders

1,585

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A

Other Info

Balance
1 RareParadise
0x151611d87ff112d8e94eb03b6bfb5e76888d0cca
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:
RareParadise

Compiler Version
v0.8.16+commit.07a7930e

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, None license

Contract Source Code (Solidity)

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

// SPDX-License-Identifier: MIT
// File: solady/src/utils/SafeTransferLib.sol


pragma solidity ^0.8.4;

/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeTransferLib.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)
/// @dev Caution! This library won't check that a token has code, responsibility is delegated to the caller.
library SafeTransferLib {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The ETH transfer has failed.
    error ETHTransferFailed();

    /// @dev The ERC20 `transferFrom` has failed.
    error TransferFromFailed();

    /// @dev The ERC20 `transfer` has failed.
    error TransferFailed();

    /// @dev The ERC20 `approve` has failed.
    error ApproveFailed();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Suggested gas stipend for contract receiving ETH
    /// that disallows any storage writes.
    uint256 internal constant _GAS_STIPEND_NO_STORAGE_WRITES = 2300;

    /// @dev Suggested gas stipend for contract receiving ETH to perform a few
    /// storage reads and writes, but low enough to prevent griefing.
    /// Multiply by a small constant (e.g. 2), if needed.
    uint256 internal constant _GAS_STIPEND_NO_GRIEF = 100000;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       ETH OPERATIONS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Sends `amount` (in wei) ETH to `to`.
    /// Reverts upon failure.
    function safeTransferETH(address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            // Transfer the ETH and check if it succeeded or not.
            if iszero(call(gas(), to, amount, 0, 0, 0, 0)) {
                // Store the function selector of `ETHTransferFailed()`.
                mstore(0x00, 0xb12d13eb)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`.
    /// The `gasStipend` can be set to a low enough value to prevent
    /// storage writes or gas griefing.
    ///
    /// If sending via the normal procedure fails, force sends the ETH by
    /// creating a temporary contract which uses `SELFDESTRUCT` to force send the ETH.
    ///
    /// Reverts if the current contract has insufficient balance.
    function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal {
        /// @solidity memory-safe-assembly
        assembly {
            // If insufficient balance, revert.
            if lt(selfbalance(), amount) {
                // Store the function selector of `ETHTransferFailed()`.
                mstore(0x00, 0xb12d13eb)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }
            // Transfer the ETH and check if it succeeded or not.
            if iszero(call(gasStipend, to, amount, 0, 0, 0, 0)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                // We can directly use `SELFDESTRUCT` in the contract creation.
                // We don't check and revert upon failure here, just in case
                // `SELFDESTRUCT`'s behavior is changed some day in the future.
                // (If that ever happens, we will riot, and port the code to use WETH).
                pop(create(amount, 0x0b, 0x16))
            }
        }
    }

    /// @dev Force sends `amount` (in wei) ETH to `to`, with a gas stipend
    /// equal to `_GAS_STIPEND_NO_GRIEF`. This gas stipend is a reasonable default
    /// for 99% of cases and can be overriden with the three-argument version of this
    /// function if necessary.
    ///
    /// If sending via the normal procedure fails, force sends the ETH by
    /// creating a temporary contract which uses `SELFDESTRUCT` to force send the ETH.
    ///
    /// Reverts if the current contract has insufficient balance.
    function forceSafeTransferETH(address to, uint256 amount) internal {
        // Manually inlined because the compiler doesn't inline functions with branches.
        /// @solidity memory-safe-assembly
        assembly {
            // If insufficient balance, revert.
            if lt(selfbalance(), amount) {
                // Store the function selector of `ETHTransferFailed()`.
                mstore(0x00, 0xb12d13eb)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }
            // Transfer the ETH and check if it succeeded or not.
            if iszero(call(_GAS_STIPEND_NO_GRIEF, to, amount, 0, 0, 0, 0)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                // We can directly use `SELFDESTRUCT` in the contract creation.
                // We don't check and revert upon failure here, just in case
                // `SELFDESTRUCT`'s behavior is changed some day in the future.
                // (If that ever happens, we will riot, and port the code to use WETH).
                pop(create(amount, 0x0b, 0x16))
            }
        }
    }

    /// @dev Sends `amount` (in wei) ETH to `to`, with a `gasStipend`.
    /// The `gasStipend` can be set to a low enough value to prevent
    /// storage writes or gas griefing.
    ///
    /// Simply use `gasleft()` for `gasStipend` if you don't need a gas stipend.
    ///
    /// Note: Does NOT revert upon failure.
    /// Returns whether the transfer of ETH is successful instead.
    function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend)
        internal
        returns (bool success)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Transfer the ETH and check if it succeeded or not.
            success := call(gasStipend, to, amount, 0, 0, 0, 0)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      ERC20 OPERATIONS                      */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.
    /// Reverts upon failure.
    ///
    /// The `from` account must have at least `amount` approved for
    /// the current contract to manage.
    function safeTransferFrom(address token, address from, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            // We'll write our calldata to this slot below, but restore it later.
            let memPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(0x00, 0x23b872dd)
            mstore(0x20, from) // Append the "from" argument.
            mstore(0x40, to) // Append the "to" argument.
            mstore(0x60, amount) // Append the "amount" argument.

            if iszero(
                and(
                    // Set success to whether the call reverted, if not we check it either
                    // returned exactly 1 (can't just be non-zero data), or had no return data.
                    or(eq(mload(0x00), 1), iszero(returndatasize())),
                    // We use 0x64 because that's the total length of our calldata (0x04 + 0x20 * 3)
                    // Counterintuitively, this call() must be positioned after the or() in the
                    // surrounding and() because and() evaluates its arguments from right to left.
                    call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
                )
            ) {
                // Store the function selector of `TransferFromFailed()`.
                mstore(0x00, 0x7939f424)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }

            mstore(0x60, 0) // Restore the zero slot to zero.
            mstore(0x40, memPointer) // Restore the memPointer.
        }
    }

    /// @dev Sends `amount` of ERC20 `token` from the current contract to `to`.
    /// Reverts upon failure.
    function safeTransfer(address token, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            // We'll write our calldata to this slot below, but restore it later.
            let memPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(0x00, 0xa9059cbb)
            mstore(0x20, to) // Append the "to" argument.
            mstore(0x40, amount) // Append the "amount" argument.

            if iszero(
                and(
                    // Set success to whether the call reverted, if not we check it either
                    // returned exactly 1 (can't just be non-zero data), or had no return data.
                    or(eq(mload(0x00), 1), iszero(returndatasize())),
                    // We use 0x44 because that's the total length of our calldata (0x04 + 0x20 * 2)
                    // Counterintuitively, this call() must be positioned after the or() in the
                    // surrounding and() because and() evaluates its arguments from right to left.
                    call(gas(), token, 0, 0x1c, 0x44, 0x00, 0x20)
                )
            ) {
                // Store the function selector of `TransferFailed()`.
                mstore(0x00, 0x90b8ec18)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }

            mstore(0x40, memPointer) // Restore the memPointer.
        }
    }

    /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.
    /// Reverts upon failure.
    function safeApprove(address token, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            // We'll write our calldata to this slot below, but restore it later.
            let memPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(0x00, 0x095ea7b3)
            mstore(0x20, to) // Append the "to" argument.
            mstore(0x40, amount) // Append the "amount" argument.

            if iszero(
                and(
                    // Set success to whether the call reverted, if not we check it either
                    // returned exactly 1 (can't just be non-zero data), or had no return data.
                    or(eq(mload(0x00), 1), iszero(returndatasize())),
                    // We use 0x44 because that's the total length of our calldata (0x04 + 0x20 * 2)
                    // Counterintuitively, this call() must be positioned after the or() in the
                    // surrounding and() because and() evaluates its arguments from right to left.
                    call(gas(), token, 0, 0x1c, 0x44, 0x00, 0x20)
                )
            ) {
                // Store the function selector of `ApproveFailed()`.
                mstore(0x00, 0x3e3f8f73)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }

            mstore(0x40, memPointer) // Restore the memPointer.
        }
    }
}

// File: solady/src/utils/LibString.sol


pragma solidity ^0.8.4;

/// @notice Library for converting numbers into strings and other string operations.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibString.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibString.sol)
library LibString {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                        CUSTOM ERRORS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The `length` of the output is too small to contain all the hex digits.
    error HexLengthInsufficient();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The constant returned when the `search` is not found in the string.
    uint256 internal constant NOT_FOUND = type(uint256).max;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     DECIMAL OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the base 10 decimal representation of `value`.
    function toString(uint256 value) internal pure returns (string memory str) {
        /// @solidity memory-safe-assembly
        assembly {
            // The maximum value of a uint256 contains 78 digits (1 byte per digit), but
            // we allocate 0xa0 bytes to keep the free memory pointer 32-byte word aligned.
            // We will need 1 word for the trailing zeros padding, 1 word for the length,
            // and 3 words for a maximum of 78 digits. Total: 5 * 0x20 = 0xa0.
            let m := add(mload(0x40), 0xa0)
            // Update the free memory pointer to allocate.
            mstore(0x40, m)
            // Assign the `str` to the end.
            str := sub(m, 0x20)
            // Zeroize the slot after the string.
            mstore(str, 0)

            // Cache the end of the memory to calculate the length later.
            let end := str

            // We write the string from rightmost digit to leftmost digit.
            // The following is essentially a do-while loop that also handles the zero case.
            for { let temp := value } 1 {} {
                str := sub(str, 1)
                // Write the character to the pointer.
                // The ASCII index of the '0' character is 48.
                mstore8(str, add(48, mod(temp, 10)))
                // Keep dividing `temp` until zero.
                temp := div(temp, 10)
                if iszero(temp) { break }
            }

            let length := sub(end, str)
            // Move the pointer 32 bytes leftwards to make room for the length.
            str := sub(str, 0x20)
            // Store the length.
            mstore(str, length)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   HEXADECIMAL OPERATIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the hexadecimal representation of `value`,
    /// left-padded to an input length of `length` bytes.
    /// The output is prefixed with "0x" encoded using 2 hexadecimal digits per byte,
    /// giving a total length of `length * 2 + 2` bytes.
    /// Reverts if `length` is too small for the output to contain all the digits.
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory str) {
        str = toHexStringNoPrefix(value, length);
        /// @solidity memory-safe-assembly
        assembly {
            let strLength := add(mload(str), 2) // Compute the length.
            mstore(str, 0x3078) // Write the "0x" prefix.
            str := sub(str, 2) // Move the pointer.
            mstore(str, strLength) // Write the length.
        }
    }

    /// @dev Returns the hexadecimal representation of `value`,
    /// left-padded to an input length of `length` bytes.
    /// The output is prefixed with "0x" encoded using 2 hexadecimal digits per byte,
    /// giving a total length of `length * 2` bytes.
    /// Reverts if `length` is too small for the output to contain all the digits.
    function toHexStringNoPrefix(uint256 value, uint256 length)
        internal
        pure
        returns (string memory str)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let start := mload(0x40)
            // We need 0x20 bytes for the trailing zeros padding, `length * 2` bytes
            // for the digits, 0x02 bytes for the prefix, and 0x20 bytes for the length.
            // We add 0x20 to the total and round down to a multiple of 0x20.
            // (0x20 + 0x20 + 0x02 + 0x20) = 0x62.
            let m := add(start, and(add(shl(1, length), 0x62), not(0x1f)))
            // Allocate the memory.
            mstore(0x40, m)
            // Assign the `str` to the end.
            str := sub(m, 0x20)
            // Zeroize the slot after the string.
            mstore(str, 0)

            // Cache the end to calculate the length later.
            let end := str
            // Store "0123456789abcdef" in scratch space.
            mstore(0x0f, 0x30313233343536373839616263646566)

            let temp := value
            // We write the string from rightmost digit to leftmost digit.
            // The following is essentially a do-while loop that also handles the zero case.
            for {} 1 {} {
                str := sub(str, 2)
                mstore8(add(str, 1), mload(and(temp, 15)))
                mstore8(str, mload(and(shr(4, temp), 15)))
                temp := shr(8, temp)
                length := sub(length, 1)
                if iszero(length) { break }
            }

            if temp {
                // Store the function selector of `HexLengthInsufficient()`.
                mstore(0x00, 0x2194895a)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }

            // Compute the string's length.
            let strLength := sub(end, str)
            // Move the pointer and write the length.
            str := sub(str, 0x20)
            mstore(str, strLength)
        }
    }

    /// @dev Returns the hexadecimal representation of `value`.
    /// The output is prefixed with "0x" and encoded using 2 hexadecimal digits per byte.
    /// As address are 20 bytes long, the output will left-padded to have
    /// a length of `20 * 2 + 2` bytes.
    function toHexString(uint256 value) internal pure returns (string memory str) {
        str = toHexStringNoPrefix(value);
        /// @solidity memory-safe-assembly
        assembly {
            let strLength := add(mload(str), 2) // Compute the length.
            mstore(str, 0x3078) // Write the "0x" prefix.
            str := sub(str, 2) // Move the pointer.
            mstore(str, strLength) // Write the length.
        }
    }

    /// @dev Returns the hexadecimal representation of `value`.
    /// The output is encoded using 2 hexadecimal digits per byte.
    /// As address are 20 bytes long, the output will left-padded to have
    /// a length of `20 * 2` bytes.
    function toHexStringNoPrefix(uint256 value) internal pure returns (string memory str) {
        /// @solidity memory-safe-assembly
        assembly {
            let start := mload(0x40)
            // We need 0x20 bytes for the trailing zeros padding, 0x20 bytes for the length,
            // 0x02 bytes for the prefix, and 0x40 bytes for the digits.
            // The next multiple of 0x20 above (0x20 + 0x20 + 0x02 + 0x40) is 0xa0.
            let m := add(start, 0xa0)
            // Allocate the memory.
            mstore(0x40, m)
            // Assign the `str` to the end.
            str := sub(m, 0x20)
            // Zeroize the slot after the string.
            mstore(str, 0)

            // Cache the end to calculate the length later.
            let end := str
            // Store "0123456789abcdef" in scratch space.
            mstore(0x0f, 0x30313233343536373839616263646566)

            // We write the string from rightmost digit to leftmost digit.
            // The following is essentially a do-while loop that also handles the zero case.
            for { let temp := value } 1 {} {
                str := sub(str, 2)
                mstore8(add(str, 1), mload(and(temp, 15)))
                mstore8(str, mload(and(shr(4, temp), 15)))
                temp := shr(8, temp)
                if iszero(temp) { break }
            }

            // Compute the string's length.
            let strLength := sub(end, str)
            // Move the pointer and write the length.
            str := sub(str, 0x20)
            mstore(str, strLength)
        }
    }

    /// @dev Returns the hexadecimal representation of `value`.
    /// The output is prefixed with "0x", encoded using 2 hexadecimal digits per byte,
    /// and the alphabets are capitalized conditionally according to
    /// https://eips.ethereum.org/EIPS/eip-55
    function toHexStringChecksumed(address value) internal pure returns (string memory str) {
        str = toHexString(value);
        /// @solidity memory-safe-assembly
        assembly {
            let mask := shl(6, div(not(0), 255)) // `0b010000000100000000 ...`
            let o := add(str, 0x22)
            let hashed := and(keccak256(o, 40), mul(34, mask)) // `0b10001000 ... `
            let t := shl(240, 136) // `0b10001000 << 240`
            for { let i := 0 } 1 {} {
                mstore(add(i, i), mul(t, byte(i, hashed)))
                i := add(i, 1)
                if eq(i, 20) { break }
            }
            mstore(o, xor(mload(o), shr(1, and(mload(0x00), and(mload(o), mask)))))
            o := add(o, 0x20)
            mstore(o, xor(mload(o), shr(1, and(mload(0x20), and(mload(o), mask)))))
        }
    }

    /// @dev Returns the hexadecimal representation of `value`.
    /// The output is prefixed with "0x" and encoded using 2 hexadecimal digits per byte.
    function toHexString(address value) internal pure returns (string memory str) {
        str = toHexStringNoPrefix(value);
        /// @solidity memory-safe-assembly
        assembly {
            let strLength := add(mload(str), 2) // Compute the length.
            mstore(str, 0x3078) // Write the "0x" prefix.
            str := sub(str, 2) // Move the pointer.
            mstore(str, strLength) // Write the length.
        }
    }

    /// @dev Returns the hexadecimal representation of `value`.
    /// The output is encoded using 2 hexadecimal digits per byte.
    function toHexStringNoPrefix(address value) internal pure returns (string memory str) {
        /// @solidity memory-safe-assembly
        assembly {
            str := mload(0x40)

            // Allocate the memory.
            // We need 0x20 bytes for the trailing zeros padding, 0x20 bytes for the length,
            // 0x02 bytes for the prefix, and 0x28 bytes for the digits.
            // The next multiple of 0x20 above (0x20 + 0x20 + 0x02 + 0x28) is 0x80.
            mstore(0x40, add(str, 0x80))

            // Store "0123456789abcdef" in scratch space.
            mstore(0x0f, 0x30313233343536373839616263646566)

            str := add(str, 2)
            mstore(str, 40)

            let o := add(str, 0x20)
            mstore(add(o, 40), 0)

            value := shl(96, value)

            // We write the string from rightmost digit to leftmost digit.
            // The following is essentially a do-while loop that also handles the zero case.
            for { let i := 0 } 1 {} {
                let p := add(o, add(i, i))
                let temp := byte(i, value)
                mstore8(add(p, 1), mload(and(temp, 15)))
                mstore8(p, mload(shr(4, temp)))
                i := add(i, 1)
                if eq(i, 20) { break }
            }
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   RUNE STRING OPERATIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the number of UTF characters in the string.
    function runeCount(string memory s) internal pure returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            if mload(s) {
                mstore(0x00, div(not(0), 255))
                mstore(0x20, 0x0202020202020202020202020202020202020202020202020303030304040506)
                let o := add(s, 0x20)
                let end := add(o, mload(s))
                for { result := 1 } 1 { result := add(result, 1) } {
                    o := add(o, byte(0, mload(shr(250, mload(o)))))
                    if iszero(lt(o, end)) { break }
                }
            }
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   BYTE STRING OPERATIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // For performance and bytecode compactness, all indices of the following operations
    // are byte (ASCII) offsets, not UTF character offsets.

    /// @dev Returns `subject` all occurrences of `search` replaced with `replacement`.
    function replace(string memory subject, string memory search, string memory replacement)
        internal
        pure
        returns (string memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let subjectLength := mload(subject)
            let searchLength := mload(search)
            let replacementLength := mload(replacement)

            subject := add(subject, 0x20)
            search := add(search, 0x20)
            replacement := add(replacement, 0x20)
            result := add(mload(0x40), 0x20)

            let subjectEnd := add(subject, subjectLength)
            if iszero(gt(searchLength, subjectLength)) {
                let subjectSearchEnd := add(sub(subjectEnd, searchLength), 1)
                let h := 0
                if iszero(lt(searchLength, 32)) { h := keccak256(search, searchLength) }
                let m := shl(3, sub(32, and(searchLength, 31)))
                let s := mload(search)
                for {} 1 {} {
                    let t := mload(subject)
                    // Whether the first `searchLength % 32` bytes of
                    // `subject` and `search` matches.
                    if iszero(shr(m, xor(t, s))) {
                        if h {
                            if iszero(eq(keccak256(subject, searchLength), h)) {
                                mstore(result, t)
                                result := add(result, 1)
                                subject := add(subject, 1)
                                if iszero(lt(subject, subjectSearchEnd)) { break }
                                continue
                            }
                        }
                        // Copy the `replacement` one word at a time.
                        for { let o := 0 } 1 {} {
                            mstore(add(result, o), mload(add(replacement, o)))
                            o := add(o, 0x20)
                            if iszero(lt(o, replacementLength)) { break }
                        }
                        result := add(result, replacementLength)
                        subject := add(subject, searchLength)
                        if searchLength {
                            if iszero(lt(subject, subjectSearchEnd)) { break }
                            continue
                        }
                    }
                    mstore(result, t)
                    result := add(result, 1)
                    subject := add(subject, 1)
                    if iszero(lt(subject, subjectSearchEnd)) { break }
                }
            }

            let resultRemainder := result
            result := add(mload(0x40), 0x20)
            let k := add(sub(resultRemainder, result), sub(subjectEnd, subject))
            // Copy the rest of the string one word at a time.
            for {} lt(subject, subjectEnd) {} {
                mstore(resultRemainder, mload(subject))
                resultRemainder := add(resultRemainder, 0x20)
                subject := add(subject, 0x20)
            }
            result := sub(result, 0x20)
            // Zeroize the slot after the string.
            let last := add(add(result, 0x20), k)
            mstore(last, 0)
            // Allocate memory for the length and the bytes,
            // rounded up to a multiple of 32.
            mstore(0x40, and(add(last, 31), not(31)))
            // Store the length of the result.
            mstore(result, k)
        }
    }

    /// @dev Returns the byte index of the first location of `search` in `subject`,
    /// searching from left to right, starting from `from`.
    /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found.
    function indexOf(string memory subject, string memory search, uint256 from)
        internal
        pure
        returns (uint256 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            for { let subjectLength := mload(subject) } 1 {} {
                if iszero(mload(search)) {
                    // `result = min(from, subjectLength)`.
                    result := xor(from, mul(xor(from, subjectLength), lt(subjectLength, from)))
                    break
                }
                let searchLength := mload(search)
                let subjectStart := add(subject, 0x20)

                result := not(0) // Initialize to `NOT_FOUND`.

                subject := add(subjectStart, from)
                let subjectSearchEnd := add(sub(add(subjectStart, subjectLength), searchLength), 1)

                let m := shl(3, sub(32, and(searchLength, 31)))
                let s := mload(add(search, 0x20))

                if iszero(lt(subject, subjectSearchEnd)) { break }

                if iszero(lt(searchLength, 32)) {
                    for { let h := keccak256(add(search, 0x20), searchLength) } 1 {} {
                        if iszero(shr(m, xor(mload(subject), s))) {
                            if eq(keccak256(subject, searchLength), h) {
                                result := sub(subject, subjectStart)
                                break
                            }
                        }
                        subject := add(subject, 1)
                        if iszero(lt(subject, subjectSearchEnd)) { break }
                    }
                    break
                }
                for {} 1 {} {
                    if iszero(shr(m, xor(mload(subject), s))) {
                        result := sub(subject, subjectStart)
                        break
                    }
                    subject := add(subject, 1)
                    if iszero(lt(subject, subjectSearchEnd)) { break }
                }
                break
            }
        }
    }

    /// @dev Returns the byte index of the first location of `search` in `subject`,
    /// searching from left to right.
    /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found.
    function indexOf(string memory subject, string memory search)
        internal
        pure
        returns (uint256 result)
    {
        result = indexOf(subject, search, 0);
    }

    /// @dev Returns the byte index of the first location of `search` in `subject`,
    /// searching from right to left, starting from `from`.
    /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found.
    function lastIndexOf(string memory subject, string memory search, uint256 from)
        internal
        pure
        returns (uint256 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            for {} 1 {} {
                let searchLength := mload(search)
                let fromMax := sub(mload(subject), searchLength)
                if iszero(gt(fromMax, from)) { from := fromMax }
                if iszero(mload(search)) {
                    result := from
                    break
                }
                result := not(0) // Initialize to `NOT_FOUND`.

                let subjectSearchEnd := sub(add(subject, 0x20), 1)

                subject := add(add(subject, 0x20), from)
                if iszero(gt(subject, subjectSearchEnd)) { break }
                // As this function is not too often used,
                // we shall simply use keccak256 for smaller bytecode size.
                for { let h := keccak256(add(search, 0x20), searchLength) } 1 {} {
                    if eq(keccak256(subject, searchLength), h) {
                        result := sub(subject, add(subjectSearchEnd, 1))
                        break
                    }
                    subject := sub(subject, 1)
                    if iszero(gt(subject, subjectSearchEnd)) { break }
                }
                break
            }
        }
    }

    /// @dev Returns the byte index of the first location of `search` in `subject`,
    /// searching from right to left.
    /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found.
    function lastIndexOf(string memory subject, string memory search)
        internal
        pure
        returns (uint256 result)
    {
        result = lastIndexOf(subject, search, uint256(int256(-1)));
    }

    /// @dev Returns whether `subject` starts with `search`.
    function startsWith(string memory subject, string memory search)
        internal
        pure
        returns (bool result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let searchLength := mload(search)
            // Just using keccak256 directly is actually cheaper.
            // forgefmt: disable-next-item
            result := and(
                iszero(gt(searchLength, mload(subject))),
                eq(
                    keccak256(add(subject, 0x20), searchLength),
                    keccak256(add(search, 0x20), searchLength)
                )
            )
        }
    }

    /// @dev Returns whether `subject` ends with `search`.
    function endsWith(string memory subject, string memory search)
        internal
        pure
        returns (bool result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let searchLength := mload(search)
            let subjectLength := mload(subject)
            // Whether `search` is not longer than `subject`.
            let withinRange := iszero(gt(searchLength, subjectLength))
            // Just using keccak256 directly is actually cheaper.
            // forgefmt: disable-next-item
            result := and(
                withinRange,
                eq(
                    keccak256(
                        // `subject + 0x20 + max(subjectLength - searchLength, 0)`.
                        add(add(subject, 0x20), mul(withinRange, sub(subjectLength, searchLength))),
                        searchLength
                    ),
                    keccak256(add(search, 0x20), searchLength)
                )
            )
        }
    }

    /// @dev Returns `subject` repeated `times`.
    function repeat(string memory subject, uint256 times)
        internal
        pure
        returns (string memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let subjectLength := mload(subject)
            if iszero(or(iszero(times), iszero(subjectLength))) {
                subject := add(subject, 0x20)
                result := mload(0x40)
                let output := add(result, 0x20)
                for {} 1 {} {
                    // Copy the `subject` one word at a time.
                    for { let o := 0 } 1 {} {
                        mstore(add(output, o), mload(add(subject, o)))
                        o := add(o, 0x20)
                        if iszero(lt(o, subjectLength)) { break }
                    }
                    output := add(output, subjectLength)
                    times := sub(times, 1)
                    if iszero(times) { break }
                }
                // Zeroize the slot after the string.
                mstore(output, 0)
                // Store the length.
                let resultLength := sub(output, add(result, 0x20))
                mstore(result, resultLength)
                // Allocate memory for the length and the bytes,
                // rounded up to a multiple of 32.
                mstore(0x40, add(result, and(add(resultLength, 63), not(31))))
            }
        }
    }

    /// @dev Returns a copy of `subject` sliced from `start` to `end` (exclusive).
    /// `start` and `end` are byte offsets.
    function slice(string memory subject, uint256 start, uint256 end)
        internal
        pure
        returns (string memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let subjectLength := mload(subject)
            if iszero(gt(subjectLength, end)) { end := subjectLength }
            if iszero(gt(subjectLength, start)) { start := subjectLength }
            if lt(start, end) {
                result := mload(0x40)
                let resultLength := sub(end, start)
                mstore(result, resultLength)
                subject := add(subject, start)
                let w := not(31)
                // Copy the `subject` one word at a time, backwards.
                for { let o := and(add(resultLength, 31), w) } 1 {} {
                    mstore(add(result, o), mload(add(subject, o)))
                    o := add(o, w) // `sub(o, 0x20)`.
                    if iszero(o) { break }
                }
                // Zeroize the slot after the string.
                mstore(add(add(result, 0x20), resultLength), 0)
                // Allocate memory for the length and the bytes,
                // rounded up to a multiple of 32.
                mstore(0x40, add(result, and(add(resultLength, 63), w)))
            }
        }
    }

    /// @dev Returns a copy of `subject` sliced from `start` to the end of the string.
    /// `start` is a byte offset.
    function slice(string memory subject, uint256 start)
        internal
        pure
        returns (string memory result)
    {
        result = slice(subject, start, uint256(int256(-1)));
    }

    /// @dev Returns all the indices of `search` in `subject`.
    /// The indices are byte offsets.
    function indicesOf(string memory subject, string memory search)
        internal
        pure
        returns (uint256[] memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let subjectLength := mload(subject)
            let searchLength := mload(search)

            if iszero(gt(searchLength, subjectLength)) {
                subject := add(subject, 0x20)
                search := add(search, 0x20)
                result := add(mload(0x40), 0x20)

                let subjectStart := subject
                let subjectSearchEnd := add(sub(add(subject, subjectLength), searchLength), 1)
                let h := 0
                if iszero(lt(searchLength, 32)) { h := keccak256(search, searchLength) }
                let m := shl(3, sub(32, and(searchLength, 31)))
                let s := mload(search)
                for {} 1 {} {
                    let t := mload(subject)
                    // Whether the first `searchLength % 32` bytes of
                    // `subject` and `search` matches.
                    if iszero(shr(m, xor(t, s))) {
                        if h {
                            if iszero(eq(keccak256(subject, searchLength), h)) {
                                subject := add(subject, 1)
                                if iszero(lt(subject, subjectSearchEnd)) { break }
                                continue
                            }
                        }
                        // Append to `result`.
                        mstore(result, sub(subject, subjectStart))
                        result := add(result, 0x20)
                        // Advance `subject` by `searchLength`.
                        subject := add(subject, searchLength)
                        if searchLength {
                            if iszero(lt(subject, subjectSearchEnd)) { break }
                            continue
                        }
                    }
                    subject := add(subject, 1)
                    if iszero(lt(subject, subjectSearchEnd)) { break }
                }
                let resultEnd := result
                // Assign `result` to the free memory pointer.
                result := mload(0x40)
                // Store the length of `result`.
                mstore(result, shr(5, sub(resultEnd, add(result, 0x20))))
                // Allocate memory for result.
                // We allocate one more word, so this array can be recycled for {split}.
                mstore(0x40, add(resultEnd, 0x20))
            }
        }
    }

    /// @dev Returns a arrays of strings based on the `delimiter` inside of the `subject` string.
    function split(string memory subject, string memory delimiter)
        internal
        pure
        returns (string[] memory result)
    {
        uint256[] memory indices = indicesOf(subject, delimiter);
        /// @solidity memory-safe-assembly
        assembly {
            let w := not(31)
            let indexPtr := add(indices, 0x20)
            let indicesEnd := add(indexPtr, shl(5, add(mload(indices), 1)))
            mstore(add(indicesEnd, w), mload(subject))
            mstore(indices, add(mload(indices), 1))
            let prevIndex := 0
            for {} 1 {} {
                let index := mload(indexPtr)
                mstore(indexPtr, 0x60)
                if iszero(eq(index, prevIndex)) {
                    let element := mload(0x40)
                    let elementLength := sub(index, prevIndex)
                    mstore(element, elementLength)
                    // Copy the `subject` one word at a time, backwards.
                    for { let o := and(add(elementLength, 31), w) } 1 {} {
                        mstore(add(element, o), mload(add(add(subject, prevIndex), o)))
                        o := add(o, w) // `sub(o, 0x20)`.
                        if iszero(o) { break }
                    }
                    // Zeroize the slot after the string.
                    mstore(add(add(element, 0x20), elementLength), 0)
                    // Allocate memory for the length and the bytes,
                    // rounded up to a multiple of 32.
                    mstore(0x40, add(element, and(add(elementLength, 63), w)))
                    // Store the `element` into the array.
                    mstore(indexPtr, element)
                }
                prevIndex := add(index, mload(delimiter))
                indexPtr := add(indexPtr, 0x20)
                if iszero(lt(indexPtr, indicesEnd)) { break }
            }
            result := indices
            if iszero(mload(delimiter)) {
                result := add(indices, 0x20)
                mstore(result, sub(mload(indices), 2))
            }
        }
    }

    /// @dev Returns a concatenated string of `a` and `b`.
    /// Cheaper than `string.concat()` and does not de-align the free memory pointer.
    function concat(string memory a, string memory b)
        internal
        pure
        returns (string memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let w := not(31)
            result := mload(0x40)
            let aLength := mload(a)
            // Copy `a` one word at a time, backwards.
            for { let o := and(add(mload(a), 32), w) } 1 {} {
                mstore(add(result, o), mload(add(a, o)))
                o := add(o, w) // `sub(o, 0x20)`.
                if iszero(o) { break }
            }
            let bLength := mload(b)
            let output := add(result, mload(a))
            // Copy `b` one word at a time, backwards.
            for { let o := and(add(bLength, 32), w) } 1 {} {
                mstore(add(output, o), mload(add(b, o)))
                o := add(o, w) // `sub(o, 0x20)`.
                if iszero(o) { break }
            }
            let totalLength := add(aLength, bLength)
            let last := add(add(result, 0x20), totalLength)
            // Zeroize the slot after the string.
            mstore(last, 0)
            // Stores the length.
            mstore(result, totalLength)
            // Allocate memory for the length and the bytes,
            // rounded up to a multiple of 32.
            mstore(0x40, and(add(last, 31), w))
        }
    }

    /// @dev Returns a copy of the string in either lowercase or UPPERCASE.
    function toCase(string memory subject, bool toUpper)
        internal
        pure
        returns (string memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let length := mload(subject)
            if length {
                result := add(mload(0x40), 0x20)
                subject := add(subject, 1)
                let flags := shl(add(70, shl(5, toUpper)), 67108863)
                let w := not(0)
                for { let o := length } 1 {} {
                    o := add(o, w)
                    let b := and(0xff, mload(add(subject, o)))
                    mstore8(add(result, o), xor(b, and(shr(b, flags), 0x20)))
                    if iszero(o) { break }
                }
                // Restore the result.
                result := mload(0x40)
                // Stores the string length.
                mstore(result, length)
                // Zeroize the slot after the string.
                let last := add(add(result, 0x20), length)
                mstore(last, 0)
                // Allocate memory for the length and the bytes,
                // rounded up to a multiple of 32.
                mstore(0x40, and(add(last, 31), not(31)))
            }
        }
    }

    /// @dev Returns a lowercased copy of the string.
    function lower(string memory subject) internal pure returns (string memory result) {
        result = toCase(subject, false);
    }

    /// @dev Returns an UPPERCASED copy of the string.
    function upper(string memory subject) internal pure returns (string memory result) {
        result = toCase(subject, true);
    }

    /// @dev Escapes the string to be used within HTML tags.
    function escapeHTML(string memory s) internal pure returns (string memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            for {
                let end := add(s, mload(s))
                result := add(mload(0x40), 0x20)
                // Store the bytes of the packed offsets and strides into the scratch space.
                // `packed = (stride << 5) | offset`. Max offset is 20. Max stride is 6.
                mstore(0x1f, 0x900094)
                mstore(0x08, 0xc0000000a6ab)
                // Store "&quot;&amp;&#39;&lt;&gt;" into the scratch space.
                mstore(0x00, shl(64, 0x2671756f743b26616d703b262333393b266c743b2667743b))
            } iszero(eq(s, end)) {} {
                s := add(s, 1)
                let c := and(mload(s), 0xff)
                // Not in `["\"","'","&","<",">"]`.
                if iszero(and(shl(c, 1), 0x500000c400000000)) {
                    mstore8(result, c)
                    result := add(result, 1)
                    continue
                }
                let t := shr(248, mload(c))
                mstore(result, mload(and(t, 31)))
                result := add(result, shr(5, t))
            }
            let last := result
            // Zeroize the slot after the string.
            mstore(last, 0)
            // Restore the result to the start of the free memory.
            result := mload(0x40)
            // Store the length of the result.
            mstore(result, sub(last, add(result, 0x20)))
            // Allocate memory for the length and the bytes,
            // rounded up to a multiple of 32.
            mstore(0x40, and(add(last, 31), not(31)))
        }
    }

    /// @dev Escapes the string to be used within double-quotes in a JSON.
    function escapeJSON(string memory s) internal pure returns (string memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            for {
                let end := add(s, mload(s))
                result := add(mload(0x40), 0x20)
                // Store "\\u0000" in scratch space.
                // Store "0123456789abcdef" in scratch space.
                // Also, store `{0x08:"b", 0x09:"t", 0x0a:"n", 0x0c:"f", 0x0d:"r"}`.
                // into the scratch space.
                mstore(0x15, 0x5c75303030303031323334353637383961626364656662746e006672)
                // Bitmask for detecting `["\"","\\"]`.
                let e := or(shl(0x22, 1), shl(0x5c, 1))
            } iszero(eq(s, end)) {} {
                s := add(s, 1)
                let c := and(mload(s), 0xff)
                if iszero(lt(c, 0x20)) {
                    if iszero(and(shl(c, 1), e)) {
                        // Not in `["\"","\\"]`.
                        mstore8(result, c)
                        result := add(result, 1)
                        continue
                    }
                    mstore8(result, 0x5c) // "\\".
                    mstore8(add(result, 1), c)
                    result := add(result, 2)
                    continue
                }
                if iszero(and(shl(c, 1), 0x3700)) {
                    // Not in `["\b","\t","\n","\f","\d"]`.
                    mstore8(0x1d, mload(shr(4, c))) // Hex value.
                    mstore8(0x1e, mload(and(c, 15))) // Hex value.
                    mstore(result, mload(0x19)) // "\\u00XX".
                    result := add(result, 6)
                    continue
                }
                mstore8(result, 0x5c) // "\\".
                mstore8(add(result, 1), mload(add(c, 8)))
                result := add(result, 2)
            }
            let last := result
            // Zeroize the slot after the string.
            mstore(last, 0)
            // Restore the result to the start of the free memory.
            result := mload(0x40)
            // Store the length of the result.
            mstore(result, sub(last, add(result, 0x20)))
            // Allocate memory for the length and the bytes,
            // rounded up to a multiple of 32.
            mstore(0x40, and(add(last, 31), not(31)))
        }
    }

    /// @dev Returns whether `a` equals `b`.
    function eq(string memory a, string memory b) internal pure returns (bool result) {
        assembly {
            result := eq(keccak256(add(a, 0x20), mload(a)), keccak256(add(b, 0x20), mload(b)))
        }
    }

    /// @dev Packs a single string with its length into a single word.
    /// Returns `bytes32(0)` if the length is zero or greater than 31.
    function packOne(string memory a) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            // We don't need to zero right pad the string,
            // since this is our own custom non-standard packing scheme.
            result :=
                mul(
                    // Load the length and the bytes.
                    mload(add(a, 0x1f)),
                    // `length != 0 && length < 32`. Abuses underflow.
                    // Assumes that the length is valid and within the block gas limit.
                    lt(sub(mload(a), 1), 0x1f)
                )
        }
    }

    /// @dev Unpacks a string packed using {packOne}.
    /// Returns the empty string if `packed` is `bytes32(0)`.
    /// If `packed` is not an output of {packOne}, the output behaviour is undefined.
    function unpackOne(bytes32 packed) internal pure returns (string memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            // Grab the free memory pointer.
            result := mload(0x40)
            // Allocate 2 words (1 for the length, 1 for the bytes).
            mstore(0x40, add(result, 0x40))
            // Zeroize the length slot.
            mstore(result, 0)
            // Store the length and bytes.
            mstore(add(result, 0x1f), packed)
            // Right pad with zeroes.
            mstore(add(add(result, 0x20), mload(result)), 0)
        }
    }

    /// @dev Packs two strings with their lengths into a single word.
    /// Returns `bytes32(0)` if combined length is zero or greater than 30.
    function packTwo(string memory a, string memory b) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let aLength := mload(a)
            // We don't need to zero right pad the strings,
            // since this is our own custom non-standard packing scheme.
            result :=
                mul(
                    // Load the length and the bytes of `a` and `b`.
                    or(
                        shl(shl(3, sub(0x1f, aLength)), mload(add(a, aLength))),
                        mload(sub(add(b, 0x1e), aLength))
                    ),
                    // `totalLength != 0 && totalLength < 31`. Abuses underflow.
                    // Assumes that the lengths are valid and within the block gas limit.
                    lt(sub(add(aLength, mload(b)), 1), 0x1e)
                )
        }
    }

    /// @dev Unpacks strings packed using {packTwo}.
    /// Returns the empty strings if `packed` is `bytes32(0)`.
    /// If `packed` is not an output of {packTwo}, the output behaviour is undefined.
    function unpackTwo(bytes32 packed)
        internal
        pure
        returns (string memory resultA, string memory resultB)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Grab the free memory pointer.
            resultA := mload(0x40)
            resultB := add(resultA, 0x40)
            // Allocate 2 words for each string (1 for the length, 1 for the byte). Total 4 words.
            mstore(0x40, add(resultB, 0x40))
            // Zeroize the length slots.
            mstore(resultA, 0)
            mstore(resultB, 0)
            // Store the lengths and bytes.
            mstore(add(resultA, 0x1f), packed)
            mstore(add(resultB, 0x1f), mload(add(add(resultA, 0x20), mload(resultA))))
            // Right pad with zeroes.
            mstore(add(add(resultA, 0x20), mload(resultA)), 0)
            mstore(add(add(resultB, 0x20), mload(resultB)), 0)
        }
    }

    /// @dev Directly returns `a` without copying.
    function directReturn(string memory a) internal pure {
        assembly {
            // Assumes that the string does not start from the scratch space.
            let retStart := sub(a, 0x20)
            let retSize := add(mload(a), 0x40)
            // Right pad with zeroes. Just in case the string is produced
            // by a method that doesn't zero right pad.
            mstore(add(retStart, retSize), 0)
            // Store the return offset.
            mstore(retStart, 0x20)
            // End the transaction, returning the string.
            return(retStart, retSize)
        }
    }
}

// File: solady/src/utils/ECDSA.sol


pragma solidity ^0.8.4;

/// @notice Gas optimized ECDSA wrapper.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ECDSA.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ECDSA.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/ECDSA.sol)
library ECDSA {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The number which `s` must not exceed in order for
    /// the signature to be non-malleable.
    bytes32 private constant _MALLEABILITY_THRESHOLD =
        0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                    RECOVERY OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the `signature`.
    ///
    /// This function does NOT accept EIP-2098 short form signatures.
    /// Use `recover(bytes32 hash, bytes32 r, bytes32 vs)` for EIP-2098
    /// short form signatures instead.
    ///
    /// WARNING!
    /// The `result` will be the zero address upon recovery failure.
    /// As such, it is extremely important to ensure that the address which
    /// the `result` is compared against is never zero.
    function recover(bytes32 hash, bytes calldata signature)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            if eq(signature.length, 65) {
                // Copy the free memory pointer so that we can restore it later.
                let m := mload(0x40)
                // Directly copy `r` and `s` from the calldata.
                calldatacopy(0x40, signature.offset, 0x40)

                // If `s` in lower half order, such that the signature is not malleable.
                if iszero(gt(mload(0x60), _MALLEABILITY_THRESHOLD)) {
                    mstore(0x00, hash)
                    // Compute `v` and store it in the scratch space.
                    mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40))))
                    pop(
                        staticcall(
                            gas(), // Amount of gas left for the transaction.
                            0x01, // Address of `ecrecover`.
                            0x00, // Start of input.
                            0x80, // Size of input.
                            0x40, // Start of output.
                            0x20 // Size of output.
                        )
                    )
                    // Restore the zero slot.
                    mstore(0x60, 0)
                    // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                    result := mload(sub(0x60, returndatasize()))
                }
                // Restore the free memory pointer.
                mstore(0x40, m)
            }
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the EIP-2098 short form signature defined by `r` and `vs`.
    ///
    /// This function only accepts EIP-2098 short form signatures.
    /// See: https://eips.ethereum.org/EIPS/eip-2098
    ///
    /// To be honest, I do not recommend using EIP-2098 signatures
    /// for simplicity, performance, and security reasons. Most if not
    /// all clients support traditional non EIP-2098 signatures by default.
    /// As such, this method is intentionally not fully inlined.
    /// It is merely included for completeness.
    ///
    /// WARNING!
    /// The `result` will be the zero address upon recovery failure.
    /// As such, it is extremely important to ensure that the address which
    /// the `result` is compared against is never zero.
    function recover(bytes32 hash, bytes32 r, bytes32 vs) internal view returns (address result) {
        uint8 v;
        bytes32 s;
        /// @solidity memory-safe-assembly
        assembly {
            s := shr(1, shl(1, vs))
            v := add(shr(255, vs), 27)
        }
        result = recover(hash, v, r, s);
    }

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the signature defined by `v`, `r`, `s`.
    ///
    /// WARNING!
    /// The `result` will be the zero address upon recovery failure.
    /// As such, it is extremely important to ensure that the address which
    /// the `result` is compared against is never zero.
    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Copy the free memory pointer so that we can restore it later.
            let m := mload(0x40)

            // If `s` in lower half order, such that the signature is not malleable.
            if iszero(gt(s, _MALLEABILITY_THRESHOLD)) {
                mstore(0x00, hash)
                mstore(0x20, v)
                mstore(0x40, r)
                mstore(0x60, s)
                pop(
                    staticcall(
                        gas(), // Amount of gas left for the transaction.
                        0x01, // Address of `ecrecover`.
                        0x00, // Start of input.
                        0x80, // Size of input.
                        0x40, // Start of output.
                        0x20 // Size of output.
                    )
                )
                // Restore the zero slot.
                mstore(0x60, 0)
                // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                result := mload(sub(0x60, returndatasize()))
            }
            // Restore the free memory pointer.
            mstore(0x40, m)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     HASHING OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns an Ethereum Signed Message, created from a `hash`.
    /// This produces a hash corresponding to the one signed with the
    /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)
    /// JSON-RPC method as part of EIP-191.
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            // Store into scratch space for keccak256.
            mstore(0x20, hash)
            mstore(0x00, "\x00\x00\x00\x00\x19Ethereum Signed Message:\n32")
            // 0x40 - 0x04 = 0x3c
            result := keccak256(0x04, 0x3c)
        }
    }

    /// @dev Returns an Ethereum Signed Message, created from `s`.
    /// This produces a hash corresponding to the one signed with the
    /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)
    /// JSON-RPC method as part of EIP-191.
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) {
        assembly {
            // We need at most 128 bytes for Ethereum signed message header.
            // The max length of the ASCII reprenstation of a uint256 is 78 bytes.
            // The length of "\x19Ethereum Signed Message:\n" is 26 bytes (i.e. 0x1a).
            // The next multiple of 32 above 78 + 26 is 128 (i.e. 0x80).

            // Instead of allocating, we temporarily copy the 128 bytes before the
            // start of `s` data to some variables.
            let m3 := mload(sub(s, 0x60))
            let m2 := mload(sub(s, 0x40))
            let m1 := mload(sub(s, 0x20))
            // The length of `s` is in bytes.
            let sLength := mload(s)

            let ptr := add(s, 0x20)

            // `end` marks the end of the memory which we will compute the keccak256 of.
            let end := add(ptr, sLength)

            // Convert the length of the bytes to ASCII decimal representation
            // and store it into the memory.
            for { let temp := sLength } 1 {} {
                ptr := sub(ptr, 1)
                mstore8(ptr, add(48, mod(temp, 10)))
                temp := div(temp, 10)
                if iszero(temp) { break }
            }

            // Copy the header over to the memory.
            mstore(sub(ptr, 0x20), "\x00\x00\x00\x00\x00\x00\x19Ethereum Signed Message:\n")
            // Compute the keccak256 of the memory.
            result := keccak256(sub(ptr, 0x1a), sub(end, sub(ptr, 0x1a)))

            // Restore the previous memory.
            mstore(s, sLength)
            mstore(sub(s, 0x20), m1)
            mstore(sub(s, 0x40), m2)
            mstore(sub(s, 0x60), m3)
        }
    }
}

// File: erc721a/contracts/IERC721A.sol


// ERC721A Contracts v4.2.3
// Creator: Chiru Labs

pragma solidity ^0.8.4;

/**
 * @dev Interface of ERC721A.
 */
interface IERC721A {
    /**
     * The caller must own the token or be an approved operator.
     */
    error ApprovalCallerNotOwnerNorApproved();

    /**
     * The token does not exist.
     */
    error ApprovalQueryForNonexistentToken();

    /**
     * Cannot query the balance for the zero address.
     */
    error BalanceQueryForZeroAddress();

    /**
     * Cannot mint to the zero address.
     */
    error MintToZeroAddress();

    /**
     * The quantity of tokens minted must be more than zero.
     */
    error MintZeroQuantity();

    /**
     * The token does not exist.
     */
    error OwnerQueryForNonexistentToken();

    /**
     * The caller must own the token or be an approved operator.
     */
    error TransferCallerNotOwnerNorApproved();

    /**
     * The token must be owned by `from`.
     */
    error TransferFromIncorrectOwner();

    /**
     * Cannot safely transfer to a contract that does not implement the
     * ERC721Receiver interface.
     */
    error TransferToNonERC721ReceiverImplementer();

    /**
     * Cannot transfer to the zero address.
     */
    error TransferToZeroAddress();

    /**
     * The token does not exist.
     */
    error URIQueryForNonexistentToken();

    /**
     * The `quantity` minted with ERC2309 exceeds the safety limit.
     */
    error MintERC2309QuantityExceedsLimit();

    /**
     * The `extraData` cannot be set on an unintialized ownership slot.
     */
    error OwnershipNotInitializedForExtraData();

    // =============================================================
    //                            STRUCTS
    // =============================================================

    struct TokenOwnership {
        // The address of the owner.
        address addr;
        // Stores the start time of ownership with minimal overhead for tokenomics.
        uint64 startTimestamp;
        // Whether the token has been burned.
        bool burned;
        // Arbitrary data similar to `startTimestamp` that can be set via {_extraData}.
        uint24 extraData;
    }

    // =============================================================
    //                         TOKEN COUNTERS
    // =============================================================

    /**
     * @dev Returns the total number of tokens in existence.
     * Burned tokens will reduce the count.
     * To get the total number of tokens minted, please see {_totalMinted}.
     */
    function totalSupply() external view returns (uint256);

    // =============================================================
    //                            IERC165
    // =============================================================

    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified)
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);

    // =============================================================
    //                            IERC721
    // =============================================================

    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

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

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

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

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

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

    /**
     * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external payable;

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom}
     * whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token
     * by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external payable;

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

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

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

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

    // =============================================================
    //                        IERC721Metadata
    // =============================================================

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

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

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

    // =============================================================
    //                           IERC2309
    // =============================================================

    /**
     * @dev Emitted when tokens in `fromTokenId` to `toTokenId`
     * (inclusive) is transferred from `from` to `to`, as defined in the
     * [ERC2309](https://eips.ethereum.org/EIPS/eip-2309) standard.
     *
     * See {_mintERC2309} for more details.
     */
    event ConsecutiveTransfer(uint256 indexed fromTokenId, uint256 toTokenId, address indexed from, address indexed to);
}

// File: erc721a/contracts/extensions/IERC721AQueryable.sol


// ERC721A Contracts v4.2.3
// Creator: Chiru Labs

pragma solidity ^0.8.4;


/**
 * @dev Interface of ERC721AQueryable.
 */
interface IERC721AQueryable is IERC721A {
    /**
     * Invalid query range (`start` >= `stop`).
     */
    error InvalidQueryRange();

    /**
     * @dev Returns the `TokenOwnership` struct at `tokenId` without reverting.
     *
     * If the `tokenId` is out of bounds:
     *
     * - `addr = address(0)`
     * - `startTimestamp = 0`
     * - `burned = false`
     * - `extraData = 0`
     *
     * If the `tokenId` is burned:
     *
     * - `addr = <Address of owner before token was burned>`
     * - `startTimestamp = <Timestamp when token was burned>`
     * - `burned = true`
     * - `extraData = <Extra data when token was burned>`
     *
     * Otherwise:
     *
     * - `addr = <Address of owner>`
     * - `startTimestamp = <Timestamp of start of ownership>`
     * - `burned = false`
     * - `extraData = <Extra data at start of ownership>`
     */
    function explicitOwnershipOf(uint256 tokenId) external view returns (TokenOwnership memory);

    /**
     * @dev Returns an array of `TokenOwnership` structs at `tokenIds` in order.
     * See {ERC721AQueryable-explicitOwnershipOf}
     */
    function explicitOwnershipsOf(uint256[] memory tokenIds) external view returns (TokenOwnership[] memory);

    /**
     * @dev Returns an array of token IDs owned by `owner`,
     * in the range [`start`, `stop`)
     * (i.e. `start <= tokenId < stop`).
     *
     * This function allows for tokens to be queried if the collection
     * grows too big for a single call of {ERC721AQueryable-tokensOfOwner}.
     *
     * Requirements:
     *
     * - `start < stop`
     */
    function tokensOfOwnerIn(
        address owner,
        uint256 start,
        uint256 stop
    ) external view returns (uint256[] memory);

    /**
     * @dev Returns an array of token IDs owned by `owner`.
     *
     * This function scans the ownership mapping and is O(`totalSupply`) in complexity.
     * It is meant to be called off-chain.
     *
     * See {ERC721AQueryable-tokensOfOwnerIn} for splitting the scan into
     * multiple smaller scans if the collection is large enough to cause
     * an out-of-gas error (10K collections should be fine).
     */
    function tokensOfOwner(address owner) external view returns (uint256[] memory);
}

// File: erc721a/contracts/ERC721A.sol


// ERC721A Contracts v4.2.3
// Creator: Chiru Labs

pragma solidity ^0.8.4;


/**
 * @dev Interface of ERC721 token receiver.
 */
interface ERC721A__IERC721Receiver {
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

/**
 * @title ERC721A
 *
 * @dev Implementation of the [ERC721](https://eips.ethereum.org/EIPS/eip-721)
 * Non-Fungible Token Standard, including the Metadata extension.
 * Optimized for lower gas during batch mints.
 *
 * Token IDs are minted in sequential order (e.g. 0, 1, 2, 3, ...)
 * starting from `_startTokenId()`.
 *
 * Assumptions:
 *
 * - An owner cannot have more than 2**64 - 1 (max value of uint64) of supply.
 * - The maximum token ID cannot exceed 2**256 - 1 (max value of uint256).
 */
contract ERC721A is IERC721A {
    // Bypass for a `--via-ir` bug (https://github.com/chiru-labs/ERC721A/pull/364).
    struct TokenApprovalRef {
        address value;
    }

    // =============================================================
    //                           CONSTANTS
    // =============================================================

    // Mask of an entry in packed address data.
    uint256 private constant _BITMASK_ADDRESS_DATA_ENTRY = (1 << 64) - 1;

    // The bit position of `numberMinted` in packed address data.
    uint256 private constant _BITPOS_NUMBER_MINTED = 64;

    // The bit position of `numberBurned` in packed address data.
    uint256 private constant _BITPOS_NUMBER_BURNED = 128;

    // The bit position of `aux` in packed address data.
    uint256 private constant _BITPOS_AUX = 192;

    // Mask of all 256 bits in packed address data except the 64 bits for `aux`.
    uint256 private constant _BITMASK_AUX_COMPLEMENT = (1 << 192) - 1;

    // The bit position of `startTimestamp` in packed ownership.
    uint256 private constant _BITPOS_START_TIMESTAMP = 160;

    // The bit mask of the `burned` bit in packed ownership.
    uint256 private constant _BITMASK_BURNED = 1 << 224;

    // The bit position of the `nextInitialized` bit in packed ownership.
    uint256 private constant _BITPOS_NEXT_INITIALIZED = 225;

    // The bit mask of the `nextInitialized` bit in packed ownership.
    uint256 private constant _BITMASK_NEXT_INITIALIZED = 1 << 225;

    // The bit position of `extraData` in packed ownership.
    uint256 private constant _BITPOS_EXTRA_DATA = 232;

    // Mask of all 256 bits in a packed ownership except the 24 bits for `extraData`.
    uint256 private constant _BITMASK_EXTRA_DATA_COMPLEMENT = (1 << 232) - 1;

    // The mask of the lower 160 bits for addresses.
    uint256 private constant _BITMASK_ADDRESS = (1 << 160) - 1;

    // The maximum `quantity` that can be minted with {_mintERC2309}.
    // This limit is to prevent overflows on the address data entries.
    // For a limit of 5000, a total of 3.689e15 calls to {_mintERC2309}
    // is required to cause an overflow, which is unrealistic.
    uint256 private constant _MAX_MINT_ERC2309_QUANTITY_LIMIT = 5000;

    // The `Transfer` event signature is given by:
    // `keccak256(bytes("Transfer(address,address,uint256)"))`.
    bytes32 private constant _TRANSFER_EVENT_SIGNATURE =
        0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;

    // =============================================================
    //                            STORAGE
    // =============================================================

    // The next token ID to be minted.
    uint256 private _currentIndex;

    // The number of tokens burned.
    uint256 private _burnCounter;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Mapping from token ID to ownership details
    // An empty struct value does not necessarily mean the token is unowned.
    // See {_packedOwnershipOf} implementation for details.
    //
    // Bits Layout:
    // - [0..159]   `addr`
    // - [160..223] `startTimestamp`
    // - [224]      `burned`
    // - [225]      `nextInitialized`
    // - [232..255] `extraData`
    mapping(uint256 => uint256) private _packedOwnerships;

    // Mapping owner address to address data.
    //
    // Bits Layout:
    // - [0..63]    `balance`
    // - [64..127]  `numberMinted`
    // - [128..191] `numberBurned`
    // - [192..255] `aux`
    mapping(address => uint256) private _packedAddressData;

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

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

    // =============================================================
    //                          CONSTRUCTOR
    // =============================================================

    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
        _currentIndex = _startTokenId();
    }

    // =============================================================
    //                   TOKEN COUNTING OPERATIONS
    // =============================================================

    /**
     * @dev Returns the starting token ID.
     * To change the starting token ID, please override this function.
     */
    function _startTokenId() internal view virtual returns (uint256) {
        return 0;
    }

    /**
     * @dev Returns the next token ID to be minted.
     */
    function _nextTokenId() internal view virtual returns (uint256) {
        return _currentIndex;
    }

    /**
     * @dev Returns the total number of tokens in existence.
     * Burned tokens will reduce the count.
     * To get the total number of tokens minted, please see {_totalMinted}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        // Counter underflow is impossible as _burnCounter cannot be incremented
        // more than `_currentIndex - _startTokenId()` times.
        unchecked {
            return _currentIndex - _burnCounter - _startTokenId();
        }
    }

    /**
     * @dev Returns the total amount of tokens minted in the contract.
     */
    function _totalMinted() internal view virtual returns (uint256) {
        // Counter underflow is impossible as `_currentIndex` does not decrement,
        // and it is initialized to `_startTokenId()`.
        unchecked {
            return _currentIndex - _startTokenId();
        }
    }

    /**
     * @dev Returns the total number of tokens burned.
     */
    function _totalBurned() internal view virtual returns (uint256) {
        return _burnCounter;
    }

    // =============================================================
    //                    ADDRESS DATA OPERATIONS
    // =============================================================

    /**
     * @dev Returns the number of tokens in `owner`'s account.
     */
    function balanceOf(address owner) public view virtual override returns (uint256) {
        if (owner == address(0)) revert BalanceQueryForZeroAddress();
        return _packedAddressData[owner] & _BITMASK_ADDRESS_DATA_ENTRY;
    }

    /**
     * Returns the number of tokens minted by `owner`.
     */
    function _numberMinted(address owner) internal view returns (uint256) {
        return (_packedAddressData[owner] >> _BITPOS_NUMBER_MINTED) & _BITMASK_ADDRESS_DATA_ENTRY;
    }

    /**
     * Returns the number of tokens burned by or on behalf of `owner`.
     */
    function _numberBurned(address owner) internal view returns (uint256) {
        return (_packedAddressData[owner] >> _BITPOS_NUMBER_BURNED) & _BITMASK_ADDRESS_DATA_ENTRY;
    }

    /**
     * Returns the auxiliary data for `owner`. (e.g. number of whitelist mint slots used).
     */
    function _getAux(address owner) internal view returns (uint64) {
        return uint64(_packedAddressData[owner] >> _BITPOS_AUX);
    }

    /**
     * Sets the auxiliary data for `owner`. (e.g. number of whitelist mint slots used).
     * If there are multiple variables, please pack them into a uint64.
     */
    function _setAux(address owner, uint64 aux) internal virtual {
        uint256 packed = _packedAddressData[owner];
        uint256 auxCasted;
        // Cast `aux` with assembly to avoid redundant masking.
        assembly {
            auxCasted := aux
        }
        packed = (packed & _BITMASK_AUX_COMPLEMENT) | (auxCasted << _BITPOS_AUX);
        _packedAddressData[owner] = packed;
    }

    // =============================================================
    //                            IERC165
    // =============================================================

    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified)
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30000 gas.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        // The interface IDs are constants representing the first 4 bytes
        // of the XOR of all function selectors in the interface.
        // See: [ERC165](https://eips.ethereum.org/EIPS/eip-165)
        // (e.g. `bytes4(i.functionA.selector ^ i.functionB.selector ^ ...)`)
        return
            interfaceId == 0x01ffc9a7 || // ERC165 interface ID for ERC165.
            interfaceId == 0x80ac58cd || // ERC165 interface ID for ERC721.
            interfaceId == 0x5b5e139f; // ERC165 interface ID for ERC721Metadata.
    }

    // =============================================================
    //                        IERC721Metadata
    // =============================================================

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

    /**
     * @dev Returns the token collection symbol.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        if (!_exists(tokenId)) revert URIQueryForNonexistentToken();

        string memory baseURI = _baseURI();
        return bytes(baseURI).length != 0 ? string(abi.encodePacked(baseURI, _toString(tokenId))) : '';
    }

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

    // =============================================================
    //                     OWNERSHIPS OPERATIONS
    // =============================================================

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) public view virtual override returns (address) {
        return address(uint160(_packedOwnershipOf(tokenId)));
    }

    /**
     * @dev Gas spent here starts off proportional to the maximum mint batch size.
     * It gradually moves to O(1) as tokens get transferred around over time.
     */
    function _ownershipOf(uint256 tokenId) internal view virtual returns (TokenOwnership memory) {
        return _unpackedOwnership(_packedOwnershipOf(tokenId));
    }

    /**
     * @dev Returns the unpacked `TokenOwnership` struct at `index`.
     */
    function _ownershipAt(uint256 index) internal view virtual returns (TokenOwnership memory) {
        return _unpackedOwnership(_packedOwnerships[index]);
    }

    /**
     * @dev Initializes the ownership slot minted at `index` for efficiency purposes.
     */
    function _initializeOwnershipAt(uint256 index) internal virtual {
        if (_packedOwnerships[index] == 0) {
            _packedOwnerships[index] = _packedOwnershipOf(index);
        }
    }

    /**
     * Returns the packed ownership data of `tokenId`.
     */
    function _packedOwnershipOf(uint256 tokenId) private view returns (uint256) {
        uint256 curr = tokenId;

        unchecked {
            if (_startTokenId() <= curr)
                if (curr < _currentIndex) {
                    uint256 packed = _packedOwnerships[curr];
                    // If not burned.
                    if (packed & _BITMASK_BURNED == 0) {
                        // Invariant:
                        // There will always be an initialized ownership slot
                        // (i.e. `ownership.addr != address(0) && ownership.burned == false`)
                        // before an unintialized ownership slot
                        // (i.e. `ownership.addr == address(0) && ownership.burned == false`)
                        // Hence, `curr` will not underflow.
                        //
                        // We can directly compare the packed value.
                        // If the address is zero, packed will be zero.
                        while (packed == 0) {
                            packed = _packedOwnerships[--curr];
                        }
                        return packed;
                    }
                }
        }
        revert OwnerQueryForNonexistentToken();
    }

    /**
     * @dev Returns the unpacked `TokenOwnership` struct from `packed`.
     */
    function _unpackedOwnership(uint256 packed) private pure returns (TokenOwnership memory ownership) {
        ownership.addr = address(uint160(packed));
        ownership.startTimestamp = uint64(packed >> _BITPOS_START_TIMESTAMP);
        ownership.burned = packed & _BITMASK_BURNED != 0;
        ownership.extraData = uint24(packed >> _BITPOS_EXTRA_DATA);
    }

    /**
     * @dev Packs ownership data into a single uint256.
     */
    function _packOwnershipData(address owner, uint256 flags) private view returns (uint256 result) {
        assembly {
            // Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean.
            owner := and(owner, _BITMASK_ADDRESS)
            // `owner | (block.timestamp << _BITPOS_START_TIMESTAMP) | flags`.
            result := or(owner, or(shl(_BITPOS_START_TIMESTAMP, timestamp()), flags))
        }
    }

    /**
     * @dev Returns the `nextInitialized` flag set if `quantity` equals 1.
     */
    function _nextInitializedFlag(uint256 quantity) private pure returns (uint256 result) {
        // For branchless setting of the `nextInitialized` flag.
        assembly {
            // `(quantity == 1) << _BITPOS_NEXT_INITIALIZED`.
            result := shl(_BITPOS_NEXT_INITIALIZED, eq(quantity, 1))
        }
    }

    // =============================================================
    //                      APPROVAL OPERATIONS
    // =============================================================

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

        if (_msgSenderERC721A() != owner)
            if (!isApprovedForAll(owner, _msgSenderERC721A())) {
                revert ApprovalCallerNotOwnerNorApproved();
            }

        _tokenApprovals[tokenId].value = to;
        emit Approval(owner, to, tokenId);
    }

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) public view virtual override returns (address) {
        if (!_exists(tokenId)) revert ApprovalQueryForNonexistentToken();

        return _tokenApprovals[tokenId].value;
    }

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom}
     * for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool approved) public virtual override {
        _operatorApprovals[_msgSenderERC721A()][operator] = approved;
        emit ApprovalForAll(_msgSenderERC721A(), operator, approved);
    }

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

    /**
     * @dev Returns whether `tokenId` exists.
     *
     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
     *
     * Tokens start existing when they are minted. See {_mint}.
     */
    function _exists(uint256 tokenId) internal view virtual returns (bool) {
        return
            _startTokenId() <= tokenId &&
            tokenId < _currentIndex && // If within bounds,
            _packedOwnerships[tokenId] & _BITMASK_BURNED == 0; // and not burned.
    }

    /**
     * @dev Returns whether `msgSender` is equal to `approvedAddress` or `owner`.
     */
    function _isSenderApprovedOrOwner(
        address approvedAddress,
        address owner,
        address msgSender
    ) private pure returns (bool result) {
        assembly {
            // Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean.
            owner := and(owner, _BITMASK_ADDRESS)
            // Mask `msgSender` to the lower 160 bits, in case the upper bits somehow aren't clean.
            msgSender := and(msgSender, _BITMASK_ADDRESS)
            // `msgSender == owner || msgSender == approvedAddress`.
            result := or(eq(msgSender, owner), eq(msgSender, approvedAddress))
        }
    }

    /**
     * @dev Returns the storage slot and value for the approved address of `tokenId`.
     */
    function _getApprovedSlotAndAddress(uint256 tokenId)
        private
        view
        returns (uint256 approvedAddressSlot, address approvedAddress)
    {
        TokenApprovalRef storage tokenApproval = _tokenApprovals[tokenId];
        // The following is equivalent to `approvedAddress = _tokenApprovals[tokenId].value`.
        assembly {
            approvedAddressSlot := tokenApproval.slot
            approvedAddress := sload(approvedAddressSlot)
        }
    }

    // =============================================================
    //                      TRANSFER OPERATIONS
    // =============================================================

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token
     * by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public payable virtual override {
        uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId);

        if (address(uint160(prevOwnershipPacked)) != from) revert TransferFromIncorrectOwner();

        (uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId);

        // The nested ifs save around 20+ gas over a compound boolean condition.
        if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A()))
            if (!isApprovedForAll(from, _msgSenderERC721A())) revert TransferCallerNotOwnerNorApproved();

        if (to == address(0)) revert TransferToZeroAddress();

        _beforeTokenTransfers(from, to, tokenId, 1);

        // Clear approvals from the previous owner.
        assembly {
            if approvedAddress {
                // This is equivalent to `delete _tokenApprovals[tokenId]`.
                sstore(approvedAddressSlot, 0)
            }
        }

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        // Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256.
        unchecked {
            // We can directly increment and decrement the balances.
            --_packedAddressData[from]; // Updates: `balance -= 1`.
            ++_packedAddressData[to]; // Updates: `balance += 1`.

            // Updates:
            // - `address` to the next owner.
            // - `startTimestamp` to the timestamp of transfering.
            // - `burned` to `false`.
            // - `nextInitialized` to `true`.
            _packedOwnerships[tokenId] = _packOwnershipData(
                to,
                _BITMASK_NEXT_INITIALIZED | _nextExtraData(from, to, prevOwnershipPacked)
            );

            // If the next slot may not have been initialized (i.e. `nextInitialized == false`) .
            if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) {
                uint256 nextTokenId = tokenId + 1;
                // If the next slot's address is zero and not burned (i.e. packed value is zero).
                if (_packedOwnerships[nextTokenId] == 0) {
                    // If the next slot is within bounds.
                    if (nextTokenId != _currentIndex) {
                        // Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`.
                        _packedOwnerships[nextTokenId] = prevOwnershipPacked;
                    }
                }
            }
        }

        emit Transfer(from, to, tokenId);
        _afterTokenTransfers(from, to, tokenId, 1);
    }

    /**
     * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public payable virtual override {
        safeTransferFrom(from, to, tokenId, '');
    }

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token
     * by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement
     * {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) public payable virtual override {
        transferFrom(from, to, tokenId);
        if (to.code.length != 0)
            if (!_checkContractOnERC721Received(from, to, tokenId, _data)) {
                revert TransferToNonERC721ReceiverImplementer();
            }
    }

    /**
     * @dev Hook that is called before a set of serially-ordered token IDs
     * are about to be transferred. This includes minting.
     * And also called before burning one token.
     *
     * `startTokenId` - the first token ID to be transferred.
     * `quantity` - the amount to be transferred.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, `from`'s `tokenId` will be
     * transferred to `to`.
     * - When `from` is zero, `tokenId` will be minted for `to`.
     * - When `to` is zero, `tokenId` will be burned by `from`.
     * - `from` and `to` are never both zero.
     */
    function _beforeTokenTransfers(
        address from,
        address to,
        uint256 startTokenId,
        uint256 quantity
    ) internal virtual {}

    /**
     * @dev Hook that is called after a set of serially-ordered token IDs
     * have been transferred. This includes minting.
     * And also called after one token has been burned.
     *
     * `startTokenId` - the first token ID to be transferred.
     * `quantity` - the amount to be transferred.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, `from`'s `tokenId` has been
     * transferred to `to`.
     * - When `from` is zero, `tokenId` has been minted for `to`.
     * - When `to` is zero, `tokenId` has been burned by `from`.
     * - `from` and `to` are never both zero.
     */
    function _afterTokenTransfers(
        address from,
        address to,
        uint256 startTokenId,
        uint256 quantity
    ) internal virtual {}

    /**
     * @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target contract.
     *
     * `from` - Previous owner of the given token ID.
     * `to` - Target address that will receive the token.
     * `tokenId` - Token ID to be transferred.
     * `_data` - Optional data to send along with the call.
     *
     * Returns whether the call correctly returned the expected magic value.
     */
    function _checkContractOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) private returns (bool) {
        try ERC721A__IERC721Receiver(to).onERC721Received(_msgSenderERC721A(), from, tokenId, _data) returns (
            bytes4 retval
        ) {
            return retval == ERC721A__IERC721Receiver(to).onERC721Received.selector;
        } catch (bytes memory reason) {
            if (reason.length == 0) {
                revert TransferToNonERC721ReceiverImplementer();
            } else {
                assembly {
                    revert(add(32, reason), mload(reason))
                }
            }
        }
    }

    // =============================================================
    //                        MINT OPERATIONS
    // =============================================================

    /**
     * @dev Mints `quantity` tokens and transfers them to `to`.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `quantity` must be greater than 0.
     *
     * Emits a {Transfer} event for each mint.
     */
    function _mint(address to, uint256 quantity) internal virtual {
        uint256 startTokenId = _currentIndex;
        if (quantity == 0) revert MintZeroQuantity();

        _beforeTokenTransfers(address(0), to, startTokenId, quantity);

        // Overflows are incredibly unrealistic.
        // `balance` and `numberMinted` have a maximum limit of 2**64.
        // `tokenId` has a maximum limit of 2**256.
        unchecked {
            // Updates:
            // - `balance += quantity`.
            // - `numberMinted += quantity`.
            //
            // We can directly add to the `balance` and `numberMinted`.
            _packedAddressData[to] += quantity * ((1 << _BITPOS_NUMBER_MINTED) | 1);

            // Updates:
            // - `address` to the owner.
            // - `startTimestamp` to the timestamp of minting.
            // - `burned` to `false`.
            // - `nextInitialized` to `quantity == 1`.
            _packedOwnerships[startTokenId] = _packOwnershipData(
                to,
                _nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0)
            );

            uint256 toMasked;
            uint256 end = startTokenId + quantity;

            // Use assembly to loop and emit the `Transfer` event for gas savings.
            // The duplicated `log4` removes an extra check and reduces stack juggling.
            // The assembly, together with the surrounding Solidity code, have been
            // delicately arranged to nudge the compiler into producing optimized opcodes.
            assembly {
                // Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean.
                toMasked := and(to, _BITMASK_ADDRESS)
                // Emit the `Transfer` event.
                log4(
                    0, // Start of data (0, since no data).
                    0, // End of data (0, since no data).
                    _TRANSFER_EVENT_SIGNATURE, // Signature.
                    0, // `address(0)`.
                    toMasked, // `to`.
                    startTokenId // `tokenId`.
                )

                // The `iszero(eq(,))` check ensures that large values of `quantity`
                // that overflows uint256 will make the loop run out of gas.
                // The compiler will optimize the `iszero` away for performance.
                for {
                    let tokenId := add(startTokenId, 1)
                } iszero(eq(tokenId, end)) {
                    tokenId := add(tokenId, 1)
                } {
                    // Emit the `Transfer` event. Similar to above.
                    log4(0, 0, _TRANSFER_EVENT_SIGNATURE, 0, toMasked, tokenId)
                }
            }
            if (toMasked == 0) revert MintToZeroAddress();

            _currentIndex = end;
        }
        _afterTokenTransfers(address(0), to, startTokenId, quantity);
    }

    /**
     * @dev Mints `quantity` tokens and transfers them to `to`.
     *
     * This function is intended for efficient minting only during contract creation.
     *
     * It emits only one {ConsecutiveTransfer} as defined in
     * [ERC2309](https://eips.ethereum.org/EIPS/eip-2309),
     * instead of a sequence of {Transfer} event(s).
     *
     * Calling this function outside of contract creation WILL make your contract
     * non-compliant with the ERC721 standard.
     * For full ERC721 compliance, substituting ERC721 {Transfer} event(s) with the ERC2309
     * {ConsecutiveTransfer} event is only permissible during contract creation.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `quantity` must be greater than 0.
     *
     * Emits a {ConsecutiveTransfer} event.
     */
    function _mintERC2309(address to, uint256 quantity) internal virtual {
        uint256 startTokenId = _currentIndex;
        if (to == address(0)) revert MintToZeroAddress();
        if (quantity == 0) revert MintZeroQuantity();
        if (quantity > _MAX_MINT_ERC2309_QUANTITY_LIMIT) revert MintERC2309QuantityExceedsLimit();

        _beforeTokenTransfers(address(0), to, startTokenId, quantity);

        // Overflows are unrealistic due to the above check for `quantity` to be below the limit.
        unchecked {
            // Updates:
            // - `balance += quantity`.
            // - `numberMinted += quantity`.
            //
            // We can directly add to the `balance` and `numberMinted`.
            _packedAddressData[to] += quantity * ((1 << _BITPOS_NUMBER_MINTED) | 1);

            // Updates:
            // - `address` to the owner.
            // - `startTimestamp` to the timestamp of minting.
            // - `burned` to `false`.
            // - `nextInitialized` to `quantity == 1`.
            _packedOwnerships[startTokenId] = _packOwnershipData(
                to,
                _nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0)
            );

            emit ConsecutiveTransfer(startTokenId, startTokenId + quantity - 1, address(0), to);

            _currentIndex = startTokenId + quantity;
        }
        _afterTokenTransfers(address(0), to, startTokenId, quantity);
    }

    /**
     * @dev Safely mints `quantity` tokens and transfers them to `to`.
     *
     * Requirements:
     *
     * - If `to` refers to a smart contract, it must implement
     * {IERC721Receiver-onERC721Received}, which is called for each safe transfer.
     * - `quantity` must be greater than 0.
     *
     * See {_mint}.
     *
     * Emits a {Transfer} event for each mint.
     */
    function _safeMint(
        address to,
        uint256 quantity,
        bytes memory _data
    ) internal virtual {
        _mint(to, quantity);

        unchecked {
            if (to.code.length != 0) {
                uint256 end = _currentIndex;
                uint256 index = end - quantity;
                do {
                    if (!_checkContractOnERC721Received(address(0), to, index++, _data)) {
                        revert TransferToNonERC721ReceiverImplementer();
                    }
                } while (index < end);
                // Reentrancy protection.
                if (_currentIndex != end) revert();
            }
        }
    }

    /**
     * @dev Equivalent to `_safeMint(to, quantity, '')`.
     */
    function _safeMint(address to, uint256 quantity) internal virtual {
        _safeMint(to, quantity, '');
    }

    // =============================================================
    //                        BURN OPERATIONS
    // =============================================================

    /**
     * @dev Equivalent to `_burn(tokenId, false)`.
     */
    function _burn(uint256 tokenId) internal virtual {
        _burn(tokenId, false);
    }

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId, bool approvalCheck) internal virtual {
        uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId);

        address from = address(uint160(prevOwnershipPacked));

        (uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId);

        if (approvalCheck) {
            // The nested ifs save around 20+ gas over a compound boolean condition.
            if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A()))
                if (!isApprovedForAll(from, _msgSenderERC721A())) revert TransferCallerNotOwnerNorApproved();
        }

        _beforeTokenTransfers(from, address(0), tokenId, 1);

        // Clear approvals from the previous owner.
        assembly {
            if approvedAddress {
                // This is equivalent to `delete _tokenApprovals[tokenId]`.
                sstore(approvedAddressSlot, 0)
            }
        }

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        // Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256.
        unchecked {
            // Updates:
            // - `balance -= 1`.
            // - `numberBurned += 1`.
            //
            // We can directly decrement the balance, and increment the number burned.
            // This is equivalent to `packed -= 1; packed += 1 << _BITPOS_NUMBER_BURNED;`.
            _packedAddressData[from] += (1 << _BITPOS_NUMBER_BURNED) - 1;

            // Updates:
            // - `address` to the last owner.
            // - `startTimestamp` to the timestamp of burning.
            // - `burned` to `true`.
            // - `nextInitialized` to `true`.
            _packedOwnerships[tokenId] = _packOwnershipData(
                from,
                (_BITMASK_BURNED | _BITMASK_NEXT_INITIALIZED) | _nextExtraData(from, address(0), prevOwnershipPacked)
            );

            // If the next slot may not have been initialized (i.e. `nextInitialized == false`) .
            if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) {
                uint256 nextTokenId = tokenId + 1;
                // If the next slot's address is zero and not burned (i.e. packed value is zero).
                if (_packedOwnerships[nextTokenId] == 0) {
                    // If the next slot is within bounds.
                    if (nextTokenId != _currentIndex) {
                        // Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`.
                        _packedOwnerships[nextTokenId] = prevOwnershipPacked;
                    }
                }
            }
        }

        emit Transfer(from, address(0), tokenId);
        _afterTokenTransfers(from, address(0), tokenId, 1);

        // Overflow not possible, as _burnCounter cannot be exceed _currentIndex times.
        unchecked {
            _burnCounter++;
        }
    }

    // =============================================================
    //                     EXTRA DATA OPERATIONS
    // =============================================================

    /**
     * @dev Directly sets the extra data for the ownership data `index`.
     */
    function _setExtraDataAt(uint256 index, uint24 extraData) internal virtual {
        uint256 packed = _packedOwnerships[index];
        if (packed == 0) revert OwnershipNotInitializedForExtraData();
        uint256 extraDataCasted;
        // Cast `extraData` with assembly to avoid redundant masking.
        assembly {
            extraDataCasted := extraData
        }
        packed = (packed & _BITMASK_EXTRA_DATA_COMPLEMENT) | (extraDataCasted << _BITPOS_EXTRA_DATA);
        _packedOwnerships[index] = packed;
    }

    /**
     * @dev Called during each token transfer to set the 24bit `extraData` field.
     * Intended to be overridden by the cosumer contract.
     *
     * `previousExtraData` - the value of `extraData` before transfer.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, `from`'s `tokenId` will be
     * transferred to `to`.
     * - When `from` is zero, `tokenId` will be minted for `to`.
     * - When `to` is zero, `tokenId` will be burned by `from`.
     * - `from` and `to` are never both zero.
     */
    function _extraData(
        address from,
        address to,
        uint24 previousExtraData
    ) internal view virtual returns (uint24) {}

    /**
     * @dev Returns the next extra data for the packed ownership data.
     * The returned result is shifted into position.
     */
    function _nextExtraData(
        address from,
        address to,
        uint256 prevOwnershipPacked
    ) private view returns (uint256) {
        uint24 extraData = uint24(prevOwnershipPacked >> _BITPOS_EXTRA_DATA);
        return uint256(_extraData(from, to, extraData)) << _BITPOS_EXTRA_DATA;
    }

    // =============================================================
    //                       OTHER OPERATIONS
    // =============================================================

    /**
     * @dev Returns the message sender (defaults to `msg.sender`).
     *
     * If you are writing GSN compatible contracts, you need to override this function.
     */
    function _msgSenderERC721A() internal view virtual returns (address) {
        return msg.sender;
    }

    /**
     * @dev Converts a uint256 to its ASCII string decimal representation.
     */
    function _toString(uint256 value) internal pure virtual returns (string memory str) {
        assembly {
            // The maximum value of a uint256 contains 78 digits (1 byte per digit), but
            // we allocate 0xa0 bytes to keep the free memory pointer 32-byte word aligned.
            // We will need 1 word for the trailing zeros padding, 1 word for the length,
            // and 3 words for a maximum of 78 digits. Total: 5 * 0x20 = 0xa0.
            let m := add(mload(0x40), 0xa0)
            // Update the free memory pointer to allocate.
            mstore(0x40, m)
            // Assign the `str` to the end.
            str := sub(m, 0x20)
            // Zeroize the slot after the string.
            mstore(str, 0)

            // Cache the end of the memory to calculate the length later.
            let end := str

            // We write the string from rightmost digit to leftmost digit.
            // The following is essentially a do-while loop that also handles the zero case.
            // prettier-ignore
            for { let temp := value } 1 {} {
                str := sub(str, 1)
                // Write the character to the pointer.
                // The ASCII index of the '0' character is 48.
                mstore8(str, add(48, mod(temp, 10)))
                // Keep dividing `temp` until zero.
                temp := div(temp, 10)
                // prettier-ignore
                if iszero(temp) { break }
            }

            let length := sub(end, str)
            // Move the pointer 32 bytes leftwards to make room for the length.
            str := sub(str, 0x20)
            // Store the length.
            mstore(str, length)
        }
    }
}

// File: erc721a/contracts/extensions/ERC721AQueryable.sol


// ERC721A Contracts v4.2.3
// Creator: Chiru Labs

pragma solidity ^0.8.4;



/**
 * @title ERC721AQueryable.
 *
 * @dev ERC721A subclass with convenience query functions.
 */
abstract contract ERC721AQueryable is ERC721A, IERC721AQueryable {
    /**
     * @dev Returns the `TokenOwnership` struct at `tokenId` without reverting.
     *
     * If the `tokenId` is out of bounds:
     *
     * - `addr = address(0)`
     * - `startTimestamp = 0`
     * - `burned = false`
     * - `extraData = 0`
     *
     * If the `tokenId` is burned:
     *
     * - `addr = <Address of owner before token was burned>`
     * - `startTimestamp = <Timestamp when token was burned>`
     * - `burned = true`
     * - `extraData = <Extra data when token was burned>`
     *
     * Otherwise:
     *
     * - `addr = <Address of owner>`
     * - `startTimestamp = <Timestamp of start of ownership>`
     * - `burned = false`
     * - `extraData = <Extra data at start of ownership>`
     */
    function explicitOwnershipOf(uint256 tokenId) public view virtual override returns (TokenOwnership memory) {
        TokenOwnership memory ownership;
        if (tokenId < _startTokenId() || tokenId >= _nextTokenId()) {
            return ownership;
        }
        ownership = _ownershipAt(tokenId);
        if (ownership.burned) {
            return ownership;
        }
        return _ownershipOf(tokenId);
    }

    /**
     * @dev Returns an array of `TokenOwnership` structs at `tokenIds` in order.
     * See {ERC721AQueryable-explicitOwnershipOf}
     */
    function explicitOwnershipsOf(uint256[] calldata tokenIds)
        external
        view
        virtual
        override
        returns (TokenOwnership[] memory)
    {
        unchecked {
            uint256 tokenIdsLength = tokenIds.length;
            TokenOwnership[] memory ownerships = new TokenOwnership[](tokenIdsLength);
            for (uint256 i; i != tokenIdsLength; ++i) {
                ownerships[i] = explicitOwnershipOf(tokenIds[i]);
            }
            return ownerships;
        }
    }

    /**
     * @dev Returns an array of token IDs owned by `owner`,
     * in the range [`start`, `stop`)
     * (i.e. `start <= tokenId < stop`).
     *
     * This function allows for tokens to be queried if the collection
     * grows too big for a single call of {ERC721AQueryable-tokensOfOwner}.
     *
     * Requirements:
     *
     * - `start < stop`
     */
    function tokensOfOwnerIn(
        address owner,
        uint256 start,
        uint256 stop
    ) external view virtual override returns (uint256[] memory) {
        unchecked {
            if (start >= stop) revert InvalidQueryRange();
            uint256 tokenIdsIdx;
            uint256 stopLimit = _nextTokenId();
            // Set `start = max(start, _startTokenId())`.
            if (start < _startTokenId()) {
                start = _startTokenId();
            }
            // Set `stop = min(stop, stopLimit)`.
            if (stop > stopLimit) {
                stop = stopLimit;
            }
            uint256 tokenIdsMaxLength = balanceOf(owner);
            // Set `tokenIdsMaxLength = min(balanceOf(owner), stop - start)`,
            // to cater for cases where `balanceOf(owner)` is too big.
            if (start < stop) {
                uint256 rangeLength = stop - start;
                if (rangeLength < tokenIdsMaxLength) {
                    tokenIdsMaxLength = rangeLength;
                }
            } else {
                tokenIdsMaxLength = 0;
            }
            uint256[] memory tokenIds = new uint256[](tokenIdsMaxLength);
            if (tokenIdsMaxLength == 0) {
                return tokenIds;
            }
            // We need to call `explicitOwnershipOf(start)`,
            // because the slot at `start` may not be initialized.
            TokenOwnership memory ownership = explicitOwnershipOf(start);
            address currOwnershipAddr;
            // If the starting slot exists (i.e. not burned), initialize `currOwnershipAddr`.
            // `ownership.address` will not be zero, as `start` is clamped to the valid token ID range.
            if (!ownership.burned) {
                currOwnershipAddr = ownership.addr;
            }
            for (uint256 i = start; i != stop && tokenIdsIdx != tokenIdsMaxLength; ++i) {
                ownership = _ownershipAt(i);
                if (ownership.burned) {
                    continue;
                }
                if (ownership.addr != address(0)) {
                    currOwnershipAddr = ownership.addr;
                }
                if (currOwnershipAddr == owner) {
                    tokenIds[tokenIdsIdx++] = i;
                }
            }
            // Downsize the array to fit.
            assembly {
                mstore(tokenIds, tokenIdsIdx)
            }
            return tokenIds;
        }
    }

    /**
     * @dev Returns an array of token IDs owned by `owner`.
     *
     * This function scans the ownership mapping and is O(`totalSupply`) in complexity.
     * It is meant to be called off-chain.
     *
     * See {ERC721AQueryable-tokensOfOwnerIn} for splitting the scan into
     * multiple smaller scans if the collection is large enough to cause
     * an out-of-gas error (10K collections should be fine).
     */
    function tokensOfOwner(address owner) external view virtual override returns (uint256[] memory) {
        unchecked {
            uint256 tokenIdsIdx;
            address currOwnershipAddr;
            uint256 tokenIdsLength = balanceOf(owner);
            uint256[] memory tokenIds = new uint256[](tokenIdsLength);
            TokenOwnership memory ownership;
            for (uint256 i = _startTokenId(); tokenIdsIdx != tokenIdsLength; ++i) {
                ownership = _ownershipAt(i);
                if (ownership.burned) {
                    continue;
                }
                if (ownership.addr != address(0)) {
                    currOwnershipAddr = ownership.addr;
                }
                if (currOwnershipAddr == owner) {
                    tokenIds[tokenIdsIdx++] = i;
                }
            }
            return tokenIds;
        }
    }
}

// File: @openzeppelin/contracts/utils/Context.sol


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

pragma solidity ^0.8.0;

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

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

// File: @openzeppelin/contracts/access/Ownable.sol


// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

pragma solidity ^0.8.0;


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

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

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

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

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

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

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

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

// File: rareparadise.sol


pragma solidity ^0.8.15;







/// @title My NFT XXX
/// @author Optimizoor (https://github.com/Vectorized)
contract RareParadise is ERC721A, ERC721AQueryable, Ownable {
    using ECDSA for bytes32;

    uint256 public constant PRICE_UNIT = 0.001 ether;

    string private _tokenURI;

    address public signer;

    uint8 public maxPerWallet = 4;
    uint8 public maxPerTransaction = 4;
    uint16 public maxSupply = 9999;
    uint16 private _whitelistPriceUnits = _toPriceUnits(0.009 ether);
    uint16 private _publicPriceUnits = _toPriceUnits(0.009 ether);

    bool public paused = true;
    bool public mintLocked;
    bool public maxSupplyLocked;
    bool public tokenURILocked;

    constructor() ERC721A("RareParadise", "RareParadise") {}

    function _startTokenId() internal view virtual override returns (uint256) {
        return 1;
    }

    function tokenURI(uint256 tokenId) public view override(ERC721A, IERC721A) returns (string memory) {
        return LibString.replace(_tokenURI, "{id}", _toString(tokenId));
    }

    function publicPrice() external view returns (uint256) {
        return _toPrice(_publicPriceUnits);
    }

    function whitelistPrice() external view returns (uint256) {
        return _toPrice(_whitelistPriceUnits);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     MINTING FUNCTIONS                      */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    function publicMint(uint256 quantity)
        external
        payable
        mintNotPaused
        requireMintable(quantity)
        requireUserMintable(quantity)
        requireExactPayment(_publicPriceUnits, quantity)
    {
        _mint(msg.sender, quantity);
    }

    function whitelistMint(uint256 quantity, bytes calldata signature)
        external
        payable
        mintNotPaused
        requireMintable(quantity)
        requireUserMintable(quantity)
        requireSignature(signature)
        requireExactPayment(_whitelistPriceUnits, quantity)
    {
        _mint(msg.sender, quantity);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          HELPERS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    function _toPriceUnits(uint256 price) private pure returns (uint16) {
        unchecked {
            require(price % PRICE_UNIT == 0, "Price must be a multiple of PRICE_UNIT.");
            require((price /= PRICE_UNIT) <= type(uint16).max, "Overflow.");
            return uint16(price);
        }
    }

    function _toPrice(uint16 priceUnits) private pure returns (uint256) {
        return uint256(priceUnits) * PRICE_UNIT;
    }

    modifier requireUserMintable(uint256 quantity) {
        unchecked {
            require(quantity <= maxPerTransaction, "Max per transaction reached.");
            require(_numberMinted(msg.sender) + quantity <= maxPerWallet, "Max number minted reached.");
        }
        _;
    }

    modifier requireMintable(uint256 quantity) {
        unchecked {
            require(mintLocked == false, "Locked.");
            require(_totalMinted() + quantity <= maxSupply, "Out of stock!");
        }
        _;
    }

    modifier requireExactPayment(uint16 priceUnits, uint256 quantity) {
        unchecked {
            require(quantity <= 100, "Quantity too high.");
            require(msg.value == _toPrice(priceUnits) * quantity, "Wrong Ether value.");
        }
        _;
    }

    modifier requireSignature(bytes calldata signature) {
        require(
            keccak256(abi.encode(msg.sender)).toEthSignedMessageHash().recover(signature) == signer,
            "Invalid signature."
        );
        _;
    }

    modifier mintNotPaused() {
        require(paused == false, "Paused.");
        _;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      ADMIN FUNCTIONS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    function airdrop(address[] calldata to, uint256 quantity) external onlyOwner requireMintable(quantity * to.length) {
        unchecked {
            for (uint256 i; i != to.length; ++i) {
                _mint(to[i], quantity);
            }
        }
    }

    function setTokenURI(string calldata value) external onlyOwner {
        require(tokenURILocked == false, "Locked.");

        _tokenURI = value;
    }

    function setMaxSupply(uint16 value) external onlyOwner {
        require(maxSupplyLocked == false, "Locked.");

        maxSupply = value;
    }

    function setMaxPerWallet(uint8 value) external onlyOwner {
        maxPerWallet = value;
    }

    function setMaxPerTransaction(uint8 value) external onlyOwner {
        maxPerTransaction = value;
    }

    function setPaused(bool value) external onlyOwner {
        if (value == false) {
            require(maxSupply != 0, "Max supply not set.");
            require(signer != address(0), "Signer not set.");
        }
        paused = value;
    }

    function setSigner(address value) external onlyOwner {
        require(value != address(0), "Signer must not be the zero address.");

        signer = value;
    }

    function lockMint() external onlyOwner {
        mintLocked = true;
    }

    function lockMaxSupply() external onlyOwner {
        maxSupplyLocked = true;
    }

    function lockTokenURI() external onlyOwner {
        tokenURILocked = true;
    }

    function setWhitelistPrice(uint256 value) external onlyOwner {
        _whitelistPriceUnits = _toPriceUnits(value);
    }

    function setPublicPrice(uint256 value) external onlyOwner {
        _publicPriceUnits = _toPriceUnits(value);
    }

    function withdraw() external payable onlyOwner {
        SafeTransferLib.safeTransferETH(msg.sender, address(this).balance);
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ApprovalCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"ApprovalQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[],"name":"InvalidQueryRange","type":"error"},{"inputs":[],"name":"MintERC2309QuantityExceedsLimit","type":"error"},{"inputs":[],"name":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[],"name":"OwnerQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"OwnershipNotInitializedForExtraData","type":"error"},{"inputs":[],"name":"TransferCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[],"name":"URIQueryForNonexistentToken","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toTokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"ConsecutiveTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"PRICE_UNIT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"to","type":"address[]"},{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"airdrop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"explicitOwnershipOf","outputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint64","name":"startTimestamp","type":"uint64"},{"internalType":"bool","name":"burned","type":"bool"},{"internalType":"uint24","name":"extraData","type":"uint24"}],"internalType":"struct IERC721A.TokenOwnership","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"explicitOwnershipsOf","outputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint64","name":"startTimestamp","type":"uint64"},{"internalType":"bool","name":"burned","type":"bool"},{"internalType":"uint24","name":"extraData","type":"uint24"}],"internalType":"struct IERC721A.TokenOwnership[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockMaxSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lockMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lockTokenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"maxPerTransaction","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxPerWallet","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupply","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupplyLocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintLocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"publicMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"publicPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"value","type":"uint8"}],"name":"setMaxPerTransaction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"value","type":"uint8"}],"name":"setMaxPerWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"value","type":"uint16"}],"name":"setMaxSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"value","type":"bool"}],"name":"setPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"setPublicPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"value","type":"address"}],"name":"setSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"value","type":"string"}],"name":"setTokenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"setWhitelistPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"signer","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenURILocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"tokensOfOwner","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"stop","type":"uint256"}],"name":"tokensOfOwnerIn","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"whitelistMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"whitelistPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"payable","type":"function"}]

60806040526004600a60146101000a81548160ff021916908360ff1602179055506004600a60156101000a81548160ff021916908360ff16021790555061270f600a60166101000a81548161ffff021916908361ffff16021790555062000073661ff973cafa8000620001ba60201b60201c565b600a60186101000a81548161ffff021916908361ffff160217905550620000a7661ff973cafa8000620001ba60201b60201c565b600a601a6101000a81548161ffff021916908361ffff1602179055506001600a601c6101000a81548160ff021916908315150217905550348015620000eb57600080fd5b506040518060400160405280600c81526020017f52617265506172616469736500000000000000000000000000000000000000008152506040518060400160405280600c81526020017f52617265506172616469736500000000000000000000000000000000000000008152508160029081620001699190620005db565b5080600390816200017b9190620005db565b506200018c6200028a60201b60201c565b6000819055505050620001b4620001a86200029360201b60201c565b6200029b60201b60201c565b6200080c565b60008066038d7ea4c680008381620001d757620001d6620006c2565b5b06146200021b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620002129062000778565b60405180910390fd5b61ffff801666038d7ea4c6800083816200023a5762000239620006c2565b5b04925082111562000282576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200027990620007ea565b60405180910390fd5b819050919050565b60006001905090565b600033905090565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680620003e357607f821691505b602082108103620003f957620003f86200039b565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302620004637fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262000424565b6200046f868362000424565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b6000620004bc620004b6620004b08462000487565b62000491565b62000487565b9050919050565b6000819050919050565b620004d8836200049b565b620004f0620004e782620004c3565b84845462000431565b825550505050565b600090565b62000507620004f8565b62000514818484620004cd565b505050565b5b818110156200053c5762000530600082620004fd565b6001810190506200051a565b5050565b601f8211156200058b576200055581620003ff565b620005608462000414565b8101602085101562000570578190505b620005886200057f8562000414565b83018262000519565b50505b505050565b600082821c905092915050565b6000620005b06000198460080262000590565b1980831691505092915050565b6000620005cb83836200059d565b9150826002028217905092915050565b620005e68262000361565b67ffffffffffffffff8111156200060257620006016200036c565b5b6200060e8254620003ca565b6200061b82828562000540565b600060209050601f8311600181146200065357600084156200063e578287015190505b6200064a8582620005bd565b865550620006ba565b601f1984166200066386620003ff565b60005b828110156200068d5784890151825560018201915060208501945060208101905062000666565b86831015620006ad5784890151620006a9601f8916826200059d565b8355505b6001600288020188555050505b505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082825260208201905092915050565b7f5072696365206d7573742062652061206d756c7469706c65206f66205052494360008201527f455f554e49542e00000000000000000000000000000000000000000000000000602082015250565b600062000760602783620006f1565b91506200076d8262000702565b604082019050919050565b60006020820190508181036000830152620007938162000751565b9050919050565b7f4f766572666c6f772e0000000000000000000000000000000000000000000000600082015250565b6000620007d2600983620006f1565b9150620007df826200079a565b602082019050919050565b600060208201905081810360008301526200080581620007c3565b9050919050565b6149fb806200081c6000396000f3fe6080604052600436106102885760003560e01c80638da5cb5b1161015a578063c6275255116100c1578063e0df5b6f1161007a578063e0df5b6f14610949578063e985e9c514610972578063ed435e58146109af578063f2fde38b146109da578063fc1a1c3614610a03578063fca76c2614610a2e57610288565b8063c62752551461084d578063c87b56dd14610876578063ccdc7178146108b3578063d5abeb01146108dc578063df3c3a3014610907578063e0b6bb671461093257610288565b8063a945bf8011610113578063a945bf801461074c578063abf08ae114610777578063ac998f45146107a0578063b88d4fde146107cb578063c204642c146107e7578063c23dc68f1461081057610288565b80638da5cb5b1461064957806395d89b411461067457806399a2557a1461069f5780639e852f75146106dc578063a22cb465146106f8578063a8d0466c1461072157610288565b806342842e0e116101fe5780636352211e116101b75780636352211e146105295780636c19e7831461056657806370a082311461058f578063715018a6146105cc578063717d57d3146105e35780638462151c1461060c57610288565b806342842e0e14610438578063453c2310146104545780634b980d671461047f5780635bbb2177146104aa5780635c975abb146104e75780635e5a9e301461051257610288565b806316c38b3c1161025057806316c38b3c1461037757806318160ddd146103a0578063238ac933146103cb57806323b872dd146103f65780632db11544146104125780633ccfd60b1461042e57610288565b806301ffc9a71461028d57806306421c2f146102ca57806306fdde03146102f3578063081812fc1461031e578063095ea7b31461035b575b600080fd5b34801561029957600080fd5b506102b460048036038101906102af91906131ce565b610a45565b6040516102c19190613216565b60405180910390f35b3480156102d657600080fd5b506102f160048036038101906102ec919061326b565b610ad7565b005b3480156102ff57600080fd5b50610308610b55565b6040516103159190613328565b60405180910390f35b34801561032a57600080fd5b5061034560048036038101906103409190613380565b610be7565b60405161035291906133ee565b60405180910390f35b61037560048036038101906103709190613435565b610c66565b005b34801561038357600080fd5b5061039e600480360381019061039991906134a1565b610daa565b005b3480156103ac57600080fd5b506103b5610ec4565b6040516103c291906134dd565b60405180910390f35b3480156103d757600080fd5b506103e0610edb565b6040516103ed91906133ee565b60405180910390f35b610410600480360381019061040b91906134f8565b610f01565b005b61042c60048036038101906104279190613380565b611223565b005b610436611498565b005b610452600480360381019061044d91906134f8565b6114ac565b005b34801561046057600080fd5b506104696114cc565b6040516104769190613567565b60405180910390f35b34801561048b57600080fd5b506104946114df565b6040516104a19190613567565b60405180910390f35b3480156104b657600080fd5b506104d160048036038101906104cc91906135e7565b6114f2565b6040516104de9190613797565b60405180910390f35b3480156104f357600080fd5b506104fc6115b5565b6040516105099190613216565b60405180910390f35b34801561051e57600080fd5b506105276115c8565b005b34801561053557600080fd5b50610550600480360381019061054b9190613380565b6115ed565b60405161055d91906133ee565b60405180910390f35b34801561057257600080fd5b5061058d600480360381019061058891906137b9565b6115ff565b005b34801561059b57600080fd5b506105b660048036038101906105b191906137b9565b6116ba565b6040516105c391906134dd565b60405180910390f35b3480156105d857600080fd5b506105e1611772565b005b3480156105ef57600080fd5b5061060a60048036038101906106059190613380565b611786565b005b34801561061857600080fd5b50610633600480360381019061062e91906137b9565b6117b6565b60405161064091906138a4565b60405180910390f35b34801561065557600080fd5b5061065e6118f9565b60405161066b91906133ee565b60405180910390f35b34801561068057600080fd5b50610689611923565b6040516106969190613328565b60405180910390f35b3480156106ab57600080fd5b506106c660048036038101906106c191906138c6565b6119b5565b6040516106d391906138a4565b60405180910390f35b6106f660048036038101906106f1919061396f565b611bc1565b005b34801561070457600080fd5b5061071f600480360381019061071a91906139cf565b611f0e565b005b34801561072d57600080fd5b50610736612019565b6040516107439190613216565b60405180910390f35b34801561075857600080fd5b5061076161202c565b60405161076e91906134dd565b60405180910390f35b34801561078357600080fd5b5061079e60048036038101906107999190613a3b565b61204c565b005b3480156107ac57600080fd5b506107b5612072565b6040516107c29190613216565b60405180910390f35b6107e560048036038101906107e09190613b98565b612085565b005b3480156107f357600080fd5b5061080e60048036038101906108099190613c71565b6120f8565b005b34801561081c57600080fd5b5061083760048036038101906108329190613380565b612215565b6040516108449190613d26565b60405180910390f35b34801561085957600080fd5b50610874600480360381019061086f9190613380565b61227f565b005b34801561088257600080fd5b5061089d60048036038101906108989190613380565b6122af565b6040516108aa9190613328565b60405180910390f35b3480156108bf57600080fd5b506108da60048036038101906108d59190613a3b565b61238a565b005b3480156108e857600080fd5b506108f16123b0565b6040516108fe9190613d50565b60405180910390f35b34801561091357600080fd5b5061091c6123c4565b6040516109299190613216565b60405180910390f35b34801561093e57600080fd5b506109476123d7565b005b34801561095557600080fd5b50610970600480360381019061096b9190613dc1565b6123fc565b005b34801561097e57600080fd5b5061099960048036038101906109949190613e0e565b612470565b6040516109a69190613216565b60405180910390f35b3480156109bb57600080fd5b506109c4612504565b6040516109d191906134dd565b60405180910390f35b3480156109e657600080fd5b50610a0160048036038101906109fc91906137b9565b61250f565b005b348015610a0f57600080fd5b50610a18612592565b604051610a2591906134dd565b60405180910390f35b348015610a3a57600080fd5b50610a436125b2565b005b60006301ffc9a760e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610aa057506380ac58cd60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610ad05750635b5e139f60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b610adf6125d7565b60001515600a601e9054906101000a900460ff16151514610b35576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b2c90613e9a565b60405180910390fd5b80600a60166101000a81548161ffff021916908361ffff16021790555050565b606060028054610b6490613ee9565b80601f0160208091040260200160405190810160405280929190818152602001828054610b9090613ee9565b8015610bdd5780601f10610bb257610100808354040283529160200191610bdd565b820191906000526020600020905b815481529060010190602001808311610bc057829003601f168201915b5050505050905090565b6000610bf282612655565b610c28576040517fcf4700e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6006600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000610c71826115ed565b90508073ffffffffffffffffffffffffffffffffffffffff16610c926126b4565b73ffffffffffffffffffffffffffffffffffffffff1614610cf557610cbe81610cb96126b4565b612470565b610cf4576040517fcfb3b94200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b826006600084815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b610db26125d7565b6000151581151503610ea7576000600a60169054906101000a900461ffff1661ffff1603610e15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e0c90613f66565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1603610ea6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e9d90613fd2565b60405180910390fd5b5b80600a601c6101000a81548160ff02191690831515021790555050565b6000610ece6126bc565b6001546000540303905090565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000610f0c826126c5565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610f73576040517fa114810000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080610f7f84612791565b91509150610f958187610f906126b4565b6127b8565b610fe157610faa86610fa56126b4565b612470565b610fe0576040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603611047576040517fea553b3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61105486868660016127fc565b801561105f57600082555b600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600081546001900391905081905550600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600081546001019190508190555061112d85611109888887612802565b7c02000000000000000000000000000000000000000000000000000000001761282a565b600460008681526020019081526020016000208190555060007c02000000000000000000000000000000000000000000000000000000008416036111b357600060018501905060006004600083815260200190815260200160002054036111b15760005481146111b0578360046000838152602001908152602001600020819055505b5b505b838573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a461121b8686866001612855565b505050505050565b60001515600a601c9054906101000a900460ff16151514611279576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112709061403e565b60405180910390fd5b8060001515600a601d9054906101000a900460ff161515146112d0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112c790613e9a565b60405180910390fd5b600a60169054906101000a900461ffff1661ffff16816112ee61285b565b011115611330576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611327906140aa565b60405180910390fd5b81600a60159054906101000a900460ff1660ff16811115611386576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161137d90614116565b60405180910390fd5b600a60149054906101000a900460ff1660ff16816113a33361286e565b0111156113e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113dc90614182565b60405180910390fd5b600a601a9054906101000a900461ffff1683606481111561143b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611432906141ee565b60405180910390fd5b80611445836128c5565b023414611487576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161147e9061425a565b60405180910390fd5b61149133866128e5565b5050505050565b6114a06125d7565b6114aa3347612aa0565b565b6114c783838360405180602001604052806000815250612085565b505050565b600a60149054906101000a900460ff1681565b600a60159054906101000a900460ff1681565b6060600083839050905060008167ffffffffffffffff81111561151857611517613a6d565b5b60405190808252806020026020018201604052801561155157816020015b61153e613113565b8152602001906001900390816115365790505b50905060005b8281146115a9576115808686838181106115745761157361427a565b5b90506020020135612215565b8282815181106115935761159261427a565b5b6020026020010181905250806001019050611557565b50809250505092915050565b600a601c9054906101000a900460ff1681565b6115d06125d7565b6001600a601f6101000a81548160ff021916908315150217905550565b60006115f8826126c5565b9050919050565b6116076125d7565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611676576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161166d9061431b565b60405180910390fd5b80600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611721576040517f8f4eb60400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054169050919050565b61177a6125d7565b6117846000612ac0565b565b61178e6125d7565b61179781612b86565b600a60186101000a81548161ffff021916908361ffff16021790555050565b606060008060006117c6856116ba565b905060008167ffffffffffffffff8111156117e4576117e3613a6d565b5b6040519080825280602002602001820160405280156118125781602001602082028036833780820191505090505b50905061181d613113565b60006118276126bc565b90505b8386146118eb5761183a81612c4a565b915081604001516118e057600073ffffffffffffffffffffffffffffffffffffffff16826000015173ffffffffffffffffffffffffffffffffffffffff161461188557816000015194505b8773ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16036118df57808387806001019850815181106118d2576118d161427a565b5b6020026020010181815250505b5b80600101905061182a565b508195505050505050919050565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60606003805461193290613ee9565b80601f016020809104026020016040519081016040528092919081815260200182805461195e90613ee9565b80156119ab5780601f10611980576101008083540402835291602001916119ab565b820191906000526020600020905b81548152906001019060200180831161198e57829003601f168201915b5050505050905090565b60608183106119f0576040517f32c1995a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000806119fb612c75565b9050611a056126bc565b851015611a1757611a146126bc565b94505b80841115611a23578093505b6000611a2e876116ba565b905084861015611a51576000868603905081811015611a4b578091505b50611a56565b600090505b60008167ffffffffffffffff811115611a7257611a71613a6d565b5b604051908082528060200260200182016040528015611aa05781602001602082028036833780820191505090505b50905060008203611ab75780945050505050611bba565b6000611ac288612215565b905060008160400151611ad757816000015190505b60008990505b888114158015611aed5750848714155b15611bac57611afb81612c4a565b92508260400151611ba157600073ffffffffffffffffffffffffffffffffffffffff16836000015173ffffffffffffffffffffffffffffffffffffffff1614611b4657826000015191505b8a73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611ba05780848880600101995081518110611b9357611b9261427a565b5b6020026020010181815250505b5b806001019050611add565b508583528296505050505050505b9392505050565b60001515600a601c9054906101000a900460ff16151514611c17576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c0e9061403e565b60405180910390fd5b8260001515600a601d9054906101000a900460ff16151514611c6e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c6590613e9a565b60405180910390fd5b600a60169054906101000a900461ffff1661ffff1681611c8c61285b565b011115611cce576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cc5906140aa565b60405180910390fd5b83600a60159054906101000a900460ff1660ff16811115611d24576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d1b90614116565b60405180910390fd5b600a60149054906101000a900460ff1660ff1681611d413361286e565b011115611d83576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d7a90614182565b60405180910390fd5b8383600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611e018383611df233604051602001611dd791906133ee565b60405160208183030381529060405280519060200120612c7e565b612cb09092919063ffffffff16565b73ffffffffffffffffffffffffffffffffffffffff1614611e57576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e4e90614387565b60405180910390fd5b600a60189054906101000a900461ffff16876064811115611ead576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ea4906141ee565b60405180910390fd5b80611eb7836128c5565b023414611ef9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ef09061425a565b60405180910390fd5b611f03338a6128e5565b505050505050505050565b8060076000611f1b6126b4565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff16611fc86126b4565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405161200d9190613216565b60405180910390a35050565b600a601e9054906101000a900460ff1681565b6000612047600a601a9054906101000a900461ffff166128c5565b905090565b6120546125d7565b80600a60146101000a81548160ff021916908360ff16021790555050565b600a601f9054906101000a900460ff1681565b612090848484610f01565b60008373ffffffffffffffffffffffffffffffffffffffff163b146120f2576120bb84848484612d22565b6120f1576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b50505050565b6121006125d7565b828290508161210f91906143d6565b60001515600a601d9054906101000a900460ff16151514612165576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161215c90613e9a565b60405180910390fd5b600a60169054906101000a900461ffff1661ffff168161218361285b565b0111156121c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121bc906140aa565b60405180910390fd5b60005b84849050811461220e576122038585838181106121e8576121e761427a565b5b90506020020160208101906121fd91906137b9565b846128e5565b8060010190506121c8565b5050505050565b61221d613113565b612225613113565b61222d6126bc565b831080612241575061223d612c75565b8310155b1561224f578091505061227a565b61225883612c4a565b905080604001511561226d578091505061227a565b61227683612e72565b9150505b919050565b6122876125d7565b61229081612b86565b600a601a6101000a81548161ffff021916908361ffff16021790555050565b6060612383600980546122c190613ee9565b80601f01602080910402602001604051908101604052809291908181526020018280546122ed90613ee9565b801561233a5780601f1061230f5761010080835404028352916020019161233a565b820191906000526020600020905b81548152906001019060200180831161231d57829003601f168201915b50505050506040518060400160405280600481526020017f7b69647d0000000000000000000000000000000000000000000000000000000081525061237e85612e92565b612ee2565b9050919050565b6123926125d7565b80600a60156101000a81548160ff021916908360ff16021790555050565b600a60169054906101000a900461ffff1681565b600a601d9054906101000a900460ff1681565b6123df6125d7565b6001600a601d6101000a81548160ff021916908315150217905550565b6124046125d7565b60001515600a601f9054906101000a900460ff1615151461245a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161245190613e9a565b60405180910390fd5b81816009918261246b9291906145e7565b505050565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b66038d7ea4c6800081565b6125176125d7565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612586576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161257d90614729565b60405180910390fd5b61258f81612ac0565b50565b60006125ad600a60189054906101000a900461ffff166128c5565b905090565b6125ba6125d7565b6001600a601e6101000a81548160ff021916908315150217905550565b6125df61303c565b73ffffffffffffffffffffffffffffffffffffffff166125fd6118f9565b73ffffffffffffffffffffffffffffffffffffffff1614612653576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161264a90614795565b60405180910390fd5b565b6000816126606126bc565b1115801561266f575060005482105b80156126ad575060007c0100000000000000000000000000000000000000000000000000000000600460008581526020019081526020016000205416145b9050919050565b600033905090565b60006001905090565b600080829050806126d46126bc565b1161275a576000548110156127595760006004600083815260200190815260200160002054905060007c0100000000000000000000000000000000000000000000000000000000821603612757575b6000810361274d576004600083600190039350838152602001908152602001600020549050612723565b809250505061278c565b505b5b6040517fdf2d9b4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b60008060006006600085815260200190815260200160002090508092508254915050915091565b600073ffffffffffffffffffffffffffffffffffffffff8316925073ffffffffffffffffffffffffffffffffffffffff821691508382148383141790509392505050565b50505050565b60008060e883901c905060e8612819868684613044565b62ffffff16901b9150509392505050565b600073ffffffffffffffffffffffffffffffffffffffff83169250814260a01b178317905092915050565b50505050565b60006128656126bc565b60005403905090565b600067ffffffffffffffff6040600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054901c169050919050565b600066038d7ea4c680008261ffff166128de91906143d6565b9050919050565b60008054905060008203612925576040517fb562e8dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61293260008483856127fc565b600160406001901b178202600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055506129a98361299a6000866000612802565b6129a38561304d565b1761282a565b6004600083815260200190815260200160002081905550600080838301905073ffffffffffffffffffffffffffffffffffffffff85169150828260007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a4600183015b818114612a4a57808360007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a4600181019050612a0f565b5060008203612a85576040517f2e07630000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000819055505050612a9b6000848385612855565b505050565b60008060008084865af1612abc5763b12d13eb6000526004601cfd5b5050565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60008066038d7ea4c680008381612ba057612b9f6147b5565b5b0614612be1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bd890614856565b60405180910390fd5b61ffff801666038d7ea4c680008381612bfd57612bfc6147b5565b5b049250821115612c42576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c39906148c2565b60405180910390fd5b819050919050565b612c52613113565b612c6e600460008481526020019081526020016000205461305d565b9050919050565b60008054905090565b6000816020527b19457468657265756d205369676e6564204d6573736167653a0a3332600052603c6004209050919050565b600060418203612d1b576040516040846040377f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a060605111612d155784600052604084013560001a602052602060406080600060015afa5060006060523d6060035191505b80604052505b9392505050565b60008373ffffffffffffffffffffffffffffffffffffffff1663150b7a02612d486126b4565b8786866040518563ffffffff1660e01b8152600401612d6a9493929190614937565b6020604051808303816000875af1925050508015612da657506040513d601f19601f82011682018060405250810190612da39190614998565b60015b612e1f573d8060008114612dd6576040519150601f19603f3d011682016040523d82523d6000602084013e612ddb565b606091505b506000815103612e17576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050949350505050565b612e7a613113565b612e8b612e86836126c5565b61305d565b9050919050565b606060a060405101806040526020810391506000825281835b600115612ecd57600184039350600a81066030018453600a8104905080612eab575b50828103602084039350808452505050919050565b60608351835183516020870196506020860195506020850194506020604051019350828701838311612fe257600183820301600060208510612f245784892090505b601f851660200360031b89515b600115612fdd578b51818118831c612fba578315612f755783888e2014612f7457808a5260018a01995060018d019c50848d10612f6e5750612fdd565b50612fd8565b5b60005b600115612f9557808c0151818c0152602081019050878110612f78575b50868a019950878d019c508715612fb957848d10612fb35750612fdd565b50612fd8565b5b808a5260018a01995060018d019c50848d10612fd65750612fdd565b505b612f31565b505050505b846020604051019550888203868203015b828a1015613010578951825260208201915060208a019950612ff3565b60208703965080602088010160008152601f19601f820116604052818852505050505050509392505050565b600033905090565b60009392505050565b60006001821460e11b9050919050565b613065613113565b81816000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060a082901c816020019067ffffffffffffffff16908167ffffffffffffffff168152505060007c01000000000000000000000000000000000000000000000000000000008316141581604001901515908115158152505060e882901c816060019062ffffff16908162ffffff1681525050919050565b6040518060800160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600067ffffffffffffffff168152602001600015158152602001600062ffffff1681525090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6131ab81613176565b81146131b657600080fd5b50565b6000813590506131c8816131a2565b92915050565b6000602082840312156131e4576131e361316c565b5b60006131f2848285016131b9565b91505092915050565b60008115159050919050565b613210816131fb565b82525050565b600060208201905061322b6000830184613207565b92915050565b600061ffff82169050919050565b61324881613231565b811461325357600080fd5b50565b6000813590506132658161323f565b92915050565b6000602082840312156132815761328061316c565b5b600061328f84828501613256565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156132d25780820151818401526020810190506132b7565b60008484015250505050565b6000601f19601f8301169050919050565b60006132fa82613298565b61330481856132a3565b93506133148185602086016132b4565b61331d816132de565b840191505092915050565b6000602082019050818103600083015261334281846132ef565b905092915050565b6000819050919050565b61335d8161334a565b811461336857600080fd5b50565b60008135905061337a81613354565b92915050565b6000602082840312156133965761339561316c565b5b60006133a48482850161336b565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006133d8826133ad565b9050919050565b6133e8816133cd565b82525050565b600060208201905061340360008301846133df565b92915050565b613412816133cd565b811461341d57600080fd5b50565b60008135905061342f81613409565b92915050565b6000806040838503121561344c5761344b61316c565b5b600061345a85828601613420565b925050602061346b8582860161336b565b9150509250929050565b61347e816131fb565b811461348957600080fd5b50565b60008135905061349b81613475565b92915050565b6000602082840312156134b7576134b661316c565b5b60006134c58482850161348c565b91505092915050565b6134d78161334a565b82525050565b60006020820190506134f260008301846134ce565b92915050565b6000806000606084860312156135115761351061316c565b5b600061351f86828701613420565b935050602061353086828701613420565b92505060406135418682870161336b565b9150509250925092565b600060ff82169050919050565b6135618161354b565b82525050565b600060208201905061357c6000830184613558565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126135a7576135a6613582565b5b8235905067ffffffffffffffff8111156135c4576135c3613587565b5b6020830191508360208202830111156135e0576135df61358c565b5b9250929050565b600080602083850312156135fe576135fd61316c565b5b600083013567ffffffffffffffff81111561361c5761361b613171565b5b61362885828601613591565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b613669816133cd565b82525050565b600067ffffffffffffffff82169050919050565b61368c8161366f565b82525050565b61369b816131fb565b82525050565b600062ffffff82169050919050565b6136b9816136a1565b82525050565b6080820160008201516136d56000850182613660565b5060208201516136e86020850182613683565b5060408201516136fb6040850182613692565b50606082015161370e60608501826136b0565b50505050565b600061372083836136bf565b60808301905092915050565b6000602082019050919050565b600061374482613634565b61374e818561363f565b935061375983613650565b8060005b8381101561378a5781516137718882613714565b975061377c8361372c565b92505060018101905061375d565b5085935050505092915050565b600060208201905081810360008301526137b18184613739565b905092915050565b6000602082840312156137cf576137ce61316c565b5b60006137dd84828501613420565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61381b8161334a565b82525050565b600061382d8383613812565b60208301905092915050565b6000602082019050919050565b6000613851826137e6565b61385b81856137f1565b935061386683613802565b8060005b8381101561389757815161387e8882613821565b975061388983613839565b92505060018101905061386a565b5085935050505092915050565b600060208201905081810360008301526138be8184613846565b905092915050565b6000806000606084860312156138df576138de61316c565b5b60006138ed86828701613420565b93505060206138fe8682870161336b565b925050604061390f8682870161336b565b9150509250925092565b60008083601f84011261392f5761392e613582565b5b8235905067ffffffffffffffff81111561394c5761394b613587565b5b6020830191508360018202830111156139685761396761358c565b5b9250929050565b6000806000604084860312156139885761398761316c565b5b60006139968682870161336b565b935050602084013567ffffffffffffffff8111156139b7576139b6613171565b5b6139c386828701613919565b92509250509250925092565b600080604083850312156139e6576139e561316c565b5b60006139f485828601613420565b9250506020613a058582860161348c565b9150509250929050565b613a188161354b565b8114613a2357600080fd5b50565b600081359050613a3581613a0f565b92915050565b600060208284031215613a5157613a5061316c565b5b6000613a5f84828501613a26565b91505092915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b613aa5826132de565b810181811067ffffffffffffffff82111715613ac457613ac3613a6d565b5b80604052505050565b6000613ad7613162565b9050613ae38282613a9c565b919050565b600067ffffffffffffffff821115613b0357613b02613a6d565b5b613b0c826132de565b9050602081019050919050565b82818337600083830152505050565b6000613b3b613b3684613ae8565b613acd565b905082815260208101848484011115613b5757613b56613a68565b5b613b62848285613b19565b509392505050565b600082601f830112613b7f57613b7e613582565b5b8135613b8f848260208601613b28565b91505092915050565b60008060008060808587031215613bb257613bb161316c565b5b6000613bc087828801613420565b9450506020613bd187828801613420565b9350506040613be28782880161336b565b925050606085013567ffffffffffffffff811115613c0357613c02613171565b5b613c0f87828801613b6a565b91505092959194509250565b60008083601f840112613c3157613c30613582565b5b8235905067ffffffffffffffff811115613c4e57613c4d613587565b5b602083019150836020820283011115613c6a57613c6961358c565b5b9250929050565b600080600060408486031215613c8a57613c8961316c565b5b600084013567ffffffffffffffff811115613ca857613ca7613171565b5b613cb486828701613c1b565b93509350506020613cc78682870161336b565b9150509250925092565b608082016000820151613ce76000850182613660565b506020820151613cfa6020850182613683565b506040820151613d0d6040850182613692565b506060820151613d2060608501826136b0565b50505050565b6000608082019050613d3b6000830184613cd1565b92915050565b613d4a81613231565b82525050565b6000602082019050613d656000830184613d41565b92915050565b60008083601f840112613d8157613d80613582565b5b8235905067ffffffffffffffff811115613d9e57613d9d613587565b5b602083019150836001820283011115613dba57613db961358c565b5b9250929050565b60008060208385031215613dd857613dd761316c565b5b600083013567ffffffffffffffff811115613df657613df5613171565b5b613e0285828601613d6b565b92509250509250929050565b60008060408385031215613e2557613e2461316c565b5b6000613e3385828601613420565b9250506020613e4485828601613420565b9150509250929050565b7f4c6f636b65642e00000000000000000000000000000000000000000000000000600082015250565b6000613e846007836132a3565b9150613e8f82613e4e565b602082019050919050565b60006020820190508181036000830152613eb381613e77565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680613f0157607f821691505b602082108103613f1457613f13613eba565b5b50919050565b7f4d617820737570706c79206e6f74207365742e00000000000000000000000000600082015250565b6000613f506013836132a3565b9150613f5b82613f1a565b602082019050919050565b60006020820190508181036000830152613f7f81613f43565b9050919050565b7f5369676e6572206e6f74207365742e0000000000000000000000000000000000600082015250565b6000613fbc600f836132a3565b9150613fc782613f86565b602082019050919050565b60006020820190508181036000830152613feb81613faf565b9050919050565b7f5061757365642e00000000000000000000000000000000000000000000000000600082015250565b60006140286007836132a3565b915061403382613ff2565b602082019050919050565b600060208201905081810360008301526140578161401b565b9050919050565b7f4f7574206f662073746f636b2100000000000000000000000000000000000000600082015250565b6000614094600d836132a3565b915061409f8261405e565b602082019050919050565b600060208201905081810360008301526140c381614087565b9050919050565b7f4d617820706572207472616e73616374696f6e20726561636865642e00000000600082015250565b6000614100601c836132a3565b915061410b826140ca565b602082019050919050565b6000602082019050818103600083015261412f816140f3565b9050919050565b7f4d6178206e756d626572206d696e74656420726561636865642e000000000000600082015250565b600061416c601a836132a3565b915061417782614136565b602082019050919050565b6000602082019050818103600083015261419b8161415f565b9050919050565b7f5175616e7469747920746f6f20686967682e0000000000000000000000000000600082015250565b60006141d86012836132a3565b91506141e3826141a2565b602082019050919050565b60006020820190508181036000830152614207816141cb565b9050919050565b7f57726f6e672045746865722076616c75652e0000000000000000000000000000600082015250565b60006142446012836132a3565b915061424f8261420e565b602082019050919050565b6000602082019050818103600083015261427381614237565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f5369676e6572206d757374206e6f7420626520746865207a65726f206164647260008201527f6573732e00000000000000000000000000000000000000000000000000000000602082015250565b60006143056024836132a3565b9150614310826142a9565b604082019050919050565b60006020820190508181036000830152614334816142f8565b9050919050565b7f496e76616c6964207369676e61747572652e0000000000000000000000000000600082015250565b60006143716012836132a3565b915061437c8261433b565b602082019050919050565b600060208201905081810360008301526143a081614364565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006143e18261334a565b91506143ec8361334a565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615614425576144246143a7565b5b828202905092915050565b600082905092915050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b60006008830261449d7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614460565b6144a78683614460565b95508019841693508086168417925050509392505050565b6000819050919050565b60006144e46144df6144da8461334a565b6144bf565b61334a565b9050919050565b6000819050919050565b6144fe836144c9565b61451261450a826144eb565b84845461446d565b825550505050565b600090565b61452761451a565b6145328184846144f5565b505050565b5b818110156145565761454b60008261451f565b600181019050614538565b5050565b601f82111561459b5761456c8161443b565b61457584614450565b81016020851015614584578190505b61459861459085614450565b830182614537565b50505b505050565b600082821c905092915050565b60006145be600019846008026145a0565b1980831691505092915050565b60006145d783836145ad565b9150826002028217905092915050565b6145f18383614430565b67ffffffffffffffff81111561460a57614609613a6d565b5b6146148254613ee9565b61461f82828561455a565b6000601f83116001811461464e576000841561463c578287013590505b61464685826145cb565b8655506146ae565b601f19841661465c8661443b565b60005b828110156146845784890135825560018201915060208501945060208101905061465f565b868310156146a1578489013561469d601f8916826145ad565b8355505b6001600288020188555050505b50505050505050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b60006147136026836132a3565b915061471e826146b7565b604082019050919050565b6000602082019050818103600083015261474281614706565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b600061477f6020836132a3565b915061478a82614749565b602082019050919050565b600060208201905081810360008301526147ae81614772565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f5072696365206d7573742062652061206d756c7469706c65206f66205052494360008201527f455f554e49542e00000000000000000000000000000000000000000000000000602082015250565b60006148406027836132a3565b915061484b826147e4565b604082019050919050565b6000602082019050818103600083015261486f81614833565b9050919050565b7f4f766572666c6f772e0000000000000000000000000000000000000000000000600082015250565b60006148ac6009836132a3565b91506148b782614876565b602082019050919050565b600060208201905081810360008301526148db8161489f565b9050919050565b600081519050919050565b600082825260208201905092915050565b6000614909826148e2565b61491381856148ed565b93506149238185602086016132b4565b61492c816132de565b840191505092915050565b600060808201905061494c60008301876133df565b61495960208301866133df565b61496660408301856134ce565b818103606083015261497881846148fe565b905095945050505050565b600081519050614992816131a2565b92915050565b6000602082840312156149ae576149ad61316c565b5b60006149bc84828501614983565b9150509291505056fea2646970667358221220c370b975e2ba79e723fab553022730e1d789afed3fd3e543a57941c869e7131f64736f6c63430008100033

Deployed Bytecode

0x6080604052600436106102885760003560e01c80638da5cb5b1161015a578063c6275255116100c1578063e0df5b6f1161007a578063e0df5b6f14610949578063e985e9c514610972578063ed435e58146109af578063f2fde38b146109da578063fc1a1c3614610a03578063fca76c2614610a2e57610288565b8063c62752551461084d578063c87b56dd14610876578063ccdc7178146108b3578063d5abeb01146108dc578063df3c3a3014610907578063e0b6bb671461093257610288565b8063a945bf8011610113578063a945bf801461074c578063abf08ae114610777578063ac998f45146107a0578063b88d4fde146107cb578063c204642c146107e7578063c23dc68f1461081057610288565b80638da5cb5b1461064957806395d89b411461067457806399a2557a1461069f5780639e852f75146106dc578063a22cb465146106f8578063a8d0466c1461072157610288565b806342842e0e116101fe5780636352211e116101b75780636352211e146105295780636c19e7831461056657806370a082311461058f578063715018a6146105cc578063717d57d3146105e35780638462151c1461060c57610288565b806342842e0e14610438578063453c2310146104545780634b980d671461047f5780635bbb2177146104aa5780635c975abb146104e75780635e5a9e301461051257610288565b806316c38b3c1161025057806316c38b3c1461037757806318160ddd146103a0578063238ac933146103cb57806323b872dd146103f65780632db11544146104125780633ccfd60b1461042e57610288565b806301ffc9a71461028d57806306421c2f146102ca57806306fdde03146102f3578063081812fc1461031e578063095ea7b31461035b575b600080fd5b34801561029957600080fd5b506102b460048036038101906102af91906131ce565b610a45565b6040516102c19190613216565b60405180910390f35b3480156102d657600080fd5b506102f160048036038101906102ec919061326b565b610ad7565b005b3480156102ff57600080fd5b50610308610b55565b6040516103159190613328565b60405180910390f35b34801561032a57600080fd5b5061034560048036038101906103409190613380565b610be7565b60405161035291906133ee565b60405180910390f35b61037560048036038101906103709190613435565b610c66565b005b34801561038357600080fd5b5061039e600480360381019061039991906134a1565b610daa565b005b3480156103ac57600080fd5b506103b5610ec4565b6040516103c291906134dd565b60405180910390f35b3480156103d757600080fd5b506103e0610edb565b6040516103ed91906133ee565b60405180910390f35b610410600480360381019061040b91906134f8565b610f01565b005b61042c60048036038101906104279190613380565b611223565b005b610436611498565b005b610452600480360381019061044d91906134f8565b6114ac565b005b34801561046057600080fd5b506104696114cc565b6040516104769190613567565b60405180910390f35b34801561048b57600080fd5b506104946114df565b6040516104a19190613567565b60405180910390f35b3480156104b657600080fd5b506104d160048036038101906104cc91906135e7565b6114f2565b6040516104de9190613797565b60405180910390f35b3480156104f357600080fd5b506104fc6115b5565b6040516105099190613216565b60405180910390f35b34801561051e57600080fd5b506105276115c8565b005b34801561053557600080fd5b50610550600480360381019061054b9190613380565b6115ed565b60405161055d91906133ee565b60405180910390f35b34801561057257600080fd5b5061058d600480360381019061058891906137b9565b6115ff565b005b34801561059b57600080fd5b506105b660048036038101906105b191906137b9565b6116ba565b6040516105c391906134dd565b60405180910390f35b3480156105d857600080fd5b506105e1611772565b005b3480156105ef57600080fd5b5061060a60048036038101906106059190613380565b611786565b005b34801561061857600080fd5b50610633600480360381019061062e91906137b9565b6117b6565b60405161064091906138a4565b60405180910390f35b34801561065557600080fd5b5061065e6118f9565b60405161066b91906133ee565b60405180910390f35b34801561068057600080fd5b50610689611923565b6040516106969190613328565b60405180910390f35b3480156106ab57600080fd5b506106c660048036038101906106c191906138c6565b6119b5565b6040516106d391906138a4565b60405180910390f35b6106f660048036038101906106f1919061396f565b611bc1565b005b34801561070457600080fd5b5061071f600480360381019061071a91906139cf565b611f0e565b005b34801561072d57600080fd5b50610736612019565b6040516107439190613216565b60405180910390f35b34801561075857600080fd5b5061076161202c565b60405161076e91906134dd565b60405180910390f35b34801561078357600080fd5b5061079e60048036038101906107999190613a3b565b61204c565b005b3480156107ac57600080fd5b506107b5612072565b6040516107c29190613216565b60405180910390f35b6107e560048036038101906107e09190613b98565b612085565b005b3480156107f357600080fd5b5061080e60048036038101906108099190613c71565b6120f8565b005b34801561081c57600080fd5b5061083760048036038101906108329190613380565b612215565b6040516108449190613d26565b60405180910390f35b34801561085957600080fd5b50610874600480360381019061086f9190613380565b61227f565b005b34801561088257600080fd5b5061089d60048036038101906108989190613380565b6122af565b6040516108aa9190613328565b60405180910390f35b3480156108bf57600080fd5b506108da60048036038101906108d59190613a3b565b61238a565b005b3480156108e857600080fd5b506108f16123b0565b6040516108fe9190613d50565b60405180910390f35b34801561091357600080fd5b5061091c6123c4565b6040516109299190613216565b60405180910390f35b34801561093e57600080fd5b506109476123d7565b005b34801561095557600080fd5b50610970600480360381019061096b9190613dc1565b6123fc565b005b34801561097e57600080fd5b5061099960048036038101906109949190613e0e565b612470565b6040516109a69190613216565b60405180910390f35b3480156109bb57600080fd5b506109c4612504565b6040516109d191906134dd565b60405180910390f35b3480156109e657600080fd5b50610a0160048036038101906109fc91906137b9565b61250f565b005b348015610a0f57600080fd5b50610a18612592565b604051610a2591906134dd565b60405180910390f35b348015610a3a57600080fd5b50610a436125b2565b005b60006301ffc9a760e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610aa057506380ac58cd60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610ad05750635b5e139f60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b610adf6125d7565b60001515600a601e9054906101000a900460ff16151514610b35576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b2c90613e9a565b60405180910390fd5b80600a60166101000a81548161ffff021916908361ffff16021790555050565b606060028054610b6490613ee9565b80601f0160208091040260200160405190810160405280929190818152602001828054610b9090613ee9565b8015610bdd5780601f10610bb257610100808354040283529160200191610bdd565b820191906000526020600020905b815481529060010190602001808311610bc057829003601f168201915b5050505050905090565b6000610bf282612655565b610c28576040517fcf4700e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6006600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000610c71826115ed565b90508073ffffffffffffffffffffffffffffffffffffffff16610c926126b4565b73ffffffffffffffffffffffffffffffffffffffff1614610cf557610cbe81610cb96126b4565b612470565b610cf4576040517fcfb3b94200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b826006600084815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b610db26125d7565b6000151581151503610ea7576000600a60169054906101000a900461ffff1661ffff1603610e15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e0c90613f66565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1603610ea6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e9d90613fd2565b60405180910390fd5b5b80600a601c6101000a81548160ff02191690831515021790555050565b6000610ece6126bc565b6001546000540303905090565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000610f0c826126c5565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610f73576040517fa114810000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080610f7f84612791565b91509150610f958187610f906126b4565b6127b8565b610fe157610faa86610fa56126b4565b612470565b610fe0576040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603611047576040517fea553b3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61105486868660016127fc565b801561105f57600082555b600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600081546001900391905081905550600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600081546001019190508190555061112d85611109888887612802565b7c02000000000000000000000000000000000000000000000000000000001761282a565b600460008681526020019081526020016000208190555060007c02000000000000000000000000000000000000000000000000000000008416036111b357600060018501905060006004600083815260200190815260200160002054036111b15760005481146111b0578360046000838152602001908152602001600020819055505b5b505b838573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a461121b8686866001612855565b505050505050565b60001515600a601c9054906101000a900460ff16151514611279576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112709061403e565b60405180910390fd5b8060001515600a601d9054906101000a900460ff161515146112d0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112c790613e9a565b60405180910390fd5b600a60169054906101000a900461ffff1661ffff16816112ee61285b565b011115611330576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611327906140aa565b60405180910390fd5b81600a60159054906101000a900460ff1660ff16811115611386576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161137d90614116565b60405180910390fd5b600a60149054906101000a900460ff1660ff16816113a33361286e565b0111156113e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113dc90614182565b60405180910390fd5b600a601a9054906101000a900461ffff1683606481111561143b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611432906141ee565b60405180910390fd5b80611445836128c5565b023414611487576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161147e9061425a565b60405180910390fd5b61149133866128e5565b5050505050565b6114a06125d7565b6114aa3347612aa0565b565b6114c783838360405180602001604052806000815250612085565b505050565b600a60149054906101000a900460ff1681565b600a60159054906101000a900460ff1681565b6060600083839050905060008167ffffffffffffffff81111561151857611517613a6d565b5b60405190808252806020026020018201604052801561155157816020015b61153e613113565b8152602001906001900390816115365790505b50905060005b8281146115a9576115808686838181106115745761157361427a565b5b90506020020135612215565b8282815181106115935761159261427a565b5b6020026020010181905250806001019050611557565b50809250505092915050565b600a601c9054906101000a900460ff1681565b6115d06125d7565b6001600a601f6101000a81548160ff021916908315150217905550565b60006115f8826126c5565b9050919050565b6116076125d7565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611676576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161166d9061431b565b60405180910390fd5b80600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611721576040517f8f4eb60400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054169050919050565b61177a6125d7565b6117846000612ac0565b565b61178e6125d7565b61179781612b86565b600a60186101000a81548161ffff021916908361ffff16021790555050565b606060008060006117c6856116ba565b905060008167ffffffffffffffff8111156117e4576117e3613a6d565b5b6040519080825280602002602001820160405280156118125781602001602082028036833780820191505090505b50905061181d613113565b60006118276126bc565b90505b8386146118eb5761183a81612c4a565b915081604001516118e057600073ffffffffffffffffffffffffffffffffffffffff16826000015173ffffffffffffffffffffffffffffffffffffffff161461188557816000015194505b8773ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16036118df57808387806001019850815181106118d2576118d161427a565b5b6020026020010181815250505b5b80600101905061182a565b508195505050505050919050565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60606003805461193290613ee9565b80601f016020809104026020016040519081016040528092919081815260200182805461195e90613ee9565b80156119ab5780601f10611980576101008083540402835291602001916119ab565b820191906000526020600020905b81548152906001019060200180831161198e57829003601f168201915b5050505050905090565b60608183106119f0576040517f32c1995a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000806119fb612c75565b9050611a056126bc565b851015611a1757611a146126bc565b94505b80841115611a23578093505b6000611a2e876116ba565b905084861015611a51576000868603905081811015611a4b578091505b50611a56565b600090505b60008167ffffffffffffffff811115611a7257611a71613a6d565b5b604051908082528060200260200182016040528015611aa05781602001602082028036833780820191505090505b50905060008203611ab75780945050505050611bba565b6000611ac288612215565b905060008160400151611ad757816000015190505b60008990505b888114158015611aed5750848714155b15611bac57611afb81612c4a565b92508260400151611ba157600073ffffffffffffffffffffffffffffffffffffffff16836000015173ffffffffffffffffffffffffffffffffffffffff1614611b4657826000015191505b8a73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611ba05780848880600101995081518110611b9357611b9261427a565b5b6020026020010181815250505b5b806001019050611add565b508583528296505050505050505b9392505050565b60001515600a601c9054906101000a900460ff16151514611c17576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c0e9061403e565b60405180910390fd5b8260001515600a601d9054906101000a900460ff16151514611c6e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c6590613e9a565b60405180910390fd5b600a60169054906101000a900461ffff1661ffff1681611c8c61285b565b011115611cce576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cc5906140aa565b60405180910390fd5b83600a60159054906101000a900460ff1660ff16811115611d24576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d1b90614116565b60405180910390fd5b600a60149054906101000a900460ff1660ff1681611d413361286e565b011115611d83576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d7a90614182565b60405180910390fd5b8383600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611e018383611df233604051602001611dd791906133ee565b60405160208183030381529060405280519060200120612c7e565b612cb09092919063ffffffff16565b73ffffffffffffffffffffffffffffffffffffffff1614611e57576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e4e90614387565b60405180910390fd5b600a60189054906101000a900461ffff16876064811115611ead576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ea4906141ee565b60405180910390fd5b80611eb7836128c5565b023414611ef9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ef09061425a565b60405180910390fd5b611f03338a6128e5565b505050505050505050565b8060076000611f1b6126b4565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff16611fc86126b4565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405161200d9190613216565b60405180910390a35050565b600a601e9054906101000a900460ff1681565b6000612047600a601a9054906101000a900461ffff166128c5565b905090565b6120546125d7565b80600a60146101000a81548160ff021916908360ff16021790555050565b600a601f9054906101000a900460ff1681565b612090848484610f01565b60008373ffffffffffffffffffffffffffffffffffffffff163b146120f2576120bb84848484612d22565b6120f1576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b50505050565b6121006125d7565b828290508161210f91906143d6565b60001515600a601d9054906101000a900460ff16151514612165576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161215c90613e9a565b60405180910390fd5b600a60169054906101000a900461ffff1661ffff168161218361285b565b0111156121c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121bc906140aa565b60405180910390fd5b60005b84849050811461220e576122038585838181106121e8576121e761427a565b5b90506020020160208101906121fd91906137b9565b846128e5565b8060010190506121c8565b5050505050565b61221d613113565b612225613113565b61222d6126bc565b831080612241575061223d612c75565b8310155b1561224f578091505061227a565b61225883612c4a565b905080604001511561226d578091505061227a565b61227683612e72565b9150505b919050565b6122876125d7565b61229081612b86565b600a601a6101000a81548161ffff021916908361ffff16021790555050565b6060612383600980546122c190613ee9565b80601f01602080910402602001604051908101604052809291908181526020018280546122ed90613ee9565b801561233a5780601f1061230f5761010080835404028352916020019161233a565b820191906000526020600020905b81548152906001019060200180831161231d57829003601f168201915b50505050506040518060400160405280600481526020017f7b69647d0000000000000000000000000000000000000000000000000000000081525061237e85612e92565b612ee2565b9050919050565b6123926125d7565b80600a60156101000a81548160ff021916908360ff16021790555050565b600a60169054906101000a900461ffff1681565b600a601d9054906101000a900460ff1681565b6123df6125d7565b6001600a601d6101000a81548160ff021916908315150217905550565b6124046125d7565b60001515600a601f9054906101000a900460ff1615151461245a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161245190613e9a565b60405180910390fd5b81816009918261246b9291906145e7565b505050565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b66038d7ea4c6800081565b6125176125d7565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612586576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161257d90614729565b60405180910390fd5b61258f81612ac0565b50565b60006125ad600a60189054906101000a900461ffff166128c5565b905090565b6125ba6125d7565b6001600a601e6101000a81548160ff021916908315150217905550565b6125df61303c565b73ffffffffffffffffffffffffffffffffffffffff166125fd6118f9565b73ffffffffffffffffffffffffffffffffffffffff1614612653576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161264a90614795565b60405180910390fd5b565b6000816126606126bc565b1115801561266f575060005482105b80156126ad575060007c0100000000000000000000000000000000000000000000000000000000600460008581526020019081526020016000205416145b9050919050565b600033905090565b60006001905090565b600080829050806126d46126bc565b1161275a576000548110156127595760006004600083815260200190815260200160002054905060007c0100000000000000000000000000000000000000000000000000000000821603612757575b6000810361274d576004600083600190039350838152602001908152602001600020549050612723565b809250505061278c565b505b5b6040517fdf2d9b4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b60008060006006600085815260200190815260200160002090508092508254915050915091565b600073ffffffffffffffffffffffffffffffffffffffff8316925073ffffffffffffffffffffffffffffffffffffffff821691508382148383141790509392505050565b50505050565b60008060e883901c905060e8612819868684613044565b62ffffff16901b9150509392505050565b600073ffffffffffffffffffffffffffffffffffffffff83169250814260a01b178317905092915050565b50505050565b60006128656126bc565b60005403905090565b600067ffffffffffffffff6040600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054901c169050919050565b600066038d7ea4c680008261ffff166128de91906143d6565b9050919050565b60008054905060008203612925576040517fb562e8dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61293260008483856127fc565b600160406001901b178202600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055506129a98361299a6000866000612802565b6129a38561304d565b1761282a565b6004600083815260200190815260200160002081905550600080838301905073ffffffffffffffffffffffffffffffffffffffff85169150828260007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a4600183015b818114612a4a57808360007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a4600181019050612a0f565b5060008203612a85576040517f2e07630000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000819055505050612a9b6000848385612855565b505050565b60008060008084865af1612abc5763b12d13eb6000526004601cfd5b5050565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60008066038d7ea4c680008381612ba057612b9f6147b5565b5b0614612be1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bd890614856565b60405180910390fd5b61ffff801666038d7ea4c680008381612bfd57612bfc6147b5565b5b049250821115612c42576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c39906148c2565b60405180910390fd5b819050919050565b612c52613113565b612c6e600460008481526020019081526020016000205461305d565b9050919050565b60008054905090565b6000816020527b19457468657265756d205369676e6564204d6573736167653a0a3332600052603c6004209050919050565b600060418203612d1b576040516040846040377f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a060605111612d155784600052604084013560001a602052602060406080600060015afa5060006060523d6060035191505b80604052505b9392505050565b60008373ffffffffffffffffffffffffffffffffffffffff1663150b7a02612d486126b4565b8786866040518563ffffffff1660e01b8152600401612d6a9493929190614937565b6020604051808303816000875af1925050508015612da657506040513d601f19601f82011682018060405250810190612da39190614998565b60015b612e1f573d8060008114612dd6576040519150601f19603f3d011682016040523d82523d6000602084013e612ddb565b606091505b506000815103612e17576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050949350505050565b612e7a613113565b612e8b612e86836126c5565b61305d565b9050919050565b606060a060405101806040526020810391506000825281835b600115612ecd57600184039350600a81066030018453600a8104905080612eab575b50828103602084039350808452505050919050565b60608351835183516020870196506020860195506020850194506020604051019350828701838311612fe257600183820301600060208510612f245784892090505b601f851660200360031b89515b600115612fdd578b51818118831c612fba578315612f755783888e2014612f7457808a5260018a01995060018d019c50848d10612f6e5750612fdd565b50612fd8565b5b60005b600115612f9557808c0151818c0152602081019050878110612f78575b50868a019950878d019c508715612fb957848d10612fb35750612fdd565b50612fd8565b5b808a5260018a01995060018d019c50848d10612fd65750612fdd565b505b612f31565b505050505b846020604051019550888203868203015b828a1015613010578951825260208201915060208a019950612ff3565b60208703965080602088010160008152601f19601f820116604052818852505050505050509392505050565b600033905090565b60009392505050565b60006001821460e11b9050919050565b613065613113565b81816000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060a082901c816020019067ffffffffffffffff16908167ffffffffffffffff168152505060007c01000000000000000000000000000000000000000000000000000000008316141581604001901515908115158152505060e882901c816060019062ffffff16908162ffffff1681525050919050565b6040518060800160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600067ffffffffffffffff168152602001600015158152602001600062ffffff1681525090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6131ab81613176565b81146131b657600080fd5b50565b6000813590506131c8816131a2565b92915050565b6000602082840312156131e4576131e361316c565b5b60006131f2848285016131b9565b91505092915050565b60008115159050919050565b613210816131fb565b82525050565b600060208201905061322b6000830184613207565b92915050565b600061ffff82169050919050565b61324881613231565b811461325357600080fd5b50565b6000813590506132658161323f565b92915050565b6000602082840312156132815761328061316c565b5b600061328f84828501613256565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156132d25780820151818401526020810190506132b7565b60008484015250505050565b6000601f19601f8301169050919050565b60006132fa82613298565b61330481856132a3565b93506133148185602086016132b4565b61331d816132de565b840191505092915050565b6000602082019050818103600083015261334281846132ef565b905092915050565b6000819050919050565b61335d8161334a565b811461336857600080fd5b50565b60008135905061337a81613354565b92915050565b6000602082840312156133965761339561316c565b5b60006133a48482850161336b565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006133d8826133ad565b9050919050565b6133e8816133cd565b82525050565b600060208201905061340360008301846133df565b92915050565b613412816133cd565b811461341d57600080fd5b50565b60008135905061342f81613409565b92915050565b6000806040838503121561344c5761344b61316c565b5b600061345a85828601613420565b925050602061346b8582860161336b565b9150509250929050565b61347e816131fb565b811461348957600080fd5b50565b60008135905061349b81613475565b92915050565b6000602082840312156134b7576134b661316c565b5b60006134c58482850161348c565b91505092915050565b6134d78161334a565b82525050565b60006020820190506134f260008301846134ce565b92915050565b6000806000606084860312156135115761351061316c565b5b600061351f86828701613420565b935050602061353086828701613420565b92505060406135418682870161336b565b9150509250925092565b600060ff82169050919050565b6135618161354b565b82525050565b600060208201905061357c6000830184613558565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126135a7576135a6613582565b5b8235905067ffffffffffffffff8111156135c4576135c3613587565b5b6020830191508360208202830111156135e0576135df61358c565b5b9250929050565b600080602083850312156135fe576135fd61316c565b5b600083013567ffffffffffffffff81111561361c5761361b613171565b5b61362885828601613591565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b613669816133cd565b82525050565b600067ffffffffffffffff82169050919050565b61368c8161366f565b82525050565b61369b816131fb565b82525050565b600062ffffff82169050919050565b6136b9816136a1565b82525050565b6080820160008201516136d56000850182613660565b5060208201516136e86020850182613683565b5060408201516136fb6040850182613692565b50606082015161370e60608501826136b0565b50505050565b600061372083836136bf565b60808301905092915050565b6000602082019050919050565b600061374482613634565b61374e818561363f565b935061375983613650565b8060005b8381101561378a5781516137718882613714565b975061377c8361372c565b92505060018101905061375d565b5085935050505092915050565b600060208201905081810360008301526137b18184613739565b905092915050565b6000602082840312156137cf576137ce61316c565b5b60006137dd84828501613420565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61381b8161334a565b82525050565b600061382d8383613812565b60208301905092915050565b6000602082019050919050565b6000613851826137e6565b61385b81856137f1565b935061386683613802565b8060005b8381101561389757815161387e8882613821565b975061388983613839565b92505060018101905061386a565b5085935050505092915050565b600060208201905081810360008301526138be8184613846565b905092915050565b6000806000606084860312156138df576138de61316c565b5b60006138ed86828701613420565b93505060206138fe8682870161336b565b925050604061390f8682870161336b565b9150509250925092565b60008083601f84011261392f5761392e613582565b5b8235905067ffffffffffffffff81111561394c5761394b613587565b5b6020830191508360018202830111156139685761396761358c565b5b9250929050565b6000806000604084860312156139885761398761316c565b5b60006139968682870161336b565b935050602084013567ffffffffffffffff8111156139b7576139b6613171565b5b6139c386828701613919565b92509250509250925092565b600080604083850312156139e6576139e561316c565b5b60006139f485828601613420565b9250506020613a058582860161348c565b9150509250929050565b613a188161354b565b8114613a2357600080fd5b50565b600081359050613a3581613a0f565b92915050565b600060208284031215613a5157613a5061316c565b5b6000613a5f84828501613a26565b91505092915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b613aa5826132de565b810181811067ffffffffffffffff82111715613ac457613ac3613a6d565b5b80604052505050565b6000613ad7613162565b9050613ae38282613a9c565b919050565b600067ffffffffffffffff821115613b0357613b02613a6d565b5b613b0c826132de565b9050602081019050919050565b82818337600083830152505050565b6000613b3b613b3684613ae8565b613acd565b905082815260208101848484011115613b5757613b56613a68565b5b613b62848285613b19565b509392505050565b600082601f830112613b7f57613b7e613582565b5b8135613b8f848260208601613b28565b91505092915050565b60008060008060808587031215613bb257613bb161316c565b5b6000613bc087828801613420565b9450506020613bd187828801613420565b9350506040613be28782880161336b565b925050606085013567ffffffffffffffff811115613c0357613c02613171565b5b613c0f87828801613b6a565b91505092959194509250565b60008083601f840112613c3157613c30613582565b5b8235905067ffffffffffffffff811115613c4e57613c4d613587565b5b602083019150836020820283011115613c6a57613c6961358c565b5b9250929050565b600080600060408486031215613c8a57613c8961316c565b5b600084013567ffffffffffffffff811115613ca857613ca7613171565b5b613cb486828701613c1b565b93509350506020613cc78682870161336b565b9150509250925092565b608082016000820151613ce76000850182613660565b506020820151613cfa6020850182613683565b506040820151613d0d6040850182613692565b506060820151613d2060608501826136b0565b50505050565b6000608082019050613d3b6000830184613cd1565b92915050565b613d4a81613231565b82525050565b6000602082019050613d656000830184613d41565b92915050565b60008083601f840112613d8157613d80613582565b5b8235905067ffffffffffffffff811115613d9e57613d9d613587565b5b602083019150836001820283011115613dba57613db961358c565b5b9250929050565b60008060208385031215613dd857613dd761316c565b5b600083013567ffffffffffffffff811115613df657613df5613171565b5b613e0285828601613d6b565b92509250509250929050565b60008060408385031215613e2557613e2461316c565b5b6000613e3385828601613420565b9250506020613e4485828601613420565b9150509250929050565b7f4c6f636b65642e00000000000000000000000000000000000000000000000000600082015250565b6000613e846007836132a3565b9150613e8f82613e4e565b602082019050919050565b60006020820190508181036000830152613eb381613e77565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680613f0157607f821691505b602082108103613f1457613f13613eba565b5b50919050565b7f4d617820737570706c79206e6f74207365742e00000000000000000000000000600082015250565b6000613f506013836132a3565b9150613f5b82613f1a565b602082019050919050565b60006020820190508181036000830152613f7f81613f43565b9050919050565b7f5369676e6572206e6f74207365742e0000000000000000000000000000000000600082015250565b6000613fbc600f836132a3565b9150613fc782613f86565b602082019050919050565b60006020820190508181036000830152613feb81613faf565b9050919050565b7f5061757365642e00000000000000000000000000000000000000000000000000600082015250565b60006140286007836132a3565b915061403382613ff2565b602082019050919050565b600060208201905081810360008301526140578161401b565b9050919050565b7f4f7574206f662073746f636b2100000000000000000000000000000000000000600082015250565b6000614094600d836132a3565b915061409f8261405e565b602082019050919050565b600060208201905081810360008301526140c381614087565b9050919050565b7f4d617820706572207472616e73616374696f6e20726561636865642e00000000600082015250565b6000614100601c836132a3565b915061410b826140ca565b602082019050919050565b6000602082019050818103600083015261412f816140f3565b9050919050565b7f4d6178206e756d626572206d696e74656420726561636865642e000000000000600082015250565b600061416c601a836132a3565b915061417782614136565b602082019050919050565b6000602082019050818103600083015261419b8161415f565b9050919050565b7f5175616e7469747920746f6f20686967682e0000000000000000000000000000600082015250565b60006141d86012836132a3565b91506141e3826141a2565b602082019050919050565b60006020820190508181036000830152614207816141cb565b9050919050565b7f57726f6e672045746865722076616c75652e0000000000000000000000000000600082015250565b60006142446012836132a3565b915061424f8261420e565b602082019050919050565b6000602082019050818103600083015261427381614237565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f5369676e6572206d757374206e6f7420626520746865207a65726f206164647260008201527f6573732e00000000000000000000000000000000000000000000000000000000602082015250565b60006143056024836132a3565b9150614310826142a9565b604082019050919050565b60006020820190508181036000830152614334816142f8565b9050919050565b7f496e76616c6964207369676e61747572652e0000000000000000000000000000600082015250565b60006143716012836132a3565b915061437c8261433b565b602082019050919050565b600060208201905081810360008301526143a081614364565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006143e18261334a565b91506143ec8361334a565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615614425576144246143a7565b5b828202905092915050565b600082905092915050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b60006008830261449d7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614460565b6144a78683614460565b95508019841693508086168417925050509392505050565b6000819050919050565b60006144e46144df6144da8461334a565b6144bf565b61334a565b9050919050565b6000819050919050565b6144fe836144c9565b61451261450a826144eb565b84845461446d565b825550505050565b600090565b61452761451a565b6145328184846144f5565b505050565b5b818110156145565761454b60008261451f565b600181019050614538565b5050565b601f82111561459b5761456c8161443b565b61457584614450565b81016020851015614584578190505b61459861459085614450565b830182614537565b50505b505050565b600082821c905092915050565b60006145be600019846008026145a0565b1980831691505092915050565b60006145d783836145ad565b9150826002028217905092915050565b6145f18383614430565b67ffffffffffffffff81111561460a57614609613a6d565b5b6146148254613ee9565b61461f82828561455a565b6000601f83116001811461464e576000841561463c578287013590505b61464685826145cb565b8655506146ae565b601f19841661465c8661443b565b60005b828110156146845784890135825560018201915060208501945060208101905061465f565b868310156146a1578489013561469d601f8916826145ad565b8355505b6001600288020188555050505b50505050505050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b60006147136026836132a3565b915061471e826146b7565b604082019050919050565b6000602082019050818103600083015261474281614706565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b600061477f6020836132a3565b915061478a82614749565b602082019050919050565b600060208201905081810360008301526147ae81614772565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f5072696365206d7573742062652061206d756c7469706c65206f66205052494360008201527f455f554e49542e00000000000000000000000000000000000000000000000000602082015250565b60006148406027836132a3565b915061484b826147e4565b604082019050919050565b6000602082019050818103600083015261486f81614833565b9050919050565b7f4f766572666c6f772e0000000000000000000000000000000000000000000000600082015250565b60006148ac6009836132a3565b91506148b782614876565b602082019050919050565b600060208201905081810360008301526148db8161489f565b9050919050565b600081519050919050565b600082825260208201905092915050565b6000614909826148e2565b61491381856148ed565b93506149238185602086016132b4565b61492c816132de565b840191505092915050565b600060808201905061494c60008301876133df565b61495960208301866133df565b61496660408301856134ce565b818103606083015261497881846148fe565b905095945050505050565b600081519050614992816131a2565b92915050565b6000602082840312156149ae576149ad61316c565b5b60006149bc84828501614983565b9150509291505056fea2646970667358221220c370b975e2ba79e723fab553022730e1d789afed3fd3e543a57941c869e7131f64736f6c63430008100033

Deployed Bytecode Sourcemap

131132:6215:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87907:639;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;135883:148;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;88809:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;95300:218;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;94733:408;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;136257:249;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;84560:323;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;131321:21;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;98939:2825;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;132623:279;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;137212:132;;;:::i;:::-;;101860:193;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;131351:29;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;131387:34;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;122606:528;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;131606:25;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;136865:83;;;;;;;;;;;;;:::i;:::-;;90202:152;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;136514:167;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;85744:233;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;130165:103;;;;;;;;;;;;;:::i;:::-;;136956:123;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;126482:900;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;129517:87;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;88985:104;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;123522:2513;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;132910:348;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;95858:234;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;131667:27;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;132098:108;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;136039:96;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;131701:26;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;102651:407;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;135449:263;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;122019:428;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;137087:117;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;131909:181;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;136143:106;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;131428:30;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;131638:22;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;136689:75;;;;;;;;;;;;;:::i;:::-;;135720:155;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;96249:164;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;131231:48;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;130423:201;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;132214:114;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;136772:85;;;;;;;;;;;;;:::i;:::-;;87907:639;87992:4;88331:10;88316:25;;:11;:25;;;;:102;;;;88408:10;88393:25;;:11;:25;;;;88316:102;:179;;;;88485:10;88470:25;;:11;:25;;;;88316:179;88296:199;;87907:639;;;:::o;135883:148::-;129403:13;:11;:13::i;:::-;135976:5:::1;135957:24;;:15;;;;;;;;;;;:24;;;135949:44;;;;;;;;;;;;:::i;:::-;;;;;;;;;136018:5;136006:9;;:17;;;;;;;;;;;;;;;;;;135883:148:::0;:::o;88809:100::-;88863:13;88896:5;88889:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;88809:100;:::o;95300:218::-;95376:7;95401:16;95409:7;95401;:16::i;:::-;95396:64;;95426:34;;;;;;;;;;;;;;95396:64;95480:15;:24;95496:7;95480:24;;;;;;;;;;;:30;;;;;;;;;;;;95473:37;;95300:218;;;:::o;94733:408::-;94822:13;94838:16;94846:7;94838;:16::i;:::-;94822:32;;94894:5;94871:28;;:19;:17;:19::i;:::-;:28;;;94867:175;;94919:44;94936:5;94943:19;:17;:19::i;:::-;94919:16;:44::i;:::-;94914:128;;94991:35;;;;;;;;;;;;;;94914:128;94867:175;95087:2;95054:15;:24;95070:7;95054:24;;;;;;;;;;;:30;;;:35;;;;;;;;;;;;;;;;;;95125:7;95121:2;95105:28;;95114:5;95105:28;;;;;;;;;;;;94811:330;94733:408;;:::o;136257:249::-;129403:13;:11;:13::i;:::-;136331:5:::1;136322:14;;:5;:14;;::::0;136318:156:::1;;136374:1;136361:9;;;;;;;;;;;:14;;::::0;136353:46:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;136440:1;136422:20;;:6;;;;;;;;;;;:20;;::::0;136414:48:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;136318:156;136493:5;136484:6;;:14;;;;;;;;;;;;;;;;;;136257:249:::0;:::o;84560:323::-;84621:7;84849:15;:13;:15::i;:::-;84834:12;;84818:13;;:28;:46;84811:53;;84560:323;:::o;131321:21::-;;;;;;;;;;;;;:::o;98939:2825::-;99081:27;99111;99130:7;99111:18;:27::i;:::-;99081:57;;99196:4;99155:45;;99171:19;99155:45;;;99151:86;;99209:28;;;;;;;;;;;;;;99151:86;99251:27;99280:23;99307:35;99334:7;99307:26;:35::i;:::-;99250:92;;;;99442:68;99467:15;99484:4;99490:19;:17;:19::i;:::-;99442:24;:68::i;:::-;99437:180;;99530:43;99547:4;99553:19;:17;:19::i;:::-;99530:16;:43::i;:::-;99525:92;;99582:35;;;;;;;;;;;;;;99525:92;99437:180;99648:1;99634:16;;:2;:16;;;99630:52;;99659:23;;;;;;;;;;;;;;99630:52;99695:43;99717:4;99723:2;99727:7;99736:1;99695:21;:43::i;:::-;99831:15;99828:160;;;99971:1;99950:19;99943:30;99828:160;100368:18;:24;100387:4;100368:24;;;;;;;;;;;;;;;;100366:26;;;;;;;;;;;;100437:18;:22;100456:2;100437:22;;;;;;;;;;;;;;;;100435:24;;;;;;;;;;;100759:146;100796:2;100845:45;100860:4;100866:2;100870:19;100845:14;:45::i;:::-;80959:8;100817:73;100759:18;:146::i;:::-;100730:17;:26;100748:7;100730:26;;;;;;;;;;;:175;;;;101076:1;80959:8;101025:19;:47;:52;101021:627;;101098:19;101130:1;101120:7;:11;101098:33;;101287:1;101253:17;:30;101271:11;101253:30;;;;;;;;;;;;:35;101249:384;;101391:13;;101376:11;:28;101372:242;;101571:19;101538:17;:30;101556:11;101538:30;;;;;;;;;;;:52;;;;101372:242;101249:384;101079:569;101021:627;101695:7;101691:2;101676:27;;101685:4;101676:27;;;;;;;;;;;;101714:42;101735:4;101741:2;101745:7;101754:1;101714:20;:42::i;:::-;99070:2694;;;98939:2825;;;:::o;132623:279::-;135117:5;135107:15;;:6;;;;;;;;;;;:15;;;135099:35;;;;;;;;;;;;:::i;:::-;;;;;;;;;132744:8:::1;134405:5;134391:19;;:10;;;;;;;;;;;:19;;;134383:39;;;;;;;;;;;;:::i;:::-;;;;;;;;;134474:9;;;;;;;;;;;134445:38;;134462:8;134445:14;:12;:14::i;:::-;:25;:38;;134437:64;;;;;;;;;;;;:::i;:::-;;;;;;;;;132783:8:::2;134109:17;;;;;;;;;;;134097:29;;:8;:29;;134089:70;;;;;;;;;;;;:::i;:::-;;;;;;;;;134222:12;;;;;;;;;;;134182:52;;134210:8;134182:25;134196:10;134182:13;:25::i;:::-;:36;:52;;134174:91;;;;;;;;;;;;:::i;:::-;;;;;;;;;132822:17:::3;;;;;;;;;;;132841:8;134662:3;134650:8;:15;;134642:46;;;;;;;;;;;;:::i;:::-;;;;;;;;;134747:8;134724:20;134733:10;134724:8;:20::i;:::-;:31;134711:9;:44;134703:75;;;;;;;;;;;;:::i;:::-;;;;;;;;;132867:27:::4;132873:10;132885:8;132867:5;:27::i;:::-;134287:1:::3;;134523::::2;135145::::1;132623:279:::0;:::o;137212:132::-;129403:13;:11;:13::i;:::-;137270:66:::1;137302:10;137314:21;137270:31;:66::i;:::-;137212:132::o:0;101860:193::-;102006:39;102023:4;102029:2;102033:7;102006:39;;;;;;;;;;;;:16;:39::i;:::-;101860:193;;;:::o;131351:29::-;;;;;;;;;;;;;:::o;131387:34::-;;;;;;;;;;;;;:::o;122606:528::-;122750:23;122816:22;122841:8;;:15;;122816:40;;122871:34;122929:14;122908:36;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;122871:73;;122964:9;122959:125;122980:14;122975:1;:19;122959:125;;123036:32;123056:8;;123065:1;123056:11;;;;;;;:::i;:::-;;;;;;;;123036:19;:32::i;:::-;123020:10;123031:1;123020:13;;;;;;;;:::i;:::-;;;;;;;:48;;;;122996:3;;;;;122959:125;;;;123105:10;123098:17;;;;122606:528;;;;:::o;131606:25::-;;;;;;;;;;;;;:::o;136865:83::-;129403:13;:11;:13::i;:::-;136936:4:::1;136919:14;;:21;;;;;;;;;;;;;;;;;;136865:83::o:0;90202:152::-;90274:7;90317:27;90336:7;90317:18;:27::i;:::-;90294:52;;90202:152;;;:::o;136514:167::-;129403:13;:11;:13::i;:::-;136603:1:::1;136586:19;;:5;:19;;::::0;136578:68:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;136668:5;136659:6;;:14;;;;;;;;;;;;;;;;;;136514:167:::0;:::o;85744:233::-;85816:7;85857:1;85840:19;;:5;:19;;;85836:60;;85868:28;;;;;;;;;;;;;;85836:60;79903:13;85914:18;:25;85933:5;85914:25;;;;;;;;;;;;;;;;:55;85907:62;;85744:233;;;:::o;130165:103::-;129403:13;:11;:13::i;:::-;130230:30:::1;130257:1;130230:18;:30::i;:::-;130165:103::o:0;136956:123::-;129403:13;:11;:13::i;:::-;137051:20:::1;137065:5;137051:13;:20::i;:::-;137028;;:43;;;;;;;;;;;;;;;;;;136956:123:::0;:::o;126482:900::-;126560:16;126614:19;126648:25;126688:22;126713:16;126723:5;126713:9;:16::i;:::-;126688:41;;126744:25;126786:14;126772:29;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;126744:57;;126816:31;;:::i;:::-;126867:9;126879:15;:13;:15::i;:::-;126867:27;;126862:472;126911:14;126896:11;:29;126862:472;;126963:15;126976:1;126963:12;:15::i;:::-;126951:27;;127001:9;:16;;;127042:8;126997:73;127118:1;127092:28;;:9;:14;;;:28;;;127088:111;;127165:9;:14;;;127145:34;;127088:111;127242:5;127221:26;;:17;:26;;;127217:102;;127298:1;127272:8;127281:13;;;;;;127272:23;;;;;;;;:::i;:::-;;;;;;;:27;;;;;127217:102;126862:472;126927:3;;;;;126862:472;;;;127355:8;127348:15;;;;;;;126482:900;;;:::o;129517:87::-;129563:7;129590:6;;;;;;;;;;;129583:13;;129517:87;:::o;88985:104::-;89041:13;89074:7;89067:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;88985:104;:::o;123522:2513::-;123665:16;123732:4;123723:5;:13;123719:45;;123745:19;;;;;;;;;;;;;;123719:45;123779:19;123813:17;123833:14;:12;:14::i;:::-;123813:34;;123933:15;:13;:15::i;:::-;123925:5;:23;123921:87;;;123977:15;:13;:15::i;:::-;123969:23;;123921:87;124084:9;124077:4;:16;124073:73;;;124121:9;124114:16;;124073:73;124160:25;124188:16;124198:5;124188:9;:16::i;:::-;124160:44;;124382:4;124374:5;:12;124370:278;;;124407:19;124436:5;124429:4;:12;124407:34;;124478:17;124464:11;:31;124460:111;;;124540:11;124520:31;;124460:111;124388:198;124370:278;;;124631:1;124611:21;;124370:278;124662:25;124704:17;124690:32;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;124662:60;;124762:1;124741:17;:22;124737:78;;124791:8;124784:15;;;;;;;;124737:78;124959:31;124993:26;125013:5;124993:19;:26::i;:::-;124959:60;;125034:25;125279:9;:16;;;125274:92;;125336:9;:14;;;125316:34;;125274:92;125385:9;125397:5;125385:17;;125380:478;125409:4;125404:1;:9;;:45;;;;;125432:17;125417:11;:32;;125404:45;125380:478;;;125487:15;125500:1;125487:12;:15::i;:::-;125475:27;;125525:9;:16;;;125566:8;125521:73;125642:1;125616:28;;:9;:14;;;:28;;;125612:111;;125689:9;:14;;;125669:34;;125612:111;125766:5;125745:26;;:17;:26;;;125741:102;;125822:1;125796:8;125805:13;;;;;;125796:23;;;;;;;;:::i;:::-;;;;;;;:27;;;;;125741:102;125380:478;125451:3;;;;;125380:478;;;;125960:11;125950:8;125943:29;126008:8;126001:15;;;;;;;;123522:2513;;;;;;:::o;132910:348::-;135117:5;135107:15;;:6;;;;;;;;;;;:15;;;135099:35;;;;;;;;;;;;:::i;:::-;;;;;;;;;133060:8:::1;134405:5;134391:19;;:10;;;;;;;;;;;:19;;;134383:39;;;;;;;;;;;;:::i;:::-;;;;;;;;;134474:9;;;;;;;;;;;134445:38;;134462:8;134445:14;:12;:14::i;:::-;:25;:38;;134437:64;;;;;;;;;;;;:::i;:::-;;;;;;;;;133099:8:::2;134109:17;;;;;;;;;;;134097:29;;:8;:29;;134089:70;;;;;;;;;;;;:::i;:::-;;;;;;;;;134222:12;;;;;;;;;;;134182:52;;134210:8;134182:25;134196:10;134182:13;:25::i;:::-;:36;:52;;134174:91;;;;;;;;;;;;:::i;:::-;;;;;;;;;133135:9:::3;;134983:6;;;;;;;;;;;134902:87;;:77;134969:9;;134902:58;134923:10;134912:22;;;;;;;;:::i;:::-;;;;;;;;;;;;;134902:33;;;;;;:56;:58::i;:::-;:66;;:77;;;;;:::i;:::-;:87;;;134880:155;;;;;;;;;;;;:::i;:::-;;;;;;;;;133175:20:::4;;;;;;;;;;;133197:8;134662:3;134650:8;:15;;134642:46;;;;;;;;;;;;:::i;:::-;;;;;;;;;134747:8;134724:20;134733:10;134724:8;:20::i;:::-;:31;134711:9;:44;134703:75;;;;;;;;;;;;:::i;:::-;;;;;;;;;133223:27:::5;133229:10;133241:8;133223:5;:27::i;:::-;135046:1:::4;;134287::::3;;134523::::2;135145::::1;132910:348:::0;;;:::o;95858:234::-;96005:8;95953:18;:39;95972:19;:17;:19::i;:::-;95953:39;;;;;;;;;;;;;;;:49;95993:8;95953:49;;;;;;;;;;;;;;;;:60;;;;;;;;;;;;;;;;;;96065:8;96029:55;;96044:19;:17;:19::i;:::-;96029:55;;;96075:8;96029:55;;;;;;:::i;:::-;;;;;;;;95858:234;;:::o;131667:27::-;;;;;;;;;;;;;:::o;132098:108::-;132144:7;132171:27;132180:17;;;;;;;;;;;132171:8;:27::i;:::-;132164:34;;132098:108;:::o;136039:96::-;129403:13;:11;:13::i;:::-;136122:5:::1;136107:12;;:20;;;;;;;;;;;;;;;;;;136039:96:::0;:::o;131701:26::-;;;;;;;;;;;;;:::o;102651:407::-;102826:31;102839:4;102845:2;102849:7;102826:12;:31::i;:::-;102890:1;102872:2;:14;;;:19;102868:183;;102911:56;102942:4;102948:2;102952:7;102961:5;102911:30;:56::i;:::-;102906:145;;102995:40;;;;;;;;;;;;;;102906:145;102868:183;102651:407;;;;:::o;135449:263::-;129403:13;:11;:13::i;:::-;135553:2:::1;;:9;;135542:8;:20;;;;:::i;:::-;134405:5;134391:19;;:10;;;;;;;;;;;:19;;;134383:39;;;;;;;;;;;;:::i;:::-;;;;;;;;;134474:9;;;;;;;;;;;134445:38;;134462:8;134445:14;:12;:14::i;:::-;:25;:38;;134437:64;;;;;;;;;;;;:::i;:::-;;;;;;;;;135605:9:::2;135600:94;135621:2;;:9;;135616:1;:14;135600:94;;135656:22;135662:2;;135665:1;135662:5;;;;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;135669:8;135656:5;:22::i;:::-;135632:3;;;;;135600:94;;;;129427:1:::1;135449:263:::0;;;:::o;122019:428::-;122103:21;;:::i;:::-;122137:31;;:::i;:::-;122193:15;:13;:15::i;:::-;122183:7;:25;:54;;;;122223:14;:12;:14::i;:::-;122212:7;:25;;122183:54;122179:103;;;122261:9;122254:16;;;;;122179:103;122304:21;122317:7;122304:12;:21::i;:::-;122292:33;;122340:9;:16;;;122336:65;;;122380:9;122373:16;;;;;122336:65;122418:21;122431:7;122418:12;:21::i;:::-;122411:28;;;122019:428;;;;:::o;137087:117::-;129403:13;:11;:13::i;:::-;137176:20:::1;137190:5;137176:13;:20::i;:::-;137156:17;;:40;;;;;;;;;;;;;;;;;;137087:117:::0;:::o;131909:181::-;131993:13;132026:56;132044:9;132026:56;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;132063:18;132073:7;132063:9;:18::i;:::-;132026:17;:56::i;:::-;132019:63;;131909:181;;;:::o;136143:106::-;129403:13;:11;:13::i;:::-;136236:5:::1;136216:17;;:25;;;;;;;;;;;;;;;;;;136143:106:::0;:::o;131428:30::-;;;;;;;;;;;;;:::o;131638:22::-;;;;;;;;;;;;;:::o;136689:75::-;129403:13;:11;:13::i;:::-;136752:4:::1;136739:10;;:17;;;;;;;;;;;;;;;;;;136689:75::o:0;135720:155::-;129403:13;:11;:13::i;:::-;135820:5:::1;135802:23;;:14;;;;;;;;;;;:23;;;135794:43;;;;;;;;;;;;:::i;:::-;;;;;;;;;135862:5;;135850:9;:17;;;;;;;:::i;:::-;;135720:155:::0;;:::o;96249:164::-;96346:4;96370:18;:25;96389:5;96370:25;;;;;;;;;;;;;;;:35;96396:8;96370:35;;;;;;;;;;;;;;;;;;;;;;;;;96363:42;;96249:164;;;;:::o;131231:48::-;131268:11;131231:48;:::o;130423:201::-;129403:13;:11;:13::i;:::-;130532:1:::1;130512:22;;:8;:22;;::::0;130504:73:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;130588:28;130607:8;130588:18;:28::i;:::-;130423:201:::0;:::o;132214:114::-;132263:7;132290:30;132299:20;;;;;;;;;;;132290:8;:30::i;:::-;132283:37;;132214:114;:::o;136772:85::-;129403:13;:11;:13::i;:::-;136845:4:::1;136827:15;;:22;;;;;;;;;;;;;;;;;;136772:85::o:0;129682:132::-;129757:12;:10;:12::i;:::-;129746:23;;:7;:5;:7::i;:::-;:23;;;129738:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;129682:132::o;96671:282::-;96736:4;96792:7;96773:15;:13;:15::i;:::-;:26;;:66;;;;;96826:13;;96816:7;:23;96773:66;:153;;;;;96925:1;80679:8;96877:17;:26;96895:7;96877:26;;;;;;;;;;;;:44;:49;96773:153;96753:173;;96671:282;;;:::o;118979:105::-;119039:7;119066:10;119059:17;;118979:105;:::o;131800:101::-;131865:7;131892:1;131885:8;;131800:101;:::o;91357:1275::-;91424:7;91444:12;91459:7;91444:22;;91527:4;91508:15;:13;:15::i;:::-;:23;91504:1061;;91561:13;;91554:4;:20;91550:1015;;;91599:14;91616:17;:23;91634:4;91616:23;;;;;;;;;;;;91599:40;;91733:1;80679:8;91705:6;:24;:29;91701:845;;92370:113;92387:1;92377:6;:11;92370:113;;92430:17;:25;92448:6;;;;;;;92430:25;;;;;;;;;;;;92421:34;;92370:113;;;92516:6;92509:13;;;;;;91701:845;91576:989;91550:1015;91504:1061;92593:31;;;;;;;;;;;;;;91357:1275;;;;:::o;97834:485::-;97936:27;97965:23;98006:38;98047:15;:24;98063:7;98047:24;;;;;;;;;;;98006:65;;98224:18;98201:41;;98281:19;98275:26;98256:45;;98186:126;97834:485;;;:::o;97062:659::-;97211:11;97376:16;97369:5;97365:28;97356:37;;97536:16;97525:9;97521:32;97508:45;;97686:15;97675:9;97672:30;97664:5;97653:9;97650:20;97647:56;97637:66;;97062:659;;;;;:::o;103720:159::-;;;;;:::o;118288:311::-;118423:7;118443:16;81083:3;118469:19;:41;;118443:68;;81083:3;118537:31;118548:4;118554:2;118558:9;118537:10;:31::i;:::-;118529:40;;:62;;118522:69;;;118288:311;;;;;:::o;93180:450::-;93260:14;93428:16;93421:5;93417:28;93408:37;;93605:5;93591:11;93566:23;93562:41;93559:52;93552:5;93549:63;93539:73;;93180:450;;;;:::o;104544:158::-;;;;;:::o;84981:296::-;85036:7;85243:15;:13;:15::i;:::-;85227:13;;:31;85220:38;;84981:296;:::o;86059:178::-;86120:7;79903:13;80041:2;86148:18;:25;86167:5;86148:25;;;;;;;;;;;;;;;;:50;;86147:82;86140:89;;86059:178;;;:::o;133872:126::-;133931:7;131268:11;133966:10;133958:19;;:32;;;;:::i;:::-;133951:39;;133872:126;;;:::o;106320:2966::-;106393:20;106416:13;;106393:36;;106456:1;106444:8;:13;106440:44;;106466:18;;;;;;;;;;;;;;106440:44;106497:61;106527:1;106531:2;106535:12;106549:8;106497:21;:61::i;:::-;107041:1;80041:2;107011:1;:26;;107010:32;106998:8;:45;106972:18;:22;106991:2;106972:22;;;;;;;;;;;;;;;;:71;;;;;;;;;;;107320:139;107357:2;107411:33;107434:1;107438:2;107442:1;107411:14;:33::i;:::-;107378:30;107399:8;107378:20;:30::i;:::-;:66;107320:18;:139::i;:::-;107286:17;:31;107304:12;107286:31;;;;;;;;;;;:173;;;;107476:16;107507:11;107536:8;107521:12;:23;107507:37;;108057:16;108053:2;108049:25;108037:37;;108429:12;108389:8;108348:1;108286:25;108227:1;108166;108139:335;108800:1;108786:12;108782:20;108740:346;108841:3;108832:7;108829:16;108740:346;;109059:7;109049:8;109046:1;109019:25;109016:1;109013;109008:59;108894:1;108885:7;108881:15;108870:26;;108740:346;;;108744:77;109131:1;109119:8;:13;109115:45;;109141:19;;;;;;;;;;;;;;109115:45;109193:3;109177:13;:19;;;;106746:2462;;109218:60;109247:1;109251:2;109255:12;109269:8;109218:20;:60::i;:::-;106382:2904;106320:2966;;:::o;2281:489::-;2532:1;2529;2526;2523;2515:6;2511:2;2504:5;2499:35;2489:263;;2642:10;2636:4;2629:24;2732:4;2726;2719:18;2489:263;2281:489;;:::o;130784:191::-;130858:16;130877:6;;;;;;;;;;;130858:25;;130903:8;130894:6;;:17;;;;;;;;;;;;;;;;;;130958:8;130927:40;;130948:8;130927:40;;;;;;;;;;;;130847:128;130784:191;:::o;133553:311::-;133613:6;133687:1;131268:11;133665:5;:18;;;;;:::i;:::-;;;:23;133657:75;;;;;;;;;;;;:::i;:::-;;;;;;;;;133780:16;133755:41;;131268:11;133756:19;;;;;;:::i;:::-;;;;;;133755:41;;133747:63;;;;;;;;;;;;:::i;:::-;;;;;;;;;133839:5;133825:20;;133553:311;;;:::o;90805:161::-;90873:21;;:::i;:::-;90914:44;90933:17;:24;90951:5;90933:24;;;;;;;;;;;;90914:18;:44::i;:::-;90907:51;;90805:161;;;:::o;84247:103::-;84302:7;84329:13;;84322:20;;84247:103;:::o;64497:414::-;64566:14;64730:4;64724;64717:18;64762:50;64756:4;64749:64;64888:4;64882;64872:21;64862:31;;64497:414;;;:::o;59345:1692::-;59452:14;59576:2;59558:16;59555:24;59552:1467;;59696:4;59690:11;59821:4;59803:16;59797:4;59784:42;59962:23;59955:4;59949:11;59946:40;59936:982;;60024:4;60018;60011:18;60178:4;60160:16;60156:27;60143:41;60140:1;60135:50;60129:4;60122:64;60582:4;60527;60474;60420;60358;60279:5;60238:394;60208:447;60737:1;60731:4;60724:15;60881:16;60875:4;60871:27;60865:34;60855:44;;59936:982;61002:1;60996:4;60989:15;59580:1439;59552:1467;59345:1692;;;;;:::o;105142:716::-;105305:4;105351:2;105326:45;;;105372:19;:17;:19::i;:::-;105393:4;105399:7;105408:5;105326:88;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;105322:529;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;105626:1;105609:6;:13;:18;105605:235;;105655:40;;;;;;;;;;;;;;105605:235;105798:6;105792:13;105783:6;105779:2;105775:15;105768:38;105322:529;105495:54;;;105485:64;;;:6;:64;;;;105478:71;;;105142:716;;;;;;:::o;90543:166::-;90613:21;;:::i;:::-;90654:47;90673:27;90692:7;90673:18;:27::i;:::-;90654:18;:47::i;:::-;90647:54;;90543:166;;;:::o;119186:1745::-;119251:17;119685:4;119678;119672:11;119668:22;119777:1;119771:4;119764:15;119852:4;119849:1;119845:12;119838:19;;119934:1;119929:3;119922:14;120038:3;120277:5;120259:428;120285:1;120259:428;;;120325:1;120320:3;120316:11;120309:18;;120496:2;120490:4;120486:13;120482:2;120478:22;120473:3;120465:36;120590:2;120584:4;120580:13;120572:21;;120657:4;120259:428;120647:25;120259:428;120263:21;120726:3;120721;120717:13;120841:4;120836:3;120832:14;120825:21;;120906:6;120901:3;120894:19;119290:1634;;;119186:1745;;;:::o;26690:3542::-;26829:20;26962:7;26956:14;27010:6;27004:13;27062:11;27056:18;27114:4;27105:7;27101:18;27090:29;;27155:4;27147:6;27143:17;27133:27;;27206:4;27193:11;27189:22;27174:37;;27252:4;27245;27239:11;27235:22;27225:32;;27304:13;27295:7;27291:27;27359:13;27345:12;27342:31;27332:1998;;27453:1;27438:12;27426:10;27422:29;27418:37;27482:1;27528:2;27514:12;27511:20;27501:72;;27558:12;27550:6;27540:31;27535:36;;27501:72;27633:2;27619:12;27615:21;27611:2;27607:30;27604:1;27600:38;27671:6;27665:13;27696:1619;27703:1;27696:1619;;;27746:7;27740:14;27927:1;27924;27920:9;27917:1;27913:17;27903:1188;;27962:1;27959:441;;;28042:1;28027:12;28018:7;28008:32;28005:39;27995:378;;28096:1;28088:6;28081:17;28154:1;28146:6;28142:14;28132:24;;28214:1;28205:7;28201:15;28190:26;;28272:16;28263:7;28260:29;28250:50;;28293:5;;;28250:50;28334:8;;;27995:378;27959:441;28512:1;28497:254;28516:1;28497:254;;;28598:1;28585:11;28581:19;28575:26;28571:1;28563:6;28559:14;28552:50;28644:4;28641:1;28637:12;28632:17;;28695;28692:1;28689:24;28497:254;28679:45;28497:254;28501:14;28799:17;28791:6;28787:30;28777:40;;28867:12;28858:7;28854:26;28843:37;;28909:12;28906:162;;;28975:16;28966:7;28963:29;28953:50;;28996:5;;;28953:50;29033:8;;;28906:162;27903:1188;29128:1;29120:6;29113:17;29174:1;29166:6;29162:14;29152:24;;29222:1;29213:7;29209:15;29198:26;;29268:16;29259:7;29256:29;29246:50;;29289:5;;;29246:50;27708:1607;27696:1619;;;;27375:1955;;;;27332:1998;29369:6;29416:4;29409;29403:11;29399:22;29389:32;;29494:7;29482:10;29478:24;29469:6;29452:15;29448:28;29444:59;29581:217;29600:10;29591:7;29588:23;29581:217;;;29664:7;29658:14;29641:15;29634:39;29731:4;29714:15;29710:26;29691:45;;29778:4;29769:7;29765:18;29754:29;;29581:217;;;29834:4;29826:6;29822:17;29812:27;;29939:1;29932:4;29924:6;29920:17;29916:25;29968:1;29962:4;29955:15;30130:2;30126:7;30121:2;30115:4;30111:13;30107:27;30101:4;30094:41;30212:1;30204:6;30197:17;26920:3305;;;;;;;26690:3542;;;;;:::o;128068:98::-;128121:7;128148:10;128141:17;;128068:98;:::o;117989:147::-;118126:6;117989:147;;;;;:::o;93732:324::-;93802:14;94035:1;94025:8;94022:15;93996:24;93992:46;93982:56;;93732:324;;;:::o;92731:366::-;92797:31;;:::i;:::-;92874:6;92841:9;:14;;:41;;;;;;;;;;;80562:3;92927:6;:33;;92893:9;:24;;:68;;;;;;;;;;;93019:1;80679:8;92991:6;:24;:29;;92972:9;:16;;:48;;;;;;;;;;;81083:3;93060:6;:28;;93031:9;:19;;:58;;;;;;;;;;;92731:366;;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::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:89::-;1554:7;1594:6;1587:5;1583:18;1572:29;;1518:89;;;:::o;1613:120::-;1685:23;1702:5;1685:23;:::i;:::-;1678:5;1675:34;1665:62;;1723:1;1720;1713:12;1665:62;1613:120;:::o;1739:137::-;1784:5;1822:6;1809:20;1800:29;;1838:32;1864:5;1838:32;:::i;:::-;1739:137;;;;:::o;1882:327::-;1940:6;1989:2;1977:9;1968:7;1964:23;1960:32;1957:119;;;1995:79;;:::i;:::-;1957:119;2115:1;2140:52;2184:7;2175:6;2164:9;2160:22;2140:52;:::i;:::-;2130:62;;2086:116;1882:327;;;;:::o;2215:99::-;2267:6;2301:5;2295:12;2285:22;;2215:99;;;:::o;2320:169::-;2404:11;2438:6;2433:3;2426:19;2478:4;2473:3;2469:14;2454:29;;2320:169;;;;:::o;2495:246::-;2576:1;2586:113;2600:6;2597:1;2594:13;2586:113;;;2685:1;2680:3;2676:11;2670:18;2666:1;2661:3;2657:11;2650:39;2622:2;2619:1;2615:10;2610:15;;2586:113;;;2733:1;2724:6;2719:3;2715:16;2708:27;2557:184;2495:246;;;:::o;2747:102::-;2788:6;2839:2;2835:7;2830:2;2823:5;2819:14;2815:28;2805:38;;2747:102;;;:::o;2855:377::-;2943:3;2971:39;3004:5;2971:39;:::i;:::-;3026:71;3090:6;3085:3;3026:71;:::i;:::-;3019:78;;3106:65;3164:6;3159:3;3152:4;3145:5;3141:16;3106:65;:::i;:::-;3196:29;3218:6;3196:29;:::i;:::-;3191:3;3187:39;3180:46;;2947:285;2855:377;;;;:::o;3238:313::-;3351:4;3389:2;3378:9;3374:18;3366:26;;3438:9;3432:4;3428:20;3424:1;3413:9;3409:17;3402:47;3466:78;3539:4;3530:6;3466:78;:::i;:::-;3458:86;;3238:313;;;;:::o;3557:77::-;3594:7;3623:5;3612:16;;3557:77;;;:::o;3640:122::-;3713:24;3731:5;3713:24;:::i;:::-;3706:5;3703:35;3693:63;;3752:1;3749;3742:12;3693:63;3640:122;:::o;3768:139::-;3814:5;3852:6;3839:20;3830:29;;3868:33;3895:5;3868:33;:::i;:::-;3768:139;;;;:::o;3913:329::-;3972:6;4021:2;4009:9;4000:7;3996:23;3992:32;3989:119;;;4027:79;;:::i;:::-;3989:119;4147:1;4172:53;4217:7;4208:6;4197:9;4193:22;4172:53;:::i;:::-;4162:63;;4118:117;3913:329;;;;:::o;4248:126::-;4285:7;4325:42;4318:5;4314:54;4303:65;;4248:126;;;:::o;4380:96::-;4417:7;4446:24;4464:5;4446:24;:::i;:::-;4435:35;;4380:96;;;:::o;4482:118::-;4569:24;4587:5;4569:24;:::i;:::-;4564:3;4557:37;4482:118;;:::o;4606:222::-;4699:4;4737:2;4726:9;4722:18;4714:26;;4750:71;4818:1;4807:9;4803:17;4794:6;4750:71;:::i;:::-;4606:222;;;;:::o;4834:122::-;4907:24;4925:5;4907:24;:::i;:::-;4900:5;4897:35;4887:63;;4946:1;4943;4936:12;4887:63;4834:122;:::o;4962:139::-;5008:5;5046:6;5033:20;5024:29;;5062:33;5089:5;5062:33;:::i;:::-;4962:139;;;;:::o;5107:474::-;5175:6;5183;5232:2;5220:9;5211:7;5207:23;5203:32;5200:119;;;5238:79;;:::i;:::-;5200:119;5358:1;5383:53;5428:7;5419:6;5408:9;5404:22;5383:53;:::i;:::-;5373:63;;5329:117;5485:2;5511:53;5556:7;5547:6;5536:9;5532:22;5511:53;:::i;:::-;5501:63;;5456:118;5107:474;;;;;:::o;5587:116::-;5657:21;5672:5;5657:21;:::i;:::-;5650:5;5647:32;5637:60;;5693:1;5690;5683:12;5637:60;5587:116;:::o;5709:133::-;5752:5;5790:6;5777:20;5768:29;;5806:30;5830:5;5806:30;:::i;:::-;5709:133;;;;:::o;5848:323::-;5904:6;5953:2;5941:9;5932:7;5928:23;5924:32;5921:119;;;5959:79;;:::i;:::-;5921:119;6079:1;6104:50;6146:7;6137:6;6126:9;6122:22;6104:50;:::i;:::-;6094:60;;6050:114;5848:323;;;;:::o;6177:118::-;6264:24;6282:5;6264:24;:::i;:::-;6259:3;6252:37;6177:118;;:::o;6301:222::-;6394:4;6432:2;6421:9;6417:18;6409:26;;6445:71;6513:1;6502:9;6498:17;6489:6;6445:71;:::i;:::-;6301:222;;;;:::o;6529:619::-;6606:6;6614;6622;6671:2;6659:9;6650:7;6646:23;6642:32;6639:119;;;6677:79;;:::i;:::-;6639:119;6797:1;6822:53;6867:7;6858:6;6847:9;6843:22;6822:53;:::i;:::-;6812:63;;6768:117;6924:2;6950:53;6995:7;6986:6;6975:9;6971:22;6950:53;:::i;:::-;6940:63;;6895:118;7052:2;7078:53;7123:7;7114:6;7103:9;7099:22;7078:53;:::i;:::-;7068:63;;7023:118;6529:619;;;;;:::o;7154:86::-;7189:7;7229:4;7222:5;7218:16;7207:27;;7154:86;;;:::o;7246:112::-;7329:22;7345:5;7329:22;:::i;:::-;7324:3;7317:35;7246:112;;:::o;7364:214::-;7453:4;7491:2;7480:9;7476:18;7468:26;;7504:67;7568:1;7557:9;7553:17;7544:6;7504:67;:::i;:::-;7364:214;;;;:::o;7584:117::-;7693:1;7690;7683:12;7707:117;7816:1;7813;7806:12;7830:117;7939:1;7936;7929:12;7970:568;8043:8;8053:6;8103:3;8096:4;8088:6;8084:17;8080:27;8070:122;;8111:79;;:::i;:::-;8070:122;8224:6;8211:20;8201:30;;8254:18;8246:6;8243:30;8240:117;;;8276:79;;:::i;:::-;8240:117;8390:4;8382:6;8378:17;8366:29;;8444:3;8436:4;8428:6;8424:17;8414:8;8410:32;8407:41;8404:128;;;8451:79;;:::i;:::-;8404:128;7970:568;;;;;:::o;8544:559::-;8630:6;8638;8687:2;8675:9;8666:7;8662:23;8658:32;8655:119;;;8693:79;;:::i;:::-;8655:119;8841:1;8830:9;8826:17;8813:31;8871:18;8863:6;8860:30;8857:117;;;8893:79;;:::i;:::-;8857:117;9006:80;9078:7;9069:6;9058:9;9054:22;9006:80;:::i;:::-;8988:98;;;;8784:312;8544:559;;;;;:::o;9109:145::-;9207:6;9241:5;9235:12;9225:22;;9109:145;;;:::o;9260:215::-;9390:11;9424:6;9419:3;9412:19;9464:4;9459:3;9455:14;9440:29;;9260:215;;;;:::o;9481:163::-;9579:4;9602:3;9594:11;;9632:4;9627:3;9623:14;9615:22;;9481:163;;;:::o;9650:108::-;9727:24;9745:5;9727:24;:::i;:::-;9722:3;9715:37;9650:108;;:::o;9764:101::-;9800:7;9840:18;9833:5;9829:30;9818:41;;9764:101;;;:::o;9871:105::-;9946:23;9963:5;9946:23;:::i;:::-;9941:3;9934:36;9871:105;;:::o;9982:99::-;10053:21;10068:5;10053:21;:::i;:::-;10048:3;10041:34;9982:99;;:::o;10087:91::-;10123:7;10163:8;10156:5;10152:20;10141:31;;10087:91;;;:::o;10184:105::-;10259:23;10276:5;10259:23;:::i;:::-;10254:3;10247:36;10184:105;;:::o;10367:864::-;10516:4;10511:3;10507:14;10603:4;10596:5;10592:16;10586:23;10622:63;10679:4;10674:3;10670:14;10656:12;10622:63;:::i;:::-;10531:164;10787:4;10780:5;10776:16;10770:23;10806:61;10861:4;10856:3;10852:14;10838:12;10806:61;:::i;:::-;10705:172;10961:4;10954:5;10950:16;10944:23;10980:57;11031:4;11026:3;11022:14;11008:12;10980:57;:::i;:::-;10887:160;11134:4;11127:5;11123:16;11117:23;11153:61;11208:4;11203:3;11199:14;11185:12;11153:61;:::i;:::-;11057:167;10485:746;10367:864;;:::o;11237:303::-;11368:10;11389:108;11493:3;11485:6;11389:108;:::i;:::-;11529:4;11524:3;11520:14;11506:28;;11237:303;;;;:::o;11546:144::-;11647:4;11679;11674:3;11670:14;11662:22;;11546:144;;;:::o;11772:980::-;11953:3;11982:85;12061:5;11982:85;:::i;:::-;12083:117;12193:6;12188:3;12083:117;:::i;:::-;12076:124;;12224:87;12305:5;12224:87;:::i;:::-;12334:7;12365:1;12350:377;12375:6;12372:1;12369:13;12350:377;;;12451:6;12445:13;12478:125;12599:3;12584:13;12478:125;:::i;:::-;12471:132;;12626:91;12710:6;12626:91;:::i;:::-;12616:101;;12410:317;12397:1;12394;12390:9;12385:14;;12350:377;;;12354:14;12743:3;12736:10;;11958:794;;;11772:980;;;;:::o;12758:497::-;12963:4;13001:2;12990:9;12986:18;12978:26;;13050:9;13044:4;13040:20;13036:1;13025:9;13021:17;13014:47;13078:170;13243:4;13234:6;13078:170;:::i;:::-;13070:178;;12758:497;;;;:::o;13261:329::-;13320:6;13369:2;13357:9;13348:7;13344:23;13340:32;13337:119;;;13375:79;;:::i;:::-;13337:119;13495:1;13520:53;13565:7;13556:6;13545:9;13541:22;13520:53;:::i;:::-;13510:63;;13466:117;13261:329;;;;:::o;13596:114::-;13663:6;13697:5;13691:12;13681:22;;13596:114;;;:::o;13716:184::-;13815:11;13849:6;13844:3;13837:19;13889:4;13884:3;13880:14;13865:29;;13716:184;;;;:::o;13906:132::-;13973:4;13996:3;13988:11;;14026:4;14021:3;14017:14;14009:22;;13906:132;;;:::o;14044:108::-;14121:24;14139:5;14121:24;:::i;:::-;14116:3;14109:37;14044:108;;:::o;14158:179::-;14227:10;14248:46;14290:3;14282:6;14248:46;:::i;:::-;14326:4;14321:3;14317:14;14303:28;;14158:179;;;;:::o;14343:113::-;14413:4;14445;14440:3;14436:14;14428:22;;14343:113;;;:::o;14492:732::-;14611:3;14640:54;14688:5;14640:54;:::i;:::-;14710:86;14789:6;14784:3;14710:86;:::i;:::-;14703:93;;14820:56;14870:5;14820:56;:::i;:::-;14899:7;14930:1;14915:284;14940:6;14937:1;14934:13;14915:284;;;15016:6;15010:13;15043:63;15102:3;15087:13;15043:63;:::i;:::-;15036:70;;15129:60;15182:6;15129:60;:::i;:::-;15119:70;;14975:224;14962:1;14959;14955:9;14950:14;;14915:284;;;14919:14;15215:3;15208:10;;14616:608;;;14492:732;;;;:::o;15230:373::-;15373:4;15411:2;15400:9;15396:18;15388:26;;15460:9;15454:4;15450:20;15446:1;15435:9;15431:17;15424:47;15488:108;15591:4;15582:6;15488:108;:::i;:::-;15480:116;;15230:373;;;;:::o;15609:619::-;15686:6;15694;15702;15751:2;15739:9;15730:7;15726:23;15722:32;15719:119;;;15757:79;;:::i;:::-;15719:119;15877:1;15902:53;15947:7;15938:6;15927:9;15923:22;15902:53;:::i;:::-;15892:63;;15848:117;16004:2;16030:53;16075:7;16066:6;16055:9;16051:22;16030:53;:::i;:::-;16020:63;;15975:118;16132:2;16158:53;16203:7;16194:6;16183:9;16179:22;16158:53;:::i;:::-;16148:63;;16103:118;15609:619;;;;;:::o;16247:552::-;16304:8;16314:6;16364:3;16357:4;16349:6;16345:17;16341:27;16331:122;;16372:79;;:::i;:::-;16331:122;16485:6;16472:20;16462:30;;16515:18;16507:6;16504:30;16501:117;;;16537:79;;:::i;:::-;16501:117;16651:4;16643:6;16639:17;16627:29;;16705:3;16697:4;16689:6;16685:17;16675:8;16671:32;16668:41;16665:128;;;16712:79;;:::i;:::-;16665:128;16247:552;;;;;:::o;16805:672::-;16884:6;16892;16900;16949:2;16937:9;16928:7;16924:23;16920:32;16917:119;;;16955:79;;:::i;:::-;16917:119;17075:1;17100:53;17145:7;17136:6;17125:9;17121:22;17100:53;:::i;:::-;17090:63;;17046:117;17230:2;17219:9;17215:18;17202:32;17261:18;17253:6;17250:30;17247:117;;;17283:79;;:::i;:::-;17247:117;17396:64;17452:7;17443:6;17432:9;17428:22;17396:64;:::i;:::-;17378:82;;;;17173:297;16805:672;;;;;:::o;17483:468::-;17548:6;17556;17605:2;17593:9;17584:7;17580:23;17576:32;17573:119;;;17611:79;;:::i;:::-;17573:119;17731:1;17756:53;17801:7;17792:6;17781:9;17777:22;17756:53;:::i;:::-;17746:63;;17702:117;17858:2;17884:50;17926:7;17917:6;17906:9;17902:22;17884:50;:::i;:::-;17874:60;;17829:115;17483:468;;;;;:::o;17957:118::-;18028:22;18044:5;18028:22;:::i;:::-;18021:5;18018:33;18008:61;;18065:1;18062;18055:12;18008:61;17957:118;:::o;18081:135::-;18125:5;18163:6;18150:20;18141:29;;18179:31;18204:5;18179:31;:::i;:::-;18081:135;;;;:::o;18222:325::-;18279:6;18328:2;18316:9;18307:7;18303:23;18299:32;18296:119;;;18334:79;;:::i;:::-;18296:119;18454:1;18479:51;18522:7;18513:6;18502:9;18498:22;18479:51;:::i;:::-;18469:61;;18425:115;18222:325;;;;:::o;18553:117::-;18662:1;18659;18652:12;18676:180;18724:77;18721:1;18714:88;18821:4;18818:1;18811:15;18845:4;18842:1;18835:15;18862:281;18945:27;18967:4;18945:27;:::i;:::-;18937:6;18933:40;19075:6;19063:10;19060:22;19039:18;19027:10;19024:34;19021:62;19018:88;;;19086:18;;:::i;:::-;19018:88;19126:10;19122:2;19115:22;18905:238;18862:281;;:::o;19149:129::-;19183:6;19210:20;;:::i;:::-;19200:30;;19239:33;19267:4;19259:6;19239:33;:::i;:::-;19149:129;;;:::o;19284:307::-;19345:4;19435:18;19427:6;19424:30;19421:56;;;19457:18;;:::i;:::-;19421:56;19495:29;19517:6;19495:29;:::i;:::-;19487:37;;19579:4;19573;19569:15;19561:23;;19284:307;;;:::o;19597:146::-;19694:6;19689:3;19684;19671:30;19735:1;19726:6;19721:3;19717:16;19710:27;19597:146;;;:::o;19749:423::-;19826:5;19851:65;19867:48;19908:6;19867:48;:::i;:::-;19851:65;:::i;:::-;19842:74;;19939:6;19932:5;19925:21;19977:4;19970:5;19966:16;20015:3;20006:6;20001:3;19997:16;19994:25;19991:112;;;20022:79;;:::i;:::-;19991:112;20112:54;20159:6;20154:3;20149;20112:54;:::i;:::-;19832:340;19749:423;;;;;:::o;20191:338::-;20246:5;20295:3;20288:4;20280:6;20276:17;20272:27;20262:122;;20303:79;;:::i;:::-;20262:122;20420:6;20407:20;20445:78;20519:3;20511:6;20504:4;20496:6;20492:17;20445:78;:::i;:::-;20436:87;;20252:277;20191:338;;;;:::o;20535:943::-;20630:6;20638;20646;20654;20703:3;20691:9;20682:7;20678:23;20674:33;20671:120;;;20710:79;;:::i;:::-;20671:120;20830:1;20855:53;20900:7;20891:6;20880:9;20876:22;20855:53;:::i;:::-;20845:63;;20801:117;20957:2;20983:53;21028:7;21019:6;21008:9;21004:22;20983:53;:::i;:::-;20973:63;;20928:118;21085:2;21111:53;21156:7;21147:6;21136:9;21132:22;21111:53;:::i;:::-;21101:63;;21056:118;21241:2;21230:9;21226:18;21213:32;21272:18;21264:6;21261:30;21258:117;;;21294:79;;:::i;:::-;21258:117;21399:62;21453:7;21444:6;21433:9;21429:22;21399:62;:::i;:::-;21389:72;;21184:287;20535:943;;;;;;;:::o;21501:568::-;21574:8;21584:6;21634:3;21627:4;21619:6;21615:17;21611:27;21601:122;;21642:79;;:::i;:::-;21601:122;21755:6;21742:20;21732:30;;21785:18;21777:6;21774:30;21771:117;;;21807:79;;:::i;:::-;21771:117;21921:4;21913:6;21909:17;21897:29;;21975:3;21967:4;21959:6;21955:17;21945:8;21941:32;21938:41;21935:128;;;21982:79;;:::i;:::-;21935:128;21501:568;;;;;:::o;22075:704::-;22170:6;22178;22186;22235:2;22223:9;22214:7;22210:23;22206:32;22203:119;;;22241:79;;:::i;:::-;22203:119;22389:1;22378:9;22374:17;22361:31;22419:18;22411:6;22408:30;22405:117;;;22441:79;;:::i;:::-;22405:117;22554:80;22626:7;22617:6;22606:9;22602:22;22554:80;:::i;:::-;22536:98;;;;22332:312;22683:2;22709:53;22754:7;22745:6;22734:9;22730:22;22709:53;:::i;:::-;22699:63;;22654:118;22075:704;;;;;:::o;22857:874::-;23016:4;23011:3;23007:14;23103:4;23096:5;23092:16;23086:23;23122:63;23179:4;23174:3;23170:14;23156:12;23122:63;:::i;:::-;23031:164;23287:4;23280:5;23276:16;23270:23;23306:61;23361:4;23356:3;23352:14;23338:12;23306:61;:::i;:::-;23205:172;23461:4;23454:5;23450:16;23444:23;23480:57;23531:4;23526:3;23522:14;23508:12;23480:57;:::i;:::-;23387:160;23634:4;23627:5;23623:16;23617:23;23653:61;23708:4;23703:3;23699:14;23685:12;23653:61;:::i;:::-;23557:167;22985:746;22857:874;;:::o;23737:347::-;23892:4;23930:3;23919:9;23915:19;23907:27;;23944:133;24074:1;24063:9;24059:17;24050:6;23944:133;:::i;:::-;23737:347;;;;:::o;24090:115::-;24175:23;24192:5;24175:23;:::i;:::-;24170:3;24163:36;24090:115;;:::o;24211:218::-;24302:4;24340:2;24329:9;24325:18;24317:26;;24353:69;24419:1;24408:9;24404:17;24395:6;24353:69;:::i;:::-;24211:218;;;;:::o;24449:553::-;24507:8;24517:6;24567:3;24560:4;24552:6;24548:17;24544:27;24534:122;;24575:79;;:::i;:::-;24534:122;24688:6;24675:20;24665:30;;24718:18;24710:6;24707:30;24704:117;;;24740:79;;:::i;:::-;24704:117;24854:4;24846:6;24842:17;24830:29;;24908:3;24900:4;24892:6;24888:17;24878:8;24874:32;24871:41;24868:128;;;24915:79;;:::i;:::-;24868:128;24449:553;;;;;:::o;25008:529::-;25079:6;25087;25136:2;25124:9;25115:7;25111:23;25107:32;25104:119;;;25142:79;;:::i;:::-;25104:119;25290:1;25279:9;25275:17;25262:31;25320:18;25312:6;25309:30;25306:117;;;25342:79;;:::i;:::-;25306:117;25455:65;25512:7;25503:6;25492:9;25488:22;25455:65;:::i;:::-;25437:83;;;;25233:297;25008:529;;;;;:::o;25543:474::-;25611:6;25619;25668:2;25656:9;25647:7;25643:23;25639:32;25636:119;;;25674:79;;:::i;:::-;25636:119;25794:1;25819:53;25864:7;25855:6;25844:9;25840:22;25819:53;:::i;:::-;25809:63;;25765:117;25921:2;25947:53;25992:7;25983:6;25972:9;25968:22;25947:53;:::i;:::-;25937:63;;25892:118;25543:474;;;;;:::o;26023:157::-;26163:9;26159:1;26151:6;26147:14;26140:33;26023:157;:::o;26186:365::-;26328:3;26349:66;26413:1;26408:3;26349:66;:::i;:::-;26342:73;;26424:93;26513:3;26424:93;:::i;:::-;26542:2;26537:3;26533:12;26526:19;;26186:365;;;:::o;26557:419::-;26723:4;26761:2;26750:9;26746:18;26738:26;;26810:9;26804:4;26800:20;26796:1;26785:9;26781:17;26774:47;26838:131;26964:4;26838:131;:::i;:::-;26830:139;;26557:419;;;:::o;26982:180::-;27030:77;27027:1;27020:88;27127:4;27124:1;27117:15;27151:4;27148:1;27141:15;27168:320;27212:6;27249:1;27243:4;27239:12;27229:22;;27296:1;27290:4;27286:12;27317:18;27307:81;;27373:4;27365:6;27361:17;27351:27;;27307:81;27435:2;27427:6;27424:14;27404:18;27401:38;27398:84;;27454:18;;:::i;:::-;27398:84;27219:269;27168:320;;;:::o;27494:169::-;27634:21;27630:1;27622:6;27618:14;27611:45;27494:169;:::o;27669:366::-;27811:3;27832:67;27896:2;27891:3;27832:67;:::i;:::-;27825:74;;27908:93;27997:3;27908:93;:::i;:::-;28026:2;28021:3;28017:12;28010:19;;27669:366;;;:::o;28041:419::-;28207:4;28245:2;28234:9;28230:18;28222:26;;28294:9;28288:4;28284:20;28280:1;28269:9;28265:17;28258:47;28322:131;28448:4;28322:131;:::i;:::-;28314:139;;28041:419;;;:::o;28466:165::-;28606:17;28602:1;28594:6;28590:14;28583:41;28466:165;:::o;28637:366::-;28779:3;28800:67;28864:2;28859:3;28800:67;:::i;:::-;28793:74;;28876:93;28965:3;28876:93;:::i;:::-;28994:2;28989:3;28985:12;28978:19;;28637:366;;;:::o;29009:419::-;29175:4;29213:2;29202:9;29198:18;29190:26;;29262:9;29256:4;29252:20;29248:1;29237:9;29233:17;29226:47;29290:131;29416:4;29290:131;:::i;:::-;29282:139;;29009:419;;;:::o;29434:157::-;29574:9;29570:1;29562:6;29558:14;29551:33;29434:157;:::o;29597:365::-;29739:3;29760:66;29824:1;29819:3;29760:66;:::i;:::-;29753:73;;29835:93;29924:3;29835:93;:::i;:::-;29953:2;29948:3;29944:12;29937:19;;29597:365;;;:::o;29968:419::-;30134:4;30172:2;30161:9;30157:18;30149:26;;30221:9;30215:4;30211:20;30207:1;30196:9;30192:17;30185:47;30249:131;30375:4;30249:131;:::i;:::-;30241:139;;29968:419;;;:::o;30393:163::-;30533:15;30529:1;30521:6;30517:14;30510:39;30393:163;:::o;30562:366::-;30704:3;30725:67;30789:2;30784:3;30725:67;:::i;:::-;30718:74;;30801:93;30890:3;30801:93;:::i;:::-;30919:2;30914:3;30910:12;30903:19;;30562:366;;;:::o;30934:419::-;31100:4;31138:2;31127:9;31123:18;31115:26;;31187:9;31181:4;31177:20;31173:1;31162:9;31158:17;31151:47;31215:131;31341:4;31215:131;:::i;:::-;31207:139;;30934:419;;;:::o;31359:178::-;31499:30;31495:1;31487:6;31483:14;31476:54;31359:178;:::o;31543:366::-;31685:3;31706:67;31770:2;31765:3;31706:67;:::i;:::-;31699:74;;31782:93;31871:3;31782:93;:::i;:::-;31900:2;31895:3;31891:12;31884:19;;31543:366;;;:::o;31915:419::-;32081:4;32119:2;32108:9;32104:18;32096:26;;32168:9;32162:4;32158:20;32154:1;32143:9;32139:17;32132:47;32196:131;32322:4;32196:131;:::i;:::-;32188:139;;31915:419;;;:::o;32340:176::-;32480:28;32476:1;32468:6;32464:14;32457:52;32340:176;:::o;32522:366::-;32664:3;32685:67;32749:2;32744:3;32685:67;:::i;:::-;32678:74;;32761:93;32850:3;32761:93;:::i;:::-;32879:2;32874:3;32870:12;32863:19;;32522:366;;;:::o;32894:419::-;33060:4;33098:2;33087:9;33083:18;33075:26;;33147:9;33141:4;33137:20;33133:1;33122:9;33118:17;33111:47;33175:131;33301:4;33175:131;:::i;:::-;33167:139;;32894:419;;;:::o;33319:168::-;33459:20;33455:1;33447:6;33443:14;33436:44;33319:168;:::o;33493:366::-;33635:3;33656:67;33720:2;33715:3;33656:67;:::i;:::-;33649:74;;33732:93;33821:3;33732:93;:::i;:::-;33850:2;33845:3;33841:12;33834:19;;33493:366;;;:::o;33865:419::-;34031:4;34069:2;34058:9;34054:18;34046:26;;34118:9;34112:4;34108:20;34104:1;34093:9;34089:17;34082:47;34146:131;34272:4;34146:131;:::i;:::-;34138:139;;33865:419;;;:::o;34290:168::-;34430:20;34426:1;34418:6;34414:14;34407:44;34290:168;:::o;34464:366::-;34606:3;34627:67;34691:2;34686:3;34627:67;:::i;:::-;34620:74;;34703:93;34792:3;34703:93;:::i;:::-;34821:2;34816:3;34812:12;34805:19;;34464:366;;;:::o;34836:419::-;35002:4;35040:2;35029:9;35025:18;35017:26;;35089:9;35083:4;35079:20;35075:1;35064:9;35060:17;35053:47;35117:131;35243:4;35117:131;:::i;:::-;35109:139;;34836:419;;;:::o;35261:180::-;35309:77;35306:1;35299:88;35406:4;35403:1;35396:15;35430:4;35427:1;35420:15;35447:223;35587:34;35583:1;35575:6;35571:14;35564:58;35656:6;35651:2;35643:6;35639:15;35632:31;35447:223;:::o;35676:366::-;35818:3;35839:67;35903:2;35898:3;35839:67;:::i;:::-;35832:74;;35915:93;36004:3;35915:93;:::i;:::-;36033:2;36028:3;36024:12;36017:19;;35676:366;;;:::o;36048:419::-;36214:4;36252:2;36241:9;36237:18;36229:26;;36301:9;36295:4;36291:20;36287:1;36276:9;36272:17;36265:47;36329:131;36455:4;36329:131;:::i;:::-;36321:139;;36048:419;;;:::o;36473:168::-;36613:20;36609:1;36601:6;36597:14;36590:44;36473:168;:::o;36647:366::-;36789:3;36810:67;36874:2;36869:3;36810:67;:::i;:::-;36803:74;;36886:93;36975:3;36886:93;:::i;:::-;37004:2;36999:3;36995:12;36988:19;;36647:366;;;:::o;37019:419::-;37185:4;37223:2;37212:9;37208:18;37200:26;;37272:9;37266:4;37262:20;37258:1;37247:9;37243:17;37236:47;37300:131;37426:4;37300:131;:::i;:::-;37292:139;;37019:419;;;:::o;37444:180::-;37492:77;37489:1;37482:88;37589:4;37586:1;37579:15;37613:4;37610:1;37603:15;37630:348;37670:7;37693:20;37711:1;37693:20;:::i;:::-;37688:25;;37727:20;37745:1;37727:20;:::i;:::-;37722:25;;37915:1;37847:66;37843:74;37840:1;37837:81;37832:1;37825:9;37818:17;37814:105;37811:131;;;37922:18;;:::i;:::-;37811:131;37970:1;37967;37963:9;37952:20;;37630:348;;;;:::o;37984:97::-;38043:6;38071:3;38061:13;;37984:97;;;;:::o;38087:141::-;38136:4;38159:3;38151:11;;38182:3;38179:1;38172:14;38216:4;38213:1;38203:18;38195:26;;38087:141;;;:::o;38234:93::-;38271:6;38318:2;38313;38306:5;38302:14;38298:23;38288:33;;38234:93;;;:::o;38333:107::-;38377:8;38427:5;38421:4;38417:16;38396:37;;38333:107;;;;:::o;38446:393::-;38515:6;38565:1;38553:10;38549:18;38588:97;38618:66;38607:9;38588:97;:::i;:::-;38706:39;38736:8;38725:9;38706:39;:::i;:::-;38694:51;;38778:4;38774:9;38767:5;38763:21;38754:30;;38827:4;38817:8;38813:19;38806:5;38803:30;38793:40;;38522:317;;38446:393;;;;;:::o;38845:60::-;38873:3;38894:5;38887:12;;38845:60;;;:::o;38911:142::-;38961:9;38994:53;39012:34;39021:24;39039:5;39021:24;:::i;:::-;39012:34;:::i;:::-;38994:53;:::i;:::-;38981:66;;38911:142;;;:::o;39059:75::-;39102:3;39123:5;39116:12;;39059:75;;;:::o;39140:269::-;39250:39;39281:7;39250:39;:::i;:::-;39311:91;39360:41;39384:16;39360:41;:::i;:::-;39352:6;39345:4;39339:11;39311:91;:::i;:::-;39305:4;39298:105;39216:193;39140:269;;;:::o;39415:73::-;39460:3;39415:73;:::o;39494:189::-;39571:32;;:::i;:::-;39612:65;39670:6;39662;39656:4;39612:65;:::i;:::-;39547:136;39494:189;;:::o;39689:186::-;39749:120;39766:3;39759:5;39756:14;39749:120;;;39820:39;39857:1;39850:5;39820:39;:::i;:::-;39793:1;39786:5;39782:13;39773:22;;39749:120;;;39689:186;;:::o;39881:543::-;39982:2;39977:3;39974:11;39971:446;;;40016:38;40048:5;40016:38;:::i;:::-;40100:29;40118:10;40100:29;:::i;:::-;40090:8;40086:44;40283:2;40271:10;40268:18;40265:49;;;40304:8;40289:23;;40265:49;40327:80;40383:22;40401:3;40383:22;:::i;:::-;40373:8;40369:37;40356:11;40327:80;:::i;:::-;39986:431;;39971:446;39881:543;;;:::o;40430:117::-;40484:8;40534:5;40528:4;40524:16;40503:37;;40430:117;;;;:::o;40553:169::-;40597:6;40630:51;40678:1;40674:6;40666:5;40663:1;40659:13;40630:51;:::i;:::-;40626:56;40711:4;40705;40701:15;40691:25;;40604:118;40553:169;;;;:::o;40727:295::-;40803:4;40949:29;40974:3;40968:4;40949:29;:::i;:::-;40941:37;;41011:3;41008:1;41004:11;40998:4;40995:21;40987:29;;40727:295;;;;:::o;41027:1403::-;41151:44;41191:3;41186;41151:44;:::i;:::-;41260:18;41252:6;41249:30;41246:56;;;41282:18;;:::i;:::-;41246:56;41326:38;41358:4;41352:11;41326:38;:::i;:::-;41411:67;41471:6;41463;41457:4;41411:67;:::i;:::-;41505:1;41534:2;41526:6;41523:14;41551:1;41546:632;;;;42222:1;42239:6;42236:84;;;42295:9;42290:3;42286:19;42273:33;42264:42;;42236:84;42346:67;42406:6;42399:5;42346:67;:::i;:::-;42340:4;42333:81;42195:229;41516:908;;41546:632;41598:4;41594:9;41586:6;41582:22;41632:37;41664:4;41632:37;:::i;:::-;41691:1;41705:215;41719:7;41716:1;41713:14;41705:215;;;41805:9;41800:3;41796:19;41783:33;41775:6;41768:49;41856:1;41848:6;41844:14;41834:24;;41903:2;41892:9;41888:18;41875:31;;41742:4;41739:1;41735:12;41730:17;;41705:215;;;41948:6;41939:7;41936:19;41933:186;;;42013:9;42008:3;42004:19;41991:33;42056:48;42098:4;42090:6;42086:17;42075:9;42056:48;:::i;:::-;42048:6;42041:64;41956:163;41933:186;42165:1;42161;42153:6;42149:14;42145:22;42139:4;42132:36;41553:625;;;41516:908;;41126:1304;;;41027:1403;;;:::o;42436:225::-;42576:34;42572:1;42564:6;42560:14;42553:58;42645:8;42640:2;42632:6;42628:15;42621:33;42436:225;:::o;42667:366::-;42809:3;42830:67;42894:2;42889:3;42830:67;:::i;:::-;42823:74;;42906:93;42995:3;42906:93;:::i;:::-;43024:2;43019:3;43015:12;43008:19;;42667:366;;;:::o;43039:419::-;43205:4;43243:2;43232:9;43228:18;43220:26;;43292:9;43286:4;43282:20;43278:1;43267:9;43263:17;43256:47;43320:131;43446:4;43320:131;:::i;:::-;43312:139;;43039:419;;;:::o;43464:182::-;43604:34;43600:1;43592:6;43588:14;43581:58;43464:182;:::o;43652:366::-;43794:3;43815:67;43879:2;43874:3;43815:67;:::i;:::-;43808:74;;43891:93;43980:3;43891:93;:::i;:::-;44009:2;44004:3;44000:12;43993:19;;43652:366;;;:::o;44024:419::-;44190:4;44228:2;44217:9;44213:18;44205:26;;44277:9;44271:4;44267:20;44263:1;44252:9;44248:17;44241:47;44305:131;44431:4;44305:131;:::i;:::-;44297:139;;44024:419;;;:::o;44449:180::-;44497:77;44494:1;44487:88;44594:4;44591:1;44584:15;44618:4;44615:1;44608:15;44635:226;44775:34;44771:1;44763:6;44759:14;44752:58;44844:9;44839:2;44831:6;44827:15;44820:34;44635:226;:::o;44867:366::-;45009:3;45030:67;45094:2;45089:3;45030:67;:::i;:::-;45023:74;;45106:93;45195:3;45106:93;:::i;:::-;45224:2;45219:3;45215:12;45208:19;;44867:366;;;:::o;45239:419::-;45405:4;45443:2;45432:9;45428:18;45420:26;;45492:9;45486:4;45482:20;45478:1;45467:9;45463:17;45456:47;45520:131;45646:4;45520:131;:::i;:::-;45512:139;;45239:419;;;:::o;45664:159::-;45804:11;45800:1;45792:6;45788:14;45781:35;45664:159;:::o;45829:365::-;45971:3;45992:66;46056:1;46051:3;45992:66;:::i;:::-;45985:73;;46067:93;46156:3;46067:93;:::i;:::-;46185:2;46180:3;46176:12;46169:19;;45829:365;;;:::o;46200:419::-;46366:4;46404:2;46393:9;46389:18;46381:26;;46453:9;46447:4;46443:20;46439:1;46428:9;46424:17;46417:47;46481:131;46607:4;46481:131;:::i;:::-;46473:139;;46200:419;;;:::o;46625:98::-;46676:6;46710:5;46704:12;46694:22;;46625:98;;;:::o;46729:168::-;46812:11;46846:6;46841:3;46834:19;46886:4;46881:3;46877:14;46862:29;;46729:168;;;;:::o;46903:373::-;46989:3;47017:38;47049:5;47017:38;:::i;:::-;47071:70;47134:6;47129:3;47071:70;:::i;:::-;47064:77;;47150:65;47208:6;47203:3;47196:4;47189:5;47185:16;47150:65;:::i;:::-;47240:29;47262:6;47240:29;:::i;:::-;47235:3;47231:39;47224:46;;46993:283;46903:373;;;;:::o;47282:640::-;47477:4;47515:3;47504:9;47500:19;47492:27;;47529:71;47597:1;47586:9;47582:17;47573:6;47529:71;:::i;:::-;47610:72;47678:2;47667:9;47663:18;47654:6;47610:72;:::i;:::-;47692;47760:2;47749:9;47745:18;47736:6;47692:72;:::i;:::-;47811:9;47805:4;47801:20;47796:2;47785:9;47781:18;47774:48;47839:76;47910:4;47901:6;47839:76;:::i;:::-;47831:84;;47282:640;;;;;;;:::o;47928:141::-;47984:5;48015:6;48009:13;48000:22;;48031:32;48057:5;48031:32;:::i;:::-;47928:141;;;;:::o;48075:349::-;48144:6;48193:2;48181:9;48172:7;48168:23;48164:32;48161:119;;;48199:79;;:::i;:::-;48161:119;48319:1;48344:63;48399:7;48390:6;48379:9;48375:22;48344:63;:::i;:::-;48334:73;;48290:127;48075:349;;;;:::o

Swarm Source

ipfs://c370b975e2ba79e723fab553022730e1d789afed3fd3e543a57941c869e7131f
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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