ETH Price: $3,495.23 (+0.23%)
Gas: 2 Gwei

Token

Primes (PRIME)
 

Overview

Max Total Supply

0 PRIME

Holders

156

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Filtered by Token Holder
meta888crypto.eth
Balance
1 PRIME
0xe969bf18fbc0ed94fbeb0821d347d0525a2c880a
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.

Contract Source Code Verified (Exact Match)

Contract Name:
Primes

Compiler Version
v0.8.7+commit.e28d00a7

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, GNU GPLv3 license

Contract Source Code (Solidity)

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

pragma solidity ^0.8.7;

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

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

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

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

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

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

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, 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
    ) external;

    /**
     * @dev Transfers `tokenId` token 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;

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

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

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

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

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

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

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

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

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

        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }

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

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

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

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

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

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

        (bool success, bytes memory returndata) = target.call{ value: value }(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

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

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

        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

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

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

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

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

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

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

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

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

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

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

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

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

contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
    using Address for address;
    using Strings for uint256;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

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

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

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

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

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

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

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

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId) public view virtual override returns (address) {
        address owner = _owners[tokenId];
        require(owner != address(0), "ERC721: owner query for nonexistent token");
        return owner;
    }

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

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

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");

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

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

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

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

        _approve(to, tokenId);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId) public view virtual override returns (address) {
        require(_exists(tokenId), "ERC721: approved query for nonexistent token");

        return _tokenApprovals[tokenId];
    }

    /**
     * @dev See {IERC721-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public virtual override {
        require(operator != _msgSender(), "ERC721: approve to caller");

        _operatorApprovals[_msgSender()][operator] = approved;
        emit ApprovalForAll(_msgSender(), operator, approved);
    }

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

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

        _transfer(from, to, tokenId);
    }

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

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

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

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

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

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

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

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

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

        _balances[to] += 1;
        _owners[tokenId] = to;

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

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

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

        // Clear approvals
        _approve(address(0), tokenId);

        _balances[owner] -= 1;
        delete _owners[tokenId];

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

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

        _beforeTokenTransfer(from, to, tokenId);

        // Clear approvals from the previous owner
        _approve(address(0), tokenId);

        _balances[from] -= 1;
        _balances[to] += 1;
        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);
    }

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

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

    /**
     * @dev Hook that is called before any token transfer. This includes minting
     * and burning.
     *
     * 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, ``from``'s `tokenId` will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {}
}

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() {
        _setOwner(_msgSender());
    }

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

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

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _setOwner(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");
        _setOwner(newOwner);
    }

    function _setOwner(address newOwner) private {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

contract Initializable {
    bool inited = false;

    modifier initializer() {
        require(!inited, "already inited");
        _;
        inited = true;
    }
}

contract EIP712Base is Initializable {
    struct EIP712Domain {
        string name;
        string version;
        address verifyingContract;
        bytes32 salt;
    }

    string public constant ERC712_VERSION = "1";

    bytes32 internal constant EIP712_DOMAIN_TYPEHASH =
        keccak256(
            bytes("EIP712Domain(string name,string version,address verifyingContract,bytes32 salt)")
        );
    bytes32 internal domainSeperator;

    // supposed to be called once while initializing.
    // one of the contracts that inherits this contract follows proxy pattern
    // so it is not possible to do this in a constructor
    function _initializeEIP712(string memory name) internal initializer {
        _setDomainSeperator(name);
    }

    function _setDomainSeperator(string memory name) internal {
        domainSeperator = keccak256(
            abi.encode(
                EIP712_DOMAIN_TYPEHASH,
                keccak256(bytes(name)),
                keccak256(bytes(ERC712_VERSION)),
                address(this),
                bytes32(getChainId())
            )
        );
    }

    function getDomainSeperator() public view returns (bytes32) {
        return domainSeperator;
    }

    function getChainId() public view returns (uint256) {
        uint256 id;
        assembly {
            id := chainid()
        }
        return id;
    }

    /**
     * Accept message hash and returns hash message in EIP712 compatible form
     * So that it can be used to recover signer from signature signed using EIP712 formatted data
     * https://eips.ethereum.org/EIPS/eip-712
     * "\\x19" makes the encoding deterministic
     * "\\x01" is the version byte to make it compatible to EIP-191
     */
    function toTypedMessageHash(bytes32 messageHash) internal view returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x01", getDomainSeperator(), messageHash));
    }
}

contract NativeMetaTransaction is EIP712Base {
    bytes32 private constant META_TRANSACTION_TYPEHASH =
        keccak256(bytes("MetaTransaction(uint256 nonce,address from,bytes functionSignature)"));
    event MetaTransactionExecuted(
        address userAddress,
        address payable relayerAddress,
        bytes functionSignature
    );
    mapping(address => uint256) nonces;

    /*
     * Meta transaction structure.
     * No point of including value field here as if user is doing value transfer then he has the funds to pay for gas
     * He should call the desired function directly in that case.
     */
    struct MetaTransaction {
        uint256 nonce;
        address from;
        bytes functionSignature;
    }

    function executeMetaTransaction(
        address userAddress,
        bytes memory functionSignature,
        bytes32 sigR,
        bytes32 sigS,
        uint8 sigV
    ) public payable returns (bytes memory) {
        MetaTransaction memory metaTx = MetaTransaction({
            nonce: nonces[userAddress],
            from: userAddress,
            functionSignature: functionSignature
        });

        require(verify(userAddress, metaTx, sigR, sigS, sigV), "Signer and signature do not match");

        // increase nonce for user (to avoid re-use)
        nonces[userAddress] += 1;

        emit MetaTransactionExecuted(userAddress, payable(msg.sender), functionSignature);

        // Append userAddress and relayer address at the end to extract it from calling context
        (bool success, bytes memory returnData) = address(this).call(
            abi.encodePacked(functionSignature, userAddress)
        );
        require(success, "Function call not successful");

        return returnData;
    }

    function hashMetaTransaction(MetaTransaction memory metaTx) internal pure returns (bytes32) {
        return
            keccak256(
                abi.encode(
                    META_TRANSACTION_TYPEHASH,
                    metaTx.nonce,
                    metaTx.from,
                    keccak256(metaTx.functionSignature)
                )
            );
    }

    function getNonce(address user) public view returns (uint256 nonce) {
        nonce = nonces[user];
    }

    function verify(
        address signer,
        MetaTransaction memory metaTx,
        bytes32 sigR,
        bytes32 sigS,
        uint8 sigV
    ) internal view returns (bool) {
        require(signer != address(0), "NativeMetaTransaction: INVALID_SIGNER");
        return
            signer == ecrecover(toTypedMessageHash(hashMetaTransaction(metaTx)), sigV, sigR, sigS);
    }
}

abstract contract ContextMixin {
    function msgSender() internal view returns (address payable sender) {
        if (msg.sender == address(this)) {
            bytes memory array = msg.data;
            uint256 index = msg.data.length;
            assembly {
                // Load the 32 bytes word from memory with the address on the lower 20 bytes, and mask those.
                sender := and(mload(add(array, index)), 0xffffffffffffffffffffffffffffffffffffffff)
            }
        } else {
            sender = payable(msg.sender);
        }
        return sender;
    }
}

contract OwnableDelegateProxy {}

contract ProxyRegistry {
    mapping(address => OwnableDelegateProxy) public proxies;
}

abstract contract ERC721Tradable is ContextMixin, Ownable, ERC721, NativeMetaTransaction {
    address public proxyRegistryAddress;
    uint256 private _currentTokenId = 0;

    constructor(
        string memory _name,
        string memory _symbol,
        address _proxyRegistryAddress
    ) ERC721(_name, _symbol) Ownable() {
        proxyRegistryAddress = _proxyRegistryAddress;
        _initializeEIP712(_name);
    }

    /**
     * Override isApprovedForAll to whitelist user's OpenSea proxy accounts to enable gas-less listings.
     */
    function isApprovedForAll(address owner, address operator) public view override returns (bool) {
        // Whitelist OpenSea proxy contract for easy trading.
        ProxyRegistry proxyRegistry = ProxyRegistry(proxyRegistryAddress);
        if (
            proxyRegistryAddress != address(0) && address(proxyRegistry.proxies(owner)) == operator
        ) {
            return true;
        }

        return super.isApprovedForAll(owner, operator);
    }

    /**
     * This is used instead of msg.sender as transactions won't be sent by the original token owner, but by OpenSea.
     */
    function _msgSender() internal view override returns (address sender) {
        return ContextMixin.msgSender();
    }
}

abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

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

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

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

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

        _;

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

library Packed16BitArray {
    using Packed16BitArray for Packed16BitArray.PackedArray;

    struct PackedArray {
        uint256[] array;
        uint256 length;
    }

    // Verifies that the higher level count is correct, and that the last uint256 is left packed with 0's
    function initStruct(uint256[] memory _arr, uint256 _len)
        internal
        pure
        returns (PackedArray memory)
    {
        uint256 actualLength = _arr.length;
        uint256 len0 = _len / 16;
        require(actualLength == len0 + 1, "Invalid arr length");

        uint256 len1 = _len % 16;
        uint256 leftPacked = uint256(_arr[len0] >> (len1 * 16));
        require(leftPacked == 0, "Invalid uint256 packing");

        return PackedArray(_arr, _len);
    }

    function getValue(PackedArray storage ref, uint256 _index) internal view returns (uint16) {
        require(_index < ref.length, "Invalid index");
        uint256 aid = _index / 16;
        uint256 iid = _index % 16;
        return uint16(ref.array[aid] >> (iid * 16));
    }

    function biDirectionalSearch(
        PackedArray storage ref,
        uint256 _startIndex,
        uint16 _delta
    ) internal view returns (uint16[2] memory hits) {
        uint16 startVal = ref.getValue(_startIndex);

        // Search down
        if (startVal >= _delta && _startIndex > 0) {
            uint16 tempVal = startVal;
            uint256 tempIdx = _startIndex - 1;
            uint16 target = startVal - _delta;

            while (tempVal >= target) {
                tempVal = ref.getValue(tempIdx);
                if (tempVal == target) {
                    hits[0] = tempVal;
                    break;
                }
                if (tempIdx == 0) {
                    break;
                } else {
                    tempIdx--;
                }
            }
        }
        {
            // Search up
            uint16 tempVal = startVal;
            uint256 tempIdx = _startIndex + 1;
            uint16 target = startVal + _delta;

            while (tempVal <= target) {
                if (tempIdx >= ref.length) break;
                tempVal = ref.getValue(tempIdx++);
                if (tempVal == target) {
                    hits[1] = tempVal;
                    break;
                }
            }
        }
    }

    function setValue(
        PackedArray storage ref,
        uint256 _index,
        uint16 _value
    ) internal {
        uint256 aid = _index / 16;
        uint256 iid = _index % 16;

        // 1. Do an && between old value and a mask
        uint256 mask = uint256(~(uint256(65535) << (iid * 16)));
        uint256 masked = ref.array[aid] & mask;
        // 2. Do an |= between (1) and positioned _value
        mask = uint256(_value) << (iid * 16);
        ref.array[aid] = masked | mask;
    }

    function extractIndex(PackedArray storage ref, uint256 _index) internal {
        // Get value at the end
        uint16 endValue = ref.getValue(ref.length - 1);
        ref.setValue(_index, endValue);
        // TODO - could get rid of this and rely on length if need to reduce gas
        // ref.setValue(ref.length - 1, 0);
        ref.length--;
    }
}

library MerkleProof {
    /**
     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
     * defined by `root`. For this, a `proof` must be provided, containing
     * sibling hashes on the branch from the leaf to the root of the tree. Each
     * pair of leaves and each pair of pre-images are assumed to be sorted.
     */
    function verify(
        bytes32[] memory proof,
        bytes32 root,
        bytes32 leaf
    ) internal pure returns (bool) {
        bytes32 computedHash = leaf;

        for (uint256 i = 0; i < proof.length; i++) {
            bytes32 proofElement = proof[i];

            if (computedHash <= proofElement) {
                // Hash(current computed hash + current element of the proof)
                computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
            } else {
                // Hash(current element of the proof + current computed hash)
                computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
            }
        }

        // Check if the computed hash (root) is equal to the provided root
        return computedHash == root;
    }
}

/// @title MathBlocks, Primes
/********************************************
 * MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM *
 * MMMMMMMMMMMMNmdddddddddddddddddmNMMMMMMM *
 * MMMMMMMMMmhyssooooooooooooooooosyhNMMMMM *
 * MMMMMMMmyso+/::::::::::::::::::/osyMMMMM *
 * MMMMMMhys+::/+++++++++++++++++/:+syNMMMM *
 * MMMMNyso/:/+/::::+/:::/+:::::::+oshMMMMM *
 * MMMMmys/-//:/++:/+://-++-+oooossydMMMMMM *
 * MMMMNyso+//+s+/:+/:+/:+/:+syddmNMMMMMMMM *
 * MMMMMNdyyyyso/:++:/+:/+/:+syNMMMMMMMMMMM *
 * MMMMMMMMMhso/:/+/:++:/++-+symMMMMMMMMMMM *
 * MMMMMMMMdys+:/++:/++:/++:/+syNMMMMMMMMMM *
 * MMMMMMMNys+:/++/:+s+:/+++:/oydMMMMMMMMMM *
 * MMMMMMMmys+:/+/:/oso/:///:/sydMMMMMMMMMM *
 * MMMMMMMMhso+///+osyso+///osyhMMMMMMMMMMM *
 * MMMMMMMMMmhyssyyhmMdhyssyydNMMMMMMMMMMMM *
 * MMMMMMMMMMMMMNMMMMMMMMMNMMMMMMMMMMMMMMMM *
 *******************************************/
struct CoreData {
    bool isPrime;
    uint16 primeIndex;
    uint8 primeFactorCount;
    uint16[2] parents;
    uint32 lastBred;
}

struct RentalData {
    bool isRentable;
    bool whitelistOnly;
    uint96 studFee;
    uint32 deadline;
    uint16[6] suitors;
}

struct PrimeData {
    uint16[2] sexyPrimes;
    uint16[2] twins;
    uint16[2] cousins;
}

struct NumberData {
    CoreData core;
    PrimeData prime;
}

struct Activity {
    uint8 tranche0;
    uint8 tranche1;
}

enum Attribute {
    TAXICAB_NUMBER,
    PERFECT_NUMBER,
    EULERS_LUCKY_NUMBER,
    UNIQUE_PRIME,
    FRIENDLY_NUMBER,
    COLOSSALLY_ABUNDANT_NUMBER,
    FIBONACCI_NUMBER,
    REPDIGIT_NUMBER,
    WEIRD_NUMBER,
    TRIANGULAR_NUMBER,
    SOPHIE_GERMAIN_PRIME,
    STRONG_PRIME,
    FRUGAL_NUMBER,
    SQUARE_NUMBER,
    EMIRP,
    MAGIC_NUMBER,
    LUCKY_NUMBER,
    GOOD_PRIME,
    HAPPY_NUMBER,
    UNTOUCHABLE_NUMBER,
    SEMIPERFECT_NUMBER,
    HARSHAD_NUMBER,
    EVIL_NUMBER
}

contract TokenAttributes {
    bytes32 public attributesRootHash;
    mapping(uint256 => uint256) internal packedTokenAttrs;

    event RevealedAttributes(uint256 tokenId, uint256 attributes);

    constructor(bytes32 _attributesRootHash) {
        attributesRootHash = _attributesRootHash;
    }

    /***************************************
                    ATTRIBUTES
    ****************************************/

    function revealAttributes(
        uint256 _tokenId,
        uint256 _attributes,
        bytes32[] memory _merkleProof
    ) public {
        bytes32 leaf = keccak256(abi.encodePacked(_tokenId, _attributes));
        require(MerkleProof.verify(_merkleProof, attributesRootHash, leaf), "Invalid merkle proof");
        packedTokenAttrs[_tokenId] = _attributes;
        emit RevealedAttributes(_tokenId, _attributes);
    }

    function getAttributes(uint256 _tokenId) public view returns (bool[23] memory attributes) {
        uint256 packed = packedTokenAttrs[_tokenId];
        for (uint8 i = 0; i < 23; i++) {
            attributes[i] = _getAttr(packed, i);
        }
        return attributes;
    }

    function _getAttr(uint256 _packed, uint256 _attribute) internal pure returns (bool attribute) {
        uint256 flag = (_packed >> _attribute) & uint256(1);
        attribute = flag == 1;
    }
}

library Base64 {
    string internal constant TABLE_ENCODE =
        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

    function encode(bytes memory data) internal pure returns (string memory) {
        if (data.length == 0) return "";

        // load the table into memory
        string memory table = TABLE_ENCODE;

        // multiply by 4/3 rounded up
        uint256 encodedLen = 4 * ((data.length + 2) / 3);

        // add some extra buffer at the end required for the writing
        string memory result = new string(encodedLen + 32);

        assembly {
            // set the actual output length
            mstore(result, encodedLen)

            // prepare the lookup table
            let tablePtr := add(table, 1)

            // input ptr
            let dataPtr := data
            let endPtr := add(dataPtr, mload(data))

            // result ptr, jump over length
            let resultPtr := add(result, 32)

            // run over the input, 3 bytes at a time
            for {

            } lt(dataPtr, endPtr) {

            } {
                // read 3 bytes
                dataPtr := add(dataPtr, 3)
                let input := mload(dataPtr)

                // write 4 characters
                mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F))))
                resultPtr := add(resultPtr, 1)
                mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F))))
                resultPtr := add(resultPtr, 1)
                mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F))))
                resultPtr := add(resultPtr, 1)
                mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))
                resultPtr := add(resultPtr, 1)
            }

            // padding with '='
            switch mod(mload(data), 3)
            case 1 {
                mstore(sub(resultPtr, 2), shl(240, 0x3d3d))
            }
            case 2 {
                mstore(sub(resultPtr, 1), shl(248, 0x3d))
            }
        }

        return result;
    }
}

library PrimesTokenURI {
    string internal constant DESCRIPTION = "Primes is MathBlocks Collection #1.";
    string internal constant STYLE =
        "<style>.p #bg{fill:#ddd} .c #bg{fill:#222} .p .factor,.p #text{fill:#222} .c .factor,.c #text{fill:#ddd} .sexy{fill:#e44C21} .cousin{fill:#348C47} .twin {fill:#3C4CE1} #grid .factor{r: 8} .c #icons *{fill: #ddd} .p #icons * {fill:#222} #icons .stroke *{fill:none} #icons .stroke {fill:none;stroke:#222;stroke-width:8} .c #icons .stroke{stroke:#ddd} .square{stroke-width:2;fill:none;stroke:#222;r:8} .c .square{stroke:#ddd} #icons #i-4 circle{stroke-width:20}</style>";

    function tokenURI(
        uint256 _tokenId,
        NumberData memory _numberData,
        uint16[] memory _factors,
        bool[23] memory _attributeValues
    ) public pure returns (string memory output) {
        string[24] memory parts;

        // 23 attributes revealed with merkle proof
        for (uint8 i = 0; i < 23; i++) {
            parts[i] = _attributeValues[i]
                ? string(abi.encodePacked('{ "value": "', _attributeNames(i), '" }'))
                : "";
        }

        // Last attribute: Unit/Prime/Composite
        parts[23] = string(
            abi.encodePacked(
                '{ "value": "',
                _tokenId == 1 ? "Unit" : _numberData.core.isPrime ? "Prime" : "Composite",
                '" }'
            )
        );

        string memory json = string(
            abi.encodePacked(
                '{ "name": "Primes #',
                _toString(_tokenId),
                '", "description": "',
                DESCRIPTION,
                '", "attributes": [',
                _getAttributes(parts),
                '], "image": "',
                _getImage(_tokenId, _numberData, _factors, _attributeValues),
                '" }'
            )
        );

        output = string(
            abi.encodePacked("data:application/json;base64,", Base64.encode(bytes(json)))
        );
    }

    function _getImage(
        uint256 _tokenId,
        NumberData memory _numberData,
        uint16[] memory _factors,
        bool[23] memory _attributeValues
    ) internal pure returns (string memory output) {
        // 350x350 canvas
        // padding: 14
        // 14x14 grid (bottom row for icons etc)
        // grid square: 23
        // inner square: 16 (circle r=8)
        string memory svg = string(
            abi.encodePacked(
                '<svg xmlns="http://www.w3.org/2000/svg" width="350" height="350">',
                _svgContent(_tokenId, _numberData, _factors, _attributeValues),
                "</svg>"
            )
        );

        output = string(abi.encodePacked("data:image/svg+xml;base64,", Base64.encode(bytes(svg))));
    }

    function _svgContent(
        uint256 _tokenId,
        NumberData memory _numberData,
        uint16[] memory _factors,
        bool[23] memory _attributeValues
    ) internal pure returns (string memory output) {
        output = string(
            abi.encodePacked(
                STYLE,
                '<g class="',
                _numberData.core.isPrime && _tokenId != 1 ? "p" : "c",
                '"><rect id="bg" width="100%" height="100%" />',
                _circles(_tokenId, _numberData, _factors),
                _text(_tokenId),
                _icons(_tokenId, _numberData.core.isPrime, _attributeValues),
                "</g>"
            )
        );
    }

    function _text(uint256 _tokenId) internal pure returns (string memory output) {
        uint256[] memory digits = _getDigits(_tokenId);

        // 16384 has an extra row; move the text to the top right to avoid an overlap
        uint256 dx = _tokenId == 16384 ? 277 : 18;
        uint256 dy = _tokenId == 16384 ? 18 : 318;

        output = string(
            abi.encodePacked(
                '<g id="text" transform="translate(',
                _toString(dx),
                ",",
                _toString(dy),
                ')">',
                _getNumeralPath(digits, 0),
                _getNumeralPath(digits, 1),
                _getNumeralPath(digits, 2),
                _getNumeralPath(digits, 3),
                _getNumeralPath(digits, 4),
                "</g>"
            )
        );
    }

    function _getNumeralPath(uint256[] memory _digits, uint256 _index)
        internal
        pure
        returns (string memory output)
    {
        if (_digits.length <= _index) {
            return output;
        }
        output = string(
            abi.encodePacked(
                '<g transform="translate(',
                _toString(_index * 12),
                ',0)"><path d="',
                _getNumeralPathD(_digits[_index]),
                '" /></g>'
            )
        );
    }

    // Space Mono numerals
    function _getNumeralPathD(uint256 _digit) internal pure returns (string memory) {
        if (_digit == 0) {
            return
                "M0 5.5a6 6 0 0 1 1.3-4C2 .4 3.3 0 4.7 0c1.5 0 2.7.5 3.5 1.4a6 6 0 0 1 1.3 4.1v3c0 1.8-.5 3.2-1.3 4.1-.8 1-2 1.4-3.5 1.4s-2.6-.5-3.5-1.4C.4 11.6 0 10.3 0 8.5v-3Zm4.7 7c1 0 1.8-.3 2.4-1 .5-.8.7-1.8.7-3.1V5.6L7.7 4 7 2.6l-1-.8c-.4-.2-.9-.3-1.4-.3-.5 0-1 0-1.3.3l-1 .8c-.3.4-.5.8-.6 1.3l-.2 1.7v2.8c0 1.3.3 2.3.8 3 .5.8 1.3 1.1 2.3 1.1ZM3.5 7c0-.3.1-.6.4-.9.2-.2.5-.3.8-.3.4 0 .7 0 .9.3.2.3.4.6.4.9 0 .3-.2.6-.4.9-.2.2-.5.3-.9.3-.3 0-.6 0-.8-.3-.3-.3-.4-.6-.4-.9Z";
        } else if (_digit == 1) {
            return "M4 12.2V1h-.2L1.6 6H0L2.5.2h3.2v12h3.8v1.4H.2v-1.5H4Z";
        } else if (_digit == 2) {
            return
                "M9.2 12.2v1.5h-9v-2.3c0-.6 0-1.1.2-1.6.2-.4.5-.8.9-1.1.4-.4.8-.7 1.4-.9l1.8-.5c1.1-.3 2-.7 2.5-1.1.5-.5.7-1 .7-1.8l-.1-1.1-.6-1c-.2-.2-.5-.4-1-.5-.3-.2-.7-.3-1.3-.3a3 3 0 0 0-2.3.9c-.5.6-.8 1.4-.8 2.4v.9H0v-1l.3-1.8c.2-.5.5-1 1-1.5.3-.4.8-.8 1.4-1a5 5 0 0 1 2-.4c.8 0 1.5.1 2 .4.6.2 1.1.5 1.5 1 .4.3.7.7.9 1.2.2.5.2 1 .2 1.5v.4c0 1-.3 1.9-1 2.6-.6.7-1.6 1.2-3 1.6-1.2.2-2.1.6-2.7 1-.6.5-.9 1.1-.9 2v.5h7.5Z";
        } else if (_digit == 3) {
            return
                "M3.3 7V4.8L7.7 2v-.2H.1V.3h9v2.4L4.7 5.5v.3h.8a3.7 3.7 0 0 1 4 3.8v.3a3.8 3.8 0 0 1-1.3 3A4.8 4.8 0 0 1 4.9 14c-.8 0-1.5-.1-2-.3a4.4 4.4 0 0 1-2.5-2.4C0 10.7 0 10.2 0 9.5v-1h1.6v1c0 .4 0 .8.2 1.2l.7 1 1 .6a3.8 3.8 0 0 0 2.5 0 3 3 0 0 0 1-.6c.3-.2.5-.5.6-.9.2-.3.2-.7.2-1v-.2c0-.8-.2-1.4-.7-1.9-.5-.4-1.2-.7-2-.7H3.4Z";
        } else if (_digit == 4) {
            return "M4.7.3h3.1v9.4H10v1.5H8v2.5H6.1v-2.5H0V9L4.7.3ZM1.4 9.5v.2h4.8V1H6L1.4 9.5Z";
        } else if (_digit == 5) {
            return
                "M.2 7.4V.3h8.5v1.5H1.8v4.8H2l.5-.8a3.4 3.4 0 0 1 1.7-1l1.1-.2c.7 0 1.2.1 1.7.3a3.9 3.9 0 0 1 2.3 2.2c.2.6.3 1.1.3 1.8v.3c0 .7-.1 1.3-.3 1.9-.2.5-.5 1-1 1.5-.3.4-.8.8-1.4 1a5 5 0 0 1-2 .4c-.8 0-1.5-.1-2.1-.3-.6-.3-1.1-.6-1.5-1-.5-.4-.8-.9-1-1.4C.1 10.7 0 10 0 9.3V9h1.6v.4c0 1 .3 1.9.9 2.4.6.5 1.4.8 2.3.8.6 0 1 0 1.4-.3l1-.7.6-1.1L8 9V9a3 3 0 0 0-.8-2c-.2-.3-.5-.5-.9-.7a2.6 2.6 0 0 0-1.8 0 2 2 0 0 0-.6.2l-.4.4-.2.5h-3Z";
        } else if (_digit == 6) {
            return
                "M7.5 4.2c0-.8-.3-1.5-.8-2s-1.2-.8-2.1-.8l-1.2.3c-.4.1-.7.3-1 .6a3.2 3.2 0 0 0-.8 2.4v2h.2c.4-.6.8-1 1.4-1.4.5-.3 1.2-.5 1.9-.5.6 0 1.2.1 1.7.4.5.1 1 .4 1.3.8l1 1.4.2 1.9v.2A4.5 4.5 0 0 1 8 12.8c-.4.3-.9.7-1.5.9a5.2 5.2 0 0 1-3.7 0c-.6-.2-1-.5-1.5-1-.4-.3-.7-.8-1-1.3L0 9.6v-5c0-.7.1-1.3.4-1.9.2-.5.5-1 1-1.4.4-.4.9-.8 1.4-1a5.4 5.4 0 0 1 3.6 0 4 4 0 0 1 2.7 3.9H7.5Zm-2.8 8.4c.4 0 .9 0 1.2-.2l1-.7c.3-.2.5-.6.6-1 .2-.3.2-.7.2-1.2v-.2c0-.4 0-.9-.2-1.2a2.7 2.7 0 0 0-1.6-1.6c-.4-.2-.8-.2-1.2-.2a3.1 3.1 0 0 0-2.2.8 3 3 0 0 0-.9 2.1v.4c0 .4 0 .8.2 1.2a2.7 2.7 0 0 0 1.6 1.6l1.3.2Z";
        } else if (_digit == 7) {
            return
                "M0 .3h9v2.3l-5.7 8.6-.6 1a2 2 0 0 0-.2 1v.5H.9V12.4a3.9 3.9 0 0 1 .7-1.3l.5-.8L7.6 2v-.2H0V.3Z";
        } else if (_digit == 8) {
            return
                "M4.5 14a6 6 0 0 1-1.8-.3L1.2 13l-.9-1.2c-.2-.4-.3-1-.3-1.5v-.2A3.3 3.3 0 0 1 .8 8a3.3 3.3 0 0 1 1.7-1v-.3a3 3 0 0 1-.8-.4c-.3-.1-.5-.4-.7-.6a3 3 0 0 1-.6-1.9v-.2A3.2 3.2 0 0 1 1.4 1a5.4 5.4 0 0 1 3.1-1h.1C5.4 0 6 0 6.5.3c.5.1 1 .4 1.3.7A3.1 3.1 0 0 1 9 3.5v.2c0 .4 0 .7-.2 1 0 .4-.2.7-.5.9a3 3 0 0 1-.6.6 3 3 0 0 1-.9.4V7a3.7 3.7 0 0 1 1.8 1 3.3 3.3 0 0 1 .7 2.2v.2A3.3 3.3 0 0 1 8.1 13l-1.4.7a6 6 0 0 1-1.9.3h-.3Zm.3-1.5c.9 0 1.6-.2 2.1-.6.6-.5.8-1 .8-1.8V10c0-.8-.3-1.4-.8-1.8-.6-.5-1.3-.7-2.2-.7-1 0-1.7.2-2.3.7-.5.4-.8 1-.8 1.8v.1c0 .7.3 1.3.8 1.8.6.4 1.3.6 2.2.6h.2ZM4.7 6a3 3 0 0 0 2-.6c.4-.5.7-1 .7-1.6v-.1A2 2 0 0 0 6.6 2a3 3 0 0 0-2-.6 3 3 0 0 0-2 .6A2 2 0 0 0 2 3.7c0 .7.2 1.2.7 1.7a3 3 0 0 0 2 .6Z";
        } else {
            return
                "M1.8 9.8c0 .8.3 1.5.8 2a3 3 0 0 0 2.1.8c.5 0 .9-.1 1.2-.3.4-.1.7-.3 1-.6.3-.3.5-.6.6-1 .2-.4.2-.9.2-1.4v-2h-.2c-.3.6-.7 1-1.3 1.4-.5.3-1.2.5-1.9.5a5 5 0 0 1-1.7-.3A3.8 3.8 0 0 1 .3 6.6C.1 6.1 0 5.5 0 4.8v-.2c0-.7.1-1.3.3-1.9A4.2 4.2 0 0 1 2.8.3 5 5 0 0 1 4.7 0 4.9 4.9 0 0 1 8 1.3c.4.4.8.8 1 1.4.2.5.3 1.1.3 1.8v4.8a5 5 0 0 1-.3 2 4.3 4.3 0 0 1-2.5 2.4 5.5 5.5 0 0 1-3.6 0L1.5 13l-1-1.3-.3-1.8h1.6Zm2.9-8.4c-.5 0-1 .1-1.3.3a2.8 2.8 0 0 0-1.6 1.6l-.2 1.2v.3c0 .4 0 .8.2 1.2l.7 1 1 .5c.3.2.7.2 1.2.2.4 0 .8 0 1.2-.2a3 3 0 0 0 1-.6l.6-1c.2-.3.2-.7.2-1v-.4c0-.5 0-.9-.2-1.2-.1-.4-.3-.7-.6-1-.3-.3-.6-.5-1-.6-.3-.2-.8-.3-1.2-.3Z";
        }
    }

    function _getIconGeometry(uint256 _attribute) internal pure returns (string memory) {
        if (_attribute == 0) {
            // Taxicab Number
            return
                '<rect y="45" width="15" height="15" rx="2"/><rect x="15" y="30" width="15" height="15" rx="2"/><rect x="30" y="15" width="15" height="15" rx="2"/><path d="M45 2c0-1.1.9-2 2-2h11a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H47a2 2 0 0 1-2-2V2Z"/><path d="M45 32c0-1.1.9-2 2-2h11a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H47a2 2 0 0 1-2-2V32Z"/><path d="M30 47c0-1.1.9-2 2-2h11a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H32a2 2 0 0 1-2-2V47Z"/><path d="M0 17c0-1.1.9-2 2-2h11a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V17Z"/><path d="M15 2c0-1.1.9-2 2-2h11a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H17a2 2 0 0 1-2-2V2Z"/>';
        } else if (_attribute == 1) {
            // Perfect Number
            return
                '<g class="stroke"><path d="m12 12 37 37"/><path d="m12 49 37-37"/><path d="M5.4 30H56"/><path d="M30.7 55.3V4.7"/></g>';
        } else if (_attribute == 2) {
            // Euler's Lucky Numbers
            return
                '<path d="M30.8 7.3c-10 0-15.4 5.9-16.4 17.8 0 .6.3.8 1 .8h29c.6 0 1-.2 1-.8C44.8 13.2 40 7.3 30.7 7.3Zm2.3 52c-8.8 0-15.6-2.4-20.2-7.2C8.3 47 6 39.9 6 30c0-10 2.2-17.3 6.6-22A23.8 23.8 0 0 1 30.8 1C45 1 52.5 9.4 53.4 26.2c0 1.7-.5 3.2-1.8 4.4a6.2 6.2 0 0 1-4.5 1.7h-32c-.5 0-.8.3-.8 1C15 46.5 21.5 53 34 53c4 0 8.3-.8 12.6-2.3.8-.3 1.5-.2 2.3.3.7.4 1 1 1 2 0 2.4-1 4-3.3 4.5-4.6 1.1-9 1.7-13.4 1.7Z"/>';
        } else if (_attribute == 3) {
            // Unique Prime
            return '<circle class="stroke" cx="30" cy="30" r="20"/>';
        } else if (_attribute == 4) {
            // Friendly Number
            return
                '<path fill-rule="evenodd" clip-rule="evenodd" d="M30 60a30 30 0 1 0 0-60 30 30 0 0 0 0 60ZM17.5 31c3.6 0 6.5-4.3 6.5-9.5S21 12 17.5 12c-3.6 0-6.5 4.3-6.5 9.5s3 9.5 6.5 9.5ZM49 21.5c0 5.2-3 9.5-6.5 9.5-3.6 0-6.5-4.3-6.5-9.5s3-9.5 6.5-9.5c3.6 0 6.5 4.3 6.5 9.5Zm-2.8 21.9a4 4 0 1 0-6.4-4.8c-5.1 7-15.2 7.3-20.6 0a4 4 0 0 0-6.4 4.8 20.5 20.5 0 0 0 33.4 0Z"/>';
        } else if (_attribute == 5) {
            // Colossally Abundant Number
            return
                '<path d="M34 4a4 4 0 0 0-8 0v22H4a4 4 0 0 0 0 8h22v22a4 4 0 0 0 8 0V34h22a4 4 0 0 0 0-8H34V4Z"/>';
        } else if (_attribute == 6) {
            // Fibonacci Number
            return
                '<path class="stroke" d="M31.3 23a.6.6 0 0 0 0-.4.6.6 0 0 0-.5-.2h-.3a.8.8 0 0 0-.5.3l-.1.4v.3a1 1 0 0 0 .5.7 1.2 1.2 0 0 0 .9.2l.5-.2.4-.5.2-.5a1.7 1.7 0 0 0-.3-1.3 2 2 0 0 0-1.3-.8h-.9l-.8.4c-.3.1-.5.4-.7.7-.2.3-.3.6-.3 1a3 3 0 0 0 .5 2.2 3.3 3.3 0 0 0 2.2 1.4h1.5a4 4 0 0 0 1.4-.7c.5-.3.9-.7 1.2-1.2a5.1 5.1 0 0 0-.2-5.6 5.8 5.8 0 0 0-3.9-2.4c-.8-.2-1.7-.2-2.6 0a7 7 0 0 0-2.5 1.2 8 8 0 0 0-2 2.1c-.5.9-.9 1.9-1 3a8.8 8.8 0 0 0 1.5 6.7 10 10 0 0 0 6.6 4.1c1.4.3 3 .3 4.4 0a13 13 0 0 0 7.8-5.6c1-1.6 1.6-3.4 2-5.2a15.2 15.2 0 0 0-2.7-11.6 17.2 17.2 0 0 0-11.5-7.2c-2.4-.4-5-.4-7.6.2-2.6.6-5.2 1.7-7.5 3.3a22.6 22.6 0 0 0-6 6.4 24.5 24.5 0 0 0-3.3 8.9A26.3 26.3 0 0 0 11 43a29.7 29.7 0 0 0 19.8 12.4A33.5 33.5 0 0 0 54.2 51"/>';
        } else if (_attribute == 7) {
            // Repdigit Number
            return
                '<g class="stroke"><path d="M44 20.8h13.8V7"/><path d="M12 11a25.4 25.4 0 0 1 36 0l9.8 9.8"/><path d="M16 37.2H2.3V51"/><path d="M48 47a25.4 25.4 0 0 1-36 0l-9.8-9.8"/></g>';
        } else if (_attribute == 8) {
            // Weird Number
            return
                '<path d="M28.8 41.6c-1.8 0-3.3-1.5-3-3.3.1-1.3.4-2.4.7-3.3a17 17 0 0 1 3.6-5.4l4.6-4.7c2-2.3 3-4.7 3-7.2s-.7-4.4-2-5.8c-1.3-1.4-3.2-2.1-5.6-2.1-2.4 0-4.3.6-5.8 1.9-.6.6-1.1 1.2-1.5 2-.8 1.6-2.1 3.1-3.9 3.1-1.8 0-3.3-1.5-2.9-3.2.6-2.4 1.8-4.4 3.7-6 2.7-2.3 6.1-3.5 10.4-3.5 4.4 0 7.9 1.2 10.3 3.6 2.5 2.4 3.7 5.6 3.7 9.8 0 4-1.9 8.1-5.6 12.1l-3.9 3.8a10 10 0 0 0-2.3 5c-.3 1.7-1.7 3.2-3.5 3.2Zm-3.5 11.1c0-1 .3-1.9 1-2.6.6-.7 1.5-1.1 2.8-1.1 1.3 0 2.2.4 2.9 1 .6.8 1 1.7 1 2.7 0 1-.4 2-1 2.7-.7.6-1.6 1-2.9 1-1.3 0-2.2-.4-2.9-1-.6-.7-1-1.6-1-2.7Z"/>';
        } else if (_attribute == 9) {
            // Triangular Number
            return
                '<path d="M2 51 28.2 8.6a2 2 0 0 1 3.4 0L58.1 51a2 2 0 0 1-1.7 3.1H3.6A2 2 0 0 1 2 51Z"/>';
        } else if (_attribute == 10) {
            // Sophie Germain Prime
            return
                '<path d="M11.6 32.2c-4.1-1.4-7-3.1-9-5.1C1 25.1 0 22.7 0 19.9c0-3.2 1-5.8 3-7.6 2-1.9 4.8-2.8 8.3-2.8 3.3 0 6.2.4 8.7 1.2.8.3 1.4.7 1.9 1.5.5.7.7 1.5.7 2.3 0 .6-.3 1.1-.8 1.5-.5.3-1 .3-1.7 0a21 21 0 0 0-8.3-1.7c-1.9 0-3.4.5-4.4 1.5-1 1-1.6 2.3-1.6 4a6 6 0 0 0 1.5 4c1 1.1 2.4 2 4.3 2.6 4.7 1.7 8 3.4 9.8 5.4 1.9 2 2.8 4.5 2.8 7.5 0 3.7-1 6.5-3.3 8.4-2.2 1.9-5.5 2.8-9.9 2.8-2.8 0-5.4-.4-7.7-1.3-1.6-.7-2.5-2-2.5-4 0-.7.3-1.1.8-1.4.6-.3 1-.3 1.6 0a15 15 0 0 0 7.3 1.8c5.2 0 7.8-2.1 7.8-6.3 0-1.6-.5-3-1.6-4.1-1-1.1-2.7-2.1-5.1-3Z"/><path d="M47.6 50.5c-5.5 0-10-1.9-13.5-5.6A20.8 20.8 0 0 1 28.8 30c0-6.3 1.8-11.3 5.3-15 3.6-3.7 8.4-5.5 14.6-5.5 2.5 0 4.8.2 7 .5a3.1 3.1 0 0 1 2.5 3.1c0 .7-.3 1.2-.8 1.6a2 2 0 0 1-1.7.3c-2-.5-4-.7-6.5-.7-4.6 0-8.2 1.4-10.7 4C36 21 34.8 25 34.8 30a17 17 0 0 0 3.7 11.5c2.4 2.8 5.6 4.2 9.7 4.2 2 0 4-.3 5.8-.9.2 0 .3-.2.3-.5V31.5c0-.3-.1-.5-.4-.5H45c-.7 0-1.2-.2-1.7-.6-.4-.5-.6-1-.6-1.7s.2-1.2.6-1.7c.5-.4 1-.7 1.7-.7h11.8a3 3 0 0 1 2.2 1 3 3 0 0 1 .9 2.2v15.4c0 1-.3 1.8-.8 2.6s-1.2 1.3-2 1.6c-2.9 1-6 1.4-9.6 1.4Z"/>';
        } else if (_attribute == 11) {
            // Strong Prime
            return
                '<g class="stroke"><path d="M4 28h52"/><path d="M16 40V15"/><path d="M10 34V21"/><path d="M43.6 40V15"/><path d="M50 34.8V20.2"/></g>';
        } else if (_attribute == 12) {
            // Frugal Number
            return
                '<circle cx="8" cy="29" r="8"/><circle cx="30" cy="29" r="8"/><circle cx="52" cy="29" r="8"/>';
        } else if (_attribute == 13) {
            // Square Number
            return '<rect width="60" height="60" rx="2"/>';
        } else if (_attribute == 14) {
            // EMIRP
            return
                '<path d="m14.8 27.7 21.4-16.1a4 4 0 0 0 1.6-3.2V4a2 2 0 0 0-3.2-1.6L2.3 26.8l-.6.4c-.9.6-1.7 1.2-1.7 2.1 0 .7.3 1.4.7 1.7l33.8 28a2 2 0 0 0 3.3-1.5v-5.1a4 4 0 0 0-1.4-3L14.7 30.8a2 2 0 0 1 .1-3.2ZM59.8 5v52.6a2 2 0 0 1-3.3 1.5L22.7 31a2 2 0 0 1 0-3l34-25.7c1.2-1 3.1 1 3.1 2.6Z"/>';
        } else if (_attribute == 15) {
            // Magic Number
            return
                '<path d="M28.1 2.9a2 2 0 0 1 3.8 0l5.5 16.9a2 2 0 0 0 2 1.4H57a2 2 0 0 1 1.2 3.6L44 35.3a2 2 0 0 0-.7 2.2l5.5 17a2 2 0 0 1-3.1 2.2L31.2 46.2a2 2 0 0 0-2.4 0L14.4 56.7a2 2 0 0 1-3-2.2l5.4-17a2 2 0 0 0-.7-2.2L1.7 24.8a2 2 0 0 1 1.2-3.6h17.8a2 2 0 0 0 1.9-1.4l5.5-17Z"/>';
        } else if (_attribute == 16) {
            // Lucky Number
            return
                '<path d="M31.3 23.8a2 2 0 0 1-2.6 0C20.3 16.4 16 12.4 16 7.5 16 3.4 19.3 0 23.5 0a9 9 0 0 1 4.8 1.3c1 .7 2.4.7 3.4 0C33 .5 34.7 0 36.3 0 40.5 0 44 3.2 44 7.3c0 5-4.3 9.1-12.7 16.5Z"/><path d="M23.8 28.7C16.4 20.3 12.4 16 7.3 16c-4 0-7.3 3.5-7.3 7.7 0 1.7.5 3.3 1.3 4.6.7 1 .7 2.4 0 3.4A9 9 0 0 0 0 36.5C0 40.7 3.4 44 7.5 44c4.9 0 9-4.3 16.3-12.7a2 2 0 0 0 0-2.6Z"/><path d="M52.7 44c-5 0-9.1-4.3-16.5-12.7a2 2 0 0 1 0-2.6C43.6 20.3 47.6 16 52.5 16c4 0 7.5 3.3 7.5 7.5a9 9 0 0 1-1.3 4.8c-.7 1-.7 2.4 0 3.4.8 1.3 1.3 3 1.3 4.6 0 4.2-3.2 7.7-7.3 7.7Z"/><path d="M28.7 36.2C20.3 43.6 16 47.6 16 52.7c0 4 3.5 7.3 7.7 7.3 1.7 0 3.3-.5 4.6-1.3 1-.7 2.4-.7 3.4 0a9 9 0 0 0 4.8 1.3c4.2 0 7.5-3.4 7.5-7.5 0-4.9-4.3-9-12.7-16.3a2 2 0 0 0-2.6 0Z"/>';
        } else if (_attribute == 17) {
            // Good Prime
            return
                '<path fill-rule="evenodd" clip-rule="evenodd" d="M56.6 8.3c2 1.4 2.5 4.2 1 6.3l-29.2 42a4.5 4.5 0 0 1-7.3.1L2.4 32.2a4.5 4.5 0 1 1 7.2-5.4l15 19.6 25.7-37c1.4-2 4.2-2.5 6.3-1Z"/>';
        } else if (_attribute == 18) {
            // Happy Number
            return
                '<path fill-rule="evenodd" clip-rule="evenodd" d="M30 60a30 30 0 1 0 0-60 30 30 0 0 0 0 60ZM17.5 23c5 0 6.5 3.7 6.5-1.5S21 12 17.5 12c-3.6 0-6.5 4.3-6.5 9.5s1.5 1.5 6.5 1.5ZM49 21.5c0 5.2-2 1.5-6.5 1.5-5 0-6.5 3.7-6.5-1.5s3-9.5 6.5-9.5c3.6 0 6.5 4.3 6.5 9.5Zm-2.8 21.9c1.3-1.8 1.4-5.6-.8-5.6H13.6a4 4 0 0 0-.8 5.6 20.5 20.5 0 0 0 33.4 0Z"/>';
        } else if (_attribute == 19) {
            // Untouchable Number
            return
                '<path d="M8.8 2.2a4 4 0 0 0-5.6 5.6l21.6 21.7L3.2 51.2a4 4 0 1 0 5.6 5.6l21.7-21.6 21.7 21.6a4 4 0 1 0 5.6-5.6L36.2 29.5 57.8 7.8a4 4 0 1 0-5.6-5.6L30.5 23.8 8.8 2.2Z"/>';
        } else if (_attribute == 20) {
            // Semiperfect Number
            return
                '<path fill-rule="evenodd" clip-rule="evenodd" d="M42.7 1a4 4 0 0 1 4 4v50.6a4 4 0 1 1-8 0V40.2l-11.9 12a4 4 0 1 1-5.6-5.7l12.1-12.2H17a4 4 0 0 1 0-8h15.3L21.2 15a4 4 0 1 1 5.6-5.6l12 11.8V5a4 4 0 0 1 4-4Z"/>';
        } else if (_attribute == 21) {
            // Harshad Number
            return
                '<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0Z"/><path d="M3.2 57.8a4 4 0 0 1 0-5.6l49-49a4 4 0 0 1 5.6 5.6l-49 49a4 4 0 0 1-5.6 0Z"/><path d="M52 60a8 8 0 1 0 0-16 8 8 0 0 0 0 16Z"/>';
        } else if (_attribute == 22) {
            // Evil Number
            return
                '<path d="M28.3 2.6 23 11a2 2 0 0 0 1.7 3.1H26v12h-7a6 6 0 0 1-6-6v-6h.4a2 2 0 0 0 1.8-3L13 7.4V7h-.3l-2.5-4.2a2 2 0 0 0-3.4 0l-5 8.2a2 2 0 0 0 1.8 3H5v6a14 14 0 0 0 14 14h7v22a4 4 0 1 0 8 0V34h8a14 14 0 0 0 14-14v-6h.4a2 2 0 0 0 1.8-3L56 7.4V7h-.3l-2.5-4.2a2 2 0 0 0-3.4 0l-5 8.2a2 2 0 0 0 1.8 3H48v6a6 6 0 0 1-6 6h-8V14h1.3a2 2 0 0 0 1.7-3l-5.3-8.4a2 2 0 0 0-3.4 0Z"/>';
        } else if (_attribute == 23) {
            // Unit
            return
                '<path d="M30-.5c.7 0 1.4.2 2 .5h12a4 4 0 0 1 0 8h-9.5v44H44a4 4 0 0 1 0 8H32a4.5 4.5 0 0 1-4 0H17a4 4 0 0 1 0-8h8.5V8H17a4 4 0 0 1 0-8h11c.6-.3 1.3-.5 2-.5Z"/>';
        } else if (_attribute == 24) {
            // Prime
            return '<circle cx="30" cy="30" r="30"/>';
        } else {
            // Composite
            return '<circle class="stroke" cx="30" cy="30" r="26"/>';
        }
    }

    function _icons(
        uint256 _tokenId,
        bool _isPrime,
        bool[23] memory _attributeValues
    ) internal pure returns (string memory output) {
        string memory icons;
        uint256 count = 0;
        for (uint256 i = 24; i > 0; i--) {
            string memory icon;

            if (i == 24) {
                uint256 specialIdx = _tokenId == 1 ? 23 : _isPrime ? 24 : 25;
                icon = _getIconGeometry(specialIdx);
            } else if (_attributeValues[i - 1]) {
                icon = _getIconGeometry(i - 1);
            } else {
                continue;
            }

            // icon geom width = 60
            // scale = 16/60 = 0.266
            // spacing = (60/16) * 23 = 86.25
            uint256 x = ((count * 1e2) * (8625)) / 1e2;
            icons = string(
                abi.encodePacked(
                    icons,
                    '<g id="i-',
                    _toString(i),
                    '" transform="scale(.266) translate(-',
                    _toDecimalString(x, 2),
                    ',0)">',
                    icon,
                    "</g>"
                )
            );
            count = count + 1;
        }
        output = string(
            abi.encodePacked('<g id="icons" transform="translate(317,317)">', icons, "</g>")
        );
    }

    function _circles(
        uint256 _tokenId,
        NumberData memory _numberData,
        uint16[] memory _factors
    ) internal pure returns (string memory output) {
        uint256 nFactor = _factors.length;
        string memory factorStr;
        string memory twinStr;
        string memory cousinStr;
        string memory sexyStr;
        string memory squareStr;

        {
            bool[14][] memory factorRows = _getBitRows(_factors);
            for (uint256 i = 0; i < nFactor; i++) {
                for (uint256 j = 0; j < 14; j++) {
                    if (factorRows[i][j]) {
                        factorStr = string(abi.encodePacked(factorStr, _circle(j, i, "factor")));
                    }
                }
            }
        }

        {
            uint16[] memory squares = _getSquares(_tokenId);
            bool[14][] memory squareRows = _getBitRows(squares);

            for (uint256 i = 0; i < squareRows.length; i++) {
                for (uint256 j = 0; j < 14; j++) {
                    if (squareRows[i][j]) {
                        squareStr = string(
                            abi.encodePacked(squareStr, _circle(j, nFactor + i, "square"))
                        );
                    }
                }
            }
            squareStr = string(abi.encodePacked('<g opacity=".2">', squareStr, "</g>"));
        }

        {
            bool[14][] memory twinRows = _getBitRows(_numberData.prime.twins);
            bool[14][] memory cousinRows = _getBitRows(_numberData.prime.cousins);
            bool[14][] memory sexyRows = _getBitRows(_numberData.prime.sexyPrimes);

            for (uint256 i = 0; i < 2; i++) {
                for (uint256 j = 0; j < 14; j++) {
                    if (twinRows[i][j]) {
                        twinStr = string(
                            abi.encodePacked(twinStr, _circle(j, nFactor + i, "twin"))
                        );
                    }
                    if (cousinRows[i][j]) {
                        cousinStr = string(
                            abi.encodePacked(cousinStr, _circle(j, nFactor + 2 + i, "cousin"))
                        );
                    }
                    if (sexyRows[i][j]) {
                        sexyStr = string(
                            abi.encodePacked(sexyStr, _circle(j, nFactor + 4 + i, "sexy"))
                        );
                    }
                }
            }
        }

        output = string(
            abi.encodePacked(
                '<g id="grid" transform="translate(26,26)">',
                squareStr,
                twinStr,
                cousinStr,
                sexyStr,
                factorStr,
                "</g>"
            )
        );
    }

    function _getSquares(uint256 _tokenId) internal pure returns (uint16[] memory) {
        uint16[] memory squares = new uint16[](14);
        if (_tokenId > 1) {
            for (uint256 i = 0; i < 14; i++) {
                uint256 square = _tokenId**(i + 2);
                if (square > 16384) {
                    break;
                }
                squares[i] = uint16(square);
            }
        }
        return squares;
    }

    function _circle(
        uint256 _xIndex,
        uint256 _yIndex,
        string memory _class
    ) internal pure returns (string memory output) {
        string memory duration;

        uint256 index = (_yIndex * 14) + _xIndex + 1;
        if (index == 1) {
            duration = "40";
        } else {
            uint256 reciprocal = (1e6 * 1e6) / (1e6 * index);
            duration = _toDecimalString(reciprocal * 40, 6);
        }

        output = string(
            abi.encodePacked(
                '<circle r="8" cx="',
                _toString(23 * _xIndex),
                '" cy="',
                _toString(23 * _yIndex),
                '" class="',
                _class,
                '">',
                '<animate attributeName="opacity" values="1;.3;1" dur="',
                duration,
                's" repeatCount="indefinite"/>',
                "</circle>"
            )
        );
    }

    function _getBits(uint16 _input) internal pure returns (bool[14] memory) {
        bool[14] memory bits;
        for (uint8 i = 0; i < 14; i++) {
            uint16 flag = (_input >> i) & uint16(1);
            bits[i] = flag == 1;
        }
        return bits;
    }

    function _getBitRows(uint16[] memory _inputs) internal pure returns (bool[14][] memory) {
        bool[14][] memory rows = new bool[14][](_inputs.length);
        for (uint8 i = 0; i < _inputs.length; i++) {
            rows[i] = _getBits(_inputs[i]);
        }
        return rows;
    }

    function _getBitRows(uint16[2] memory _inputs) internal pure returns (bool[14][] memory) {
        bool[14][] memory rows = new bool[14][](_inputs.length);
        for (uint8 i = 0; i < _inputs.length; i++) {
            rows[i] = _getBits(_inputs[i]);
        }
        return rows;
    }

    function _getAttributes(string[24] memory _parts) internal pure returns (string memory output) {
        for (uint256 i = 0; i < _parts.length; i++) {
            string memory input = _parts[i];

            if (bytes(input).length == 0) {
                continue;
            }

            output = string(abi.encodePacked(output, bytes(output).length > 0 ? "," : "", input));
        }
        return output;
    }

    function _getDigits(uint256 _value) internal pure returns (uint256[] memory) {
        if (_value == 0) {
            uint256[] memory zero = new uint256[](1);
            return zero;
        }
        uint256 temp = _value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        uint256[] memory result = new uint256[](digits);
        temp = _value;
        while (temp != 0) {
            digits -= 1;
            result[digits] = uint256(temp % 10);
            temp /= 10;
        }
        return result;
    }

    function _toString(uint256 _value) internal pure returns (string memory) {
        uint256[] memory digits = _getDigits(uint256(_value));
        bytes memory buffer = new bytes(digits.length);
        for (uint256 i = 0; i < digits.length; i++) {
            buffer[i] = bytes1(uint8(48 + digits[i]));
        }
        return string(buffer);
    }

    function _toDecimalString(uint256 _value, uint256 _decimals)
        internal
        pure
        returns (string memory)
    {
        if (_decimals == 0 || _value == 0) {
            return _toString(_value);
        }

        uint256[] memory digits = _getDigits(_value);
        uint256 len = digits.length;
        bool undersized = len <= _decimals;

        // Index of the decimal point
        uint256 ptIdx = undersized ? 1 : len - _decimals;

        // Leading zeroes
        uint256 leading = undersized ? 1 + (_decimals - len) : 0;

        // Create buffer for total length
        uint256 bufferLen = len + 1 + leading;
        bytes memory buffer = new bytes(bufferLen);
        uint256 offset = 0;

        // Fill buffer
        for (uint256 i = 0; i < bufferLen; i++) {
            if (i == ptIdx) {
                // Add decimal point
                buffer[i] = bytes1(uint8(46));
                offset++;
            } else if (leading > 0 && i <= leading) {
                // Add leading zero
                buffer[i] = bytes1(uint8(48));
                offset++;
            } else {
                // Add digit with index offset for added bytes
                buffer[i] = bytes1(uint8(48 + digits[i - offset]));
            }
        }

        return string(buffer);
    }

    function _attributeNames(uint256 _i) internal pure returns (string memory) {
        string[23] memory attributeNames = [
            "Taxicab",
            "Perfect",
            "Euler's Lucky Number",
            "Unique Prime",
            "Friendly",
            "Colossally Abundant",
            "Fibonacci",
            "Repdigit",
            "Weird",
            "Triangular",
            "Sophie Germain Prime",
            "Strong Prime",
            "Frugal",
            "Square",
            "Emirp",
            "Magic",
            "Lucky",
            "Good Prime",
            "Happy",
            "Untouchable",
            "Semiperfect",
            "Harshad",
            "Evil"
        ];
        return attributeNames[_i];
    }
}

// SPDX-License-Identifier: GPL-3.0
/// @title MathBlocks, Primes
/********************************************
 * MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM *
 * MMMMMMMMMMMMNmdddddddddddddddddmNMMMMMMM *
 * MMMMMMMMMmhyssooooooooooooooooosyhNMMMMM *
 * MMMMMMMmyso+/::::::::::::::::::/osyMMMMM *
 * MMMMMMhys+::/+++++++++++++++++/:+syNMMMM *
 * MMMMNyso/:/+/::::+/:::/+:::::::+oshMMMMM *
 * MMMMmys/-//:/++:/+://-++-+oooossydMMMMMM *
 * MMMMNyso+//+s+/:+/:+/:+/:+syddmNMMMMMMMM *
 * MMMMMNdyyyyso/:++:/+:/+/:+syNMMMMMMMMMMM *
 * MMMMMMMMMhso/:/+/:++:/++-+symMMMMMMMMMMM *
 * MMMMMMMMdys+:/++:/++:/++:/+syNMMMMMMMMMM *
 * MMMMMMMNys+:/++/:+s+:/+++:/oydMMMMMMMMMM *
 * MMMMMMMmys+:/+/:/oso/:///:/sydMMMMMMMMMM *
 * MMMMMMMMhso+///+osyso+///osyhMMMMMMMMMMM *
 * MMMMMMMMMmhyssyyhmMdhyssyydNMMMMMMMMMMMM *
 * MMMMMMMMMMMMMNMMMMMMMMMNMMMMMMMMMMMMMMMM *
 *******************************************/
contract Primes is ERC721Tradable, ReentrancyGuard, TokenAttributes {
    using Packed16BitArray for Packed16BitArray.PackedArray;

    // Periods
    uint256 internal constant RESCUE_SALE_GRACE_PERIOD = 48 hours;
    uint256 internal constant WHITELIST_ONLY_PERIOD = 24 hours;
    uint256 internal constant BATCH_0_GRACE_PERIOD = 2 hours;
    uint256 internal constant BATCH_1_GRACE_PERIOD = 2 hours;
    uint256 internal constant BATCH_2_GRACE_PERIOD = 12 hours;

    // Prices: 0.05 ETH for FLC, 0.075 for EGS
    uint256 internal constant BATCH_0_PRICE = 5e16;
    uint256 internal constant BATCH_1_PRICE = 75e15;

    Packed16BitArray.PackedArray internal packedPrimes;

    Packed16BitArray.PackedArray internal batch0;
    Packed16BitArray.PackedArray internal batch1;
    Packed16BitArray.PackedArray internal batch2;

    bytes32 public whitelistRootHash;

    mapping(uint256 => CoreData) public data;
    mapping(uint256 => RentalData) public rental;
    mapping(address => Activity) public users;

    address public auctionHouse;

    uint256 public batchStartTime;
    uint256 public nonce;
    address public immutable setupAddr;
    uint256 public immutable BREEDING_COOLDOWN;

    event Initialized();
    event PrimeClaimed(uint256 tokenId);
    event BatchStarted(uint256 batchId);
    event Bred(uint16 tokenId, uint256 parent1, uint256 parent2);
    event Listed(uint16 tokenId);
    event UnListed(uint16 tokenId);

    constructor(
        address _dao,
        uint256 _breedCooldown,
        address _proxyRegistryAddress,
        bytes32 _attributesRootHash,
        bytes32 _whitelistRootHash
    )
        ERC721Tradable("Primes", "PRIME", _proxyRegistryAddress)
        TokenAttributes(_attributesRootHash)
    {
        setupAddr = msg.sender;
        transferOwnership(_dao);
        BREEDING_COOLDOWN = _breedCooldown;
        whitelistRootHash = _whitelistRootHash;
    }

    /***************************************
                    VIEWS
    ****************************************/

    function fetchPrime(uint256 _index) public view returns (uint16 primeNumber) {
        return packedPrimes.getValue(_index);
    }

    function getNumberData(uint256 _tokenId) public view returns (NumberData memory) {
        require(_tokenId <= 2**14, "Number too large");
        CoreData memory core = data[_tokenId];
        return
            NumberData({
                core: core,
                prime: PrimeData({
                    sexyPrimes: sexyPrimes(core.primeIndex),
                    twins: twins(core.primeIndex),
                    cousins: cousins(core.primeIndex)
                })
            });
    }

    function getSuitors(uint256 _tokenId) public view returns (uint16[6] memory) {
        return rental[_tokenId].suitors;
    }

    function getParents(uint256 _tokenId) public view returns (uint16[2] memory) {
        return data[_tokenId].parents;
    }

    /***************************************
                    BREEDING
    ****************************************/

    function breedPrimes(
        uint16 _parent1,
        uint16 _parent2,
        uint256 _attributes,
        bytes32[] memory _merkleProof
    ) external nonReentrant {
        BreedInput memory input1 = _getInput(_parent1);
        BreedInput memory input2 = _getInput(_parent2);
        require(input1.owns && input2.owns, "Breeder must own input token");
        _breed(input1, input2, _attributes, _merkleProof);
    }

    function crossBreed(
        uint16 _parent1,
        uint16 _parent2,
        uint256 _attributes,
        bytes32[] memory _merkleProof
    ) external payable nonReentrant {
        BreedInput memory input1 = _getInput(_parent1);
        BreedInput memory input2 = _getInput(_parent2);
        require(input1.owns, "Must own first input");
        require(input2.rentalData.isRentable, "Must be rentable");
        require(msg.value >= input2.rentalData.studFee, "Must pay stud fee");
        payable(input2.owner).transfer((msg.value * 9) / 10);
        require(block.timestamp < input2.rentalData.deadline, "Rental passed deadline");
        if (input2.rentalData.whitelistOnly) {
            bool isSuitor;
            for (uint256 i = 0; i < 6; i++) {
                isSuitor = isSuitor || input2.rentalData.suitors[i] == _parent1;
            }
            require(isSuitor, "Must be whitelisted suitor");
        }
        _breed(input1, input2, _attributes, _merkleProof);
    }

    function _breed(
        BreedInput memory _input1,
        BreedInput memory _input2,
        uint256 _attributes,
        bytes32[] memory _merkleProof
    ) internal {
        // VALIDATION
        // 1. Check less than max uint16
        uint256 childVal = uint256(_input1.id) * uint256(_input2.id);
        require(childVal <= 2**14, "Number too large");
        uint16 scaledVal = uint16(childVal);

        // 2. Number doesn't exist
        require(!_exists(scaledVal), "Number already taken");

        // 3. Tokens passed cooldown
        require(
            block.timestamp > _input1.tokenData.lastBred + BREEDING_COOLDOWN &&
                block.timestamp > _input2.tokenData.lastBred + BREEDING_COOLDOWN,
            "Cannot breed so quickly"
        );

        // 4. Composites can't self-breed
        require(
            !(_input1.id == _input2.id && !_input1.tokenData.isPrime),
            "Composites cannot self-breed"
        );

        // Breed
        data[_input1.id].lastBred = uint32(block.timestamp);
        data[_input2.id].lastBred = uint32(block.timestamp);
        data[scaledVal] = CoreData({
            isPrime: false,
            primeIndex: 0,
            primeFactorCount: _input1.tokenData.primeFactorCount +
                _input2.tokenData.primeFactorCount,
            parents: [_input1.id, _input2.id],
            lastBred: uint32(block.timestamp)
        });
        _safeMint(msg.sender, scaledVal);
        if (_attributes > 0) {
            revealAttributes(scaledVal, _attributes, _merkleProof);
        }
        _burnAfterBreeding(_input1, _input2);

        emit Bred(scaledVal, _input1.id, _input2.id);
    }

    function _burnAfterBreeding(BreedInput memory _input1, BreedInput memory _input2) internal {
        // Both primes, no burn
        if (_input1.tokenData.isPrime && _input2.tokenData.isPrime) return;
        // One prime,
        if (_input1.tokenData.isPrime) {
            require(_input2.owns, "Breeder must own burning");
            _burn(_input2.id);
        } else if (_input2.tokenData.isPrime) {
            require(_input1.owns, "Breeder must own burning");
            _burn(_input1.id);
        }
        // No primes, both burn
        else {
            require(_input1.owns && _input2.owns, "Breeder must own burning");
            _burn(_input1.id);
            _burn(_input2.id);
        }
    }

    function list(
        uint16 _tokenId,
        uint96 _fee,
        uint32 _deadline,
        uint16[] memory _suitors
    ) external {
        require(msg.sender == ownerOf(_tokenId), "Must own said token");

        uint16[6] memory suitors;
        uint256 len = _suitors.length;
        if (len > 0) {
            require(len < 6, "Max 6 suitors");
            for (uint256 i = 0; i < len; i++) {
                suitors[i] = _suitors[i];
            }
        }

        rental[_tokenId] = RentalData({
            isRentable: true,
            whitelistOnly: len > 0,
            studFee: _fee,
            deadline: _deadline,
            suitors: suitors
        });

        emit Listed(_tokenId);
    }

    function unlist(uint16 _tokenId) external {
        require(msg.sender == ownerOf(_tokenId), "Must own said token");

        uint16[6] memory empty6;
        rental[_tokenId] = RentalData(false, false, 0, 0, empty6);

        emit UnListed(_tokenId);
    }

    struct BreedInput {
        bool owns;
        address owner;
        uint16 id;
        CoreData tokenData;
        RentalData rentalData;
    }

    function _getInput(uint16 _breedInput) internal view returns (BreedInput memory) {
        address owner = ownerOf(_breedInput);
        return
            BreedInput({
                owns: owner == msg.sender,
                owner: owner,
                id: _breedInput,
                tokenData: data[_breedInput],
                rentalData: rental[_breedInput]
            });
    }

    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual override {
        super._beforeTokenTransfer(from, to, tokenId);
        uint16[6] memory empty6;
        rental[tokenId] = RentalData(false, false, 0, 0, empty6);
    }

    /***************************************
                    TOKEN URI
    ****************************************/

    function tokenURI(uint256 _tokenId) public view override returns (string memory output) {
        NumberData memory numberData = getNumberData(_tokenId);
        bool[23] memory attributeValues = getAttributes(_tokenId);
        uint16[] memory factors = getPrimeFactors(uint16(_tokenId), numberData);
        return PrimesTokenURI.tokenURI(_tokenId, numberData, factors, attributeValues);
    }

    function getPrimeFactors(uint16 _tokenId, NumberData memory _numberData)
        public
        view
        returns (uint16[] memory factors)
    {
        factors = _getFactors(_tokenId, _numberData.core);
        factors = _insertion(factors);
    }

    function _getFactors(uint16 _tokenId, CoreData memory _core)
        internal
        view
        returns (uint16[] memory factors)
    {
        if (_core.isPrime) {
            factors = new uint16[](1);
            factors[0] = _tokenId;
        } else {
            uint16[] memory parent1Factors = _getFactors(_core.parents[0], data[_core.parents[0]]);
            uint256 len1 = parent1Factors.length;
            uint16[] memory parent2Factors = _getFactors(_core.parents[1], data[_core.parents[1]]);
            uint256 len2 = parent2Factors.length;
            factors = new uint16[](len1 + len2);
            for (uint256 i = 0; i < len1; i++) {
                factors[i] = parent1Factors[i];
            }
            for (uint256 i = 0; i < len2; i++) {
                factors[len1 + i] = parent2Factors[i];
            }
        }
    }

    function _insertion(uint16[] memory _arr) internal pure returns (uint16[] memory) {
        uint256 length = _arr.length;
        for (uint256 i = 1; i < length; i++) {
            uint16 key = _arr[i];
            uint256 j = i - 1;
            while ((int256(j) >= 0) && (_arr[j] > key)) {
                _arr[j + 1] = _arr[j];
                unchecked {
                    j--;
                }
            }
            unchecked {
                _arr[j + 1] = key;
            }
        }
        return _arr;
    }

    function sexyPrimes(uint256 _primeIndex) public view returns (uint16[2] memory matches) {
        if (_primeIndex > 0) {
            matches = packedPrimes.biDirectionalSearch(_primeIndex, 6);
            if (_primeIndex == 4) {
                // 7: 1 is not prime but is in packedPrimes; exclude it here
                matches[0] = 0;
            }
        }
    }

    function twins(uint256 _primeIndex) public view returns (uint16[2] memory matches) {
        if (_primeIndex > 0) {
            matches = packedPrimes.biDirectionalSearch(_primeIndex, 2);
            if (_primeIndex == 2) {
                // 3: 1 is not prime but is in packedPrimes; exclude it here
                matches[0] = 0;
            }
        }
    }

    function cousins(uint256 _primeIndex) public view returns (uint16[2] memory matches) {
        if (_primeIndex > 0) {
            matches = packedPrimes.biDirectionalSearch(_primeIndex, 4);
            if (_primeIndex == 3) {
                // 5: 1 is not prime but is in packedPrimes; exclude it here
                matches[0] = 0;
            }
        }
    }

    /***************************************
                    MINTING
    ****************************************/

    function mintRandomPrime(
        uint256 _batch0Cap,
        uint256 _batch1Cap,
        bytes32[] memory _merkleProof
    ) external payable {
        mintRandomPrimes(1, _batch0Cap, _batch1Cap, _merkleProof);
    }

    function mintRandomPrimes(
        uint256 _count,
        uint256 _batch0Cap,
        uint256 _batch1Cap,
        bytes32[] memory _merkleProof
    ) public payable nonReentrant {
        (bool active, uint256 batchId, uint256 remaining, ) = batchCheck();
        require(active && batchId < 2, "Batch not active");
        require(remaining >= _count, "Not enough Primes available");
        require(_count <= 20, "Cannot mint >20 Primes at once");

        uint256 unitPrice = batchId == 0 ? BATCH_0_PRICE : BATCH_1_PRICE;
        require(msg.value >= _count * unitPrice, "Requires value");

        _validateUser(batchId, _count, _batch0Cap, _batch1Cap, _merkleProof);
        for (uint256 i = 0; i < _count; i++) {
            _getPrime(batchId);
        }
    }

    function getNextPrime() external nonReentrant returns (uint256 tokenId) {
        require(msg.sender == auctionHouse, "Must be the auctioneer");

        (bool active, uint256 batchId, uint256 remaining, ) = batchCheck();
        require(active && batchId == 2, "Batch not active");
        require(remaining > 0, "No more Primes");

        uint256 idx = batch2.length - 1;
        uint16 primeIndex = batch2.getValue(idx);
        batch2.extractIndex(idx);

        tokenId = _mintLocal(msg.sender, primeIndex);
    }

    // After each batch has begun, the DAO can mint to ensure no bottleneck
    function rescueSale() external onlyOwner nonReentrant {
        (bool active, uint256 batchId, uint256 remaining, ) = batchCheck();
        require(active, "Batch not active");
        require(
            block.timestamp > batchStartTime + RESCUE_SALE_GRACE_PERIOD,
            "Must wait for sale to elapse"
        );
        uint256 rescueCount = remaining < 20 ? remaining : 20;
        for (uint256 i = 0; i < rescueCount; i++) {
            _getPrime(batchId);
        }
    }

    function withdraw() external onlyOwner nonReentrant {
        payable(owner()).transfer(address(this).balance);
    }

    function batchCheck()
        public
        view
        returns (
            bool active,
            uint256 batch,
            uint256 remaining,
            uint256 startTime
        )
    {
        uint256 ts = batchStartTime;
        if (ts == 0) {
            return (false, 0, 0, 0);
        }
        if (batch0.length > 0) {
            startTime = batchStartTime + BATCH_0_GRACE_PERIOD;
            return (block.timestamp > startTime, 0, batch0.length, startTime);
        }
        if (batch1.length > 0) {
            startTime = batchStartTime + BATCH_1_GRACE_PERIOD;
            return (block.timestamp > startTime, 1, batch1.length, startTime);
        }
        startTime = batchStartTime + BATCH_2_GRACE_PERIOD;
        return (block.timestamp > startTime, 2, batch2.length, startTime);
    }

    /***************************************
                MINTING - INTERNAL
    ****************************************/

    function _getPrime(uint256 _batchId) internal {
        uint256 seed = _rand();
        uint16 primeIndex;
        if (_batchId == 0) {
            uint256 idx = seed % batch0.length;
            primeIndex = batch0.getValue(idx);
            batch0.extractIndex(idx);
            _triggerTimestamp(_batchId, batch0.length);
        } else if (_batchId == 1) {
            uint256 idx = seed % batch1.length;
            primeIndex = batch1.getValue(idx);
            batch1.extractIndex(idx);
            _triggerTimestamp(_batchId, batch1.length);
        } else {
            revert("Invalid batchId");
        }

        _mintLocal(msg.sender, primeIndex);
    }

    function _mintLocal(address _beneficiary, uint16 _primeIndex)
        internal
        returns (uint256 tokenId)
    {
        uint16[2] memory empty;
        tokenId = fetchPrime(_primeIndex);
        data[tokenId] = CoreData({
            isPrime: true,
            primeIndex: _primeIndex,
            primeFactorCount: 1,
            parents: empty,
            lastBred: uint32(block.timestamp)
        });
        _safeMint(_beneficiary, tokenId);
        emit PrimeClaimed(tokenId);
    }

    function _validateUser(
        uint256 _batchId,
        uint256 _count,
        uint256 _batch0Cap,
        uint256 _batch1Cap,
        bytes32[] memory _merkleProof
    ) internal {
        if (block.timestamp < batchStartTime + WHITELIST_ONLY_PERIOD) {
            bytes32 leaf = keccak256(abi.encodePacked(msg.sender, _batch0Cap, _batch1Cap));
            require(
                MerkleProof.verify(_merkleProof, whitelistRootHash, leaf),
                "Invalid merkle proof"
            );

            uint8 countAfter = (
                _batchId == 0 ? users[msg.sender].tranche0 : users[msg.sender].tranche1
            ) + uint8(_count);

            if (_batchId == 0) {
                require(countAfter <= _batch0Cap, "Exceeding cap");
                users[msg.sender].tranche0 = countAfter;
            } else {
                require(countAfter <= _batch1Cap, "Exceeding cap");
                users[msg.sender].tranche1 = countAfter;
            }
        }
    }

    function _triggerTimestamp(uint256 _batchId, uint256 _len) internal {
        if (_len == 0) {
            batchStartTime = block.timestamp;
            emit BatchStarted(_batchId + 1);
        }
    }

    function _rand() internal virtual returns (uint256 seed) {
        nonce++;
        seed = uint256(
            keccak256(
                abi.encodePacked(
                    block.timestamp +
                        block.difficulty +
                        ((uint256(keccak256(abi.encodePacked(block.coinbase)))) /
                            (block.timestamp)) +
                        block.gaslimit +
                        ((uint256(keccak256(abi.encodePacked(msg.sender)))) / (block.timestamp)) +
                        block.number,
                    nonce
                )
            )
        );
    }

    /***************************************
                INITIALIZING
    ****************************************/

    modifier onlyInitializer() {
        require(msg.sender == setupAddr, "Only initializer");
        _;
    }

    function initPrimes(uint256[] calldata _data, uint256 _length) external onlyInitializer {
        require(packedPrimes.length == 0, "Already initialized");
        packedPrimes = Packed16BitArray.initStruct(_data, _length);
    }

    function initBatch0(uint256[] calldata _data, uint256 _length) external onlyInitializer {
        require(batch0.length == 0, "Already initialized");
        batch0 = Packed16BitArray.initStruct(_data, _length);
    }

    function initBatch1(uint256[] calldata _data, uint256 _length) external onlyInitializer {
        require(batch1.length == 0, "Already initialized");
        batch1 = Packed16BitArray.initStruct(_data, _length);
    }

    function initBatch2(uint256[] calldata _data, uint256 _length) external onlyInitializer {
        require(batch2.length == 0, "Already initialized");
        batch2 = Packed16BitArray.initStruct(_data, _length);
    }

    function start(address _auctionHouse) external onlyInitializer {
        require(
            packedPrimes.length > 0 && batch0.length > 0 && batch1.length > 0 && batch2.length > 0,
            "Not initialized"
        );
        batchStartTime = block.timestamp;
        auctionHouse = _auctionHouse;

        _mintLocal(owner(), 0);

        emit Initialized();
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_dao","type":"address"},{"internalType":"uint256","name":"_breedCooldown","type":"uint256"},{"internalType":"address","name":"_proxyRegistryAddress","type":"address"},{"internalType":"bytes32","name":"_attributesRootHash","type":"bytes32"},{"internalType":"bytes32","name":"_whitelistRootHash","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"batchId","type":"uint256"}],"name":"BatchStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"tokenId","type":"uint16"},{"indexed":false,"internalType":"uint256","name":"parent1","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"parent2","type":"uint256"}],"name":"Bred","type":"event"},{"anonymous":false,"inputs":[],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"tokenId","type":"uint16"}],"name":"Listed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"userAddress","type":"address"},{"indexed":false,"internalType":"address payable","name":"relayerAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"functionSignature","type":"bytes"}],"name":"MetaTransactionExecuted","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":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"PrimeClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"attributes","type":"uint256"}],"name":"RevealedAttributes","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"tokenId","type":"uint16"}],"name":"UnListed","type":"event"},{"inputs":[],"name":"BREEDING_COOLDOWN","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERC712_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"attributesRootHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"auctionHouse","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"batchCheck","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint256","name":"batch","type":"uint256"},{"internalType":"uint256","name":"remaining","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"batchStartTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_parent1","type":"uint16"},{"internalType":"uint16","name":"_parent2","type":"uint16"},{"internalType":"uint256","name":"_attributes","type":"uint256"},{"internalType":"bytes32[]","name":"_merkleProof","type":"bytes32[]"}],"name":"breedPrimes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_primeIndex","type":"uint256"}],"name":"cousins","outputs":[{"internalType":"uint16[2]","name":"matches","type":"uint16[2]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_parent1","type":"uint16"},{"internalType":"uint16","name":"_parent2","type":"uint16"},{"internalType":"uint256","name":"_attributes","type":"uint256"},{"internalType":"bytes32[]","name":"_merkleProof","type":"bytes32[]"}],"name":"crossBreed","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"data","outputs":[{"internalType":"bool","name":"isPrime","type":"bool"},{"internalType":"uint16","name":"primeIndex","type":"uint16"},{"internalType":"uint8","name":"primeFactorCount","type":"uint8"},{"internalType":"uint32","name":"lastBred","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"bytes","name":"functionSignature","type":"bytes"},{"internalType":"bytes32","name":"sigR","type":"bytes32"},{"internalType":"bytes32","name":"sigS","type":"bytes32"},{"internalType":"uint8","name":"sigV","type":"uint8"}],"name":"executeMetaTransaction","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"fetchPrime","outputs":[{"internalType":"uint16","name":"primeNumber","type":"uint16"}],"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":"uint256","name":"_tokenId","type":"uint256"}],"name":"getAttributes","outputs":[{"internalType":"bool[23]","name":"attributes","type":"bool[23]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDomainSeperator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNextPrime","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getNumberData","outputs":[{"components":[{"components":[{"internalType":"bool","name":"isPrime","type":"bool"},{"internalType":"uint16","name":"primeIndex","type":"uint16"},{"internalType":"uint8","name":"primeFactorCount","type":"uint8"},{"internalType":"uint16[2]","name":"parents","type":"uint16[2]"},{"internalType":"uint32","name":"lastBred","type":"uint32"}],"internalType":"struct CoreData","name":"core","type":"tuple"},{"components":[{"internalType":"uint16[2]","name":"sexyPrimes","type":"uint16[2]"},{"internalType":"uint16[2]","name":"twins","type":"uint16[2]"},{"internalType":"uint16[2]","name":"cousins","type":"uint16[2]"}],"internalType":"struct PrimeData","name":"prime","type":"tuple"}],"internalType":"struct NumberData","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getParents","outputs":[{"internalType":"uint16[2]","name":"","type":"uint16[2]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_tokenId","type":"uint16"},{"components":[{"components":[{"internalType":"bool","name":"isPrime","type":"bool"},{"internalType":"uint16","name":"primeIndex","type":"uint16"},{"internalType":"uint8","name":"primeFactorCount","type":"uint8"},{"internalType":"uint16[2]","name":"parents","type":"uint16[2]"},{"internalType":"uint32","name":"lastBred","type":"uint32"}],"internalType":"struct CoreData","name":"core","type":"tuple"},{"components":[{"internalType":"uint16[2]","name":"sexyPrimes","type":"uint16[2]"},{"internalType":"uint16[2]","name":"twins","type":"uint16[2]"},{"internalType":"uint16[2]","name":"cousins","type":"uint16[2]"}],"internalType":"struct PrimeData","name":"prime","type":"tuple"}],"internalType":"struct NumberData","name":"_numberData","type":"tuple"}],"name":"getPrimeFactors","outputs":[{"internalType":"uint16[]","name":"factors","type":"uint16[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getSuitors","outputs":[{"internalType":"uint16[6]","name":"","type":"uint16[6]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_data","type":"uint256[]"},{"internalType":"uint256","name":"_length","type":"uint256"}],"name":"initBatch0","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_data","type":"uint256[]"},{"internalType":"uint256","name":"_length","type":"uint256"}],"name":"initBatch1","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_data","type":"uint256[]"},{"internalType":"uint256","name":"_length","type":"uint256"}],"name":"initBatch2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_data","type":"uint256[]"},{"internalType":"uint256","name":"_length","type":"uint256"}],"name":"initPrimes","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"uint16","name":"_tokenId","type":"uint16"},{"internalType":"uint96","name":"_fee","type":"uint96"},{"internalType":"uint32","name":"_deadline","type":"uint32"},{"internalType":"uint16[]","name":"_suitors","type":"uint16[]"}],"name":"list","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_batch0Cap","type":"uint256"},{"internalType":"uint256","name":"_batch1Cap","type":"uint256"},{"internalType":"bytes32[]","name":"_merkleProof","type":"bytes32[]"}],"name":"mintRandomPrime","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_count","type":"uint256"},{"internalType":"uint256","name":"_batch0Cap","type":"uint256"},{"internalType":"uint256","name":"_batch1Cap","type":"uint256"},{"internalType":"bytes32[]","name":"_merkleProof","type":"bytes32[]"}],"name":"mintRandomPrimes","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"proxyRegistryAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"rental","outputs":[{"internalType":"bool","name":"isRentable","type":"bool"},{"internalType":"bool","name":"whitelistOnly","type":"bool"},{"internalType":"uint96","name":"studFee","type":"uint96"},{"internalType":"uint32","name":"deadline","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rescueSale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_attributes","type":"uint256"},{"internalType":"bytes32[]","name":"_merkleProof","type":"bytes32[]"}],"name":"revealAttributes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setupAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_primeIndex","type":"uint256"}],"name":"sexyPrimes","outputs":[{"internalType":"uint16[2]","name":"matches","type":"uint16[2]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_auctionHouse","type":"address"}],"name":"start","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"output","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_primeIndex","type":"uint256"}],"name":"twins","outputs":[{"internalType":"uint16[2]","name":"matches","type":"uint16[2]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_tokenId","type":"uint16"}],"name":"unlist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"users","outputs":[{"internalType":"uint8","name":"tranche0","type":"uint8"},{"internalType":"uint8","name":"tranche1","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"whitelistRootHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60c06040526007805460ff191690556000600b553480156200002057600080fd5b506040516200600c3803806200600c8339810160408190526200004391620004a9565b81604051806040016040528060068152602001655072696d657360d01b815250604051806040016040528060058152602001645052494d4560d81b8152508582826200009e620000986200012160201b60201c565b6200013d565b8151620000b3906001906020850190620003e6565b508051620000c9906002906020840190620003e6565b5050600a80546001600160a01b0319166001600160a01b03841617905550620000f2836200018d565b50506001600c5550600d553360601b6080526200010f85620001f2565b60a0939093525050601755506200053a565b600062000138620002e560201b62002a9e1760201c565b905090565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60075460ff1615620001d75760405162461bcd60e51b815260206004820152600e60248201526d185b1c9958591e481a5b9a5d195960921b60448201526064015b60405180910390fd5b620001e28162000344565b506007805460ff19166001179055565b620001fc62000121565b6001600160a01b0316620002186000546001600160a01b031690565b6001600160a01b031614620002705760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620001ce565b6001600160a01b038116620002d75760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401620001ce565b620002e2816200013d565b50565b6000333014156200033e57600080368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050503601516001600160a01b03169150620003419050565b50335b90565b6040518060800160405280604f815260200162005fbd604f9139805160209182012082519282019290922060408051808201825260018152603160f81b90840152805180840194909452838101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608401523060808401524660a0808501919091528151808503909101815260c090930190528151910120600855565b828054620003f490620004fd565b90600052602060002090601f01602090048101928262000418576000855562000463565b82601f106200043357805160ff191683800117855562000463565b8280016001018555821562000463579182015b828111156200046357825182559160200191906001019062000446565b506200047192915062000475565b5090565b5b8082111562000471576000815560010162000476565b80516001600160a01b0381168114620004a457600080fd5b919050565b600080600080600060a08688031215620004c257600080fd5b620004cd866200048c565b945060208601519350620004e4604087016200048c565b6060870151608090970151959894975095949392505050565b600181811c908216806200051257607f821691505b602082108114156200053457634e487b7160e01b600052602260045260246000fd5b50919050565b60805160601c60a051615a296200059460003960008181610828015281816130a301526130e6015260008181610bcd01528181610e29015281816116d40152818161211e0152818161266a01526127b50152615a296000f3fe6080604052600436106103765760003560e01c80637a0839bb116101d1578063b88d4fde11610102578063e86b8d71116100a0578063f0ba84401161006f578063f0ba844014610af2578063f2fde38b14610b7b578063fae6595a14610b9b578063ff6a29a314610bbb57600080fd5b8063e86b8d7114610a7c578063e985e9c514610a9c578063ec3ea81514610abc578063ed9152c814610ad257600080fd5b8063d1a12d6a116100dc578063d1a12d6a146109f9578063dc84355414610a0f578063dd0b281e14610a3c578063e1452a6f14610a5c57600080fd5b8063b88d4fde14610999578063c87b56dd146109b9578063cd7c0326146109d957600080fd5b8063a046d5101161016f578063a87430ba11610149578063a87430ba146108dd578063a9922b6214610930578063affed0e014610963578063b40e0e931461097957600080fd5b8063a046d5101461087d578063a22cb4651461089d578063a35d521a146108bd57600080fd5b80638592ffd5116101ab5780638592ffd5146107e957806387bfa1d7146108165780638da5cb5b1461084a57806395d89b411461086857600080fd5b80637a0839bb146107865780638197a838146107b3578063824e39fb146107c957600080fd5b80632d0335ab116102ab5780636352211e1161024957806370a082311161022357806370a082311461071e578063715018a61461073e57806373593edd146107535780637636d3e41461076657600080fd5b80636352211e1461064e57806365c138501461066e5780636c728d9e146106fe57600080fd5b806342842e0e1161028557806342842e0e146105b55780634378a6e3146105d55780635225a135146106025780635d818d9e1461061757600080fd5b80632d0335ab146105575780633408e4701461058d5780633ccfd60b146105a057600080fd5b80630c53c51c1161031857806320379ee5116102f257806320379ee5146104d55780632342592f146104ea57806323b872dd1461050a578063242a00871461052a57600080fd5b80630c53c51c146104825780630f7e5970146104955780631fa2c0a3146104c257600080fd5b806307ab1beb1161035457806307ab1beb146103f557806307cfce4114610417578063081812fc1461042a578063095ea7b31461046257600080fd5b806301ffc9a71461037b57806303403abb146103b057806306fdde03146103d3575b600080fd5b34801561038757600080fd5b5061039b610396366004614e06565b610bef565b60405190151581526020015b60405180910390f35b3480156103bc57600080fd5b506103c5610c41565b6040519081526020016103a7565b3480156103df57600080fd5b506103e8610d8c565b6040516103a791906153b2565b34801561040157600080fd5b50610415610410366004614d8c565b610e1e565b005b610415610425366004614fac565b610eed565b34801561043657600080fd5b5061044a6104453660046150e5565b61117f565b6040516001600160a01b0390911681526020016103a7565b34801561046e57600080fd5b5061041561047d366004614d60565b611214565b6103e8610490366004614ced565b61133c565b3480156104a157600080fd5b506103e8604051806040016040528060018152602001603160f81b81525081565b6104156104d036600461514d565b611516565b3480156104e157600080fd5b506008546103c5565b3480156104f657600080fd5b50610415610505366004614d8c565b6116c9565b34801561051657600080fd5b50610415610525366004614c0c565b611785565b34801561053657600080fd5b5061054a6105453660046150e5565b6117bd565b6040516103a79190615330565b34801561056357600080fd5b506103c5610572366004614bb6565b6001600160a01b031660009081526009602052604090205490565b34801561059957600080fd5b50466103c5565b3480156105ac57600080fd5b5061041561182e565b3480156105c157600080fd5b506104156105d0366004614c0c565b6118e1565b3480156105e157600080fd5b506105f56105f03660046150e5565b6118fc565b6040516103a791906152fc565b34801561060e57600080fd5b50610415611965565b34801561062357600080fd5b5061062c611aac565b60408051941515855260208501939093529183015260608201526080016103a7565b34801561065a57600080fd5b5061044a6106693660046150e5565b611b60565b34801561067a57600080fd5b506106c76106893660046150e5565b60196020526000908152604090205460ff808216916101008104909116906201000081046001600160601b031690600160701b900463ffffffff1684565b6040516103a79493929190931515845291151560208401526001600160601b0316604083015263ffffffff16606082015260800190565b34801561070a57600080fd5b5061054a6107193660046150e5565b611bd7565b34801561072a57600080fd5b506103c5610739366004614bb6565b611c16565b34801561074a57600080fd5b50610415611c9d565b6104156107613660046150fe565b611cf2565b34801561077257600080fd5b50610415610781366004615007565b611cff565b34801561079257600080fd5b506107a66107a1366004614ee5565b611f4e565b6040516103a7919061536a565b3480156107bf57600080fd5b506103c5601c5481565b3480156107d557600080fd5b5061054a6107e43660046150e5565b611f70565b3480156107f557600080fd5b506108096108043660046150e5565b611f9f565b6040516103a7919061558c565b34801561082257600080fd5b506103c57f000000000000000000000000000000000000000000000000000000000000000081565b34801561085657600080fd5b506000546001600160a01b031661044a565b34801561087457600080fd5b506103e8612104565b34801561088957600080fd5b50610415610898366004614d8c565b612113565b3480156108a957600080fd5b506104156108b8366004614cb8565b6121cf565b3480156108c957600080fd5b506104156108d8366004614eca565b6122d1565b3480156108e957600080fd5b506109166108f8366004614bb6565b601a6020526000908152604090205460ff8082169161010090041682565b6040805160ff9384168152929091166020830152016103a7565b34801561093c57600080fd5b5061095061094b3660046150e5565b612433565b60405161ffff90911681526020016103a7565b34801561096f57600080fd5b506103c5601d5481565b34801561098557600080fd5b506104156109943660046150fe565b612440565b3480156109a557600080fd5b506104156109b4366004614c4d565b612510565b3480156109c557600080fd5b506103e86109d43660046150e5565b61254f565b3480156109e557600080fd5b50600a5461044a906001600160a01b031681565b348015610a0557600080fd5b506103c560175481565b348015610a1b57600080fd5b50610a2f610a2a3660046150e5565b61260b565b6040516103a7919061533e565b348015610a4857600080fd5b50610415610a57366004614bb6565b61265f565b348015610a6857600080fd5b5061054a610a773660046150e5565b61277b565b348015610a8857600080fd5b50610415610a97366004614d8c565b6127aa565b348015610aa857600080fd5b5061039b610ab7366004614bd3565b612866565b348015610ac857600080fd5b506103c5600d5481565b348015610ade57600080fd5b50601b5461044a906001600160a01b031681565b348015610afe57600080fd5b50610b48610b0d3660046150e5565b6018602052600090815260409020805460029091015460ff8083169261ffff6101008204169263010000009091049091169063ffffffff1684565b60408051941515855261ffff909316602085015260ff9091169183019190915263ffffffff1660608201526080016103a7565b348015610b8757600080fd5b50610415610b96366004614bb6565b612949565b348015610ba757600080fd5b50610415610bb6366004614fac565b612a03565b348015610bc757600080fd5b5061044a7f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b031982166380ac58cd60e01b1480610c2057506001600160e01b03198216635b5e139f60e01b145b80610c3b57506301ffc9a760e01b6001600160e01b03198316145b92915050565b60006002600c541415610c6f5760405162461bcd60e51b8152600401610c6690615555565b60405180910390fd5b6002600c55601b546001600160a01b03163314610cc75760405162461bcd60e51b815260206004820152601660248201527526bab9ba103132903a34329030bab1ba34b7b732b2b960511b6044820152606401610c66565b6000806000610cd4611aac565b50925092509250828015610ce85750816002145b610d045760405162461bcd60e51b8152600401610c6690615478565b60008111610d455760405162461bcd60e51b815260206004820152600e60248201526d4e6f206d6f7265205072696d657360901b6044820152606401610c66565b601654600090610d5790600190615849565b90506000610d66601583612afb565b9050610d73601583612b95565b610d7d3382612bdb565b6001600c559695505050505050565b606060018054610d9b906158a3565b80601f0160208091040260200160405190810160405280929190818152602001828054610dc7906158a3565b8015610e145780601f10610de957610100808354040283529160200191610e14565b820191906000526020600020905b815481529060010190602001808311610df757829003601f168201915b5050505050905090565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e665760405162461bcd60e51b8152600401610c66906153c5565b60125415610e865760405162461bcd60e51b8152600401610c6690615528565b610ec4838380806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250859250612cf8915050565b80518051601191610eda91839160200190614782565b5060208201518160010155905050505050565b6002600c541415610f105760405162461bcd60e51b8152600401610c6690615555565b6002600c556000610f2085612e10565b90506000610f2d85612e10565b8251909150610f755760405162461bcd60e51b8152602060048201526014602482015273135d5cdd081bdddb88199a5c9cdd081a5b9c1d5d60621b6044820152606401610c66565b608081015151610fba5760405162461bcd60e51b815260206004820152601060248201526f4d7573742062652072656e7461626c6560801b6044820152606401610c66565b8060800151604001516001600160601b031634101561100f5760405162461bcd60e51b81526020600482015260116024820152704d7573742070617920737475642066656560781b6044820152606401610c66565b60208101516001600160a01b03166108fc600a61102d346009615807565b61103791906157f3565b6040518115909202916000818181858888f1935050505015801561105f573d6000803e3d6000fd5b5080608001516060015163ffffffff1642106110b65760405162461bcd60e51b815260206004820152601660248201527552656e74616c2070617373656420646561646c696e6560501b6044820152606401610c66565b80608001516020015115611166576000805b600681101561111657818061110257508761ffff1683608001516080015182600681106110f7576110f7615959565b602002015161ffff16145b91508061110e816158de565b9150506110c8565b50806111645760405162461bcd60e51b815260206004820152601a60248201527f4d7573742062652077686974656c697374656420737569746f720000000000006044820152606401610c66565b505b61117282828686612fd2565b50506001600c5550505050565b6000818152600360205260408120546001600160a01b03166111f85760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610c66565b506000908152600560205260409020546001600160a01b031690565b600061121f82611b60565b9050806001600160a01b0316836001600160a01b0316141561128d5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610c66565b806001600160a01b031661129f6133a1565b6001600160a01b031614806112bb57506112bb81610ab76133a1565b61132d5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610c66565b61133783836133b0565b505050565b60408051606081810183526001600160a01b0388166000818152600960209081529085902054845283015291810186905261137a878287878761341e565b6113d05760405162461bcd60e51b815260206004820152602160248201527f5369676e657220616e64207369676e617475726520646f206e6f74206d6174636044820152600d60fb1b6064820152608401610c66565b6001600160a01b03871660009081526009602052604081208054600192906113f99084906157b6565b90915550506040517f5845892132946850460bff5a0083f71031bc5bf9aadcd40f1de79423eac9b10b9061143290899033908a90615293565b60405180910390a1600080306001600160a01b0316888a60405160200161145a929190615261565b60408051601f198184030181529082905261147491615245565b6000604051808303816000865af19150503d80600081146114b1576040519150601f19603f3d011682016040523d82523d6000602084013e6114b6565b606091505b5091509150816115085760405162461bcd60e51b815260206004820152601c60248201527f46756e6374696f6e2063616c6c206e6f74207375636365737366756c000000006044820152606401610c66565b925050505b95945050505050565b6002600c5414156115395760405162461bcd60e51b8152600401610c6690615555565b6002600c556000808061154a611aac565b5092509250925082801561155e5750600282105b61157a5760405162461bcd60e51b8152600401610c6690615478565b868110156115ca5760405162461bcd60e51b815260206004820152601b60248201527f4e6f7420656e6f756768205072696d657320617661696c61626c6500000000006044820152606401610c66565b601487111561161b5760405162461bcd60e51b815260206004820152601e60248201527f43616e6e6f74206d696e74203e3230205072696d6573206174206f6e636500006044820152606401610c66565b600082156116315767010a741a4627800061163a565b66b1a2bc2ec500005b90506116468189615807565b3410156116865760405162461bcd60e51b815260206004820152600e60248201526d52657175697265732076616c756560901b6044820152606401610c66565b611693838989898961350e565b60005b888110156116b9576116a7846136d6565b806116b1816158de565b915050611696565b50506001600c5550505050505050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146117115760405162461bcd60e51b8152600401610c66906153c5565b601654156117315760405162461bcd60e51b8152600401610c6690615528565b61176f838380806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250859250612cf8915050565b80518051601591610eda91839160200190614782565b6117966117906133a1565b826137ae565b6117b25760405162461bcd60e51b8152600401610c66906154d7565b61133783838361387d565b6117c56147cd565b600082815260186020526040808220815180830192839052926001909101916002918390855b82829054906101000a900461ffff1661ffff16815260200190600201906020826001010492830192600103820291508084116117eb575094979650505050505050565b6118366133a1565b6001600160a01b03166118516000546001600160a01b031690565b6001600160a01b0316146118775760405162461bcd60e51b8152600401610c66906154a2565b6002600c54141561189a5760405162461bcd60e51b8152600401610c6690615555565b6002600c55600080546040516001600160a01b03909116914780156108fc02929091818181858888f193505050501580156118d9573d6000803e3d6000fd5b506001600c55565b61133783838360405180602001604052806000815250612510565b6119046147eb565b6000828152600e6020526040812054905b60178160ff16101561195e57600160ff821683901c811614838260ff166017811061194257611942615959565b9115156020909202015280611956816158f9565b915050611915565b5050919050565b61196d6133a1565b6001600160a01b03166119886000546001600160a01b031690565b6001600160a01b0316146119ae5760405162461bcd60e51b8152600401610c66906154a2565b6002600c5414156119d15760405162461bcd60e51b8152600401610c6690615555565b6002600c55600080806119e2611aac565b5092509250925082611a065760405162461bcd60e51b8152600401610c6690615478565b6202a300601c54611a1791906157b6565b4211611a655760405162461bcd60e51b815260206004820152601c60248201527f4d757374207761697420666f722073616c6520746f20656c61707365000000006044820152606401610c66565b600060148210611a76576014611a78565b815b905060005b81811015611aa057611a8e846136d6565b80611a98816158de565b915050611a7d565b50506001600c55505050565b6000806000806000601c5490508060001415611ad657600080600080945094509450945050611b5a565b60125415611b0757611c20601c54611aee91906157b6565b9150814211600060116001015494509450945050611b5a565b60145415611b3857611c20601c54611b1f91906157b6565b9150814211600160136001015494509450945050611b5a565b61a8c0601c54611b4891906157b6565b60165442821096506002955093509150505b90919293565b6000818152600360205260408120546001600160a01b031680610c3b5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610c66565b611bdf6147cd565b8115611c1157611bf2600f836002613a28565b90508160021415611c1157600081815b61ffff90921660209290920201525b919050565b60006001600160a01b038216611c815760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608401610c66565b506001600160a01b031660009081526004602052604090205490565b611ca56133a1565b6001600160a01b0316611cc06000546001600160a01b031690565b6001600160a01b031614611ce65760405162461bcd60e51b8152600401610c66906154a2565b611cf06000613b56565b565b6113376001848484611516565b611d0c8461ffff16611b60565b6001600160a01b0316336001600160a01b031614611d625760405162461bcd60e51b815260206004820152601360248201527226bab9ba1037bbb71039b0b4b2103a37b5b2b760691b6044820152606401610c66565b611d6a61480a565b81518015611e0b5760068110611db25760405162461bcd60e51b815260206004820152600d60248201526c4d6178203620737569746f727360981b6044820152606401610c66565b60005b81811015611e0957838181518110611dcf57611dcf615959565b6020026020010151838260068110611de957611de9615959565b61ffff909216602092909202015280611e01816158de565b915050611db5565b505b6040518060a001604052806001151581526020016000831115158152602001866001600160601b031681526020018563ffffffff16815260200183815250601960008861ffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548160ff02191690831515021790555060408201518160000160026101000a8154816001600160601b0302191690836001600160601b03160217905550606082015181600001600e6101000a81548163ffffffff021916908363ffffffff160217905550608082015181600101906006611f0b929190614828565b505060405161ffff881681527f1e8109f6f067c9591f7a38bcb3b3688cdc1b164ea7c3daba0ac8eeb5fea0919691506020015b60405180910390a1505050505050565b6060611f5e838360000151613ba6565b9050611f6981613e26565b9392505050565b611f786147cd565b8115611c1157611f8b600f836006613a28565b90508160041415611c115760008181611c02565b611fa76148b9565b614000821115611fec5760405162461bcd60e51b815260206004820152601060248201526f4e756d62657220746f6f206c6172676560801b6044820152606401610c66565b6000828152601860209081526040808320815160a081018352815460ff80821615158352610100820461ffff16958301959095526301000000900490931683830152815180830192839052909160608401919060018401906002908288855b82829054906101000a900461ffff1661ffff168152602001906002019060208260010104928301926001038202915080841161204b575050509284525050506002919091015463ffffffff1660209182015260408051808201825283815281516060810190925283830151939450929183019181906120cd9061ffff16611f70565b81526020016120e3856020015161ffff16611bd7565b81526020016120f9856020015161ffff1661277b565b905290529392505050565b606060028054610d9b906158a3565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461215b5760405162461bcd60e51b8152600401610c66906153c5565b6010541561217b5760405162461bcd60e51b8152600401610c6690615528565b6121b9838380806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250859250612cf8915050565b80518051600f91610eda91839160200190614782565b6121d76133a1565b6001600160a01b0316826001600160a01b031614156122385760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610c66565b80600660006122456133a1565b6001600160a01b03908116825260208083019390935260409182016000908120918716808252919093529120805460ff1916921515929092179091556122896133a1565b6001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516122c5911515815260200190565b60405180910390a35050565b6122de8161ffff16611b60565b6001600160a01b0316336001600160a01b0316146123345760405162461bcd60e51b815260206004820152601360248201527226bab9ba1037bbb71039b0b4b2103a37b5b2b760691b6044820152606401610c66565b61233c61480a565b6040805160a08101825260008082526020808301828152838501838152606085018481526080860188815261ffff8a1686526019909452959093208451815492519451965163ffffffff16600160701b0263ffffffff60701b196001600160601b039890981662010000029790971662010000600160901b03199515156101000261ff00199215159290921661ffff199094169390931717939093161793909317815591519091906123f49060018301906006614828565b505060405161ffff841681527f396f7dc4f260ae4695269b875731b4d5f1ad68f054148f2f494970c5b9b8b4da91506020015b60405180910390a15050565b6000610c3b600f83612afb565b604080516020810185905290810183905260009060600160405160208183030381529060405280519060200120905061247c82600d5483613f39565b6124bf5760405162461bcd60e51b815260206004820152601460248201527324b73b30b634b21036b2b935b63290383937b7b360611b6044820152606401610c66565b6000848152600e602090815260409182902085905581518681529081018590527f8d713df5173641079700714d0f246546c554a22ba03e8c018c8c558563b93232910160405180910390a150505050565b61252161251b6133a1565b836137ae565b61253d5760405162461bcd60e51b8152600401610c66906154d7565b61254984848484613fe8565b50505050565b6060600061255c83611f9f565b90506000612569846118fc565b905060006125778584611f4e565b60405163255c8cc760e01b81529091507340614f51a985302d7060966a072b7e846a21e4e69063255c8cc7906125b790889087908690889060040161561c565b60006040518083038186803b1580156125cf57600080fd5b505af41580156125e3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261150d9190810190614e5d565b61261361480a565b600082815260196020908152604091829020825160c08101938490526001909101805461ffff1682529092909160069190839060029086018084116117eb575094979650505050505050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146126a75760405162461bcd60e51b8152600401610c66906153c5565b601054158015906126b9575060125415155b80156126c6575060145415155b80156126d3575060165415155b6127115760405162461bcd60e51b815260206004820152600f60248201526e139bdd081a5b9a5d1a585b1a5e9959608a1b6044820152606401610c66565b42601c55601b80546001600160a01b0383166001600160a01b031990911617905561274e6127476000546001600160a01b031690565b6000612bdb565b506040517f5daa87a0e9463431830481fd4b6e3403442dfb9a12b9c07597e9f61d50b633c890600090a150565b6127836147cd565b8115611c1157612796600f836004613a28565b90508160031415611c115760008181611c02565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146127f25760405162461bcd60e51b8152600401610c66906153c5565b601454156128125760405162461bcd60e51b8152600401610c6690615528565b612850838380806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250859250612cf8915050565b80518051601391610eda91839160200190614782565b600a546000906001600160a01b03168015801590612908575060405163c455279160e01b81526001600160a01b038581166004830152808516919083169063c45527919060240160206040518083038186803b1580156128c557600080fd5b505afa1580156128d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128fd9190614e40565b6001600160a01b0316145b15612917576001915050610c3b565b6001600160a01b0380851660009081526006602090815260408083209387168352929052205460ff165b949350505050565b6129516133a1565b6001600160a01b031661296c6000546001600160a01b031690565b6001600160a01b0316146129925760405162461bcd60e51b8152600401610c66906154a2565b6001600160a01b0381166129f75760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610c66565b612a0081613b56565b50565b6002600c541415612a265760405162461bcd60e51b8152600401610c6690615555565b6002600c556000612a3685612e10565b90506000612a4385612e10565b82519091508015612a52575080515b6111665760405162461bcd60e51b815260206004820152601c60248201527f42726565646572206d757374206f776e20696e70757420746f6b656e000000006044820152606401610c66565b600033301415612af557600080368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050503601516001600160a01b03169150612af89050565b50335b90565b600082600101548210612b405760405162461bcd60e51b815260206004820152600d60248201526c092dcecc2d8d2c840d2dcc8caf609b1b6044820152606401610c66565b6000612b4d6010846157f3565b90506000612b5c601085615919565b9050612b69816010615807565b856000018381548110612b7e57612b7e615959565b9060005260206000200154901c9250505092915050565b6000612bb260018460010154612bab9190615849565b8490612afb565b9050612bbf83838361401b565b600183018054906000612bd18361588c565b9190505550505050565b6000612be56147cd565b612bf28361ffff16612433565b6040805160a081018252600180825261ffff8781166020808501918252848601848152606086018981524263ffffffff1660808801529784166000818152601890935296909120855181549351925162ffffff1990941690151562ffff0019161761010092909416919091029290921763ff0000001916630100000060ff909216919091021781559351929550909291612c90918301906002614828565b50608091909101516002909101805463ffffffff191663ffffffff909216919091179055612cbe84836140b7565b6040518281527f6c685112450c2165ecbd4d3be7e8fb204a0d220e3fa51953f6fcedf5037ed3059060200160405180910390a15092915050565b60408051808201909152606081526000602082015282516000612d1c6010856157f3565b9050612d298160016157b6565b8214612d6c5760405162461bcd60e51b8152602060048201526012602482015271092dcecc2d8d2c840c2e4e440d8cadccee8d60731b6044820152606401610c66565b6000612d79601086615919565b90506000612d88826010615807565b878481518110612d9a57612d9a615959565b6020026020010151901c905080600014612df65760405162461bcd60e51b815260206004820152601760248201527f496e76616c69642075696e74323536207061636b696e670000000000000000006044820152606401610c66565b505060408051808201909152948552505050602082015290565b612e186148de565b6000612e278361ffff16611b60565b6040805160a080820183526001600160a01b038416338114835260208084019190915261ffff80891684860181905260009081526018835285902085519384018652805460ff808216151586526101008204909316938501939093526301000000909204168285015283518085019094529394509092606080850193908301906001830160028282826020028201916000905b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411612eba575050509284525050506002919091015463ffffffff90811660209283015291835261ffff87166000908152601982526040808220815160a081018352815460ff808216151583526101008204161515828701526201000081046001600160601b031682850152600160701b90049095166060860152815160c08101928390529590930194608085019290916001850191600691908390855b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411612f8857505050929093525050509152509392505050565b6000836040015161ffff16856040015161ffff16612ff09190615807565b90506140008111156130375760405162461bcd60e51b815260206004820152601060248201526f4e756d62657220746f6f206c6172676560801b6044820152606401610c66565b8061305d61ffff82166000908152600360205260409020546001600160a01b0316151590565b156130a15760405162461bcd60e51b8152602060048201526014602482015273273ab6b132b91030b63932b0b23c903a30b5b2b760611b6044820152606401610c66565b7f000000000000000000000000000000000000000000000000000000000000000086606001516080015163ffffffff166130db91906157b6565b4211801561312157507f000000000000000000000000000000000000000000000000000000000000000085606001516080015163ffffffff1661311e91906157b6565b42115b61316d5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f7420627265656420736f20717569636b6c790000000000000000006044820152606401610c66565b846040015161ffff16866040015161ffff1614801561318f5750606086015151155b156131dc5760405162461bcd60e51b815260206004820152601c60248201527f436f6d706f73697465732063616e6e6f742073656c662d6272656564000000006044820152606401610c66565b60408087015161ffff9081166000908152601860209081528382206002908101805463ffffffff421663ffffffff1991821681179092558b8701519095168452858420909101805490941617909255825160a0810184528181529182015260608088015183015190890151830151919283019161325991906157ce565b60ff90811682526040805180820182528a82015161ffff90811682528a8301518116602080840191909152808601929092524263ffffffff169483019490945285841660009081526018825282902085518154928701519387015162ffffff1990931690151562ffff0019161761010093909516929092029390931763ff00000019166301000000939092169290920217815560608201516133019060018301906002614828565b50608091909101516002909101805463ffffffff191663ffffffff9092169190911790556133333361ffff83166140b7565b8315613348576133488161ffff168585612440565b61335286866140d5565b60408087015186820151825161ffff808616825292831660208201529116918101919091527f30be847db9d81ac3b6da70a088210302e2688f8a3be64693715f10f36526941e90606001611f3e565b60006133ab612a9e565b905090565b600081815260056020526040902080546001600160a01b0319166001600160a01b03841690811790915581906133e582611b60565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60006001600160a01b0386166134845760405162461bcd60e51b815260206004820152602560248201527f4e61746976654d6574615472616e73616374696f6e3a20494e56414c49445f5360448201526424a3a722a960d91b6064820152608401610c66565b60016134976134928761419f565b61421c565b6040805160008152602081018083529290925260ff851690820152606081018690526080810185905260a0016020604051602081039080840390855afa1580156134e5573d6000803e3d6000fd5b505050602060405103516001600160a01b0316866001600160a01b031614905095945050505050565b62015180601c5461351f91906157b6565b4210156136cf576040516001600160601b03193360601b16602082015260348101849052605481018390526000906074016040516020818303038152906040528051906020012090506135758260175483613f39565b6135b85760405162461bcd60e51b815260206004820152601460248201527324b73b30b634b21036b2b935b63290383937b7b360611b6044820152606401610c66565b60008587156135de57336000908152601a6020526040902054610100900460ff166135f2565b336000908152601a602052604090205460ff165b6135fc91906157ce565b90508661366757848160ff1611156136465760405162461bcd60e51b815260206004820152600d60248201526c0457863656564696e672063617609c1b6044820152606401610c66565b336000908152601a60205260409020805460ff191660ff83161790556136cc565b838160ff1611156136aa5760405162461bcd60e51b815260206004820152600d60248201526c0457863656564696e672063617609c1b6044820152606401610c66565b336000908152601a60205260409020805461ff00191661010060ff8416021790555b50505b5050505050565b60006136e061424c565b9050600082613728576012546000906136f99084615919565b9050613706601182612afb565b9150613713601182612b95565b61372284601160010154614347565b506137a4565b826001141561376a576014546000906137419084615919565b905061374e601382612afb565b915061375b601382612b95565b61372284601360010154614347565b60405162461bcd60e51b815260206004820152600f60248201526e125b9d985b1a590818985d18da1259608a1b6044820152606401610c66565b6125493382612bdb565b6000818152600360205260408120546001600160a01b03166138275760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610c66565b600061383283611b60565b9050806001600160a01b0316846001600160a01b0316148061386d5750836001600160a01b03166138628461117f565b6001600160a01b0316145b8061294157506129418185612866565b826001600160a01b031661389082611b60565b6001600160a01b0316146138f85760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b6064820152608401610c66565b6001600160a01b03821661395a5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610c66565b61396583838361438a565b6139706000826133b0565b6001600160a01b0383166000908152600460205260408120805460019290613999908490615849565b90915550506001600160a01b03821660009081526004602052604081208054600192906139c79084906157b6565b909155505060008181526003602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b613a306147cd565b6000613a3c8585612afb565b90508261ffff168161ffff1610158015613a565750600084115b15613ad157806000613a69600187615849565b90506000613a778685615826565b90505b8061ffff168361ffff1610613acd57613a938883612afb565b92508061ffff168361ffff161415613ab15761ffff83168552613acd565b81613abb57613acd565b81613ac58161588c565b925050613a7a565b5050505b806000613adf8660016157b6565b90506000613aed8685615790565b90505b8061ffff168361ffff1611613b4b5787600101548210613b0f57613b4b565b613b2582613b1c816158de565b93508990612afb565b92508061ffff168361ffff161415613b465761ffff83166020860152613b4b565b613af0565b505050509392505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b805160609015613bff5760408051600180825281830190925290602080830190803683370190505090508281600081518110613be457613be4615959565b602002602001019061ffff16908161ffff1681525050610c3b565b60608201518051600091613ce091906018908490815b6020908102919091015161ffff9081168352828201939093526040918201600020825160a081018452815460ff808216151583526101008204909616938201939093526301000000909204909316818301528151808301909252919060608301906001830160028282826020028201916000905b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411613c89575050509284525050506002919091015463ffffffff16602090910152613ba6565b8051606085015160208101519293509091600091613d05919060189084906001613c15565b8051909150613d1481846157b6565b6001600160401b03811115613d2b57613d2b61596f565b604051908082528060200260200182016040528015613d54578160200160208202803683370190505b50945060005b83811015613db357848181518110613d7457613d74615959565b6020026020010151868281518110613d8e57613d8e615959565b61ffff9092166020928302919091019091015280613dab816158de565b915050613d5a565b5060005b81811015613e1b57828181518110613dd157613dd1615959565b6020026020010151868286613de691906157b6565b81518110613df657613df6615959565b61ffff9092166020928302919091019091015280613e13816158de565b915050613db7565b505050505092915050565b805160609060015b81811015613f31576000848281518110613e4a57613e4a615959565b602002602001015190506000600183613e639190615849565b90505b60008112158015613e9757508161ffff16868281518110613e8957613e89615959565b602002602001015161ffff16115b15613ef057858181518110613eae57613eae615959565b602002602001015186826001613ec491906157b6565b81518110613ed457613ed4615959565b61ffff9092166020928302919091019091015260001901613e66565b81868260010181518110613f0657613f06615959565b602002602001019061ffff16908161ffff168152505050508080613f29906158de565b915050613e2e565b509192915050565b600081815b8551811015613fdd576000868281518110613f5b57613f5b615959565b60200260200101519050808311613f9d576040805160208101859052908101829052606001604051602081830303815290604052805190602001209250613fca565b60408051602081018390529081018490526060016040516020818303038152906040528051906020012092505b5080613fd5816158de565b915050613f3e565b509092149392505050565b613ff384848461387d565b613fff84848484614446565b6125495760405162461bcd60e51b8152600401610c66906153ef565b60006140286010846157f3565b90506000614037601085615919565b90506000614046826010615807565b61ffff901b19905060008187600001858154811061406657614066615959565b90600052602060002001541690508260106140819190615807565b8561ffff16901b91508181178760000185815481106140a2576140a2615959565b60009182526020909120015550505050505050565b6140d182826040518060200160405280600081525061455a565b5050565b60608201515180156140e957506060810151515b156140f2575050565b6060820151511561412c57805161411b5760405162461bcd60e51b8152600401610c6690615441565b6140d1816040015161ffff1661458d565b606081015151156141665781516141555760405162461bcd60e51b8152600401610c6690615441565b6140d1826040015161ffff1661458d565b81518015614172575080515b61418e5760405162461bcd60e51b8152600401610c6690615441565b61411b826040015161ffff1661458d565b60006040518060800160405280604381526020016159b160439139805160209182012083518483015160408087015180519086012090516141ff950193845260208401929092526001600160a01b03166040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b600061422760085490565b60405161190160f01b60208201526022810191909152604281018390526062016141ff565b601d80546000918261425d836158de565b90915550506040516001600160601b03193360601b166020820152439042906034016040516020818303038152906040528051906020012060001c6142a291906157f3565b6040516001600160601b03194160601b166020820152459042906034016040516020818303038152906040528051906020012060001c6142e291906157f3565b6142ec44426157b6565b6142f691906157b6565b61430091906157b6565b61430a91906157b6565b61431491906157b6565b601d546040805160208101939093528201526060016040516020818303038152906040528051906020012060001c905090565b806140d15742601c557fa3cfaded1a887a6b8bc79d67e12e00966d9805697c70933c8a9eff74e667eb2e61437c8360016157b6565b604051908152602001612427565b61439261480a565b6040805160a0810182526000808252602080830182815283850183815260608501848152608086018881528986526019909452959093208451815492519451965163ffffffff16600160701b0263ffffffff60701b196001600160601b039890981662010000029790971662010000600160901b03199515156101000261ff00199215159290921661ffff199094169390931717939093161793909317815591519091906136cc9060018301906006614828565b60006001600160a01b0384163b1561454f57836001600160a01b031663150b7a0261446f6133a1565b8786866040518563ffffffff1660e01b815260040161449194939291906152bf565b602060405180830381600087803b1580156144ab57600080fd5b505af19250505080156144db575060408051601f3d908101601f191682019092526144d891810190614e23565b60015b614535573d808015614509576040519150601f19603f3d011682016040523d82523d6000602084013e61450e565b606091505b50805161452d5760405162461bcd60e51b8152600401610c66906153ef565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050612941565b506001949350505050565b6145648383614634565b6145716000848484614446565b6113375760405162461bcd60e51b8152600401610c66906153ef565b600061459882611b60565b90506145a68160008461438a565b6145b16000836133b0565b6001600160a01b03811660009081526004602052604081208054600192906145da908490615849565b909155505060008281526003602052604080822080546001600160a01b0319169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6001600160a01b03821661468a5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610c66565b6000818152600360205260409020546001600160a01b0316156146ef5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610c66565b6146fb6000838361438a565b6001600160a01b03821660009081526004602052604081208054600192906147249084906157b6565b909155505060008181526003602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b8280548282559060005260206000209081019282156147bd579160200282015b828111156147bd5782518255916020019190600101906147a2565b506147c9929150614914565b5090565b60405180604001604052806002906020820280368337509192915050565b604051806102e001604052806017906020820280368337509192915050565b6040518060c001604052806006906020820280368337509192915050565b6001830191839082156147bd5791602002820160005b8382111561487e57835183826101000a81548161ffff021916908361ffff160217905550926020019260020160208160010104928301926001030261483e565b80156148ac5782816101000a81549061ffff021916905560020160208160010104928301926001030261487e565b50506147c9929150614914565b60405180604001604052806148cc614929565b81526020016148d961495f565b905290565b6040805160a0810182526000808252602082018190529181019190915260608101614907614929565b81526020016148d961498c565b5b808211156147c95760008155600101614915565b6040805160a08101825260008082526020820181905291810191909152606081016149526147cd565b8152600060209091015290565b60405180606001604052806149726147cd565b815260200161497f6147cd565b81526020016148d96147cd565b6040805160a0810182526000808252602082018190529181018290526060810191909152608081016148d961480a565b600082601f8301126149cd57600080fd5b813560206149e26149dd83615746565b615716565b80838252828201915082860187848660051b8901011115614a0257600080fd5b60005b85811015614a2157813584529284019290840190600101614a05565b5090979650505050505050565b600082601f830112614a3f57600080fd5b604051604081018181106001600160401b0382111715614a6157614a6161596f565b8060405250808385604086011115614a7857600080fd5b60005b6002811015614aa257614a8d82614b7f565b83526020928301929190910190600101614a7b565b509195945050505050565b80358015158114611c1157600080fd5b600082601f830112614ace57600080fd5b8135614adc6149dd82615769565b818152846020838601011115614af157600080fd5b816020850160208301376000918101602001919091529392505050565b600060c08284031215614b2057600080fd5b604051606081018181106001600160401b0382111715614b4257614b4261596f565b604052905080614b528484614a2e565b8152614b618460408501614a2e565b6020820152614b738460808501614a2e565b60408201525092915050565b803561ffff81168114611c1157600080fd5b803563ffffffff81168114611c1157600080fd5b803560ff81168114611c1157600080fd5b600060208284031215614bc857600080fd5b8135611f6981615985565b60008060408385031215614be657600080fd5b8235614bf181615985565b91506020830135614c0181615985565b809150509250929050565b600080600060608486031215614c2157600080fd5b8335614c2c81615985565b92506020840135614c3c81615985565b929592945050506040919091013590565b60008060008060808587031215614c6357600080fd5b8435614c6e81615985565b93506020850135614c7e81615985565b92506040850135915060608501356001600160401b03811115614ca057600080fd5b614cac87828801614abd565b91505092959194509250565b60008060408385031215614ccb57600080fd5b8235614cd681615985565b9150614ce460208401614aad565b90509250929050565b600080600080600060a08688031215614d0557600080fd5b8535614d1081615985565b945060208601356001600160401b03811115614d2b57600080fd5b614d3788828901614abd565b9450506040860135925060608601359150614d5460808701614ba5565b90509295509295909350565b60008060408385031215614d7357600080fd5b8235614d7e81615985565b946020939093013593505050565b600080600060408486031215614da157600080fd5b83356001600160401b0380821115614db857600080fd5b818601915086601f830112614dcc57600080fd5b813581811115614ddb57600080fd5b8760208260051b8501011115614df057600080fd5b6020928301989097509590910135949350505050565b600060208284031215614e1857600080fd5b8135611f698161599a565b600060208284031215614e3557600080fd5b8151611f698161599a565b600060208284031215614e5257600080fd5b8151611f6981615985565b600060208284031215614e6f57600080fd5b81516001600160401b03811115614e8557600080fd5b8201601f81018413614e9657600080fd5b8051614ea46149dd82615769565b818152856020838501011115614eb957600080fd5b61150d826020830160208601615860565b600060208284031215614edc57600080fd5b611f6982614b7f565b6000808284036101a0811215614efa57600080fd5b614f0384614b7f565b9250601f1901610180811215614f1857600080fd5b614f206156cc565b60c0821215614f2e57600080fd5b614f366156f4565b9150614f4460208601614aad565b8252614f5260408601614b7f565b6020830152614f6360608601614ba5565b6040830152614f758660808701614a2e565b6060830152614f8660c08601614b91565b6080830152818152614f9b8660e08701614b0e565b602082015280925050509250929050565b60008060008060808587031215614fc257600080fd5b614fcb85614b7f565b9350614fd960208601614b7f565b92506040850135915060608501356001600160401b03811115614ffb57600080fd5b614cac878288016149bc565b6000806000806080858703121561501d57600080fd5b61502685614b7f565b93506020808601356001600160601b038116811461504357600080fd5b935061505160408701614b91565b925060608601356001600160401b0381111561506c57600080fd5b8601601f8101881361507d57600080fd5b803561508b6149dd82615746565b8082825284820191508484018b868560051b87010111156150ab57600080fd5b600094505b838510156150d5576150c181614b7f565b8352600194909401939185019185016150b0565b50979a9699509497505050505050565b6000602082840312156150f757600080fd5b5035919050565b60008060006060848603121561511357600080fd5b833592506020840135915060408401356001600160401b0381111561513757600080fd5b615143868287016149bc565b9150509250925092565b6000806000806080858703121561516357600080fd5b84359350602085013592506040850135915060608501356001600160401b03811115614ffb57600080fd5b8060005b60178110156125495781511515845260209384019390910190600101615192565b8060005b600281101561254957815161ffff168452602093840193909101906001016151b7565b600081518084526020808501945080840160005b8381101561520e57815161ffff16875295820195908201906001016151ee565b509495945050505050565b60008151808452615231816020860160208601615860565b601f01601f19169290920160200192915050565b60008251615257818460208701615860565b9190910192915050565b60008351615273818460208801615860565b60609390931b6001600160601b0319169190920190815260140192915050565b6001600160a01b0384811682528316602082015260606040820181905260009061150d90830184615219565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906152f290830184615219565b9695505050505050565b6102e08101818360005b60178110156153275781511515835260209283019290910190600101615306565b50505092915050565b60408101610c3b82846151b3565b60c08101818360005b600681101561532757815161ffff16835260209283019290910190600101615347565b6020808252825182820181905260009190848201906040850190845b818110156153a657835161ffff1683529284019291840191600101615386565b50909695505050505050565b602081526000611f696020830184615219565b60208082526010908201526f27b7363c9034b734ba34b0b634bd32b960811b604082015260600190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b60208082526018908201527f42726565646572206d757374206f776e206275726e696e670000000000000000604082015260600190565b60208082526010908201526f4261746368206e6f742061637469766560801b604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b602080825260139082015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b600061018082019050825180511515835261ffff602082015116602084015260ff604082015116604084015260608101516155ca60608501826151b3565b5063ffffffff60808201511660a08401525060208301516155ef60c0840182516151b3565b60208101516156026101008501826151b3565b50604001516156156101408401826151b3565b5092915050565b60006104a0868352855180511515602085015261ffff602082015116604085015260ff6040820151166060850152606081015161565c60808601826151b3565b5063ffffffff60808201511660c085015250602086015161568160e0850182516151b3565b60208101516156946101208601826151b3565b50604001516156a76101608501826151b3565b50806101a08401526156bb818401866151da565b91505061150d6101c083018461518e565b604080519081016001600160401b03811182821017156156ee576156ee61596f565b60405290565b60405160a081016001600160401b03811182821017156156ee576156ee61596f565b604051601f8201601f191681016001600160401b038111828210171561573e5761573e61596f565b604052919050565b60006001600160401b0382111561575f5761575f61596f565b5060051b60200190565b60006001600160401b038211156157825761578261596f565b50601f01601f191660200190565b600061ffff8083168185168083038211156157ad576157ad61592d565b01949350505050565b600082198211156157c9576157c961592d565b500190565b600060ff821660ff84168060ff038211156157eb576157eb61592d565b019392505050565b60008261580257615802615943565b500490565b60008160001904831182151516156158215761582161592d565b500290565b600061ffff838116908316818110156158415761584161592d565b039392505050565b60008282101561585b5761585b61592d565b500390565b60005b8381101561587b578181015183820152602001615863565b838111156125495750506000910152565b60008161589b5761589b61592d565b506000190190565b600181811c908216806158b757607f821691505b602082108114156158d857634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156158f2576158f261592d565b5060010190565b600060ff821660ff8114156159105761591061592d565b60010192915050565b60008261592857615928615943565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114612a0057600080fd5b6001600160e01b031981168114612a0057600080fdfe4d6574615472616e73616374696f6e2875696e74323536206e6f6e63652c616464726573732066726f6d2c62797465732066756e6374696f6e5369676e617475726529a26469706673582212204441b21cbfe6a1dd26971eed92a336b3877f15f6861293a2babc875af44889be64736f6c63430008070033454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c6164647265737320766572696679696e67436f6e74726163742c627974657333322073616c7429000000000000000000000000adca2cccf35cbb27fd757f1c0329df767f8e38f00000000000000000000000000000000000000000000000000000000000015180000000000000000000000000a5409ec958c83c3f309868babaca7c86dcb077c12310fdb07b877408b4a51a7903d83160d08a6e6c479a835f59be40ef1ddc60015ea25fa487381abb3a9e7c19686f6ac798a505266486be93a7065ccad2004f3e

Deployed Bytecode

0x6080604052600436106103765760003560e01c80637a0839bb116101d1578063b88d4fde11610102578063e86b8d71116100a0578063f0ba84401161006f578063f0ba844014610af2578063f2fde38b14610b7b578063fae6595a14610b9b578063ff6a29a314610bbb57600080fd5b8063e86b8d7114610a7c578063e985e9c514610a9c578063ec3ea81514610abc578063ed9152c814610ad257600080fd5b8063d1a12d6a116100dc578063d1a12d6a146109f9578063dc84355414610a0f578063dd0b281e14610a3c578063e1452a6f14610a5c57600080fd5b8063b88d4fde14610999578063c87b56dd146109b9578063cd7c0326146109d957600080fd5b8063a046d5101161016f578063a87430ba11610149578063a87430ba146108dd578063a9922b6214610930578063affed0e014610963578063b40e0e931461097957600080fd5b8063a046d5101461087d578063a22cb4651461089d578063a35d521a146108bd57600080fd5b80638592ffd5116101ab5780638592ffd5146107e957806387bfa1d7146108165780638da5cb5b1461084a57806395d89b411461086857600080fd5b80637a0839bb146107865780638197a838146107b3578063824e39fb146107c957600080fd5b80632d0335ab116102ab5780636352211e1161024957806370a082311161022357806370a082311461071e578063715018a61461073e57806373593edd146107535780637636d3e41461076657600080fd5b80636352211e1461064e57806365c138501461066e5780636c728d9e146106fe57600080fd5b806342842e0e1161028557806342842e0e146105b55780634378a6e3146105d55780635225a135146106025780635d818d9e1461061757600080fd5b80632d0335ab146105575780633408e4701461058d5780633ccfd60b146105a057600080fd5b80630c53c51c1161031857806320379ee5116102f257806320379ee5146104d55780632342592f146104ea57806323b872dd1461050a578063242a00871461052a57600080fd5b80630c53c51c146104825780630f7e5970146104955780631fa2c0a3146104c257600080fd5b806307ab1beb1161035457806307ab1beb146103f557806307cfce4114610417578063081812fc1461042a578063095ea7b31461046257600080fd5b806301ffc9a71461037b57806303403abb146103b057806306fdde03146103d3575b600080fd5b34801561038757600080fd5b5061039b610396366004614e06565b610bef565b60405190151581526020015b60405180910390f35b3480156103bc57600080fd5b506103c5610c41565b6040519081526020016103a7565b3480156103df57600080fd5b506103e8610d8c565b6040516103a791906153b2565b34801561040157600080fd5b50610415610410366004614d8c565b610e1e565b005b610415610425366004614fac565b610eed565b34801561043657600080fd5b5061044a6104453660046150e5565b61117f565b6040516001600160a01b0390911681526020016103a7565b34801561046e57600080fd5b5061041561047d366004614d60565b611214565b6103e8610490366004614ced565b61133c565b3480156104a157600080fd5b506103e8604051806040016040528060018152602001603160f81b81525081565b6104156104d036600461514d565b611516565b3480156104e157600080fd5b506008546103c5565b3480156104f657600080fd5b50610415610505366004614d8c565b6116c9565b34801561051657600080fd5b50610415610525366004614c0c565b611785565b34801561053657600080fd5b5061054a6105453660046150e5565b6117bd565b6040516103a79190615330565b34801561056357600080fd5b506103c5610572366004614bb6565b6001600160a01b031660009081526009602052604090205490565b34801561059957600080fd5b50466103c5565b3480156105ac57600080fd5b5061041561182e565b3480156105c157600080fd5b506104156105d0366004614c0c565b6118e1565b3480156105e157600080fd5b506105f56105f03660046150e5565b6118fc565b6040516103a791906152fc565b34801561060e57600080fd5b50610415611965565b34801561062357600080fd5b5061062c611aac565b60408051941515855260208501939093529183015260608201526080016103a7565b34801561065a57600080fd5b5061044a6106693660046150e5565b611b60565b34801561067a57600080fd5b506106c76106893660046150e5565b60196020526000908152604090205460ff808216916101008104909116906201000081046001600160601b031690600160701b900463ffffffff1684565b6040516103a79493929190931515845291151560208401526001600160601b0316604083015263ffffffff16606082015260800190565b34801561070a57600080fd5b5061054a6107193660046150e5565b611bd7565b34801561072a57600080fd5b506103c5610739366004614bb6565b611c16565b34801561074a57600080fd5b50610415611c9d565b6104156107613660046150fe565b611cf2565b34801561077257600080fd5b50610415610781366004615007565b611cff565b34801561079257600080fd5b506107a66107a1366004614ee5565b611f4e565b6040516103a7919061536a565b3480156107bf57600080fd5b506103c5601c5481565b3480156107d557600080fd5b5061054a6107e43660046150e5565b611f70565b3480156107f557600080fd5b506108096108043660046150e5565b611f9f565b6040516103a7919061558c565b34801561082257600080fd5b506103c57f000000000000000000000000000000000000000000000000000000000001518081565b34801561085657600080fd5b506000546001600160a01b031661044a565b34801561087457600080fd5b506103e8612104565b34801561088957600080fd5b50610415610898366004614d8c565b612113565b3480156108a957600080fd5b506104156108b8366004614cb8565b6121cf565b3480156108c957600080fd5b506104156108d8366004614eca565b6122d1565b3480156108e957600080fd5b506109166108f8366004614bb6565b601a6020526000908152604090205460ff8082169161010090041682565b6040805160ff9384168152929091166020830152016103a7565b34801561093c57600080fd5b5061095061094b3660046150e5565b612433565b60405161ffff90911681526020016103a7565b34801561096f57600080fd5b506103c5601d5481565b34801561098557600080fd5b506104156109943660046150fe565b612440565b3480156109a557600080fd5b506104156109b4366004614c4d565b612510565b3480156109c557600080fd5b506103e86109d43660046150e5565b61254f565b3480156109e557600080fd5b50600a5461044a906001600160a01b031681565b348015610a0557600080fd5b506103c560175481565b348015610a1b57600080fd5b50610a2f610a2a3660046150e5565b61260b565b6040516103a7919061533e565b348015610a4857600080fd5b50610415610a57366004614bb6565b61265f565b348015610a6857600080fd5b5061054a610a773660046150e5565b61277b565b348015610a8857600080fd5b50610415610a97366004614d8c565b6127aa565b348015610aa857600080fd5b5061039b610ab7366004614bd3565b612866565b348015610ac857600080fd5b506103c5600d5481565b348015610ade57600080fd5b50601b5461044a906001600160a01b031681565b348015610afe57600080fd5b50610b48610b0d3660046150e5565b6018602052600090815260409020805460029091015460ff8083169261ffff6101008204169263010000009091049091169063ffffffff1684565b60408051941515855261ffff909316602085015260ff9091169183019190915263ffffffff1660608201526080016103a7565b348015610b8757600080fd5b50610415610b96366004614bb6565b612949565b348015610ba757600080fd5b50610415610bb6366004614fac565b612a03565b348015610bc757600080fd5b5061044a7f000000000000000000000000ff62c2edae704b956a64d445485f6e709142f4e181565b60006001600160e01b031982166380ac58cd60e01b1480610c2057506001600160e01b03198216635b5e139f60e01b145b80610c3b57506301ffc9a760e01b6001600160e01b03198316145b92915050565b60006002600c541415610c6f5760405162461bcd60e51b8152600401610c6690615555565b60405180910390fd5b6002600c55601b546001600160a01b03163314610cc75760405162461bcd60e51b815260206004820152601660248201527526bab9ba103132903a34329030bab1ba34b7b732b2b960511b6044820152606401610c66565b6000806000610cd4611aac565b50925092509250828015610ce85750816002145b610d045760405162461bcd60e51b8152600401610c6690615478565b60008111610d455760405162461bcd60e51b815260206004820152600e60248201526d4e6f206d6f7265205072696d657360901b6044820152606401610c66565b601654600090610d5790600190615849565b90506000610d66601583612afb565b9050610d73601583612b95565b610d7d3382612bdb565b6001600c559695505050505050565b606060018054610d9b906158a3565b80601f0160208091040260200160405190810160405280929190818152602001828054610dc7906158a3565b8015610e145780601f10610de957610100808354040283529160200191610e14565b820191906000526020600020905b815481529060010190602001808311610df757829003601f168201915b5050505050905090565b336001600160a01b037f000000000000000000000000ff62c2edae704b956a64d445485f6e709142f4e11614610e665760405162461bcd60e51b8152600401610c66906153c5565b60125415610e865760405162461bcd60e51b8152600401610c6690615528565b610ec4838380806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250859250612cf8915050565b80518051601191610eda91839160200190614782565b5060208201518160010155905050505050565b6002600c541415610f105760405162461bcd60e51b8152600401610c6690615555565b6002600c556000610f2085612e10565b90506000610f2d85612e10565b8251909150610f755760405162461bcd60e51b8152602060048201526014602482015273135d5cdd081bdddb88199a5c9cdd081a5b9c1d5d60621b6044820152606401610c66565b608081015151610fba5760405162461bcd60e51b815260206004820152601060248201526f4d7573742062652072656e7461626c6560801b6044820152606401610c66565b8060800151604001516001600160601b031634101561100f5760405162461bcd60e51b81526020600482015260116024820152704d7573742070617920737475642066656560781b6044820152606401610c66565b60208101516001600160a01b03166108fc600a61102d346009615807565b61103791906157f3565b6040518115909202916000818181858888f1935050505015801561105f573d6000803e3d6000fd5b5080608001516060015163ffffffff1642106110b65760405162461bcd60e51b815260206004820152601660248201527552656e74616c2070617373656420646561646c696e6560501b6044820152606401610c66565b80608001516020015115611166576000805b600681101561111657818061110257508761ffff1683608001516080015182600681106110f7576110f7615959565b602002015161ffff16145b91508061110e816158de565b9150506110c8565b50806111645760405162461bcd60e51b815260206004820152601a60248201527f4d7573742062652077686974656c697374656420737569746f720000000000006044820152606401610c66565b505b61117282828686612fd2565b50506001600c5550505050565b6000818152600360205260408120546001600160a01b03166111f85760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610c66565b506000908152600560205260409020546001600160a01b031690565b600061121f82611b60565b9050806001600160a01b0316836001600160a01b0316141561128d5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610c66565b806001600160a01b031661129f6133a1565b6001600160a01b031614806112bb57506112bb81610ab76133a1565b61132d5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610c66565b61133783836133b0565b505050565b60408051606081810183526001600160a01b0388166000818152600960209081529085902054845283015291810186905261137a878287878761341e565b6113d05760405162461bcd60e51b815260206004820152602160248201527f5369676e657220616e64207369676e617475726520646f206e6f74206d6174636044820152600d60fb1b6064820152608401610c66565b6001600160a01b03871660009081526009602052604081208054600192906113f99084906157b6565b90915550506040517f5845892132946850460bff5a0083f71031bc5bf9aadcd40f1de79423eac9b10b9061143290899033908a90615293565b60405180910390a1600080306001600160a01b0316888a60405160200161145a929190615261565b60408051601f198184030181529082905261147491615245565b6000604051808303816000865af19150503d80600081146114b1576040519150601f19603f3d011682016040523d82523d6000602084013e6114b6565b606091505b5091509150816115085760405162461bcd60e51b815260206004820152601c60248201527f46756e6374696f6e2063616c6c206e6f74207375636365737366756c000000006044820152606401610c66565b925050505b95945050505050565b6002600c5414156115395760405162461bcd60e51b8152600401610c6690615555565b6002600c556000808061154a611aac565b5092509250925082801561155e5750600282105b61157a5760405162461bcd60e51b8152600401610c6690615478565b868110156115ca5760405162461bcd60e51b815260206004820152601b60248201527f4e6f7420656e6f756768205072696d657320617661696c61626c6500000000006044820152606401610c66565b601487111561161b5760405162461bcd60e51b815260206004820152601e60248201527f43616e6e6f74206d696e74203e3230205072696d6573206174206f6e636500006044820152606401610c66565b600082156116315767010a741a4627800061163a565b66b1a2bc2ec500005b90506116468189615807565b3410156116865760405162461bcd60e51b815260206004820152600e60248201526d52657175697265732076616c756560901b6044820152606401610c66565b611693838989898961350e565b60005b888110156116b9576116a7846136d6565b806116b1816158de565b915050611696565b50506001600c5550505050505050565b336001600160a01b037f000000000000000000000000ff62c2edae704b956a64d445485f6e709142f4e116146117115760405162461bcd60e51b8152600401610c66906153c5565b601654156117315760405162461bcd60e51b8152600401610c6690615528565b61176f838380806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250859250612cf8915050565b80518051601591610eda91839160200190614782565b6117966117906133a1565b826137ae565b6117b25760405162461bcd60e51b8152600401610c66906154d7565b61133783838361387d565b6117c56147cd565b600082815260186020526040808220815180830192839052926001909101916002918390855b82829054906101000a900461ffff1661ffff16815260200190600201906020826001010492830192600103820291508084116117eb575094979650505050505050565b6118366133a1565b6001600160a01b03166118516000546001600160a01b031690565b6001600160a01b0316146118775760405162461bcd60e51b8152600401610c66906154a2565b6002600c54141561189a5760405162461bcd60e51b8152600401610c6690615555565b6002600c55600080546040516001600160a01b03909116914780156108fc02929091818181858888f193505050501580156118d9573d6000803e3d6000fd5b506001600c55565b61133783838360405180602001604052806000815250612510565b6119046147eb565b6000828152600e6020526040812054905b60178160ff16101561195e57600160ff821683901c811614838260ff166017811061194257611942615959565b9115156020909202015280611956816158f9565b915050611915565b5050919050565b61196d6133a1565b6001600160a01b03166119886000546001600160a01b031690565b6001600160a01b0316146119ae5760405162461bcd60e51b8152600401610c66906154a2565b6002600c5414156119d15760405162461bcd60e51b8152600401610c6690615555565b6002600c55600080806119e2611aac565b5092509250925082611a065760405162461bcd60e51b8152600401610c6690615478565b6202a300601c54611a1791906157b6565b4211611a655760405162461bcd60e51b815260206004820152601c60248201527f4d757374207761697420666f722073616c6520746f20656c61707365000000006044820152606401610c66565b600060148210611a76576014611a78565b815b905060005b81811015611aa057611a8e846136d6565b80611a98816158de565b915050611a7d565b50506001600c55505050565b6000806000806000601c5490508060001415611ad657600080600080945094509450945050611b5a565b60125415611b0757611c20601c54611aee91906157b6565b9150814211600060116001015494509450945050611b5a565b60145415611b3857611c20601c54611b1f91906157b6565b9150814211600160136001015494509450945050611b5a565b61a8c0601c54611b4891906157b6565b60165442821096506002955093509150505b90919293565b6000818152600360205260408120546001600160a01b031680610c3b5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610c66565b611bdf6147cd565b8115611c1157611bf2600f836002613a28565b90508160021415611c1157600081815b61ffff90921660209290920201525b919050565b60006001600160a01b038216611c815760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608401610c66565b506001600160a01b031660009081526004602052604090205490565b611ca56133a1565b6001600160a01b0316611cc06000546001600160a01b031690565b6001600160a01b031614611ce65760405162461bcd60e51b8152600401610c66906154a2565b611cf06000613b56565b565b6113376001848484611516565b611d0c8461ffff16611b60565b6001600160a01b0316336001600160a01b031614611d625760405162461bcd60e51b815260206004820152601360248201527226bab9ba1037bbb71039b0b4b2103a37b5b2b760691b6044820152606401610c66565b611d6a61480a565b81518015611e0b5760068110611db25760405162461bcd60e51b815260206004820152600d60248201526c4d6178203620737569746f727360981b6044820152606401610c66565b60005b81811015611e0957838181518110611dcf57611dcf615959565b6020026020010151838260068110611de957611de9615959565b61ffff909216602092909202015280611e01816158de565b915050611db5565b505b6040518060a001604052806001151581526020016000831115158152602001866001600160601b031681526020018563ffffffff16815260200183815250601960008861ffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548160ff02191690831515021790555060408201518160000160026101000a8154816001600160601b0302191690836001600160601b03160217905550606082015181600001600e6101000a81548163ffffffff021916908363ffffffff160217905550608082015181600101906006611f0b929190614828565b505060405161ffff881681527f1e8109f6f067c9591f7a38bcb3b3688cdc1b164ea7c3daba0ac8eeb5fea0919691506020015b60405180910390a1505050505050565b6060611f5e838360000151613ba6565b9050611f6981613e26565b9392505050565b611f786147cd565b8115611c1157611f8b600f836006613a28565b90508160041415611c115760008181611c02565b611fa76148b9565b614000821115611fec5760405162461bcd60e51b815260206004820152601060248201526f4e756d62657220746f6f206c6172676560801b6044820152606401610c66565b6000828152601860209081526040808320815160a081018352815460ff80821615158352610100820461ffff16958301959095526301000000900490931683830152815180830192839052909160608401919060018401906002908288855b82829054906101000a900461ffff1661ffff168152602001906002019060208260010104928301926001038202915080841161204b575050509284525050506002919091015463ffffffff1660209182015260408051808201825283815281516060810190925283830151939450929183019181906120cd9061ffff16611f70565b81526020016120e3856020015161ffff16611bd7565b81526020016120f9856020015161ffff1661277b565b905290529392505050565b606060028054610d9b906158a3565b336001600160a01b037f000000000000000000000000ff62c2edae704b956a64d445485f6e709142f4e1161461215b5760405162461bcd60e51b8152600401610c66906153c5565b6010541561217b5760405162461bcd60e51b8152600401610c6690615528565b6121b9838380806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250859250612cf8915050565b80518051600f91610eda91839160200190614782565b6121d76133a1565b6001600160a01b0316826001600160a01b031614156122385760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610c66565b80600660006122456133a1565b6001600160a01b03908116825260208083019390935260409182016000908120918716808252919093529120805460ff1916921515929092179091556122896133a1565b6001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516122c5911515815260200190565b60405180910390a35050565b6122de8161ffff16611b60565b6001600160a01b0316336001600160a01b0316146123345760405162461bcd60e51b815260206004820152601360248201527226bab9ba1037bbb71039b0b4b2103a37b5b2b760691b6044820152606401610c66565b61233c61480a565b6040805160a08101825260008082526020808301828152838501838152606085018481526080860188815261ffff8a1686526019909452959093208451815492519451965163ffffffff16600160701b0263ffffffff60701b196001600160601b039890981662010000029790971662010000600160901b03199515156101000261ff00199215159290921661ffff199094169390931717939093161793909317815591519091906123f49060018301906006614828565b505060405161ffff841681527f396f7dc4f260ae4695269b875731b4d5f1ad68f054148f2f494970c5b9b8b4da91506020015b60405180910390a15050565b6000610c3b600f83612afb565b604080516020810185905290810183905260009060600160405160208183030381529060405280519060200120905061247c82600d5483613f39565b6124bf5760405162461bcd60e51b815260206004820152601460248201527324b73b30b634b21036b2b935b63290383937b7b360611b6044820152606401610c66565b6000848152600e602090815260409182902085905581518681529081018590527f8d713df5173641079700714d0f246546c554a22ba03e8c018c8c558563b93232910160405180910390a150505050565b61252161251b6133a1565b836137ae565b61253d5760405162461bcd60e51b8152600401610c66906154d7565b61254984848484613fe8565b50505050565b6060600061255c83611f9f565b90506000612569846118fc565b905060006125778584611f4e565b60405163255c8cc760e01b81529091507340614f51a985302d7060966a072b7e846a21e4e69063255c8cc7906125b790889087908690889060040161561c565b60006040518083038186803b1580156125cf57600080fd5b505af41580156125e3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261150d9190810190614e5d565b61261361480a565b600082815260196020908152604091829020825160c08101938490526001909101805461ffff1682529092909160069190839060029086018084116117eb575094979650505050505050565b336001600160a01b037f000000000000000000000000ff62c2edae704b956a64d445485f6e709142f4e116146126a75760405162461bcd60e51b8152600401610c66906153c5565b601054158015906126b9575060125415155b80156126c6575060145415155b80156126d3575060165415155b6127115760405162461bcd60e51b815260206004820152600f60248201526e139bdd081a5b9a5d1a585b1a5e9959608a1b6044820152606401610c66565b42601c55601b80546001600160a01b0383166001600160a01b031990911617905561274e6127476000546001600160a01b031690565b6000612bdb565b506040517f5daa87a0e9463431830481fd4b6e3403442dfb9a12b9c07597e9f61d50b633c890600090a150565b6127836147cd565b8115611c1157612796600f836004613a28565b90508160031415611c115760008181611c02565b336001600160a01b037f000000000000000000000000ff62c2edae704b956a64d445485f6e709142f4e116146127f25760405162461bcd60e51b8152600401610c66906153c5565b601454156128125760405162461bcd60e51b8152600401610c6690615528565b612850838380806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250859250612cf8915050565b80518051601391610eda91839160200190614782565b600a546000906001600160a01b03168015801590612908575060405163c455279160e01b81526001600160a01b038581166004830152808516919083169063c45527919060240160206040518083038186803b1580156128c557600080fd5b505afa1580156128d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128fd9190614e40565b6001600160a01b0316145b15612917576001915050610c3b565b6001600160a01b0380851660009081526006602090815260408083209387168352929052205460ff165b949350505050565b6129516133a1565b6001600160a01b031661296c6000546001600160a01b031690565b6001600160a01b0316146129925760405162461bcd60e51b8152600401610c66906154a2565b6001600160a01b0381166129f75760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610c66565b612a0081613b56565b50565b6002600c541415612a265760405162461bcd60e51b8152600401610c6690615555565b6002600c556000612a3685612e10565b90506000612a4385612e10565b82519091508015612a52575080515b6111665760405162461bcd60e51b815260206004820152601c60248201527f42726565646572206d757374206f776e20696e70757420746f6b656e000000006044820152606401610c66565b600033301415612af557600080368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050503601516001600160a01b03169150612af89050565b50335b90565b600082600101548210612b405760405162461bcd60e51b815260206004820152600d60248201526c092dcecc2d8d2c840d2dcc8caf609b1b6044820152606401610c66565b6000612b4d6010846157f3565b90506000612b5c601085615919565b9050612b69816010615807565b856000018381548110612b7e57612b7e615959565b9060005260206000200154901c9250505092915050565b6000612bb260018460010154612bab9190615849565b8490612afb565b9050612bbf83838361401b565b600183018054906000612bd18361588c565b9190505550505050565b6000612be56147cd565b612bf28361ffff16612433565b6040805160a081018252600180825261ffff8781166020808501918252848601848152606086018981524263ffffffff1660808801529784166000818152601890935296909120855181549351925162ffffff1990941690151562ffff0019161761010092909416919091029290921763ff0000001916630100000060ff909216919091021781559351929550909291612c90918301906002614828565b50608091909101516002909101805463ffffffff191663ffffffff909216919091179055612cbe84836140b7565b6040518281527f6c685112450c2165ecbd4d3be7e8fb204a0d220e3fa51953f6fcedf5037ed3059060200160405180910390a15092915050565b60408051808201909152606081526000602082015282516000612d1c6010856157f3565b9050612d298160016157b6565b8214612d6c5760405162461bcd60e51b8152602060048201526012602482015271092dcecc2d8d2c840c2e4e440d8cadccee8d60731b6044820152606401610c66565b6000612d79601086615919565b90506000612d88826010615807565b878481518110612d9a57612d9a615959565b6020026020010151901c905080600014612df65760405162461bcd60e51b815260206004820152601760248201527f496e76616c69642075696e74323536207061636b696e670000000000000000006044820152606401610c66565b505060408051808201909152948552505050602082015290565b612e186148de565b6000612e278361ffff16611b60565b6040805160a080820183526001600160a01b038416338114835260208084019190915261ffff80891684860181905260009081526018835285902085519384018652805460ff808216151586526101008204909316938501939093526301000000909204168285015283518085019094529394509092606080850193908301906001830160028282826020028201916000905b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411612eba575050509284525050506002919091015463ffffffff90811660209283015291835261ffff87166000908152601982526040808220815160a081018352815460ff808216151583526101008204161515828701526201000081046001600160601b031682850152600160701b90049095166060860152815160c08101928390529590930194608085019290916001850191600691908390855b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411612f8857505050929093525050509152509392505050565b6000836040015161ffff16856040015161ffff16612ff09190615807565b90506140008111156130375760405162461bcd60e51b815260206004820152601060248201526f4e756d62657220746f6f206c6172676560801b6044820152606401610c66565b8061305d61ffff82166000908152600360205260409020546001600160a01b0316151590565b156130a15760405162461bcd60e51b8152602060048201526014602482015273273ab6b132b91030b63932b0b23c903a30b5b2b760611b6044820152606401610c66565b7f000000000000000000000000000000000000000000000000000000000001518086606001516080015163ffffffff166130db91906157b6565b4211801561312157507f000000000000000000000000000000000000000000000000000000000001518085606001516080015163ffffffff1661311e91906157b6565b42115b61316d5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f7420627265656420736f20717569636b6c790000000000000000006044820152606401610c66565b846040015161ffff16866040015161ffff1614801561318f5750606086015151155b156131dc5760405162461bcd60e51b815260206004820152601c60248201527f436f6d706f73697465732063616e6e6f742073656c662d6272656564000000006044820152606401610c66565b60408087015161ffff9081166000908152601860209081528382206002908101805463ffffffff421663ffffffff1991821681179092558b8701519095168452858420909101805490941617909255825160a0810184528181529182015260608088015183015190890151830151919283019161325991906157ce565b60ff90811682526040805180820182528a82015161ffff90811682528a8301518116602080840191909152808601929092524263ffffffff169483019490945285841660009081526018825282902085518154928701519387015162ffffff1990931690151562ffff0019161761010093909516929092029390931763ff00000019166301000000939092169290920217815560608201516133019060018301906002614828565b50608091909101516002909101805463ffffffff191663ffffffff9092169190911790556133333361ffff83166140b7565b8315613348576133488161ffff168585612440565b61335286866140d5565b60408087015186820151825161ffff808616825292831660208201529116918101919091527f30be847db9d81ac3b6da70a088210302e2688f8a3be64693715f10f36526941e90606001611f3e565b60006133ab612a9e565b905090565b600081815260056020526040902080546001600160a01b0319166001600160a01b03841690811790915581906133e582611b60565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60006001600160a01b0386166134845760405162461bcd60e51b815260206004820152602560248201527f4e61746976654d6574615472616e73616374696f6e3a20494e56414c49445f5360448201526424a3a722a960d91b6064820152608401610c66565b60016134976134928761419f565b61421c565b6040805160008152602081018083529290925260ff851690820152606081018690526080810185905260a0016020604051602081039080840390855afa1580156134e5573d6000803e3d6000fd5b505050602060405103516001600160a01b0316866001600160a01b031614905095945050505050565b62015180601c5461351f91906157b6565b4210156136cf576040516001600160601b03193360601b16602082015260348101849052605481018390526000906074016040516020818303038152906040528051906020012090506135758260175483613f39565b6135b85760405162461bcd60e51b815260206004820152601460248201527324b73b30b634b21036b2b935b63290383937b7b360611b6044820152606401610c66565b60008587156135de57336000908152601a6020526040902054610100900460ff166135f2565b336000908152601a602052604090205460ff165b6135fc91906157ce565b90508661366757848160ff1611156136465760405162461bcd60e51b815260206004820152600d60248201526c0457863656564696e672063617609c1b6044820152606401610c66565b336000908152601a60205260409020805460ff191660ff83161790556136cc565b838160ff1611156136aa5760405162461bcd60e51b815260206004820152600d60248201526c0457863656564696e672063617609c1b6044820152606401610c66565b336000908152601a60205260409020805461ff00191661010060ff8416021790555b50505b5050505050565b60006136e061424c565b9050600082613728576012546000906136f99084615919565b9050613706601182612afb565b9150613713601182612b95565b61372284601160010154614347565b506137a4565b826001141561376a576014546000906137419084615919565b905061374e601382612afb565b915061375b601382612b95565b61372284601360010154614347565b60405162461bcd60e51b815260206004820152600f60248201526e125b9d985b1a590818985d18da1259608a1b6044820152606401610c66565b6125493382612bdb565b6000818152600360205260408120546001600160a01b03166138275760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610c66565b600061383283611b60565b9050806001600160a01b0316846001600160a01b0316148061386d5750836001600160a01b03166138628461117f565b6001600160a01b0316145b8061294157506129418185612866565b826001600160a01b031661389082611b60565b6001600160a01b0316146138f85760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b6064820152608401610c66565b6001600160a01b03821661395a5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610c66565b61396583838361438a565b6139706000826133b0565b6001600160a01b0383166000908152600460205260408120805460019290613999908490615849565b90915550506001600160a01b03821660009081526004602052604081208054600192906139c79084906157b6565b909155505060008181526003602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b613a306147cd565b6000613a3c8585612afb565b90508261ffff168161ffff1610158015613a565750600084115b15613ad157806000613a69600187615849565b90506000613a778685615826565b90505b8061ffff168361ffff1610613acd57613a938883612afb565b92508061ffff168361ffff161415613ab15761ffff83168552613acd565b81613abb57613acd565b81613ac58161588c565b925050613a7a565b5050505b806000613adf8660016157b6565b90506000613aed8685615790565b90505b8061ffff168361ffff1611613b4b5787600101548210613b0f57613b4b565b613b2582613b1c816158de565b93508990612afb565b92508061ffff168361ffff161415613b465761ffff83166020860152613b4b565b613af0565b505050509392505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b805160609015613bff5760408051600180825281830190925290602080830190803683370190505090508281600081518110613be457613be4615959565b602002602001019061ffff16908161ffff1681525050610c3b565b60608201518051600091613ce091906018908490815b6020908102919091015161ffff9081168352828201939093526040918201600020825160a081018452815460ff808216151583526101008204909616938201939093526301000000909204909316818301528151808301909252919060608301906001830160028282826020028201916000905b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411613c89575050509284525050506002919091015463ffffffff16602090910152613ba6565b8051606085015160208101519293509091600091613d05919060189084906001613c15565b8051909150613d1481846157b6565b6001600160401b03811115613d2b57613d2b61596f565b604051908082528060200260200182016040528015613d54578160200160208202803683370190505b50945060005b83811015613db357848181518110613d7457613d74615959565b6020026020010151868281518110613d8e57613d8e615959565b61ffff9092166020928302919091019091015280613dab816158de565b915050613d5a565b5060005b81811015613e1b57828181518110613dd157613dd1615959565b6020026020010151868286613de691906157b6565b81518110613df657613df6615959565b61ffff9092166020928302919091019091015280613e13816158de565b915050613db7565b505050505092915050565b805160609060015b81811015613f31576000848281518110613e4a57613e4a615959565b602002602001015190506000600183613e639190615849565b90505b60008112158015613e9757508161ffff16868281518110613e8957613e89615959565b602002602001015161ffff16115b15613ef057858181518110613eae57613eae615959565b602002602001015186826001613ec491906157b6565b81518110613ed457613ed4615959565b61ffff9092166020928302919091019091015260001901613e66565b81868260010181518110613f0657613f06615959565b602002602001019061ffff16908161ffff168152505050508080613f29906158de565b915050613e2e565b509192915050565b600081815b8551811015613fdd576000868281518110613f5b57613f5b615959565b60200260200101519050808311613f9d576040805160208101859052908101829052606001604051602081830303815290604052805190602001209250613fca565b60408051602081018390529081018490526060016040516020818303038152906040528051906020012092505b5080613fd5816158de565b915050613f3e565b509092149392505050565b613ff384848461387d565b613fff84848484614446565b6125495760405162461bcd60e51b8152600401610c66906153ef565b60006140286010846157f3565b90506000614037601085615919565b90506000614046826010615807565b61ffff901b19905060008187600001858154811061406657614066615959565b90600052602060002001541690508260106140819190615807565b8561ffff16901b91508181178760000185815481106140a2576140a2615959565b60009182526020909120015550505050505050565b6140d182826040518060200160405280600081525061455a565b5050565b60608201515180156140e957506060810151515b156140f2575050565b6060820151511561412c57805161411b5760405162461bcd60e51b8152600401610c6690615441565b6140d1816040015161ffff1661458d565b606081015151156141665781516141555760405162461bcd60e51b8152600401610c6690615441565b6140d1826040015161ffff1661458d565b81518015614172575080515b61418e5760405162461bcd60e51b8152600401610c6690615441565b61411b826040015161ffff1661458d565b60006040518060800160405280604381526020016159b160439139805160209182012083518483015160408087015180519086012090516141ff950193845260208401929092526001600160a01b03166040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b600061422760085490565b60405161190160f01b60208201526022810191909152604281018390526062016141ff565b601d80546000918261425d836158de565b90915550506040516001600160601b03193360601b166020820152439042906034016040516020818303038152906040528051906020012060001c6142a291906157f3565b6040516001600160601b03194160601b166020820152459042906034016040516020818303038152906040528051906020012060001c6142e291906157f3565b6142ec44426157b6565b6142f691906157b6565b61430091906157b6565b61430a91906157b6565b61431491906157b6565b601d546040805160208101939093528201526060016040516020818303038152906040528051906020012060001c905090565b806140d15742601c557fa3cfaded1a887a6b8bc79d67e12e00966d9805697c70933c8a9eff74e667eb2e61437c8360016157b6565b604051908152602001612427565b61439261480a565b6040805160a0810182526000808252602080830182815283850183815260608501848152608086018881528986526019909452959093208451815492519451965163ffffffff16600160701b0263ffffffff60701b196001600160601b039890981662010000029790971662010000600160901b03199515156101000261ff00199215159290921661ffff199094169390931717939093161793909317815591519091906136cc9060018301906006614828565b60006001600160a01b0384163b1561454f57836001600160a01b031663150b7a0261446f6133a1565b8786866040518563ffffffff1660e01b815260040161449194939291906152bf565b602060405180830381600087803b1580156144ab57600080fd5b505af19250505080156144db575060408051601f3d908101601f191682019092526144d891810190614e23565b60015b614535573d808015614509576040519150601f19603f3d011682016040523d82523d6000602084013e61450e565b606091505b50805161452d5760405162461bcd60e51b8152600401610c66906153ef565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050612941565b506001949350505050565b6145648383614634565b6145716000848484614446565b6113375760405162461bcd60e51b8152600401610c66906153ef565b600061459882611b60565b90506145a68160008461438a565b6145b16000836133b0565b6001600160a01b03811660009081526004602052604081208054600192906145da908490615849565b909155505060008281526003602052604080822080546001600160a01b0319169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6001600160a01b03821661468a5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610c66565b6000818152600360205260409020546001600160a01b0316156146ef5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610c66565b6146fb6000838361438a565b6001600160a01b03821660009081526004602052604081208054600192906147249084906157b6565b909155505060008181526003602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b8280548282559060005260206000209081019282156147bd579160200282015b828111156147bd5782518255916020019190600101906147a2565b506147c9929150614914565b5090565b60405180604001604052806002906020820280368337509192915050565b604051806102e001604052806017906020820280368337509192915050565b6040518060c001604052806006906020820280368337509192915050565b6001830191839082156147bd5791602002820160005b8382111561487e57835183826101000a81548161ffff021916908361ffff160217905550926020019260020160208160010104928301926001030261483e565b80156148ac5782816101000a81549061ffff021916905560020160208160010104928301926001030261487e565b50506147c9929150614914565b60405180604001604052806148cc614929565b81526020016148d961495f565b905290565b6040805160a0810182526000808252602082018190529181019190915260608101614907614929565b81526020016148d961498c565b5b808211156147c95760008155600101614915565b6040805160a08101825260008082526020820181905291810191909152606081016149526147cd565b8152600060209091015290565b60405180606001604052806149726147cd565b815260200161497f6147cd565b81526020016148d96147cd565b6040805160a0810182526000808252602082018190529181018290526060810191909152608081016148d961480a565b600082601f8301126149cd57600080fd5b813560206149e26149dd83615746565b615716565b80838252828201915082860187848660051b8901011115614a0257600080fd5b60005b85811015614a2157813584529284019290840190600101614a05565b5090979650505050505050565b600082601f830112614a3f57600080fd5b604051604081018181106001600160401b0382111715614a6157614a6161596f565b8060405250808385604086011115614a7857600080fd5b60005b6002811015614aa257614a8d82614b7f565b83526020928301929190910190600101614a7b565b509195945050505050565b80358015158114611c1157600080fd5b600082601f830112614ace57600080fd5b8135614adc6149dd82615769565b818152846020838601011115614af157600080fd5b816020850160208301376000918101602001919091529392505050565b600060c08284031215614b2057600080fd5b604051606081018181106001600160401b0382111715614b4257614b4261596f565b604052905080614b528484614a2e565b8152614b618460408501614a2e565b6020820152614b738460808501614a2e565b60408201525092915050565b803561ffff81168114611c1157600080fd5b803563ffffffff81168114611c1157600080fd5b803560ff81168114611c1157600080fd5b600060208284031215614bc857600080fd5b8135611f6981615985565b60008060408385031215614be657600080fd5b8235614bf181615985565b91506020830135614c0181615985565b809150509250929050565b600080600060608486031215614c2157600080fd5b8335614c2c81615985565b92506020840135614c3c81615985565b929592945050506040919091013590565b60008060008060808587031215614c6357600080fd5b8435614c6e81615985565b93506020850135614c7e81615985565b92506040850135915060608501356001600160401b03811115614ca057600080fd5b614cac87828801614abd565b91505092959194509250565b60008060408385031215614ccb57600080fd5b8235614cd681615985565b9150614ce460208401614aad565b90509250929050565b600080600080600060a08688031215614d0557600080fd5b8535614d1081615985565b945060208601356001600160401b03811115614d2b57600080fd5b614d3788828901614abd565b9450506040860135925060608601359150614d5460808701614ba5565b90509295509295909350565b60008060408385031215614d7357600080fd5b8235614d7e81615985565b946020939093013593505050565b600080600060408486031215614da157600080fd5b83356001600160401b0380821115614db857600080fd5b818601915086601f830112614dcc57600080fd5b813581811115614ddb57600080fd5b8760208260051b8501011115614df057600080fd5b6020928301989097509590910135949350505050565b600060208284031215614e1857600080fd5b8135611f698161599a565b600060208284031215614e3557600080fd5b8151611f698161599a565b600060208284031215614e5257600080fd5b8151611f6981615985565b600060208284031215614e6f57600080fd5b81516001600160401b03811115614e8557600080fd5b8201601f81018413614e9657600080fd5b8051614ea46149dd82615769565b818152856020838501011115614eb957600080fd5b61150d826020830160208601615860565b600060208284031215614edc57600080fd5b611f6982614b7f565b6000808284036101a0811215614efa57600080fd5b614f0384614b7f565b9250601f1901610180811215614f1857600080fd5b614f206156cc565b60c0821215614f2e57600080fd5b614f366156f4565b9150614f4460208601614aad565b8252614f5260408601614b7f565b6020830152614f6360608601614ba5565b6040830152614f758660808701614a2e565b6060830152614f8660c08601614b91565b6080830152818152614f9b8660e08701614b0e565b602082015280925050509250929050565b60008060008060808587031215614fc257600080fd5b614fcb85614b7f565b9350614fd960208601614b7f565b92506040850135915060608501356001600160401b03811115614ffb57600080fd5b614cac878288016149bc565b6000806000806080858703121561501d57600080fd5b61502685614b7f565b93506020808601356001600160601b038116811461504357600080fd5b935061505160408701614b91565b925060608601356001600160401b0381111561506c57600080fd5b8601601f8101881361507d57600080fd5b803561508b6149dd82615746565b8082825284820191508484018b868560051b87010111156150ab57600080fd5b600094505b838510156150d5576150c181614b7f565b8352600194909401939185019185016150b0565b50979a9699509497505050505050565b6000602082840312156150f757600080fd5b5035919050565b60008060006060848603121561511357600080fd5b833592506020840135915060408401356001600160401b0381111561513757600080fd5b615143868287016149bc565b9150509250925092565b6000806000806080858703121561516357600080fd5b84359350602085013592506040850135915060608501356001600160401b03811115614ffb57600080fd5b8060005b60178110156125495781511515845260209384019390910190600101615192565b8060005b600281101561254957815161ffff168452602093840193909101906001016151b7565b600081518084526020808501945080840160005b8381101561520e57815161ffff16875295820195908201906001016151ee565b509495945050505050565b60008151808452615231816020860160208601615860565b601f01601f19169290920160200192915050565b60008251615257818460208701615860565b9190910192915050565b60008351615273818460208801615860565b60609390931b6001600160601b0319169190920190815260140192915050565b6001600160a01b0384811682528316602082015260606040820181905260009061150d90830184615219565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906152f290830184615219565b9695505050505050565b6102e08101818360005b60178110156153275781511515835260209283019290910190600101615306565b50505092915050565b60408101610c3b82846151b3565b60c08101818360005b600681101561532757815161ffff16835260209283019290910190600101615347565b6020808252825182820181905260009190848201906040850190845b818110156153a657835161ffff1683529284019291840191600101615386565b50909695505050505050565b602081526000611f696020830184615219565b60208082526010908201526f27b7363c9034b734ba34b0b634bd32b960811b604082015260600190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b60208082526018908201527f42726565646572206d757374206f776e206275726e696e670000000000000000604082015260600190565b60208082526010908201526f4261746368206e6f742061637469766560801b604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b602080825260139082015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b600061018082019050825180511515835261ffff602082015116602084015260ff604082015116604084015260608101516155ca60608501826151b3565b5063ffffffff60808201511660a08401525060208301516155ef60c0840182516151b3565b60208101516156026101008501826151b3565b50604001516156156101408401826151b3565b5092915050565b60006104a0868352855180511515602085015261ffff602082015116604085015260ff6040820151166060850152606081015161565c60808601826151b3565b5063ffffffff60808201511660c085015250602086015161568160e0850182516151b3565b60208101516156946101208601826151b3565b50604001516156a76101608501826151b3565b50806101a08401526156bb818401866151da565b91505061150d6101c083018461518e565b604080519081016001600160401b03811182821017156156ee576156ee61596f565b60405290565b60405160a081016001600160401b03811182821017156156ee576156ee61596f565b604051601f8201601f191681016001600160401b038111828210171561573e5761573e61596f565b604052919050565b60006001600160401b0382111561575f5761575f61596f565b5060051b60200190565b60006001600160401b038211156157825761578261596f565b50601f01601f191660200190565b600061ffff8083168185168083038211156157ad576157ad61592d565b01949350505050565b600082198211156157c9576157c961592d565b500190565b600060ff821660ff84168060ff038211156157eb576157eb61592d565b019392505050565b60008261580257615802615943565b500490565b60008160001904831182151516156158215761582161592d565b500290565b600061ffff838116908316818110156158415761584161592d565b039392505050565b60008282101561585b5761585b61592d565b500390565b60005b8381101561587b578181015183820152602001615863565b838111156125495750506000910152565b60008161589b5761589b61592d565b506000190190565b600181811c908216806158b757607f821691505b602082108114156158d857634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156158f2576158f261592d565b5060010190565b600060ff821660ff8114156159105761591061592d565b60010192915050565b60008261592857615928615943565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114612a0057600080fd5b6001600160e01b031981168114612a0057600080fdfe4d6574615472616e73616374696f6e2875696e74323536206e6f6e63652c616464726573732066726f6d2c62797465732066756e6374696f6e5369676e617475726529a26469706673582212204441b21cbfe6a1dd26971eed92a336b3877f15f6861293a2babc875af44889be64736f6c63430008070033

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

000000000000000000000000adca2cccf35cbb27fd757f1c0329df767f8e38f00000000000000000000000000000000000000000000000000000000000015180000000000000000000000000a5409ec958c83c3f309868babaca7c86dcb077c12310fdb07b877408b4a51a7903d83160d08a6e6c479a835f59be40ef1ddc60015ea25fa487381abb3a9e7c19686f6ac798a505266486be93a7065ccad2004f3e

-----Decoded View---------------
Arg [0] : _dao (address): 0xAdCa2CCcF35CbB27fD757f1c0329DF767f8E38F0
Arg [1] : _breedCooldown (uint256): 86400
Arg [2] : _proxyRegistryAddress (address): 0xa5409ec958C83C3f309868babACA7c86DCB077c1
Arg [3] : _attributesRootHash (bytes32): 0x2310fdb07b877408b4a51a7903d83160d08a6e6c479a835f59be40ef1ddc6001
Arg [4] : _whitelistRootHash (bytes32): 0x5ea25fa487381abb3a9e7c19686f6ac798a505266486be93a7065ccad2004f3e

-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 000000000000000000000000adca2cccf35cbb27fd757f1c0329df767f8e38f0
Arg [1] : 0000000000000000000000000000000000000000000000000000000000015180
Arg [2] : 000000000000000000000000a5409ec958c83c3f309868babaca7c86dcb077c1
Arg [3] : 2310fdb07b877408b4a51a7903d83160d08a6e6c479a835f59be40ef1ddc6001
Arg [4] : 5ea25fa487381abb3a9e7c19686f6ac798a505266486be93a7065ccad2004f3e


Libraries Used


Deployed Bytecode Sourcemap

82922:20325:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19408:355;;;;;;;;;;-1:-1:-1;19408:355:0;;;;;:::i;:::-;;:::i;:::-;;;19582:14:1;;19575:22;19557:41;;19545:2;19530:18;19408:355:0;;;;;;;;96386:531;;;;;;;;;;;;;:::i;:::-;;;21062:25:1;;;21050:2;21035:18;96386:531:0;20916:177:1;20403:100:0;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;102179:220::-;;;;;;;;;;-1:-1:-1;102179:220:0;;;;;:::i;:::-;;:::i;:::-;;86498:1009;;;;;;:::i;:::-;;:::i;21975:221::-;;;;;;;;;;-1:-1:-1;21975:221:0;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;16530:32:1;;;16512:51;;16500:2;16485:18;21975:221:0;16366:203:1;21498:411:0;;;;;;;;;;-1:-1:-1;21498:411:0;;;;;:::i;:::-;;:::i;36452:1040::-;;;;;;:::i;:::-;;:::i;33904:43::-;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;33904:43:0;;;;;95593:785;;;;;;:::i;:::-;;:::i;34867:101::-;;;;;;;;;;-1:-1:-1;34945:15:0;;34867:101;;102635:220;;;;;;;;;;-1:-1:-1;102635:220:0;;;;;:::i;:::-;;:::i;22915:376::-;;;;;;;;;;-1:-1:-1;22915:376:0;;;;;:::i;:::-;;:::i;85800:125::-;;;;;;;;;;-1:-1:-1;85800:125:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;37886:107::-;;;;;;;;;;-1:-1:-1;37886:107:0;;;;;:::i;:::-;-1:-1:-1;;;;;37973:12:0;37939:13;37973:12;;;:6;:12;;;;;;;37886:107;34976:161;;;;;;;;;;-1:-1:-1;35090:9:0;34976:161;;97504:119;;;;;;;;;;;;;:::i;23362:185::-;;;;;;;;;;-1:-1:-1;23362:185:0;;;;;:::i;:::-;;:::i;49529:283::-;;;;;;;;;;-1:-1:-1;49529:283:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;97002:494::-;;;;;;;;;;;;;:::i;97631:837::-;;;;;;;;;;;;;:::i;:::-;;;;20760:14:1;;20753:22;20735:41;;20807:2;20792:18;;20785:34;;;;20835:18;;;20828:34;20893:2;20878:18;;20871:34;20722:3;20707:19;97631:837:0;20510:401:1;20097:239:0;;;;;;;;;;-1:-1:-1;20097:239:0;;;;;:::i;:::-;;:::i;83861:44::-;;;;;;;;;;-1:-1:-1;83861:44:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;83861:44:0;;-1:-1:-1;;;83861:44:0;;;;;;;;;;;;;;;19849:14:1;;19842:22;19824:41;;19908:14;;19901:22;19896:2;19881:18;;19874:50;-1:-1:-1;;;;;19960:39:1;19955:2;19940:18;;19933:67;20048:10;20036:23;20031:2;20016:18;;20009:51;19811:3;19796:19;;19609:457;94480:370:0;;;;;;;;;;-1:-1:-1;94480:370:0;;;;;:::i;:::-;;:::i;19827:208::-;;;;;;;;;;-1:-1:-1;19827:208:0;;;;;:::i;:::-;;:::i;32912:94::-;;;;;;;;;;;;;:::i;95362:223::-;;;;;;:::i;:::-;;:::i;89974:739::-;;;;;;;;;;-1:-1:-1;89974:739:0;;;;;:::i;:::-;;:::i;92400:259::-;;;;;;;;;;-1:-1:-1;92400:259:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;83998:29::-;;;;;;;;;;;;;;;;94097:375;;;;;;;;;;-1:-1:-1;94097:375:0;;;;;:::i;:::-;;:::i;85150:507::-;;;;;;;;;;-1:-1:-1;85150:507:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;84102:42::-;;;;;;;;;;;;;;;32261:87;;;;;;;;;;-1:-1:-1;32307:7:0;32334:6;-1:-1:-1;;;;;32334:6:0;32261:87;;20572:104;;;;;;;;;;;;;:::i;101939:232::-;;;;;;;;;;-1:-1:-1;101939:232:0;;;;;:::i;:::-;;:::i;22268:295::-;;;;;;;;;;-1:-1:-1;22268:295:0;;;;;:::i;:::-;;:::i;90721:264::-;;;;;;;;;;-1:-1:-1;90721:264:0;;;;;:::i;:::-;;:::i;83912:41::-;;;;;;;;;;-1:-1:-1;83912:41:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;43577:4:1;43565:17;;;43547:36;;43619:17;;;;43614:2;43599:18;;43592:45;43520:18;83912:41:0;43381:262:1;85010:132:0;;;;;;;;;;-1:-1:-1;85010:132:0;;;;;:::i;:::-;;:::i;:::-;;;41171:6:1;41159:19;;;41141:38;;41129:2;41114:18;85010:132:0;40997:188:1;84034:20:0;;;;;;;;;;;;;;;;49090:431;;;;;;;;;;-1:-1:-1;49090:431:0;;;;;:::i;:::-;;:::i;23618:365::-;;;;;;;;;;-1:-1:-1;23618:365:0;;;;;:::i;:::-;;:::i;91992:400::-;;;;;;;;;;-1:-1:-1;91992:400:0;;;;;:::i;:::-;;:::i;39225:35::-;;;;;;;;;;-1:-1:-1;39225:35:0;;;;-1:-1:-1;;;;;39225:35:0;;;83773:32;;;;;;;;;;;;;;;;85665:127;;;;;;;;;;-1:-1:-1;85665:127:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;102863:381::-;;;;;;;;;;-1:-1:-1;102863:381:0;;;;;:::i;:::-;;:::i;94858:372::-;;;;;;;;;;-1:-1:-1;94858:372:0;;;;;:::i;:::-;;:::i;102407:220::-;;;;;;;;;;-1:-1:-1;102407:220:0;;;;;:::i;:::-;;:::i;39695:466::-;;;;;;;;;;-1:-1:-1;39695:466:0;;;;;:::i;:::-;;:::i;48683:33::-;;;;;;;;;;;;;;;;83962:27;;;;;;;;;;-1:-1:-1;83962:27:0;;;;-1:-1:-1;;;;;83962:27:0;;;83814:40;;;;;;;;;;-1:-1:-1;83814:40:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20313:14:1;;20306:22;20288:41;;20377:6;20365:19;;;20360:2;20345:18;;20338:47;20433:4;20421:17;;;20401:18;;;20394:45;;;;20487:10;20475:23;20470:2;20455:18;;20448:51;20275:3;20260:19;83814:40:0;20071:434:1;33161:192:0;;;;;;;;;;-1:-1:-1;33161:192:0;;;;;:::i;:::-;;:::i;86058:432::-;;;;;;;;;;-1:-1:-1;86058:432:0;;;;;:::i;:::-;;:::i;84061:34::-;;;;;;;;;;;;;;;19408:355;19555:4;-1:-1:-1;;;;;;19597:40:0;;-1:-1:-1;;;19597:40:0;;:105;;-1:-1:-1;;;;;;;19654:48:0;;-1:-1:-1;;;19654:48:0;19597:105;:158;;;-1:-1:-1;;;;;;;;;;18378:40:0;;;19719:36;19577:178;19408:355;-1:-1:-1;;19408:355:0:o;96386:531::-;96441:15;41316:1;41912:7;;:19;;41904:63;;;;-1:-1:-1;;;41904:63:0;;;;;;;:::i;:::-;;;;;;;;;41316:1;42045:7;:18;96491:12:::1;::::0;-1:-1:-1;;;;;96491:12:0::1;96477:10;:26;96469:61;;;::::0;-1:-1:-1;;;96469:61:0;;31478:2:1;96469:61:0::1;::::0;::::1;31460:21:1::0;31517:2;31497:18;;;31490:30;-1:-1:-1;;;31536:18:1;;;31529:52;31598:18;;96469:61:0::1;31276:346:1::0;96469:61:0::1;96544:11;96557:15:::0;96574:17:::1;96597:12;:10;:12::i;:::-;96543:66;;;;;;;96628:6;:22;;;;;96638:7;96649:1;96638:12;96628:22;96620:51;;;;-1:-1:-1::0;;;96620:51:0::1;;;;;;;:::i;:::-;96702:1;96690:9;:13;96682:40;;;::::0;-1:-1:-1;;;96682:40:0;;38420:2:1;96682:40:0::1;::::0;::::1;38402:21:1::0;38459:2;38439:18;;;38432:30;-1:-1:-1;;;38478:18:1;;;38471:44;38532:18;;96682:40:0::1;38218:338:1::0;96682:40:0::1;96749:13:::0;;96735:11:::1;::::0;96749:17:::1;::::0;96765:1:::1;::::0;96749:17:::1;:::i;:::-;96735:31:::0;-1:-1:-1;96777:17:0::1;96797:20;:6;96735:31:::0;96797:15:::1;:20::i;:::-;96777:40:::0;-1:-1:-1;96828:24:0::1;:6;96848:3:::0;96828:19:::1;:24::i;:::-;96875:34;96886:10;96898;96875;:34::i;:::-;41272:1:::0;42224:7;:22;96865:44;96386:531;-1:-1:-1;;;;;;96386:531:0:o;20403:100::-;20457:13;20490:5;20483:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20403:100;:::o;102179:220::-;101867:10;-1:-1:-1;;;;;101881:9:0;101867:23;;101859:52;;;;-1:-1:-1;;;101859:52:0;;;;;;;:::i;:::-;102286:13;;:18;102278:50:::1;;;;-1:-1:-1::0;;;102278:50:0::1;;;;;;;:::i;:::-;102348:43;102376:5;;102348:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;102383:7:0;;-1:-1:-1;102348:27:0::1;::::0;-1:-1:-1;;102348:43:0:i:1;:::-;102339:52:::0;;;;:6:::1;::::0;:52:::1;::::0;:6;;:52:::1;;::::0;::::1;:::i;:::-;;;;;;;;;;;;;102179:220:::0;;;:::o;86498:1009::-;41316:1;41912:7;;:19;;41904:63;;;;-1:-1:-1;;;41904:63:0;;;;;;;:::i;:::-;41316:1;42045:7;:18;86688:24:::1;86715:19;86725:8:::0;86715:9:::1;:19::i;:::-;86688:46;;86745:24;86772:19;86782:8;86772:9;:19::i;:::-;86810:11:::0;;86745:46;;-1:-1:-1;86802:44:0::1;;;::::0;-1:-1:-1;;;86802:44:0;;39829:2:1;86802:44:0::1;::::0;::::1;39811:21:1::0;39868:2;39848:18;;;39841:30;-1:-1:-1;;;39887:18:1;;;39880:50;39947:18;;86802:44:0::1;39627:344:1::0;86802:44:0::1;86865:17;::::0;::::1;::::0;:28;86857:57:::1;;;::::0;-1:-1:-1;;;86857:57:0;;35519:2:1;86857:57:0::1;::::0;::::1;35501:21:1::0;35558:2;35538:18;;;35531:30;-1:-1:-1;;;35577:18:1;;;35570:46;35633:18;;86857:57:0::1;35317:340:1::0;86857:57:0::1;86946:6;:17;;;:25;;;-1:-1:-1::0;;;;;86933:38:0::1;:9;:38;;86925:68;;;::::0;-1:-1:-1;;;86925:68:0;;36623:2:1;86925:68:0::1;::::0;::::1;36605:21:1::0;36662:2;36642:18;;;36635:30;-1:-1:-1;;;36681:18:1;;;36674:47;36738:18;;86925:68:0::1;36421:341:1::0;86925:68:0::1;87012:12;::::0;::::1;::::0;-1:-1:-1;;;;;87004:30:0::1;:52;87053:2;87036:13;:9;87048:1;87036:13;:::i;:::-;87035:20;;;;:::i;:::-;87004:52;::::0;;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;::::1;;;;;;;;;;;;;::::0;::::1;;;;;;87093:6;:17;;;:26;;;87075:44;;:15;:44;87067:79;;;::::0;-1:-1:-1;;;87067:79:0;;31127:2:1;87067:79:0::1;::::0;::::1;31109:21:1::0;31166:2;31146:18;;;31139:30;-1:-1:-1;;;31185:18:1;;;31178:52;31247:18;;87067:79:0::1;30925:346:1::0;87067:79:0::1;87161:6;:17;;;:31;;;87157:283;;;87209:13;::::0;87237:130:::1;87261:1;87257;:5;87237:130;;;87299:8;:52;;;;87343:8;87311:40;;:6;:17;;;:25;;;87337:1;87311:28;;;;;;;:::i;:::-;;;;;:40;;;87299:52;87288:63:::0;-1:-1:-1;87264:3:0;::::1;::::0;::::1;:::i;:::-;;;;87237:130;;;;87389:8;87381:47;;;::::0;-1:-1:-1;;;87381:47:0;;23272:2:1;87381:47:0::1;::::0;::::1;23254:21:1::0;23311:2;23291:18;;;23284:30;23350:28;23330:18;;;23323:56;23396:18;;87381:47:0::1;23070:350:1::0;87381:47:0::1;87194:246;87157:283;87450:49;87457:6;87465;87473:11;87486:12;87450:6;:49::i;:::-;-1:-1:-1::0;;41272:1:0;42224:7;:22;-1:-1:-1;;;;86498:1009:0:o;21975:221::-;22051:7;25619:16;;;:7;:16;;;;;;-1:-1:-1;;;;;25619:16:0;22071:73;;;;-1:-1:-1;;;22071:73:0;;32178:2:1;22071:73:0;;;32160:21:1;32217:2;32197:18;;;32190:30;32256:34;32236:18;;;32229:62;-1:-1:-1;;;32307:18:1;;;32300:42;32359:19;;22071:73:0;31976:408:1;22071:73:0;-1:-1:-1;22164:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;22164:24:0;;21975:221::o;21498:411::-;21579:13;21595:23;21610:7;21595:14;:23::i;:::-;21579:39;;21643:5;-1:-1:-1;;;;;21637:11:0;:2;-1:-1:-1;;;;;21637:11:0;;;21629:57;;;;-1:-1:-1;;;21629:57:0;;36221:2:1;21629:57:0;;;36203:21:1;36260:2;36240:18;;;36233:30;36299:34;36279:18;;;36272:62;-1:-1:-1;;;36350:18:1;;;36343:31;36391:19;;21629:57:0;36019:397:1;21629:57:0;21737:5;-1:-1:-1;;;;;21721:21:0;:12;:10;:12::i;:::-;-1:-1:-1;;;;;21721:21:0;;:62;;;;21746:37;21763:5;21770:12;:10;:12::i;21746:37::-;21699:168;;;;-1:-1:-1;;;21699:168:0;;29168:2:1;21699:168:0;;;29150:21:1;29207:2;29187:18;;;29180:30;29246:34;29226:18;;;29219:62;29317:26;29297:18;;;29290:54;29361:19;;21699:168:0;28966:420:1;21699:168:0;21880:21;21889:2;21893:7;21880:8;:21::i;:::-;21568:341;21498:411;;:::o;36452:1040::-;36710:152;;;36653:12;36710:152;;;;;-1:-1:-1;;;;;36748:19:0;;36678:29;36748:19;;;:6;:19;;;;;;;;;36710:152;;;;;;;;;;;36883:45;36755:11;36710:152;36911:4;36917;36923;36883:6;:45::i;:::-;36875:91;;;;-1:-1:-1;;;36875:91:0;;33711:2:1;36875:91:0;;;33693:21:1;33750:2;33730:18;;;33723:30;33789:34;33769:18;;;33762:62;-1:-1:-1;;;33840:18:1;;;33833:31;33881:19;;36875:91:0;33509:397:1;36875:91:0;-1:-1:-1;;;;;37033:19:0;;;;;;:6;:19;;;;;:24;;37056:1;;37033:19;:24;;37056:1;;37033:24;:::i;:::-;;;;-1:-1:-1;;37075:76:0;;;;;;37099:11;;37120:10;;37133:17;;37075:76;:::i;:::-;;;;;;;;37262:12;37276:23;37311:4;-1:-1:-1;;;;;37303:18:0;37353:17;37372:11;37336:48;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;37336:48:0;;;;;;;;;;37303:92;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;37261:134;;;;37414:7;37406:48;;;;-1:-1:-1;;;37406:48:0;;24453:2:1;37406:48:0;;;24435:21:1;24492:2;24472:18;;;24465:30;24531;24511:18;;;24504:58;24579:18;;37406:48:0;24251:352:1;37406:48:0;37474:10;-1:-1:-1;;;36452:1040:0;;;;;;;;:::o;95593:785::-;41316:1;41912:7;;:19;;41904:63;;;;-1:-1:-1;;;41904:63:0;;;;;;;:::i;:::-;41316:1;42045:7;:18;95789:11:::1;::::0;;95842:12:::1;:10;:12::i;:::-;95788:66;;;;;;;95873:6;:21;;;;;95893:1;95883:7;:11;95873:21;95865:50;;;;-1:-1:-1::0;;;95865:50:0::1;;;;;;;:::i;:::-;95947:6;95934:9;:19;;95926:59;;;::::0;-1:-1:-1;;;95926:59:0;;22571:2:1;95926:59:0::1;::::0;::::1;22553:21:1::0;22610:2;22590:18;;;22583:30;22649:29;22629:18;;;22622:57;22696:18;;95926:59:0::1;22369:351:1::0;95926:59:0::1;96014:2;96004:6;:12;;95996:55;;;::::0;-1:-1:-1;;;95996:55:0;;38763:2:1;95996:55:0::1;::::0;::::1;38745:21:1::0;38802:2;38782:18;;;38775:30;38841:32;38821:18;;;38814:60;38891:18;;95996:55:0::1;38561:354:1::0;95996:55:0::1;96064:17;96084:12:::0;;:44:::1;;83545:5;96084:44;;;83492:4;96084:44;96064:64:::0;-1:-1:-1;96160:18:0::1;96064:64:::0;96160:6;:18:::1;:::i;:::-;96147:9;:31;;96139:58;;;::::0;-1:-1:-1;;;96139:58:0;;38077:2:1;96139:58:0::1;::::0;::::1;38059:21:1::0;38116:2;38096:18;;;38089:30;-1:-1:-1;;;38135:18:1;;;38128:44;38189:18;;96139:58:0::1;37875:338:1::0;96139:58:0::1;96210:68;96224:7;96233:6;96241:10;96253;96265:12;96210:13;:68::i;:::-;96294:9;96289:82;96313:6;96309:1;:10;96289:82;;;96341:18;96351:7;96341:9;:18::i;:::-;96321:3:::0;::::1;::::0;::::1;:::i;:::-;;;;96289:82;;;-1:-1:-1::0;;41272:1:0;42224:7;:22;-1:-1:-1;;;;;;;95593:785:0:o;102635:220::-;101867:10;-1:-1:-1;;;;;101881:9:0;101867:23;;101859:52;;;;-1:-1:-1;;;101859:52:0;;;;;;;:::i;:::-;102742:13;;:18;102734:50:::1;;;;-1:-1:-1::0;;;102734:50:0::1;;;;;;;:::i;:::-;102804:43;102832:5;;102804:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;102839:7:0;;-1:-1:-1;102804:27:0::1;::::0;-1:-1:-1;;102804:43:0:i:1;:::-;102795:52:::0;;;;:6:::1;::::0;:52:::1;::::0;:6;;:52:::1;;::::0;::::1;:::i;22915:376::-:0;23124:41;23143:12;:10;:12::i;:::-;23157:7;23124:18;:41::i;:::-;23102:140;;;;-1:-1:-1;;;23102:140:0;;;;;;;:::i;:::-;23255:28;23265:4;23271:2;23275:7;23255:9;:28::i;85800:125::-;85859:16;;:::i;:::-;85895:14;;;;:4;:14;;;;;;85888:29;;;;;;;;;;85895:22;;;;;85888:29;;85895:22;;85888:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;85888:29:0;;85800:125;-1:-1:-1;;;;;;;85800:125:0:o;97504:119::-;32492:12;:10;:12::i;:::-;-1:-1:-1;;;;;32481:23:0;:7;32307;32334:6;-1:-1:-1;;;;;32334:6:0;;32261:87;32481:7;-1:-1:-1;;;;;32481:23:0;;32473:68;;;;-1:-1:-1;;;32473:68:0;;;;;;;:::i;:::-;41316:1:::1;41912:7;;:19;;41904:63;;;;-1:-1:-1::0;;;41904:63:0::1;;;;;;;:::i;:::-;41316:1;42045:7;:18:::0;32307:7;32334:6;;97567:48:::2;::::0;-1:-1:-1;;;;;32334:6:0;;;;97593:21:::2;97567:48:::0;::::2;;;::::0;97593:21;;97567:48;32307:7;97567:48;97593:21;32334:6;97567:48;::::2;;;;;;;;;;;;;::::0;::::2;;;;;-1:-1:-1::0;41272:1:0::1;42224:7;:22:::0;97504:119::o;23362:185::-;23500:39;23517:4;23523:2;23527:7;23500:39;;;;;;;;;;;;:16;:39::i;49529:283::-;49591:26;;:::i;:::-;49630:14;49647:26;;;:16;:26;;;;;;;49684:93;49706:2;49702:1;:6;;;49684:93;;;49974:1;49746:19;;;49941:21;;;49940:36;;49999:9;49730:10;49741:1;49730:13;;;;;;;;;:::i;:::-;:35;;;:13;;;;;:35;49710:3;;;;:::i;:::-;;;;49684:93;;;;49787:17;49529:283;;;:::o;97002:494::-;32492:12;:10;:12::i;:::-;-1:-1:-1;;;;;32481:23:0;:7;32307;32334:6;-1:-1:-1;;;;;32334:6:0;;32261:87;32481:7;-1:-1:-1;;;;;32481:23:0;;32473:68;;;;-1:-1:-1;;;32473:68:0;;;;;;;:::i;:::-;41316:1:::1;41912:7;;:19;;41904:63;;;;-1:-1:-1::0;;;41904:63:0::1;;;;;;;:::i;:::-;41316:1;42045:7;:18:::0;97068:11:::2;::::0;;97121:12:::2;:10;:12::i;:::-;97067:66;;;;;;;97152:6;97144:35;;;;-1:-1:-1::0;;;97144:35:0::2;;;;;;;:::i;:::-;83130:8;97230:14;;:41;;;;:::i;:::-;97212:15;:59;97190:137;;;::::0;-1:-1:-1;;;97190:137:0;;35864:2:1;97190:137:0::2;::::0;::::2;35846:21:1::0;35903:2;35883:18;;;35876:30;35942;35922:18;;;35915:58;35990:18;;97190:137:0::2;35662:352:1::0;97190:137:0::2;97338:19;97372:2;97360:9;:14;:31;;97389:2;97360:31;;;97377:9;97360:31;97338:53;;97407:9;97402:87;97426:11;97422:1;:15;97402:87;;;97459:18;97469:7;97459:9;:18::i;:::-;97439:3:::0;::::2;::::0;::::2;:::i;:::-;;;;97402:87;;;-1:-1:-1::0;;41272:1:0::1;42224:7;:22:::0;-1:-1:-1;;;97002:494:0:o;97631:837::-;97715:11;97741:13;97769:17;97801;97846:10;97859:14;;97846:27;;97888:2;97894:1;97888:7;97884:63;;;97920:5;97927:1;97930;97933;97912:23;;;;;;;;;;;97884:63;97961:13;;:17;97957:179;;83259:7;98007:14;;:37;;;;:::i;:::-;97995:49;;98085:9;98067:15;:27;98096:1;98099:6;:13;;;98059:65;;;;;;;;;97957:179;98150:13;;:17;98146:179;;83322:7;98196:14;;:37;;;;:::i;:::-;98184:49;;98274:9;98256:15;:27;98285:1;98288:6;:13;;;98248:65;;;;;;;;;98146:179;83385:8;98347:14;;:37;;;;:::i;:::-;98435:13;;98403:15;:27;-1:-1:-1;98403:27:0;-1:-1:-1;98432:1:0;;-1:-1:-1;98435:13:0;-1:-1:-1;98335:49:0;-1:-1:-1;;97631:837:0;;;;;:::o;20097:239::-;20169:7;20205:16;;;:7;:16;;;;;;-1:-1:-1;;;;;20205:16:0;20240:19;20232:73;;;;-1:-1:-1;;;20232:73:0;;30004:2:1;20232:73:0;;;29986:21:1;30043:2;30023:18;;;30016:30;30082:34;30062:18;;;30055:62;-1:-1:-1;;;30133:18:1;;;30126:39;30182:19;;20232:73:0;29802:405:1;94480:370:0;94537:24;;:::i;:::-;94578:15;;94574:269;;94620:48;:12;94653:11;94666:1;94620:32;:48::i;:::-;94610:58;;94687:11;94702:1;94687:16;94683:149;;;94815:1;94802:7;94815:1;94802:10;:14;;;;:10;;;;;;:14;94683:149;94480:370;;;:::o;19827:208::-;19899:7;-1:-1:-1;;;;;19927:19:0;;19919:74;;;;-1:-1:-1;;;19919:74:0;;29593:2:1;19919:74:0;;;29575:21:1;29632:2;29612:18;;;29605:30;29671:34;29651:18;;;29644:62;-1:-1:-1;;;29722:18:1;;;29715:40;29772:19;;19919:74:0;29391:406:1;19919:74:0;-1:-1:-1;;;;;;20011:16:0;;;;;:9;:16;;;;;;;19827:208::o;32912:94::-;32492:12;:10;:12::i;:::-;-1:-1:-1;;;;;32481:23:0;:7;32307;32334:6;-1:-1:-1;;;;;32334:6:0;;32261:87;32481:7;-1:-1:-1;;;;;32481:23:0;;32473:68;;;;-1:-1:-1;;;32473:68:0;;;;;;;:::i;:::-;32977:21:::1;32995:1;32977:9;:21::i;:::-;32912:94::o:0;95362:223::-;95520:57;95537:1;95540:10;95552;95564:12;95520:16;:57::i;89974:739::-;90147:17;90155:8;90147:17;;:7;:17::i;:::-;-1:-1:-1;;;;;90133:31:0;:10;-1:-1:-1;;;;;90133:31:0;;90125:63;;;;-1:-1:-1;;;90125:63:0;;34470:2:1;90125:63:0;;;34452:21:1;34509:2;34489:18;;;34482:30;-1:-1:-1;;;34528:18:1;;;34521:49;34587:18;;90125:63:0;34268:343:1;90125:63:0;90201:24;;:::i;:::-;90250:15;;90280:7;;90276:180;;90318:1;90312:3;:7;90304:33;;;;-1:-1:-1;;;90304:33:0;;37735:2:1;90304:33:0;;;37717:21:1;37774:2;37754:18;;;37747:30;-1:-1:-1;;;37793:18:1;;;37786:43;37846:18;;90304:33:0;37533:337:1;90304:33:0;90357:9;90352:93;90376:3;90372:1;:7;90352:93;;;90418:8;90427:1;90418:11;;;;;;;;:::i;:::-;;;;;;;90405:7;90413:1;90405:10;;;;;;;:::i;:::-;:24;;;;:10;;;;;;:24;90381:3;;;;:::i;:::-;;;;90352:93;;;;90276:180;90487:184;;;;;;;;90525:4;90487:184;;;;;;90565:1;90559:3;:7;90487:184;;;;;;90590:4;-1:-1:-1;;;;;90487:184:0;;;;;90619:9;90487:184;;;;;;90652:7;90487:184;;;90468:6;:16;90475:8;90468:16;;;;;;;;;;;;;:203;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;90468:203:0;;;;;-1:-1:-1;;;;;90468:203:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;90689:16:0;;41171:6:1;41159:19;;41141:38;;90689:16:0;;-1:-1:-1;41129:2:1;41114:18;90689:16:0;;;;;;;;90114:599;;89974:739;;;;:::o;92400:259::-;92521:23;92572:39;92584:8;92594:11;:16;;;92572:11;:39::i;:::-;92562:49;;92632:19;92643:7;92632:10;:19::i;:::-;92622:29;92400:259;-1:-1:-1;;;92400:259:0:o;94097:375::-;94159:24;;:::i;:::-;94200:15;;94196:269;;94242:48;:12;94275:11;94288:1;94242:32;:48::i;:::-;94232:58;;94309:11;94324:1;94309:16;94305:149;;;94437:1;94424:7;94437:1;94424:10;;85150:507;85212:17;;:::i;:::-;85262:5;85250:8;:17;;85242:46;;;;-1:-1:-1;;;85242:46:0;;27375:2:1;85242:46:0;;;27357:21:1;27414:2;27394:18;;;27387:30;-1:-1:-1;;;27433:18:1;;;27426:46;27489:18;;85242:46:0;27173:340:1;85242:46:0;85299:20;85322:14;;;:4;:14;;;;;;;;85299:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;85322:14;;85299:37;;;;;;;;;;;;:20;:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;85299:37:0;;;-1:-1:-1;;;85299:37:0;;;;;;;;;;;;;85367:282;;;;;;;;;;;85433:200;;;;;;;;85489:15;;;;85367:282;;-1:-1:-1;85367:282:0;;;;;85433:200;;85478:27;;;;:10;:27::i;:::-;85433:200;;;;85535:22;85541:4;:15;;;85535:22;;:5;:22::i;:::-;85433:200;;;;85589:24;85597:4;:15;;;85589:24;;:7;:24::i;:::-;85433:200;;85367:282;;85347:302;85150:507;-1:-1:-1;;;85150:507:0:o;20572:104::-;20628:13;20661:7;20654:14;;;;;:::i;101939:232::-;101867:10;-1:-1:-1;;;;;101881:9:0;101867:23;;101859:52;;;;-1:-1:-1;;;101859:52:0;;;;;;;:::i;:::-;102046:19;;:24;102038:56:::1;;;;-1:-1:-1::0;;;102038:56:0::1;;;;;;;:::i;:::-;102120:43;102148:5;;102120:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;102155:7:0;;-1:-1:-1;102120:27:0::1;::::0;-1:-1:-1;;102120:43:0:i:1;:::-;102105:58:::0;;;;:12:::1;::::0;:58:::1;::::0;:12;;:58:::1;;::::0;::::1;:::i;22268:295::-:0;22383:12;:10;:12::i;:::-;-1:-1:-1;;;;;22371:24:0;:8;-1:-1:-1;;;;;22371:24:0;;;22363:62;;;;-1:-1:-1;;;22363:62:0;;26608:2:1;22363:62:0;;;26590:21:1;26647:2;26627:18;;;26620:30;26686:27;26666:18;;;26659:55;26731:18;;22363:62:0;26406:349:1;22363:62:0;22483:8;22438:18;:32;22457:12;:10;:12::i;:::-;-1:-1:-1;;;;;22438:32:0;;;;;;;;;;;;;;;;;-1:-1:-1;22438:32:0;;;:42;;;;;;;;;;;;:53;;-1:-1:-1;;22438:53:0;;;;;;;;;;;22522:12;:10;:12::i;:::-;-1:-1:-1;;;;;22507:48:0;;22546:8;22507:48;;;;19582:14:1;19575:22;19557:41;;19545:2;19530:18;;19417:187;22507:48:0;;;;;;;;22268:295;;:::o;90721:264::-;90796:17;90804:8;90796:17;;:7;:17::i;:::-;-1:-1:-1;;;;;90782:31:0;:10;-1:-1:-1;;;;;90782:31:0;;90774:63;;;;-1:-1:-1;;;90774:63:0;;34470:2:1;90774:63:0;;;34452:21:1;34509:2;34489:18;;;34482:30;-1:-1:-1;;;34528:18:1;;;34521:49;34587:18;;90774:63:0;34268:343:1;90774:63:0;90850:23;;:::i;:::-;90903:38;;;;;;;;-1:-1:-1;90903:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;90884:16;;;;;:6;:16;;;;;;;:57;;;;;;;;;;90903:38;90884:57;-1:-1:-1;;;90884:57:0;-1:-1:-1;;;;;;;;;90884:57:0;;;;;;;;;;-1:-1:-1;;;;;;90884:57:0;;;;;-1:-1:-1;;90884:57:0;;;;;;;-1:-1:-1;;90884:57:0;;;;;;;;;;;;;;;;;;;;;90903:38;;90884:16;:57;;90903:38;90884:57;;;;;:::i;:::-;-1:-1:-1;;90959:18:0;;41171:6:1;41159:19;;41141:38;;90959:18:0;;-1:-1:-1;41129:2:1;41114:18;90959::0;;;;;;;;90763:222;90721:264;:::o;85010:132::-;85067:18;85105:29;:12;85127:6;85105:21;:29::i;49090:431::-;49263:39;;;;;;14923:19:1;;;14958:12;;;14951:28;;;49238:12:0;;14995::1;;49263:39:0;;;;;;;;;;;;49253:50;;;;;;49238:65;;49322:58;49341:12;49355:18;;49375:4;49322:18;:58::i;:::-;49314:91;;;;-1:-1:-1;;;49314:91:0;;32952:2:1;49314:91:0;;;32934:21:1;32991:2;32971:18;;;32964:30;-1:-1:-1;;;33010:18:1;;;33003:50;33070:18;;49314:91:0;32750:344:1;49314:91:0;49416:26;;;;:16;:26;;;;;;;;;:40;;;49472:41;;43302:25:1;;;43343:18;;;43336:34;;;49472:41:0;;43275:18:1;49472:41:0;;;;;;;49227:294;49090:431;;;:::o;23618:365::-;23807:41;23826:12;:10;:12::i;:::-;23840:7;23807:18;:41::i;:::-;23785:140;;;;-1:-1:-1;;;23785:140:0;;;;;;;:::i;:::-;23936:39;23950:4;23956:2;23960:7;23969:5;23936:13;:39::i;:::-;23618:365;;;;:::o;91992:400::-;92058:20;92091:28;92122:23;92136:8;92122:13;:23::i;:::-;92091:54;;92156:31;92190:23;92204:8;92190:13;:23::i;:::-;92156:57;;92224:23;92250:45;92273:8;92284:10;92250:15;:45::i;:::-;92313:71;;-1:-1:-1;;;92313:71:0;;92224;;-1:-1:-1;92313:14:0;;:23;;:71;;92337:8;;92347:10;;92224:71;;92368:15;;92313:71;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;92313:71:0;;;;;;;;;;;;:::i;85665:127::-;85724:16;;:::i;:::-;85760;;;;:6;:16;;;;;;;;;85753:31;;;;;;;;;85760:24;;;;85753:31;;;;;;;;85760:24;;85753:31;;;85760:24;;85753:31;;;;;;;;;-1:-1:-1;85753:31:0;;85665:127;-1:-1:-1;;;;;;;85665:127:0:o;102863:381::-;101867:10;-1:-1:-1;;;;;101881:9:0;101867:23;;101859:52;;;;-1:-1:-1;;;101859:52:0;;;;;;;:::i;:::-;102959:19;;:23;;;;:44:::1;;-1:-1:-1::0;102986:13:0;;:17;;102959:44:::1;:65;;;;-1:-1:-1::0;103007:13:0;;:17;;102959:65:::1;:86;;;;-1:-1:-1::0;103028:13:0;;:17;;102959:86:::1;102937:151;;;::::0;-1:-1:-1;;;102937:151:0;;28824:2:1;102937:151:0::1;::::0;::::1;28806:21:1::0;28863:2;28843:18;;;28836:30;-1:-1:-1;;;28882:18:1;;;28875:45;28937:18;;102937:151:0::1;28622:339:1::0;102937:151:0::1;103116:15;103099:14;:32:::0;103142:12:::1;:28:::0;;-1:-1:-1;;;;;103142:28:0;::::1;-1:-1:-1::0;;;;;;103142:28:0;;::::1;;::::0;;103183:22:::1;103194:7;32307::::0;32334:6;-1:-1:-1;;;;;32334:6:0;;32261:87;103194:7:::1;103203:1;103183:10;:22::i;:::-;-1:-1:-1::0;103223:13:0::1;::::0;::::1;::::0;;;::::1;102863:381:::0;:::o;94858:372::-;94917:24;;:::i;:::-;94958:15;;94954:269;;95000:48;:12;95033:11;95046:1;95000:32;:48::i;:::-;94990:58;;95067:11;95082:1;95067:16;95063:149;;;95195:1;95182:7;95195:1;95182:10;;102407:220;101867:10;-1:-1:-1;;;;;101881:9:0;101867:23;;101859:52;;;;-1:-1:-1;;;101859:52:0;;;;;;;:::i;:::-;102514:13;;:18;102506:50:::1;;;;-1:-1:-1::0;;;102506:50:0::1;;;;;;;:::i;:::-;102576:43;102604:5;;102576:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;102611:7:0;;-1:-1:-1;102576:27:0::1;::::0;-1:-1:-1;;102576:43:0:i:1;:::-;102567:52:::0;;;;:6:::1;::::0;:52:::1;::::0;:6;;:52:::1;;::::0;::::1;:::i;39695:466::-:0;39908:20;;39784:4;;-1:-1:-1;;;;;39908:20:0;39958:34;;;;;:87;;-1:-1:-1;40004:28:0;;-1:-1:-1;;;40004:28:0;;-1:-1:-1;;;;;16530:32:1;;;40004:28:0;;;16512:51:1;39996:49:0;;;;40004:21;;;;;;16485:18:1;;40004:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;39996:49:0;;39958:87;39940:155;;;40079:4;40072:11;;;;;39940:155;-1:-1:-1;;;;;22805:25:0;;;22776:4;22805:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;40114:39;40107:46;39695:466;-1:-1:-1;;;;39695:466:0:o;33161:192::-;32492:12;:10;:12::i;:::-;-1:-1:-1;;;;;32481:23:0;:7;32307;32334:6;-1:-1:-1;;;;;32334:6:0;;32261:87;32481:7;-1:-1:-1;;;;;32481:23:0;;32473:68;;;;-1:-1:-1;;;32473:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;33250:22:0;::::1;33242:73;;;::::0;-1:-1:-1;;;33242:73:0;;24046:2:1;33242:73:0::1;::::0;::::1;24028:21:1::0;24085:2;24065:18;;;24058:30;24124:34;24104:18;;;24097:62;-1:-1:-1;;;24175:18:1;;;24168:36;24221:19;;33242:73:0::1;23844:402:1::0;33242:73:0::1;33326:19;33336:8;33326:9;:19::i;:::-;33161:192:::0;:::o;86058:432::-;41316:1;41912:7;;:19;;41904:63;;;;-1:-1:-1;;;41904:63:0;;;;;;;:::i;:::-;41316:1;42045:7;:18;86241:24:::1;86268:19;86278:8:::0;86268:9:::1;:19::i;:::-;86241:46;;86298:24;86325:19;86335:8;86325:9;:19::i;:::-;86363:11:::0;;86298:46;;-1:-1:-1;86363:26:0;::::1;;;-1:-1:-1::0;86378:11:0;;86363:26:::1;86355:67;;;::::0;-1:-1:-1;;;86355:67:0;;34818:2:1;86355:67:0::1;::::0;::::1;34800:21:1::0;34857:2;34837:18;;;34830:30;34896;34876:18;;;34869:58;34944:18;;86355:67:0::1;34616:352:1::0;38436:557:0;38480:22;38519:10;38541:4;38519:27;38515:447;;;38563:18;38584:8;;38563:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;38623:8:0;38812:17;38806:24;-1:-1:-1;;;;;38802:73:0;;-1:-1:-1;38515:447:0;;-1:-1:-1;38515:447:0;;-1:-1:-1;38939:10:0;38515:447;38436:557;:::o;43052:280::-;43134:6;43170:3;:10;;;43161:6;:19;43153:45;;;;-1:-1:-1;;;43153:45:0;;25167:2:1;43153:45:0;;;25149:21:1;25206:2;25186:18;;;25179:30;-1:-1:-1;;;25225:18:1;;;25218:43;25278:18;;43153:45:0;24965:337:1;43153:45:0;43209:11;43223;43232:2;43223:6;:11;:::i;:::-;43209:25;-1:-1:-1;43245:11:0;43259;43268:2;43259:6;:11;:::i;:::-;43245:25;-1:-1:-1;43314:8:0;43245:25;43320:2;43314:8;:::i;:::-;43295:3;:9;;43305:3;43295:14;;;;;;;;:::i;:::-;;;;;;;;;:28;;43281:43;;;;43052:280;;;;:::o;45181:361::-;45297:15;45315:28;45341:1;45328:3;:10;;;:14;;;;:::i;:::-;45315:3;;:12;:28::i;:::-;45297:46;-1:-1:-1;45354:30:0;:3;45367:6;45297:46;45354:12;:30::i;:::-;45522:10;;;:12;;;:10;:12;;;:::i;:::-;;;;;;45253:289;45181:361;;:::o;99299:510::-;99397:15;99430:22;;:::i;:::-;99473:23;99484:11;99473:23;;:10;:23::i;:::-;99523:198;;;;;;;;99556:4;99523:198;;;99463:33;99523:198;;;;;;;;;;;;;;;;;;;;;;99693:15;99523:198;;;;;;99463:33;;;-1:-1:-1;99507:13:0;;;:4;:13;;;;;;;:214;;;;;;;;-1:-1:-1;;99507:214:0;;;;;;-1:-1:-1;;99507:214:0;;;;;;;;;;;;;;;-1:-1:-1;;99507:214:0;;99523:198;99507:214;;;;;;;;;;;;99463:33;;-1:-1:-1;99523:198:0;;99507:13;:214;;;;;;;:::i;:::-;-1:-1:-1;99507:214:0;;;;;;;;;;;;-1:-1:-1;;99507:214:0;;;;;;;;;;;99732:32;99742:12;99756:7;99732:9;:32::i;:::-;99780:21;;21062:25:1;;;99780:21:0;;21050:2:1;21035:18;99780:21:0;;;;;;;99419:390;99299:510;;;;:::o;42550:494::-;-1:-1:-1;;;;;;;;;;;;;;;;;42716:11:0;;42693:20;42753:9;42760:2;42753:4;:9;:::i;:::-;42738:24;-1:-1:-1;42797:8:0;42738:24;42804:1;42797:8;:::i;:::-;42781:12;:24;42773:55;;;;-1:-1:-1;;;42773:55:0;;39122:2:1;42773:55:0;;;39104:21:1;39161:2;39141:18;;;39134:30;-1:-1:-1;;;39180:18:1;;;39173:48;39238:18;;42773:55:0;38920:342:1;42773:55:0;42841:12;42856:9;42863:2;42856:4;:9;:::i;:::-;42841:24;-1:-1:-1;42876:18:0;42920:9;42841:24;42927:2;42920:9;:::i;:::-;42905:4;42910;42905:10;;;;;;;;:::i;:::-;;;;;;;:25;;42876:55;;42950:10;42964:1;42950:15;42942:51;;;;-1:-1:-1;;;42942:51:0;;25851:2:1;42942:51:0;;;25833:21:1;25890:2;25870:18;;;25863:30;25929:25;25909:18;;;25902:53;25972:18;;42942:51:0;25649:347:1;42942:51:0;-1:-1:-1;;43013:23:0;;;;;;;;;;;;-1:-1:-1;;;43013:23:0;;;;;42550:494::o;91152:400::-;91214:17;;:::i;:::-;91244:13;91260:20;91268:11;91260:20;;:7;:20::i;:::-;91311:233;;;;;;;;;-1:-1:-1;;;;;91347:19:0;;91356:10;91347:19;;91311:233;;;;;;;;;;;;;;;;;;;;-1:-1:-1;91461:17:0;;;:4;:17;;;;;91311:233;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;91244:36;;-1:-1:-1;91311:233:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;91311:233:0;;;-1:-1:-1;;;91311:233:0;;;;;;;;;;;;;;;;;;91509:19;;;-1:-1:-1;91509:19:0;;;:6;:19;;;;;;91311:233;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;91311:233:0;;;;;-1:-1:-1;;;91311:233:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;91311:233:0;;;;-1:-1:-1;;;91311:233:0;;-1:-1:-1;91291:253:0;;-1:-1:-1;;;91152:400:0:o;87515:1713::-;87765:16;87814:7;:10;;;87806:19;;87792:7;:10;;;87784:19;;:41;;;;:::i;:::-;87765:60;;87856:5;87844:8;:17;;87836:46;;;;-1:-1:-1;;;87836:46:0;;27375:2:1;87836:46:0;;;27357:21:1;27414:2;27394:18;;;27387:30;-1:-1:-1;;;27433:18:1;;;27426:46;27489:18;;87836:46:0;27173:340:1;87836:46:0;87919:8;87986:18;;;;25595:4;25619:16;;;:7;:16;;;;;;-1:-1:-1;;;;;25619:16:0;:30;;;25530:127;87986:18;87985:19;87977:52;;;;-1:-1:-1;;;87977:52:0;;31829:2:1;87977:52:0;;;31811:21:1;31868:2;31848:18;;;31841:30;-1:-1:-1;;;31887:18:1;;;31880:50;31947:18;;87977:52:0;31627:344:1;87977:52:0;88149:17;88120:7;:17;;;:26;;;:46;;;;;;:::i;:::-;88102:15;:64;:149;;;;;88234:17;88205:7;:17;;;:26;;;:46;;;;;;:::i;:::-;88187:15;:64;88102:149;88080:222;;;;-1:-1:-1;;;88080:222:0;;30414:2:1;88080:222:0;;;30396:21:1;30453:2;30433:18;;;30426:30;30492:25;30472:18;;;30465:53;30535:18;;88080:222:0;30212:347:1;88080:222:0;88396:7;:10;;;88382:24;;:7;:10;;;:24;;;:54;;;;-1:-1:-1;88411:17:0;;;;:25;88410:26;88382:54;88380:57;88358:135;;;;-1:-1:-1;;;88358:135:0;;34113:2:1;88358:135:0;;;34095:21:1;34152:2;34132:18;;;34125:30;34191;34171:18;;;34164:58;34239:18;;88358:135:0;33911:352:1;88358:135:0;88529:10;;;;;88524:16;;;;;;;;:4;:16;;;;;;;:25;;;;:51;;;88559:15;88524:51;-1:-1:-1;;88524:51:0;;;;;;;;88591:10;;;;88586:16;;;;;;;;:25;;;:51;;;;;;;;;88666:295;;;;;;;;;;;;;;88819:17;;;;;:34;;;88765:17;;;;:34;;;88666:295;;;;;88765:88;;88819:34;88765:88;:::i;:::-;88666:295;;;;;;;;;;;;;;88878:10;;;;88666:295;;;;;;88890:10;;;;88666:295;;;;;;;;;;;;;;;;;88933:15;88666:295;;;;;;;;;88648:15;;;-1:-1:-1;88648:15:0;;;:4;:15;;;;;:313;;;;;;;;;;;;-1:-1:-1;;88648:313:0;;;;;;-1:-1:-1;;88648:313:0;;;;;;;;;;;;;;;-1:-1:-1;;88648:313:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;88648:313:0;;;;;:::i;:::-;-1:-1:-1;88648:313:0;;;;;;;;;;;;-1:-1:-1;;88648:313:0;;;;;;;;;;;88972:32;88982:10;88972:32;;;:9;:32::i;:::-;89019:15;;89015:102;;89051:54;89068:9;89051:54;;89079:11;89092:12;89051:16;:54::i;:::-;89127:36;89146:7;89155;89127:18;:36::i;:::-;89197:10;;;;;89209;;;;89181:39;;41398:6:1;41431:15;;;41413:34;;41483:15;;;41478:2;41463:18;;41456:43;41535:15;;41515:18;;;41508:43;;;;89181:39:0;;41376:2:1;41361:18;89181:39:0;41190:367:1;40305:120:0;40359:14;40393:24;:22;:24::i;:::-;40386:31;;40305:120;:::o;29579:174::-;29654:24;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;29654:29:0;-1:-1:-1;;;;;29654:29:0;;;;;;;;:24;;29708:23;29654:24;29708:14;:23::i;:::-;-1:-1:-1;;;;;29699:46:0;;;;;;;;;;;29579:174;;:::o;38001:390::-;38179:4;-1:-1:-1;;;;;38204:20:0;;38196:70;;;;-1:-1:-1;;;38196:70:0;;28418:2:1;38196:70:0;;;28400:21:1;28457:2;28437:18;;;28430:30;28496:34;28476:18;;;28469:62;-1:-1:-1;;;28547:18:1;;;28540:35;28592:19;;38196:70:0;28216:401:1;38196:70:0;38307:76;38317:47;38336:27;38356:6;38336:19;:27::i;:::-;38317:18;:47::i;:::-;38307:76;;;;;;;;;;;;21747:25:1;;;;21820:4;21808:17;;21788:18;;;21781:45;21842:18;;;21835:34;;;21885:18;;;21878:34;;;21719:19;;38307:76:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;38297:86:0;:6;-1:-1:-1;;;;;38297:86:0;;38277:106;;38001:390;;;;;;;:::o;99817:1012::-;83195:8;100039:14;;:38;;;;:::i;:::-;100021:15;:56;100017:805;;;100119:52;;-1:-1:-1;;;;;;100136:10:0;14607:2:1;14603:15;14599:53;100119:52:0;;;14587:66:1;14669:12;;;14662:28;;;14706:12;;;14699:28;;;100094:12:0;;14743::1;;100119:52:0;;;;;;;;;;;;100109:63;;;;;;100094:78;;100213:57;100232:12;100246:17;;100265:4;100213:18;:57::i;:::-;100187:139;;;;-1:-1:-1;;;100187:139:0;;32952:2:1;100187:139:0;;;32934:21:1;32991:2;32971:18;;;32964:30;-1:-1:-1;;;33010:18:1;;;33003:50;33070:18;;100187:139:0;32750:344:1;100187:139:0;100343:16;100476:6;100381:13;;:71;;100432:10;100426:17;;;;:5;:17;;;;;:26;;;;;;100381:71;;;100403:10;100397:17;;;;:5;:17;;;;;:26;;;100381:71;100362:121;;;;:::i;:::-;100343:140;-1:-1:-1;100504:13:0;100500:311;;100560:10;100546;:24;;;;100538:50;;;;-1:-1:-1;;;100538:50:0;;25509:2:1;100538:50:0;;;25491:21:1;25548:2;25528:18;;;25521:30;-1:-1:-1;;;25567:18:1;;;25560:43;25620:18;;100538:50:0;25307:337:1;100538:50:0;100613:10;100607:17;;;;:5;:17;;;;;:39;;-1:-1:-1;;100607:39:0;;;;;;;100500:311;;;100709:10;100695;:24;;;;100687:50;;;;-1:-1:-1;;;100687:50:0;;25509:2:1;100687:50:0;;;25491:21:1;25548:2;25528:18;;;25521:30;-1:-1:-1;;;25567:18:1;;;25560:43;25620:18;;100687:50:0;25307:337:1;100687:50:0;100762:10;100756:17;;;;:5;:17;;;;;:39;;-1:-1:-1;;100756:39:0;;;;;;;;;100500:311;100079:743;;100017:805;99817:1012;;;;;:::o;98607:684::-;98664:12;98679:7;:5;:7::i;:::-;98664:22;-1:-1:-1;98697:17:0;98729:13;98725:512;;98780:13;;98759:11;;98773:20;;:4;:20;:::i;:::-;98759:34;-1:-1:-1;98821:20:0;:6;98759:34;98821:15;:20::i;:::-;98808:33;-1:-1:-1;98856:24:0;:6;98876:3;98856:19;:24::i;:::-;98895:42;98913:8;98923:6;:13;;;98895:17;:42::i;:::-;98744:205;98725:512;;;98959:8;98971:1;98959:13;98955:282;;;99010:13;;98989:11;;99003:20;;:4;:20;:::i;:::-;98989:34;-1:-1:-1;99051:20:0;:6;98989:34;99051:15;:20::i;:::-;99038:33;-1:-1:-1;99086:24:0;:6;99106:3;99086:19;:24::i;:::-;99125:42;99143:8;99153:6;:13;;;99125:17;:42::i;98955:282::-;99200:25;;-1:-1:-1;;;99200:25:0;;35175:2:1;99200:25:0;;;35157:21:1;35214:2;35194:18;;;35187:30;-1:-1:-1;;;35233:18:1;;;35226:45;35288:18;;99200:25:0;34973:339:1;98955:282:0;99249:34;99260:10;99272;99249;:34::i;25824:415::-;25953:4;25619:16;;;:7;:16;;;;;;-1:-1:-1;;;;;25619:16:0;25975:73;;;;-1:-1:-1;;;25975:73:0;;26962:2:1;25975:73:0;;;26944:21:1;27001:2;26981:18;;;26974:30;27040:34;27020:18;;;27013:62;-1:-1:-1;;;27091:18:1;;;27084:42;27143:19;;25975:73:0;26760:408:1;25975:73:0;26059:13;26075:23;26090:7;26075:14;:23::i;:::-;26059:39;;26128:5;-1:-1:-1;;;;;26117:16:0;:7;-1:-1:-1;;;;;26117:16:0;;:64;;;;26174:7;-1:-1:-1;;;;;26150:31:0;:20;26162:7;26150:11;:20::i;:::-;-1:-1:-1;;;;;26150:31:0;;26117:64;:113;;;;26198:32;26215:5;26222:7;26198:16;:32::i;28883:578::-;29042:4;-1:-1:-1;;;;;29015:31:0;:23;29030:7;29015:14;:23::i;:::-;-1:-1:-1;;;;;29015:31:0;;29007:85;;;;-1:-1:-1;;;29007:85:0;;33301:2:1;29007:85:0;;;33283:21:1;33340:2;33320:18;;;33313:30;33379:34;33359:18;;;33352:62;-1:-1:-1;;;33430:18:1;;;33423:39;33479:19;;29007:85:0;33099:405:1;29007:85:0;-1:-1:-1;;;;;29111:16:0;;29103:65;;;;-1:-1:-1;;;29103:65:0;;26203:2:1;29103:65:0;;;26185:21:1;26242:2;26222:18;;;26215:30;26281:34;26261:18;;;26254:62;-1:-1:-1;;;26332:18:1;;;26325:34;26376:19;;29103:65:0;26001:400:1;29103:65:0;29181:39;29202:4;29208:2;29212:7;29181:20;:39::i;:::-;29285:29;29302:1;29306:7;29285:8;:29::i;:::-;-1:-1:-1;;;;;29327:15:0;;;;;;:9;:15;;;;;:20;;29346:1;;29327:15;:20;;29346:1;;29327:20;:::i;:::-;;;;-1:-1:-1;;;;;;;29358:13:0;;;;;;:9;:13;;;;;:18;;29375:1;;29358:13;:18;;29375:1;;29358:18;:::i;:::-;;;;-1:-1:-1;;29387:16:0;;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;29387:21:0;-1:-1:-1;;;;;29387:21:0;;;;;;;;;29426:27;;29387:16;;29426:27;;;;;;;28883:578;;;:::o;43340:1312::-;43487:21;;:::i;:::-;43521:15;43539:25;:3;43552:11;43539:12;:25::i;:::-;43521:43;;43617:6;43605:18;;:8;:18;;;;:37;;;;;43641:1;43627:11;:15;43605:37;43601:570;;;43676:8;43659:14;43717:15;43731:1;43717:11;:15;:::i;:::-;43699:33;-1:-1:-1;43747:13:0;43763:17;43774:6;43763:8;:17;:::i;:::-;43747:33;;43797:363;43815:6;43804:17;;:7;:17;;;43797:363;;43852:21;:3;43865:7;43852:12;:21::i;:::-;43842:31;;43907:6;43896:17;;:7;:17;;;43892:111;;;43938:17;;;;;43978:5;;43892:111;44025:12;44021:124;;44062:5;;44021:124;44116:9;;;;:::i;:::-;;;;43797:363;;;43644:527;;;43601:570;44239:8;44222:14;44280:15;:11;44294:1;44280:15;:::i;:::-;44262:33;-1:-1:-1;44310:13:0;44326:17;44337:6;44326:8;:17;:::i;:::-;44310:33;;44360:274;44378:6;44367:17;;:7;:17;;;44360:274;;44420:3;:10;;;44409:7;:21;44405:32;;44432:5;;44405:32;44466:23;44479:9;;;;:::i;:::-;;-1:-1:-1;44466:3:0;;:12;:23::i;:::-;44456:33;;44523:6;44512:17;;:7;:17;;;44508:111;;;44554:17;;;:7;;;:17;44594:5;;44508:111;44360:274;;;44181:464;;;43510:1142;43340:1312;;;;;:::o;33361:173::-;33417:16;33436:6;;-1:-1:-1;;;;;33453:17:0;;;-1:-1:-1;;;;;;33453:17:0;;;;;;33486:40;;33436:6;;;;;;;33486:40;;33417:16;33486:40;33406:128;33361:173;:::o;92667:873::-;92823:13;;92778:23;;92819:714;;;92863:15;;;92876:1;92863:15;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;92863:15:0;92853:25;;92906:8;92893:7;92901:1;92893:10;;;;;;;;:::i;:::-;;;;;;:21;;;;;;;;;;;92819:714;;;92992:13;;;;:16;;92947:30;;92980:53;;92992:16;93010:4;;92947:30;;;93015:16;;;;;;;;;;93010:22;;;;;;;;;;;;;;;;;-1:-1:-1;93010:22:0;92980:53;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;93010:22;92980:53;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;92980:53:0;;;-1:-1:-1;;;92980:53:0;;;;;;;;;;;;;:11;:53::i;:::-;93063:21;;93144:13;;;;:16;;;;93063:21;;-1:-1:-1;93063:21:0;;93048:12;;93132:53;;93144:16;93162:4;;93048:12;;93158:1;93167:16;;93132:53;93215:21;;93099:86;;-1:-1:-1;93274:11:0;93215:21;93274:4;:11;:::i;:::-;-1:-1:-1;;;;;93261:25:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;93261:25:0;;93251:35;;93306:9;93301:100;93325:4;93321:1;:8;93301:100;;;93368:14;93383:1;93368:17;;;;;;;;:::i;:::-;;;;;;;93355:7;93363:1;93355:10;;;;;;;;:::i;:::-;:30;;;;:10;;;;;;;;;;;:30;93331:3;;;;:::i;:::-;;;;93301:100;;;;93420:9;93415:107;93439:4;93435:1;:8;93415:107;;;93489:14;93504:1;93489:17;;;;;;;;:::i;:::-;;;;;;;93469:7;93484:1;93477:4;:8;;;;:::i;:::-;93469:17;;;;;;;;:::i;:::-;:37;;;;:17;;;;;;;;;;;:37;93445:3;;;;:::i;:::-;;;;93415:107;;;;92932:601;;;;92667:873;;;;:::o;93548:541::-;93658:11;;93613:15;;93697:1;93680:380;93704:6;93700:1;:10;93680:380;;;93732:10;93745:4;93750:1;93745:7;;;;;;;;:::i;:::-;;;;;;;93732:20;;93767:9;93783:1;93779;:5;;;;:::i;:::-;93767:17;;93799:174;93820:1;93814;93807:14;;93806:35;;;;;93837:3;93827:13;;:4;93832:1;93827:7;;;;;;;;:::i;:::-;;;;;;;:13;;;93806:35;93799:174;;;93876:4;93881:1;93876:7;;;;;;;;:::i;:::-;;;;;;;93862:4;93867:1;93871;93867:5;;;;:::i;:::-;93862:11;;;;;;;;:::i;:::-;:21;;;;:11;;;;;;;;;;;:21;-1:-1:-1;;93935:3:0;93799:174;;;94030:3;94016:4;94021:1;94025;94021:5;94016:11;;;;;;;;:::i;:::-;;;;;;:17;;;;;;;;;;;93717:343;;93712:3;;;;;:::i;:::-;;;;93680:380;;;-1:-1:-1;94077:4:0;;93548:541;-1:-1:-1;;93548:541:0:o;45910:830::-;46035:4;46075;46035;46092:525;46116:5;:12;46112:1;:16;46092:525;;;46150:20;46173:5;46179:1;46173:8;;;;;;;;:::i;:::-;;;;;;;46150:31;;46218:12;46202;:28;46198:408;;46355:44;;;;;;14923:19:1;;;14958:12;;;14951:28;;;14995:12;;46355:44:0;;;;;;;;;;;;46345:55;;;;;;46330:70;;46198:408;;;46545:44;;;;;;14923:19:1;;;14958:12;;;14951:28;;;14995:12;;46545:44:0;;;;;;;;;;;;46535:55;;;;;;46520:70;;46198:408;-1:-1:-1;46130:3:0;;;;:::i;:::-;;;;46092:525;;;-1:-1:-1;46712:20:0;;;;45910:830;-1:-1:-1;;;45910:830:0:o;24865:352::-;25022:28;25032:4;25038:2;25042:7;25022:9;:28::i;:::-;25083:48;25106:4;25112:2;25116:7;25125:5;25083:22;:48::i;:::-;25061:148;;;;-1:-1:-1;;;25061:148:0;;;;;;;:::i;44660:513::-;44788:11;44802;44811:2;44802:6;:11;:::i;:::-;44788:25;-1:-1:-1;44824:11:0;44838;44847:2;44838:6;:11;:::i;:::-;44824:25;-1:-1:-1;44915:12:0;44959:8;44824:25;44965:2;44959:8;:::i;:::-;44948:5;44940:28;;44938:31;44915:55;;44981:14;45015:4;44998:3;:9;;45008:3;44998:14;;;;;;;;:::i;:::-;;;;;;;;;:21;44981:38;;45115:3;45121:2;45115:8;;;;:::i;:::-;45103:6;45095:15;;:29;;45088:36;;45161:4;45152:6;:13;45135:3;:9;;45145:3;45135:14;;;;;;;;:::i;:::-;;;;;;;;;;:30;-1:-1:-1;;;;;;;44660:513:0:o;26581:110::-;26657:26;26667:2;26671:7;26657:26;;;;;;;;;;;;:9;:26::i;:::-;26581:110;;:::o;89236:730::-;89375:17;;;;:25;:54;;;;-1:-1:-1;89404:17:0;;;;:25;89375:54;89371:67;;;89236:730;;:::o;89371:67::-;89475:17;;;;:25;89471:488;;;89525:12;;89517:49;;;;-1:-1:-1;;;89517:49:0;;;;;;;:::i;:::-;89581:17;89587:7;:10;;;89581:17;;:5;:17::i;89471:488::-;89620:17;;;;:25;89616:343;;;89670:12;;89662:49;;;;-1:-1:-1;;;89662:49:0;;;;;;;:::i;:::-;89726:17;89732:7;:10;;;89726:17;;:5;:17::i;89616:343::-;89826:12;;:28;;;;-1:-1:-1;89842:12:0;;89826:28;89818:65;;;;-1:-1:-1;;;89818:65:0;;;;;;;:::i;:::-;89898:17;89904:7;:10;;;89898:17;;:5;:17::i;37500:378::-;37583:7;35818:76;;;;;;;;;;;;;;;;;35808:87;;;;;;;37732:12;;37767:11;;;;37811:24;;;;;37801:35;;;;;;37651:204;;;;;21329:25:1;;;21385:2;21370:18;;21363:34;;;;-1:-1:-1;;;;;21433:32:1;21428:2;21413:18;;21406:60;21497:2;21482:18;;21475:34;21316:3;21301:19;;21098:417;37651:204:0;;;;;;;;;;;;;37623:247;;;;;;37603:267;;37500:378;;;:::o;35506:181::-;35578:7;35644:20;34945:15;;;34867:101;35644:20;35615:63;;-1:-1:-1;;;35615:63:0;;;15975:27:1;16018:11;;;16011:27;;;;16054:12;;;16047:28;;;16091:12;;35615:63:0;15717:392:1;101051:637:0;101119:5;:7;;101094:12;;;101119:7;;;:::i;:::-;;;;-1:-1:-1;;101515:28:0;;-1:-1:-1;;;;;;101532:10:0;14067:2:1;14063:15;14059:53;101515:28:0;;;14047:66:1;101595:12:0;;101550:15;;14129:12:1;;101515:28:0;;;;;;;;;;;;101505:39;;;;;;101497:48;;101496:70;;;;:::i;:::-;101340:32;;-1:-1:-1;;;;;;101357:14:0;14067:2:1;14063:15;14059:53;101340:32:0;;;14047:66:1;101453:14:0;;101408:15;;14129:12:1;;101340:32:0;;;;;;;;;;;;101330:43;;;;;;101322:52;;101321:103;;;;:::i;:::-;101233:59;101276:16;101233:15;:59;:::i;:::-;:192;;;;:::i;:::-;:234;;;;:::i;:::-;:334;;;;:::i;:::-;:374;;;;:::i;:::-;101630:5;;101194:460;;;;;;14923:19:1;;;;14958:12;;14951:28;14995:12;;101194:460:0;;;;;;;;;;;;101166:503;;;;;;101144:536;;101137:543;;101051:637;:::o;100837:206::-;100920:9;100916:120;;100963:15;100946:14;:32;100998:26;101011:12;:8;101022:1;101011:12;:::i;:::-;100998:26;;21062:25:1;;;21050:2;21035:18;100998:26:0;20916:177:1;91560:298:0;91760:23;;:::i;:::-;91812:38;;;;;;;;-1:-1:-1;91812:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;91794:15;;;:6;:15;;;;;;;:56;;;;;;;;;;91812:38;91794:56;-1:-1:-1;;;91794:56:0;-1:-1:-1;;;;;;;;;91794:56:0;;;;;;;;;;-1:-1:-1;;;;;;91794:56:0;;;;;-1:-1:-1;;91794:56:0;;;;;;;-1:-1:-1;;91794:56:0;;;;;;;;;;;;;;;;;;;;;91812:38;;91794:15;:56;;91812:38;91794:56;;;;;:::i;30318:835::-;30473:4;-1:-1:-1;;;;;30494:13:0;;7970:20;8018:8;30490:656;;30546:2;-1:-1:-1;;;;;30530:36:0;;30567:12;:10;:12::i;:::-;30581:4;30587:7;30596:5;30530:72;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;30530:72:0;;;;;;;;-1:-1:-1;;30530:72:0;;;;;;;;;;;;:::i;:::-;;;30526:565;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;30808:13:0;;30804:272;;30851:60;;-1:-1:-1;;;30851:60:0;;;;;;;:::i;30804:272::-;31026:6;31020:13;31011:6;31007:2;31003:15;30996:38;30526:565;-1:-1:-1;;;;;;30685:55:0;-1:-1:-1;;;30685:55:0;;-1:-1:-1;30678:62:0;;30490:656;-1:-1:-1;31130:4:0;30318:835;;;;;;:::o;26918:321::-;27048:18;27054:2;27058:7;27048:5;:18::i;:::-;27099:54;27130:1;27134:2;27138:7;27147:5;27099:22;:54::i;:::-;27077:154;;;;-1:-1:-1;;;27077:154:0;;;;;;;:::i;28186:360::-;28246:13;28262:23;28277:7;28262:14;:23::i;:::-;28246:39;;28298:48;28319:5;28334:1;28338:7;28298:20;:48::i;:::-;28387:29;28404:1;28408:7;28387:8;:29::i;:::-;-1:-1:-1;;;;;28429:16:0;;;;;;:9;:16;;;;;:21;;28449:1;;28429:16;:21;;28449:1;;28429:21;:::i;:::-;;;;-1:-1:-1;;28468:16:0;;;;:7;:16;;;;;;28461:23;;-1:-1:-1;;;;;;28461:23:0;;;28502:36;28476:7;;28468:16;-1:-1:-1;;;;;28502:36:0;;;;;28468:16;;28502:36;28235:311;28186:360;:::o;27575:382::-;-1:-1:-1;;;;;27655:16:0;;27647:61;;;;-1:-1:-1;;;27647:61:0;;30766:2:1;27647:61:0;;;30748:21:1;;;30785:18;;;30778:30;30844:34;30824:18;;;30817:62;30896:18;;27647:61:0;30564:356:1;27647:61:0;25595:4;25619:16;;;:7;:16;;;;;;-1:-1:-1;;;;;25619:16:0;:30;27719:58;;;;-1:-1:-1;;;27719:58:0;;24810:2:1;27719:58:0;;;24792:21:1;24849:2;24829:18;;;24822:30;24888;24868:18;;;24861:58;24936:18;;27719:58:0;24608:352:1;27719:58:0;27790:45;27819:1;27823:2;27827:7;27790:20;:45::i;:::-;-1:-1:-1;;;;;27848:13:0;;;;;;:9;:13;;;;;:18;;27865:1;;27848:13;:18;;27865:1;;27848:18;:::i;:::-;;;;-1:-1:-1;;27877:16:0;;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;27877:21:0;-1:-1:-1;;;;;27877:21:0;;;;;;;;27916:33;;27877:16;;;27916:33;;27877:16;;27916:33;27575:382;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;14:673:1:-;68:5;121:3;114:4;106:6;102:17;98:27;88:55;;139:1;136;129:12;88:55;175:6;162:20;201:4;225:60;241:43;281:2;241:43;:::i;:::-;225:60;:::i;:::-;307:3;331:2;326:3;319:15;359:2;354:3;350:12;343:19;;394:2;386:6;382:15;446:3;441:2;435;432:1;428:10;420:6;416:23;412:32;409:41;406:61;;;463:1;460;453:12;406:61;485:1;495:163;509:2;506:1;503:9;495:163;;;566:17;;554:30;;604:12;;;;636;;;;527:1;520:9;495:163;;;-1:-1:-1;676:5:1;;14:673;-1:-1:-1;;;;;;;14:673:1:o;692:686::-;741:5;794:3;787:4;779:6;775:17;771:27;761:55;;812:1;809;802:12;761:55;845:2;839:9;887:2;879:6;875:15;956:6;944:10;941:22;-1:-1:-1;;;;;908:10:1;905:34;902:62;899:88;;;967:18;;:::i;:::-;1007:10;1003:2;996:22;;1038:6;1064;1102:3;1097:2;1089:6;1085:15;1082:24;1079:44;;;1119:1;1116;1109:12;1079:44;1141:1;1151:197;1165:4;1162:1;1159:11;1151:197;;;1224:22;1242:3;1224:22;:::i;:::-;1212:35;;1270:4;1294:12;;;;1326;;;;;1185:1;1178:9;1151:197;;;-1:-1:-1;1366:6:1;;692:686;-1:-1:-1;;;;;692:686:1:o;1383:160::-;1448:20;;1504:13;;1497:21;1487:32;;1477:60;;1533:1;1530;1523:12;1548:462;1590:5;1643:3;1636:4;1628:6;1624:17;1620:27;1610:55;;1661:1;1658;1651:12;1610:55;1697:6;1684:20;1728:48;1744:31;1772:2;1744:31;:::i;1728:48::-;1801:2;1792:7;1785:19;1847:3;1840:4;1835:2;1827:6;1823:15;1819:26;1816:35;1813:55;;;1864:1;1861;1854:12;1813:55;1929:2;1922:4;1914:6;1910:17;1903:4;1894:7;1890:18;1877:55;1977:1;1952:16;;;1970:4;1948:27;1941:38;;;;1956:7;1548:462;-1:-1:-1;;;1548:462:1:o;2015:591::-;2071:5;2119:4;2107:9;2102:3;2098:19;2094:30;2091:50;;;2137:1;2134;2127:12;2091:50;2170:2;2164:9;2212:4;2204:6;2200:17;2283:6;2271:10;2268:22;-1:-1:-1;;;;;2235:10:1;2232:34;2229:62;2226:88;;;2294:18;;:::i;:::-;2330:2;2323:22;2363:6;-1:-1:-1;2363:6:1;2393:39;2428:3;2417:9;2393:39;:::i;:::-;2385:6;2378:55;2468:48;2512:3;2507:2;2496:9;2492:18;2468:48;:::i;:::-;2461:4;2453:6;2449:17;2442:75;2550:49;2595:3;2589;2578:9;2574:19;2550:49;:::i;:::-;2545:2;2537:6;2533:15;2526:74;;2015:591;;;;:::o;2611:159::-;2678:20;;2738:6;2727:18;;2717:29;;2707:57;;2760:1;2757;2750:12;2775:163;2842:20;;2902:10;2891:22;;2881:33;;2871:61;;2928:1;2925;2918:12;2943:156;3009:20;;3069:4;3058:16;;3048:27;;3038:55;;3089:1;3086;3079:12;3104:247;3163:6;3216:2;3204:9;3195:7;3191:23;3187:32;3184:52;;;3232:1;3229;3222:12;3184:52;3271:9;3258:23;3290:31;3315:5;3290:31;:::i;3356:388::-;3424:6;3432;3485:2;3473:9;3464:7;3460:23;3456:32;3453:52;;;3501:1;3498;3491:12;3453:52;3540:9;3527:23;3559:31;3584:5;3559:31;:::i;:::-;3609:5;-1:-1:-1;3666:2:1;3651:18;;3638:32;3679:33;3638:32;3679:33;:::i;:::-;3731:7;3721:17;;;3356:388;;;;;:::o;3749:456::-;3826:6;3834;3842;3895:2;3883:9;3874:7;3870:23;3866:32;3863:52;;;3911:1;3908;3901:12;3863:52;3950:9;3937:23;3969:31;3994:5;3969:31;:::i;:::-;4019:5;-1:-1:-1;4076:2:1;4061:18;;4048:32;4089:33;4048:32;4089:33;:::i;:::-;3749:456;;4141:7;;-1:-1:-1;;;4195:2:1;4180:18;;;;4167:32;;3749:456::o;4210:665::-;4305:6;4313;4321;4329;4382:3;4370:9;4361:7;4357:23;4353:33;4350:53;;;4399:1;4396;4389:12;4350:53;4438:9;4425:23;4457:31;4482:5;4457:31;:::i;:::-;4507:5;-1:-1:-1;4564:2:1;4549:18;;4536:32;4577:33;4536:32;4577:33;:::i;:::-;4629:7;-1:-1:-1;4683:2:1;4668:18;;4655:32;;-1:-1:-1;4738:2:1;4723:18;;4710:32;-1:-1:-1;;;;;4754:30:1;;4751:50;;;4797:1;4794;4787:12;4751:50;4820:49;4861:7;4852:6;4841:9;4837:22;4820:49;:::i;:::-;4810:59;;;4210:665;;;;;;;:::o;4880:315::-;4945:6;4953;5006:2;4994:9;4985:7;4981:23;4977:32;4974:52;;;5022:1;5019;5012:12;4974:52;5061:9;5048:23;5080:31;5105:5;5080:31;:::i;:::-;5130:5;-1:-1:-1;5154:35:1;5185:2;5170:18;;5154:35;:::i;:::-;5144:45;;4880:315;;;;;:::o;5200:663::-;5302:6;5310;5318;5326;5334;5387:3;5375:9;5366:7;5362:23;5358:33;5355:53;;;5404:1;5401;5394:12;5355:53;5443:9;5430:23;5462:31;5487:5;5462:31;:::i;:::-;5512:5;-1:-1:-1;5568:2:1;5553:18;;5540:32;-1:-1:-1;;;;;5584:30:1;;5581:50;;;5627:1;5624;5617:12;5581:50;5650:49;5691:7;5682:6;5671:9;5667:22;5650:49;:::i;:::-;5640:59;;;5746:2;5735:9;5731:18;5718:32;5708:42;;5797:2;5786:9;5782:18;5769:32;5759:42;;5820:37;5852:3;5841:9;5837:19;5820:37;:::i;:::-;5810:47;;5200:663;;;;;;;;:::o;5868:315::-;5936:6;5944;5997:2;5985:9;5976:7;5972:23;5968:32;5965:52;;;6013:1;6010;6003:12;5965:52;6052:9;6039:23;6071:31;6096:5;6071:31;:::i;:::-;6121:5;6173:2;6158:18;;;;6145:32;;-1:-1:-1;;;5868:315:1:o;6188:689::-;6283:6;6291;6299;6352:2;6340:9;6331:7;6327:23;6323:32;6320:52;;;6368:1;6365;6358:12;6320:52;6408:9;6395:23;-1:-1:-1;;;;;6478:2:1;6470:6;6467:14;6464:34;;;6494:1;6491;6484:12;6464:34;6532:6;6521:9;6517:22;6507:32;;6577:7;6570:4;6566:2;6562:13;6558:27;6548:55;;6599:1;6596;6589:12;6548:55;6639:2;6626:16;6665:2;6657:6;6654:14;6651:34;;;6681:1;6678;6671:12;6651:34;6736:7;6729:4;6719:6;6716:1;6712:14;6708:2;6704:23;6700:34;6697:47;6694:67;;;6757:1;6754;6747:12;6694:67;6788:4;6780:13;;;;6812:6;;-1:-1:-1;6850:20:1;;;;6837:34;;6188:689;-1:-1:-1;;;;6188:689:1:o;6882:245::-;6940:6;6993:2;6981:9;6972:7;6968:23;6964:32;6961:52;;;7009:1;7006;6999:12;6961:52;7048:9;7035:23;7067:30;7091:5;7067:30;:::i;7132:249::-;7201:6;7254:2;7242:9;7233:7;7229:23;7225:32;7222:52;;;7270:1;7267;7260:12;7222:52;7302:9;7296:16;7321:30;7345:5;7321:30;:::i;7386:280::-;7485:6;7538:2;7526:9;7517:7;7513:23;7509:32;7506:52;;;7554:1;7551;7544:12;7506:52;7586:9;7580:16;7605:31;7630:5;7605:31;:::i;7671:635::-;7751:6;7804:2;7792:9;7783:7;7779:23;7775:32;7772:52;;;7820:1;7817;7810:12;7772:52;7853:9;7847:16;-1:-1:-1;;;;;7878:6:1;7875:30;7872:50;;;7918:1;7915;7908:12;7872:50;7941:22;;7994:4;7986:13;;7982:27;-1:-1:-1;7972:55:1;;8023:1;8020;8013:12;7972:55;8052:2;8046:9;8077:48;8093:31;8121:2;8093:31;:::i;8077:48::-;8148:2;8141:5;8134:17;8188:7;8183:2;8178;8174;8170:11;8166:20;8163:33;8160:53;;;8209:1;8206;8199:12;8160:53;8222:54;8273:2;8268;8261:5;8257:14;8252:2;8248;8244:11;8222:54;:::i;8311:184::-;8369:6;8422:2;8410:9;8401:7;8397:23;8393:32;8390:52;;;8438:1;8435;8428:12;8390:52;8461:28;8479:9;8461:28;:::i;8500:978::-;8595:6;8603;8647:9;8638:7;8634:23;8677:3;8673:2;8669:12;8666:32;;;8694:1;8691;8684:12;8666:32;8717:28;8735:9;8717:28;:::i;:::-;8707:38;-1:-1:-1;;;8764:16:1;8800:6;8792:15;;8789:35;;;8820:1;8817;8810:12;8789:35;8846:22;;:::i;:::-;8888:4;8884:2;8880:13;8877:33;;;8906:1;8903;8896:12;8877:33;8934:22;;:::i;:::-;8919:37;;8981:35;9012:2;9001:9;8997:18;8981:35;:::i;:::-;8972:7;8965:52;9051:39;9084:4;9073:9;9069:20;9051:39;:::i;:::-;9046:2;9037:7;9033:16;9026:65;9127:36;9159:2;9148:9;9144:18;9127:36;:::i;:::-;9120:4;9111:7;9107:18;9100:64;9198:53;9243:7;9237:3;9226:9;9222:19;9198:53;:::i;:::-;9193:2;9184:7;9180:16;9173:79;9287:39;9320:4;9309:9;9305:20;9287:39;:::i;:::-;9281:3;9272:7;9268:17;9261:66;9350:7;9343:5;9336:22;9390:57;9439:7;9433:3;9422:9;9418:19;9390:57;:::i;:::-;9385:2;9378:5;9374:14;9367:81;9467:5;9457:15;;;;8500:978;;;;;:::o;9483:561::-;9592:6;9600;9608;9616;9669:3;9657:9;9648:7;9644:23;9640:33;9637:53;;;9686:1;9683;9676:12;9637:53;9709:28;9727:9;9709:28;:::i;:::-;9699:38;;9756:37;9789:2;9778:9;9774:18;9756:37;:::i;:::-;9746:47;;9840:2;9829:9;9825:18;9812:32;9802:42;;9895:2;9884:9;9880:18;9867:32;-1:-1:-1;;;;;9914:6:1;9911:30;9908:50;;;9954:1;9951;9944:12;9908:50;9977:61;10030:7;10021:6;10010:9;10006:22;9977:61;:::i;10049:1231::-;10156:6;10164;10172;10180;10233:3;10221:9;10212:7;10208:23;10204:33;10201:53;;;10250:1;10247;10240:12;10201:53;10273:28;10291:9;10273:28;:::i;:::-;10263:38;;10320:2;10372;10361:9;10357:18;10344:32;-1:-1:-1;;;;;10409:5:1;10405:38;10398:5;10395:49;10385:77;;10458:1;10455;10448:12;10385:77;10481:5;-1:-1:-1;10505:37:1;10538:2;10523:18;;10505:37;:::i;:::-;10495:47;;10593:2;10582:9;10578:18;10565:32;-1:-1:-1;;;;;10612:6:1;10609:30;10606:50;;;10652:1;10649;10642:12;10606:50;10675:22;;10728:4;10720:13;;10716:27;-1:-1:-1;10706:55:1;;10757:1;10754;10747:12;10706:55;10793:2;10780:16;10816:60;10832:43;10872:2;10832:43;:::i;10816:60::-;10898:3;10922:2;10917:3;10910:15;10950:2;10945:3;10941:12;10934:19;;10981:2;10977;10973:11;11029:7;11024:2;11018;11015:1;11011:10;11007:2;11003:19;10999:28;10996:41;10993:61;;;11050:1;11047;11040:12;10993:61;11072:1;11063:10;;11082:168;11096:2;11093:1;11090:9;11082:168;;;11153:22;11171:3;11153:22;:::i;:::-;11141:35;;11114:1;11107:9;;;;;11196:12;;;;11228;;11082:168;;;-1:-1:-1;10049:1231:1;;;;-1:-1:-1;10049:1231:1;;-1:-1:-1;;;;;;10049:1231:1:o;11285:180::-;11344:6;11397:2;11385:9;11376:7;11372:23;11368:32;11365:52;;;11413:1;11410;11403:12;11365:52;-1:-1:-1;11436:23:1;;11285:180;-1:-1:-1;11285:180:1:o;11470:484::-;11572:6;11580;11588;11641:2;11629:9;11620:7;11616:23;11612:32;11609:52;;;11657:1;11654;11647:12;11609:52;11693:9;11680:23;11670:33;;11750:2;11739:9;11735:18;11722:32;11712:42;;11805:2;11794:9;11790:18;11777:32;-1:-1:-1;;;;;11824:6:1;11821:30;11818:50;;;11864:1;11861;11854:12;11818:50;11887:61;11940:7;11931:6;11920:9;11916:22;11887:61;:::i;:::-;11877:71;;;11470:484;;;;;:::o;11959:553::-;12070:6;12078;12086;12094;12147:3;12135:9;12126:7;12122:23;12118:33;12115:53;;;12164:1;12161;12154:12;12115:53;12200:9;12187:23;12177:33;;12257:2;12246:9;12242:18;12229:32;12219:42;;12308:2;12297:9;12293:18;12280:32;12270:42;;12363:2;12352:9;12348:18;12335:32;-1:-1:-1;;;;;12382:6:1;12379:30;12376:50;;;12422:1;12419;12412:12;12517:339;12607:5;12630:1;12640:210;12654:4;12651:1;12648:11;12640:210;;;12727:13;;12720:21;12713:29;12701:42;;12766:4;12790:12;;;;12825:15;;;;12674:1;12667:9;12640:210;;12861:338;12953:5;12976:1;12986:207;13000:4;12997:1;12994:11;12986:207;;;13063:13;;13078:6;13059:26;13047:39;;13109:4;13133:12;;;;13168:15;;;;13020:1;13013:9;12986:207;;13204:447;13256:3;13294:5;13288:12;13321:6;13316:3;13309:19;13347:4;13376:2;13371:3;13367:12;13360:19;;13413:2;13406:5;13402:14;13434:1;13444:182;13458:6;13455:1;13452:13;13444:182;;;13523:13;;13538:6;13519:26;13507:39;;13566:12;;;;13601:15;;;;13480:1;13473:9;13444:182;;;-1:-1:-1;13642:3:1;;13204:447;-1:-1:-1;;;;;13204:447:1:o;13656:257::-;13697:3;13735:5;13729:12;13762:6;13757:3;13750:19;13778:63;13834:6;13827:4;13822:3;13818:14;13811:4;13804:5;13800:16;13778:63;:::i;:::-;13895:2;13874:15;-1:-1:-1;;13870:29:1;13861:39;;;;13902:4;13857:50;;13656:257;-1:-1:-1;;13656:257:1:o;15018:274::-;15147:3;15185:6;15179:13;15201:53;15247:6;15242:3;15235:4;15227:6;15223:17;15201:53;:::i;:::-;15270:16;;;;;15018:274;-1:-1:-1;;15018:274:1:o;15297:415::-;15454:3;15492:6;15486:13;15508:53;15554:6;15549:3;15542:4;15534:6;15530:17;15508:53;:::i;:::-;15630:2;15626:15;;;;-1:-1:-1;;;;;;15622:53:1;15583:16;;;;15608:68;;;15703:2;15692:14;;15297:415;-1:-1:-1;;15297:415:1:o;16574:431::-;-1:-1:-1;;;;;16831:15:1;;;16813:34;;16883:15;;16878:2;16863:18;;16856:43;16935:2;16930;16915:18;;16908:30;;;16756:4;;16955:44;;16980:18;;16972:6;16955:44;:::i;17010:488::-;-1:-1:-1;;;;;17279:15:1;;;17261:34;;17331:15;;17326:2;17311:18;;17304:43;17378:2;17363:18;;17356:34;;;17426:3;17421:2;17406:18;;17399:31;;;17204:4;;17447:45;;17472:19;;17464:6;17447:45;:::i;:::-;17439:53;17010:488;-1:-1:-1;;;;;;17010:488:1:o;17503:507::-;17679:3;17664:19;;17668:9;17760:6;17637:4;17794:210;17808:4;17805:1;17802:11;17794:210;;;17881:13;;17874:21;17867:29;17855:42;;17920:4;17944:12;;;;17979:15;;;;17828:1;17821:9;17794:210;;;17798:3;;;17503:507;;;;:::o;18015:238::-;18193:2;18178:18;;18205:42;18182:9;18229:6;18205:42;:::i;18258:506::-;18436:3;18421:19;;18425:9;18517:6;18394:4;18551:207;18565:4;18562:1;18559:11;18551:207;;;18628:13;;18643:6;18624:26;18612:39;;18674:4;18698:12;;;;18733:15;;;;18585:1;18578:9;18551:207;;18769:643;18938:2;18990:21;;;19060:13;;18963:18;;;19082:22;;;18909:4;;18938:2;19161:15;;;;19135:2;19120:18;;;18909:4;19204:182;19218:6;19215:1;19212:13;19204:182;;;19283:13;;19298:6;19279:26;19267:39;;19361:15;;;;19326:12;;;;19240:1;19233:9;19204:182;;;-1:-1:-1;19403:3:1;;18769:643;-1:-1:-1;;;;;;18769:643:1:o;21923:217::-;22070:2;22059:9;22052:21;22033:4;22090:44;22130:2;22119:9;22115:18;22107:6;22090:44;:::i;22725:340::-;22927:2;22909:21;;;22966:2;22946:18;;;22939:30;-1:-1:-1;;;23000:2:1;22985:18;;22978:46;23056:2;23041:18;;22725:340::o;23425:414::-;23627:2;23609:21;;;23666:2;23646:18;;;23639:30;23705:34;23700:2;23685:18;;23678:62;-1:-1:-1;;;23771:2:1;23756:18;;23749:48;23829:3;23814:19;;23425:414::o;27518:348::-;27720:2;27702:21;;;27759:2;27739:18;;;27732:30;27798:26;27793:2;27778:18;;27771:54;27857:2;27842:18;;27518:348::o;27871:340::-;28073:2;28055:21;;;28112:2;28092:18;;;28085:30;-1:-1:-1;;;28146:2:1;28131:18;;28124:46;28202:2;28187:18;;27871:340::o;32389:356::-;32591:2;32573:21;;;32610:18;;;32603:30;32669:34;32664:2;32649:18;;32642:62;32736:2;32721:18;;32389:356::o;36767:413::-;36969:2;36951:21;;;37008:2;36988:18;;;36981:30;37047:34;37042:2;37027:18;;37020:62;-1:-1:-1;;;37113:2:1;37098:18;;37091:47;37170:3;37155:19;;36767:413::o;37185:343::-;37387:2;37369:21;;;37426:2;37406:18;;;37399:30;-1:-1:-1;;;37460:2:1;37445:18;;37438:49;37519:2;37504:18;;37185:343::o;39267:355::-;39469:2;39451:21;;;39508:2;39488:18;;;39481:30;39547:33;39542:2;39527:18;;39520:61;39613:2;39598:18;;39267:355::o;39976:1016::-;40124:4;40166:3;40155:9;40151:19;40143:27;;40195:6;40189:13;40249:2;40243:9;40236:17;40229:25;40218:9;40211:44;40319:6;40311:4;40307:2;40303:13;40297:20;40293:33;40286:4;40275:9;40271:20;40264:63;40391:4;40383;40379:2;40375:13;40369:20;40365:31;40358:4;40347:9;40343:20;40336:61;40440:4;40436:2;40432:13;40426:20;40455:59;40508:4;40497:9;40493:20;40479:12;40455:59;:::i;:::-;;40578:10;40570:4;40566:2;40562:13;40556:20;40552:37;40545:4;40534:9;40530:20;40523:67;;40639:4;40631:6;40627:17;40621:24;40654:68;40716:4;40705:9;40701:20;40684:14;40678:21;40654:68;:::i;:::-;40779:4;40763:14;40759:25;40753:32;40794:60;40849:3;40838:9;40834:19;40818:14;40794:60;:::i;:::-;-1:-1:-1;40911:4:1;40891:25;40885:32;40926:60;40981:3;40966:19;;40885:32;40926:60;:::i;:::-;;39976:1016;;;;:::o;41744:1379::-;42074:4;42103;42134:6;42123:9;42116:25;42166:6;42160:13;42229:2;42223:9;42216:17;42209:25;42204:2;42193:9;42189:18;42182:53;42295:6;42289:2;42285;42281:11;42275:18;42271:31;42266:2;42255:9;42251:18;42244:59;42363:4;42357:2;42353;42349:11;42343:18;42339:29;42334:2;42323:9;42319:18;42312:57;42412:2;42408;42404:11;42398:18;42425:58;42478:3;42467:9;42463:19;42449:12;42425:58;:::i;:::-;;42545:10;42538:3;42534:2;42530:12;42524:19;42520:36;42514:3;42503:9;42499:19;42492:65;;42606:2;42598:6;42594:15;42588:22;42619:67;42681:3;42670:9;42666:19;42649:14;42643:21;42619:67;:::i;:::-;42743:2;42727:14;42723:23;42717:30;42756:60;42811:3;42800:9;42796:19;42780:14;42756:60;:::i;:::-;-1:-1:-1;42873:2:1;42853:23;42847:30;42886:60;42941:3;42926:19;;42847:30;42886:60;:::i;:::-;;42983:2;42977:3;42966:9;42962:19;42955:31;43003:55;43054:2;43043:9;43039:18;43031:6;43003:55;:::i;:::-;42995:63;;;43067:50;43112:3;43101:9;43097:19;43089:6;43067:50;:::i;43648:257::-;43720:4;43714:11;;;43752:17;;-1:-1:-1;;;;;43784:34:1;;43820:22;;;43781:62;43778:88;;;43846:18;;:::i;:::-;43882:4;43875:24;43648:257;:::o;43910:253::-;43982:2;43976:9;44024:4;44012:17;;-1:-1:-1;;;;;44044:34:1;;44080:22;;;44041:62;44038:88;;;44106:18;;:::i;44168:275::-;44239:2;44233:9;44304:2;44285:13;;-1:-1:-1;;44281:27:1;44269:40;;-1:-1:-1;;;;;44324:34:1;;44360:22;;;44321:62;44318:88;;;44386:18;;:::i;:::-;44422:2;44415:22;44168:275;;-1:-1:-1;44168:275:1:o;44448:183::-;44508:4;-1:-1:-1;;;;;44533:6:1;44530:30;44527:56;;;44563:18;;:::i;:::-;-1:-1:-1;44608:1:1;44604:14;44620:4;44600:25;;44448:183::o;44636:186::-;44684:4;-1:-1:-1;;;;;44709:6:1;44706:30;44703:56;;;44739:18;;:::i;:::-;-1:-1:-1;44805:2:1;44784:15;-1:-1:-1;;44780:29:1;44811:4;44776:40;;44636:186::o;44827:224::-;44866:3;44894:6;44927:2;44924:1;44920:10;44957:2;44954:1;44950:10;44988:3;44984:2;44980:12;44975:3;44972:21;44969:47;;;44996:18;;:::i;:::-;45032:13;;44827:224;-1:-1:-1;;;;44827:224:1:o;45056:128::-;45096:3;45127:1;45123:6;45120:1;45117:13;45114:39;;;45133:18;;:::i;:::-;-1:-1:-1;45169:9:1;;45056:128::o;45189:204::-;45227:3;45263:4;45260:1;45256:12;45295:4;45292:1;45288:12;45330:3;45324:4;45320:14;45315:3;45312:23;45309:49;;;45338:18;;:::i;:::-;45374:13;;45189:204;-1:-1:-1;;;45189:204:1:o;45398:120::-;45438:1;45464;45454:35;;45469:18;;:::i;:::-;-1:-1:-1;45503:9:1;;45398:120::o;45523:168::-;45563:7;45629:1;45625;45621:6;45617:14;45614:1;45611:21;45606:1;45599:9;45592:17;45588:45;45585:71;;;45636:18;;:::i;:::-;-1:-1:-1;45676:9:1;;45523:168::o;45696:217::-;45735:4;45764:6;45820:10;;;;45790;;45842:12;;;45839:38;;;45857:18;;:::i;:::-;45894:13;;45696:217;-1:-1:-1;;;45696:217:1:o;45918:125::-;45958:4;45986:1;45983;45980:8;45977:34;;;45991:18;;:::i;:::-;-1:-1:-1;46028:9:1;;45918:125::o;46048:258::-;46120:1;46130:113;46144:6;46141:1;46138:13;46130:113;;;46220:11;;;46214:18;46201:11;;;46194:39;46166:2;46159:10;46130:113;;;46261:6;46258:1;46255:13;46252:48;;;-1:-1:-1;;46296:1:1;46278:16;;46271:27;46048:258::o;46311:136::-;46350:3;46378:5;46368:39;;46387:18;;:::i;:::-;-1:-1:-1;;;46423:18:1;;46311:136::o;46452:380::-;46531:1;46527:12;;;;46574;;;46595:61;;46649:4;46641:6;46637:17;46627:27;;46595:61;46702:2;46694:6;46691:14;46671:18;46668:38;46665:161;;;46748:10;46743:3;46739:20;46736:1;46729:31;46783:4;46780:1;46773:15;46811:4;46808:1;46801:15;46665:161;;46452:380;;;:::o;46837:135::-;46876:3;-1:-1:-1;;46897:17:1;;46894:43;;;46917:18;;:::i;:::-;-1:-1:-1;46964:1:1;46953:13;;46837:135::o;46977:175::-;47014:3;47058:4;47051:5;47047:16;47087:4;47078:7;47075:17;47072:43;;;47095:18;;:::i;:::-;47144:1;47131:15;;46977:175;-1:-1:-1;;46977:175:1:o;47157:112::-;47189:1;47215;47205:35;;47220:18;;:::i;:::-;-1:-1:-1;47254:9:1;;47157:112::o;47274:127::-;47335:10;47330:3;47326:20;47323:1;47316:31;47366:4;47363:1;47356:15;47390:4;47387:1;47380:15;47406:127;47467:10;47462:3;47458:20;47455:1;47448:31;47498:4;47495:1;47488:15;47522:4;47519:1;47512:15;47538:127;47599:10;47594:3;47590:20;47587:1;47580:31;47630:4;47627:1;47620:15;47654:4;47651:1;47644:15;47670:127;47731:10;47726:3;47722:20;47719:1;47712:31;47762:4;47759:1;47752:15;47786:4;47783:1;47776:15;47802:131;-1:-1:-1;;;;;47877:31:1;;47867:42;;47857:70;;47923:1;47920;47913:12;47938:131;-1:-1:-1;;;;;;48012:32:1;;48002:43;;47992:71;;48059:1;48056;48049:12

Swarm Source

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