ETH Price: $3,297.62 (-3.74%)
Gas: 7 Gwei

Token

Kurai Michi (KM-NFT)
 

Overview

Max Total Supply

5,777 KM-NFT

Holders

1,730

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Balance
3 KM-NFT
0x842bd53f78df7b497428b5b6db4ff9999e9b71e4
Loading...
Loading
Loading...
Loading
Loading...
Loading

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

Contract Source Code Verified (Exact Match)

Contract Name:
KuraiMichi

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity Multiple files format)

File 5 of 11: KuraiMichi.sol
// SPDX-License-Identifier: MIT

import {DefaultOperatorFilterer} from "./DefaultOperatorFilterer.sol";

pragma solidity ^0.8.0;

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

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

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

pragma solidity ^0.8.0; 

abstract contract ReentrancyGuard { 
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }
    modifier nonReentrant() {
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
   _status = _ENTERED;

        _;
        _status = _NOT_ENTERED;
    }
}

library Strings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
 
    function toString(uint256 value) internal pure returns (string memory) { 
        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);
    }
 
    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);
    }
 
    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);
    }
}
 
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}
 
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
 
    constructor() {
        _transferOwnership(_msgSender());
    }
 
    function owner() public view virtual returns (address) {
        return _owner;
    } 
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }
 
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }
 
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }
 
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}
 
library Address { 
    function isContract(address account) internal view returns (bool) { 
        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    } 
    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");
    }
 
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, "Address: low-level call failed");
    } 
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }
 
    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");
    }
 
    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);
    } 
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }
 
    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);
    }
 
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }
 
    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
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else { 
            if (returndata.length > 0) { 

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}
 
interface IERC721Receiver { 
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}
 
interface IERC165 { 
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
 
abstract contract ERC165 is IERC165 { 
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
} 
interface IERC721 is IERC165 { 
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); 
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); 
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved); 
    function balanceOf(address owner) external view returns (uint256 balance); 
    function ownerOf(uint256 tokenId) external view returns (address owner); 
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external; 
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external; 
    function approve(address to, uint256 tokenId) external;
 
    function getApproved(uint256 tokenId) external view returns (address operator); 
    function setApprovalForAll(address operator, bool _approved) external; 
    function isApprovedForAll(address owner, address operator) external view returns (bool); 
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external;
} 
interface IERC721Enumerable is IERC721 { 
    function totalSupply() external view returns (uint256); 
    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId); 
    function tokenByIndex(uint256 index) external view returns (uint256);
}  
interface IERC721Metadata is IERC721 { 
    function name() external view returns (string memory); 
    function symbol() external view returns (string memory); 
    function tokenURI(uint256 tokenId) external view returns (string memory);
}

error ApprovalCallerNotOwnerNorApproved();
error ApprovalQueryForNonexistentToken();
error ApproveToCaller();
error ApprovalToCurrentOwner();
error BalanceQueryForZeroAddress();
error MintToZeroAddress();
error MintZeroQuantity();
error OwnerQueryForNonexistentToken();
error TransferCallerNotOwnerNorApproved();
error TransferFromIncorrectOwner();
error TransferToNonERC721ReceiverImplementer();
error TransferToZeroAddress();
error URIQueryForNonexistentToken();

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

    // Compiler will pack this into a single 256bit word.
    struct TokenOwnership {
        // The address of the owner.
        address addr;
        // Keeps track of the start time of ownership with minimal overhead for tokenomics.
        uint64 startTimestamp;
        // Whether the token has been burned.
        bool burned;
    }

    // Compiler will pack this into a single 256bit word.
    struct AddressData {
        // Realistically, 2**64-1 is more than enough.
        uint64 balance;
        // Keeps track of mint count with minimal overhead for tokenomics.
        uint64 numberMinted;
        // Keeps track of burn count with minimal overhead for tokenomics.
        uint64 numberBurned;
        // For miscellaneous variable(s) pertaining to the address
        // (e.g. number of whitelist mint slots used).
        // If there are multiple variables, please pack them into a uint64.
        uint64 aux;
    }

    // The tokenId of the next token to be minted.
    uint256 internal _currentIndex;

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

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Mapping from token ID to ownership details
    // An empty struct value does not necessarily mean the token is unowned. See _ownershipOf implementation for details.
    mapping(uint256 => TokenOwnership) internal _ownerships;

    // Mapping owner address to address data
    mapping(address => AddressData) private _addressData;

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

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

    /**
     * To change the starting tokenId, please override this function.
     */
    function _startTokenId() internal view virtual returns (uint256) {
        return 1;
    }

    /**
     * @dev Burned tokens are calculated here, use _totalMinted() if you want to count just minted tokens.
     */
    function totalSupply() public view returns (uint256) {
        // Counter underflow is impossible as _burnCounter cannot be incremented
        // more than _currentIndex - _startTokenId() times
        unchecked {
            return _currentIndex - _burnCounter - _startTokenId();
        }
    }

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

    /**
     * @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 override returns (uint256) {
        if (owner == address(0)) revert BalanceQueryForZeroAddress();
        return uint256(_addressData[owner].balance);
    }

    /**
     * Returns the number of tokens minted by `owner`.
     */
    function _numberMinted(address owner) internal view returns (uint256) {
        return uint256(_addressData[owner].numberMinted);
    }

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

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

    /**
     * Sets the auxillary data for `owner`. (e.g. number of whitelist mint slots used).
     * If there are multiple variables, please pack them into a uint64.
     */
    function _setAux(address owner, uint64 aux) internal {
        _addressData[owner].aux = aux;
    }

    /**
     * Gas spent here starts off proportional to the maximum mint batch size.
     * It gradually moves to O(1) as tokens get transferred around in the collection over time.
     */
    function _ownershipOf(uint256 tokenId) internal view returns (TokenOwnership memory) {
        uint256 curr = tokenId;

        unchecked {
            if (_startTokenId() <= curr && curr < _currentIndex) {
                TokenOwnership memory ownership = _ownerships[curr];
                if (!ownership.burned) {
                    if (ownership.addr != address(0)) {
                        return ownership;
                    }
                    // Invariant:
                    // There will always be an ownership that has an address and is not burned
                    // before an ownership that does not have an address and is not burned.
                    // Hence, curr will not underflow.
                    while (true) {
                        curr--;
                        ownership = _ownerships[curr];
                        if (ownership.addr != address(0)) {
                            return ownership;
                        }
                    }
                }
            }
        }
        revert OwnerQueryForNonexistentToken();
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId) public view override returns (address) {
        return _ownershipOf(tokenId).addr;
    }

    /**
     * @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) {
        if (!_exists(tokenId)) revert URIQueryForNonexistentToken();

        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 override {
        address owner = ERC721A.ownerOf(tokenId);
        if (to == owner) revert ApprovalToCurrentOwner();

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

        _approve(to, tokenId, owner);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId) public view override returns (address) {
        if (!_exists(tokenId)) revert ApprovalQueryForNonexistentToken();

        return _tokenApprovals[tokenId];
    }

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

        _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 {
        _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 {
        _transfer(from, to, tokenId);
        if (to.isContract() && !_checkContractOnERC721Received(from, to, tokenId, _data)) {
            revert TransferToNonERC721ReceiverImplementer();
        }
    }

    /**
     * @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`),
     */
    function _exists(uint256 tokenId) internal view returns (bool) {
        return _startTokenId() <= tokenId && tokenId < _currentIndex && !_ownerships[tokenId].burned;
    }

    function _safeMint(address to, uint256 quantity) internal {
        _safeMint(to, quantity, '');
    }

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

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

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

        // Overflows are incredibly unrealistic.
        // balance or numberMinted overflow if current value of either + quantity > 1.8e19 (2**64) - 1
        // updatedIndex overflows if _currentIndex + quantity > 1.2e77 (2**256) - 1
        unchecked {
            _addressData[to].balance += uint64(quantity);
            _addressData[to].numberMinted += uint64(quantity);

            _ownerships[startTokenId].addr = to;
            _ownerships[startTokenId].startTimestamp = uint64(block.timestamp);

            uint256 updatedIndex = startTokenId;
            uint256 end = updatedIndex + quantity;

            if (safe && to.isContract()) {
                do {
                    emit Transfer(address(0), to, updatedIndex);
                    if (!_checkContractOnERC721Received(address(0), to, updatedIndex++, _data)) {
                        revert TransferToNonERC721ReceiverImplementer();
                    }
                } while (updatedIndex != end);
                // Reentrancy protection
                if (_currentIndex != startTokenId) revert();
            } else {
                do {
                    emit Transfer(address(0), to, updatedIndex++);
                } while (updatedIndex != end);
            }
            _currentIndex = updatedIndex;
        }
        _afterTokenTransfers(address(0), to, startTokenId, quantity);
    }

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *
     * 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
    ) private {
        TokenOwnership memory prevOwnership = _ownershipOf(tokenId);

        if (prevOwnership.addr != from) revert TransferFromIncorrectOwner();

        bool isApprovedOrOwner = (_msgSender() == from ||
            isApprovedForAll(from, _msgSender()) ||
            getApproved(tokenId) == _msgSender());

        if (!isApprovedOrOwner) revert TransferCallerNotOwnerNorApproved();
        if (to == address(0)) revert TransferToZeroAddress();

        _beforeTokenTransfers(from, to, tokenId, 1);

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

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

            TokenOwnership storage currSlot = _ownerships[tokenId];
            currSlot.addr = to;
            currSlot.startTimestamp = uint64(block.timestamp);

            // If the ownership slot of tokenId+1 is not explicitly set, that means the transfer initiator owns it.
            // Set the slot of tokenId+1 explicitly in storage to maintain correctness for ownerOf(tokenId+1) calls.
            uint256 nextTokenId = tokenId + 1;
            TokenOwnership storage nextSlot = _ownerships[nextTokenId];
            if (nextSlot.addr == address(0)) {
                // This will suffice for checking _exists(nextTokenId),
                // as a burned slot cannot contain the zero address.
                if (nextTokenId != _currentIndex) {
                    nextSlot.addr = from;
                    nextSlot.startTimestamp = prevOwnership.startTimestamp;
                }
            }
        }

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

    /**
     * @dev This is equivalent to _burn(tokenId, false)
     */
    function _burn(uint256 tokenId) internal virtual {
        _burn(tokenId, false);
    }

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

        address from = prevOwnership.addr;

        if (approvalCheck) {
            bool isApprovedOrOwner = (_msgSender() == from ||
                isApprovedForAll(from, _msgSender()) ||
                getApproved(tokenId) == _msgSender());

            if (!isApprovedOrOwner) revert TransferCallerNotOwnerNorApproved();
        }

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

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

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        // Counter overflow is incredibly unrealistic as tokenId would have to be 2**256.
        unchecked {
            AddressData storage addressData = _addressData[from];
            addressData.balance -= 1;
            addressData.numberBurned += 1;

            // Keep track of who burned the token, and the timestamp of burning.
            TokenOwnership storage currSlot = _ownerships[tokenId];
            currSlot.addr = from;
            currSlot.startTimestamp = uint64(block.timestamp);
            currSlot.burned = true;

            // If the ownership slot of tokenId+1 is not explicitly set, that means the burn initiator owns it.
            // Set the slot of tokenId+1 explicitly in storage to maintain correctness for ownerOf(tokenId+1) calls.
            uint256 nextTokenId = tokenId + 1;
            TokenOwnership storage nextSlot = _ownerships[nextTokenId];
            if (nextSlot.addr == address(0)) {
                // This will suffice for checking _exists(nextTokenId),
                // as a burned slot cannot contain the zero address.
                if (nextTokenId != _currentIndex) {
                    nextSlot.addr = from;
                    nextSlot.startTimestamp = prevOwnership.startTimestamp;
                }
            }
        }

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

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

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

    /**
     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target 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 _checkContractOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) private returns (bool) {
        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 TransferToNonERC721ReceiverImplementer();
            } else {
                assembly {
                    revert(add(32, reason), mload(reason))
                }
            }
        }
    }

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

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

contract KuraiMichi is Ownable, ERC721A, ReentrancyGuard, DefaultOperatorFilterer {
  using Strings for uint256;


  uint256 public MAX_PER_Transaction = 3; // maximam amount that user can mint/Transaction
  uint256 public MAX_PER_WALLET = 3; // maximam amount that user can mint/Wallet

  uint256 public PRICE = 0.01 ether; 

  uint256 private constant TotalCollectionSize_ = 7777; // total number of nfts
  uint256 private constant MaxMintPerBatch_ = 20; //max mint per transaction
  uint256 public PhaseCollectionSize_ = 5000; // total number of nfts in Phase 1

  uint public reserve = 0;
  uint public status = 0; //0-pause 1-whitelist 2-public

  string private _baseTokenURI;
  string private _uriBeforeReveal;
  bool public revealed = false;

  mapping(address => uint256) public publicClaimedBy;

  constructor() ERC721A("Kurai Michi","KM-NFT") {

  }

  modifier callerIsUser() {
    require(tx.origin == msg.sender, "The caller is another contract");
    _;
  }
 
  function mint(uint256 quantity) external payable callerIsUser {
    require(status == 2 , "Sale is not Active");
    require(totalSupply() + quantity <= TotalCollectionSize_-reserve, "reached max supply");
    require(totalSupply() + quantity <= PhaseCollectionSize_, "reached max supply");
    require(quantity <= MAX_PER_Transaction,"can not mint this many");
    require(msg.value >= PRICE * quantity, "Need to send more ETH.");

    publicClaimedBy[msg.sender] += quantity;
    require(publicClaimedBy[msg.sender] <= MAX_PER_WALLET, "Purchase exceeds max allowed");

    _safeMint(msg.sender, quantity);
  }

   function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
    require(_exists(tokenId),"ERC721Metadata: URI query for nonexistent token");

    if(revealed == false){
        return _uriBeforeReveal;
    }

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

     function changeRevealStatus() public onlyOwner {
        revealed = true;
    }

  function setBaseURI(string memory baseURI) external onlyOwner {
    _baseTokenURI = baseURI;
  }
  function _baseURI() internal view virtual override returns (string memory) {
    return _baseTokenURI;
  }

  function setURIbeforeReveal(string memory URI) external onlyOwner {
    _uriBeforeReveal = URI;
  }

  function numberMinted(address owner) public view returns (uint256) {
    return _numberMinted(owner);
  }
  function getOwnershipData(uint256 tokenId)
    external
    view
    returns (TokenOwnership memory)
  {
    return _ownershipOf(tokenId);
  }

  function withdrawMoney() external onlyOwner nonReentrant {
    (bool success, ) = msg.sender.call{value: address(this).balance}("");
    require(success, "Transfer failed.");
  }

  function changeMintPrice(uint256 _newPrice) external onlyOwner
  {
      PRICE = _newPrice;
  }

  function changeMAX_PER_Transaction(uint256 q) external onlyOwner
  {
      MAX_PER_Transaction = q;
  }

     function changeMAX_PER_WALLET(uint256 q) external onlyOwner
  {
      MAX_PER_WALLET = q;
  }

  function setStatus(uint256 s)external onlyOwner{
      status = s;
  }

   function getStatus()public view returns(uint){
      return status;
  }

 function setReserveTokens(uint256 _quantity) public onlyOwner {
        reserve=_quantity;
    }
    
  function getPrice(uint256 _quantity) public view returns (uint256) {
       
        return _quantity*PRICE;
    }

 function mintReserveTokens(uint quantity) public onlyOwner {
        require(quantity <= reserve, "The quantity exceeds the reserve.");
        reserve -= quantity;
        _safeMint(msg.sender, quantity);

    }

  function airdrop(address sendTo, uint quantity)public onlyOwner{
    require(totalSupply() + quantity <= TotalCollectionSize_, "reached max supply");
    _safeMint(sendTo, quantity);
  }

    //    Raffle/WL/OG CODE STARTS    //

    uint256 public whiteListPerWallet = 1;
    uint256 public MAX_PER_WL_TRANSACTION = 1; // maximam amount that user can mint/Wallet
    bytes32 public whitelistMerkleRoot;
    uint256 public itemPriceWhiteList = 0.008 ether;
    mapping(address => uint256) public whiteListClaimedBy;
    uint256 private TotalWLavailable = 5000; // total number of nfts


    function setWhitelistMerkleRoot(bytes32 _whitelistMerkleRoot) external onlyOwner {
        whitelistMerkleRoot = _whitelistMerkleRoot;
    }

    function getWhitelistPrice(uint256 _quantity) public view returns (uint256) {
       
           return _quantity*itemPriceWhiteList;
    }

    function inWhitelist(bytes32[] memory _proof, address _owner) public view returns (bool) {
        return MerkleProof.verify(_proof, whitelistMerkleRoot, keccak256(abi.encodePacked(_owner)));
    }


    function purchaseWhiteListTokens(uint256 _howMany, bytes32[] calldata _proof) external payable {
        require(status == 1 , "Sale is not active ");
        require(totalSupply()+_howMany<=TotalWLavailable,"Quantity must be lesser then MaxSupply");
        require(inWhitelist(_proof, msg.sender), "You are not in presale");
        require(msg.value >= _howMany * itemPriceWhiteList, "Try to send more ETH");
        require(_howMany <= MAX_PER_WL_TRANSACTION , "can not mint this many");

        whiteListClaimedBy[msg.sender] += _howMany;
        require(whiteListClaimedBy[msg.sender] <= whiteListPerWallet, "Purchase exceeds max allowed");

        _safeMint(msg.sender, _howMany);

    }

    function setWhiteListPerWallet(uint256 _whiteListPerWallet) external onlyOwner {
        whiteListPerWallet = _whiteListPerWallet;
    }

     function setWLavailable(uint256 _whiteListCollection) external onlyOwner {
        TotalWLavailable = _whiteListCollection;
    }

    function setPriceWhiteList(uint256 _itemPriceWhiteList) external onlyOwner {
        itemPriceWhiteList = _itemPriceWhiteList;
    }

    function changeMAX_PER_WL_TRANSACTION(uint256 q) external onlyOwner
  {
      MAX_PER_WL_TRANSACTION = q;
  }


    //    ROYALTY CODE IMPORTS    //


    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public override onlyAllowedOperator(from) {
        super.transferFrom(from, to, tokenId);
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public override onlyAllowedOperator(from) {
        super.safeTransferFrom(from, to, tokenId);
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) public override onlyAllowedOperator(from) {
        super.safeTransferFrom(from, to, tokenId, data);
    }
}

File 1 of 11: Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

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

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

File 2 of 11: DefaultOperatorFilterer.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import {OperatorFilterer} from "./OperatorFilterer.sol";

abstract contract DefaultOperatorFilterer is OperatorFilterer {
    address constant DEFAULT_SUBSCRIPTION =
        address(0x3cc6CddA760b79bAfa08dF41ECFA224f810dCeB6);

    constructor() OperatorFilterer(DEFAULT_SUBSCRIPTION, true) {}
}

File 3 of 11: EnumerableSet.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.

pragma solidity ^0.8.0;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 *
 * [WARNING]
 * ====
 * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
 * unusable.
 * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
 *
 * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
 * array of EnumerableSet.
 * ====
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;
        // Position of the value in the `values` array, plus 1 because index 0
        // means a value is not in the set.
        mapping(bytes32 => uint256) _indexes;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._indexes[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We read and store the value's index to prevent multiple reads from the same storage slot
        uint256 valueIndex = set._indexes[value];

        if (valueIndex != 0) {
            // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = valueIndex - 1;
            uint256 lastIndex = set._values.length - 1;

            if (lastIndex != toDeleteIndex) {
                bytes32 lastValue = set._values[lastIndex];

                // Move the last value to the index where the value to delete is
                set._values[toDeleteIndex] = lastValue;
                // Update the index for the moved value
                set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
            }

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the index for the deleted slot
            delete set._indexes[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value)
        private
        view
        returns (bool)
    {
        return set._indexes[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function _at(Set storage set, uint256 index)
        private
        view
        returns (bytes32)
    {
        return set._values[index];
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function _values(Set storage set) private view returns (bytes32[] memory) {
        return set._values;
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes32Set storage set, bytes32 value)
        internal
        returns (bool)
    {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes32Set storage set, bytes32 value)
        internal
        returns (bool)
    {
        return _remove(set._inner, value);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes32Set storage set, bytes32 value)
        internal
        view
        returns (bool)
    {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(Bytes32Set storage set, uint256 index)
        internal
        view
        returns (bytes32)
    {
        return _at(set._inner, index);
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(Bytes32Set storage set)
        internal
        view
        returns (bytes32[] memory)
    {
        bytes32[] memory store = _values(set._inner);
        bytes32[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value)
        internal
        returns (bool)
    {
        return _add(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value)
        internal
        returns (bool)
    {
        return _remove(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value)
        internal
        view
        returns (bool)
    {
        return _contains(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(AddressSet storage set, uint256 index)
        internal
        view
        returns (address)
    {
        return address(uint160(uint256(_at(set._inner, index))));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(AddressSet storage set)
        internal
        view
        returns (address[] memory)
    {
        bytes32[] memory store = _values(set._inner);
        address[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }

    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value)
        internal
        returns (bool)
    {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value)
        internal
        view
        returns (bool)
    {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(UintSet storage set, uint256 index)
        internal
        view
        returns (uint256)
    {
        return uint256(_at(set._inner, index));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(UintSet storage set)
        internal
        view
        returns (uint256[] memory)
    {
        bytes32[] memory store = _values(set._inner);
        uint256[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }
}

File 4 of 11: IOperatorFilterRegistry.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

interface IOperatorFilterRegistry {
    function isOperatorAllowed(address registrant, address operator) external view returns (bool);
    function register(address registrant) external;
    function registerAndSubscribe(address registrant, address subscription) external;
    function registerAndCopyEntries(address registrant, address registrantToCopy) external;
    function updateOperator(address registrant, address operator, bool filtered) external;
    function updateOperators(address registrant, address[] calldata operators, bool filtered) external;
    function updateCodeHash(address registrant, bytes32 codehash, bool filtered) external;
    function updateCodeHashes(address registrant, bytes32[] calldata codeHashes, bool filtered) external;
    function subscribe(address registrant, address registrantToSubscribe) external;
    function unsubscribe(address registrant, bool copyExistingEntries) external;
    function subscriptionOf(address addr) external returns (address registrant);
    function subscribers(address registrant) external returns (address[] memory);
    function subscriberAt(address registrant, uint256 index) external returns (address);
    function copyEntriesOf(address registrant, address registrantToCopy) external;
    function isOperatorFiltered(address registrant, address operator) external returns (bool);
    function isCodeHashOfFiltered(address registrant, address operatorWithCode) external returns (bool);
    function isCodeHashFiltered(address registrant, bytes32 codeHash) external returns (bool);
    function filteredOperators(address addr) external returns (address[] memory);
    function filteredCodeHashes(address addr) external returns (bytes32[] memory);
    function filteredOperatorAt(address registrant, uint256 index) external returns (address);
    function filteredCodeHashAt(address registrant, uint256 index) external returns (bytes32);
    function isRegistered(address addr) external returns (bool);
    function codeHashOf(address addr) external returns (bytes32);
}

File 6 of 11: OperatorFilterer.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import {IOperatorFilterRegistry} from "./IOperatorFilterRegistry.sol";

abstract contract OperatorFilterer {
    error OperatorNotAllowed(address operator);

    IOperatorFilterRegistry constant operatorFilterRegistry =
        IOperatorFilterRegistry(0x000000000000AAeB6D7670E522A718067333cd4E);

    constructor(address subscriptionOrRegistrantToCopy, bool subscribe) {
        // If an inheriting token contract is deployed to a network without the registry deployed, the modifier
        // will not revert, but the contract will need to be registered with the registry once it is deployed in
        // order for the modifier to filter addresses.
        if (address(operatorFilterRegistry).code.length > 0) {
            if (subscribe) {
                operatorFilterRegistry.registerAndSubscribe(
                    address(this),
                    subscriptionOrRegistrantToCopy
                );
            } else {
                if (subscriptionOrRegistrantToCopy != address(0)) {
                    operatorFilterRegistry.registerAndCopyEntries(
                        address(this),
                        subscriptionOrRegistrantToCopy
                    );
                } else {
                    operatorFilterRegistry.register(address(this));
                }
            }
        }
    }

    modifier onlyAllowedOperator(address from) virtual {
        // Check registry code length to facilitate testing in environments without a deployed registry.
        if (address(operatorFilterRegistry).code.length > 0) {
            // Allow spending tokens from addresses with balance
            // Note that this still allows listings and marketplaces with escrow to transfer tokens if transferred
            // from an EOA.
            if (from == msg.sender) {
                _;
                return;
            }
            if (
                !(operatorFilterRegistry.isOperatorAllowed(
                    address(this),
                    msg.sender
                ) &&
                    operatorFilterRegistry.isOperatorAllowed(
                        address(this),
                        from
                    ))
            ) {
                revert OperatorNotAllowed(msg.sender);
            }
        }
        _;
    }
}

File 7 of 11: OperatorFilterRegistry.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import {IOperatorFilterRegistry} from "./IOperatorFilterRegistry.sol";
import {Ownable} from "./Ownable.sol";
import {EnumerableSet} from "./EnumerableSet.sol";
import {OperatorFilterRegistryErrorsAndEvents} from "./OperatorFilterRegistryErrorsAndEvents.sol";

/**
 * @title  OperatorFilterRegistry
 * @notice Borrows heavily from the QQL BlacklistOperatorFilter contract:
 *         https://github.com/qql-art/contracts/blob/main/contracts/BlacklistOperatorFilter.sol
 * @notice This contracts allows tokens or token owners to register specific addresses or codeHashes that may be
 * *       restricted according to the isOperatorAllowed function.
 */
contract OperatorFilterRegistry is
    IOperatorFilterRegistry,
    OperatorFilterRegistryErrorsAndEvents
{
    using EnumerableSet for EnumerableSet.AddressSet;
    using EnumerableSet for EnumerableSet.Bytes32Set;

    /// @dev initialized accounts have a nonzero codehash (see https://eips.ethereum.org/EIPS/eip-1052)
    /// Note that this will also be a smart contract's codehash when making calls from its constructor.
    bytes32 constant EOA_CODEHASH = keccak256("");

    mapping(address => EnumerableSet.AddressSet) private _filteredOperators;
    mapping(address => EnumerableSet.Bytes32Set) private _filteredCodeHashes;
    mapping(address => address) private _registrations;
    mapping(address => EnumerableSet.AddressSet) private _subscribers;

    /**
     * @notice restricts method caller to the address or EIP-173 "owner()"
     */
    modifier onlyAddressOrOwner(address addr) {
        if (msg.sender != addr) {
            try Ownable(addr).owner() returns (address owner) {
                if (msg.sender != owner) {
                    revert OnlyAddressOrOwner();
                }
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert NotOwnable();
                } else {
                    /// @solidity memory-safe-assembly
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        }
        _;
    }

    /**
     * @notice Returns true if operator is not filtered for a given token, either by address or codeHash. Also returns
     *         true if supplied registrant address is not registered.
     */
    function isOperatorAllowed(address registrant, address operator)
        external
        view
        returns (bool)
    {
        address registration = _registrations[registrant];
        if (registration != address(0)) {
            EnumerableSet.AddressSet storage filteredOperatorsRef;
            EnumerableSet.Bytes32Set storage filteredCodeHashesRef;

            filteredOperatorsRef = _filteredOperators[registration];
            filteredCodeHashesRef = _filteredCodeHashes[registration];

            if (filteredOperatorsRef.contains(operator)) {
                revert AddressFiltered(operator);
            }
            if (operator.code.length > 0) {
                bytes32 codeHash = operator.codehash;
                if (filteredCodeHashesRef.contains(codeHash)) {
                    revert CodeHashFiltered(operator, codeHash);
                }
            }
        }
        return true;
    }

    //////////////////
    // AUTH METHODS //
    //////////////////

    /**
     * @notice Registers an address with the registry. May be called by address itself or by EIP-173 owner.
     */
    function register(address registrant)
        external
        onlyAddressOrOwner(registrant)
    {
        if (_registrations[registrant] != address(0)) {
            revert AlreadyRegistered();
        }
        _registrations[registrant] = registrant;
        emit RegistrationUpdated(registrant, true);
    }

    /**
     * @notice Unregisters an address with the registry and removes its subscription. May be called by address itself or by EIP-173 owner.
     *         Note that this does not remove any filtered addresses or codeHashes.
     *         Also note that any subscriptions to this registrant will still be active and follow the existing filtered addresses and codehashes.
     */
    function unregister(address registrant)
        external
        onlyAddressOrOwner(registrant)
    {
        address registration = _registrations[registrant];
        if (registration == address(0)) {
            revert NotRegistered(registrant);
        }
        if (registration != registrant) {
            _subscribers[registration].remove(registrant);
            emit SubscriptionUpdated(registrant, registration, false);
        }
        _registrations[registrant] = address(0);
        emit RegistrationUpdated(registrant, false);
    }

    /**
     * @notice Registers an address with the registry and "subscribes" to another address's filtered operators and codeHashes.
     */
    function registerAndSubscribe(address registrant, address subscription)
        external
        onlyAddressOrOwner(registrant)
    {
        address registration = _registrations[registrant];
        if (registration != address(0)) {
            revert AlreadyRegistered();
        }
        if (registrant == subscription) {
            revert CannotSubscribeToSelf();
        }
        address subscriptionRegistration = _registrations[subscription];
        if (subscriptionRegistration == address(0)) {
            revert NotRegistered(subscription);
        }
        if (subscriptionRegistration != subscription) {
            revert CannotSubscribeToRegistrantWithSubscription(subscription);
        }

        _registrations[registrant] = subscription;
        _subscribers[subscription].add(registrant);
        emit RegistrationUpdated(registrant, true);
        emit SubscriptionUpdated(registrant, subscription, true);
    }

    /**
     * @notice Registers an address with the registry and copies the filtered operators and codeHashes from another
     *         address without subscribing.
     */
    function registerAndCopyEntries(
        address registrant,
        address registrantToCopy
    ) external onlyAddressOrOwner(registrant) {
        if (registrantToCopy == registrant) {
            revert CannotCopyFromSelf();
        }
        address registration = _registrations[registrant];
        if (registration != address(0)) {
            revert AlreadyRegistered();
        }
        address registrantRegistration = _registrations[registrantToCopy];
        if (registrantRegistration == address(0)) {
            revert NotRegistered(registrantToCopy);
        }
        _registrations[registrant] = registrant;
        emit RegistrationUpdated(registrant, true);
        _copyEntries(registrant, registrantToCopy);
    }

    /**
     * @notice Update an operator address for a registered address - when filtered is true, the operator is filtered.
     */
    function updateOperator(
        address registrant,
        address operator,
        bool filtered
    ) external onlyAddressOrOwner(registrant) {
        address registration = _registrations[registrant];
        if (registration == address(0)) {
            revert NotRegistered(registrant);
        }
        if (registration != registrant) {
            revert CannotUpdateWhileSubscribed(registration);
        }
        EnumerableSet.AddressSet
            storage filteredOperatorsRef = _filteredOperators[registrant];

        if (!filtered) {
            bool removed = filteredOperatorsRef.remove(operator);
            if (!removed) {
                revert AddressNotFiltered(operator);
            }
        } else {
            bool added = filteredOperatorsRef.add(operator);
            if (!added) {
                revert AddressAlreadyFiltered(operator);
            }
        }
        emit OperatorUpdated(registrant, operator, filtered);
    }

    /**
     * @notice Update a codeHash for a registered address - when filtered is true, the codeHash is filtered.
     */
    function updateCodeHash(
        address registrant,
        bytes32 codeHash,
        bool filtered
    ) external onlyAddressOrOwner(registrant) {
        if (codeHash == EOA_CODEHASH) {
            revert CannotFilterEOAs();
        }
        address registration = _registrations[registrant];
        if (registration == address(0)) {
            revert NotRegistered(registrant);
        }
        if (registration != registrant) {
            revert CannotUpdateWhileSubscribed(registration);
        }
        EnumerableSet.Bytes32Set
            storage filteredCodeHashesRef = _filteredCodeHashes[registrant];

        if (!filtered) {
            bool removed = filteredCodeHashesRef.remove(codeHash);
            if (!removed) {
                revert CodeHashNotFiltered(codeHash);
            }
        } else {
            bool added = filteredCodeHashesRef.add(codeHash);
            if (!added) {
                revert CodeHashAlreadyFiltered(codeHash);
            }
        }
        emit CodeHashUpdated(registrant, codeHash, filtered);
    }

    /**
     * @notice Update multiple operators for a registered address - when filtered is true, the operators will be filtered. Reverts on duplicates.
     */
    function updateOperators(
        address registrant,
        address[] calldata operators,
        bool filtered
    ) external onlyAddressOrOwner(registrant) {
        address registration = _registrations[registrant];
        if (registration == address(0)) {
            revert NotRegistered(registrant);
        }
        if (registration != registrant) {
            revert CannotUpdateWhileSubscribed(registration);
        }
        EnumerableSet.AddressSet
            storage filteredOperatorsRef = _filteredOperators[registrant];
        uint256 operatorsLength = operators.length;
        unchecked {
            if (!filtered) {
                for (uint256 i = 0; i < operatorsLength; ++i) {
                    address operator = operators[i];
                    bool removed = filteredOperatorsRef.remove(operator);
                    if (!removed) {
                        revert AddressNotFiltered(operator);
                    }
                }
            } else {
                for (uint256 i = 0; i < operatorsLength; ++i) {
                    address operator = operators[i];
                    bool added = filteredOperatorsRef.add(operator);
                    if (!added) {
                        revert AddressAlreadyFiltered(operator);
                    }
                }
            }
        }
        emit OperatorsUpdated(registrant, operators, filtered);
    }

    /**
     * @notice Update multiple codeHashes for a registered address - when filtered is true, the codeHashes will be filtered. Reverts on duplicates.
     */
    function updateCodeHashes(
        address registrant,
        bytes32[] calldata codeHashes,
        bool filtered
    ) external onlyAddressOrOwner(registrant) {
        address registration = _registrations[registrant];
        if (registration == address(0)) {
            revert NotRegistered(registrant);
        }
        if (registration != registrant) {
            revert CannotUpdateWhileSubscribed(registration);
        }
        EnumerableSet.Bytes32Set
            storage filteredCodeHashesRef = _filteredCodeHashes[registrant];
        uint256 codeHashesLength = codeHashes.length;
        unchecked {
            if (!filtered) {
                for (uint256 i = 0; i < codeHashesLength; ++i) {
                    bytes32 codeHash = codeHashes[i];
                    bool removed = filteredCodeHashesRef.remove(codeHash);
                    if (!removed) {
                        revert CodeHashNotFiltered(codeHash);
                    }
                }
            } else {
                for (uint256 i = 0; i < codeHashesLength; ++i) {
                    bytes32 codeHash = codeHashes[i];
                    if (codeHash == EOA_CODEHASH) {
                        revert CannotFilterEOAs();
                    }
                    bool added = filteredCodeHashesRef.add(codeHash);
                    if (!added) {
                        revert CodeHashAlreadyFiltered(codeHash);
                    }
                }
            }
        }
        emit CodeHashesUpdated(registrant, codeHashes, filtered);
    }

    /**
     * @notice Subscribe an address to another registrant's filtered operators and codeHashes. Will remove previous
     *         subscription if present.
     *         Note that accounts with subscriptions may go on to subscribe to other accounts - in this case,
     *         subscriptions will not be forwarded. Instead the former subscription's existing entries will still be
     *         used.
     */
    function subscribe(address registrant, address newSubscription)
        external
        onlyAddressOrOwner(registrant)
    {
        if (registrant == newSubscription) {
            revert CannotSubscribeToSelf();
        }
        if (newSubscription == address(0)) {
            revert CannotSubscribeToZeroAddress();
        }
        address registration = _registrations[registrant];
        if (registration == address(0)) {
            revert NotRegistered(registrant);
        }
        if (registration == newSubscription) {
            revert AlreadySubscribed(newSubscription);
        }
        address newSubscriptionRegistration = _registrations[newSubscription];
        if (newSubscriptionRegistration == address(0)) {
            revert NotRegistered(newSubscription);
        }
        if (newSubscriptionRegistration != newSubscription) {
            revert CannotSubscribeToRegistrantWithSubscription(newSubscription);
        }

        if (registration != registrant) {
            _subscribers[registration].remove(registrant);
            emit SubscriptionUpdated(registrant, registration, false);
        }
        _registrations[registrant] = newSubscription;
        _subscribers[newSubscription].add(registrant);
        emit SubscriptionUpdated(registrant, newSubscription, true);
    }

    /**
     * @notice Unsubscribe an address from its current subscribed registrant, and optionally copy its filtered operators and codeHashes.
     */
    function unsubscribe(address registrant, bool copyExistingEntries)
        external
        onlyAddressOrOwner(registrant)
    {
        address registration = _registrations[registrant];
        if (registration == address(0)) {
            revert NotRegistered(registrant);
        }
        if (registration == registrant) {
            revert NotSubscribed();
        }
        _subscribers[registration].remove(registrant);
        _registrations[registrant] = registrant;
        emit SubscriptionUpdated(registrant, registration, false);
        if (copyExistingEntries) {
            _copyEntries(registrant, registration);
        }
    }

    /**
     * @notice Copy filtered operators and codeHashes from a different registrantToCopy to addr.
     */
    function copyEntriesOf(address registrant, address registrantToCopy)
        external
        onlyAddressOrOwner(registrant)
    {
        if (registrant == registrantToCopy) {
            revert CannotCopyFromSelf();
        }
        address registration = _registrations[registrant];
        if (registration == address(0)) {
            revert NotRegistered(registrant);
        }
        if (registration != registrant) {
            revert CannotUpdateWhileSubscribed(registration);
        }
        address registrantRegistration = _registrations[registrantToCopy];
        if (registrantRegistration == address(0)) {
            revert NotRegistered(registrantToCopy);
        }
        _copyEntries(registrant, registrantToCopy);
    }

    /// @dev helper to copy entries from registrantToCopy to registrant and emit events
    function _copyEntries(address registrant, address registrantToCopy)
        private
    {
        EnumerableSet.AddressSet
            storage filteredOperatorsRef = _filteredOperators[registrantToCopy];
        EnumerableSet.Bytes32Set
            storage filteredCodeHashesRef = _filteredCodeHashes[
                registrantToCopy
            ];
        uint256 filteredOperatorsLength = filteredOperatorsRef.length();
        uint256 filteredCodeHashesLength = filteredCodeHashesRef.length();
        unchecked {
            for (uint256 i = 0; i < filteredOperatorsLength; ++i) {
                address operator = filteredOperatorsRef.at(i);
                bool added = _filteredOperators[registrant].add(operator);
                if (added) {
                    emit OperatorUpdated(registrant, operator, true);
                }
            }
            for (uint256 i = 0; i < filteredCodeHashesLength; ++i) {
                bytes32 codehash = filteredCodeHashesRef.at(i);
                bool added = _filteredCodeHashes[registrant].add(codehash);
                if (added) {
                    emit CodeHashUpdated(registrant, codehash, true);
                }
            }
        }
    }

    //////////////////
    // VIEW METHODS //
    //////////////////

    /**
     * @notice Get the subscription address of a given registrant, if any.
     */
    function subscriptionOf(address registrant)
        external
        view
        returns (address subscription)
    {
        subscription = _registrations[registrant];
        if (subscription == address(0)) {
            revert NotRegistered(registrant);
        } else if (subscription == registrant) {
            subscription = address(0);
        }
    }

    /**
     * @notice Get the set of addresses subscribed to a given registrant.
     *         Note that order is not guaranteed as updates are made.
     */
    function subscribers(address registrant)
        external
        view
        returns (address[] memory)
    {
        return _subscribers[registrant].values();
    }

    /**
     * @notice Get the subscriber at a given index in the set of addresses subscribed to a given registrant.
     *         Note that order is not guaranteed as updates are made.
     */
    function subscriberAt(address registrant, uint256 index)
        external
        view
        returns (address)
    {
        return _subscribers[registrant].at(index);
    }

    /**
     * @notice Returns true if operator is filtered by a given address or its subscription.
     */
    function isOperatorFiltered(address registrant, address operator)
        external
        view
        returns (bool)
    {
        address registration = _registrations[registrant];
        if (registration != registrant) {
            return _filteredOperators[registration].contains(operator);
        }
        return _filteredOperators[registrant].contains(operator);
    }

    /**
     * @notice Returns true if a codeHash is filtered by a given address or its subscription.
     */
    function isCodeHashFiltered(address registrant, bytes32 codeHash)
        external
        view
        returns (bool)
    {
        address registration = _registrations[registrant];
        if (registration != registrant) {
            return _filteredCodeHashes[registration].contains(codeHash);
        }
        return _filteredCodeHashes[registrant].contains(codeHash);
    }

    /**
     * @notice Returns true if the hash of an address's code is filtered by a given address or its subscription.
     */
    function isCodeHashOfFiltered(address registrant, address operatorWithCode)
        external
        view
        returns (bool)
    {
        bytes32 codeHash = operatorWithCode.codehash;
        address registration = _registrations[registrant];
        if (registration != registrant) {
            return _filteredCodeHashes[registration].contains(codeHash);
        }
        return _filteredCodeHashes[registrant].contains(codeHash);
    }

    /**
     * @notice Returns true if an address has registered
     */
    function isRegistered(address registrant) external view returns (bool) {
        return _registrations[registrant] != address(0);
    }

    /**
     * @notice Returns a list of filtered operators for a given address or its subscription.
     */
    function filteredOperators(address registrant)
        external
        view
        returns (address[] memory)
    {
        address registration = _registrations[registrant];
        if (registration != registrant) {
            return _filteredOperators[registration].values();
        }
        return _filteredOperators[registrant].values();
    }

    /**
     * @notice Returns the set of filtered codeHashes for a given address or its subscription.
     *         Note that order is not guaranteed as updates are made.
     */
    function filteredCodeHashes(address registrant)
        external
        view
        returns (bytes32[] memory)
    {
        address registration = _registrations[registrant];
        if (registration != registrant) {
            return _filteredCodeHashes[registration].values();
        }
        return _filteredCodeHashes[registrant].values();
    }

    /**
     * @notice Returns the filtered operator at the given index of the set of filtered operators for a given address or
     *         its subscription.
     *         Note that order is not guaranteed as updates are made.
     */
    function filteredOperatorAt(address registrant, uint256 index)
        external
        view
        returns (address)
    {
        address registration = _registrations[registrant];
        if (registration != registrant) {
            return _filteredOperators[registration].at(index);
        }
        return _filteredOperators[registrant].at(index);
    }

    /**
     * @notice Returns the filtered codeHash at the given index of the list of filtered codeHashes for a given address or
     *         its subscription.
     *         Note that order is not guaranteed as updates are made.
     */
    function filteredCodeHashAt(address registrant, uint256 index)
        external
        view
        returns (bytes32)
    {
        address registration = _registrations[registrant];
        if (registration != registrant) {
            return _filteredCodeHashes[registration].at(index);
        }
        return _filteredCodeHashes[registrant].at(index);
    }

    /// @dev Convenience method to compute the code hash of an arbitrary contract
    function codeHashOf(address a) external view returns (bytes32) {
        return a.codehash;
    }
}

File 8 of 11: OperatorFilterRegistryErrorsAndEvents.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

contract OperatorFilterRegistryErrorsAndEvents {
    error CannotFilterEOAs();
    error AddressAlreadyFiltered(address operator);
    error AddressNotFiltered(address operator);
    error CodeHashAlreadyFiltered(bytes32 codeHash);
    error CodeHashNotFiltered(bytes32 codeHash);
    error OnlyAddressOrOwner();
    error NotRegistered(address registrant);
    error AlreadyRegistered();
    error AlreadySubscribed(address subscription);
    error NotSubscribed();
    error CannotUpdateWhileSubscribed(address subscription);
    error CannotSubscribeToSelf();
    error CannotSubscribeToZeroAddress();
    error NotOwnable();
    error AddressFiltered(address filtered);
    error CodeHashFiltered(address account, bytes32 codeHash);
    error CannotSubscribeToRegistrantWithSubscription(address registrant);
    error CannotCopyFromSelf();

    event RegistrationUpdated(address indexed registrant, bool indexed registered);
    event OperatorUpdated(address indexed registrant, address indexed operator, bool indexed filtered);
    event OperatorsUpdated(address indexed registrant, address[] operators, bool indexed filtered);
    event CodeHashUpdated(address indexed registrant, bytes32 indexed codeHash, bool indexed filtered);
    event CodeHashesUpdated(address indexed registrant, bytes32[] codeHashes, bool indexed filtered);
    event SubscriptionUpdated(address indexed registrant, address indexed subscription, bool indexed subscribed);
}

File 9 of 11: Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
pragma solidity ^0.8.0;

import {Context} from "./Context.sol";

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

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

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

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

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

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

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

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

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

File 10 of 11: Ownable2Step.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (access/Ownable2Step.sol)

pragma solidity ^0.8.0;

import "./Ownable.sol";

/**
 * @dev Contract module which provides access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership} and {acceptOwnership}.
 *
 * This module is used through inheritance. It will make available all functions
 * from parent (Ownable).
 */
abstract contract Ownable2Step is Ownable {
    address private _pendingOwner;

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

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

    /**
     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner)
        public
        virtual
        override
        onlyOwner
    {
        _pendingOwner = newOwner;
        emit OwnershipTransferStarted(owner(), newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual override {
        delete _pendingOwner;
        super._transferOwnership(newOwner);
    }

    /**
     * @dev The new owner accepts the ownership transfer.
     */
    function acceptOwnership() external {
        address sender = _msgSender();
        require(
            pendingOwner() == sender,
            "Ownable2Step: caller is not the new owner"
        );
        _transferOwnership(sender);
    }
}

File 11 of 11: OwnedRegistrant.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import {IOperatorFilterRegistry} from "./IOperatorFilterRegistry.sol";
import {Ownable2Step} from "./Ownable2Step.sol";

/**
 * @title  OwnedRegistrant
 * @notice Ownable contract that registers itself with the OperatorFilterRegistry and administers its own entries,
 *         to facilitate a subscription whose ownership can be transferred.
 */
contract OwnedRegistrant is Ownable2Step {
    address constant registry = 0x000000000000AAeB6D7670E522A718067333cd4E;

    constructor(address _owner) {
        IOperatorFilterRegistry(registry).register(address(this));
        transferOwnership(_owner);
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ApprovalCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"ApprovalQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"ApprovalToCurrentOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[],"name":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"OperatorNotAllowed","type":"error"},{"inputs":[],"name":"OwnerQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"TransferCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"MAX_PER_Transaction","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_PER_WALLET","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_PER_WL_TRANSACTION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PhaseCollectionSize_","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sendTo","type":"address"},{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"airdrop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"q","type":"uint256"}],"name":"changeMAX_PER_Transaction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"q","type":"uint256"}],"name":"changeMAX_PER_WALLET","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"q","type":"uint256"}],"name":"changeMAX_PER_WL_TRANSACTION","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newPrice","type":"uint256"}],"name":"changeMintPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"changeRevealStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getOwnershipData","outputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint64","name":"startTimestamp","type":"uint64"},{"internalType":"bool","name":"burned","type":"bool"}],"internalType":"struct ERC721A.TokenOwnership","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_quantity","type":"uint256"}],"name":"getPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStatus","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_quantity","type":"uint256"}],"name":"getWhitelistPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"},{"internalType":"address","name":"_owner","type":"address"}],"name":"inWhitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"itemPriceWhiteList","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"mintReserveTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"numberMinted","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":[{"internalType":"address","name":"","type":"address"}],"name":"publicClaimedBy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_howMany","type":"uint256"},{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"}],"name":"purchaseWhiteListTokens","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"reserve","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"revealed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"baseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_itemPriceWhiteList","type":"uint256"}],"name":"setPriceWhiteList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_quantity","type":"uint256"}],"name":"setReserveTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"s","type":"uint256"}],"name":"setStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"URI","type":"string"}],"name":"setURIbeforeReveal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_whiteListCollection","type":"uint256"}],"name":"setWLavailable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_whiteListPerWallet","type":"uint256"}],"name":"setWhiteListPerWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_whitelistMerkleRoot","type":"bytes32"}],"name":"setWhitelistMerkleRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"status","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whiteListClaimedBy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"whiteListPerWallet","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"whitelistMerkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawMoney","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040526003600a556003600b55662386f26fc10000600c55611388600d556000600e556000600f556000601260006101000a81548160ff02191690831515021790555060016014556001601555661c6bf5263400006017556113886019553480156200006c57600080fd5b50733cc6cdda760b79bafa08df41ecfa224f810dceb660016040518060400160405280600b81526020017f4b75726169204d696368690000000000000000000000000000000000000000008152506040518060400160405280600681526020017f4b4d2d4e4654000000000000000000000000000000000000000000000000000081525062000110620001046200035160201b60201c565b6200035960201b60201c565b8160039081620001219190620006a0565b508060049081620001339190620006a0565b50620001446200041d60201b60201c565b6001819055505050600160098190555060006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115620003495780156200020f576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff16637d3e3dbe30846040518363ffffffff1660e01b8152600401620001d5929190620007cc565b600060405180830381600087803b158015620001f057600080fd5b505af115801562000205573d6000803e3d6000fd5b5050505062000348565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614620002c9576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663a0af290330846040518363ffffffff1660e01b81526004016200028f929190620007cc565b600060405180830381600087803b158015620002aa57600080fd5b505af1158015620002bf573d6000803e3d6000fd5b5050505062000347565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff16634420e486306040518263ffffffff1660e01b8152600401620003129190620007f9565b600060405180830381600087803b1580156200032d57600080fd5b505af115801562000342573d6000803e3d6000fd5b505050505b5b5b505062000816565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60006001905090565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680620004a857607f821691505b602082108103620004be57620004bd62000460565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302620005287fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82620004e9565b620005348683620004e9565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b6000620005816200057b62000575846200054c565b62000556565b6200054c565b9050919050565b6000819050919050565b6200059d8362000560565b620005b5620005ac8262000588565b848454620004f6565b825550505050565b600090565b620005cc620005bd565b620005d981848462000592565b505050565b5b818110156200060157620005f5600082620005c2565b600181019050620005df565b5050565b601f82111562000650576200061a81620004c4565b6200062584620004d9565b8101602085101562000635578190505b6200064d6200064485620004d9565b830182620005de565b50505b505050565b600082821c905092915050565b6000620006756000198460080262000655565b1980831691505092915050565b600062000690838362000662565b9150826002028217905092915050565b620006ab8262000426565b67ffffffffffffffff811115620006c757620006c662000431565b5b620006d382546200048f565b620006e082828562000605565b600060209050601f83116001811462000718576000841562000703578287015190505b6200070f858262000682565b8655506200077f565b601f1984166200072886620004c4565b60005b8281101562000752578489015182556001820191506020850194506020810190506200072b565b868310156200077257848901516200076e601f89168262000662565b8355505b6001600288020188555050505b505050505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620007b48262000787565b9050919050565b620007c681620007a7565b82525050565b6000604082019050620007e36000830185620007bb565b620007f26020830184620007bb565b9392505050565b6000602082019050620008106000830184620007bb565b92915050565b6158ae80620008266000396000f3fe6080604052600436106103355760003560e01c80638825b014116101ab578063b333ca91116100f7578063dc33e68111610095578063e7d61da81161006f578063e7d61da814610bfa578063e8006bb014610c25578063e985e9c514610c4e578063f2fde38b14610c8b57610335565b8063dc33e68114610b43578063e5ec56a014610b80578063e757223014610bbd57610335565b8063c49e8062116100d1578063c49e806214610a89578063c7b8fca714610ab2578063c87b56dd14610adb578063cd3293de14610b1857610335565b8063b333ca9114610a0c578063b88d4fde14610a37578063bd32fb6614610a6057610335565b8063a0712d6811610164578063a5cdae2d1161013e578063a5cdae2d14610964578063aa98e0c61461098d578063ac446002146109b8578063aebceff4146109cf57610335565b8063a0712d68146108f6578063a22cb46514610912578063a40ece7a1461093b57610335565b80638825b014146107e65780638ba4cc3c1461080f5780638d859f3e146108385780638da5cb5b146108635780639231ab2a1461088e57806395d89b41146108cb57610335565b80632d5b005d116102855780636352211e1161022357806370a08231116101fd57806370a082311461072a578063715018a614610767578063752361431461077e578063852cbaee146107bb57610335565b80636352211e1461069b57806369ba1a75146106d85780636a44e1731461070157610335565b80634e69d5601161025f5780634e69d560146105f1578063518302271461061c57806351d7ff931461064757806355f804b31461067257610335565b80632d5b005d146105885780633fd173661461059f57806342842e0e146105c857610335565b806318160ddd116102f257806323b872dd116102cc57806323b872dd146104e25780632632d5f81461050b578063288bd8fd146105365780632ba2865b1461055f57610335565b806318160ddd1461044f5780631984b2861461047a578063200d2ed2146104b757610335565b806301ffc9a71461033a57806306fdde0314610377578063081812fc146103a2578063095ea7b3146103df5780630f2cdd6c1461040857806310157fc314610433575b600080fd5b34801561034657600080fd5b50610361600480360381019061035c919061401a565b610cb4565b60405161036e9190614062565b60405180910390f35b34801561038357600080fd5b5061038c610d96565b604051610399919061410d565b60405180910390f35b3480156103ae57600080fd5b506103c960048036038101906103c49190614165565b610e28565b6040516103d691906141d3565b60405180910390f35b3480156103eb57600080fd5b506104066004803603810190610401919061421a565b610ea4565b005b34801561041457600080fd5b5061041d610fae565b60405161042a9190614269565b60405180910390f35b61044d600480360381019061044891906142e9565b610fb4565b005b34801561045b57600080fd5b50610464611258565b6040516104719190614269565b60405180910390f35b34801561048657600080fd5b506104a1600480360381019061049c9190614349565b61126f565b6040516104ae9190614269565b60405180910390f35b3480156104c357600080fd5b506104cc611287565b6040516104d99190614269565b60405180910390f35b3480156104ee57600080fd5b5061050960048036038101906105049190614376565b61128d565b005b34801561051757600080fd5b5061052061146f565b60405161052d9190614269565b60405180910390f35b34801561054257600080fd5b5061055d60048036038101906105589190614165565b611475565b005b34801561056b57600080fd5b5061058660048036038101906105819190614165565b61155c565b005b34801561059457600080fd5b5061059d6115e2565b005b3480156105ab57600080fd5b506105c660048036038101906105c19190614165565b61167b565b005b3480156105d457600080fd5b506105ef60048036038101906105ea9190614376565b611701565b005b3480156105fd57600080fd5b506106066118e3565b6040516106139190614269565b60405180910390f35b34801561062857600080fd5b506106316118ed565b60405161063e9190614062565b60405180910390f35b34801561065357600080fd5b5061065c611900565b6040516106699190614269565b60405180910390f35b34801561067e57600080fd5b50610699600480360381019061069491906144f9565b611906565b005b3480156106a757600080fd5b506106c260048036038101906106bd9190614165565b611995565b6040516106cf91906141d3565b60405180910390f35b3480156106e457600080fd5b506106ff60048036038101906106fa9190614165565b6119ab565b005b34801561070d57600080fd5b5061072860048036038101906107239190614165565b611a31565b005b34801561073657600080fd5b50610751600480360381019061074c9190614349565b611ab7565b60405161075e9190614269565b60405180910390f35b34801561077357600080fd5b5061077c611b86565b005b34801561078a57600080fd5b506107a560048036038101906107a09190614349565b611c0e565b6040516107b29190614269565b60405180910390f35b3480156107c757600080fd5b506107d0611c26565b6040516107dd9190614269565b60405180910390f35b3480156107f257600080fd5b5061080d60048036038101906108089190614165565b611c2c565b005b34801561081b57600080fd5b506108366004803603810190610831919061421a565b611cb2565b005b34801561084457600080fd5b5061084d611d93565b60405161085a9190614269565b60405180910390f35b34801561086f57600080fd5b50610878611d99565b60405161088591906141d3565b60405180910390f35b34801561089a57600080fd5b506108b560048036038101906108b09190614165565b611dc2565b6040516108c291906145c5565b60405180910390f35b3480156108d757600080fd5b506108e0611dda565b6040516108ed919061410d565b60405180910390f35b610910600480360381019061090b9190614165565b611e6c565b005b34801561091e57600080fd5b506109396004803603810190610934919061460c565b612156565b005b34801561094757600080fd5b50610962600480360381019061095d9190614165565b6122cd565b005b34801561097057600080fd5b5061098b60048036038101906109869190614165565b612353565b005b34801561099957600080fd5b506109a26123d9565b6040516109af9190614665565b60405180910390f35b3480156109c457600080fd5b506109cd6123df565b005b3480156109db57600080fd5b506109f660048036038101906109f19190614165565b61255f565b604051610a039190614269565b60405180910390f35b348015610a1857600080fd5b50610a21612576565b604051610a2e9190614269565b60405180910390f35b348015610a4357600080fd5b50610a5e6004803603810190610a599190614721565b61257c565b005b348015610a6c57600080fd5b50610a876004803603810190610a8291906147d0565b612761565b005b348015610a9557600080fd5b50610ab06004803603810190610aab9190614165565b6127e7565b005b348015610abe57600080fd5b50610ad96004803603810190610ad491906144f9565b61286d565b005b348015610ae757600080fd5b50610b026004803603810190610afd9190614165565b6128fc565b604051610b0f919061410d565b60405180910390f35b348015610b2457600080fd5b50610b2d612a51565b604051610b3a9190614269565b60405180910390f35b348015610b4f57600080fd5b50610b6a6004803603810190610b659190614349565b612a57565b604051610b779190614269565b60405180910390f35b348015610b8c57600080fd5b50610ba76004803603810190610ba291906148c0565b612a69565b604051610bb49190614062565b60405180910390f35b348015610bc957600080fd5b50610be46004803603810190610bdf9190614165565b612aa6565b604051610bf19190614269565b60405180910390f35b348015610c0657600080fd5b50610c0f612abd565b604051610c1c9190614269565b60405180910390f35b348015610c3157600080fd5b50610c4c6004803603810190610c479190614165565b612ac3565b005b348015610c5a57600080fd5b50610c756004803603810190610c70919061491c565b612b49565b604051610c829190614062565b60405180910390f35b348015610c9757600080fd5b50610cb26004803603810190610cad9190614349565b612bdd565b005b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610d7f57507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610d8f5750610d8e82612cd4565b5b9050919050565b606060038054610da59061498b565b80601f0160208091040260200160405190810160405280929190818152602001828054610dd19061498b565b8015610e1e5780601f10610df357610100808354040283529160200191610e1e565b820191906000526020600020905b815481529060010190602001808311610e0157829003601f168201915b5050505050905090565b6000610e3382612d3e565b610e69576040517fcf4700e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000610eaf82611995565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f16576040517f943f7b8c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16610f35612d8c565b73ffffffffffffffffffffffffffffffffffffffff1614158015610f675750610f6581610f60612d8c565b612b49565b155b15610f9e576040517fcfb3b94200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610fa9838383612d94565b505050565b600b5481565b6001600f5414610ff9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ff090614a08565b60405180910390fd5b60195483611005611258565b61100f9190614a57565b1115611050576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161104790614afd565b60405180910390fd5b61109b828280806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505033612a69565b6110da576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110d190614b69565b60405180910390fd5b601754836110e89190614b89565b34101561112a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161112190614c17565b60405180910390fd5b60155483111561116f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161116690614c83565b60405180910390fd5b82601860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546111be9190614a57565b92505081905550601454601860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541115611249576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161124090614cef565b60405180910390fd5b6112533384612e46565b505050565b6000611262612e64565b6002546001540303905090565b60186020528060005260406000206000915090505481565b600f5481565b8260006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b111561145d573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036112ff576112fa848484612e6d565b611469565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b8152600401611348929190614d0f565b602060405180830381865afa158015611365573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113899190614d4d565b801561141b57506daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b81526004016113d9929190614d0f565b602060405180830381865afa1580156113f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061141a9190614d4d565b5b61145c57336040517fede71dcc00000000000000000000000000000000000000000000000000000000815260040161145391906141d3565b60405180910390fd5b5b611468848484612e6d565b5b50505050565b60175481565b61147d612d8c565b73ffffffffffffffffffffffffffffffffffffffff1661149b611d99565b73ffffffffffffffffffffffffffffffffffffffff16146114f1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114e890614dc6565b60405180910390fd5b600e54811115611536576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161152d90614e58565b60405180910390fd5b80600e60008282546115489190614e78565b925050819055506115593382612e46565b50565b611564612d8c565b73ffffffffffffffffffffffffffffffffffffffff16611582611d99565b73ffffffffffffffffffffffffffffffffffffffff16146115d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115cf90614dc6565b60405180910390fd5b80600b8190555050565b6115ea612d8c565b73ffffffffffffffffffffffffffffffffffffffff16611608611d99565b73ffffffffffffffffffffffffffffffffffffffff161461165e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161165590614dc6565b60405180910390fd5b6001601260006101000a81548160ff021916908315150217905550565b611683612d8c565b73ffffffffffffffffffffffffffffffffffffffff166116a1611d99565b73ffffffffffffffffffffffffffffffffffffffff16146116f7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116ee90614dc6565b60405180910390fd5b80600c8190555050565b8260006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b11156118d1573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036117735761176e848484612e7d565b6118dd565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b81526004016117bc929190614d0f565b602060405180830381865afa1580156117d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117fd9190614d4d565b801561188f57506daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b815260040161184d929190614d0f565b602060405180830381865afa15801561186a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061188e9190614d4d565b5b6118d057336040517fede71dcc0000000000000000000000000000000000000000000000000000000081526004016118c791906141d3565b60405180910390fd5b5b6118dc848484612e7d565b5b50505050565b6000600f54905090565b601260009054906101000a900460ff1681565b600a5481565b61190e612d8c565b73ffffffffffffffffffffffffffffffffffffffff1661192c611d99565b73ffffffffffffffffffffffffffffffffffffffff1614611982576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161197990614dc6565b60405180910390fd5b80601090816119919190615058565b5050565b60006119a082612e9d565b600001519050919050565b6119b3612d8c565b73ffffffffffffffffffffffffffffffffffffffff166119d1611d99565b73ffffffffffffffffffffffffffffffffffffffff1614611a27576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a1e90614dc6565b60405180910390fd5b80600f8190555050565b611a39612d8c565b73ffffffffffffffffffffffffffffffffffffffff16611a57611d99565b73ffffffffffffffffffffffffffffffffffffffff1614611aad576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611aa490614dc6565b60405180910390fd5b80600e8190555050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611b1e576040517f8f4eb60400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900467ffffffffffffffff1667ffffffffffffffff169050919050565b611b8e612d8c565b73ffffffffffffffffffffffffffffffffffffffff16611bac611d99565b73ffffffffffffffffffffffffffffffffffffffff1614611c02576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bf990614dc6565b60405180910390fd5b611c0c600061312c565b565b60136020528060005260406000206000915090505481565b60145481565b611c34612d8c565b73ffffffffffffffffffffffffffffffffffffffff16611c52611d99565b73ffffffffffffffffffffffffffffffffffffffff1614611ca8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c9f90614dc6565b60405180910390fd5b8060178190555050565b611cba612d8c565b73ffffffffffffffffffffffffffffffffffffffff16611cd8611d99565b73ffffffffffffffffffffffffffffffffffffffff1614611d2e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d2590614dc6565b60405180910390fd5b611e6181611d3a611258565b611d449190614a57565b1115611d85576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d7c90615176565b60405180910390fd5b611d8f8282612e46565b5050565b600c5481565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b611dca613f6b565b611dd382612e9d565b9050919050565b606060048054611de99061498b565b80601f0160208091040260200160405190810160405280929190818152602001828054611e159061498b565b8015611e625780601f10611e3757610100808354040283529160200191611e62565b820191906000526020600020905b815481529060010190602001808311611e4557829003601f168201915b5050505050905090565b3373ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff1614611eda576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ed1906151e2565b60405180910390fd5b6002600f5414611f1f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f169061524e565b60405180910390fd5b600e54611e61611f2f9190614e78565b81611f38611258565b611f429190614a57565b1115611f83576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f7a90615176565b60405180910390fd5b600d5481611f8f611258565b611f999190614a57565b1115611fda576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fd190615176565b60405180910390fd5b600a5481111561201f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161201690614c83565b60405180910390fd5b80600c5461202d9190614b89565b34101561206f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612066906152ba565b60405180910390fd5b80601360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546120be9190614a57565b92505081905550600b54601360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541115612149576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161214090614cef565b60405180910390fd5b6121533382612e46565b50565b61215e612d8c565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036121c2576040517fb06307db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600860006121cf612d8c565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff1661227c612d8c565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516122c19190614062565b60405180910390a35050565b6122d5612d8c565b73ffffffffffffffffffffffffffffffffffffffff166122f3611d99565b73ffffffffffffffffffffffffffffffffffffffff1614612349576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161234090614dc6565b60405180910390fd5b80600a8190555050565b61235b612d8c565b73ffffffffffffffffffffffffffffffffffffffff16612379611d99565b73ffffffffffffffffffffffffffffffffffffffff16146123cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123c690614dc6565b60405180910390fd5b8060148190555050565b60165481565b6123e7612d8c565b73ffffffffffffffffffffffffffffffffffffffff16612405611d99565b73ffffffffffffffffffffffffffffffffffffffff161461245b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161245290614dc6565b60405180910390fd5b6002600954036124a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161249790615326565b60405180910390fd5b600260098190555060003373ffffffffffffffffffffffffffffffffffffffff16476040516124ce90615377565b60006040518083038185875af1925050503d806000811461250b576040519150601f19603f3d011682016040523d82523d6000602084013e612510565b606091505b5050905080612554576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161254b906153d8565b60405180910390fd5b506001600981905550565b60006017548261256f9190614b89565b9050919050565b600d5481565b8360006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b111561274d573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036125ef576125ea858585856131f0565b61275a565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b8152600401612638929190614d0f565b602060405180830381865afa158015612655573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126799190614d4d565b801561270b57506daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b81526004016126c9929190614d0f565b602060405180830381865afa1580156126e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061270a9190614d4d565b5b61274c57336040517fede71dcc00000000000000000000000000000000000000000000000000000000815260040161274391906141d3565b60405180910390fd5b5b612759858585856131f0565b5b5050505050565b612769612d8c565b73ffffffffffffffffffffffffffffffffffffffff16612787611d99565b73ffffffffffffffffffffffffffffffffffffffff16146127dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127d490614dc6565b60405180910390fd5b8060168190555050565b6127ef612d8c565b73ffffffffffffffffffffffffffffffffffffffff1661280d611d99565b73ffffffffffffffffffffffffffffffffffffffff1614612863576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161285a90614dc6565b60405180910390fd5b8060158190555050565b612875612d8c565b73ffffffffffffffffffffffffffffffffffffffff16612893611d99565b73ffffffffffffffffffffffffffffffffffffffff16146128e9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128e090614dc6565b60405180910390fd5b80601190816128f89190615058565b5050565b606061290782612d3e565b612946576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161293d9061546a565b60405180910390fd5b60001515601260009054906101000a900460ff161515036129f3576011805461296e9061498b565b80601f016020809104026020016040519081016040528092919081815260200182805461299a9061498b565b80156129e75780601f106129bc576101008083540402835291602001916129e7565b820191906000526020600020905b8154815290600101906020018083116129ca57829003601f168201915b50505050509050612a4c565b60006129fd61326c565b90506000815111612a1d5760405180602001604052806000815250612a48565b80612a27846132fe565b604051602001612a3892919061555e565b6040516020818303038152906040525b9150505b919050565b600e5481565b6000612a628261345e565b9050919050565b6000612a9e8360165484604051602001612a8391906155e0565b604051602081830303815290604052805190602001206134c8565b905092915050565b6000600c5482612ab69190614b89565b9050919050565b60155481565b612acb612d8c565b73ffffffffffffffffffffffffffffffffffffffff16612ae9611d99565b73ffffffffffffffffffffffffffffffffffffffff1614612b3f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b3690614dc6565b60405180910390fd5b8060198190555050565b6000600860008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b612be5612d8c565b73ffffffffffffffffffffffffffffffffffffffff16612c03611d99565b73ffffffffffffffffffffffffffffffffffffffff1614612c59576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c5090614dc6565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612cc8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612cbf9061566d565b60405180910390fd5b612cd18161312c565b50565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b600081612d49612e64565b11158015612d58575060015482105b8015612d85575060056000838152602001908152602001600020600001601c9054906101000a900460ff16155b9050919050565b600033905090565b826007600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b612e608282604051806020016040528060008152506134df565b5050565b60006001905090565b612e788383836134f1565b505050565b612e988383836040518060200160405280600081525061257c565b505050565b612ea5613f6b565b600082905080612eb3612e64565b11158015612ec2575060015481105b156130f5576000600560008381526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160008201601c9054906101000a900460ff161515151581525050905080604001516130f357600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1614612fd7578092505050613127565b5b6001156130f257818060019003925050600560008381526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160008201601c9054906101000a900460ff1615151515815250509050600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff16146130ed578092505050613127565b612fd8565b5b505b6040517fdf2d9b4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6131fb8484846134f1565b61321a8373ffffffffffffffffffffffffffffffffffffffff166139a5565b801561322f575061322d848484846139b8565b155b15613266576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b60606010805461327b9061498b565b80601f01602080910402602001604051908101604052809291908181526020018280546132a79061498b565b80156132f45780601f106132c9576101008083540402835291602001916132f4565b820191906000526020600020905b8154815290600101906020018083116132d757829003601f168201915b5050505050905090565b606060008203613345576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050613459565b600082905060005b600082146133775780806133609061568d565b915050600a826133709190615704565b915061334d565b60008167ffffffffffffffff811115613393576133926143ce565b5b6040519080825280601f01601f1916602001820160405280156133c55781602001600182028036833780820191505090505b5090505b60008514613452576001826133de9190614e78565b9150600a856133ed9190615735565b60306133f99190614a57565b60f81b81838151811061340f5761340e615766565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a8561344b9190615704565b94506133c9565b8093505050505b919050565b6000600660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160089054906101000a900467ffffffffffffffff1667ffffffffffffffff169050919050565b6000826134d58584613b08565b1490509392505050565b6134ec8383836001613b7d565b505050565b60006134fc82612e9d565b90508373ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1614613567576040517fa114810000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008473ffffffffffffffffffffffffffffffffffffffff16613588612d8c565b73ffffffffffffffffffffffffffffffffffffffff1614806135b757506135b6856135b1612d8c565b612b49565b5b806135fc57506135c5612d8c565b73ffffffffffffffffffffffffffffffffffffffff166135e484610e28565b73ffffffffffffffffffffffffffffffffffffffff16145b905080613635576040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361369b576040517fea553b3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6136a88585856001613f48565b6136b460008487612d94565b6001600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160392506101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506001600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506000600560008581526020019081526020016000209050848160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550428160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060006001850190506000600560008381526020019081526020016000209050600073ffffffffffffffffffffffffffffffffffffffff168160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff160361393357600154821461393257878160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555084602001518160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505b5b505050828473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a461399e8585856001613f4e565b5050505050565b600080823b905060008111915050919050565b60008373ffffffffffffffffffffffffffffffffffffffff1663150b7a026139de612d8c565b8786866040518563ffffffff1660e01b8152600401613a0094939291906157ea565b6020604051808303816000875af1925050508015613a3c57506040513d601f19601f82011682018060405250810190613a39919061584b565b60015b613ab5573d8060008114613a6c576040519150601f19603f3d011682016040523d82523d6000602084013e613a71565b606091505b506000815103613aad576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050949350505050565b60008082905060005b8451811015613b72576000858281518110613b2f57613b2e615766565b5b60200260200101519050808311613b5157613b4a8382613f54565b9250613b5e565b613b5b8184613f54565b92505b508080613b6a9061568d565b915050613b11565b508091505092915050565b60006001549050600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603613bea576040517f2e07630000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008403613c24576040517fb562e8dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613c316000868387613f48565b83600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555083600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160088282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550846005600083815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550426005600083815260200190815260200160002060000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550600081905060008582019050838015613dfb5750613dfa8773ffffffffffffffffffffffffffffffffffffffff166139a5565b5b15613ec0575b818773ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4613e7060008884806001019550886139b8565b613ea6576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b808203613e01578260015414613ebb57600080fd5b613f2b565b5b818060010192508773ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4808203613ec1575b816001819055505050613f416000868387613f4e565b5050505050565b50505050565b50505050565b600082600052816020526040600020905092915050565b6040518060600160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600067ffffffffffffffff1681526020016000151581525090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b613ff781613fc2565b811461400257600080fd5b50565b60008135905061401481613fee565b92915050565b6000602082840312156140305761402f613fb8565b5b600061403e84828501614005565b91505092915050565b60008115159050919050565b61405c81614047565b82525050565b60006020820190506140776000830184614053565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156140b757808201518184015260208101905061409c565b60008484015250505050565b6000601f19601f8301169050919050565b60006140df8261407d565b6140e98185614088565b93506140f9818560208601614099565b614102816140c3565b840191505092915050565b6000602082019050818103600083015261412781846140d4565b905092915050565b6000819050919050565b6141428161412f565b811461414d57600080fd5b50565b60008135905061415f81614139565b92915050565b60006020828403121561417b5761417a613fb8565b5b600061418984828501614150565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006141bd82614192565b9050919050565b6141cd816141b2565b82525050565b60006020820190506141e860008301846141c4565b92915050565b6141f7816141b2565b811461420257600080fd5b50565b600081359050614214816141ee565b92915050565b6000806040838503121561423157614230613fb8565b5b600061423f85828601614205565b925050602061425085828601614150565b9150509250929050565b6142638161412f565b82525050565b600060208201905061427e600083018461425a565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126142a9576142a8614284565b5b8235905067ffffffffffffffff8111156142c6576142c5614289565b5b6020830191508360208202830111156142e2576142e161428e565b5b9250929050565b60008060006040848603121561430257614301613fb8565b5b600061431086828701614150565b935050602084013567ffffffffffffffff81111561433157614330613fbd565b5b61433d86828701614293565b92509250509250925092565b60006020828403121561435f5761435e613fb8565b5b600061436d84828501614205565b91505092915050565b60008060006060848603121561438f5761438e613fb8565b5b600061439d86828701614205565b93505060206143ae86828701614205565b92505060406143bf86828701614150565b9150509250925092565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b614406826140c3565b810181811067ffffffffffffffff82111715614425576144246143ce565b5b80604052505050565b6000614438613fae565b905061444482826143fd565b919050565b600067ffffffffffffffff821115614464576144636143ce565b5b61446d826140c3565b9050602081019050919050565b82818337600083830152505050565b600061449c61449784614449565b61442e565b9050828152602081018484840111156144b8576144b76143c9565b5b6144c384828561447a565b509392505050565b600082601f8301126144e0576144df614284565b5b81356144f0848260208601614489565b91505092915050565b60006020828403121561450f5761450e613fb8565b5b600082013567ffffffffffffffff81111561452d5761452c613fbd565b5b614539848285016144cb565b91505092915050565b61454b816141b2565b82525050565b600067ffffffffffffffff82169050919050565b61456e81614551565b82525050565b61457d81614047565b82525050565b6060820160008201516145996000850182614542565b5060208201516145ac6020850182614565565b5060408201516145bf6040850182614574565b50505050565b60006060820190506145da6000830184614583565b92915050565b6145e981614047565b81146145f457600080fd5b50565b600081359050614606816145e0565b92915050565b6000806040838503121561462357614622613fb8565b5b600061463185828601614205565b9250506020614642858286016145f7565b9150509250929050565b6000819050919050565b61465f8161464c565b82525050565b600060208201905061467a6000830184614656565b92915050565b600067ffffffffffffffff82111561469b5761469a6143ce565b5b6146a4826140c3565b9050602081019050919050565b60006146c46146bf84614680565b61442e565b9050828152602081018484840111156146e0576146df6143c9565b5b6146eb84828561447a565b509392505050565b600082601f83011261470857614707614284565b5b81356147188482602086016146b1565b91505092915050565b6000806000806080858703121561473b5761473a613fb8565b5b600061474987828801614205565b945050602061475a87828801614205565b935050604061476b87828801614150565b925050606085013567ffffffffffffffff81111561478c5761478b613fbd565b5b614798878288016146f3565b91505092959194509250565b6147ad8161464c565b81146147b857600080fd5b50565b6000813590506147ca816147a4565b92915050565b6000602082840312156147e6576147e5613fb8565b5b60006147f4848285016147bb565b91505092915050565b600067ffffffffffffffff821115614818576148176143ce565b5b602082029050602081019050919050565b600061483c614837846147fd565b61442e565b9050808382526020820190506020840283018581111561485f5761485e61428e565b5b835b81811015614888578061487488826147bb565b845260208401935050602081019050614861565b5050509392505050565b600082601f8301126148a7576148a6614284565b5b81356148b7848260208601614829565b91505092915050565b600080604083850312156148d7576148d6613fb8565b5b600083013567ffffffffffffffff8111156148f5576148f4613fbd565b5b61490185828601614892565b925050602061491285828601614205565b9150509250929050565b6000806040838503121561493357614932613fb8565b5b600061494185828601614205565b925050602061495285828601614205565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806149a357607f821691505b6020821081036149b6576149b561495c565b5b50919050565b7f53616c65206973206e6f74206163746976652000000000000000000000000000600082015250565b60006149f2601383614088565b91506149fd826149bc565b602082019050919050565b60006020820190508181036000830152614a21816149e5565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614a628261412f565b9150614a6d8361412f565b9250828201905080821115614a8557614a84614a28565b5b92915050565b7f5175616e74697479206d757374206265206c6573736572207468656e204d617860008201527f537570706c790000000000000000000000000000000000000000000000000000602082015250565b6000614ae7602683614088565b9150614af282614a8b565b604082019050919050565b60006020820190508181036000830152614b1681614ada565b9050919050565b7f596f7520617265206e6f7420696e2070726573616c6500000000000000000000600082015250565b6000614b53601683614088565b9150614b5e82614b1d565b602082019050919050565b60006020820190508181036000830152614b8281614b46565b9050919050565b6000614b948261412f565b9150614b9f8361412f565b9250828202614bad8161412f565b91508282048414831517614bc457614bc3614a28565b5b5092915050565b7f54727920746f2073656e64206d6f726520455448000000000000000000000000600082015250565b6000614c01601483614088565b9150614c0c82614bcb565b602082019050919050565b60006020820190508181036000830152614c3081614bf4565b9050919050565b7f63616e206e6f74206d696e742074686973206d616e7900000000000000000000600082015250565b6000614c6d601683614088565b9150614c7882614c37565b602082019050919050565b60006020820190508181036000830152614c9c81614c60565b9050919050565b7f50757263686173652065786365656473206d617820616c6c6f77656400000000600082015250565b6000614cd9601c83614088565b9150614ce482614ca3565b602082019050919050565b60006020820190508181036000830152614d0881614ccc565b9050919050565b6000604082019050614d2460008301856141c4565b614d3160208301846141c4565b9392505050565b600081519050614d47816145e0565b92915050565b600060208284031215614d6357614d62613fb8565b5b6000614d7184828501614d38565b91505092915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000614db0602083614088565b9150614dbb82614d7a565b602082019050919050565b60006020820190508181036000830152614ddf81614da3565b9050919050565b7f546865207175616e74697479206578636565647320746865207265736572766560008201527f2e00000000000000000000000000000000000000000000000000000000000000602082015250565b6000614e42602183614088565b9150614e4d82614de6565b604082019050919050565b60006020820190508181036000830152614e7181614e35565b9050919050565b6000614e838261412f565b9150614e8e8361412f565b9250828203905081811115614ea657614ea5614a28565b5b92915050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302614f0e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614ed1565b614f188683614ed1565b95508019841693508086168417925050509392505050565b6000819050919050565b6000614f55614f50614f4b8461412f565b614f30565b61412f565b9050919050565b6000819050919050565b614f6f83614f3a565b614f83614f7b82614f5c565b848454614ede565b825550505050565b600090565b614f98614f8b565b614fa3818484614f66565b505050565b5b81811015614fc757614fbc600082614f90565b600181019050614fa9565b5050565b601f82111561500c57614fdd81614eac565b614fe684614ec1565b81016020851015614ff5578190505b61500961500185614ec1565b830182614fa8565b50505b505050565b600082821c905092915050565b600061502f60001984600802615011565b1980831691505092915050565b6000615048838361501e565b9150826002028217905092915050565b6150618261407d565b67ffffffffffffffff81111561507a576150796143ce565b5b615084825461498b565b61508f828285614fcb565b600060209050601f8311600181146150c257600084156150b0578287015190505b6150ba858261503c565b865550615122565b601f1984166150d086614eac565b60005b828110156150f8578489015182556001820191506020850194506020810190506150d3565b868310156151155784890151615111601f89168261501e565b8355505b6001600288020188555050505b505050505050565b7f72656163686564206d617820737570706c790000000000000000000000000000600082015250565b6000615160601283614088565b915061516b8261512a565b602082019050919050565b6000602082019050818103600083015261518f81615153565b9050919050565b7f5468652063616c6c657220697320616e6f7468657220636f6e74726163740000600082015250565b60006151cc601e83614088565b91506151d782615196565b602082019050919050565b600060208201905081810360008301526151fb816151bf565b9050919050565b7f53616c65206973206e6f74204163746976650000000000000000000000000000600082015250565b6000615238601283614088565b915061524382615202565b602082019050919050565b600060208201905081810360008301526152678161522b565b9050919050565b7f4e65656420746f2073656e64206d6f7265204554482e00000000000000000000600082015250565b60006152a4601683614088565b91506152af8261526e565b602082019050919050565b600060208201905081810360008301526152d381615297565b9050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b6000615310601f83614088565b915061531b826152da565b602082019050919050565b6000602082019050818103600083015261533f81615303565b9050919050565b600081905092915050565b50565b6000615361600083615346565b915061536c82615351565b600082019050919050565b600061538282615354565b9150819050919050565b7f5472616e73666572206661696c65642e00000000000000000000000000000000600082015250565b60006153c2601083614088565b91506153cd8261538c565b602082019050919050565b600060208201905081810360008301526153f1816153b5565b9050919050565b7f4552433732314d657461646174613a2055524920717565727920666f72206e6f60008201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000602082015250565b6000615454602f83614088565b915061545f826153f8565b604082019050919050565b6000602082019050818103600083015261548381615447565b9050919050565b600081905092915050565b60006154a08261407d565b6154aa818561548a565b93506154ba818560208601614099565b80840191505092915050565b7f2f00000000000000000000000000000000000000000000000000000000000000600082015250565b60006154fc60018361548a565b9150615507826154c6565b600182019050919050565b7f2e6a736f6e000000000000000000000000000000000000000000000000000000600082015250565b600061554860058361548a565b915061555382615512565b600582019050919050565b600061556a8285615495565b9150615575826154ef565b91506155818284615495565b915061558c8261553b565b91508190509392505050565b60008160601b9050919050565b60006155b082615598565b9050919050565b60006155c2826155a5565b9050919050565b6155da6155d5826141b2565b6155b7565b82525050565b60006155ec82846155c9565b60148201915081905092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000615657602683614088565b9150615662826155fb565b604082019050919050565b600060208201905081810360008301526156868161564a565b9050919050565b60006156988261412f565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036156ca576156c9614a28565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061570f8261412f565b915061571a8361412f565b92508261572a576157296156d5565b5b828204905092915050565b60006157408261412f565b915061574b8361412f565b92508261575b5761575a6156d5565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081519050919050565b600082825260208201905092915050565b60006157bc82615795565b6157c681856157a0565b93506157d6818560208601614099565b6157df816140c3565b840191505092915050565b60006080820190506157ff60008301876141c4565b61580c60208301866141c4565b615819604083018561425a565b818103606083015261582b81846157b1565b905095945050505050565b60008151905061584581613fee565b92915050565b60006020828403121561586157615860613fb8565b5b600061586f84828501615836565b9150509291505056fea264697066735822122016e1a25eea7aa727a3fcb84dd68ae2b08d1a76aa092df56bfdacc70641ca77a164736f6c63430008110033

Deployed Bytecode

0x6080604052600436106103355760003560e01c80638825b014116101ab578063b333ca91116100f7578063dc33e68111610095578063e7d61da81161006f578063e7d61da814610bfa578063e8006bb014610c25578063e985e9c514610c4e578063f2fde38b14610c8b57610335565b8063dc33e68114610b43578063e5ec56a014610b80578063e757223014610bbd57610335565b8063c49e8062116100d1578063c49e806214610a89578063c7b8fca714610ab2578063c87b56dd14610adb578063cd3293de14610b1857610335565b8063b333ca9114610a0c578063b88d4fde14610a37578063bd32fb6614610a6057610335565b8063a0712d6811610164578063a5cdae2d1161013e578063a5cdae2d14610964578063aa98e0c61461098d578063ac446002146109b8578063aebceff4146109cf57610335565b8063a0712d68146108f6578063a22cb46514610912578063a40ece7a1461093b57610335565b80638825b014146107e65780638ba4cc3c1461080f5780638d859f3e146108385780638da5cb5b146108635780639231ab2a1461088e57806395d89b41146108cb57610335565b80632d5b005d116102855780636352211e1161022357806370a08231116101fd57806370a082311461072a578063715018a614610767578063752361431461077e578063852cbaee146107bb57610335565b80636352211e1461069b57806369ba1a75146106d85780636a44e1731461070157610335565b80634e69d5601161025f5780634e69d560146105f1578063518302271461061c57806351d7ff931461064757806355f804b31461067257610335565b80632d5b005d146105885780633fd173661461059f57806342842e0e146105c857610335565b806318160ddd116102f257806323b872dd116102cc57806323b872dd146104e25780632632d5f81461050b578063288bd8fd146105365780632ba2865b1461055f57610335565b806318160ddd1461044f5780631984b2861461047a578063200d2ed2146104b757610335565b806301ffc9a71461033a57806306fdde0314610377578063081812fc146103a2578063095ea7b3146103df5780630f2cdd6c1461040857806310157fc314610433575b600080fd5b34801561034657600080fd5b50610361600480360381019061035c919061401a565b610cb4565b60405161036e9190614062565b60405180910390f35b34801561038357600080fd5b5061038c610d96565b604051610399919061410d565b60405180910390f35b3480156103ae57600080fd5b506103c960048036038101906103c49190614165565b610e28565b6040516103d691906141d3565b60405180910390f35b3480156103eb57600080fd5b506104066004803603810190610401919061421a565b610ea4565b005b34801561041457600080fd5b5061041d610fae565b60405161042a9190614269565b60405180910390f35b61044d600480360381019061044891906142e9565b610fb4565b005b34801561045b57600080fd5b50610464611258565b6040516104719190614269565b60405180910390f35b34801561048657600080fd5b506104a1600480360381019061049c9190614349565b61126f565b6040516104ae9190614269565b60405180910390f35b3480156104c357600080fd5b506104cc611287565b6040516104d99190614269565b60405180910390f35b3480156104ee57600080fd5b5061050960048036038101906105049190614376565b61128d565b005b34801561051757600080fd5b5061052061146f565b60405161052d9190614269565b60405180910390f35b34801561054257600080fd5b5061055d60048036038101906105589190614165565b611475565b005b34801561056b57600080fd5b5061058660048036038101906105819190614165565b61155c565b005b34801561059457600080fd5b5061059d6115e2565b005b3480156105ab57600080fd5b506105c660048036038101906105c19190614165565b61167b565b005b3480156105d457600080fd5b506105ef60048036038101906105ea9190614376565b611701565b005b3480156105fd57600080fd5b506106066118e3565b6040516106139190614269565b60405180910390f35b34801561062857600080fd5b506106316118ed565b60405161063e9190614062565b60405180910390f35b34801561065357600080fd5b5061065c611900565b6040516106699190614269565b60405180910390f35b34801561067e57600080fd5b50610699600480360381019061069491906144f9565b611906565b005b3480156106a757600080fd5b506106c260048036038101906106bd9190614165565b611995565b6040516106cf91906141d3565b60405180910390f35b3480156106e457600080fd5b506106ff60048036038101906106fa9190614165565b6119ab565b005b34801561070d57600080fd5b5061072860048036038101906107239190614165565b611a31565b005b34801561073657600080fd5b50610751600480360381019061074c9190614349565b611ab7565b60405161075e9190614269565b60405180910390f35b34801561077357600080fd5b5061077c611b86565b005b34801561078a57600080fd5b506107a560048036038101906107a09190614349565b611c0e565b6040516107b29190614269565b60405180910390f35b3480156107c757600080fd5b506107d0611c26565b6040516107dd9190614269565b60405180910390f35b3480156107f257600080fd5b5061080d60048036038101906108089190614165565b611c2c565b005b34801561081b57600080fd5b506108366004803603810190610831919061421a565b611cb2565b005b34801561084457600080fd5b5061084d611d93565b60405161085a9190614269565b60405180910390f35b34801561086f57600080fd5b50610878611d99565b60405161088591906141d3565b60405180910390f35b34801561089a57600080fd5b506108b560048036038101906108b09190614165565b611dc2565b6040516108c291906145c5565b60405180910390f35b3480156108d757600080fd5b506108e0611dda565b6040516108ed919061410d565b60405180910390f35b610910600480360381019061090b9190614165565b611e6c565b005b34801561091e57600080fd5b506109396004803603810190610934919061460c565b612156565b005b34801561094757600080fd5b50610962600480360381019061095d9190614165565b6122cd565b005b34801561097057600080fd5b5061098b60048036038101906109869190614165565b612353565b005b34801561099957600080fd5b506109a26123d9565b6040516109af9190614665565b60405180910390f35b3480156109c457600080fd5b506109cd6123df565b005b3480156109db57600080fd5b506109f660048036038101906109f19190614165565b61255f565b604051610a039190614269565b60405180910390f35b348015610a1857600080fd5b50610a21612576565b604051610a2e9190614269565b60405180910390f35b348015610a4357600080fd5b50610a5e6004803603810190610a599190614721565b61257c565b005b348015610a6c57600080fd5b50610a876004803603810190610a8291906147d0565b612761565b005b348015610a9557600080fd5b50610ab06004803603810190610aab9190614165565b6127e7565b005b348015610abe57600080fd5b50610ad96004803603810190610ad491906144f9565b61286d565b005b348015610ae757600080fd5b50610b026004803603810190610afd9190614165565b6128fc565b604051610b0f919061410d565b60405180910390f35b348015610b2457600080fd5b50610b2d612a51565b604051610b3a9190614269565b60405180910390f35b348015610b4f57600080fd5b50610b6a6004803603810190610b659190614349565b612a57565b604051610b779190614269565b60405180910390f35b348015610b8c57600080fd5b50610ba76004803603810190610ba291906148c0565b612a69565b604051610bb49190614062565b60405180910390f35b348015610bc957600080fd5b50610be46004803603810190610bdf9190614165565b612aa6565b604051610bf19190614269565b60405180910390f35b348015610c0657600080fd5b50610c0f612abd565b604051610c1c9190614269565b60405180910390f35b348015610c3157600080fd5b50610c4c6004803603810190610c479190614165565b612ac3565b005b348015610c5a57600080fd5b50610c756004803603810190610c70919061491c565b612b49565b604051610c829190614062565b60405180910390f35b348015610c9757600080fd5b50610cb26004803603810190610cad9190614349565b612bdd565b005b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610d7f57507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610d8f5750610d8e82612cd4565b5b9050919050565b606060038054610da59061498b565b80601f0160208091040260200160405190810160405280929190818152602001828054610dd19061498b565b8015610e1e5780601f10610df357610100808354040283529160200191610e1e565b820191906000526020600020905b815481529060010190602001808311610e0157829003601f168201915b5050505050905090565b6000610e3382612d3e565b610e69576040517fcf4700e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000610eaf82611995565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f16576040517f943f7b8c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16610f35612d8c565b73ffffffffffffffffffffffffffffffffffffffff1614158015610f675750610f6581610f60612d8c565b612b49565b155b15610f9e576040517fcfb3b94200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610fa9838383612d94565b505050565b600b5481565b6001600f5414610ff9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ff090614a08565b60405180910390fd5b60195483611005611258565b61100f9190614a57565b1115611050576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161104790614afd565b60405180910390fd5b61109b828280806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505033612a69565b6110da576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110d190614b69565b60405180910390fd5b601754836110e89190614b89565b34101561112a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161112190614c17565b60405180910390fd5b60155483111561116f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161116690614c83565b60405180910390fd5b82601860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546111be9190614a57565b92505081905550601454601860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541115611249576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161124090614cef565b60405180910390fd5b6112533384612e46565b505050565b6000611262612e64565b6002546001540303905090565b60186020528060005260406000206000915090505481565b600f5481565b8260006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b111561145d573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036112ff576112fa848484612e6d565b611469565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b8152600401611348929190614d0f565b602060405180830381865afa158015611365573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113899190614d4d565b801561141b57506daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b81526004016113d9929190614d0f565b602060405180830381865afa1580156113f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061141a9190614d4d565b5b61145c57336040517fede71dcc00000000000000000000000000000000000000000000000000000000815260040161145391906141d3565b60405180910390fd5b5b611468848484612e6d565b5b50505050565b60175481565b61147d612d8c565b73ffffffffffffffffffffffffffffffffffffffff1661149b611d99565b73ffffffffffffffffffffffffffffffffffffffff16146114f1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114e890614dc6565b60405180910390fd5b600e54811115611536576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161152d90614e58565b60405180910390fd5b80600e60008282546115489190614e78565b925050819055506115593382612e46565b50565b611564612d8c565b73ffffffffffffffffffffffffffffffffffffffff16611582611d99565b73ffffffffffffffffffffffffffffffffffffffff16146115d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115cf90614dc6565b60405180910390fd5b80600b8190555050565b6115ea612d8c565b73ffffffffffffffffffffffffffffffffffffffff16611608611d99565b73ffffffffffffffffffffffffffffffffffffffff161461165e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161165590614dc6565b60405180910390fd5b6001601260006101000a81548160ff021916908315150217905550565b611683612d8c565b73ffffffffffffffffffffffffffffffffffffffff166116a1611d99565b73ffffffffffffffffffffffffffffffffffffffff16146116f7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116ee90614dc6565b60405180910390fd5b80600c8190555050565b8260006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b11156118d1573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036117735761176e848484612e7d565b6118dd565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b81526004016117bc929190614d0f565b602060405180830381865afa1580156117d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117fd9190614d4d565b801561188f57506daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b815260040161184d929190614d0f565b602060405180830381865afa15801561186a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061188e9190614d4d565b5b6118d057336040517fede71dcc0000000000000000000000000000000000000000000000000000000081526004016118c791906141d3565b60405180910390fd5b5b6118dc848484612e7d565b5b50505050565b6000600f54905090565b601260009054906101000a900460ff1681565b600a5481565b61190e612d8c565b73ffffffffffffffffffffffffffffffffffffffff1661192c611d99565b73ffffffffffffffffffffffffffffffffffffffff1614611982576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161197990614dc6565b60405180910390fd5b80601090816119919190615058565b5050565b60006119a082612e9d565b600001519050919050565b6119b3612d8c565b73ffffffffffffffffffffffffffffffffffffffff166119d1611d99565b73ffffffffffffffffffffffffffffffffffffffff1614611a27576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a1e90614dc6565b60405180910390fd5b80600f8190555050565b611a39612d8c565b73ffffffffffffffffffffffffffffffffffffffff16611a57611d99565b73ffffffffffffffffffffffffffffffffffffffff1614611aad576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611aa490614dc6565b60405180910390fd5b80600e8190555050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611b1e576040517f8f4eb60400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900467ffffffffffffffff1667ffffffffffffffff169050919050565b611b8e612d8c565b73ffffffffffffffffffffffffffffffffffffffff16611bac611d99565b73ffffffffffffffffffffffffffffffffffffffff1614611c02576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bf990614dc6565b60405180910390fd5b611c0c600061312c565b565b60136020528060005260406000206000915090505481565b60145481565b611c34612d8c565b73ffffffffffffffffffffffffffffffffffffffff16611c52611d99565b73ffffffffffffffffffffffffffffffffffffffff1614611ca8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c9f90614dc6565b60405180910390fd5b8060178190555050565b611cba612d8c565b73ffffffffffffffffffffffffffffffffffffffff16611cd8611d99565b73ffffffffffffffffffffffffffffffffffffffff1614611d2e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d2590614dc6565b60405180910390fd5b611e6181611d3a611258565b611d449190614a57565b1115611d85576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d7c90615176565b60405180910390fd5b611d8f8282612e46565b5050565b600c5481565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b611dca613f6b565b611dd382612e9d565b9050919050565b606060048054611de99061498b565b80601f0160208091040260200160405190810160405280929190818152602001828054611e159061498b565b8015611e625780601f10611e3757610100808354040283529160200191611e62565b820191906000526020600020905b815481529060010190602001808311611e4557829003601f168201915b5050505050905090565b3373ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff1614611eda576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ed1906151e2565b60405180910390fd5b6002600f5414611f1f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f169061524e565b60405180910390fd5b600e54611e61611f2f9190614e78565b81611f38611258565b611f429190614a57565b1115611f83576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f7a90615176565b60405180910390fd5b600d5481611f8f611258565b611f999190614a57565b1115611fda576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fd190615176565b60405180910390fd5b600a5481111561201f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161201690614c83565b60405180910390fd5b80600c5461202d9190614b89565b34101561206f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612066906152ba565b60405180910390fd5b80601360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546120be9190614a57565b92505081905550600b54601360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541115612149576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161214090614cef565b60405180910390fd5b6121533382612e46565b50565b61215e612d8c565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036121c2576040517fb06307db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600860006121cf612d8c565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff1661227c612d8c565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516122c19190614062565b60405180910390a35050565b6122d5612d8c565b73ffffffffffffffffffffffffffffffffffffffff166122f3611d99565b73ffffffffffffffffffffffffffffffffffffffff1614612349576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161234090614dc6565b60405180910390fd5b80600a8190555050565b61235b612d8c565b73ffffffffffffffffffffffffffffffffffffffff16612379611d99565b73ffffffffffffffffffffffffffffffffffffffff16146123cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123c690614dc6565b60405180910390fd5b8060148190555050565b60165481565b6123e7612d8c565b73ffffffffffffffffffffffffffffffffffffffff16612405611d99565b73ffffffffffffffffffffffffffffffffffffffff161461245b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161245290614dc6565b60405180910390fd5b6002600954036124a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161249790615326565b60405180910390fd5b600260098190555060003373ffffffffffffffffffffffffffffffffffffffff16476040516124ce90615377565b60006040518083038185875af1925050503d806000811461250b576040519150601f19603f3d011682016040523d82523d6000602084013e612510565b606091505b5050905080612554576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161254b906153d8565b60405180910390fd5b506001600981905550565b60006017548261256f9190614b89565b9050919050565b600d5481565b8360006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b111561274d573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036125ef576125ea858585856131f0565b61275a565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b8152600401612638929190614d0f565b602060405180830381865afa158015612655573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126799190614d4d565b801561270b57506daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b81526004016126c9929190614d0f565b602060405180830381865afa1580156126e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061270a9190614d4d565b5b61274c57336040517fede71dcc00000000000000000000000000000000000000000000000000000000815260040161274391906141d3565b60405180910390fd5b5b612759858585856131f0565b5b5050505050565b612769612d8c565b73ffffffffffffffffffffffffffffffffffffffff16612787611d99565b73ffffffffffffffffffffffffffffffffffffffff16146127dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127d490614dc6565b60405180910390fd5b8060168190555050565b6127ef612d8c565b73ffffffffffffffffffffffffffffffffffffffff1661280d611d99565b73ffffffffffffffffffffffffffffffffffffffff1614612863576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161285a90614dc6565b60405180910390fd5b8060158190555050565b612875612d8c565b73ffffffffffffffffffffffffffffffffffffffff16612893611d99565b73ffffffffffffffffffffffffffffffffffffffff16146128e9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128e090614dc6565b60405180910390fd5b80601190816128f89190615058565b5050565b606061290782612d3e565b612946576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161293d9061546a565b60405180910390fd5b60001515601260009054906101000a900460ff161515036129f3576011805461296e9061498b565b80601f016020809104026020016040519081016040528092919081815260200182805461299a9061498b565b80156129e75780601f106129bc576101008083540402835291602001916129e7565b820191906000526020600020905b8154815290600101906020018083116129ca57829003601f168201915b50505050509050612a4c565b60006129fd61326c565b90506000815111612a1d5760405180602001604052806000815250612a48565b80612a27846132fe565b604051602001612a3892919061555e565b6040516020818303038152906040525b9150505b919050565b600e5481565b6000612a628261345e565b9050919050565b6000612a9e8360165484604051602001612a8391906155e0565b604051602081830303815290604052805190602001206134c8565b905092915050565b6000600c5482612ab69190614b89565b9050919050565b60155481565b612acb612d8c565b73ffffffffffffffffffffffffffffffffffffffff16612ae9611d99565b73ffffffffffffffffffffffffffffffffffffffff1614612b3f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b3690614dc6565b60405180910390fd5b8060198190555050565b6000600860008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b612be5612d8c565b73ffffffffffffffffffffffffffffffffffffffff16612c03611d99565b73ffffffffffffffffffffffffffffffffffffffff1614612c59576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c5090614dc6565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612cc8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612cbf9061566d565b60405180910390fd5b612cd18161312c565b50565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b600081612d49612e64565b11158015612d58575060015482105b8015612d85575060056000838152602001908152602001600020600001601c9054906101000a900460ff16155b9050919050565b600033905090565b826007600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b612e608282604051806020016040528060008152506134df565b5050565b60006001905090565b612e788383836134f1565b505050565b612e988383836040518060200160405280600081525061257c565b505050565b612ea5613f6b565b600082905080612eb3612e64565b11158015612ec2575060015481105b156130f5576000600560008381526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160008201601c9054906101000a900460ff161515151581525050905080604001516130f357600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1614612fd7578092505050613127565b5b6001156130f257818060019003925050600560008381526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160008201601c9054906101000a900460ff1615151515815250509050600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff16146130ed578092505050613127565b612fd8565b5b505b6040517fdf2d9b4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6131fb8484846134f1565b61321a8373ffffffffffffffffffffffffffffffffffffffff166139a5565b801561322f575061322d848484846139b8565b155b15613266576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b60606010805461327b9061498b565b80601f01602080910402602001604051908101604052809291908181526020018280546132a79061498b565b80156132f45780601f106132c9576101008083540402835291602001916132f4565b820191906000526020600020905b8154815290600101906020018083116132d757829003601f168201915b5050505050905090565b606060008203613345576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050613459565b600082905060005b600082146133775780806133609061568d565b915050600a826133709190615704565b915061334d565b60008167ffffffffffffffff811115613393576133926143ce565b5b6040519080825280601f01601f1916602001820160405280156133c55781602001600182028036833780820191505090505b5090505b60008514613452576001826133de9190614e78565b9150600a856133ed9190615735565b60306133f99190614a57565b60f81b81838151811061340f5761340e615766565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a8561344b9190615704565b94506133c9565b8093505050505b919050565b6000600660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160089054906101000a900467ffffffffffffffff1667ffffffffffffffff169050919050565b6000826134d58584613b08565b1490509392505050565b6134ec8383836001613b7d565b505050565b60006134fc82612e9d565b90508373ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1614613567576040517fa114810000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008473ffffffffffffffffffffffffffffffffffffffff16613588612d8c565b73ffffffffffffffffffffffffffffffffffffffff1614806135b757506135b6856135b1612d8c565b612b49565b5b806135fc57506135c5612d8c565b73ffffffffffffffffffffffffffffffffffffffff166135e484610e28565b73ffffffffffffffffffffffffffffffffffffffff16145b905080613635576040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361369b576040517fea553b3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6136a88585856001613f48565b6136b460008487612d94565b6001600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160392506101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506001600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506000600560008581526020019081526020016000209050848160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550428160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060006001850190506000600560008381526020019081526020016000209050600073ffffffffffffffffffffffffffffffffffffffff168160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff160361393357600154821461393257878160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555084602001518160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505b5b505050828473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a461399e8585856001613f4e565b5050505050565b600080823b905060008111915050919050565b60008373ffffffffffffffffffffffffffffffffffffffff1663150b7a026139de612d8c565b8786866040518563ffffffff1660e01b8152600401613a0094939291906157ea565b6020604051808303816000875af1925050508015613a3c57506040513d601f19601f82011682018060405250810190613a39919061584b565b60015b613ab5573d8060008114613a6c576040519150601f19603f3d011682016040523d82523d6000602084013e613a71565b606091505b506000815103613aad576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050949350505050565b60008082905060005b8451811015613b72576000858281518110613b2f57613b2e615766565b5b60200260200101519050808311613b5157613b4a8382613f54565b9250613b5e565b613b5b8184613f54565b92505b508080613b6a9061568d565b915050613b11565b508091505092915050565b60006001549050600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603613bea576040517f2e07630000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008403613c24576040517fb562e8dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613c316000868387613f48565b83600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555083600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160088282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550846005600083815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550426005600083815260200190815260200160002060000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550600081905060008582019050838015613dfb5750613dfa8773ffffffffffffffffffffffffffffffffffffffff166139a5565b5b15613ec0575b818773ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4613e7060008884806001019550886139b8565b613ea6576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b808203613e01578260015414613ebb57600080fd5b613f2b565b5b818060010192508773ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4808203613ec1575b816001819055505050613f416000868387613f4e565b5050505050565b50505050565b50505050565b600082600052816020526040600020905092915050565b6040518060600160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600067ffffffffffffffff1681526020016000151581525090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b613ff781613fc2565b811461400257600080fd5b50565b60008135905061401481613fee565b92915050565b6000602082840312156140305761402f613fb8565b5b600061403e84828501614005565b91505092915050565b60008115159050919050565b61405c81614047565b82525050565b60006020820190506140776000830184614053565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156140b757808201518184015260208101905061409c565b60008484015250505050565b6000601f19601f8301169050919050565b60006140df8261407d565b6140e98185614088565b93506140f9818560208601614099565b614102816140c3565b840191505092915050565b6000602082019050818103600083015261412781846140d4565b905092915050565b6000819050919050565b6141428161412f565b811461414d57600080fd5b50565b60008135905061415f81614139565b92915050565b60006020828403121561417b5761417a613fb8565b5b600061418984828501614150565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006141bd82614192565b9050919050565b6141cd816141b2565b82525050565b60006020820190506141e860008301846141c4565b92915050565b6141f7816141b2565b811461420257600080fd5b50565b600081359050614214816141ee565b92915050565b6000806040838503121561423157614230613fb8565b5b600061423f85828601614205565b925050602061425085828601614150565b9150509250929050565b6142638161412f565b82525050565b600060208201905061427e600083018461425a565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126142a9576142a8614284565b5b8235905067ffffffffffffffff8111156142c6576142c5614289565b5b6020830191508360208202830111156142e2576142e161428e565b5b9250929050565b60008060006040848603121561430257614301613fb8565b5b600061431086828701614150565b935050602084013567ffffffffffffffff81111561433157614330613fbd565b5b61433d86828701614293565b92509250509250925092565b60006020828403121561435f5761435e613fb8565b5b600061436d84828501614205565b91505092915050565b60008060006060848603121561438f5761438e613fb8565b5b600061439d86828701614205565b93505060206143ae86828701614205565b92505060406143bf86828701614150565b9150509250925092565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b614406826140c3565b810181811067ffffffffffffffff82111715614425576144246143ce565b5b80604052505050565b6000614438613fae565b905061444482826143fd565b919050565b600067ffffffffffffffff821115614464576144636143ce565b5b61446d826140c3565b9050602081019050919050565b82818337600083830152505050565b600061449c61449784614449565b61442e565b9050828152602081018484840111156144b8576144b76143c9565b5b6144c384828561447a565b509392505050565b600082601f8301126144e0576144df614284565b5b81356144f0848260208601614489565b91505092915050565b60006020828403121561450f5761450e613fb8565b5b600082013567ffffffffffffffff81111561452d5761452c613fbd565b5b614539848285016144cb565b91505092915050565b61454b816141b2565b82525050565b600067ffffffffffffffff82169050919050565b61456e81614551565b82525050565b61457d81614047565b82525050565b6060820160008201516145996000850182614542565b5060208201516145ac6020850182614565565b5060408201516145bf6040850182614574565b50505050565b60006060820190506145da6000830184614583565b92915050565b6145e981614047565b81146145f457600080fd5b50565b600081359050614606816145e0565b92915050565b6000806040838503121561462357614622613fb8565b5b600061463185828601614205565b9250506020614642858286016145f7565b9150509250929050565b6000819050919050565b61465f8161464c565b82525050565b600060208201905061467a6000830184614656565b92915050565b600067ffffffffffffffff82111561469b5761469a6143ce565b5b6146a4826140c3565b9050602081019050919050565b60006146c46146bf84614680565b61442e565b9050828152602081018484840111156146e0576146df6143c9565b5b6146eb84828561447a565b509392505050565b600082601f83011261470857614707614284565b5b81356147188482602086016146b1565b91505092915050565b6000806000806080858703121561473b5761473a613fb8565b5b600061474987828801614205565b945050602061475a87828801614205565b935050604061476b87828801614150565b925050606085013567ffffffffffffffff81111561478c5761478b613fbd565b5b614798878288016146f3565b91505092959194509250565b6147ad8161464c565b81146147b857600080fd5b50565b6000813590506147ca816147a4565b92915050565b6000602082840312156147e6576147e5613fb8565b5b60006147f4848285016147bb565b91505092915050565b600067ffffffffffffffff821115614818576148176143ce565b5b602082029050602081019050919050565b600061483c614837846147fd565b61442e565b9050808382526020820190506020840283018581111561485f5761485e61428e565b5b835b81811015614888578061487488826147bb565b845260208401935050602081019050614861565b5050509392505050565b600082601f8301126148a7576148a6614284565b5b81356148b7848260208601614829565b91505092915050565b600080604083850312156148d7576148d6613fb8565b5b600083013567ffffffffffffffff8111156148f5576148f4613fbd565b5b61490185828601614892565b925050602061491285828601614205565b9150509250929050565b6000806040838503121561493357614932613fb8565b5b600061494185828601614205565b925050602061495285828601614205565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806149a357607f821691505b6020821081036149b6576149b561495c565b5b50919050565b7f53616c65206973206e6f74206163746976652000000000000000000000000000600082015250565b60006149f2601383614088565b91506149fd826149bc565b602082019050919050565b60006020820190508181036000830152614a21816149e5565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614a628261412f565b9150614a6d8361412f565b9250828201905080821115614a8557614a84614a28565b5b92915050565b7f5175616e74697479206d757374206265206c6573736572207468656e204d617860008201527f537570706c790000000000000000000000000000000000000000000000000000602082015250565b6000614ae7602683614088565b9150614af282614a8b565b604082019050919050565b60006020820190508181036000830152614b1681614ada565b9050919050565b7f596f7520617265206e6f7420696e2070726573616c6500000000000000000000600082015250565b6000614b53601683614088565b9150614b5e82614b1d565b602082019050919050565b60006020820190508181036000830152614b8281614b46565b9050919050565b6000614b948261412f565b9150614b9f8361412f565b9250828202614bad8161412f565b91508282048414831517614bc457614bc3614a28565b5b5092915050565b7f54727920746f2073656e64206d6f726520455448000000000000000000000000600082015250565b6000614c01601483614088565b9150614c0c82614bcb565b602082019050919050565b60006020820190508181036000830152614c3081614bf4565b9050919050565b7f63616e206e6f74206d696e742074686973206d616e7900000000000000000000600082015250565b6000614c6d601683614088565b9150614c7882614c37565b602082019050919050565b60006020820190508181036000830152614c9c81614c60565b9050919050565b7f50757263686173652065786365656473206d617820616c6c6f77656400000000600082015250565b6000614cd9601c83614088565b9150614ce482614ca3565b602082019050919050565b60006020820190508181036000830152614d0881614ccc565b9050919050565b6000604082019050614d2460008301856141c4565b614d3160208301846141c4565b9392505050565b600081519050614d47816145e0565b92915050565b600060208284031215614d6357614d62613fb8565b5b6000614d7184828501614d38565b91505092915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000614db0602083614088565b9150614dbb82614d7a565b602082019050919050565b60006020820190508181036000830152614ddf81614da3565b9050919050565b7f546865207175616e74697479206578636565647320746865207265736572766560008201527f2e00000000000000000000000000000000000000000000000000000000000000602082015250565b6000614e42602183614088565b9150614e4d82614de6565b604082019050919050565b60006020820190508181036000830152614e7181614e35565b9050919050565b6000614e838261412f565b9150614e8e8361412f565b9250828203905081811115614ea657614ea5614a28565b5b92915050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302614f0e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614ed1565b614f188683614ed1565b95508019841693508086168417925050509392505050565b6000819050919050565b6000614f55614f50614f4b8461412f565b614f30565b61412f565b9050919050565b6000819050919050565b614f6f83614f3a565b614f83614f7b82614f5c565b848454614ede565b825550505050565b600090565b614f98614f8b565b614fa3818484614f66565b505050565b5b81811015614fc757614fbc600082614f90565b600181019050614fa9565b5050565b601f82111561500c57614fdd81614eac565b614fe684614ec1565b81016020851015614ff5578190505b61500961500185614ec1565b830182614fa8565b50505b505050565b600082821c905092915050565b600061502f60001984600802615011565b1980831691505092915050565b6000615048838361501e565b9150826002028217905092915050565b6150618261407d565b67ffffffffffffffff81111561507a576150796143ce565b5b615084825461498b565b61508f828285614fcb565b600060209050601f8311600181146150c257600084156150b0578287015190505b6150ba858261503c565b865550615122565b601f1984166150d086614eac565b60005b828110156150f8578489015182556001820191506020850194506020810190506150d3565b868310156151155784890151615111601f89168261501e565b8355505b6001600288020188555050505b505050505050565b7f72656163686564206d617820737570706c790000000000000000000000000000600082015250565b6000615160601283614088565b915061516b8261512a565b602082019050919050565b6000602082019050818103600083015261518f81615153565b9050919050565b7f5468652063616c6c657220697320616e6f7468657220636f6e74726163740000600082015250565b60006151cc601e83614088565b91506151d782615196565b602082019050919050565b600060208201905081810360008301526151fb816151bf565b9050919050565b7f53616c65206973206e6f74204163746976650000000000000000000000000000600082015250565b6000615238601283614088565b915061524382615202565b602082019050919050565b600060208201905081810360008301526152678161522b565b9050919050565b7f4e65656420746f2073656e64206d6f7265204554482e00000000000000000000600082015250565b60006152a4601683614088565b91506152af8261526e565b602082019050919050565b600060208201905081810360008301526152d381615297565b9050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b6000615310601f83614088565b915061531b826152da565b602082019050919050565b6000602082019050818103600083015261533f81615303565b9050919050565b600081905092915050565b50565b6000615361600083615346565b915061536c82615351565b600082019050919050565b600061538282615354565b9150819050919050565b7f5472616e73666572206661696c65642e00000000000000000000000000000000600082015250565b60006153c2601083614088565b91506153cd8261538c565b602082019050919050565b600060208201905081810360008301526153f1816153b5565b9050919050565b7f4552433732314d657461646174613a2055524920717565727920666f72206e6f60008201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000602082015250565b6000615454602f83614088565b915061545f826153f8565b604082019050919050565b6000602082019050818103600083015261548381615447565b9050919050565b600081905092915050565b60006154a08261407d565b6154aa818561548a565b93506154ba818560208601614099565b80840191505092915050565b7f2f00000000000000000000000000000000000000000000000000000000000000600082015250565b60006154fc60018361548a565b9150615507826154c6565b600182019050919050565b7f2e6a736f6e000000000000000000000000000000000000000000000000000000600082015250565b600061554860058361548a565b915061555382615512565b600582019050919050565b600061556a8285615495565b9150615575826154ef565b91506155818284615495565b915061558c8261553b565b91508190509392505050565b60008160601b9050919050565b60006155b082615598565b9050919050565b60006155c2826155a5565b9050919050565b6155da6155d5826141b2565b6155b7565b82525050565b60006155ec82846155c9565b60148201915081905092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000615657602683614088565b9150615662826155fb565b604082019050919050565b600060208201905081810360008301526156868161564a565b9050919050565b60006156988261412f565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036156ca576156c9614a28565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061570f8261412f565b915061571a8361412f565b92508261572a576157296156d5565b5b828204905092915050565b60006157408261412f565b915061574b8361412f565b92508261575b5761575a6156d5565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081519050919050565b600082825260208201905092915050565b60006157bc82615795565b6157c681856157a0565b93506157d6818560208601614099565b6157df816140c3565b840191505092915050565b60006080820190506157ff60008301876141c4565b61580c60208301866141c4565b615819604083018561425a565b818103606083015261582b81846157b1565b905095945050505050565b60008151905061584581613fee565b92915050565b60006020828403121561586157615860613fb8565b5b600061586f84828501615836565b9150509291505056fea264697066735822122016e1a25eea7aa727a3fcb84dd68ae2b08d1a76aa092df56bfdacc70641ca77a164736f6c63430008110033

Deployed Bytecode Sourcemap

32006:6727:4:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14760:300;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;17788:98;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;19244:200;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;18821:362;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;32214:33;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;36824:696;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;14031:297;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;36199:53;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;32601:22;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;38097:191;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;36146:47;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;35522:212;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;35055:93;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;34015:79;;;;;;;;;;;;;:::i;:::-;;34846:95;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;38294:199;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;35227:71;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;32726:28;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;32123:38;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;34098:96;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;17603:123;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;35152:70;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;35301:96;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;15119:203;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;5066:101;;;;;;;;;;;;;:::i;:::-;;32759:50;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;35972:37;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;37804:132;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;35738:186;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;32296:33;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4851:85;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;34518:142;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;17950:102;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;32983:611;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;19511:282;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;34945:103;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;37526:136;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;36106:34;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;34664:178;;;;;;;;;;;;;:::i;:::-;;36475:139;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;32492:42;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;38499:232;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;36329:140;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;37942:109;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;34307:99;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;33599:409;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;32574:23;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;34410:105;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;36620:197;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;35405:114;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;36015:41;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;37669:129;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;19859:162;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;5174:198;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;14760:300;14862:4;14912:25;14897:40;;;:11;:40;;;;:104;;;;14968:33;14953:48;;;:11;:48;;;;14897:104;:156;;;;15017:36;15041:11;15017:23;:36::i;:::-;14897:156;14878:175;;14760:300;;;:::o;17788:98::-;17842:13;17874:5;17867:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17788:98;:::o;19244:200::-;19312:7;19336:16;19344:7;19336;:16::i;:::-;19331:64;;19361:34;;;;;;;;;;;;;;19331:64;19413:15;:24;19429:7;19413:24;;;;;;;;;;;;;;;;;;;;;19406:31;;19244:200;;;:::o;18821:362::-;18893:13;18909:24;18925:7;18909:15;:24::i;:::-;18893:40;;18953:5;18947:11;;:2;:11;;;18943:48;;18967:24;;;;;;;;;;;;;;18943:48;19022:5;19006:21;;:12;:10;:12::i;:::-;:21;;;;:63;;;;;19032:37;19049:5;19056:12;:10;:12::i;:::-;19032:16;:37::i;:::-;19031:38;19006:63;19002:136;;;19092:35;;;;;;;;;;;;;;19002:136;19148:28;19157:2;19161:7;19170:5;19148:8;:28::i;:::-;18883:300;18821:362;;:::o;32214:33::-;;;;:::o;36824:696::-;36947:1;36937:6;;:11;36929:44;;;;;;;;;;;;:::i;:::-;;;;;;;;;37015:16;;37005:8;36991:13;:11;:13::i;:::-;:22;;;;:::i;:::-;:40;;36983:90;;;;;;;;;;;;:::i;:::-;;;;;;;;;37091:31;37103:6;;37091:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;37111:10;37091:11;:31::i;:::-;37083:66;;;;;;;;;;;;:::i;:::-;;;;;;;;;37191:18;;37180:8;:29;;;;:::i;:::-;37167:9;:42;;37159:75;;;;;;;;;;;;:::i;:::-;;;;;;;;;37264:22;;37252:8;:34;;37244:70;;;;;;;;;;;;:::i;:::-;;;;;;;;;37359:8;37325:18;:30;37344:10;37325:30;;;;;;;;;;;;;;;;:42;;;;;;;:::i;:::-;;;;;;;;37419:18;;37385;:30;37404:10;37385:30;;;;;;;;;;;;;;;;:52;;37377:93;;;;;;;;;;;;:::i;:::-;;;;;;;;;37481:31;37491:10;37503:8;37481:9;:31::i;:::-;36824:696;;;:::o;14031:297::-;14075:7;14296:15;:13;:15::i;:::-;14281:12;;14265:13;;:28;:46;14258:53;;14031:297;:::o;36199:53::-;;;;;;;;;;;;;;;;;:::o;32601:22::-;;;;:::o;38097:191::-;38228:4;1603:1:7;310:42;1557:43;;;:47;1553:769;;;1840:10;1832:18;;:4;:18;;;1828:82;;38244:37:4::1;38263:4;38269:2;38273:7;38244:18;:37::i;:::-;1889:7:7::0;;1828:82;310:42;1946:40;;;2016:4;2043:10;1946:125;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:280;;;;;310:42;2095:40;;;2169:4;2200;2095:131;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1946:280;1923:389;;2286:10;2267:30;;;;;;;;;;;:::i;:::-;;;;;;;;1923:389;1553:769;38244:37:4::1;38263:4;38269:2;38273:7;38244:18;:37::i;:::-;38097:191:::0;;;;;:::o;36146:47::-;;;;:::o;35522:212::-;4992:12;:10;:12::i;:::-;4981:23;;:7;:5;:7::i;:::-;:23;;;4973:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;35611:7:::1;;35599:8;:19;;35591:65;;;;;;;;;;;;:::i;:::-;;;;;;;;;35677:8;35666:7;;:19;;;;;;;:::i;:::-;;;;;;;;35695:31;35705:10;35717:8;35695:9;:31::i;:::-;35522:212:::0;:::o;35055:93::-;4992:12;:10;:12::i;:::-;4981:23;;:7;:5;:7::i;:::-;:23;;;4973:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;35142:1:::1;35125:14;:18;;;;35055:93:::0;:::o;34015:79::-;4992:12;:10;:12::i;:::-;4981:23;;:7;:5;:7::i;:::-;:23;;;4973:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;34083:4:::1;34072:8;;:15;;;;;;;;;;;;;;;;;;34015:79::o:0;34846:95::-;4992:12;:10;:12::i;:::-;4981:23;;:7;:5;:7::i;:::-;:23;;;4973:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;34927:9:::1;34919:5;:17;;;;34846:95:::0;:::o;38294:199::-;38429:4;1603:1:7;310:42;1557:43;;;:47;1553:769;;;1840:10;1832:18;;:4;:18;;;1828:82;;38445:41:4::1;38468:4;38474:2;38478:7;38445:22;:41::i;:::-;1889:7:7::0;;1828:82;310:42;1946:40;;;2016:4;2043:10;1946:125;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:280;;;;;310:42;2095:40;;;2169:4;2200;2095:131;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1946:280;1923:389;;2286:10;2267:30;;;;;;;;;;;:::i;:::-;;;;;;;;1923:389;1553:769;38445:41:4::1;38468:4;38474:2;38478:7;38445:22;:41::i;:::-;38294:199:::0;;;;;:::o;35227:71::-;35267:4;35287:6;;35280:13;;35227:71;:::o;32726:28::-;;;;;;;;;;;;;:::o;32123:38::-;;;;:::o;34098:96::-;4992:12;:10;:12::i;:::-;4981:23;;:7;:5;:7::i;:::-;:23;;;4973:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;34182:7:::1;34166:13;:23;;;;;;:::i;:::-;;34098:96:::0;:::o;17603:123::-;17667:7;17693:21;17706:7;17693:12;:21::i;:::-;:26;;;17686:33;;17603:123;;;:::o;35152:70::-;4992:12;:10;:12::i;:::-;4981:23;;:7;:5;:7::i;:::-;:23;;;4973:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;35216:1:::1;35207:6;:10;;;;35152:70:::0;:::o;35301:96::-;4992:12;:10;:12::i;:::-;4981:23;;:7;:5;:7::i;:::-;:23;;;4973:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;35381:9:::1;35373:7;:17;;;;35301:96:::0;:::o;15119:203::-;15183:7;15223:1;15206:19;;:5;:19;;;15202:60;;15234:28;;;;;;;;;;;;;;15202:60;15287:12;:19;15300:5;15287:19;;;;;;;;;;;;;;;:27;;;;;;;;;;;;15279:36;;15272:43;;15119:203;;;:::o;5066:101::-;4992:12;:10;:12::i;:::-;4981:23;;:7;:5;:7::i;:::-;:23;;;4973:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;5130:30:::1;5157:1;5130:18;:30::i;:::-;5066:101::o:0;32759:50::-;;;;;;;;;;;;;;;;;:::o;35972:37::-;;;;:::o;37804:132::-;4992:12;:10;:12::i;:::-;4981:23;;:7;:5;:7::i;:::-;:23;;;4973:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;37910:19:::1;37889:18;:40;;;;37804:132:::0;:::o;35738:186::-;4992:12;:10;:12::i;:::-;4981:23;;:7;:5;:7::i;:::-;:23;;;4973:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;32383:4:::1;35831:8;35815:13;:11;:13::i;:::-;:24;;;;:::i;:::-;:48;;35807:79;;;;;;;;;;;;:::i;:::-;;;;;;;;;35892:27;35902:6;35910:8;35892:9;:27::i;:::-;35738:186:::0;;:::o;32296:33::-;;;;:::o;4851:85::-;4897:7;4923:6;;;;;;;;;;;4916:13;;4851:85;:::o;34518:142::-;34596:21;;:::i;:::-;34634;34647:7;34634:12;:21::i;:::-;34627:28;;34518:142;;;:::o;17950:102::-;18006:13;18038:7;18031:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17950:102;:::o;32983:611::-;32921:10;32908:23;;:9;:23;;;32900:66;;;;;;;;;;;;:::i;:::-;;;;;;;;;33069:1:::1;33059:6;;:11;33051:43;;;;;;;;;;;;:::i;:::-;;;;;;;;;33157:7;;32383:4;33136:28;;;;:::i;:::-;33124:8;33108:13;:11;:13::i;:::-;:24;;;;:::i;:::-;:56;;33100:87;;;;;;;;;;;;:::i;:::-;;;;;;;;;33229:20;;33217:8;33201:13;:11;:13::i;:::-;:24;;;;:::i;:::-;:48;;33193:79;;;;;;;;;;;;:::i;:::-;;;;;;;;;33298:19;;33286:8;:31;;33278:65;;;;;;;;;;;;:::i;:::-;;;;;;;;;33378:8;33370:5;;:16;;;;:::i;:::-;33357:9;:29;;33349:64;;;;;;;;;;;;:::i;:::-;;;;;;;;;33451:8;33420:15;:27;33436:10;33420:27;;;;;;;;;;;;;;;;:39;;;;;;;:::i;:::-;;;;;;;;33504:14;;33473:15;:27;33489:10;33473:27;;;;;;;;;;;;;;;;:45;;33465:86;;;;;;;;;;;;:::i;:::-;;;;;;;;;33558:31;33568:10;33580:8;33558:9;:31::i;:::-;32983:611:::0;:::o;19511:282::-;19621:12;:10;:12::i;:::-;19609:24;;:8;:24;;;19605:54;;19642:17;;;;;;;;;;;;;;19605:54;19715:8;19670:18;:32;19689:12;:10;:12::i;:::-;19670:32;;;;;;;;;;;;;;;:42;19703:8;19670:42;;;;;;;;;;;;;;;;:53;;;;;;;;;;;;;;;;;;19767:8;19738:48;;19753:12;:10;:12::i;:::-;19738:48;;;19777:8;19738:48;;;;;;:::i;:::-;;;;;;;;19511:282;;:::o;34945:103::-;4992:12;:10;:12::i;:::-;4981:23;;:7;:5;:7::i;:::-;:23;;;4973:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;35042:1:::1;35020:19;:23;;;;34945:103:::0;:::o;37526:136::-;4992:12;:10;:12::i;:::-;4981:23;;:7;:5;:7::i;:::-;:23;;;4973:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;37636:19:::1;37615:18;:40;;;;37526:136:::0;:::o;36106:34::-;;;;:::o;34664:178::-;4992:12;:10;:12::i;:::-;4981:23;;:7;:5;:7::i;:::-;:23;;;4973:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;2716:1:::1;2854:7;;:19:::0;2846:63:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;2716:1;2914:7;:18;;;;34728:12:::2;34746:10;:15;;34769:21;34746:49;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34727:68;;;34809:7;34801:36;;;;;;;;;;;;:::i;:::-;;;;;;;;;34721:121;2673:1:::1;2954:7;:22;;;;34664:178::o:0;36475:139::-;36542:7;36589:18;;36579:9;:28;;;;:::i;:::-;36572:35;;36475:139;;;:::o;32492:42::-;;;;:::o;38499:232::-;38661:4;1603:1:7;310:42;1557:43;;;:47;1553:769;;;1840:10;1832:18;;:4;:18;;;1828:82;;38677:47:4::1;38700:4;38706:2;38710:7;38719:4;38677:22;:47::i;:::-;1889:7:7::0;;1828:82;310:42;1946:40;;;2016:4;2043:10;1946:125;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:280;;;;;310:42;2095:40;;;2169:4;2200;2095:131;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1946:280;1923:389;;2286:10;2267:30;;;;;;;;;;;:::i;:::-;;;;;;;;1923:389;1553:769;38677:47:4::1;38700:4;38706:2;38710:7;38719:4;38677:22;:47::i;:::-;38499:232:::0;;;;;;:::o;36329:140::-;4992:12;:10;:12::i;:::-;4981:23;;:7;:5;:7::i;:::-;:23;;;4973:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;36442:20:::1;36420:19;:42;;;;36329:140:::0;:::o;37942:109::-;4992:12;:10;:12::i;:::-;4981:23;;:7;:5;:7::i;:::-;:23;;;4973:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;38045:1:::1;38020:22;:26;;;;37942:109:::0;:::o;34307:99::-;4992:12;:10;:12::i;:::-;4981:23;;:7;:5;:7::i;:::-;:23;;;4973:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;34398:3:::1;34379:16;:22;;;;;;:::i;:::-;;34307:99:::0;:::o;33599:409::-;33672:13;33701:16;33709:7;33701;:16::i;:::-;33693:75;;;;;;;;;;;;:::i;:::-;;;;;;;;;33790:5;33778:17;;:8;;;;;;;;;;;:17;;;33775:61;;33813:16;33806:23;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33775:61;33842:21;33866:10;:8;:10::i;:::-;33842:34;;33919:1;33901:7;33895:21;:25;:108;;;;;;;;;;;;;;;;;33955:7;33969:18;:7;:16;:18::i;:::-;33938:59;;;;;;;;;:::i;:::-;;;;;;;;;;;;;33895:108;33882:121;;;33599:409;;;;:::o;32574:23::-;;;;:::o;34410:105::-;34468:7;34490:20;34504:5;34490:13;:20::i;:::-;34483:27;;34410:105;;;:::o;36620:197::-;36703:4;36726:84;36745:6;36753:19;;36801:6;36784:24;;;;;;;;:::i;:::-;;;;;;;;;;;;;36774:35;;;;;;36726:18;:84::i;:::-;36719:91;;36620:197;;;;:::o;35405:114::-;35463:7;35507:5;;35497:9;:15;;;;:::i;:::-;35490:22;;35405:114;;;:::o;36015:41::-;;;;:::o;37669:129::-;4992:12;:10;:12::i;:::-;4981:23;;:7;:5;:7::i;:::-;:23;;;4973:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;37771:20:::1;37752:16;:39;;;;37669:129:::0;:::o;19859:162::-;19956:4;19979:18;:25;19998:5;19979:25;;;;;;;;;;;;;;;:35;20005:8;19979:35;;;;;;;;;;;;;;;;;;;;;;;;;19972:42;;19859:162;;;;:::o;5174:198::-;4992:12;:10;:12::i;:::-;4981:23;;:7;:5;:7::i;:::-;:23;;;4973:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;5282:1:::1;5262:22;;:8;:22;;::::0;5254:73:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;5337:28;5356:8;5337:18;:28::i;:::-;5174:198:::0;:::o;9369:155::-;9454:4;9492:25;9477:40;;;:11;:40;;;;9470:47;;9369:155;;;:::o;21163:172::-;21220:4;21262:7;21243:15;:13;:15::i;:::-;:26;;:53;;;;;21283:13;;21273:7;:23;21243:53;:85;;;;;21301:11;:20;21313:7;21301:20;;;;;;;;;;;:27;;;;;;;;;;;;21300:28;21243:85;21236:92;;21163:172;;;:::o;4412:96::-;4465:7;4491:10;4484:17;;4412:96;:::o;29103:189::-;29240:2;29213:15;:24;29229:7;29213:24;;;;;;;;;;;;:29;;;;;;;;;;;;;;;;;;29277:7;29273:2;29257:28;;29266:5;29257:28;;;;;;;;;;;;29103:189;;;:::o;21341:102::-;21409:27;21419:2;21423:8;21409:27;;;;;;;;;;;;:9;:27::i;:::-;21341:102;;:::o;13812:90::-;13868:7;13894:1;13887:8;;13812:90;:::o;20083:164::-;20212:28;20222:4;20228:2;20232:7;20212:9;:28::i;:::-;20083:164;;;:::o;20313:179::-;20446:39;20463:4;20469:2;20473:7;20446:39;;;;;;;;;;;;:16;:39::i;:::-;20313:179;;;:::o;16462:1084::-;16524:21;;:::i;:::-;16557:12;16572:7;16557:22;;16637:4;16618:15;:13;:15::i;:::-;:23;;:47;;;;;16652:13;;16645:4;:20;16618:47;16614:868;;;16685:31;16719:11;:17;16731:4;16719:17;;;;;;;;;;;16685:51;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;16759:9;:16;;;16754:714;;16829:1;16803:28;;:9;:14;;;:28;;;16799:99;;16866:9;16859:16;;;;;;16799:99;17195:255;17202:4;17195:255;;;17234:6;;;;;;;;17278:11;:17;17290:4;17278:17;;;;;;;;;;;17266:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17351:1;17325:28;;:9;:14;;;:28;;;17321:107;;17392:9;17385:16;;;;;;17321:107;17195:255;;;16754:714;16667:815;16614:868;17508:31;;;;;;;;;;;;;;16462:1084;;;;:::o;5379:187::-;5452:16;5471:6;;;;;;;;;;;5452:25;;5496:8;5487:6;;:17;;;;;;;;;;;;;;;;;;5550:8;5519:40;;5540:8;5519:40;;;;;;;;;;;;5442:124;5379:187;:::o;20558:359::-;20719:28;20729:4;20735:2;20739:7;20719:9;:28::i;:::-;20761:15;:2;:13;;;:15::i;:::-;:76;;;;;20781:56;20812:4;20818:2;20822:7;20831:5;20781:30;:56::i;:::-;20780:57;20761:76;20757:154;;;20860:40;;;;;;;;;;;;;;20757:154;20558:359;;;;:::o;34197:106::-;34257:13;34285;34278:20;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34197:106;:::o;3075:516::-;3131:13;3170:1;3161:5;:10;3157:51;;3187:10;;;;;;;;;;;;;;;;;;;;;3157:51;3217:12;3232:5;3217:20;;3247:14;3271:75;3286:1;3278:4;:9;3271:75;;3303:8;;;;;:::i;:::-;;;;3333:2;3325:10;;;;;:::i;:::-;;;3271:75;;;3355:19;3387:6;3377:17;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3355:39;;3404:150;3420:1;3411:5;:10;3404:150;;3447:1;3437:11;;;;;:::i;:::-;;;3513:2;3505:5;:10;;;;:::i;:::-;3492:2;:24;;;;:::i;:::-;3479:39;;3462:6;3469;3462:14;;;;;;;;:::i;:::-;;;;;:56;;;;;;;;;;;3541:2;3532:11;;;;;:::i;:::-;;;3404:150;;;3577:6;3563:21;;;;;3075:516;;;;:::o;15399:135::-;15460:7;15494:12;:19;15507:5;15494:19;;;;;;;;;;;;;;;:32;;;;;;;;;;;;15486:41;;15479:48;;15399:135;;;:::o;1141:184::-;1262:4;1314;1285:25;1298:5;1305:4;1285:12;:25::i;:::-;:33;1278:40;;1141:184;;;;;:::o;21794:157::-;21912:32;21918:2;21922:8;21932:5;21939:4;21912:5;:32::i;:::-;21794:157;;;:::o;24173:2082::-;24283:35;24321:21;24334:7;24321:12;:21::i;:::-;24283:59;;24379:4;24357:26;;:13;:18;;;:26;;;24353:67;;24392:28;;;;;;;;;;;;;;24353:67;24431:22;24473:4;24457:20;;:12;:10;:12::i;:::-;:20;;;:72;;;;24493:36;24510:4;24516:12;:10;:12::i;:::-;24493:16;:36::i;:::-;24457:72;:124;;;;24569:12;:10;:12::i;:::-;24545:36;;:20;24557:7;24545:11;:20::i;:::-;:36;;;24457:124;24431:151;;24598:17;24593:66;;24624:35;;;;;;;;;;;;;;24593:66;24687:1;24673:16;;:2;:16;;;24669:52;;24698:23;;;;;;;;;;;;;;24669:52;24732:43;24754:4;24760:2;24764:7;24773:1;24732:21;:43::i;:::-;24837:35;24854:1;24858:7;24867:4;24837:8;:35::i;:::-;25192:1;25162:12;:18;25175:4;25162:18;;;;;;;;;;;;;;;:26;;;:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;25235:1;25207:12;:16;25220:2;25207:16;;;;;;;;;;;;;;;:24;;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;25251:31;25285:11;:20;25297:7;25285:20;;;;;;;;;;;25251:54;;25335:2;25319:8;:13;;;:18;;;;;;;;;;;;;;;;;;25384:15;25351:8;:23;;;:49;;;;;;;;;;;;;;;;;;25648:19;25680:1;25670:7;:11;25648:33;;25695:31;25729:11;:24;25741:11;25729:24;;;;;;;;;;;25695:58;;25796:1;25771:27;;:8;:13;;;;;;;;;;;;:27;;;25767:377;;25978:13;;25963:11;:28;25959:171;;26031:4;26015:8;:13;;;:20;;;;;;;;;;;;;;;;;;26083:13;:28;;;26057:8;:23;;;:54;;;;;;;;;;;;;;;;;;25959:171;25767:377;25138:1016;;;26188:7;26184:2;26169:27;;26178:4;26169:27;;;;;;;;;;;;26206:42;26227:4;26233:2;26237:7;26246:1;26206:20;:42::i;:::-;24273:1982;;24173:2082;;;:::o;5594:191::-;5654:4;5671:12;5736:7;5724:20;5716:28;;5777:1;5770:4;:8;5763:15;;;5594:191;;;:::o;29773:650::-;29931:4;29967:2;29951:36;;;29988:12;:10;:12::i;:::-;30002:4;30008:7;30017:5;29951:72;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;29947:470;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30199:1;30182:6;:13;:18;30178:229;;30227:40;;;;;;;;;;;;;;30178:229;30367:6;30361:13;30352:6;30348:2;30344:15;30337:38;29947:470;30079:45;;;30069:55;;;:6;:55;;;;30062:62;;;29773:650;;;;;;:::o;1676:662::-;1759:7;1778:20;1801:4;1778:27;;1820:9;1815:488;1839:5;:12;1835:1;:16;1815:488;;;1872:20;1895:5;1901:1;1895:8;;;;;;;;:::i;:::-;;;;;;;;1872:31;;1937:12;1921;:28;1917:376;;2062:42;2077:12;2091;2062:14;:42::i;:::-;2047:57;;1917:376;;;2236:42;2251:12;2265;2236:14;:42::i;:::-;2221:57;;1917:376;1858:445;1853:3;;;;;:::i;:::-;;;;1815:488;;;;2319:12;2312:19;;;1676:662;;;;:::o;22198:1733::-;22331:20;22354:13;;22331:36;;22395:1;22381:16;;:2;:16;;;22377:48;;22406:19;;;;;;;;;;;;;;22377:48;22451:1;22439:8;:13;22435:44;;22461:18;;;;;;;;;;;;;;22435:44;22490:61;22520:1;22524:2;22528:12;22542:8;22490:21;:61::i;:::-;22857:8;22822:12;:16;22835:2;22822:16;;;;;;;;;;;;;;;:24;;;:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22920:8;22880:12;:16;22893:2;22880:16;;;;;;;;;;;;;;;:29;;;:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22977:2;22944:11;:25;22956:12;22944:25;;;;;;;;;;;:30;;;:35;;;;;;;;;;;;;;;;;;23043:15;22993:11;:25;23005:12;22993:25;;;;;;;;;;;:40;;;:66;;;;;;;;;;;;;;;;;;23074:20;23097:12;23074:35;;23123:11;23152:8;23137:12;:23;23123:37;;23179:4;:23;;;;;23187:15;:2;:13;;;:15::i;:::-;23179:23;23175:628;;;23222:309;23277:12;23273:2;23252:38;;23269:1;23252:38;;;;;;;;;;;;23317:69;23356:1;23360:2;23364:14;;;;;;23380:5;23317:30;:69::i;:::-;23312:172;;23421:40;;;;;;;;;;;;;;23312:172;23526:3;23510:12;:19;23222:309;;23610:12;23593:13;;:29;23589:43;;23624:8;;;23589:43;23175:628;;;23671:118;23726:14;;;;;;23722:2;23701:40;;23718:1;23701:40;;;;;;;;;;;;23784:3;23768:12;:19;23671:118;;23175:628;23832:12;23816:13;:28;;;;22798:1057;;23864:60;23893:1;23897:2;23901:12;23915:8;23864:20;:60::i;:::-;22321:1610;22198:1733;;;;:::o;31054:154::-;;;;;:::o;31849:153::-;;;;;:::o;2344:218::-;2412:13;2473:1;2467:4;2460:15;2501:1;2495:4;2488:15;2541:4;2535;2525:21;2516:30;;2344:218;;;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;7:75:11:-;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:149;370:7;410:66;403:5;399:78;388:89;;334:149;;;:::o;489:120::-;561:23;578:5;561:23;:::i;:::-;554:5;551:34;541:62;;599:1;596;589:12;541:62;489:120;:::o;615:137::-;660:5;698:6;685:20;676:29;;714:32;740:5;714:32;:::i;:::-;615:137;;;;:::o;758:327::-;816:6;865:2;853:9;844:7;840:23;836:32;833:119;;;871:79;;:::i;:::-;833:119;991:1;1016:52;1060:7;1051:6;1040:9;1036:22;1016:52;:::i;:::-;1006:62;;962:116;758:327;;;;:::o;1091:90::-;1125:7;1168:5;1161:13;1154:21;1143:32;;1091:90;;;:::o;1187:109::-;1268:21;1283:5;1268:21;:::i;:::-;1263:3;1256:34;1187:109;;:::o;1302:210::-;1389:4;1427:2;1416:9;1412:18;1404:26;;1440:65;1502:1;1491:9;1487:17;1478:6;1440:65;:::i;:::-;1302:210;;;;:::o;1518:99::-;1570:6;1604:5;1598:12;1588:22;;1518:99;;;:::o;1623:169::-;1707:11;1741:6;1736:3;1729:19;1781:4;1776:3;1772:14;1757:29;;1623:169;;;;:::o;1798:246::-;1879:1;1889:113;1903:6;1900:1;1897:13;1889:113;;;1988:1;1983:3;1979:11;1973:18;1969:1;1964:3;1960:11;1953:39;1925:2;1922:1;1918:10;1913:15;;1889:113;;;2036:1;2027:6;2022:3;2018:16;2011:27;1860:184;1798:246;;;:::o;2050:102::-;2091:6;2142:2;2138:7;2133:2;2126:5;2122:14;2118:28;2108:38;;2050:102;;;:::o;2158:377::-;2246:3;2274:39;2307:5;2274:39;:::i;:::-;2329:71;2393:6;2388:3;2329:71;:::i;:::-;2322:78;;2409:65;2467:6;2462:3;2455:4;2448:5;2444:16;2409:65;:::i;:::-;2499:29;2521:6;2499:29;:::i;:::-;2494:3;2490:39;2483:46;;2250:285;2158:377;;;;:::o;2541:313::-;2654:4;2692:2;2681:9;2677:18;2669:26;;2741:9;2735:4;2731:20;2727:1;2716:9;2712:17;2705:47;2769:78;2842:4;2833:6;2769:78;:::i;:::-;2761:86;;2541:313;;;;:::o;2860:77::-;2897:7;2926:5;2915:16;;2860:77;;;:::o;2943:122::-;3016:24;3034:5;3016:24;:::i;:::-;3009:5;3006:35;2996:63;;3055:1;3052;3045:12;2996:63;2943:122;:::o;3071:139::-;3117:5;3155:6;3142:20;3133:29;;3171:33;3198:5;3171:33;:::i;:::-;3071:139;;;;:::o;3216:329::-;3275:6;3324:2;3312:9;3303:7;3299:23;3295:32;3292:119;;;3330:79;;:::i;:::-;3292:119;3450:1;3475:53;3520:7;3511:6;3500:9;3496:22;3475:53;:::i;:::-;3465:63;;3421:117;3216:329;;;;:::o;3551:126::-;3588:7;3628:42;3621:5;3617:54;3606:65;;3551:126;;;:::o;3683:96::-;3720:7;3749:24;3767:5;3749:24;:::i;:::-;3738:35;;3683:96;;;:::o;3785:118::-;3872:24;3890:5;3872:24;:::i;:::-;3867:3;3860:37;3785:118;;:::o;3909:222::-;4002:4;4040:2;4029:9;4025:18;4017:26;;4053:71;4121:1;4110:9;4106:17;4097:6;4053:71;:::i;:::-;3909:222;;;;:::o;4137:122::-;4210:24;4228:5;4210:24;:::i;:::-;4203:5;4200:35;4190:63;;4249:1;4246;4239:12;4190:63;4137:122;:::o;4265:139::-;4311:5;4349:6;4336:20;4327:29;;4365:33;4392:5;4365:33;:::i;:::-;4265:139;;;;:::o;4410:474::-;4478:6;4486;4535:2;4523:9;4514:7;4510:23;4506:32;4503:119;;;4541:79;;:::i;:::-;4503:119;4661:1;4686:53;4731:7;4722:6;4711:9;4707:22;4686:53;:::i;:::-;4676:63;;4632:117;4788:2;4814:53;4859:7;4850:6;4839:9;4835:22;4814:53;:::i;:::-;4804:63;;4759:118;4410:474;;;;;:::o;4890:118::-;4977:24;4995:5;4977:24;:::i;:::-;4972:3;4965:37;4890:118;;:::o;5014:222::-;5107:4;5145:2;5134:9;5130:18;5122:26;;5158:71;5226:1;5215:9;5211:17;5202:6;5158:71;:::i;:::-;5014:222;;;;:::o;5242:117::-;5351:1;5348;5341:12;5365:117;5474:1;5471;5464:12;5488:117;5597:1;5594;5587:12;5628:568;5701:8;5711:6;5761:3;5754:4;5746:6;5742:17;5738:27;5728:122;;5769:79;;:::i;:::-;5728:122;5882:6;5869:20;5859:30;;5912:18;5904:6;5901:30;5898:117;;;5934:79;;:::i;:::-;5898:117;6048:4;6040:6;6036:17;6024:29;;6102:3;6094:4;6086:6;6082:17;6072:8;6068:32;6065:41;6062:128;;;6109:79;;:::i;:::-;6062:128;5628:568;;;;;:::o;6202:704::-;6297:6;6305;6313;6362:2;6350:9;6341:7;6337:23;6333:32;6330:119;;;6368:79;;:::i;:::-;6330:119;6488:1;6513:53;6558:7;6549:6;6538:9;6534:22;6513:53;:::i;:::-;6503:63;;6459:117;6643:2;6632:9;6628:18;6615:32;6674:18;6666:6;6663:30;6660:117;;;6696:79;;:::i;:::-;6660:117;6809:80;6881:7;6872:6;6861:9;6857:22;6809:80;:::i;:::-;6791:98;;;;6586:313;6202:704;;;;;:::o;6912:329::-;6971:6;7020:2;7008:9;6999:7;6995:23;6991:32;6988:119;;;7026:79;;:::i;:::-;6988:119;7146:1;7171:53;7216:7;7207:6;7196:9;7192:22;7171:53;:::i;:::-;7161:63;;7117:117;6912:329;;;;:::o;7247:619::-;7324:6;7332;7340;7389:2;7377:9;7368:7;7364:23;7360:32;7357:119;;;7395:79;;:::i;:::-;7357:119;7515:1;7540:53;7585:7;7576:6;7565:9;7561:22;7540:53;:::i;:::-;7530:63;;7486:117;7642:2;7668:53;7713:7;7704:6;7693:9;7689:22;7668:53;:::i;:::-;7658:63;;7613:118;7770:2;7796:53;7841:7;7832:6;7821:9;7817:22;7796:53;:::i;:::-;7786:63;;7741:118;7247:619;;;;;:::o;7872:117::-;7981:1;7978;7971:12;7995:180;8043:77;8040:1;8033:88;8140:4;8137:1;8130:15;8164:4;8161:1;8154:15;8181:281;8264:27;8286:4;8264:27;:::i;:::-;8256:6;8252:40;8394:6;8382:10;8379:22;8358:18;8346:10;8343:34;8340:62;8337:88;;;8405:18;;:::i;:::-;8337:88;8445:10;8441:2;8434:22;8224:238;8181:281;;:::o;8468:129::-;8502:6;8529:20;;:::i;:::-;8519:30;;8558:33;8586:4;8578:6;8558:33;:::i;:::-;8468:129;;;:::o;8603:308::-;8665:4;8755:18;8747:6;8744:30;8741:56;;;8777:18;;:::i;:::-;8741:56;8815:29;8837:6;8815:29;:::i;:::-;8807:37;;8899:4;8893;8889:15;8881:23;;8603:308;;;:::o;8917:146::-;9014:6;9009:3;9004;8991:30;9055:1;9046:6;9041:3;9037:16;9030:27;8917:146;;;:::o;9069:425::-;9147:5;9172:66;9188:49;9230:6;9188:49;:::i;:::-;9172:66;:::i;:::-;9163:75;;9261:6;9254:5;9247:21;9299:4;9292:5;9288:16;9337:3;9328:6;9323:3;9319:16;9316:25;9313:112;;;9344:79;;:::i;:::-;9313:112;9434:54;9481:6;9476:3;9471;9434:54;:::i;:::-;9153:341;9069:425;;;;;:::o;9514:340::-;9570:5;9619:3;9612:4;9604:6;9600:17;9596:27;9586:122;;9627:79;;:::i;:::-;9586:122;9744:6;9731:20;9769:79;9844:3;9836:6;9829:4;9821:6;9817:17;9769:79;:::i;:::-;9760:88;;9576:278;9514:340;;;;:::o;9860:509::-;9929:6;9978:2;9966:9;9957:7;9953:23;9949:32;9946:119;;;9984:79;;:::i;:::-;9946:119;10132:1;10121:9;10117:17;10104:31;10162:18;10154:6;10151:30;10148:117;;;10184:79;;:::i;:::-;10148:117;10289:63;10344:7;10335:6;10324:9;10320:22;10289:63;:::i;:::-;10279:73;;10075:287;9860:509;;;;:::o;10375:108::-;10452:24;10470:5;10452:24;:::i;:::-;10447:3;10440:37;10375:108;;:::o;10489:101::-;10525:7;10565:18;10558:5;10554:30;10543:41;;10489:101;;;:::o;10596:105::-;10671:23;10688:5;10671:23;:::i;:::-;10666:3;10659:36;10596:105;;:::o;10707:99::-;10778:21;10793:5;10778:21;:::i;:::-;10773:3;10766:34;10707:99;;:::o;10882:699::-;11043:4;11038:3;11034:14;11130:4;11123:5;11119:16;11113:23;11149:63;11206:4;11201:3;11197:14;11183:12;11149:63;:::i;:::-;11058:164;11314:4;11307:5;11303:16;11297:23;11333:61;11388:4;11383:3;11379:14;11365:12;11333:61;:::i;:::-;11232:172;11488:4;11481:5;11477:16;11471:23;11507:57;11558:4;11553:3;11549:14;11535:12;11507:57;:::i;:::-;11414:160;11012:569;10882:699;;:::o;11587:350::-;11744:4;11782:2;11771:9;11767:18;11759:26;;11795:135;11927:1;11916:9;11912:17;11903:6;11795:135;:::i;:::-;11587:350;;;;:::o;11943:116::-;12013:21;12028:5;12013:21;:::i;:::-;12006:5;12003:32;11993:60;;12049:1;12046;12039:12;11993:60;11943:116;:::o;12065:133::-;12108:5;12146:6;12133:20;12124:29;;12162:30;12186:5;12162:30;:::i;:::-;12065:133;;;;:::o;12204:468::-;12269:6;12277;12326:2;12314:9;12305:7;12301:23;12297:32;12294:119;;;12332:79;;:::i;:::-;12294:119;12452:1;12477:53;12522:7;12513:6;12502:9;12498:22;12477:53;:::i;:::-;12467:63;;12423:117;12579:2;12605:50;12647:7;12638:6;12627:9;12623:22;12605:50;:::i;:::-;12595:60;;12550:115;12204:468;;;;;:::o;12678:77::-;12715:7;12744:5;12733:16;;12678:77;;;:::o;12761:118::-;12848:24;12866:5;12848:24;:::i;:::-;12843:3;12836:37;12761:118;;:::o;12885:222::-;12978:4;13016:2;13005:9;13001:18;12993:26;;13029:71;13097:1;13086:9;13082:17;13073:6;13029:71;:::i;:::-;12885:222;;;;:::o;13113:307::-;13174:4;13264:18;13256:6;13253:30;13250:56;;;13286:18;;:::i;:::-;13250:56;13324:29;13346:6;13324:29;:::i;:::-;13316:37;;13408:4;13402;13398:15;13390:23;;13113:307;;;:::o;13426:423::-;13503:5;13528:65;13544:48;13585:6;13544:48;:::i;:::-;13528:65;:::i;:::-;13519:74;;13616:6;13609:5;13602:21;13654:4;13647:5;13643:16;13692:3;13683:6;13678:3;13674:16;13671:25;13668:112;;;13699:79;;:::i;:::-;13668:112;13789:54;13836:6;13831:3;13826;13789:54;:::i;:::-;13509:340;13426:423;;;;;:::o;13868:338::-;13923:5;13972:3;13965:4;13957:6;13953:17;13949:27;13939:122;;13980:79;;:::i;:::-;13939:122;14097:6;14084:20;14122:78;14196:3;14188:6;14181:4;14173:6;14169:17;14122:78;:::i;:::-;14113:87;;13929:277;13868:338;;;;:::o;14212:943::-;14307:6;14315;14323;14331;14380:3;14368:9;14359:7;14355:23;14351:33;14348:120;;;14387:79;;:::i;:::-;14348:120;14507:1;14532:53;14577:7;14568:6;14557:9;14553:22;14532:53;:::i;:::-;14522:63;;14478:117;14634:2;14660:53;14705:7;14696:6;14685:9;14681:22;14660:53;:::i;:::-;14650:63;;14605:118;14762:2;14788:53;14833:7;14824:6;14813:9;14809:22;14788:53;:::i;:::-;14778:63;;14733:118;14918:2;14907:9;14903:18;14890:32;14949:18;14941:6;14938:30;14935:117;;;14971:79;;:::i;:::-;14935:117;15076:62;15130:7;15121:6;15110:9;15106:22;15076:62;:::i;:::-;15066:72;;14861:287;14212:943;;;;;;;:::o;15161:122::-;15234:24;15252:5;15234:24;:::i;:::-;15227:5;15224:35;15214:63;;15273:1;15270;15263:12;15214:63;15161:122;:::o;15289:139::-;15335:5;15373:6;15360:20;15351:29;;15389:33;15416:5;15389:33;:::i;:::-;15289:139;;;;:::o;15434:329::-;15493:6;15542:2;15530:9;15521:7;15517:23;15513:32;15510:119;;;15548:79;;:::i;:::-;15510:119;15668:1;15693:53;15738:7;15729:6;15718:9;15714:22;15693:53;:::i;:::-;15683:63;;15639:117;15434:329;;;;:::o;15769:311::-;15846:4;15936:18;15928:6;15925:30;15922:56;;;15958:18;;:::i;:::-;15922:56;16008:4;16000:6;15996:17;15988:25;;16068:4;16062;16058:15;16050:23;;15769:311;;;:::o;16103:710::-;16199:5;16224:81;16240:64;16297:6;16240:64;:::i;:::-;16224:81;:::i;:::-;16215:90;;16325:5;16354:6;16347:5;16340:21;16388:4;16381:5;16377:16;16370:23;;16441:4;16433:6;16429:17;16421:6;16417:30;16470:3;16462:6;16459:15;16456:122;;;16489:79;;:::i;:::-;16456:122;16604:6;16587:220;16621:6;16616:3;16613:15;16587:220;;;16696:3;16725:37;16758:3;16746:10;16725:37;:::i;:::-;16720:3;16713:50;16792:4;16787:3;16783:14;16776:21;;16663:144;16647:4;16642:3;16638:14;16631:21;;16587:220;;;16591:21;16205:608;;16103:710;;;;;:::o;16836:370::-;16907:5;16956:3;16949:4;16941:6;16937:17;16933:27;16923:122;;16964:79;;:::i;:::-;16923:122;17081:6;17068:20;17106:94;17196:3;17188:6;17181:4;17173:6;17169:17;17106:94;:::i;:::-;17097:103;;16913:293;16836:370;;;;:::o;17212:684::-;17305:6;17313;17362:2;17350:9;17341:7;17337:23;17333:32;17330:119;;;17368:79;;:::i;:::-;17330:119;17516:1;17505:9;17501:17;17488:31;17546:18;17538:6;17535:30;17532:117;;;17568:79;;:::i;:::-;17532:117;17673:78;17743:7;17734:6;17723:9;17719:22;17673:78;:::i;:::-;17663:88;;17459:302;17800:2;17826:53;17871:7;17862:6;17851:9;17847:22;17826:53;:::i;:::-;17816:63;;17771:118;17212:684;;;;;:::o;17902:474::-;17970:6;17978;18027:2;18015:9;18006:7;18002:23;17998:32;17995:119;;;18033:79;;:::i;:::-;17995:119;18153:1;18178:53;18223:7;18214:6;18203:9;18199:22;18178:53;:::i;:::-;18168:63;;18124:117;18280:2;18306:53;18351:7;18342:6;18331:9;18327:22;18306:53;:::i;:::-;18296:63;;18251:118;17902:474;;;;;:::o;18382:180::-;18430:77;18427:1;18420:88;18527:4;18524:1;18517:15;18551:4;18548:1;18541:15;18568:320;18612:6;18649:1;18643:4;18639:12;18629:22;;18696:1;18690:4;18686:12;18717:18;18707:81;;18773:4;18765:6;18761:17;18751:27;;18707:81;18835:2;18827:6;18824:14;18804:18;18801:38;18798:84;;18854:18;;:::i;:::-;18798:84;18619:269;18568:320;;;:::o;18894:169::-;19034:21;19030:1;19022:6;19018:14;19011:45;18894:169;:::o;19069:366::-;19211:3;19232:67;19296:2;19291:3;19232:67;:::i;:::-;19225:74;;19308:93;19397:3;19308:93;:::i;:::-;19426:2;19421:3;19417:12;19410:19;;19069:366;;;:::o;19441:419::-;19607:4;19645:2;19634:9;19630:18;19622:26;;19694:9;19688:4;19684:20;19680:1;19669:9;19665:17;19658:47;19722:131;19848:4;19722:131;:::i;:::-;19714:139;;19441:419;;;:::o;19866:180::-;19914:77;19911:1;19904:88;20011:4;20008:1;20001:15;20035:4;20032:1;20025:15;20052:191;20092:3;20111:20;20129:1;20111:20;:::i;:::-;20106:25;;20145:20;20163:1;20145:20;:::i;:::-;20140:25;;20188:1;20185;20181:9;20174:16;;20209:3;20206:1;20203:10;20200:36;;;20216:18;;:::i;:::-;20200:36;20052:191;;;;:::o;20249:225::-;20389:34;20385:1;20377:6;20373:14;20366:58;20458:8;20453:2;20445:6;20441:15;20434:33;20249:225;:::o;20480:366::-;20622:3;20643:67;20707:2;20702:3;20643:67;:::i;:::-;20636:74;;20719:93;20808:3;20719:93;:::i;:::-;20837:2;20832:3;20828:12;20821:19;;20480:366;;;:::o;20852:419::-;21018:4;21056:2;21045:9;21041:18;21033:26;;21105:9;21099:4;21095:20;21091:1;21080:9;21076:17;21069:47;21133:131;21259:4;21133:131;:::i;:::-;21125:139;;20852:419;;;:::o;21277:172::-;21417:24;21413:1;21405:6;21401:14;21394:48;21277:172;:::o;21455:366::-;21597:3;21618:67;21682:2;21677:3;21618:67;:::i;:::-;21611:74;;21694:93;21783:3;21694:93;:::i;:::-;21812:2;21807:3;21803:12;21796:19;;21455:366;;;:::o;21827:419::-;21993:4;22031:2;22020:9;22016:18;22008:26;;22080:9;22074:4;22070:20;22066:1;22055:9;22051:17;22044:47;22108:131;22234:4;22108:131;:::i;:::-;22100:139;;21827:419;;;:::o;22252:410::-;22292:7;22315:20;22333:1;22315:20;:::i;:::-;22310:25;;22349:20;22367:1;22349:20;:::i;:::-;22344:25;;22404:1;22401;22397:9;22426:30;22444:11;22426:30;:::i;:::-;22415:41;;22605:1;22596:7;22592:15;22589:1;22586:22;22566:1;22559:9;22539:83;22516:139;;22635:18;;:::i;:::-;22516:139;22300:362;22252:410;;;;:::o;22668:170::-;22808:22;22804:1;22796:6;22792:14;22785:46;22668:170;:::o;22844:366::-;22986:3;23007:67;23071:2;23066:3;23007:67;:::i;:::-;23000:74;;23083:93;23172:3;23083:93;:::i;:::-;23201:2;23196:3;23192:12;23185:19;;22844:366;;;:::o;23216:419::-;23382:4;23420:2;23409:9;23405:18;23397:26;;23469:9;23463:4;23459:20;23455:1;23444:9;23440:17;23433:47;23497:131;23623:4;23497:131;:::i;:::-;23489:139;;23216:419;;;:::o;23641:172::-;23781:24;23777:1;23769:6;23765:14;23758:48;23641:172;:::o;23819:366::-;23961:3;23982:67;24046:2;24041:3;23982:67;:::i;:::-;23975:74;;24058:93;24147:3;24058:93;:::i;:::-;24176:2;24171:3;24167:12;24160:19;;23819:366;;;:::o;24191:419::-;24357:4;24395:2;24384:9;24380:18;24372:26;;24444:9;24438:4;24434:20;24430:1;24419:9;24415:17;24408:47;24472:131;24598:4;24472:131;:::i;:::-;24464:139;;24191:419;;;:::o;24616:178::-;24756:30;24752:1;24744:6;24740:14;24733:54;24616:178;:::o;24800:366::-;24942:3;24963:67;25027:2;25022:3;24963:67;:::i;:::-;24956:74;;25039:93;25128:3;25039:93;:::i;:::-;25157:2;25152:3;25148:12;25141:19;;24800:366;;;:::o;25172:419::-;25338:4;25376:2;25365:9;25361:18;25353:26;;25425:9;25419:4;25415:20;25411:1;25400:9;25396:17;25389:47;25453:131;25579:4;25453:131;:::i;:::-;25445:139;;25172:419;;;:::o;25597:332::-;25718:4;25756:2;25745:9;25741:18;25733:26;;25769:71;25837:1;25826:9;25822:17;25813:6;25769:71;:::i;:::-;25850:72;25918:2;25907:9;25903:18;25894:6;25850:72;:::i;:::-;25597:332;;;;;:::o;25935:137::-;25989:5;26020:6;26014:13;26005:22;;26036:30;26060:5;26036:30;:::i;:::-;25935:137;;;;:::o;26078:345::-;26145:6;26194:2;26182:9;26173:7;26169:23;26165:32;26162:119;;;26200:79;;:::i;:::-;26162:119;26320:1;26345:61;26398:7;26389:6;26378:9;26374:22;26345:61;:::i;:::-;26335:71;;26291:125;26078:345;;;;:::o;26429:182::-;26569:34;26565:1;26557:6;26553:14;26546:58;26429:182;:::o;26617:366::-;26759:3;26780:67;26844:2;26839:3;26780:67;:::i;:::-;26773:74;;26856:93;26945:3;26856:93;:::i;:::-;26974:2;26969:3;26965:12;26958:19;;26617:366;;;:::o;26989:419::-;27155:4;27193:2;27182:9;27178:18;27170:26;;27242:9;27236:4;27232:20;27228:1;27217:9;27213:17;27206:47;27270:131;27396:4;27270:131;:::i;:::-;27262:139;;26989:419;;;:::o;27414:220::-;27554:34;27550:1;27542:6;27538:14;27531:58;27623:3;27618:2;27610:6;27606:15;27599:28;27414:220;:::o;27640:366::-;27782:3;27803:67;27867:2;27862:3;27803:67;:::i;:::-;27796:74;;27879:93;27968:3;27879:93;:::i;:::-;27997:2;27992:3;27988:12;27981:19;;27640:366;;;:::o;28012:419::-;28178:4;28216:2;28205:9;28201:18;28193:26;;28265:9;28259:4;28255:20;28251:1;28240:9;28236:17;28229:47;28293:131;28419:4;28293:131;:::i;:::-;28285:139;;28012:419;;;:::o;28437:194::-;28477:4;28497:20;28515:1;28497:20;:::i;:::-;28492:25;;28531:20;28549:1;28531:20;:::i;:::-;28526:25;;28575:1;28572;28568:9;28560:17;;28599:1;28593:4;28590:11;28587:37;;;28604:18;;:::i;:::-;28587:37;28437:194;;;;:::o;28637:141::-;28686:4;28709:3;28701:11;;28732:3;28729:1;28722:14;28766:4;28763:1;28753:18;28745:26;;28637:141;;;:::o;28784:93::-;28821:6;28868:2;28863;28856:5;28852:14;28848:23;28838:33;;28784:93;;;:::o;28883:107::-;28927:8;28977:5;28971:4;28967:16;28946:37;;28883:107;;;;:::o;28996:393::-;29065:6;29115:1;29103:10;29099:18;29138:97;29168:66;29157:9;29138:97;:::i;:::-;29256:39;29286:8;29275:9;29256:39;:::i;:::-;29244:51;;29328:4;29324:9;29317:5;29313:21;29304:30;;29377:4;29367:8;29363:19;29356:5;29353:30;29343:40;;29072:317;;28996:393;;;;;:::o;29395:60::-;29423:3;29444:5;29437:12;;29395:60;;;:::o;29461:142::-;29511:9;29544:53;29562:34;29571:24;29589:5;29571:24;:::i;:::-;29562:34;:::i;:::-;29544:53;:::i;:::-;29531:66;;29461:142;;;:::o;29609:75::-;29652:3;29673:5;29666:12;;29609:75;;;:::o;29690:269::-;29800:39;29831:7;29800:39;:::i;:::-;29861:91;29910:41;29934:16;29910:41;:::i;:::-;29902:6;29895:4;29889:11;29861:91;:::i;:::-;29855:4;29848:105;29766:193;29690:269;;;:::o;29965:73::-;30010:3;29965:73;:::o;30044:189::-;30121:32;;:::i;:::-;30162:65;30220:6;30212;30206:4;30162:65;:::i;:::-;30097:136;30044:189;;:::o;30239:186::-;30299:120;30316:3;30309:5;30306:14;30299:120;;;30370:39;30407:1;30400:5;30370:39;:::i;:::-;30343:1;30336:5;30332:13;30323:22;;30299:120;;;30239:186;;:::o;30431:543::-;30532:2;30527:3;30524:11;30521:446;;;30566:38;30598:5;30566:38;:::i;:::-;30650:29;30668:10;30650:29;:::i;:::-;30640:8;30636:44;30833:2;30821:10;30818:18;30815:49;;;30854:8;30839:23;;30815:49;30877:80;30933:22;30951:3;30933:22;:::i;:::-;30923:8;30919:37;30906:11;30877:80;:::i;:::-;30536:431;;30521:446;30431:543;;;:::o;30980:117::-;31034:8;31084:5;31078:4;31074:16;31053:37;;30980:117;;;;:::o;31103:169::-;31147:6;31180:51;31228:1;31224:6;31216:5;31213:1;31209:13;31180:51;:::i;:::-;31176:56;31261:4;31255;31251:15;31241:25;;31154:118;31103:169;;;;:::o;31277:295::-;31353:4;31499:29;31524:3;31518:4;31499:29;:::i;:::-;31491:37;;31561:3;31558:1;31554:11;31548:4;31545:21;31537:29;;31277:295;;;;:::o;31577:1395::-;31694:37;31727:3;31694:37;:::i;:::-;31796:18;31788:6;31785:30;31782:56;;;31818:18;;:::i;:::-;31782:56;31862:38;31894:4;31888:11;31862:38;:::i;:::-;31947:67;32007:6;31999;31993:4;31947:67;:::i;:::-;32041:1;32065:4;32052:17;;32097:2;32089:6;32086:14;32114:1;32109:618;;;;32771:1;32788:6;32785:77;;;32837:9;32832:3;32828:19;32822:26;32813:35;;32785:77;32888:67;32948:6;32941:5;32888:67;:::i;:::-;32882:4;32875:81;32744:222;32079:887;;32109:618;32161:4;32157:9;32149:6;32145:22;32195:37;32227:4;32195:37;:::i;:::-;32254:1;32268:208;32282:7;32279:1;32276:14;32268:208;;;32361:9;32356:3;32352:19;32346:26;32338:6;32331:42;32412:1;32404:6;32400:14;32390:24;;32459:2;32448:9;32444:18;32431:31;;32305:4;32302:1;32298:12;32293:17;;32268:208;;;32504:6;32495:7;32492:19;32489:179;;;32562:9;32557:3;32553:19;32547:26;32605:48;32647:4;32639:6;32635:17;32624:9;32605:48;:::i;:::-;32597:6;32590:64;32512:156;32489:179;32714:1;32710;32702:6;32698:14;32694:22;32688:4;32681:36;32116:611;;;32079:887;;31669:1303;;;31577:1395;;:::o;32978:168::-;33118:20;33114:1;33106:6;33102:14;33095:44;32978:168;:::o;33152:366::-;33294:3;33315:67;33379:2;33374:3;33315:67;:::i;:::-;33308:74;;33391:93;33480:3;33391:93;:::i;:::-;33509:2;33504:3;33500:12;33493:19;;33152:366;;;:::o;33524:419::-;33690:4;33728:2;33717:9;33713:18;33705:26;;33777:9;33771:4;33767:20;33763:1;33752:9;33748:17;33741:47;33805:131;33931:4;33805:131;:::i;:::-;33797:139;;33524:419;;;:::o;33949:180::-;34089:32;34085:1;34077:6;34073:14;34066:56;33949:180;:::o;34135:366::-;34277:3;34298:67;34362:2;34357:3;34298:67;:::i;:::-;34291:74;;34374:93;34463:3;34374:93;:::i;:::-;34492:2;34487:3;34483:12;34476:19;;34135:366;;;:::o;34507:419::-;34673:4;34711:2;34700:9;34696:18;34688:26;;34760:9;34754:4;34750:20;34746:1;34735:9;34731:17;34724:47;34788:131;34914:4;34788:131;:::i;:::-;34780:139;;34507:419;;;:::o;34932:168::-;35072:20;35068:1;35060:6;35056:14;35049:44;34932:168;:::o;35106:366::-;35248:3;35269:67;35333:2;35328:3;35269:67;:::i;:::-;35262:74;;35345:93;35434:3;35345:93;:::i;:::-;35463:2;35458:3;35454:12;35447:19;;35106:366;;;:::o;35478:419::-;35644:4;35682:2;35671:9;35667:18;35659:26;;35731:9;35725:4;35721:20;35717:1;35706:9;35702:17;35695:47;35759:131;35885:4;35759:131;:::i;:::-;35751:139;;35478:419;;;:::o;35903:172::-;36043:24;36039:1;36031:6;36027:14;36020:48;35903:172;:::o;36081:366::-;36223:3;36244:67;36308:2;36303:3;36244:67;:::i;:::-;36237:74;;36320:93;36409:3;36320:93;:::i;:::-;36438:2;36433:3;36429:12;36422:19;;36081:366;;;:::o;36453:419::-;36619:4;36657:2;36646:9;36642:18;36634:26;;36706:9;36700:4;36696:20;36692:1;36681:9;36677:17;36670:47;36734:131;36860:4;36734:131;:::i;:::-;36726:139;;36453:419;;;:::o;36878:181::-;37018:33;37014:1;37006:6;37002:14;36995:57;36878:181;:::o;37065:366::-;37207:3;37228:67;37292:2;37287:3;37228:67;:::i;:::-;37221:74;;37304:93;37393:3;37304:93;:::i;:::-;37422:2;37417:3;37413:12;37406:19;;37065:366;;;:::o;37437:419::-;37603:4;37641:2;37630:9;37626:18;37618:26;;37690:9;37684:4;37680:20;37676:1;37665:9;37661:17;37654:47;37718:131;37844:4;37718:131;:::i;:::-;37710:139;;37437:419;;;:::o;37862:147::-;37963:11;38000:3;37985:18;;37862:147;;;;:::o;38015:114::-;;:::o;38135:398::-;38294:3;38315:83;38396:1;38391:3;38315:83;:::i;:::-;38308:90;;38407:93;38496:3;38407:93;:::i;:::-;38525:1;38520:3;38516:11;38509:18;;38135:398;;;:::o;38539:379::-;38723:3;38745:147;38888:3;38745:147;:::i;:::-;38738:154;;38909:3;38902:10;;38539:379;;;:::o;38924:166::-;39064:18;39060:1;39052:6;39048:14;39041:42;38924:166;:::o;39096:366::-;39238:3;39259:67;39323:2;39318:3;39259:67;:::i;:::-;39252:74;;39335:93;39424:3;39335:93;:::i;:::-;39453:2;39448:3;39444:12;39437:19;;39096:366;;;:::o;39468:419::-;39634:4;39672:2;39661:9;39657:18;39649:26;;39721:9;39715:4;39711:20;39707:1;39696:9;39692:17;39685:47;39749:131;39875:4;39749:131;:::i;:::-;39741:139;;39468:419;;;:::o;39893:234::-;40033:34;40029:1;40021:6;40017:14;40010:58;40102:17;40097:2;40089:6;40085:15;40078:42;39893:234;:::o;40133:366::-;40275:3;40296:67;40360:2;40355:3;40296:67;:::i;:::-;40289:74;;40372:93;40461:3;40372:93;:::i;:::-;40490:2;40485:3;40481:12;40474:19;;40133:366;;;:::o;40505:419::-;40671:4;40709:2;40698:9;40694:18;40686:26;;40758:9;40752:4;40748:20;40744:1;40733:9;40729:17;40722:47;40786:131;40912:4;40786:131;:::i;:::-;40778:139;;40505:419;;;:::o;40930:148::-;41032:11;41069:3;41054:18;;40930:148;;;;:::o;41084:390::-;41190:3;41218:39;41251:5;41218:39;:::i;:::-;41273:89;41355:6;41350:3;41273:89;:::i;:::-;41266:96;;41371:65;41429:6;41424:3;41417:4;41410:5;41406:16;41371:65;:::i;:::-;41461:6;41456:3;41452:16;41445:23;;41194:280;41084:390;;;;:::o;41480:151::-;41620:3;41616:1;41608:6;41604:14;41597:27;41480:151;:::o;41637:400::-;41797:3;41818:84;41900:1;41895:3;41818:84;:::i;:::-;41811:91;;41911:93;42000:3;41911:93;:::i;:::-;42029:1;42024:3;42020:11;42013:18;;41637:400;;;:::o;42043:155::-;42183:7;42179:1;42171:6;42167:14;42160:31;42043:155;:::o;42204:400::-;42364:3;42385:84;42467:1;42462:3;42385:84;:::i;:::-;42378:91;;42478:93;42567:3;42478:93;:::i;:::-;42596:1;42591:3;42587:11;42580:18;;42204:400;;;:::o;42610:967::-;42992:3;43014:95;43105:3;43096:6;43014:95;:::i;:::-;43007:102;;43126:148;43270:3;43126:148;:::i;:::-;43119:155;;43291:95;43382:3;43373:6;43291:95;:::i;:::-;43284:102;;43403:148;43547:3;43403:148;:::i;:::-;43396:155;;43568:3;43561:10;;42610:967;;;;;:::o;43583:94::-;43616:8;43664:5;43660:2;43656:14;43635:35;;43583:94;;;:::o;43683:::-;43722:7;43751:20;43765:5;43751:20;:::i;:::-;43740:31;;43683:94;;;:::o;43783:100::-;43822:7;43851:26;43871:5;43851:26;:::i;:::-;43840:37;;43783:100;;;:::o;43889:157::-;43994:45;44014:24;44032:5;44014:24;:::i;:::-;43994:45;:::i;:::-;43989:3;43982:58;43889:157;;:::o;44052:256::-;44164:3;44179:75;44250:3;44241:6;44179:75;:::i;:::-;44279:2;44274:3;44270:12;44263:19;;44299:3;44292:10;;44052:256;;;;:::o;44314:225::-;44454:34;44450:1;44442:6;44438:14;44431:58;44523:8;44518:2;44510:6;44506:15;44499:33;44314:225;:::o;44545:366::-;44687:3;44708:67;44772:2;44767:3;44708:67;:::i;:::-;44701:74;;44784:93;44873:3;44784:93;:::i;:::-;44902:2;44897:3;44893:12;44886:19;;44545:366;;;:::o;44917:419::-;45083:4;45121:2;45110:9;45106:18;45098:26;;45170:9;45164:4;45160:20;45156:1;45145:9;45141:17;45134:47;45198:131;45324:4;45198:131;:::i;:::-;45190:139;;44917:419;;;:::o;45342:233::-;45381:3;45404:24;45422:5;45404:24;:::i;:::-;45395:33;;45450:66;45443:5;45440:77;45437:103;;45520:18;;:::i;:::-;45437:103;45567:1;45560:5;45556:13;45549:20;;45342:233;;;:::o;45581:180::-;45629:77;45626:1;45619:88;45726:4;45723:1;45716:15;45750:4;45747:1;45740:15;45767:185;45807:1;45824:20;45842:1;45824:20;:::i;:::-;45819:25;;45858:20;45876:1;45858:20;:::i;:::-;45853:25;;45897:1;45887:35;;45902:18;;:::i;:::-;45887:35;45944:1;45941;45937:9;45932:14;;45767:185;;;;:::o;45958:176::-;45990:1;46007:20;46025:1;46007:20;:::i;:::-;46002:25;;46041:20;46059:1;46041:20;:::i;:::-;46036:25;;46080:1;46070:35;;46085:18;;:::i;:::-;46070:35;46126:1;46123;46119:9;46114:14;;45958:176;;;;:::o;46140:180::-;46188:77;46185:1;46178:88;46285:4;46282:1;46275:15;46309:4;46306:1;46299:15;46326:98;46377:6;46411:5;46405:12;46395:22;;46326:98;;;:::o;46430:168::-;46513:11;46547:6;46542:3;46535:19;46587:4;46582:3;46578:14;46563:29;;46430:168;;;;:::o;46604:373::-;46690:3;46718:38;46750:5;46718:38;:::i;:::-;46772:70;46835:6;46830:3;46772:70;:::i;:::-;46765:77;;46851:65;46909:6;46904:3;46897:4;46890:5;46886:16;46851:65;:::i;:::-;46941:29;46963:6;46941:29;:::i;:::-;46936:3;46932:39;46925:46;;46694:283;46604:373;;;;:::o;46983:640::-;47178:4;47216:3;47205:9;47201:19;47193:27;;47230:71;47298:1;47287:9;47283:17;47274:6;47230:71;:::i;:::-;47311:72;47379:2;47368:9;47364:18;47355:6;47311:72;:::i;:::-;47393;47461:2;47450:9;47446:18;47437:6;47393:72;:::i;:::-;47512:9;47506:4;47502:20;47497:2;47486:9;47482:18;47475:48;47540:76;47611:4;47602:6;47540:76;:::i;:::-;47532:84;;46983:640;;;;;;;:::o;47629:141::-;47685:5;47716:6;47710:13;47701:22;;47732:32;47758:5;47732:32;:::i;:::-;47629:141;;;;:::o;47776:349::-;47845:6;47894:2;47882:9;47873:7;47869:23;47865:32;47862:119;;;47900:79;;:::i;:::-;47862:119;48020:1;48045:63;48100:7;48091:6;48080:9;48076:22;48045:63;:::i;:::-;48035:73;;47991:127;47776:349;;;;:::o

Swarm Source

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