ETH Price: $2,746.05 (+0.25%)

Token

Composable NFT (CNFT)
 

Overview

Max Total Supply

0 CNFT

Holders

2

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Balance
1 CNFT
0xE56E9df212ddA0aA0b5e388743fEbC43030640b9
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:
ComposableTopDown

Compiler Version
v0.8.0+commit.c7dfd78e

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, Unlicense license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2021-11-25
*/

// Sources flattened with hardhat v2.3.0 https://hardhat.org

// File @openzeppelin/contracts/utils/introspection/[email protected]

// SPDX-License-Identifier: UNLICENSED

pragma solidity ^0.8.0;

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


// File @openzeppelin/contracts/utils/introspection/[email protected]


pragma solidity ^0.8.0;

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


// File @openzeppelin/contracts/utils/math/[email protected]


pragma solidity ^0.8.0;

// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is no longer needed starting with Solidity 0.8. The compiler
 * now has built in overflow checking.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        return a + b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        unchecked {
            require(b <= a, errorMessage);
            return a - b;
        }
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a / b;
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}


// File @openzeppelin/contracts/token/ERC721/[email protected]


pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

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

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

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


// File @openzeppelin/contracts/token/ERC721/[email protected]


pragma solidity ^0.8.0;

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


// File contracts/interfaces/IERC998ERC721BottomUp.sol


pragma solidity ^0.8.0;

interface IERC998ERC721BottomUp {
    event TransferToParent(
        address indexed _toContract,
        uint256 indexed _toTokenId,
        uint256 _tokenId
    );
    event TransferFromParent(
        address indexed _fromContract,
        uint256 indexed _fromTokenId,
        uint256 _tokenId
    );

    function rootOwnerOf(uint256 _tokenId)
        external
        view
        returns (bytes32 rootOwner);

    /**
     * The tokenOwnerOf function gets the owner of the _tokenId which can be a user address or another ERC721 token.
     * The tokenOwner address return value can be either a user address or an ERC721 contract address.
     * If the tokenOwner address is a user address then parentTokenId will be 0 and should not be used or considered.
     * If tokenOwner address is a user address then isParent is false, otherwise isChild is true, which means that
     * tokenOwner is an ERC721 contract address and _tokenId is a child of tokenOwner and parentTokenId.
     */
    function tokenOwnerOf(uint256 _tokenId)
        external
        view
        returns (
            bytes32 tokenOwner,
            uint256 parentTokenId,
            bool isParent
        );

    // Transfers _tokenId as a child to _toContract and _toTokenId
    function transferToParent(
        address _from,
        address _toContract,
        uint256 _toTokenId,
        uint256 _tokenId,
        bytes memory _data
    ) external;

    // Transfers _tokenId from a parent ERC721 token to a user address.
    function transferFromParent(
        address _fromContract,
        uint256 _fromTokenId,
        address _to,
        uint256 _tokenId,
        bytes memory _data
    ) external;

    // Transfers _tokenId from a parent ERC721 token to a parent ERC721 token.
    function transferAsChild(
        address _fromContract,
        uint256 _fromTokenId,
        address _toContract,
        uint256 _toTokenId,
        uint256 _tokenId,
        bytes memory _data
    ) external;
}


// File contracts/interfaces/IERC998ERC721BottomUpEnumerable.sol


pragma solidity ^0.8.0;

interface IERC998ERC721BottomUpEnumerable {
    function totalChildTokens(address _parentContract, uint256 _parentTokenId)
        external
        view
        returns (uint256);

    function childTokenByIndex(
        address _parentContract,
        uint256 _parentTokenId,
        uint256 _index
    ) external view returns (uint256);
}


// File contracts/ComposableBottomUp.sol


pragma solidity ^0.8.0;





contract ComposableBottomUp is
    ERC165,
    IERC721,
    IERC998ERC721BottomUp,
    IERC998ERC721BottomUpEnumerable
{
    using SafeMath for uint256;
    struct TokenOwner {
        address tokenOwner;
        uint256 parentTokenId;
    }

    // return this.rootOwnerOf.selector ^ this.rootOwnerOfChild.selector ^
    //   this.tokenOwnerOf.selector ^ this.ownerOfChild.selector;
    bytes32 constant ERC998_MAGIC_VALUE = 0x00000000000000000000000000000000000000000000000000000000cd740db5;

    // tokenId => token owner
    mapping(uint256 => TokenOwner) internal tokenIdToTokenOwner;

    // root token owner address => (tokenId => approved address)
    mapping(address => mapping(uint256 => address))
        internal rootOwnerAndTokenIdToApprovedAddress;

    // token owner address => token count
    mapping(address => uint256) internal tokenOwnerToTokenCount;

    // token owner => (operator address => bool)
    mapping(address => mapping(address => bool)) internal tokenOwnerToOperators;

    // parent address => (parent tokenId => array of child tokenIds)
    mapping(address => mapping(uint256 => uint256[]))
        private parentToChildTokenIds;

    // tokenId => position in childTokens array
    mapping(uint256 => uint256) private tokenIdToChildTokenIdsIndex;

    // wrapper on minting new 721
    /*
    function mint721(address _to) public returns(uint256) {
      _mint(_to, allTokens.length + 1);
      return allTokens.length;
    }
    */
    //from zepellin ERC721Receiver.sol
    //old version
    bytes4 constant ERC721_RECEIVED = 0x150b7a02;

    function isContract(address _addr) internal view returns (bool) {
        uint256 size;
        assembly {
            size := extcodesize(_addr)
        }
        return size > 0;
    }

    function _tokenOwnerOf(uint256 _tokenId)
        internal
        view
        returns (
            address tokenOwner,
            uint256 parentTokenId,
            bool isParent
        )
    {
        tokenOwner = tokenIdToTokenOwner[_tokenId].tokenOwner;
        require(
            tokenOwner != address(0),
            "ComposableBottomUp: _tokenOwnerOf tokenOwner zero address"
        );
        parentTokenId = tokenIdToTokenOwner[_tokenId].parentTokenId;
        if (parentTokenId > 0) {
            isParent = true;
            parentTokenId--;
        } else {
            isParent = false;
        }
        return (tokenOwner, parentTokenId, isParent);
    }

    function tokenOwnerOf(uint256 _tokenId)
        external
        view
        override
        returns (
            bytes32 tokenOwner,
            uint256 parentTokenId,
            bool isParent
        )
    {
        address tokenOwnerAddress = tokenIdToTokenOwner[_tokenId].tokenOwner;
        require(tokenOwnerAddress != address(0), "ComposableBottomUp: tokenOwnerOf tokenOwnerAddress zero address");
        parentTokenId = tokenIdToTokenOwner[_tokenId].parentTokenId;
        if (parentTokenId > 0) {
            isParent = true;
            parentTokenId--;
        } else {
            isParent = false;
        }
        return (
            (ERC998_MAGIC_VALUE << 224) |
                bytes32(uint256(uint160(tokenOwnerAddress))),
            parentTokenId,
            isParent
        );
    }

    // Use Cases handled:
    // Case 1: Token owner is this contract and no parent tokenId.
    // Case 2: Token owner is this contract and token
    // Case 3: Token owner is top-down composable
    // Case 4: Token owner is an unknown contract
    // Case 5: Token owner is a user
    // Case 6: Token owner is a bottom-up composable
    // Case 7: Token owner is ERC721 token owned by top-down token
    // Case 8: Token owner is ERC721 token owned by unknown contract
    // Case 9: Token owner is ERC721 token owned by user
    function rootOwnerOf(uint256 _tokenId)
        public
        view
        override
        returns (bytes32 rootOwner)
    {
        address rootOwnerAddress = tokenIdToTokenOwner[_tokenId].tokenOwner;
        require(
            rootOwnerAddress != address(0),
            "ComposableBottomUp: rootOwnerOf rootOwnerAddress zero address"
        );
        uint256 parentTokenId = tokenIdToTokenOwner[_tokenId].parentTokenId;
        bool isParent = parentTokenId > 0;
        parentTokenId--;
        bytes memory callData;
        bytes memory data;
        bool callSuccess;

        if ((rootOwnerAddress == address(this))) {
            do {
                if (isParent == false) {
                    // Case 1: Token owner is this contract and no token.
                    // This case should not happen.
                    return
                        (ERC998_MAGIC_VALUE << 224) |
                        bytes32(uint256(uint160(rootOwnerAddress)));
                } else {
                    // Case 2: Token owner is this contract and token
                    (rootOwnerAddress, parentTokenId, isParent) = _tokenOwnerOf(
                        parentTokenId
                    );
                }
            } while (rootOwnerAddress == address(this));
            _tokenId = parentTokenId;
        }

        if (isParent == false) {
            // success if this token is owned by a top-down token
            // 0xed81cdda == rootOwnerOfChild(address, uint256)
            callData = abi.encodeWithSelector(
                0xed81cdda,
                address(this),
                _tokenId
            );
            (callSuccess, data) = rootOwnerAddress.staticcall(callData);
            if (callSuccess) {
                assembly {
                    rootOwner := mload(add(data, 0x20))
                }
            }
            if (callSuccess == true && rootOwner >> 224 == ERC998_MAGIC_VALUE) {
                // Case 3: Token owner is top-down composable
                return rootOwner;
            } else {
                // Case 4: Token owner is an unknown contract
                // Or
                // Case 5: Token owner is a user
                return
                    (ERC998_MAGIC_VALUE << 224) |
                    bytes32(uint256(uint160(rootOwnerAddress)));
            }
        } else {
            // 0x43a61a8e == rootOwnerOf(uint256)
            callData = abi.encodeWithSelector(0x43a61a8e, parentTokenId);
            (callSuccess, data) = rootOwnerAddress.staticcall(callData);
            if (callSuccess) {
                assembly {
                    rootOwner := mload(add(data, 0x20))
                }
            }
            if (callSuccess == true && rootOwner >> 224 == ERC998_MAGIC_VALUE) {
                // Case 6: Token owner is a bottom-up composable
                // Or
                // Case 2: Token owner is top-down composable
                return rootOwner;
            } else {
                // token owner is ERC721
                address childContract = rootOwnerAddress;
                //0x6352211e == "ownerOf(uint256)"
                callData = abi.encodeWithSelector(0x6352211e, parentTokenId);
                (callSuccess, data) = rootOwnerAddress.staticcall(callData);
                if (callSuccess) {
                    assembly {
                        rootOwnerAddress := mload(add(data, 0x20))
                    }
                }
                require(callSuccess, "Call to ownerOf failed");

                // 0xed81cdda == rootOwnerOfChild(address,uint256)
                callData = abi.encodeWithSelector(
                    0xed81cdda,
                    childContract,
                    parentTokenId
                );

                (callSuccess, data) = rootOwnerAddress.staticcall(callData);
                if (callSuccess) {
                    assembly {
                        rootOwner := mload(add(data, 0x20))
                    }
                }
                if (
                    callSuccess == true &&
                    rootOwner >> 224 == ERC998_MAGIC_VALUE
                ) {
                    // Case 7: Token owner is ERC721 token owned by top-down token
                    return rootOwner;
                } else {
                    // Case 8: Token owner is ERC721 token owned by unknown contract
                    // Or
                    // Case 9: Token owner is ERC721 token owned by user
                    return
                        (ERC998_MAGIC_VALUE << 224) |
                        bytes32(uint256(uint160(rootOwnerAddress)));
                }
            }
        }
    }

    /**
     * In a bottom-up composable authentication to transfer etc. is done by getting the rootOwner by finding the parent token
     * and then the parent token of that one until a final owner address is found.  If the msg.sender is the rootOwner or is
     * approved by the rootOwner then msg.sender is authenticated and the action can occur.
     * This enables the owner of the top-most parent of a tree of composables to call any method on child composables.
     */
    // returns the root owner at the top of the tree of composables
    function ownerOf(uint256 _tokenId) external view override returns (address) {
        address tokenOwner = tokenIdToTokenOwner[_tokenId].tokenOwner;
        require(
            tokenOwner != address(0),
            "ComposableBottomUp: ownerOf tokenOwner zero address"
        );
        return tokenOwner;
    }

    function balanceOf(address _tokenOwner)
        external
        view
        override
        returns (uint256)
    {
        require(
            _tokenOwner != address(0),
            "ComposableBottomUp: balanceOf _tokenOwner zero address"
        );
        return tokenOwnerToTokenCount[_tokenOwner];
    }

    function approve(address _approved, uint256 _tokenId) external override {
        address tokenOwner = tokenIdToTokenOwner[_tokenId].tokenOwner;
        require(tokenOwner != address(0), "ComposableBottomUp: approve tokenOwner zero address");
        address rootOwner = address(uint160(uint256(rootOwnerOf(_tokenId))));
        require(
            rootOwner == msg.sender ||
                tokenOwnerToOperators[rootOwner][msg.sender],
            "ComposableBottomUp: approve msg.sender not eligible"
        );

        rootOwnerAndTokenIdToApprovedAddress[rootOwner][_tokenId] = _approved;
        emit Approval(rootOwner, _approved, _tokenId);
    }

    function getApproved(uint256 _tokenId)
        external
        view
        override
        returns (address)
    {
        address rootOwner = address(uint160(uint256(rootOwnerOf(_tokenId))));
        return rootOwnerAndTokenIdToApprovedAddress[rootOwner][_tokenId];
    }

    function setApprovalForAll(address _operator, bool _approved)
        external
        override
    {
        require(_operator != address(0), "ComposableBottomUp: setApprovalForAll _operator zero address");
        tokenOwnerToOperators[msg.sender][_operator] = _approved;
        emit ApprovalForAll(msg.sender, _operator, _approved);
    }

    function isApprovedForAll(address _owner, address _operator)
        external
        view
        override
        returns (bool)
    {
        require(_owner != address(0), "ComposableBottomUp: isApprovedForAll _owner zero address");
        require(_operator != address(0), "ComposableBottomUp: isApprovedForAll _operator zero address");
        return tokenOwnerToOperators[_owner][_operator];
    }

    function removeChild(
        address _fromContract,
        uint256 _fromTokenId,
        uint256 _tokenId
    ) internal {
        uint256 childTokenIndex = tokenIdToChildTokenIdsIndex[_tokenId];
        uint256 lastChildTokenIndex =
            parentToChildTokenIds[_fromContract][_fromTokenId].length - 1;
        uint256 lastChildTokenId =
            parentToChildTokenIds[_fromContract][_fromTokenId][
                lastChildTokenIndex
            ];

        if (_tokenId != lastChildTokenId) {
            parentToChildTokenIds[_fromContract][_fromTokenId][
                childTokenIndex
            ] = lastChildTokenId;
            tokenIdToChildTokenIdsIndex[lastChildTokenId] = childTokenIndex;
        }
        // parentToChildTokenIds[_fromContract][_fromTokenId].length--;
        // added:
        parentToChildTokenIds[_fromContract][_fromTokenId].pop();
    }

    function authenticateAndClearApproval(uint256 _tokenId) private {
        address rootOwner = address(uint160(uint256(rootOwnerOf(_tokenId))));
        address approvedAddress =
            rootOwnerAndTokenIdToApprovedAddress[rootOwner][_tokenId];
        require(
            rootOwner == msg.sender ||
                tokenOwnerToOperators[rootOwner][msg.sender] ||
                approvedAddress == msg.sender,
            "ComposableBottomUp: authenticateAndClearApproval msg.sender not eligible"
        );

        // clear approval
        if (approvedAddress != address(0)) {
            delete rootOwnerAndTokenIdToApprovedAddress[rootOwner][_tokenId];
            emit Approval(rootOwner, address(0), _tokenId);
        }
    }

    function transferFromParent(
        address _fromContract,
        uint256 _fromTokenId,
        address _to,
        uint256 _tokenId,
        bytes memory _data
    ) external override {
        require(tokenIdToTokenOwner[_tokenId].tokenOwner == _fromContract, "ComposableBottomUp: transferFromParent tokenOwner != _fromContract");
        require(_to != address(0), "ComposableBottomUp: transferFromParent _to zero address");
        uint256 parentTokenId = tokenIdToTokenOwner[_tokenId].parentTokenId;
        require(parentTokenId != 0, "ComposableBottomUp: transferFromParent token does not have a parent token.");
        require(parentTokenId - 1 == _fromTokenId, "ComposableBottomUp: transferFromParent _fromTokenId not matching parentTokenId");
        authenticateAndClearApproval(_tokenId);

        // remove and transfer token
        if (_fromContract != _to) {
            assert(tokenOwnerToTokenCount[_fromContract] > 0);
            tokenOwnerToTokenCount[_fromContract]--;
            tokenOwnerToTokenCount[_to]++;
        }

        tokenIdToTokenOwner[_tokenId].tokenOwner = _to;
        tokenIdToTokenOwner[_tokenId].parentTokenId = 0;

        removeChild(_fromContract, _fromTokenId, _tokenId);
        delete tokenIdToChildTokenIdsIndex[_tokenId];

        if (isContract(_to)) {
            bytes4 retval =
                IERC721Receiver(_to).onERC721Received(
                    msg.sender,
                    _fromContract,
                    _tokenId,
                    _data
                );
            require(retval == ERC721_RECEIVED, "ComposableBottomUp: transferFromParent onERC721Received invalid value");
        }

        emit Transfer(_fromContract, _to, _tokenId);
        emit TransferFromParent(_fromContract, _fromTokenId, _tokenId);
    }

    function transferToParent(
        address _from,
        address _toContract,
        uint256 _toTokenId,
        uint256 _tokenId,
        bytes memory _data
    ) external override {
        require(_from != address(0), "ComposableBottomUp: transferToParent _from zero address");
        require(tokenIdToTokenOwner[_tokenId].tokenOwner == _from, "ComposableBottomUp: transferToParent tokenOwner != _from");
        require(_toContract != address(0), "ComposableBottomUp: transferToParent _toContract zero address");
        require(
            tokenIdToTokenOwner[_tokenId].parentTokenId == 0,
            "ComposableBottomUp: transferToParent Cannot transfer from address when owned by a token."
        );
        address approvedAddress =
            rootOwnerAndTokenIdToApprovedAddress[_from][_tokenId];
        if (msg.sender != _from) {
            // 0xed81cdda == rootOwnerOfChild(address,uint256)
            bytes memory callData =
                abi.encodeWithSelector(0xed81cdda, address(this), _tokenId);
            (bool callSuccess, bytes memory data) = _from.staticcall(callData);
            if (callSuccess == true) {
                bytes32 rootOwner;
                assembly {
                    rootOwner := mload(add(data, 0x20))
                }
                require(
                    rootOwner >> 224 != ERC998_MAGIC_VALUE,
                    "ComposableBottomUp: transferToParent Token is child of other top down composable"
                );
            }
            require(
                tokenOwnerToOperators[_from][msg.sender] ||
                    approvedAddress == msg.sender,
                    "ComposableBottomUp: transferToParent msg.sender is not eligible"
            );
        }

        // clear approval
        if (approvedAddress != address(0)) {
            delete rootOwnerAndTokenIdToApprovedAddress[_from][_tokenId];
            emit Approval(_from, address(0), _tokenId);
        }

        // remove and transfer token
        if (_from != _toContract) {
            assert(tokenOwnerToTokenCount[_from] > 0);
            tokenOwnerToTokenCount[_from]--;
            tokenOwnerToTokenCount[_toContract]++;
        }
        TokenOwner memory parentToken =
            TokenOwner(_toContract, _toTokenId.add(1));
        tokenIdToTokenOwner[_tokenId] = parentToken;
        uint256 index = parentToChildTokenIds[_toContract][_toTokenId].length;
        parentToChildTokenIds[_toContract][_toTokenId].push(_tokenId);
        tokenIdToChildTokenIdsIndex[_tokenId] = index;

        require(
            IERC721(_toContract).ownerOf(_toTokenId) != address(0),
            "ComposableBottomUp: transferToParent _toTokenId does not exist"
        );

        emit Transfer(_from, _toContract, _tokenId);
        emit TransferToParent(_toContract, _toTokenId, _tokenId);
    }

    function transferAsChild(
        address _fromContract,
        uint256 _fromTokenId,
        address _toContract,
        uint256 _toTokenId,
        uint256 _tokenId,
        bytes memory _data
    ) external override {
        require(tokenIdToTokenOwner[_tokenId].tokenOwner == _fromContract, "ComposableBottomUp: transferAsChild tokenOwner != _fromContract");
        require(_toContract != address(0), "ComposableBottomUp: transferAsChild _toContract zero address");
        uint256 parentTokenId = tokenIdToTokenOwner[_tokenId].parentTokenId;
        require(parentTokenId > 0, "ComposableBottomUp: transferAsChild No parent token to transfer from.");
        require(parentTokenId - 1 == _fromTokenId, "ComposableBottomUp: transferAsChild parentTokenId != _fromTokenId");
        address rootOwner = address(uint160(uint256(rootOwnerOf(_tokenId))));
        address approvedAddress =
            rootOwnerAndTokenIdToApprovedAddress[rootOwner][_tokenId];
        require(
            rootOwner == msg.sender ||
                tokenOwnerToOperators[rootOwner][msg.sender] ||
                approvedAddress == msg.sender,
                "ComposableBottomUp: transferAsChild msg.sender not eligible"
        );
        // clear approval
        if (approvedAddress != address(0)) {
            delete rootOwnerAndTokenIdToApprovedAddress[rootOwner][_tokenId];
            emit Approval(rootOwner, address(0), _tokenId);
        }

        // remove and transfer token
        if (_fromContract != _toContract) {
            assert(tokenOwnerToTokenCount[_fromContract] > 0);
            tokenOwnerToTokenCount[_fromContract]--;
            tokenOwnerToTokenCount[_toContract]++;
        }

        TokenOwner memory parentToken = TokenOwner(_toContract, _toTokenId);
        tokenIdToTokenOwner[_tokenId] = parentToken;

        removeChild(_fromContract, _fromTokenId, _tokenId);

        //add to parentToChildTokenIds
        uint256 index = parentToChildTokenIds[_toContract][_toTokenId].length;
        parentToChildTokenIds[_toContract][_toTokenId].push(_tokenId);
        tokenIdToChildTokenIdsIndex[_tokenId] = index;

        require(
            IERC721(_toContract).ownerOf(_toTokenId) != address(0),
            "ComposableBottomUp: transferAsChild _toTokenId does not exist"
        );

        emit Transfer(_fromContract, _toContract, _tokenId);
        emit TransferFromParent(_fromContract, _fromTokenId, _tokenId);
        emit TransferToParent(_toContract, _toTokenId, _tokenId);
    }

    function _transferFrom(
        address _from,
        address _to,
        uint256 _tokenId
    ) private {
        require(_from != address(0), "ComposableBottomUp: _transferFrom _from zero address");
        require(tokenIdToTokenOwner[_tokenId].tokenOwner == _from, "ComposableBottomUp: _transferFrom tokenOwner != _from");
        require(
            tokenIdToTokenOwner[_tokenId].parentTokenId == 0,
            "ComposableBottomUp: _transferFrom Cannot transfer from address when owned by a token."
        );
        require(_to != address(0), "ComposableBottomUp: _transferFrom _to zero address");
        address approvedAddress =
            rootOwnerAndTokenIdToApprovedAddress[_from][_tokenId];
        if (msg.sender != _from) {
            // 0xed81cdda == rootOwnerOfChild(address,uint256)
            bytes memory callData =
                abi.encodeWithSelector(0xed81cdda, address(this), _tokenId);
            (bool callSuccess, bytes memory data) = _from.staticcall(callData);
            if (callSuccess == true) {
                bytes32 rootOwner;
                if (callSuccess) {
                    assembly {
                        rootOwner := mload(add(data, 0x20))
                    }
                }
                require(
                    rootOwner >> 224 != ERC998_MAGIC_VALUE,
                    "ComposableBottomUp: _transferFrom Token is child of other top down composable"
                );
            }
            require(
                tokenOwnerToOperators[_from][msg.sender] ||
                    approvedAddress == msg.sender,
                    "ComposableBottomUp: _transferFrom msg.sender not eligible"
            );
        }

        // clear approval
        if (approvedAddress != address(0)) {
            delete rootOwnerAndTokenIdToApprovedAddress[_from][_tokenId];
            emit Approval(_from, address(0), _tokenId);
        }

        // remove and transfer token
        if (_from != _to) {
            assert(tokenOwnerToTokenCount[_from] > 0);
            tokenOwnerToTokenCount[_from]--;
            tokenIdToTokenOwner[_tokenId].tokenOwner = _to;
            tokenOwnerToTokenCount[_to]++;
        }
        emit Transfer(_from, _to, _tokenId);
    }

    function transferFrom(
        address _from,
        address _to,
        uint256 _tokenId
    ) external override {
        _transferFrom(_from, _to, _tokenId);
    }

    function safeTransferFrom(
        address _from,
        address _to,
        uint256 _tokenId
    ) external override {
        _transferFrom(_from, _to, _tokenId);
        if (isContract(_to)) {
            bytes4 retval =
                IERC721Receiver(_to).onERC721Received(
                    msg.sender,
                    _from,
                    _tokenId,
                    ""
                );
            require(retval == ERC721_RECEIVED, "ComposableBottomUp: safeTransferFrom(3) onERC721Received invalid value");
        }
    }

    function safeTransferFrom(
        address _from,
        address _to,
        uint256 _tokenId,
        bytes memory _data
    ) external override {
        _transferFrom(_from, _to, _tokenId);
        if (isContract(_to)) {
            bytes4 retval =
                IERC721Receiver(_to).onERC721Received(
                    msg.sender,
                    _from,
                    _tokenId,
                    _data
                );
            require(retval == ERC721_RECEIVED, "ComposableBottomUp: safeTransferFrom(4) onERC721Received invalid value");
        }
    }

    function totalChildTokens(address _parentContract, uint256 _parentTokenId)
        external
        view
        override
        returns (uint256)
    {
        return parentToChildTokenIds[_parentContract][_parentTokenId].length;
    }

    function childTokenByIndex(
        address _parentContract,
        uint256 _parentTokenId,
        uint256 _index
    ) external view override returns (uint256) {
        require(
            parentToChildTokenIds[_parentContract][_parentTokenId].length >
                _index,
                "ComposableBottomUp: childTokenByIndex invalid _index"
        );
        return parentToChildTokenIds[_parentContract][_parentTokenId][_index];
    }
}


// File @openzeppelin/contracts/token/ERC721/extensions/[email protected]


pragma solidity ^0.8.0;

/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Metadata is IERC721 {

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

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

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


// File @openzeppelin/contracts/utils/[email protected]


pragma solidity ^0.8.0;

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

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 0;
    }

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

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (bool success, ) = recipient.call{ value: amount }("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

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

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

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

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

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: value }(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

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

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

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

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

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

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

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

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}


// File @openzeppelin/contracts/utils/structs/[email protected]


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

            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs
            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.

            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) {
        require(set._values.length > index, "EnumerableSet: index out of bounds");
        return set._values[index];
    }

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

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


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


// File contracts/interfaces/IERC20AndERC223.sol


pragma solidity ^0.8.0;

interface IERC20AndERC223 {
    function transferFrom(
        address _from,
        address _to,
        uint256 _value
    ) external returns (bool success);

    function transfer(address to, uint256 value)
        external
        returns (bool success);

    function transfer(
        address to,
        uint256 value,
        bytes memory data
    ) external returns (bool success);

    function allowance(address _owner, address _spender)
        external
        view
        returns (uint256 remaining);
}


// File contracts/interfaces/IERC998ERC20TopDown.sol


pragma solidity ^0.8.0;

interface IERC998ERC20TopDown {
    event ReceivedERC20(address indexed _from, uint256 indexed _tokenId, address indexed _erc20Contract, uint256 _value);
    event TransferERC20(uint256 indexed _tokenId, address indexed _to, address indexed _erc20Contract, uint256 _value);

    function tokenFallback(address _from, uint256 _value, bytes memory _data) external;
    function balanceOfERC20(uint256 _tokenId, address _erc20Contract) external view returns (uint256);
    function transferERC20(uint256 _tokenId, address _to, address _erc20Contract, uint256 _value) external;
    function transferERC223(uint256 _tokenId, address _to, address _erc223Contract, uint256 _value, bytes memory _data) external;
    function getERC20(address _from, uint256 _tokenId, address _erc20Contract, uint256 _value) external;
}


// File contracts/interfaces/IERC998ERC20TopDownEnumerable.sol


pragma solidity ^0.8.0;

interface IERC998ERC20TopDownEnumerable {
    function totalERC20Contracts(uint256 _tokenId) external view returns (uint256);
    function erc20ContractByIndex(uint256 _tokenId, uint256 _index) external view returns (address);
}


// File contracts/interfaces/IERC998ERC721TopDown.sol


pragma solidity ^0.8.0;

interface IERC998ERC721TopDown {
    event ReceivedChild(
        address indexed _from,
        uint256 indexed _tokenId,
        address indexed _childContract,
        uint256 _childTokenId
    );
    event TransferChild(
        uint256 indexed tokenId,
        address indexed _to,
        address indexed _childContract,
        uint256 _childTokenId
    );

    function rootOwnerOf(uint256 _tokenId)
        external
        view
        returns (bytes32 rootOwner);

    function rootOwnerOfChild(address _childContract, uint256 _childTokenId)
        external
        view
        returns (bytes32 rootOwner);

    function ownerOfChild(address _childContract, uint256 _childTokenId)
        external
        view
        returns (bytes32 parentTokenOwner, uint256 parentTokenId);

    function onERC721Received(
        address _operator,
        address _from,
        uint256 _childTokenId,
        bytes calldata _data
    ) external returns (bytes4);

    function transferChild(
        uint256 _fromTokenId,
        address _to,
        address _childContract,
        uint256 _childTokenId
    ) external;

    function safeTransferChild(
        uint256 _fromTokenId,
        address _to,
        address _childContract,
        uint256 _childTokenId
    ) external;

    function safeTransferChild(
        uint256 _fromTokenId,
        address _to,
        address _childContract,
        uint256 _childTokenId,
        bytes memory _data
    ) external;

    function transferChildToParent(
        uint256 _fromTokenId,
        address _toContract,
        uint256 _toTokenId,
        address _childContract,
        uint256 _childTokenId,
        bytes memory _data
    ) external;

    // getChild function enables older contracts like cryptokitties to be transferred into a composable
    // The _childContract must approve this contract. Then getChild can be called.
    function getChild(
        address _from,
        uint256 _tokenId,
        address _childContract,
        uint256 _childTokenId
    ) external;
}


// File contracts/interfaces/IERC998ERC721TopDownEnumerable.sol


pragma solidity ^0.8.0;

interface IERC998ERC721TopDownEnumerable {
    function totalChildContracts(uint256 _tokenId)
        external
        view
        returns (uint256);

    function childContractByIndex(uint256 _tokenId, uint256 _index)
        external
        view
        returns (address childContract);

    function totalChildTokens(uint256 _tokenId, address _childContract)
        external
        view
        returns (uint256);

    function childTokenByIndex(
        uint256 _tokenId,
        address _childContract,
        uint256 _index
    ) external view returns (uint256 childTokenId);
}


// File contracts/ComposableTopDown.sol


pragma solidity ^0.8.0;











contract ComposableTopDown is
    ERC165,
    IERC721,
    IERC998ERC721TopDown,
    IERC998ERC721TopDownEnumerable,
    IERC998ERC20TopDown,
    IERC998ERC20TopDownEnumerable,
    IERC721Metadata
{
    using Address for address;
    using EnumerableSet for EnumerableSet.UintSet;
    using EnumerableSet for EnumerableSet.AddressSet;
    // return this.rootOwnerOf.selector ^ this.rootOwnerOfChild.selector ^
    //   this.tokenOwnerOf.selector ^ this.ownerOfChild.selector;
    bytes4 constant ERC998_MAGIC_VALUE = 0xcd740db5;
    bytes32 constant ERC998_MAGIC_VALUE_32 = 0xcd740db500000000000000000000000000000000000000000000000000000000;

    uint256 tokenCount = 0;

    // tokenId => token owner
    mapping(uint256 => address) private tokenIdToTokenOwner;

    // tokenId => last state hash indicator
    mapping(uint256 => uint256) private tokenIdToStateHash;

    // root token owner address => (tokenId => approved address)
    mapping(address => mapping(uint256 => address))
        private rootOwnerAndTokenIdToApprovedAddress;

    // token owner address => token count
    mapping(address => uint256) private tokenOwnerToTokenCount;

    // token owner => (operator address => bool)
    mapping(address => mapping(address => bool)) private tokenOwnerToOperators;

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

    // Token name
    string public override name;

    // Token symbol
    string public override symbol;

    constructor(string memory _name, string memory _symbol) {
        name = _name;
        symbol = _symbol;
    }

    function safeMint(address _to, string memory _tokenURI) external returns (uint256) {
        return _safeMint(_to, _tokenURI);
    }

    function safeMint(address _to) external returns (uint256) {
        return _safeMint(_to, '');
    }

    function _safeMint(address _to, string memory _tokenURI) internal returns (uint256) {
        require(_to != address(0), "ComposableTopDown: _to zero address");
        tokenCount++;
        uint256 tokenCount_ = tokenCount;
        tokenIdToTokenOwner[tokenCount_] = _to;
        tokenOwnerToTokenCount[_to]++;
        tokenIdToStateHash[tokenCount] = uint256(keccak256(abi.encodePacked(uint256(uint160(address(this))), tokenCount)));
        if (bytes(_tokenURI).length > 0) {
            tokenURIs[tokenCount_] = _tokenURI;
        }

        emit Transfer(address(0), _to, tokenCount_);
        require(_checkOnERC721Received(address(0), _to, tokenCount_, ""), "ComposableTopDown: transfer to non ERC721Receiver implementer");
        return tokenCount_;
    }

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId) external override view returns (string memory) {
        require(tokenIdToTokenOwner[tokenId] != address(0), "ComposableTopDown: URI query for nonexistent token");
        string memory _tokenURI = tokenURIs[tokenId];
        require(bytes(_tokenURI).length > 0, "ComposableTopDown: URI is not set");
        return _tokenURI;
    }


    //from zepellin ERC721Receiver.sol
    //old version
    bytes4 constant ERC721_RECEIVED_OLD = 0xf0b9e5ba;
    //new version
    bytes4 constant ERC721_RECEIVED_NEW = 0x150b7a02;

    bytes4 constant ALLOWANCE = bytes4(keccak256("allowance(address,address)"));
    bytes4 constant APPROVE = bytes4(keccak256("approve(address,uint256)"));
    bytes4 constant ROOT_OWNER_OF_CHILD =
        bytes4(keccak256("rootOwnerOfChild(address,uint256)"));

    ////////////////////////////////////////////////////////
    // ERC721 implementation
    ////////////////////////////////////////////////////////
    function rootOwnerOf(uint256 _tokenId)
        public
        view
        override
        returns (bytes32 rootOwner)
    {
        return rootOwnerOfChild(address(0), _tokenId);
    }

    // returns the owner at the top of the tree of composables
    // Use Cases handled:
    // Case 1: Token owner is this contract and token.
    // Case 2: Token owner is other top-down composable
    // Case 3: Token owner is other contract
    // Case 4: Token owner is user
    function rootOwnerOfChild(address _childContract, uint256 _childTokenId)
        public
        view
        override
        returns (bytes32 rootOwner)
    {
        address rootOwnerAddress;
        if (_childContract != address(0)) {
            (rootOwnerAddress, _childTokenId) = _ownerOfChild(
                _childContract,
                _childTokenId
            );
        } else {
            rootOwnerAddress = tokenIdToTokenOwner[_childTokenId];
            require(rootOwnerAddress != address(0), "ComposableTopDown: ownerOf _tokenId zero address");
        }
        // Case 1: Token owner is this contract and token.
        while (rootOwnerAddress == address(this)) {
            (rootOwnerAddress, _childTokenId) = _ownerOfChild(
                rootOwnerAddress,
                _childTokenId
            );
        }
        bytes memory callData =
            abi.encodeWithSelector(
                ROOT_OWNER_OF_CHILD,
                address(this),
                _childTokenId
            );
        (bool callSuccess, bytes memory data) =
            rootOwnerAddress.staticcall(callData);
        if (callSuccess) {
            assembly {
                rootOwner := mload(add(data, 0x20))
            }
        }

        if (callSuccess == true && rootOwner & 0xffffffff00000000000000000000000000000000000000000000000000000000 == ERC998_MAGIC_VALUE_32) {
            // Case 2: Token owner is other top-down composable
            return rootOwner;
        } else {
            // Case 3: Token owner is other contract
            // Or
            // Case 4: Token owner is user
            assembly {
                rootOwner := or(ERC998_MAGIC_VALUE_32, rootOwnerAddress)
            }
        }
    }

    // returns the owner at the top of the tree of composables

    function ownerOf(uint256 _tokenId)
        public
        view
        override
        returns (address tokenOwner)
    {
        tokenOwner = tokenIdToTokenOwner[_tokenId];
        require(
            tokenOwner != address(0),
            "ComposableTopDown: ownerOf _tokenId zero address"
        );
        return tokenOwner;
    }

    function balanceOf(address _tokenOwner)
        external
        view
        override
        returns (uint256)
    {
        require(
            _tokenOwner != address(0),
            "ComposableTopDown: balanceOf _tokenOwner zero address"
        );
        return tokenOwnerToTokenCount[_tokenOwner];
    }

    function approve(address _approved, uint256 _tokenId) external override {
        address rootOwner = address(uint160(uint256(rootOwnerOf(_tokenId))));
        require(
            rootOwner == msg.sender ||
                tokenOwnerToOperators[rootOwner][msg.sender],
            "ComposableTopDown: approve msg.sender not owner"
        );
        rootOwnerAndTokenIdToApprovedAddress[rootOwner][_tokenId] = _approved;
        emit Approval(rootOwner, _approved, _tokenId);
    }

    function getApproved(uint256 _tokenId)
        public
        view
        override
        returns (address)
    {
        address rootOwner = address(uint160(uint256(rootOwnerOf(_tokenId))));
        return rootOwnerAndTokenIdToApprovedAddress[rootOwner][_tokenId];
    }

    function setApprovalForAll(address _operator, bool _approved)
        external
        override
    {
        require(
            _operator != address(0),
            "ComposableTopDown: setApprovalForAll _operator zero address"
        );
        tokenOwnerToOperators[msg.sender][_operator] = _approved;
        emit ApprovalForAll(msg.sender, _operator, _approved);
    }

    function isApprovedForAll(address _owner, address _operator)
        external
        view
        override
        returns (bool)
    {
        require(
            _owner != address(0),
            "ComposableTopDown: isApprovedForAll _owner zero address"
        );
        require(
            _operator != address(0),
            "ComposableTopDown: isApprovedForAll _operator zero address"
        );
        return tokenOwnerToOperators[_owner][_operator];
    }

    function transferFrom(
        address _from,
        address _to,
        uint256 _tokenId
    ) public override {
        _transferFrom(_from, _to, _tokenId);
    }

    function safeTransferFrom(
        address _from,
        address _to,
        uint256 _tokenId
    ) public override {
        _transferFrom(_from, _to, _tokenId);
        if (_to.isContract()) {
            bytes4 retval =
                IERC721Receiver(_to).onERC721Received(
                    msg.sender,
                    _from,
                    _tokenId,
                    ""
                );
            require(
                retval == ERC721_RECEIVED_OLD || retval == ERC721_RECEIVED_NEW,
                "ComposableTopDown: safeTransferFrom(3) onERC721Received invalid return value"
            );
        }
    }

    function safeTransferFrom(
        address _from,
        address _to,
        uint256 _tokenId,
        bytes memory _data
    ) public override {
        _transferFrom(_from, _to, _tokenId);
        if (_to.isContract()) {
            bytes4 retval =
                IERC721Receiver(_to).onERC721Received(
                    msg.sender,
                    _from,
                    _tokenId,
                    _data
                );
            require(
                retval == ERC721_RECEIVED_OLD || retval == ERC721_RECEIVED_NEW,
                "ComposableTopDown: safeTransferFrom(4) onERC721Received invalid return value"
            );
            rootOwnerOf(_tokenId);
        }
    }

    function _transferFrom(
        address _from,
        address _to,
        uint256 _tokenId
    ) private {
        require(
            _from != address(0),
            "ComposableTopDown: _transferFrom _from zero address"
        );
        require(
            tokenIdToTokenOwner[_tokenId] == _from,
            "ComposableTopDown: _transferFrom _from not owner"
        );
        require(
            _to != address(0),
            "ComposableTopDown: _transferFrom _to zero address"
        );

        if (msg.sender != _from) {
            bytes memory callData =
                abi.encodeWithSelector(
                    ROOT_OWNER_OF_CHILD,
                    address(this),
                    _tokenId
                );
            (bool callSuccess, bytes memory data) = _from.staticcall(callData);
            if (callSuccess == true) {
                bytes32 rootOwner;
                assembly {
                    rootOwner := mload(add(data, 0x20))
                }
                require(
                    rootOwner & 0xffffffff00000000000000000000000000000000000000000000000000000000 != ERC998_MAGIC_VALUE_32,
                    "ComposableTopDown: _transferFrom token is child of other top down composable"
                );
            }

            require(
                tokenOwnerToOperators[_from][msg.sender] ||
                    rootOwnerAndTokenIdToApprovedAddress[_from][_tokenId] ==
                    msg.sender,
                "ComposableTopDown: _transferFrom msg.sender not approved"
            );
        }

        // clear approval
        if (
            rootOwnerAndTokenIdToApprovedAddress[_from][_tokenId] != address(0)
        ) {
            delete rootOwnerAndTokenIdToApprovedAddress[_from][_tokenId];
            emit Approval(_from, address(0), _tokenId);
        }

        // remove and transfer token
        if (_from != _to) {
            assert(tokenOwnerToTokenCount[_from] > 0);
            tokenOwnerToTokenCount[_from]--;
            tokenIdToTokenOwner[_tokenId] = _to;
            tokenOwnerToTokenCount[_to]++;
        }
        emit Transfer(_from, _to, _tokenId);
    }

    ////////////////////////////////////////////////////////
    // ERC998ERC721 and ERC998ERC721Enumerable implementation
    ////////////////////////////////////////////////////////

    // tokenId => child contract
    mapping(uint256 => EnumerableSet.AddressSet) private childContracts;

    // tokenId => (child address => array of child tokens)
    mapping(uint256 => mapping(address => EnumerableSet.UintSet))
        private childTokens;

    // child address => childId => tokenId
    mapping(address => mapping(uint256 => uint256)) private childTokenOwner;

    function safeTransferChild(
        uint256 _fromTokenId,
        address _to,
        address _childContract,
        uint256 _childTokenId
    ) external override {
        _transferChild(_fromTokenId, _to, _childContract, _childTokenId);
        IERC721(_childContract).safeTransferFrom(
            address(this),
            _to,
            _childTokenId
        );
        emit TransferChild(_fromTokenId, _to, _childContract, _childTokenId);
    }

    function safeTransferChild(
        uint256 _fromTokenId,
        address _to,
        address _childContract,
        uint256 _childTokenId,
        bytes memory _data
    ) external override {
        _transferChild(_fromTokenId, _to, _childContract, _childTokenId);
        IERC721(_childContract).safeTransferFrom(
            address(this),
            _to,
            _childTokenId,
            _data
        );
        emit TransferChild(_fromTokenId, _to, _childContract, _childTokenId);
    }

    function transferChild(
        uint256 _fromTokenId,
        address _to,
        address _childContract,
        uint256 _childTokenId
    ) external override {
        _transferChild(_fromTokenId, _to, _childContract, _childTokenId);
        //this is here to be compatible with cryptokitties and other old contracts that require being owner and approved
        // before transferring.
        //does not work with current standard which does not allow approving self, so we must let it fail in that case.
        bytes memory callData =
            abi.encodeWithSelector(APPROVE, this, _childTokenId);
        _childContract.call(callData);

        IERC721(_childContract).transferFrom(address(this), _to, _childTokenId);
        emit TransferChild(_fromTokenId, _to, _childContract, _childTokenId);
    }

    function transferChildToParent(
        uint256 _fromTokenId,
        address _toContract,
        uint256 _toTokenId,
        address _childContract,
        uint256 _childTokenId,
        bytes memory _data
    ) external override {
        _transferChild(
            _fromTokenId,
            _toContract,
            _childContract,
            _childTokenId
        );
        emit TransferChild(
            _fromTokenId,
            _toContract,
            _childContract,
            _childTokenId
        );
        IERC998ERC721BottomUp(_childContract).transferToParent(
            address(this),
            _toContract,
            _toTokenId,
            _childTokenId,
            _data
        );
    }

    // this contract has to be approved first in _childContract
    function getChild(
        address _from,
        uint256 _tokenId,
        address _childContract,
        uint256 _childTokenId
    ) external override {
        receiveChild(_from, _tokenId, _childContract, _childTokenId);
        require(
            _from == msg.sender ||
                IERC721(_childContract).isApprovedForAll(_from, msg.sender) ||
                IERC721(_childContract).getApproved(_childTokenId) ==
                msg.sender,
            "ComposableTopDown: getChild msg.sender not approved"
        );
        IERC721(_childContract).transferFrom(
            _from,
            address(this),
            _childTokenId
        );
        // a check for looped ownership chain
        rootOwnerOf(_tokenId);
    }

    function onERC721Received(
        address _from,
        uint256 _childTokenId,
        bytes calldata _data
    ) external returns (bytes4) {
        require(
            _data.length > 0,
            "ComposableTopDown: onERC721Received(3) _data must contain the uint256 tokenId to transfer the child token to"
        );
        // convert up to 32 bytes of _data to uint256, owner nft tokenId passed as uint in bytes
        uint256 tokenId = _parseTokenId(_data);
        receiveChild(_from, tokenId, msg.sender, _childTokenId);
        require(
            IERC721(msg.sender).ownerOf(_childTokenId) != address(0),
            "ComposableTopDown: onERC721Received(3) child token not owned"
        );
        // a check for looped ownership chain
        rootOwnerOf(tokenId);
        return ERC721_RECEIVED_OLD;
    }

    function onERC721Received(
        address,
        address _from,
        uint256 _childTokenId,
        bytes calldata _data
    ) external override returns (bytes4) {
        require(
            _data.length > 0,
            "ComposableTopDown: onERC721Received(4) _data must contain the uint256 tokenId to transfer the child token to"
        );
        // convert up to 32 bytes of _data to uint256, owner nft tokenId passed as uint in bytes
        uint256 tokenId = _parseTokenId(_data);
        receiveChild(_from, tokenId, msg.sender, _childTokenId);
        require(
            IERC721(msg.sender).ownerOf(_childTokenId) != address(0),
            "ComposableTopDown: onERC721Received(4) child token not owned"
        );
        // a check for looped ownership chain
        rootOwnerOf(tokenId);
        return ERC721_RECEIVED_NEW;
    }

    function childExists(address _childContract, uint256 _childTokenId)
        external
        view
        returns (bool)
    {
        uint256 tokenId = childTokenOwner[_childContract][_childTokenId];
        return tokenId != 0;
    }

    function totalChildContracts(uint256 _tokenId)
        external
        view
        override
        returns (uint256)
    {
        return childContracts[_tokenId].length();
    }

    function childContractByIndex(uint256 _tokenId, uint256 _index)
        external
        view
        override
        returns (address childContract)
    {
        return childContracts[_tokenId].at(_index);
    }

    function totalChildTokens(uint256 _tokenId, address _childContract)
        external
        view
        override
        returns (uint256)
    {
        return childTokens[_tokenId][_childContract].length();
    }

    function childTokenByIndex(
        uint256 _tokenId,
        address _childContract,
        uint256 _index
    ) external view override returns (uint256 childTokenId) {
        return childTokens[_tokenId][_childContract].at(_index);
    }

    function ownerOfChild(address _childContract, uint256 _childTokenId)
        external
        view
        override
        returns (bytes32 parentTokenOwner, uint256 parentTokenId)
    {
        parentTokenId = childTokenOwner[_childContract][_childTokenId];
        require(
            parentTokenId != 0,
            "ComposableTopDown: ownerOfChild not found"
        );
        address parentTokenOwnerAddress = tokenIdToTokenOwner[parentTokenId];
        assembly {
            parentTokenOwner := or(ERC998_MAGIC_VALUE_32, parentTokenOwnerAddress)
        }

    }

    function _transferChild(
        uint256 _fromTokenId,
        address _to,
        address _childContract,
        uint256 _childTokenId
    ) private {
        uint256 tokenId = childTokenOwner[_childContract][_childTokenId];
        require(
            tokenId != 0,
            "ComposableTopDown: _transferChild _childContract _childTokenId not found"
        );
        require(
            tokenId == _fromTokenId,
            "ComposableTopDown: _transferChild wrong tokenId found"
        );
        require(
            _to != address(0),
            "ComposableTopDown: _transferChild _to zero address"
        );
        address rootOwner = address(uint160(uint256(rootOwnerOf(tokenId))));
        require(
            rootOwner == msg.sender ||
                tokenOwnerToOperators[rootOwner][msg.sender] ||
                rootOwnerAndTokenIdToApprovedAddress[rootOwner][tokenId] ==
                msg.sender,
            "ComposableTopDown: _transferChild msg.sender not eligible"
        );
        removeChild(tokenId, _childContract, _childTokenId);
    }

    function _ownerOfChild(address _childContract, uint256 _childTokenId)
        private
        view
        returns (address parentTokenOwner, uint256 parentTokenId)
    {
        parentTokenId = childTokenOwner[_childContract][_childTokenId];
        require(
            parentTokenId != 0,
            "ComposableTopDown: _ownerOfChild not found"
        );
        return (tokenIdToTokenOwner[parentTokenId], parentTokenId);
    }

    function _parseTokenId(bytes memory _data)
        private
        pure
        returns (uint256 tokenId)
    {
        // convert up to 32 bytes of_data to uint256, owner nft tokenId passed as uint in bytes
        assembly {
            tokenId := mload(add(_data, 0x20))
        }
        if (_data.length < 32) {
            tokenId = tokenId >> (256 - _data.length * 8);
        }
    }

    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)
        private returns (bool)
    {
        if (to.isContract()) {
            try IERC721Receiver(to).onERC721Received(msg.sender, from, tokenId, _data) returns (bytes4 retval) {
                return retval == IERC721Receiver(to).onERC721Received.selector;
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert("ERC721: transfer to non ERC721Receiver implementer");
                } else {
                    // solhint-disable-next-line no-inline-assembly
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        } else {
            return true;
        }
    }

    function removeChild(
        uint256 _tokenId,
        address _childContract,
        uint256 _childTokenId
    ) private {
        // remove child token
        uint256 lastTokenIndex =
            childTokens[_tokenId][_childContract].length() - 1;
        require(childTokens[_tokenId][_childContract].remove(_childTokenId), "ComposableTopDown: removeChild: _childTokenId not found");
        delete childTokenOwner[_childContract][_childTokenId];

        // remove contract
        if (lastTokenIndex == 0) {
            require(childContracts[_tokenId].remove(_childContract), "ComposableTopDown: removeChild: _childContract not found");
        }
        if (_childContract == address(this)) {
            _updateStateHash(_tokenId, uint256(uint160(_childContract)), tokenIdToStateHash[_childTokenId]);
        } else {
            _updateStateHash(_tokenId, uint256(uint160(_childContract)), _childTokenId);
        }
    }

    function receiveChild(
        address _from,
        uint256 _tokenId,
        address _childContract,
        uint256 _childTokenId
    ) private {
        require(
            tokenIdToTokenOwner[_tokenId] != address(0),
            "ComposableTopDown: receiveChild _tokenId does not exist."
        );
        require(
            childTokenOwner[_childContract][_childTokenId] != _tokenId,
            "ComposableTopDown: receiveChild _childTokenId already received"
        );
        uint256 childTokensLength =
            childTokens[_tokenId][_childContract].length();
        if (childTokensLength == 0) {
            require(childContracts[_tokenId].add(_childContract), "ComposableTopDown: receiveChild: add _childContract");
        }
        require(childTokens[_tokenId][_childContract].add(_childTokenId), "ComposableTopDown: receiveChild: add _childTokenId");
        childTokenOwner[_childContract][_childTokenId] = _tokenId;
        if (_childContract == address(this)) {
            _updateStateHash(_tokenId, uint256(uint160(_childContract)), tokenIdToStateHash[_childTokenId]);
        } else {
            _updateStateHash(_tokenId, uint256(uint160(_childContract)), _childTokenId);
        }
        emit ReceivedChild(_from, _tokenId, _childContract, _childTokenId);
    }

    ////////////////////////////////////////////////////////
    // ERC998ERC223 and ERC998ERC223Enumerable implementation
    ////////////////////////////////////////////////////////

    // tokenId => token contract
    mapping(uint256 => EnumerableSet.AddressSet) erc20Contracts;

    // tokenId => (token contract => balance)
    mapping(uint256 => mapping(address => uint256)) erc20Balances;

    function transferERC20(
        uint256 _tokenId,
        address _to,
        address _erc20Contract,
        uint256 _value
    ) external override {
        require(
            _to != address(0),
            "ComposableTopDown: transferERC20 _to zero address"
        );
        address rootOwner = address(uint160(uint256(rootOwnerOf(_tokenId))));
        require(
            rootOwner == msg.sender ||
                tokenOwnerToOperators[rootOwner][msg.sender] ||
                rootOwnerAndTokenIdToApprovedAddress[rootOwner][_tokenId] ==
                msg.sender,
            "ComposableTopDown: transferERC20 msg.sender not eligible"
        );
        removeERC20(_tokenId, _erc20Contract, _value);
        require(
            IERC20AndERC223(_erc20Contract).transfer(_to, _value),
            "ComposableTopDown: transferERC20 transfer failed"
        );
        emit TransferERC20(_tokenId, _to, _erc20Contract, _value);
    }

    // implementation of ERC 223
    function transferERC223(
        uint256 _tokenId,
        address _to,
        address _erc223Contract,
        uint256 _value,
        bytes memory _data
    ) external override {
        require(
            _to != address(0),
            "ComposableTopDown: transferERC223 _to zero address"
        );
        address rootOwner = address(uint160(uint256(rootOwnerOf(_tokenId))));
        require(
            rootOwner == msg.sender ||
                tokenOwnerToOperators[rootOwner][msg.sender] ||
                rootOwnerAndTokenIdToApprovedAddress[rootOwner][_tokenId] ==
                msg.sender,
            "ComposableTopDown: transferERC223 msg.sender not eligible"
        );
        removeERC20(_tokenId, _erc223Contract, _value);
        require(
            IERC20AndERC223(_erc223Contract).transfer(_to, _value, _data),
            "ComposableTopDown: transferERC223 transfer failed"
        );
        emit TransferERC20(_tokenId, _to, _erc223Contract, _value);
    }

    // used by ERC 223
    function tokenFallback(
        address _from,
        uint256 _value,
        bytes memory _data
    ) external override {
        require(
            _data.length > 0,
            "ComposableTopDown: tokenFallback _data must contain the uint256 tokenId to transfer the token to"
        );
        require(
            tx.origin != msg.sender,
            "ComposableTopDown: tokenFallback msg.sender is not a contract"
        );
        uint256 tokenId = _parseTokenId(_data);
        erc20Received(_from, tokenId, msg.sender, _value);
    }

    function balanceOfERC20(uint256 _tokenId, address _erc20Contract)
        external
        view
        override
        returns (uint256)
    {
        return erc20Balances[_tokenId][_erc20Contract];
    }

    function erc20ContractByIndex(uint256 _tokenId, uint256 _index)
        external
        view
        override
        returns (address)
    {
        return erc20Contracts[_tokenId].at(_index);
    }

    function totalERC20Contracts(uint256 _tokenId)
        external
        view
        override
        returns (uint256)
    {
        return erc20Contracts[_tokenId].length();
    }

    // this contract has to be approved first by _erc20Contract
    function getERC20(
        address _from,
        uint256 _tokenId,
        address _erc20Contract,
        uint256 _value
    ) public override {
        bool allowed = _from == msg.sender;
        if (!allowed) {
            bytes memory callData =
                abi.encodeWithSelector(ALLOWANCE, _from, msg.sender);
            (bool callSuccess, bytes memory data) =
                _erc20Contract.staticcall(callData);
            require(
                callSuccess,
                "ComposableTopDown: getERC20 allowance failed"
            );
            uint256 remaining;
            assembly {
                remaining := mload(add(data, 0x20))
            }
            require(
                remaining >= _value,
                "ComposableTopDown: getERC20 value greater than remaining"
            );
            allowed = true;
        }
        require(allowed, "ComposableTopDown: getERC20 not allowed to getERC20");
        erc20Received(_from, _tokenId, _erc20Contract, _value);
        require(
            IERC20AndERC223(_erc20Contract).transferFrom(
                _from,
                address(this),
                _value
            ),
            "ComposableTopDown: getERC20 transfer failed"
        );
    }

    function erc20Received(
        address _from,
        uint256 _tokenId,
        address _erc20Contract,
        uint256 _value
    ) private {
        require(
            tokenIdToTokenOwner[_tokenId] != address(0),
            "ComposableTopDown: erc20Received _tokenId does not exist"
        );
        if (_value == 0) {
            return;
        }
        uint256 erc20Balance = erc20Balances[_tokenId][_erc20Contract];
        if (erc20Balance == 0) {
            require(erc20Contracts[_tokenId].add(_erc20Contract), "ComposableTopDown: erc20Received: erc20Contracts add _erc20Contract");
        }
        erc20Balances[_tokenId][_erc20Contract] += _value;
        _updateStateHash(_tokenId, uint256(uint160(_erc20Contract)), erc20Balance + _value);
        emit ReceivedERC20(_from, _tokenId, _erc20Contract, _value);
    }

    function removeERC20(
        uint256 _tokenId,
        address _erc20Contract,
        uint256 _value
    ) private {
        if (_value == 0) {
            return;
        }
        uint256 erc20Balance = erc20Balances[_tokenId][_erc20Contract];
        require(
            erc20Balance >= _value,
            "ComposableTopDown: removeERC20 value not enough"
        );
        unchecked {
            // overflow already checked
            uint256 newERC20Balance = erc20Balance - _value;
            erc20Balances[_tokenId][_erc20Contract] = newERC20Balance;
            if (newERC20Balance == 0) {
                require(erc20Contracts[_tokenId].remove(_erc20Contract), "ComposableTopDown: removeERC20: erc20Contracts remove _erc20Contract");
            }
            _updateStateHash(_tokenId, uint256(uint160(_erc20Contract)), newERC20Balance);
        }
    }

    ////////////////////////////////////////////////////////
    // ERC165 implementation
    ////////////////////////////////////////////////////////

    /**
     * @dev See {IERC165-supportsInterface}.
     * The interface id 0x1bc995e4 is added. The spec claims it to be the interface id of IERC998ERC721TopDown.
     * But it is not.
     * It is added anyway in case some contract checks it being compliant with the spec.
     */
    function supportsInterface(bytes4 interfaceId) public view override(IERC165,ERC165) returns (bool) {
        return interfaceId == type(IERC721).interfaceId
            || interfaceId == type(IERC721Metadata).interfaceId
            || interfaceId == type(IERC998ERC721TopDown).interfaceId
            || interfaceId == type(IERC998ERC721TopDownEnumerable).interfaceId
            || interfaceId == type(IERC998ERC20TopDown).interfaceId
            || interfaceId == type(IERC998ERC20TopDownEnumerable).interfaceId
            || interfaceId == 0x1bc995e4
            || super.supportsInterface(interfaceId);
    }

    ////////////////////////////////////////////////////////
    // Last State Hash
    ////////////////////////////////////////////////////////

    /**
     * Update the state hash of tokenId and all its ancestors.
     * @param tokenId token id
     * @param childReference generalization of a child contract adddress
     * @param value new balance of ERC20, childTokenId of ERC721 or a child's state hash (if childContract==address(this))
     */
    function _updateStateHash(uint256 tokenId, uint256 childReference, uint256 value) private {
        uint256 _newStateHash = uint256(keccak256(abi.encodePacked(tokenIdToStateHash[tokenId], childReference, value)));
        tokenIdToStateHash[tokenId] = _newStateHash;
        while (tokenIdToTokenOwner[tokenId] == address(this)) {
            tokenId = childTokenOwner[address(this)][tokenId];
            _newStateHash = uint256(keccak256(abi.encodePacked(tokenIdToStateHash[tokenId], uint256(uint160(address(this))), _newStateHash)));
            tokenIdToStateHash[tokenId] = _newStateHash;
        }
    }

    function stateHash(uint256 tokenId) public view returns (uint256) {
        uint256 _stateHash = tokenIdToStateHash[tokenId];
        require(_stateHash > 0, "ComposableTopDown: stateHash of _tokenId is zero");
        return _stateHash;
    }

    /**
     * @dev See {safeTransferFrom}.
     * Check the state hash and call safeTransferFrom.
     */
    function safeCheckedTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        uint256 expectedStateHash
    ) external {
        require(expectedStateHash == tokenIdToStateHash[tokenId], "ComposableTopDown: stateHash mismatch (1)");
        safeTransferFrom(from, to, tokenId);
    }

    /**
     * @dev See {transferFrom}.
     * Check the state hash and call transferFrom.
     */
    function checkedTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        uint256 expectedStateHash
    ) external {
        require(expectedStateHash == tokenIdToStateHash[tokenId], "ComposableTopDown: stateHash mismatch (2)");
        transferFrom(from, to, tokenId);
    }

    /**
     * @dev See {safeTransferFrom}.
     * Check the state hash and call safeTransferFrom.
     */
    function safeCheckedTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        uint256 expectedStateHash,
        bytes calldata data
    ) external {
        require(expectedStateHash == tokenIdToStateHash[tokenId], "ComposableTopDown: stateHash mismatch (3)");
        safeTransferFrom(from, to, tokenId, data);
    }

}


// File contracts/samples/ContractIERC721ReceiverNew.sol


pragma solidity ^0.8.0;

contract ContractIERC721ReceiverNew is IERC721Receiver {
    bytes4 constant ERC721_RECEIVED = 0xcd740db5;

    function onERC721Received(
        address,
        address,
        uint256,
        bytes calldata
    ) external pure override returns (bytes4) {
        return ERC721_RECEIVED;
    }
}


// File @openzeppelin/contracts/utils/[email protected]


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) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
}


// File @openzeppelin/contracts/utils/[email protected]


pragma solidity ^0.8.0;

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

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

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

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

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

}


// File @openzeppelin/contracts/token/ERC721/[email protected]


pragma solidity ^0.8.0;







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

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

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

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

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

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

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

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

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

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

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

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

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

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

    /**
     * @dev Base URI for computing {tokenURI}. Empty by default, can be overriden
     * in child contracts.
     */
    function _baseURI() internal view virtual returns (string memory) {
        return "";
    }

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

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

        _approve(to, tokenId);
    }

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

        return _tokenApprovals[tokenId];
    }

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

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

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

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

        _transfer(from, to, tokenId);
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        _beforeTokenTransfer(from, to, tokenId);

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

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

        emit Transfer(from, to, tokenId);
    }

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

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

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


// File @openzeppelin/contracts/utils/[email protected]


pragma solidity ^0.8.0;

/**
 * @title Counters
 * @author Matt Condon (@shrugs)
 * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number
 * of elements in a mapping, issuing ERC721 ids, or counting request ids.
 *
 * Include with `using Counters for Counters.Counter;`
 */
library Counters {
    struct Counter {
        // This variable should never be directly accessed by users of the library: interactions must be restricted to
        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
        // this feature: see https://github.com/ethereum/solidity/issues/4637
        uint256 _value; // default: 0
    }

    function current(Counter storage counter) internal view returns (uint256) {
        return counter._value;
    }

    function increment(Counter storage counter) internal {
        unchecked {
            counter._value += 1;
        }
    }

    function decrement(Counter storage counter) internal {
        uint256 value = counter._value;
        require(value > 0, "Counter: decrement overflow");
        unchecked {
            counter._value = value - 1;
        }
    }
}


// File contracts/samples/ContractIERC721ReceiverOld.sol


pragma solidity ^0.8.0;



contract ContractIERC721ReceiverOld is ERC721, IERC721Receiver {
    bytes4 constant ERC721_RECEIVED_OLD = 0xf0b9e5ba;

    using Counters for Counters.Counter;

    Counters.Counter public _tokenIds;

    uint256 data = 1;

    constructor() public ERC721("NFT_OLD_RECEIVER", "NOR") {}

    function mint721(address _to) public returns (uint256) {
        _tokenIds.increment();
        uint256 newItemId = _tokenIds.current();

        _safeMint(_to, newItemId);
        return newItemId;
    }

    function onERC721Received(
        address,
        address,
        uint256,
        bytes calldata
    ) external pure override returns (bytes4) {
        return ERC721_RECEIVED_OLD;
    }
}


// File @openzeppelin/contracts/token/ERC20/[email protected]


pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

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

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

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

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

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

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


// File @openzeppelin/contracts/token/ERC20/extensions/[email protected]


pragma solidity ^0.8.0;

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

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

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


// File @openzeppelin/contracts/token/ERC20/[email protected]


pragma solidity ^0.8.0;



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

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

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

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

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

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

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

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

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

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

    /**
     * @dev See {IERC20-approve}.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * Requirements:
     *
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     * - the caller must have allowance for ``sender``'s tokens of at least
     * `amount`.
     */
    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);

        uint256 currentAllowance = _allowances[sender][_msgSender()];
        require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
        _approve(sender, _msgSender(), currentAllowance - amount);

        return true;
    }

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

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

        return true;
    }

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

        _beforeTokenTransfer(sender, recipient, amount);

        uint256 senderBalance = _balances[sender];
        require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
        _balances[sender] = senderBalance - amount;
        _balances[recipient] += amount;

        emit Transfer(sender, recipient, amount);
    }

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

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

        _totalSupply += amount;
        _balances[account] += amount;
        emit Transfer(address(0), account, amount);
    }

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

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

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        _balances[account] = accountBalance - amount;
        _totalSupply -= amount;

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

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

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

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


// File contracts/interfaces/IERC223Receiver.sol


pragma solidity ^0.8.0;

interface IERC223Receiver {
  /**
   * @dev Standard ERC223 function that will handle incoming token transfers.
   *
   * @param _from  Token sender address.
   * @param _value Amount of tokens.
   * @param _data  Transaction metadata.
   */
  function tokenFallback(address _from, uint _value, bytes memory _data) external;
}


// File contracts/samples/SampleERC20.sol


pragma solidity ^0.8.0;


contract SampleERC20 is ERC20 {
    using Address for address;

    constructor(string memory tokenName, string memory tokenSymbol)
        public
        ERC20(tokenName, tokenSymbol)
    {}

    function mint(address account, uint256 amount) public {
        super._mint(account, amount);
    }

    function transfer(
        address _to,
        uint256 _value,
        bytes memory _data
    ) external returns (bool) {
        _transfer(msg.sender, _to, _value);

        if (_to.isContract()) {
            // Require proper transaction handling.
            IERC223Receiver receiver = IERC223Receiver(_to);
            receiver.tokenFallback(msg.sender, _value, _data);
        }

        return true;
    }
}


// File contracts/interfaces/IERC721ReceiverOld.sol


pragma solidity ^0.8.0;

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


// File contracts/samples/SampleNFT.sol


pragma solidity ^0.8.0;


contract SampleNFT is ERC721 {
    using Address for address;
    using Counters for Counters.Counter;

    Counters.Counter public _tokenIds;
    mapping(string => bool) public hashes;

    uint256 data = 1;

    //old version
    bytes4 constant ERC721_RECEIVED_OLD = 0xf0b9e5ba;

    constructor() public ERC721("Sample NFT", "NFT") {}

    /// wrapper on minting new 721
    function mint721(address _to, string memory _hash)
        public
        returns (uint256)
    {
        require(hashes[_hash] != true);
        hashes[_hash] = true;

        _tokenIds.increment();
        uint256 newItemId = _tokenIds.current();

        _safeMint(_to, newItemId);
        return newItemId;
    }

    function safeTransferFromOld(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) public {
        require(
            _isApprovedOrOwner(_msgSender(), tokenId),
            "SampleNFT: transfer caller is not owner nor approved"
        );

        _transfer(from, to, tokenId);

        require(
            _checkOnERC721ReceivedOld(from, to, tokenId, _data),
            "SampleNFT: transfer to non ERC721Receiver implementer"
        );
    }

    /// @dev mocked for ComposableTopDown safeTransferChild(4)
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public override {
        safeTransferFrom(from, to, tokenId, abi.encode(data));
    }

    function _checkOnERC721ReceivedOld(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) private returns (bool) {
        if (!to.isContract()) {
            return true;
        }
        bytes memory returndata =
            to.functionCall(
                abi.encodeWithSelector(
                    IERC721ReceiverOld(to).onERC721Received.selector,
                    from,
                    tokenId,
                    _data
                ),
                "SampleNFT: transfer to non ERC721Receiver implementer"
            );
        bytes4 retval = abi.decode(returndata, (bytes4));
        return (retval == ERC721_RECEIVED_OLD);
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"uint256","name":"_tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"_childContract","type":"address"},{"indexed":false,"internalType":"uint256","name":"_childTokenId","type":"uint256"}],"name":"ReceivedChild","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"uint256","name":"_tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"_erc20Contract","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"ReceivedERC20","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":true,"internalType":"address","name":"_childContract","type":"address"},{"indexed":false,"internalType":"uint256","name":"_childTokenId","type":"uint256"}],"name":"TransferChild","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":true,"internalType":"address","name":"_erc20Contract","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"TransferERC20","type":"event"},{"inputs":[{"internalType":"address","name":"_approved","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenOwner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_erc20Contract","type":"address"}],"name":"balanceOfERC20","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"},{"internalType":"uint256","name":"expectedStateHash","type":"uint256"}],"name":"checkedTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"childContractByIndex","outputs":[{"internalType":"address","name":"childContract","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_childContract","type":"address"},{"internalType":"uint256","name":"_childTokenId","type":"uint256"}],"name":"childExists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_childContract","type":"address"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"childTokenByIndex","outputs":[{"internalType":"uint256","name":"childTokenId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"erc20ContractByIndex","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_childContract","type":"address"},{"internalType":"uint256","name":"_childTokenId","type":"uint256"}],"name":"getChild","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_erc20Contract","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"getERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_childTokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_childTokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"tokenOwner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_childContract","type":"address"},{"internalType":"uint256","name":"_childTokenId","type":"uint256"}],"name":"ownerOfChild","outputs":[{"internalType":"bytes32","name":"parentTokenOwner","type":"bytes32"},{"internalType":"uint256","name":"parentTokenId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"rootOwnerOf","outputs":[{"internalType":"bytes32","name":"rootOwner","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_childContract","type":"address"},{"internalType":"uint256","name":"_childTokenId","type":"uint256"}],"name":"rootOwnerOfChild","outputs":[{"internalType":"bytes32","name":"rootOwner","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"expectedStateHash","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeCheckedTransferFrom","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":"uint256","name":"expectedStateHash","type":"uint256"}],"name":"safeCheckedTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"}],"name":"safeMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"string","name":"_tokenURI","type":"string"}],"name":"safeMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fromTokenId","type":"uint256"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"address","name":"_childContract","type":"address"},{"internalType":"uint256","name":"_childTokenId","type":"uint256"}],"name":"safeTransferChild","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fromTokenId","type":"uint256"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"address","name":"_childContract","type":"address"},{"internalType":"uint256","name":"_childTokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferChild","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_operator","type":"address"},{"internalType":"bool","name":"_approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"stateHash","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":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"tokenFallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"totalChildContracts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_childContract","type":"address"}],"name":"totalChildTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"totalERC20Contracts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fromTokenId","type":"uint256"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"address","name":"_childContract","type":"address"},{"internalType":"uint256","name":"_childTokenId","type":"uint256"}],"name":"transferChild","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fromTokenId","type":"uint256"},{"internalType":"address","name":"_toContract","type":"address"},{"internalType":"uint256","name":"_toTokenId","type":"uint256"},{"internalType":"address","name":"_childContract","type":"address"},{"internalType":"uint256","name":"_childTokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"transferChildToParent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"address","name":"_erc20Contract","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"transferERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"address","name":"_erc223Contract","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"transferERC223","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6080604052600080553480156200001557600080fd5b5060405162004e4f38038062004e4f8339810160408190526200003891620001bd565b81516200004d9060079060208501906200006c565b508051620000639060089060208401906200006c565b50505062000277565b8280546200007a9062000224565b90600052602060002090601f0160209004810192826200009e5760008555620000e9565b82601f10620000b957805160ff1916838001178555620000e9565b82800160010185558215620000e9579182015b82811115620000e9578251825591602001919060010190620000cc565b50620000f7929150620000fb565b5090565b5b80821115620000f75760008155600101620000fc565b600082601f83011262000123578081fd5b81516001600160401b038082111562000140576200014062000261565b6040516020601f8401601f191682018101838111838210171562000168576200016862000261565b60405283825285840181018710156200017f578485fd5b8492505b83831015620001a2578583018101518284018201529182019162000183565b83831115620001b357848185840101525b5095945050505050565b60008060408385031215620001d0578182fd5b82516001600160401b0380821115620001e7578384fd5b620001f58683870162000112565b935060208501519150808211156200020b578283fd5b506200021a8582860162000112565b9150509250929050565b6002810460018216806200023957607f821691505b602082108114156200025b57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052604160045260246000fd5b614bc880620002876000396000f3fe608060405234801561001057600080fd5b50600436106102535760003560e01c80636352211e11610146578063ba6b5f96116100c3578063d49d1bac11610087578063d49d1bac14610527578063e226ed221461053a578063e985e9c51461054d578063eadb80b814610560578063ed81cdda14610581578063f0b9e5ba1461059457610253565b8063ba6b5f96146104c8578063bef44f18146104db578063c0ee0b8a146104ee578063c87b56dd14610501578063d204c45e1461051457610253565b80638da7d0b51161010a5780638da7d0b51461047457806395d89b4114610487578063a22cb4651461048f578063a7811732146104a2578063b88d4fde146104b557610253565b80636352211e1461041557806370a082311461042857806379eda5411461043b578063830ef41b1461044e5780638d81f51e1461046157610253565b80631d98f3c5116101d457806342842e0e1161019857806342842e0e146103b657806343a61a8e146103c95780634ff33816146103dc5780635680a3ad146103ef578063627c81ff1461040257610253565b80631d98f3c51461035757806323b872dd1461036a57806335b21ceb1461037d5780633cc8cf1e1461039057806340d097c3146103a357610253565b8063095ea7b31161021b578063095ea7b3146102de5780630d5a621b146102f1578063150b7a0214610304578063160b01a1146103245780631c5481e21461034457610253565b806301ffc9a71461025857806306fdde031461028157806307cff6f214610296578063081812fc146102ab57806308937f62146102cb575b600080fd5b61026b61026636600461334f565b6105a7565b60405161027891906136ed565b60405180910390f35b610289610676565b6040516102789190613716565b6102a96102a436600461323b565b610704565b005b6102be6102b9366004613387565b610902565b604051610278919061359d565b6102a96102d9366004613494565b61093c565b6102a96102ec366004613210565b610a02565b6102be6102ff366004613510565b610acb565b610317610312366004612fe8565b610aec565b6040516102789190613701565b61033761033236600461346e565b610c14565b60405161027891906136f8565b6102a96103523660046130c3565b610c48565b6102a96103653660046133c3565b610c86565b6102a9610378366004612fa8565b610d46565b61033761038b36600461339f565b610d56565b6102a961039e366004613108565b610d81565b6103376103b1366004612f38565b610df8565b6102a96103c4366004612fa8565b610e13565b6103376103d7366004613387565b610f07565b6103376103ea366004613387565b610f14565b61026b6103fd366004613210565b610f40565b6102be610410366004613510565b610f6a565b6102be610423366004613387565b610f82565b610337610436366004612f38565b610fb7565b6102a96104493660046130c3565b610ffb565b6102a961045c3660046133c3565b611033565b6102a961046f3660046133fa565b6111e5565b610337610482366004613387565b611299565b6102896112b0565b6102a961049d366004613182565b6112bd565b6103376104b0366004613387565b611352565b6102a96104c3366004613059565b611369565b6102a96104d636600461323b565b611468565b6102a96104e93660046133c3565b61161a565b6102a96104fc3660046132dc565b61171e565b61028961050f366004613387565b611778565b6103376105223660046131af565b611869565b6102a96105353660046133fa565b611875565b61033761054836600461339f565b611a2a565b61026b61055b366004612f70565b611a52565b61057361056e366004613210565b611acf565b604051610278929190613579565b61033761058f366004613210565b611b3a565b6103176105a2366004613282565b611ccc565b60006001600160e01b031982166380ac58cd60e01b14806105d857506001600160e01b03198216635b5e139f60e01b145b806105f357506001600160e01b0319821663cde244d960e01b145b8061060e57506001600160e01b031982166328d12bf960e21b145b8061062957506001600160e01b03198216637294ffed60e01b145b8061064457506001600160e01b0319821663c5fd96cd60e01b145b8061065f57506306f2657960e21b6001600160e01b03198316145b8061066e575061066e82611df3565b90505b919050565b6007805461068390614a74565b80601f01602080910402602001604051908101604052809291908181526020018280546106af90614a74565b80156106fc5780601f106106d1576101008083540402835291602001916106fc565b820191906000526020600020905b8154815290600101906020018083116106df57829003601f168201915b505050505081565b6001600160a01b0384163314806108345760007fdd62ed3e90e97b3d417db9c0c7522647811bafca5afc6694f143588d255fdfb4863360405160240161074b9291906135b1565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b0383818316178352505050509050600080856001600160a01b03168360405161079b919061355d565b600060405180830381855afa9150503d80600081146107d6576040519150601f19603f3d011682016040523d82523d6000602084013e6107db565b606091505b5091509150816108065760405162461bcd60e51b81526004016107fd90614997565b60405180910390fd5b60208101518581101561082b5760405162461bcd60e51b81526004016107fd90613bbe565b60019450505050505b806108515760405162461bcd60e51b81526004016107fd90613e87565b61085d85858585611e0c565b6040516323b872dd60e01b81526001600160a01b038416906323b872dd9061088d908890309087906004016135cb565b602060405180830381600087803b1580156108a757600080fd5b505af11580156108bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108df9190613333565b6108fb5760405162461bcd60e51b81526004016107fd90613c9f565b5050505050565b60008061090e83610f07565b6001600160a01b03908116600090815260036020908152604080832087845290915290205416915050919050565b61094886868585611f3f565b826001600160a01b0316856001600160a01b0316877f0ef52e516fb5aec15a5d3587e5480481b702b26db93c8430eca78b61990fd3f68560405161098c91906136f8565b60405180910390a46040516307a8567d60e51b81526001600160a01b0384169063f50acfa0906109c8903090899089908890889060040161365f565b600060405180830381600087803b1580156109e257600080fd5b505af11580156109f6573d6000803e3d6000fd5b50505050505050505050565b6000610a0d82610f07565b90506001600160a01b038116331480610a4957506001600160a01b038116600090815260056020908152604080832033845290915290205460ff165b610a655760405162461bcd60e51b81526004016107fd906141d0565b6001600160a01b03818116600081815260036020908152604080832087845290915280822080546001600160a01b031916948816948517905551859392917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6000828152600960205260408120610ae39083612062565b90505b92915050565b600081610b0b5760405162461bcd60e51b81526004016107fd90613adb565b6000610b4c84848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061206e92505050565b9050610b5a868233886120a0565b6040516331a9108f60e11b81526000903390636352211e90610b809089906004016136f8565b60206040518083038186803b158015610b9857600080fd5b505afa158015610bac573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bd09190612f54565b6001600160a01b03161415610bf75760405162461bcd60e51b81526004016107fd90613d3f565b610c0081610f07565b50630a85bd0160e11b979650505050505050565b6000838152600a602090815260408083206001600160a01b03861684529091528120610c409083612062565b949350505050565b6000828152600260205260409020548114610c755760405162461bcd60e51b81526004016107fd9061481c565b610c80848484610d46565b50505050565b610c9284848484611f3f565b604051632142170760e11b81526001600160a01b038316906342842e0e90610cc2903090879086906004016135cb565b600060405180830381600087803b158015610cdc57600080fd5b505af1158015610cf0573d6000803e3d6000fd5b50505050816001600160a01b0316836001600160a01b0316857f0ef52e516fb5aec15a5d3587e5480481b702b26db93c8430eca78b61990fd3f684604051610d3891906136f8565b60405180910390a450505050565b610d51838383612274565b505050565b6000828152600a602090815260408083206001600160a01b03851684529091528120610ae390612618565b6000848152600260205260409020548314610dae5760405162461bcd60e51b81526004016107fd906139fd565b610df086868685858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061136992505050565b505050505050565b600061066e8260405180602001604052806000815250612623565b610e1e838383612274565b610e30826001600160a01b031661277b565b15610d5157604051630a85bd0160e11b81526000906001600160a01b0384169063150b7a0290610e689033908890879060040161362c565b602060405180830381600087803b158015610e8257600080fd5b505af1158015610e96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eba919061336b565b90506001600160e01b0319811663785cf2dd60e11b1480610eeb57506001600160e01b03198116630a85bd0160e11b145b610c805760405162461bcd60e51b81526004016107fd90614536565b600061066e600083611b3a565b6000818152600260205260408120548061066e5760405162461bcd60e51b81526004016107fd906148b8565b6001600160a01b03919091166000908152600b602090815260408083209383529290522054151590565b6000828152600c60205260408120610ae39083612062565b6000818152600160205260409020546001600160a01b0316806106715760405162461bcd60e51b81526004016107fd90614123565b60006001600160a01b038216610fdf5760405162461bcd60e51b81526004016107fd90613cea565b506001600160a01b031660009081526004602052604090205490565b60008281526002602052604090205481146110285760405162461bcd60e51b81526004016107fd906143b2565b610c80848484610e13565b6001600160a01b0383166110595760405162461bcd60e51b81526004016107fd90613df3565b600061106485610f07565b90506001600160a01b0381163314806110a057506001600160a01b038116600090815260056020908152604080832033845290915290205460ff165b806110cf57506001600160a01b0381811660009081526003602090815260408083208984529091529020541633145b6110eb5760405162461bcd60e51b81526004016107fd90614355565b6110f6858484612781565b60405163a9059cbb60e01b81526001600160a01b0384169063a9059cbb9061112490879086906004016136a4565b602060405180830381600087803b15801561113e57600080fd5b505af1158015611152573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111769190613333565b6111925760405162461bcd60e51b81526004016107fd9061396e565b826001600160a01b0316846001600160a01b0316867fa8352277873fc0d2b233b8127433da351a4164fa701ed6ff79655694222932c4856040516111d691906136f8565b60405180910390a45050505050565b6111f185858585611f3f565b604051635c46a7ef60e11b81526001600160a01b0384169063b88d4fde906112239030908890879087906004016135ef565b600060405180830381600087803b15801561123d57600080fd5b505af1158015611251573d6000803e3d6000fd5b50505050826001600160a01b0316846001600160a01b0316867f0ef52e516fb5aec15a5d3587e5480481b702b26db93c8430eca78b61990fd3f6856040516111d691906136f8565b600081815260096020526040812061066e90612618565b6008805461068390614a74565b6001600160a01b0382166112e35760405162461bcd60e51b81526004016107fd90614272565b3360008181526005602090815260408083206001600160a01b038716808552925291829020805460ff191685151517905590519091907f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31906113469085906136ed565b60405180910390a35050565b6000818152600c6020526040812061066e90612618565b611374848484612274565b611386836001600160a01b031661277b565b15610c8057604051630a85bd0160e11b81526000906001600160a01b0385169063150b7a02906113c09033908990889088906004016135ef565b602060405180830381600087803b1580156113da57600080fd5b505af11580156113ee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611412919061336b565b90506001600160e01b0319811663785cf2dd60e11b148061144357506001600160e01b03198116630a85bd0160e11b145b61145f5760405162461bcd60e51b81526004016107fd9061385b565b610df083610f07565b611474848484846120a0565b6001600160a01b038416331480611504575060405163e985e9c560e01b81526001600160a01b0383169063e985e9c5906114b490879033906004016135b1565b60206040518083038186803b1580156114cc57600080fd5b505afa1580156114e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115049190613333565b80611593575060405163020604bf60e21b815233906001600160a01b0384169063081812fc906115389085906004016136f8565b60206040518083038186803b15801561155057600080fd5b505afa158015611564573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115889190612f54565b6001600160a01b0316145b6115af5760405162461bcd60e51b81526004016107fd90614865565b6040516323b872dd60e01b81526001600160a01b038316906323b872dd906115df908790309086906004016135cb565b600060405180830381600087803b1580156115f957600080fd5b505af115801561160d573d6000803e3d6000fd5b505050506108fb83610f07565b61162684848484611f3f565b60007f095ea7b334ae44009aa867bfb386f5c3b4b443ac6f0ee573fa91c4608fbadfba308360405160240161165c9291906136a4565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b0383818316178352505050509050826001600160a01b0316816040516116a9919061355d565b6000604051808303816000865af19150503d80600081146116e6576040519150601f19603f3d011682016040523d82523d6000602084013e6116eb565b606091505b50506040516323b872dd60e01b81526001600160a01b03851691506323b872dd90611223903090889087906004016135cb565b600081511161173f5760405162461bcd60e51b81526004016107fd90613c1b565b3233141561175f5760405162461bcd60e51b81526004016107fd906143fb565b600061176a8261206e565b9050610c8084823386611e0c565b6000818152600160205260409020546060906001600160a01b03166117af5760405162461bcd60e51b81526004016107fd906137c7565b600082815260066020526040812080546117c890614a74565b80601f01602080910402602001604051908101604052809291908181526020018280546117f490614a74565b80156118415780601f1061181657610100808354040283529160200191611841565b820191906000526020600020905b81548152906001019060200180831161182457829003601f168201915b50505050509050600081511161066e5760405162461bcd60e51b81526004016107fd9061477e565b6000610ae38383612623565b6001600160a01b03841661189b5760405162461bcd60e51b81526004016107fd906138cd565b60006118a686610f07565b90506001600160a01b0381163314806118e257506001600160a01b038116600090815260056020908152604080832033845290915290205460ff165b8061191157506001600160a01b0381811660009081526003602090815260408083208a84529091529020541633145b61192d5760405162461bcd60e51b81526004016107fd90614069565b611938868585612781565b604051635f22feb160e11b81526001600160a01b0385169063be45fd6290611968908890879087906004016136bd565b602060405180830381600087803b15801561198257600080fd5b505af1158015611996573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ba9190613333565b6119d65760405162461bcd60e51b81526004016107fd90614946565b836001600160a01b0316856001600160a01b0316877fa8352277873fc0d2b233b8127433da351a4164fa701ed6ff79655694222932c486604051611a1a91906136f8565b60405180910390a4505050505050565b6000918252600d602090815260408084206001600160a01b0393909316845291905290205490565b60006001600160a01b038316611a7a5760405162461bcd60e51b81526004016107fd906145a8565b6001600160a01b038216611aa05760405162461bcd60e51b81526004016107fd906147bf565b506001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b6001600160a01b0382166000908152600b6020908152604080832084845290915281205480611b105760405162461bcd60e51b81526004016107fd906144a2565b6000818152600160205260409020546001600160a01b031663cd740db560e01b1794909350915050565b6000806001600160a01b03841615611b5f57611b568484612844565b93509050611b95565b506000828152600160205260409020546001600160a01b031680611b955760405162461bcd60e51b81526004016107fd90614123565b6001600160a01b038116301415611bb057611b568184612844565b60007fed81cdda615fca130279b404b909f51438f5997d5ab9a459aecb921fbd297b6d3085604051602401611be69291906136a4565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b0383818316178352505050509050600080836001600160a01b031683604051611c36919061355d565b600060405180830381855afa9150503d8060008114611c71576040519150601f19603f3d011682016040523d82523d6000602084013e611c76565b606091505b50915091508115611c8957602081015194505b6001821515148015611cab57506001600160e01b0319851663cd740db560e01b145b15611cb95750505050610ae6565b50505063cd740db560e01b179392505050565b600081611ceb5760405162461bcd60e51b81526004016107fd906142cf565b6000611d2c84848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061206e92505050565b9050611d3a868233886120a0565b6040516331a9108f60e11b81526000903390636352211e90611d609089906004016136f8565b60206040518083038186803b158015611d7857600080fd5b505afa158015611d8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611db09190612f54565b6001600160a01b03161415611dd75760405162461bcd60e51b81526004016107fd906144eb565b611de081610f07565b5063785cf2dd60e11b9695505050505050565b6001600160e01b031981166301ffc9a760e01b14919050565b6000838152600160205260409020546001600160a01b0316611e405760405162461bcd60e51b81526004016107fd906140c6565b80611e4a57610c80565b6000838152600d602090815260408083206001600160a01b038616845290915290205480611ea6576000848152600c60205260409020611e8a90846128a7565b611ea65760405162461bcd60e51b81526004016107fd90613d8a565b6000848152600d602090815260408083206001600160a01b038716845290915281208054849290611ed89084906149e3565b90915550611efb9050846001600160a01b038516611ef685856149e3565b6128bc565b826001600160a01b031684866001600160a01b03167f684ce28ace37552c6bfb98b7cceda8ed55327078eafb5dfb31218e0856382763856040516111d691906136f8565b6001600160a01b0382166000908152600b6020908152604080832084845290915290205480611f805760405162461bcd60e51b81526004016107fd90613fb0565b848114611f9f5760405162461bcd60e51b81526004016107fd90613a46565b6001600160a01b038416611fc55760405162461bcd60e51b81526004016107fd90613eda565b6000611fd082610f07565b90506001600160a01b03811633148061200c57506001600160a01b038116600090815260056020908152604080832033845290915290205460ff165b8061203b57506001600160a01b0381811660009081526003602090815260408083208684529091529020541633145b6120575760405162461bcd60e51b81526004016107fd90613f65565b610df0828585612991565b6000610ae38383612ac0565b60006020820151905060208251101561067157815161208e9060086149fb565b61209a90610100614a1a565b1c919050565b6000838152600160205260409020546001600160a01b03166120d45760405162461bcd60e51b81526004016107fd9061400c565b6001600160a01b0382166000908152600b602090815260408083208484529091529020548314156121175760405162461bcd60e51b81526004016107fd90613b61565b6000838152600a602090815260408083206001600160a01b0386168452909152812061214290612618565b90508061217d57600084815260096020526040902061216190846128a7565b61217d5760405162461bcd60e51b81526004016107fd9061421f565b6000848152600a602090815260408083206001600160a01b038716845290915290206121a99083612b19565b6121c55760405162461bcd60e51b81526004016107fd90614665565b6001600160a01b0383166000818152600b60209081526040808320868452909152902085905530141561221c576000828152600260205260409020546122179085906001600160a01b038616906128bc565b612230565b61223084846001600160a01b0316846128bc565b826001600160a01b031684866001600160a01b03167f0371ddf2288ad1ba92626a7e31c86a9d006e592cfe57d7d946ef08b13457c08b856040516111d691906136f8565b6001600160a01b03831661229a5760405162461bcd60e51b81526004016107fd90613786565b6000818152600160205260409020546001600160a01b038481169116146122d35760405162461bcd60e51b81526004016107fd90614908565b6001600160a01b0382166122f95760405162461bcd60e51b81526004016107fd906139be565b336001600160a01b0384161461248e5760007fed81cdda615fca130279b404b909f51438f5997d5ab9a459aecb921fbd297b6d308360405160240161233f9291906136a4565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b0383818316178352505050509050600080856001600160a01b03168360405161238f919061355d565b600060405180830381855afa9150503d80600081146123ca576040519150601f19603f3d011682016040523d82523d6000602084013e6123cf565b606091505b509092509050600182151514156124185760208101516001600160e01b0319811663cd740db560e01b14156124165760405162461bcd60e51b81526004016107fd90614605565b505b6001600160a01b038616600090815260056020908152604080832033845290915290205460ff168061246e57506001600160a01b0386811660009081526003602090815260408083208884529091529020541633145b61248a5760405162461bcd60e51b81526004016107fd90613f1a565b5050505b6001600160a01b0383811660009081526003602090815260408083208584529091529020541615612515576001600160a01b038316600081815260036020908152604080832085845290915280822080546001600160a01b0319169055518392907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925908390a45b816001600160a01b0316836001600160a01b0316146125d2576001600160a01b03831660009081526004602052604090205461256157634e487b7160e01b600052600160045260246000fd5b6001600160a01b038316600090815260046020526040812080549161258583614a5d565b9091555050600081815260016020908152604080832080546001600160a01b0319166001600160a01b0387169081179091558352600490915281208054916125cc83614aaf565b91905055505b80826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b600061066e82612b25565b60006001600160a01b03831661264b5760405162461bcd60e51b81526004016107fd90613e44565b60008054908061265a83614aaf565b90915550506000805480825260016020908152604080842080546001600160a01b0319166001600160a01b038916908117909155845260049091528220805491926126a483614aaf565b90915550506000546040516126bd913091602001613579565b60408051601f198184030181529181528151602092830120600080548152600290935291205582511561270b576000818152600660209081526040909120845161270992860190612dd0565b505b60405181906001600160a01b038616906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a461275f6000858360405180602001604052806000815250612b29565b610ae35760405162461bcd60e51b81526004016107fd90614173565b3b151590565b8061278b57610d51565b6000838152600d602090815260408083206001600160a01b0386168452909152902054818110156127ce5760405162461bcd60e51b81526004016107fd9061391f565b6000848152600d602090815260408083206001600160a01b038716845290915290208282039081905580612830576000858152600c602052604090206128149085612c3a565b6128305760405162461bcd60e51b81526004016107fd90614714565b6108fb85856001600160a01b0316836128bc565b6001600160a01b0382166000908152600b60209081526040808320848452909152812054806128855760405162461bcd60e51b81526004016107fd90614458565b6000818152600160205260409020546001600160a01b031691505b9250929050565b6000610ae3836001600160a01b038416612c4f565b60008381526002602090815260408083205490516128de928691869101613587565b60408051601f19818403018152918152815160209283012060008781526002909352912081905590505b6000848152600160205260409020546001600160a01b0316301415610c8057306000818152600b6020908152604080832097835296815286822054808352600282529187902054965191966129639390929091859101613587565b60408051601f1981840301815291815281516020928301206000878152600290935291208190559050612908565b6000838152600a602090815260408083206001600160a01b038616845290915281206001906129bf90612618565b6129c99190614a1a565b6000858152600a602090815260408083206001600160a01b038816845290915290209091506129f89083612c99565b612a145760405162461bcd60e51b81526004016107fd906146b7565b6001600160a01b0383166000908152600b6020908152604080832085845290915281205580612a71576000848152600960205260409020612a559084612c3a565b612a715760405162461bcd60e51b81526004016107fd90613729565b6001600160a01b038316301415612aac57600082815260026020526040902054612aa79085906001600160a01b038616906128bc565b610c80565b610c8084846001600160a01b0316846128bc565b81546000908210612ae35760405162461bcd60e51b81526004016107fd90613819565b826000018281548110612b0657634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905092915050565b6000610ae38383612c4f565b5490565b6000612b3d846001600160a01b031661277b565b15612c3257604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290612b749033908990889088906004016135ef565b602060405180830381600087803b158015612b8e57600080fd5b505af1925050508015612bbe575060408051601f3d908101601f19168201909252612bbb9181019061336b565b60015b612c18573d808015612bec576040519150601f19603f3d011682016040523d82523d6000602084013e612bf1565b606091505b508051612c105760405162461bcd60e51b81526004016107fd90613a89565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050610c40565b506001610c40565b6000610ae3836001600160a01b038416612ca1565b6000612c5b8383612db8565b612c9157508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610ae6565b506000610ae6565b6000610ae383835b60008181526001830160205260408120548015612dae576000612cc5600183614a1a565b8554909150600090612cd990600190614a1a565b90506000866000018281548110612d0057634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905080876000018481548110612d3157634e487b7160e01b600052603260045260246000fd5b600091825260208083209091019290925582815260018901909152604090208490558654879080612d7257634e487b7160e01b600052603160045260246000fd5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050610ae6565b6000915050610ae6565b60009081526001919091016020526040902054151590565b828054612ddc90614a74565b90600052602060002090601f016020900481019282612dfe5760008555612e44565b82601f10612e1757805160ff1916838001178555612e44565b82800160010185558215612e44579182015b82811115612e44578251825591602001919060010190612e29565b50612e50929150612e54565b5090565b5b80821115612e505760008155600101612e55565b600067ffffffffffffffff80841115612e8457612e84614ae0565b604051601f8501601f191681016020018281118282101715612ea857612ea8614ae0565b604052848152915081838501861015612ec057600080fd5b8484602083013760006020868301015250509392505050565b60008083601f840112612eea578182fd5b50813567ffffffffffffffff811115612f01578182fd5b6020830191508360208285010111156128a057600080fd5b600082601f830112612f29578081fd5b610ae383833560208501612e69565b600060208284031215612f49578081fd5b8135610ae381614af6565b600060208284031215612f65578081fd5b8151610ae381614af6565b60008060408385031215612f82578081fd5b8235612f8d81614af6565b91506020830135612f9d81614af6565b809150509250929050565b600080600060608486031215612fbc578081fd5b8335612fc781614af6565b92506020840135612fd781614af6565b929592945050506040919091013590565b600080600080600060808688031215612fff578081fd5b853561300a81614af6565b9450602086013561301a81614af6565b935060408601359250606086013567ffffffffffffffff81111561303c578182fd5b61304888828901612ed9565b969995985093965092949392505050565b6000806000806080858703121561306e578384fd5b843561307981614af6565b9350602085013561308981614af6565b925060408501359150606085013567ffffffffffffffff8111156130ab578182fd5b6130b787828801612f19565b91505092959194509250565b600080600080608085870312156130d8578384fd5b84356130e381614af6565b935060208501356130f381614af6565b93969395505050506040820135916060013590565b60008060008060008060a08789031215613120578081fd5b863561312b81614af6565b9550602087013561313b81614af6565b94506040870135935060608701359250608087013567ffffffffffffffff811115613164578182fd5b61317089828a01612ed9565b979a9699509497509295939492505050565b60008060408385031215613194578182fd5b823561319f81614af6565b91506020830135612f9d81614b0e565b600080604083850312156131c1578182fd5b82356131cc81614af6565b9150602083013567ffffffffffffffff8111156131e7578182fd5b8301601f810185136131f7578182fd5b61320685823560208401612e69565b9150509250929050565b60008060408385031215613222578182fd5b823561322d81614af6565b946020939093013593505050565b60008060008060808587031215613250578182fd5b843561325b81614af6565b935060208501359250604085013561327281614af6565b9396929550929360600135925050565b60008060008060608587031215613297578182fd5b84356132a281614af6565b935060208501359250604085013567ffffffffffffffff8111156132c4578283fd5b6132d087828801612ed9565b95989497509550505050565b6000806000606084860312156132f0578081fd5b83356132fb81614af6565b925060208401359150604084013567ffffffffffffffff81111561331d578182fd5b61332986828701612f19565b9150509250925092565b600060208284031215613344578081fd5b8151610ae381614b0e565b600060208284031215613360578081fd5b8135610ae381614b1c565b60006020828403121561337c578081fd5b8151610ae381614b1c565b600060208284031215613398578081fd5b5035919050565b600080604083850312156133b1578182fd5b823591506020830135612f9d81614af6565b600080600080608085870312156133d8578182fd5b8435935060208501356133ea81614af6565b9250604085013561327281614af6565b600080600080600060a08688031215613411578283fd5b85359450602086013561342381614af6565b9350604086013561343381614af6565b925060608601359150608086013567ffffffffffffffff811115613455578182fd5b61346188828901612f19565b9150509295509295909350565b600080600060608486031215613482578081fd5b833592506020840135612fd781614af6565b60008060008060008060c087890312156134ac578384fd5b8635955060208701356134be81614af6565b94506040870135935060608701356134d581614af6565b92506080870135915060a087013567ffffffffffffffff8111156134f7578182fd5b61350389828a01612f19565b9150509295509295509295565b60008060408385031215613522578182fd5b50508035926020909101359150565b60008151808452613549816020860160208601614a31565b601f01601f19169290920160200192915050565b6000825161356f818460208701614a31565b9190910192915050565b918252602082015260400190565b9283526020830191909152604082015260600190565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061362290830184613531565b9695505050505050565b6001600160a01b039384168152919092166020820152604081019190915260806060820181905260009082015260a00190565b6001600160a01b03868116825285166020820152604081018490526060810183905260a06080820181905260009061369990830184613531565b979650505050505050565b6001600160a01b03929092168252602082015260400190565b600060018060a01b0385168252836020830152606060408301526136e46060830184613531565b95945050505050565b901515815260200190565b90815260200190565b6001600160e01b031991909116815260200190565b600060208252610ae36020830184613531565b60208082526038908201527f436f6d706f7361626c65546f70446f776e3a2072656d6f76654368696c643a2060408201527f5f6368696c64436f6e7472616374206e6f7420666f756e640000000000000000606082015260800190565b6020808252603390820152600080516020614b53833981519152604082015272205f66726f6d207a65726f206164647265737360681b606082015260800190565b60208082526032908201527f436f6d706f7361626c65546f70446f776e3a2055524920717565727920666f72604082015271103737b732bc34b9ba32b73a103a37b5b2b760711b606082015260800190565b60208082526022908201527f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e604082015261647360f01b606082015260800190565b6020808252604c908201527f436f6d706f7361626c65546f70446f776e3a20736166655472616e736665724660408201527f726f6d283429206f6e455243373231526563656976656420696e76616c69642060608201526b72657475726e2076616c756560a01b608082015260a00190565b60208082526032908201527f436f6d706f7361626c65546f70446f776e3a207472616e73666572455243323260408201527133205f746f207a65726f206164647265737360701b606082015260800190565b6020808252602f908201527f436f6d706f7361626c65546f70446f776e3a2072656d6f76654552433230207660408201526e0c2d8eaca40dcdee840cadcdeeaced608b1b606082015260800190565b60208082526030908201527f436f6d706f7361626c65546f70446f776e3a207472616e73666572455243323060408201526f081d1c985b9cd9995c8819985a5b195960821b606082015260800190565b6020808252603190820152600080516020614b53833981519152604082015270205f746f207a65726f206164647265737360781b606082015260800190565b60208082526029908201527f436f6d706f7361626c65546f70446f776e3a20737461746548617368206d69736040820152686d617463682028332960b81b606082015260800190565b6020808252603590820152600080516020614b7383398151915260408201527419081ddc9bdb99c81d1bdad95b925908199bdd5b99605a1b606082015260800190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6020808252606c90820152600080516020614b3383398151915260408201527f766564283429205f64617461206d75737420636f6e7461696e2074686520756960608201527f6e7432353620746f6b656e496420746f207472616e736665722074686520636860808201526b696c6420746f6b656e20746f60a01b60a082015260c00190565b6020808252603e908201527f436f6d706f7361626c65546f70446f776e3a20726563656976654368696c642060408201527f5f6368696c64546f6b656e496420616c72656164792072656365697665640000606082015260800190565b60208082526038908201527f436f6d706f7361626c65546f70446f776e3a2067657445524332302076616c7560408201527f652067726561746572207468616e2072656d61696e696e670000000000000000606082015260800190565b602080825260609082018190527f436f6d706f7361626c65546f70446f776e3a20746f6b656e46616c6c6261636b60408301527f205f64617461206d75737420636f6e7461696e207468652075696e7432353620908201527f746f6b656e496420746f207472616e736665722074686520746f6b656e20746f608082015260a00190565b6020808252602b908201527f436f6d706f7361626c65546f70446f776e3a206765744552433230207472616e60408201526a1cd9995c8819985a5b195960aa1b606082015260800190565b60208082526035908201527f436f6d706f7361626c65546f70446f776e3a2062616c616e63654f66205f746f6040820152746b656e4f776e6572207a65726f206164647265737360581b606082015260800190565b6020808252603c90820152600080516020614b3383398151915260408201527f766564283429206368696c6420746f6b656e206e6f74206f776e656400000000606082015260800190565b60208082526043908201527f436f6d706f7361626c65546f70446f776e3a206572633230526563656976656460408201527f3a206572633230436f6e74726163747320616464205f6572633230436f6e74726060820152621858dd60ea1b608082015260a00190565b60208082526031908201527f436f6d706f7361626c65546f70446f776e3a207472616e736665724552433230604082015270205f746f207a65726f206164647265737360781b606082015260800190565b60208082526023908201527f436f6d706f7361626c65546f70446f776e3a205f746f207a65726f206164647260408201526265737360e81b606082015260800190565b60208082526033908201527f436f6d706f7361626c65546f70446f776e3a206765744552433230206e6f74206040820152720616c6c6f77656420746f20676574455243323606c1b606082015260800190565b6020808252603290820152600080516020614b7383398151915260408201527164205f746f207a65726f206164647265737360701b606082015260800190565b6020808252603890820152600080516020614b5383398151915260408201527f206d73672e73656e646572206e6f7420617070726f7665640000000000000000606082015260800190565b6020808252603990820152600080516020614b7383398151915260408201527f64206d73672e73656e646572206e6f7420656c696769626c6500000000000000606082015260800190565b6020808252604890820152600080516020614b7383398151915260408201527f64205f6368696c64436f6e7472616374205f6368696c64546f6b656e4964206e6060820152671bdd08199bdd5b9960c21b608082015260a00190565b60208082526038908201527f436f6d706f7361626c65546f70446f776e3a20726563656976654368696c642060408201527f5f746f6b656e496420646f6573206e6f742065786973742e0000000000000000606082015260800190565b60208082526039908201527f436f6d706f7361626c65546f70446f776e3a207472616e73666572455243323260408201527f33206d73672e73656e646572206e6f7420656c696769626c6500000000000000606082015260800190565b60208082526038908201527f436f6d706f7361626c65546f70446f776e3a206572633230526563656976656460408201527f205f746f6b656e496420646f6573206e6f742065786973740000000000000000606082015260800190565b60208082526030908201527f436f6d706f7361626c65546f70446f776e3a206f776e65724f66205f746f6b6560408201526f6e4964207a65726f206164647265737360801b606082015260800190565b6020808252603d908201527f436f6d706f7361626c65546f70446f776e3a207472616e7366657220746f206e60408201527f6f6e20455243373231526563656976657220696d706c656d656e746572000000606082015260800190565b6020808252602f908201527f436f6d706f7361626c65546f70446f776e3a20617070726f7665206d73672e7360408201526e32b73232b9103737ba1037bbb732b960891b606082015260800190565b60208082526033908201527f436f6d706f7361626c65546f70446f776e3a20726563656976654368696c643a604082015272081859190817d8da1a5b1910dbdb9d1c9858dd606a1b606082015260800190565b6020808252603b908201527f436f6d706f7361626c65546f70446f776e3a20736574417070726f76616c466f60408201527f72416c6c205f6f70657261746f72207a65726f20616464726573730000000000606082015260800190565b6020808252606c90820152600080516020614b3383398151915260408201527f766564283329205f64617461206d75737420636f6e7461696e2074686520756960608201527f6e7432353620746f6b656e496420746f207472616e736665722074686520636860808201526b696c6420746f6b656e20746f60a01b60a082015260c00190565b60208082526038908201527f436f6d706f7361626c65546f70446f776e3a207472616e73666572455243323060408201527f206d73672e73656e646572206e6f7420656c696769626c650000000000000000606082015260800190565b60208082526029908201527f436f6d706f7361626c65546f70446f776e3a20737461746548617368206d69736040820152686d617463682028312960b81b606082015260800190565b6020808252603d908201527f436f6d706f7361626c65546f70446f776e3a20746f6b656e46616c6c6261636b60408201527f206d73672e73656e646572206973206e6f74206120636f6e7472616374000000606082015260800190565b6020808252602a908201527f436f6d706f7361626c65546f70446f776e3a205f6f776e65724f664368696c64604082015269081b9bdd08199bdd5b9960b21b606082015260800190565b60208082526029908201527f436f6d706f7361626c65546f70446f776e3a206f776e65724f664368696c64206040820152681b9bdd08199bdd5b9960ba1b606082015260800190565b6020808252603c90820152600080516020614b3383398151915260408201527f766564283329206368696c6420746f6b656e206e6f74206f776e656400000000606082015260800190565b6020808252604c908201527f436f6d706f7361626c65546f70446f776e3a20736166655472616e736665724660408201527f726f6d283329206f6e455243373231526563656976656420696e76616c69642060608201526b72657475726e2076616c756560a01b608082015260a00190565b60208082526037908201527f436f6d706f7361626c65546f70446f776e3a206973417070726f766564466f7260408201527f416c6c205f6f776e6572207a65726f2061646472657373000000000000000000606082015260800190565b6020808252604c90820152600080516020614b5383398151915260408201527f20746f6b656e206973206368696c64206f66206f7468657220746f7020646f7760608201526b6e20636f6d706f7361626c6560a01b608082015260a00190565b60208082526032908201527f436f6d706f7361626c65546f70446f776e3a20726563656976654368696c643a604082015271081859190817d8da1a5b19151bdad95b925960721b606082015260800190565b60208082526037908201527f436f6d706f7361626c65546f70446f776e3a2072656d6f76654368696c643a2060408201527f5f6368696c64546f6b656e4964206e6f7420666f756e64000000000000000000606082015260800190565b60208082526044908201527f436f6d706f7361626c65546f70446f776e3a2072656d6f766545524332303a2060408201527f6572633230436f6e7472616374732072656d6f7665205f6572633230436f6e746060820152631c9858dd60e21b608082015260a00190565b60208082526021908201527f436f6d706f7361626c65546f70446f776e3a20555249206973206e6f742073656040820152601d60fa1b606082015260800190565b6020808252603a908201527f436f6d706f7361626c65546f70446f776e3a206973417070726f766564466f7260408201527f416c6c205f6f70657261746f72207a65726f2061646472657373000000000000606082015260800190565b60208082526029908201527f436f6d706f7361626c65546f70446f776e3a20737461746548617368206d69736040820152686d617463682028322960b81b606082015260800190565b60208082526033908201527f436f6d706f7361626c65546f70446f776e3a206765744368696c64206d73672e6040820152721cd95b99195c881b9bdd08185c1c1c9bdd9959606a1b606082015260800190565b60208082526030908201527f436f6d706f7361626c65546f70446f776e3a20737461746548617368206f662060408201526f5f746f6b656e4964206973207a65726f60801b606082015260800190565b6020808252603090820152600080516020614b5383398151915260408201526f102fb33937b6903737ba1037bbb732b960811b606082015260800190565b60208082526031908201527f436f6d706f7361626c65546f70446f776e3a207472616e7366657245524332326040820152700cc81d1c985b9cd9995c8819985a5b1959607a1b606082015260800190565b6020808252602c908201527f436f6d706f7361626c65546f70446f776e3a20676574455243323020616c6c6f60408201526b1dd85b98d94819985a5b195960a21b606082015260800190565b600082198211156149f6576149f6614aca565b500190565b6000816000190483118215151615614a1557614a15614aca565b500290565b600082821015614a2c57614a2c614aca565b500390565b60005b83811015614a4c578181015183820152602001614a34565b83811115610c805750506000910152565b600081614a6c57614a6c614aca565b506000190190565b600281046001821680614a8857607f821691505b60208210811415614aa957634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415614ac357614ac3614aca565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114614b0b57600080fd5b50565b8015158114614b0b57600080fd5b6001600160e01b031981168114614b0b57600080fdfe436f6d706f7361626c65546f70446f776e3a206f6e4552433732315265636569436f6d706f7361626c65546f70446f776e3a205f7472616e7366657246726f6d436f6d706f7361626c65546f70446f776e3a205f7472616e736665724368696ca264697066735822122015ff459bc4f58905da537b06bee1b19459690784b7679a4f977b1eebacd46b3d64736f6c6343000800003300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000e436f6d706f7361626c65204e46540000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004434e465400000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106102535760003560e01c80636352211e11610146578063ba6b5f96116100c3578063d49d1bac11610087578063d49d1bac14610527578063e226ed221461053a578063e985e9c51461054d578063eadb80b814610560578063ed81cdda14610581578063f0b9e5ba1461059457610253565b8063ba6b5f96146104c8578063bef44f18146104db578063c0ee0b8a146104ee578063c87b56dd14610501578063d204c45e1461051457610253565b80638da7d0b51161010a5780638da7d0b51461047457806395d89b4114610487578063a22cb4651461048f578063a7811732146104a2578063b88d4fde146104b557610253565b80636352211e1461041557806370a082311461042857806379eda5411461043b578063830ef41b1461044e5780638d81f51e1461046157610253565b80631d98f3c5116101d457806342842e0e1161019857806342842e0e146103b657806343a61a8e146103c95780634ff33816146103dc5780635680a3ad146103ef578063627c81ff1461040257610253565b80631d98f3c51461035757806323b872dd1461036a57806335b21ceb1461037d5780633cc8cf1e1461039057806340d097c3146103a357610253565b8063095ea7b31161021b578063095ea7b3146102de5780630d5a621b146102f1578063150b7a0214610304578063160b01a1146103245780631c5481e21461034457610253565b806301ffc9a71461025857806306fdde031461028157806307cff6f214610296578063081812fc146102ab57806308937f62146102cb575b600080fd5b61026b61026636600461334f565b6105a7565b60405161027891906136ed565b60405180910390f35b610289610676565b6040516102789190613716565b6102a96102a436600461323b565b610704565b005b6102be6102b9366004613387565b610902565b604051610278919061359d565b6102a96102d9366004613494565b61093c565b6102a96102ec366004613210565b610a02565b6102be6102ff366004613510565b610acb565b610317610312366004612fe8565b610aec565b6040516102789190613701565b61033761033236600461346e565b610c14565b60405161027891906136f8565b6102a96103523660046130c3565b610c48565b6102a96103653660046133c3565b610c86565b6102a9610378366004612fa8565b610d46565b61033761038b36600461339f565b610d56565b6102a961039e366004613108565b610d81565b6103376103b1366004612f38565b610df8565b6102a96103c4366004612fa8565b610e13565b6103376103d7366004613387565b610f07565b6103376103ea366004613387565b610f14565b61026b6103fd366004613210565b610f40565b6102be610410366004613510565b610f6a565b6102be610423366004613387565b610f82565b610337610436366004612f38565b610fb7565b6102a96104493660046130c3565b610ffb565b6102a961045c3660046133c3565b611033565b6102a961046f3660046133fa565b6111e5565b610337610482366004613387565b611299565b6102896112b0565b6102a961049d366004613182565b6112bd565b6103376104b0366004613387565b611352565b6102a96104c3366004613059565b611369565b6102a96104d636600461323b565b611468565b6102a96104e93660046133c3565b61161a565b6102a96104fc3660046132dc565b61171e565b61028961050f366004613387565b611778565b6103376105223660046131af565b611869565b6102a96105353660046133fa565b611875565b61033761054836600461339f565b611a2a565b61026b61055b366004612f70565b611a52565b61057361056e366004613210565b611acf565b604051610278929190613579565b61033761058f366004613210565b611b3a565b6103176105a2366004613282565b611ccc565b60006001600160e01b031982166380ac58cd60e01b14806105d857506001600160e01b03198216635b5e139f60e01b145b806105f357506001600160e01b0319821663cde244d960e01b145b8061060e57506001600160e01b031982166328d12bf960e21b145b8061062957506001600160e01b03198216637294ffed60e01b145b8061064457506001600160e01b0319821663c5fd96cd60e01b145b8061065f57506306f2657960e21b6001600160e01b03198316145b8061066e575061066e82611df3565b90505b919050565b6007805461068390614a74565b80601f01602080910402602001604051908101604052809291908181526020018280546106af90614a74565b80156106fc5780601f106106d1576101008083540402835291602001916106fc565b820191906000526020600020905b8154815290600101906020018083116106df57829003601f168201915b505050505081565b6001600160a01b0384163314806108345760007fdd62ed3e90e97b3d417db9c0c7522647811bafca5afc6694f143588d255fdfb4863360405160240161074b9291906135b1565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b0383818316178352505050509050600080856001600160a01b03168360405161079b919061355d565b600060405180830381855afa9150503d80600081146107d6576040519150601f19603f3d011682016040523d82523d6000602084013e6107db565b606091505b5091509150816108065760405162461bcd60e51b81526004016107fd90614997565b60405180910390fd5b60208101518581101561082b5760405162461bcd60e51b81526004016107fd90613bbe565b60019450505050505b806108515760405162461bcd60e51b81526004016107fd90613e87565b61085d85858585611e0c565b6040516323b872dd60e01b81526001600160a01b038416906323b872dd9061088d908890309087906004016135cb565b602060405180830381600087803b1580156108a757600080fd5b505af11580156108bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108df9190613333565b6108fb5760405162461bcd60e51b81526004016107fd90613c9f565b5050505050565b60008061090e83610f07565b6001600160a01b03908116600090815260036020908152604080832087845290915290205416915050919050565b61094886868585611f3f565b826001600160a01b0316856001600160a01b0316877f0ef52e516fb5aec15a5d3587e5480481b702b26db93c8430eca78b61990fd3f68560405161098c91906136f8565b60405180910390a46040516307a8567d60e51b81526001600160a01b0384169063f50acfa0906109c8903090899089908890889060040161365f565b600060405180830381600087803b1580156109e257600080fd5b505af11580156109f6573d6000803e3d6000fd5b50505050505050505050565b6000610a0d82610f07565b90506001600160a01b038116331480610a4957506001600160a01b038116600090815260056020908152604080832033845290915290205460ff165b610a655760405162461bcd60e51b81526004016107fd906141d0565b6001600160a01b03818116600081815260036020908152604080832087845290915280822080546001600160a01b031916948816948517905551859392917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6000828152600960205260408120610ae39083612062565b90505b92915050565b600081610b0b5760405162461bcd60e51b81526004016107fd90613adb565b6000610b4c84848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061206e92505050565b9050610b5a868233886120a0565b6040516331a9108f60e11b81526000903390636352211e90610b809089906004016136f8565b60206040518083038186803b158015610b9857600080fd5b505afa158015610bac573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bd09190612f54565b6001600160a01b03161415610bf75760405162461bcd60e51b81526004016107fd90613d3f565b610c0081610f07565b50630a85bd0160e11b979650505050505050565b6000838152600a602090815260408083206001600160a01b03861684529091528120610c409083612062565b949350505050565b6000828152600260205260409020548114610c755760405162461bcd60e51b81526004016107fd9061481c565b610c80848484610d46565b50505050565b610c9284848484611f3f565b604051632142170760e11b81526001600160a01b038316906342842e0e90610cc2903090879086906004016135cb565b600060405180830381600087803b158015610cdc57600080fd5b505af1158015610cf0573d6000803e3d6000fd5b50505050816001600160a01b0316836001600160a01b0316857f0ef52e516fb5aec15a5d3587e5480481b702b26db93c8430eca78b61990fd3f684604051610d3891906136f8565b60405180910390a450505050565b610d51838383612274565b505050565b6000828152600a602090815260408083206001600160a01b03851684529091528120610ae390612618565b6000848152600260205260409020548314610dae5760405162461bcd60e51b81526004016107fd906139fd565b610df086868685858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061136992505050565b505050505050565b600061066e8260405180602001604052806000815250612623565b610e1e838383612274565b610e30826001600160a01b031661277b565b15610d5157604051630a85bd0160e11b81526000906001600160a01b0384169063150b7a0290610e689033908890879060040161362c565b602060405180830381600087803b158015610e8257600080fd5b505af1158015610e96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eba919061336b565b90506001600160e01b0319811663785cf2dd60e11b1480610eeb57506001600160e01b03198116630a85bd0160e11b145b610c805760405162461bcd60e51b81526004016107fd90614536565b600061066e600083611b3a565b6000818152600260205260408120548061066e5760405162461bcd60e51b81526004016107fd906148b8565b6001600160a01b03919091166000908152600b602090815260408083209383529290522054151590565b6000828152600c60205260408120610ae39083612062565b6000818152600160205260409020546001600160a01b0316806106715760405162461bcd60e51b81526004016107fd90614123565b60006001600160a01b038216610fdf5760405162461bcd60e51b81526004016107fd90613cea565b506001600160a01b031660009081526004602052604090205490565b60008281526002602052604090205481146110285760405162461bcd60e51b81526004016107fd906143b2565b610c80848484610e13565b6001600160a01b0383166110595760405162461bcd60e51b81526004016107fd90613df3565b600061106485610f07565b90506001600160a01b0381163314806110a057506001600160a01b038116600090815260056020908152604080832033845290915290205460ff165b806110cf57506001600160a01b0381811660009081526003602090815260408083208984529091529020541633145b6110eb5760405162461bcd60e51b81526004016107fd90614355565b6110f6858484612781565b60405163a9059cbb60e01b81526001600160a01b0384169063a9059cbb9061112490879086906004016136a4565b602060405180830381600087803b15801561113e57600080fd5b505af1158015611152573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111769190613333565b6111925760405162461bcd60e51b81526004016107fd9061396e565b826001600160a01b0316846001600160a01b0316867fa8352277873fc0d2b233b8127433da351a4164fa701ed6ff79655694222932c4856040516111d691906136f8565b60405180910390a45050505050565b6111f185858585611f3f565b604051635c46a7ef60e11b81526001600160a01b0384169063b88d4fde906112239030908890879087906004016135ef565b600060405180830381600087803b15801561123d57600080fd5b505af1158015611251573d6000803e3d6000fd5b50505050826001600160a01b0316846001600160a01b0316867f0ef52e516fb5aec15a5d3587e5480481b702b26db93c8430eca78b61990fd3f6856040516111d691906136f8565b600081815260096020526040812061066e90612618565b6008805461068390614a74565b6001600160a01b0382166112e35760405162461bcd60e51b81526004016107fd90614272565b3360008181526005602090815260408083206001600160a01b038716808552925291829020805460ff191685151517905590519091907f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31906113469085906136ed565b60405180910390a35050565b6000818152600c6020526040812061066e90612618565b611374848484612274565b611386836001600160a01b031661277b565b15610c8057604051630a85bd0160e11b81526000906001600160a01b0385169063150b7a02906113c09033908990889088906004016135ef565b602060405180830381600087803b1580156113da57600080fd5b505af11580156113ee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611412919061336b565b90506001600160e01b0319811663785cf2dd60e11b148061144357506001600160e01b03198116630a85bd0160e11b145b61145f5760405162461bcd60e51b81526004016107fd9061385b565b610df083610f07565b611474848484846120a0565b6001600160a01b038416331480611504575060405163e985e9c560e01b81526001600160a01b0383169063e985e9c5906114b490879033906004016135b1565b60206040518083038186803b1580156114cc57600080fd5b505afa1580156114e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115049190613333565b80611593575060405163020604bf60e21b815233906001600160a01b0384169063081812fc906115389085906004016136f8565b60206040518083038186803b15801561155057600080fd5b505afa158015611564573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115889190612f54565b6001600160a01b0316145b6115af5760405162461bcd60e51b81526004016107fd90614865565b6040516323b872dd60e01b81526001600160a01b038316906323b872dd906115df908790309086906004016135cb565b600060405180830381600087803b1580156115f957600080fd5b505af115801561160d573d6000803e3d6000fd5b505050506108fb83610f07565b61162684848484611f3f565b60007f095ea7b334ae44009aa867bfb386f5c3b4b443ac6f0ee573fa91c4608fbadfba308360405160240161165c9291906136a4565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b0383818316178352505050509050826001600160a01b0316816040516116a9919061355d565b6000604051808303816000865af19150503d80600081146116e6576040519150601f19603f3d011682016040523d82523d6000602084013e6116eb565b606091505b50506040516323b872dd60e01b81526001600160a01b03851691506323b872dd90611223903090889087906004016135cb565b600081511161173f5760405162461bcd60e51b81526004016107fd90613c1b565b3233141561175f5760405162461bcd60e51b81526004016107fd906143fb565b600061176a8261206e565b9050610c8084823386611e0c565b6000818152600160205260409020546060906001600160a01b03166117af5760405162461bcd60e51b81526004016107fd906137c7565b600082815260066020526040812080546117c890614a74565b80601f01602080910402602001604051908101604052809291908181526020018280546117f490614a74565b80156118415780601f1061181657610100808354040283529160200191611841565b820191906000526020600020905b81548152906001019060200180831161182457829003601f168201915b50505050509050600081511161066e5760405162461bcd60e51b81526004016107fd9061477e565b6000610ae38383612623565b6001600160a01b03841661189b5760405162461bcd60e51b81526004016107fd906138cd565b60006118a686610f07565b90506001600160a01b0381163314806118e257506001600160a01b038116600090815260056020908152604080832033845290915290205460ff165b8061191157506001600160a01b0381811660009081526003602090815260408083208a84529091529020541633145b61192d5760405162461bcd60e51b81526004016107fd90614069565b611938868585612781565b604051635f22feb160e11b81526001600160a01b0385169063be45fd6290611968908890879087906004016136bd565b602060405180830381600087803b15801561198257600080fd5b505af1158015611996573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ba9190613333565b6119d65760405162461bcd60e51b81526004016107fd90614946565b836001600160a01b0316856001600160a01b0316877fa8352277873fc0d2b233b8127433da351a4164fa701ed6ff79655694222932c486604051611a1a91906136f8565b60405180910390a4505050505050565b6000918252600d602090815260408084206001600160a01b0393909316845291905290205490565b60006001600160a01b038316611a7a5760405162461bcd60e51b81526004016107fd906145a8565b6001600160a01b038216611aa05760405162461bcd60e51b81526004016107fd906147bf565b506001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b6001600160a01b0382166000908152600b6020908152604080832084845290915281205480611b105760405162461bcd60e51b81526004016107fd906144a2565b6000818152600160205260409020546001600160a01b031663cd740db560e01b1794909350915050565b6000806001600160a01b03841615611b5f57611b568484612844565b93509050611b95565b506000828152600160205260409020546001600160a01b031680611b955760405162461bcd60e51b81526004016107fd90614123565b6001600160a01b038116301415611bb057611b568184612844565b60007fed81cdda615fca130279b404b909f51438f5997d5ab9a459aecb921fbd297b6d3085604051602401611be69291906136a4565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b0383818316178352505050509050600080836001600160a01b031683604051611c36919061355d565b600060405180830381855afa9150503d8060008114611c71576040519150601f19603f3d011682016040523d82523d6000602084013e611c76565b606091505b50915091508115611c8957602081015194505b6001821515148015611cab57506001600160e01b0319851663cd740db560e01b145b15611cb95750505050610ae6565b50505063cd740db560e01b179392505050565b600081611ceb5760405162461bcd60e51b81526004016107fd906142cf565b6000611d2c84848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061206e92505050565b9050611d3a868233886120a0565b6040516331a9108f60e11b81526000903390636352211e90611d609089906004016136f8565b60206040518083038186803b158015611d7857600080fd5b505afa158015611d8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611db09190612f54565b6001600160a01b03161415611dd75760405162461bcd60e51b81526004016107fd906144eb565b611de081610f07565b5063785cf2dd60e11b9695505050505050565b6001600160e01b031981166301ffc9a760e01b14919050565b6000838152600160205260409020546001600160a01b0316611e405760405162461bcd60e51b81526004016107fd906140c6565b80611e4a57610c80565b6000838152600d602090815260408083206001600160a01b038616845290915290205480611ea6576000848152600c60205260409020611e8a90846128a7565b611ea65760405162461bcd60e51b81526004016107fd90613d8a565b6000848152600d602090815260408083206001600160a01b038716845290915281208054849290611ed89084906149e3565b90915550611efb9050846001600160a01b038516611ef685856149e3565b6128bc565b826001600160a01b031684866001600160a01b03167f684ce28ace37552c6bfb98b7cceda8ed55327078eafb5dfb31218e0856382763856040516111d691906136f8565b6001600160a01b0382166000908152600b6020908152604080832084845290915290205480611f805760405162461bcd60e51b81526004016107fd90613fb0565b848114611f9f5760405162461bcd60e51b81526004016107fd90613a46565b6001600160a01b038416611fc55760405162461bcd60e51b81526004016107fd90613eda565b6000611fd082610f07565b90506001600160a01b03811633148061200c57506001600160a01b038116600090815260056020908152604080832033845290915290205460ff165b8061203b57506001600160a01b0381811660009081526003602090815260408083208684529091529020541633145b6120575760405162461bcd60e51b81526004016107fd90613f65565b610df0828585612991565b6000610ae38383612ac0565b60006020820151905060208251101561067157815161208e9060086149fb565b61209a90610100614a1a565b1c919050565b6000838152600160205260409020546001600160a01b03166120d45760405162461bcd60e51b81526004016107fd9061400c565b6001600160a01b0382166000908152600b602090815260408083208484529091529020548314156121175760405162461bcd60e51b81526004016107fd90613b61565b6000838152600a602090815260408083206001600160a01b0386168452909152812061214290612618565b90508061217d57600084815260096020526040902061216190846128a7565b61217d5760405162461bcd60e51b81526004016107fd9061421f565b6000848152600a602090815260408083206001600160a01b038716845290915290206121a99083612b19565b6121c55760405162461bcd60e51b81526004016107fd90614665565b6001600160a01b0383166000818152600b60209081526040808320868452909152902085905530141561221c576000828152600260205260409020546122179085906001600160a01b038616906128bc565b612230565b61223084846001600160a01b0316846128bc565b826001600160a01b031684866001600160a01b03167f0371ddf2288ad1ba92626a7e31c86a9d006e592cfe57d7d946ef08b13457c08b856040516111d691906136f8565b6001600160a01b03831661229a5760405162461bcd60e51b81526004016107fd90613786565b6000818152600160205260409020546001600160a01b038481169116146122d35760405162461bcd60e51b81526004016107fd90614908565b6001600160a01b0382166122f95760405162461bcd60e51b81526004016107fd906139be565b336001600160a01b0384161461248e5760007fed81cdda615fca130279b404b909f51438f5997d5ab9a459aecb921fbd297b6d308360405160240161233f9291906136a4565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b0383818316178352505050509050600080856001600160a01b03168360405161238f919061355d565b600060405180830381855afa9150503d80600081146123ca576040519150601f19603f3d011682016040523d82523d6000602084013e6123cf565b606091505b509092509050600182151514156124185760208101516001600160e01b0319811663cd740db560e01b14156124165760405162461bcd60e51b81526004016107fd90614605565b505b6001600160a01b038616600090815260056020908152604080832033845290915290205460ff168061246e57506001600160a01b0386811660009081526003602090815260408083208884529091529020541633145b61248a5760405162461bcd60e51b81526004016107fd90613f1a565b5050505b6001600160a01b0383811660009081526003602090815260408083208584529091529020541615612515576001600160a01b038316600081815260036020908152604080832085845290915280822080546001600160a01b0319169055518392907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925908390a45b816001600160a01b0316836001600160a01b0316146125d2576001600160a01b03831660009081526004602052604090205461256157634e487b7160e01b600052600160045260246000fd5b6001600160a01b038316600090815260046020526040812080549161258583614a5d565b9091555050600081815260016020908152604080832080546001600160a01b0319166001600160a01b0387169081179091558352600490915281208054916125cc83614aaf565b91905055505b80826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b600061066e82612b25565b60006001600160a01b03831661264b5760405162461bcd60e51b81526004016107fd90613e44565b60008054908061265a83614aaf565b90915550506000805480825260016020908152604080842080546001600160a01b0319166001600160a01b038916908117909155845260049091528220805491926126a483614aaf565b90915550506000546040516126bd913091602001613579565b60408051601f198184030181529181528151602092830120600080548152600290935291205582511561270b576000818152600660209081526040909120845161270992860190612dd0565b505b60405181906001600160a01b038616906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a461275f6000858360405180602001604052806000815250612b29565b610ae35760405162461bcd60e51b81526004016107fd90614173565b3b151590565b8061278b57610d51565b6000838152600d602090815260408083206001600160a01b0386168452909152902054818110156127ce5760405162461bcd60e51b81526004016107fd9061391f565b6000848152600d602090815260408083206001600160a01b038716845290915290208282039081905580612830576000858152600c602052604090206128149085612c3a565b6128305760405162461bcd60e51b81526004016107fd90614714565b6108fb85856001600160a01b0316836128bc565b6001600160a01b0382166000908152600b60209081526040808320848452909152812054806128855760405162461bcd60e51b81526004016107fd90614458565b6000818152600160205260409020546001600160a01b031691505b9250929050565b6000610ae3836001600160a01b038416612c4f565b60008381526002602090815260408083205490516128de928691869101613587565b60408051601f19818403018152918152815160209283012060008781526002909352912081905590505b6000848152600160205260409020546001600160a01b0316301415610c8057306000818152600b6020908152604080832097835296815286822054808352600282529187902054965191966129639390929091859101613587565b60408051601f1981840301815291815281516020928301206000878152600290935291208190559050612908565b6000838152600a602090815260408083206001600160a01b038616845290915281206001906129bf90612618565b6129c99190614a1a565b6000858152600a602090815260408083206001600160a01b038816845290915290209091506129f89083612c99565b612a145760405162461bcd60e51b81526004016107fd906146b7565b6001600160a01b0383166000908152600b6020908152604080832085845290915281205580612a71576000848152600960205260409020612a559084612c3a565b612a715760405162461bcd60e51b81526004016107fd90613729565b6001600160a01b038316301415612aac57600082815260026020526040902054612aa79085906001600160a01b038616906128bc565b610c80565b610c8084846001600160a01b0316846128bc565b81546000908210612ae35760405162461bcd60e51b81526004016107fd90613819565b826000018281548110612b0657634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905092915050565b6000610ae38383612c4f565b5490565b6000612b3d846001600160a01b031661277b565b15612c3257604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290612b749033908990889088906004016135ef565b602060405180830381600087803b158015612b8e57600080fd5b505af1925050508015612bbe575060408051601f3d908101601f19168201909252612bbb9181019061336b565b60015b612c18573d808015612bec576040519150601f19603f3d011682016040523d82523d6000602084013e612bf1565b606091505b508051612c105760405162461bcd60e51b81526004016107fd90613a89565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050610c40565b506001610c40565b6000610ae3836001600160a01b038416612ca1565b6000612c5b8383612db8565b612c9157508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610ae6565b506000610ae6565b6000610ae383835b60008181526001830160205260408120548015612dae576000612cc5600183614a1a565b8554909150600090612cd990600190614a1a565b90506000866000018281548110612d0057634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905080876000018481548110612d3157634e487b7160e01b600052603260045260246000fd5b600091825260208083209091019290925582815260018901909152604090208490558654879080612d7257634e487b7160e01b600052603160045260246000fd5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050610ae6565b6000915050610ae6565b60009081526001919091016020526040902054151590565b828054612ddc90614a74565b90600052602060002090601f016020900481019282612dfe5760008555612e44565b82601f10612e1757805160ff1916838001178555612e44565b82800160010185558215612e44579182015b82811115612e44578251825591602001919060010190612e29565b50612e50929150612e54565b5090565b5b80821115612e505760008155600101612e55565b600067ffffffffffffffff80841115612e8457612e84614ae0565b604051601f8501601f191681016020018281118282101715612ea857612ea8614ae0565b604052848152915081838501861015612ec057600080fd5b8484602083013760006020868301015250509392505050565b60008083601f840112612eea578182fd5b50813567ffffffffffffffff811115612f01578182fd5b6020830191508360208285010111156128a057600080fd5b600082601f830112612f29578081fd5b610ae383833560208501612e69565b600060208284031215612f49578081fd5b8135610ae381614af6565b600060208284031215612f65578081fd5b8151610ae381614af6565b60008060408385031215612f82578081fd5b8235612f8d81614af6565b91506020830135612f9d81614af6565b809150509250929050565b600080600060608486031215612fbc578081fd5b8335612fc781614af6565b92506020840135612fd781614af6565b929592945050506040919091013590565b600080600080600060808688031215612fff578081fd5b853561300a81614af6565b9450602086013561301a81614af6565b935060408601359250606086013567ffffffffffffffff81111561303c578182fd5b61304888828901612ed9565b969995985093965092949392505050565b6000806000806080858703121561306e578384fd5b843561307981614af6565b9350602085013561308981614af6565b925060408501359150606085013567ffffffffffffffff8111156130ab578182fd5b6130b787828801612f19565b91505092959194509250565b600080600080608085870312156130d8578384fd5b84356130e381614af6565b935060208501356130f381614af6565b93969395505050506040820135916060013590565b60008060008060008060a08789031215613120578081fd5b863561312b81614af6565b9550602087013561313b81614af6565b94506040870135935060608701359250608087013567ffffffffffffffff811115613164578182fd5b61317089828a01612ed9565b979a9699509497509295939492505050565b60008060408385031215613194578182fd5b823561319f81614af6565b91506020830135612f9d81614b0e565b600080604083850312156131c1578182fd5b82356131cc81614af6565b9150602083013567ffffffffffffffff8111156131e7578182fd5b8301601f810185136131f7578182fd5b61320685823560208401612e69565b9150509250929050565b60008060408385031215613222578182fd5b823561322d81614af6565b946020939093013593505050565b60008060008060808587031215613250578182fd5b843561325b81614af6565b935060208501359250604085013561327281614af6565b9396929550929360600135925050565b60008060008060608587031215613297578182fd5b84356132a281614af6565b935060208501359250604085013567ffffffffffffffff8111156132c4578283fd5b6132d087828801612ed9565b95989497509550505050565b6000806000606084860312156132f0578081fd5b83356132fb81614af6565b925060208401359150604084013567ffffffffffffffff81111561331d578182fd5b61332986828701612f19565b9150509250925092565b600060208284031215613344578081fd5b8151610ae381614b0e565b600060208284031215613360578081fd5b8135610ae381614b1c565b60006020828403121561337c578081fd5b8151610ae381614b1c565b600060208284031215613398578081fd5b5035919050565b600080604083850312156133b1578182fd5b823591506020830135612f9d81614af6565b600080600080608085870312156133d8578182fd5b8435935060208501356133ea81614af6565b9250604085013561327281614af6565b600080600080600060a08688031215613411578283fd5b85359450602086013561342381614af6565b9350604086013561343381614af6565b925060608601359150608086013567ffffffffffffffff811115613455578182fd5b61346188828901612f19565b9150509295509295909350565b600080600060608486031215613482578081fd5b833592506020840135612fd781614af6565b60008060008060008060c087890312156134ac578384fd5b8635955060208701356134be81614af6565b94506040870135935060608701356134d581614af6565b92506080870135915060a087013567ffffffffffffffff8111156134f7578182fd5b61350389828a01612f19565b9150509295509295509295565b60008060408385031215613522578182fd5b50508035926020909101359150565b60008151808452613549816020860160208601614a31565b601f01601f19169290920160200192915050565b6000825161356f818460208701614a31565b9190910192915050565b918252602082015260400190565b9283526020830191909152604082015260600190565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061362290830184613531565b9695505050505050565b6001600160a01b039384168152919092166020820152604081019190915260806060820181905260009082015260a00190565b6001600160a01b03868116825285166020820152604081018490526060810183905260a06080820181905260009061369990830184613531565b979650505050505050565b6001600160a01b03929092168252602082015260400190565b600060018060a01b0385168252836020830152606060408301526136e46060830184613531565b95945050505050565b901515815260200190565b90815260200190565b6001600160e01b031991909116815260200190565b600060208252610ae36020830184613531565b60208082526038908201527f436f6d706f7361626c65546f70446f776e3a2072656d6f76654368696c643a2060408201527f5f6368696c64436f6e7472616374206e6f7420666f756e640000000000000000606082015260800190565b6020808252603390820152600080516020614b53833981519152604082015272205f66726f6d207a65726f206164647265737360681b606082015260800190565b60208082526032908201527f436f6d706f7361626c65546f70446f776e3a2055524920717565727920666f72604082015271103737b732bc34b9ba32b73a103a37b5b2b760711b606082015260800190565b60208082526022908201527f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e604082015261647360f01b606082015260800190565b6020808252604c908201527f436f6d706f7361626c65546f70446f776e3a20736166655472616e736665724660408201527f726f6d283429206f6e455243373231526563656976656420696e76616c69642060608201526b72657475726e2076616c756560a01b608082015260a00190565b60208082526032908201527f436f6d706f7361626c65546f70446f776e3a207472616e73666572455243323260408201527133205f746f207a65726f206164647265737360701b606082015260800190565b6020808252602f908201527f436f6d706f7361626c65546f70446f776e3a2072656d6f76654552433230207660408201526e0c2d8eaca40dcdee840cadcdeeaced608b1b606082015260800190565b60208082526030908201527f436f6d706f7361626c65546f70446f776e3a207472616e73666572455243323060408201526f081d1c985b9cd9995c8819985a5b195960821b606082015260800190565b6020808252603190820152600080516020614b53833981519152604082015270205f746f207a65726f206164647265737360781b606082015260800190565b60208082526029908201527f436f6d706f7361626c65546f70446f776e3a20737461746548617368206d69736040820152686d617463682028332960b81b606082015260800190565b6020808252603590820152600080516020614b7383398151915260408201527419081ddc9bdb99c81d1bdad95b925908199bdd5b99605a1b606082015260800190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6020808252606c90820152600080516020614b3383398151915260408201527f766564283429205f64617461206d75737420636f6e7461696e2074686520756960608201527f6e7432353620746f6b656e496420746f207472616e736665722074686520636860808201526b696c6420746f6b656e20746f60a01b60a082015260c00190565b6020808252603e908201527f436f6d706f7361626c65546f70446f776e3a20726563656976654368696c642060408201527f5f6368696c64546f6b656e496420616c72656164792072656365697665640000606082015260800190565b60208082526038908201527f436f6d706f7361626c65546f70446f776e3a2067657445524332302076616c7560408201527f652067726561746572207468616e2072656d61696e696e670000000000000000606082015260800190565b602080825260609082018190527f436f6d706f7361626c65546f70446f776e3a20746f6b656e46616c6c6261636b60408301527f205f64617461206d75737420636f6e7461696e207468652075696e7432353620908201527f746f6b656e496420746f207472616e736665722074686520746f6b656e20746f608082015260a00190565b6020808252602b908201527f436f6d706f7361626c65546f70446f776e3a206765744552433230207472616e60408201526a1cd9995c8819985a5b195960aa1b606082015260800190565b60208082526035908201527f436f6d706f7361626c65546f70446f776e3a2062616c616e63654f66205f746f6040820152746b656e4f776e6572207a65726f206164647265737360581b606082015260800190565b6020808252603c90820152600080516020614b3383398151915260408201527f766564283429206368696c6420746f6b656e206e6f74206f776e656400000000606082015260800190565b60208082526043908201527f436f6d706f7361626c65546f70446f776e3a206572633230526563656976656460408201527f3a206572633230436f6e74726163747320616464205f6572633230436f6e74726060820152621858dd60ea1b608082015260a00190565b60208082526031908201527f436f6d706f7361626c65546f70446f776e3a207472616e736665724552433230604082015270205f746f207a65726f206164647265737360781b606082015260800190565b60208082526023908201527f436f6d706f7361626c65546f70446f776e3a205f746f207a65726f206164647260408201526265737360e81b606082015260800190565b60208082526033908201527f436f6d706f7361626c65546f70446f776e3a206765744552433230206e6f74206040820152720616c6c6f77656420746f20676574455243323606c1b606082015260800190565b6020808252603290820152600080516020614b7383398151915260408201527164205f746f207a65726f206164647265737360701b606082015260800190565b6020808252603890820152600080516020614b5383398151915260408201527f206d73672e73656e646572206e6f7420617070726f7665640000000000000000606082015260800190565b6020808252603990820152600080516020614b7383398151915260408201527f64206d73672e73656e646572206e6f7420656c696769626c6500000000000000606082015260800190565b6020808252604890820152600080516020614b7383398151915260408201527f64205f6368696c64436f6e7472616374205f6368696c64546f6b656e4964206e6060820152671bdd08199bdd5b9960c21b608082015260a00190565b60208082526038908201527f436f6d706f7361626c65546f70446f776e3a20726563656976654368696c642060408201527f5f746f6b656e496420646f6573206e6f742065786973742e0000000000000000606082015260800190565b60208082526039908201527f436f6d706f7361626c65546f70446f776e3a207472616e73666572455243323260408201527f33206d73672e73656e646572206e6f7420656c696769626c6500000000000000606082015260800190565b60208082526038908201527f436f6d706f7361626c65546f70446f776e3a206572633230526563656976656460408201527f205f746f6b656e496420646f6573206e6f742065786973740000000000000000606082015260800190565b60208082526030908201527f436f6d706f7361626c65546f70446f776e3a206f776e65724f66205f746f6b6560408201526f6e4964207a65726f206164647265737360801b606082015260800190565b6020808252603d908201527f436f6d706f7361626c65546f70446f776e3a207472616e7366657220746f206e60408201527f6f6e20455243373231526563656976657220696d706c656d656e746572000000606082015260800190565b6020808252602f908201527f436f6d706f7361626c65546f70446f776e3a20617070726f7665206d73672e7360408201526e32b73232b9103737ba1037bbb732b960891b606082015260800190565b60208082526033908201527f436f6d706f7361626c65546f70446f776e3a20726563656976654368696c643a604082015272081859190817d8da1a5b1910dbdb9d1c9858dd606a1b606082015260800190565b6020808252603b908201527f436f6d706f7361626c65546f70446f776e3a20736574417070726f76616c466f60408201527f72416c6c205f6f70657261746f72207a65726f20616464726573730000000000606082015260800190565b6020808252606c90820152600080516020614b3383398151915260408201527f766564283329205f64617461206d75737420636f6e7461696e2074686520756960608201527f6e7432353620746f6b656e496420746f207472616e736665722074686520636860808201526b696c6420746f6b656e20746f60a01b60a082015260c00190565b60208082526038908201527f436f6d706f7361626c65546f70446f776e3a207472616e73666572455243323060408201527f206d73672e73656e646572206e6f7420656c696769626c650000000000000000606082015260800190565b60208082526029908201527f436f6d706f7361626c65546f70446f776e3a20737461746548617368206d69736040820152686d617463682028312960b81b606082015260800190565b6020808252603d908201527f436f6d706f7361626c65546f70446f776e3a20746f6b656e46616c6c6261636b60408201527f206d73672e73656e646572206973206e6f74206120636f6e7472616374000000606082015260800190565b6020808252602a908201527f436f6d706f7361626c65546f70446f776e3a205f6f776e65724f664368696c64604082015269081b9bdd08199bdd5b9960b21b606082015260800190565b60208082526029908201527f436f6d706f7361626c65546f70446f776e3a206f776e65724f664368696c64206040820152681b9bdd08199bdd5b9960ba1b606082015260800190565b6020808252603c90820152600080516020614b3383398151915260408201527f766564283329206368696c6420746f6b656e206e6f74206f776e656400000000606082015260800190565b6020808252604c908201527f436f6d706f7361626c65546f70446f776e3a20736166655472616e736665724660408201527f726f6d283329206f6e455243373231526563656976656420696e76616c69642060608201526b72657475726e2076616c756560a01b608082015260a00190565b60208082526037908201527f436f6d706f7361626c65546f70446f776e3a206973417070726f766564466f7260408201527f416c6c205f6f776e6572207a65726f2061646472657373000000000000000000606082015260800190565b6020808252604c90820152600080516020614b5383398151915260408201527f20746f6b656e206973206368696c64206f66206f7468657220746f7020646f7760608201526b6e20636f6d706f7361626c6560a01b608082015260a00190565b60208082526032908201527f436f6d706f7361626c65546f70446f776e3a20726563656976654368696c643a604082015271081859190817d8da1a5b19151bdad95b925960721b606082015260800190565b60208082526037908201527f436f6d706f7361626c65546f70446f776e3a2072656d6f76654368696c643a2060408201527f5f6368696c64546f6b656e4964206e6f7420666f756e64000000000000000000606082015260800190565b60208082526044908201527f436f6d706f7361626c65546f70446f776e3a2072656d6f766545524332303a2060408201527f6572633230436f6e7472616374732072656d6f7665205f6572633230436f6e746060820152631c9858dd60e21b608082015260a00190565b60208082526021908201527f436f6d706f7361626c65546f70446f776e3a20555249206973206e6f742073656040820152601d60fa1b606082015260800190565b6020808252603a908201527f436f6d706f7361626c65546f70446f776e3a206973417070726f766564466f7260408201527f416c6c205f6f70657261746f72207a65726f2061646472657373000000000000606082015260800190565b60208082526029908201527f436f6d706f7361626c65546f70446f776e3a20737461746548617368206d69736040820152686d617463682028322960b81b606082015260800190565b60208082526033908201527f436f6d706f7361626c65546f70446f776e3a206765744368696c64206d73672e6040820152721cd95b99195c881b9bdd08185c1c1c9bdd9959606a1b606082015260800190565b60208082526030908201527f436f6d706f7361626c65546f70446f776e3a20737461746548617368206f662060408201526f5f746f6b656e4964206973207a65726f60801b606082015260800190565b6020808252603090820152600080516020614b5383398151915260408201526f102fb33937b6903737ba1037bbb732b960811b606082015260800190565b60208082526031908201527f436f6d706f7361626c65546f70446f776e3a207472616e7366657245524332326040820152700cc81d1c985b9cd9995c8819985a5b1959607a1b606082015260800190565b6020808252602c908201527f436f6d706f7361626c65546f70446f776e3a20676574455243323020616c6c6f60408201526b1dd85b98d94819985a5b195960a21b606082015260800190565b600082198211156149f6576149f6614aca565b500190565b6000816000190483118215151615614a1557614a15614aca565b500290565b600082821015614a2c57614a2c614aca565b500390565b60005b83811015614a4c578181015183820152602001614a34565b83811115610c805750506000910152565b600081614a6c57614a6c614aca565b506000190190565b600281046001821680614a8857607f821691505b60208210811415614aa957634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415614ac357614ac3614aca565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114614b0b57600080fd5b50565b8015158114614b0b57600080fd5b6001600160e01b031981168114614b0b57600080fdfe436f6d706f7361626c65546f70446f776e3a206f6e4552433732315265636569436f6d706f7361626c65546f70446f776e3a205f7472616e7366657246726f6d436f6d706f7361626c65546f70446f776e3a205f7472616e736665724368696ca264697066735822122015ff459bc4f58905da537b06bee1b19459690784b7679a4f977b1eebacd46b3d64736f6c63430008000033

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

00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000e436f6d706f7361626c65204e46540000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004434e465400000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _name (string): Composable NFT
Arg [1] : _symbol (string): CNFT

-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [2] : 000000000000000000000000000000000000000000000000000000000000000e
Arg [3] : 436f6d706f7361626c65204e4654000000000000000000000000000000000000
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [5] : 434e465400000000000000000000000000000000000000000000000000000000


Deployed Bytecode Sourcemap

65771:35438:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;97896:623;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;67191:27;;;:::i;:::-;;;;;;;:::i;94394:1282::-;;;;;;:::i;:::-;;:::i;:::-;;73073:281;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;80467:747::-;;;;;;:::i;:::-;;:::i;72574:491::-;;;;;;:::i;:::-;;:::i;84236:221::-;;;;;;:::i;:::-;;:::i;82911:871::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;84695:247::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;100413:314::-;;;;;;:::i;:::-;;:::i;78630:468::-;;;;;;:::i;:::-;;:::i;74247:172::-;;;;;;:::i;:::-;;:::i;84465:222::-;;;;;;:::i;:::-;;:::i;100846:358::-;;;;;;:::i;:::-;;:::i;67550:102::-;;;;;;:::i;:::-;;:::i;74427:656::-;;;;;;:::i;:::-;;:::i;69540:193::-;;;;;;:::i;:::-;;:::i;99614:247::-;;;;;;:::i;:::-;;:::i;83790:242::-;;;;;;:::i;:::-;;:::i;93918:207::-;;;;;;:::i;:::-;;:::i;71888:348::-;;;;;;:::i;:::-;;:::i;72244:322::-;;;;;;:::i;:::-;;:::i;99980:::-;;;;;;:::i;:::-;;:::i;91072:969::-;;;;;;:::i;:::-;;:::i;79106:517::-;;;;;;:::i;:::-;;:::i;84040:188::-;;;;;;:::i;:::-;;:::i;67248:29::-;;;:::i;73362:385::-;;;;;;:::i;:::-;;:::i;94133:188::-;;;;;;:::i;:::-;;:::i;75091:724::-;;;;;;:::i;:::-;;:::i;81287:764::-;;;;;;:::i;:::-;;:::i;79631:828::-;;;;;;:::i;:::-;;:::i;93128:561::-;;;;;;:::i;:::-;;:::i;68544:372::-;;;;;;:::i;:::-;;:::i;67408:134::-;;;;;;:::i;:::-;;:::i;92083:1013::-;;;;;;:::i;:::-;;:::i;93697:213::-;;;;;;:::i;:::-;;:::i;73755:484::-;;;;;;:::i;:::-;;:::i;84950:588::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;70027:1787::-;;;;;;:::i;:::-;;:::i;82059:844::-;;;;;;:::i;:::-;;:::i;97896:623::-;97989:4;-1:-1:-1;;;;;;98013:40:0;;-1:-1:-1;;;98013:40:0;;:105;;-1:-1:-1;;;;;;;98070:48:0;;-1:-1:-1;;;98070:48:0;98013:105;:175;;;-1:-1:-1;;;;;;;98135:53:0;;-1:-1:-1;;;98135:53:0;98013:175;:255;;;-1:-1:-1;;;;;;;98205:63:0;;-1:-1:-1;;;98205:63:0;98013:255;:324;;;-1:-1:-1;;;;;;;98285:52:0;;-1:-1:-1;;;98285:52:0;98013:324;:403;;;-1:-1:-1;;;;;;;98354:62:0;;-1:-1:-1;;;98354:62:0;98013:403;:445;;;-1:-1:-1;;;;;;;;;;98433:25:0;;;98013:445;:498;;;;98475:36;98499:11;98475:23;:36::i;:::-;98006:505;;97896:623;;;;:::o;67191:27::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;94394:1282::-;-1:-1:-1;;;;;94570:19:0;;94579:10;94570:19;;94600:678;;94629:21;69151:39;94704:5;94711:10;94670:52;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;;;;;94670:52:0;;;;;;;-1:-1:-1;;;;;94670:52:0;;;;;;;;;;;94629:93;;94738:16;94756:17;94794:14;-1:-1:-1;;;;;94794:25:0;94820:8;94794:35;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;94737:92;;;;94870:11;94844:117;;;;-1:-1:-1;;;94844:117:0;;;;;;;:::i;:::-;;;;;;;;;95065:4;95055:15;;95049:22;95126:19;;;;95100:137;;;;-1:-1:-1;;;95100:137:0;;;;;;;:::i;:::-;95262:4;95252:14;;94600:678;;;;;95296:7;95288:71;;;;-1:-1:-1;;;95288:71:0;;;;;;;:::i;:::-;95370:54;95384:5;95391:8;95401:14;95417:6;95370:13;:54::i;:::-;95457:140;;-1:-1:-1;;;95457:140:0;;-1:-1:-1;;;;;95457:44:0;;;;;:140;;95520:5;;95552:4;;95576:6;;95457:140;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;95435:233;;;;-1:-1:-1;;;95435:233:0;;;;;;;:::i;:::-;94394:1282;;;;;:::o;73073:281::-;73178:7;73203:17;73247:21;73259:8;73247:11;:21::i;:::-;-1:-1:-1;;;;;73289:47:0;;;73239:30;73289:47;;;:36;:47;;;;;;;;:57;;;;;;;;;;;-1:-1:-1;;73073:281:0;;;:::o;80467:747::-;80718:135;80747:12;80774:11;80800:14;80829:13;80718:14;:135::i;:::-;80950:14;-1:-1:-1;;;;;80869:134:0;80924:11;-1:-1:-1;;;;;80869:134:0;80897:12;80869:134;80979:13;80869:134;;;;;;:::i;:::-;;;;;;;;81014:192;;-1:-1:-1;;;81014:192:0;;-1:-1:-1;;;;;81014:54:0;;;;;:192;;81091:4;;81111:11;;81137:10;;81162:13;;81190:5;;81014:192;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;80467:747;;;;;;:::o;72574:491::-;72657:17;72701:21;72713:8;72701:11;:21::i;:::-;72693:30;-1:-1:-1;;;;;;72758:23:0;;72771:10;72758:23;;:88;;-1:-1:-1;;;;;;72802:32:0;;;;;;:21;:32;;;;;;;;72835:10;72802:44;;;;;;;;;;72758:88;72736:185;;;;-1:-1:-1;;;72736:185:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;72932:47:0;;;;;;;:36;:47;;;;;;;;:57;;;;;;;;;:69;;-1:-1:-1;;;;;;72932:69:0;;;;;;;;;73017:40;72932:57;;:69;:47;73017:40;;;72574:491;;;:::o;84236:221::-;84368:21;84414:24;;;:14;:24;;;;;:35;;84442:6;84414:27;:35::i;:::-;84407:42;;84236:221;;;;;:::o;82911:871::-;83076:6;83117:16;83095:174;;;;-1:-1:-1;;;83095:174:0;;;;;;;:::i;:::-;83378:15;83396:20;83410:5;;83396:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;83396:13:0;;-1:-1:-1;;;83396:20:0:i;:::-;83378:38;;83427:55;83440:5;83447:7;83456:10;83468:13;83427:12;:55::i;:::-;83515:42;;-1:-1:-1;;;83515:42:0;;83569:1;;83523:10;;83515:27;;:42;;83543:13;;83515:42;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;83515:56:0;;;83493:166;;;;-1:-1:-1;;;83493:166:0;;;;;;;:::i;:::-;83717:20;83729:7;83717:11;:20::i;:::-;-1:-1:-1;;;;83755:19:0;82911:871;-1:-1:-1;;;;;;;82911:871:0:o;84695:247::-;84846:20;84886:21;;;:11;:21;;;;;;;;-1:-1:-1;;;;;84886:37:0;;;;;;;;;:48;;84927:6;84886:40;:48::i;:::-;84879:55;84695:247;-1:-1:-1;;;;84695:247:0:o;100413:314::-;100604:27;;;;:18;:27;;;;;;100583:48;;100575:102;;;;-1:-1:-1;;;100575:102:0;;;;;;;:::i;:::-;100688:31;100701:4;100707:2;100711:7;100688:12;:31::i;:::-;100413:314;;;;:::o;78630:468::-;78811:64;78826:12;78840:3;78845:14;78861:13;78811:14;:64::i;:::-;78886:125;;-1:-1:-1;;;78886:125:0;;-1:-1:-1;;;;;78886:40:0;;;;;:125;;78949:4;;78969:3;;78987:13;;78886:125;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;79060:14;-1:-1:-1;;;;;79027:63:0;79055:3;-1:-1:-1;;;;;79027:63:0;79041:12;79027:63;79076:13;79027:63;;;;;;:::i;:::-;;;;;;;;78630:468;;;;:::o;74247:172::-;74376:35;74390:5;74397:3;74402:8;74376:13;:35::i;:::-;74247:172;;;:::o;84465:222::-;84601:7;84633:21;;;:11;:21;;;;;;;;-1:-1:-1;;;;;84633:37:0;;;;;;;;;:46;;:44;:46::i;100846:358::-;101071:27;;;;:18;:27;;;;;;101050:48;;101042:102;;;;-1:-1:-1;;;101042:102:0;;;;;;;:::i;:::-;101155:41;101172:4;101178:2;101182:7;101191:4;;101155:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;101155:16:0;;-1:-1:-1;;;101155:41:0:i;:::-;100846:358;;;;;;:::o;67550:102::-;67599:7;67626:18;67636:3;67626:18;;;;;;;;;;;;:9;:18::i;74427:656::-;74560:35;74574:5;74581:3;74586:8;74560:13;:35::i;:::-;74610:16;:3;-1:-1:-1;;;;;74610:14:0;;:16::i;:::-;74606:470;;;74676:173;;-1:-1:-1;;;74676:173:0;;74643:13;;-1:-1:-1;;;;;74676:37:0;;;;;:173;;74736:10;;74769:5;;74797:8;;74676:173;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;74643:206;-1:-1:-1;;;;;;;74890:29:0;;-1:-1:-1;;;74890:29:0;;:62;;-1:-1:-1;;;;;;;74923:29:0;;-1:-1:-1;;;74923:29:0;74890:62;74864:200;;;;-1:-1:-1;;;74864:200:0;;;;;;;:::i;69540:193::-;69645:17;69687:38;69712:1;69716:8;69687:16;:38::i;99614:247::-;99671:7;99712:27;;;:18;:27;;;;;;99758:14;99750:75;;;;-1:-1:-1;;;99750:75:0;;;;;;;:::i;83790:242::-;-1:-1:-1;;;;;83948:31:0;;;;83908:4;83948:31;;;:15;:31;;;;;;;;:46;;;;;;;;84012:12;;;83790:242::o;93918:207::-;94050:7;94082:24;;;:14;:24;;;;;:35;;94110:6;94082:27;:35::i;71888:348::-;71989:18;72038:29;;;:19;:29;;;;;;-1:-1:-1;;;;;72038:29:0;72100:24;72078:122;;;;-1:-1:-1;;;72078:122:0;;;;;;;:::i;72244:322::-;72352:7;-1:-1:-1;;;;;72399:25:0;;72377:128;;;;-1:-1:-1;;;72377:128:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;;72523:35:0;;;;;:22;:35;;;;;;;72244:322::o;99980:::-;100175:27;;;;:18;:27;;;;;;100154:48;;100146:102;;;;-1:-1:-1;;;100146:102:0;;;;;;;:::i;:::-;100259:35;100276:4;100282:2;100286:7;100259:16;:35::i;91072:969::-;-1:-1:-1;;;;;91260:17:0;;91238:116;;;;-1:-1:-1;;;91238:116:0;;;;;;;:::i;:::-;91365:17;91409:21;91421:8;91409:11;:21::i;:::-;91401:30;-1:-1:-1;;;;;;91466:23:0;;91479:10;91466:23;;:88;;-1:-1:-1;;;;;;91510:32:0;;;;;;:21;:32;;;;;;;;91543:10;91510:44;;;;;;;;;;91466:88;:197;;;-1:-1:-1;;;;;;91575:47:0;;;;;;;:36;:47;;;;;;;;:57;;;;;;;;;;91653:10;91575:88;91466:197;91444:303;;;;-1:-1:-1;;;91444:303:0;;;;;;;:::i;:::-;91758:45;91770:8;91780:14;91796:6;91758:11;:45::i;:::-;91836:53;;-1:-1:-1;;;91836:53:0;;-1:-1:-1;;;;;91836:40:0;;;;;:53;;91877:3;;91882:6;;91836:53;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;91814:151;;;;-1:-1:-1;;;91814:151:0;;;;;;;:::i;:::-;92010:14;-1:-1:-1;;;;;91981:52:0;92005:3;-1:-1:-1;;;;;91981:52:0;91995:8;91981:52;92026:6;91981:52;;;;;;:::i;:::-;;;;;;;;91072:969;;;;;:::o;79106:517::-;79316:64;79331:12;79345:3;79350:14;79366:13;79316:14;:64::i;:::-;79391:145;;-1:-1:-1;;;79391:145:0;;-1:-1:-1;;;;;79391:40:0;;;;;:145;;79454:4;;79474:3;;79492:13;;79520:5;;79391:145;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;79585:14;-1:-1:-1;;;;;79552:63:0;79580:3;-1:-1:-1;;;;;79552:63:0;79566:12;79552:63;79601:13;79552:63;;;;;;:::i;84040:188::-;84155:7;84187:24;;;:14;:24;;;;;:33;;:31;:33::i;67248:29::-;;;;;;;:::i;73362:385::-;-1:-1:-1;;;;;73498:23:0;;73476:132;;;;-1:-1:-1;;;73476:132:0;;;;;;;:::i;:::-;73641:10;73619:33;;;;:21;:33;;;;;;;;-1:-1:-1;;;;;73619:44:0;;;;;;;;;;;:56;;-1:-1:-1;;73619:56:0;;;;;;;73691:48;;73619:44;;73641:10;73691:48;;;;73619:56;;73691:48;:::i;:::-;;;;;;;;73362:385;;:::o;94133:188::-;94248:7;94280:24;;;:14;:24;;;;;:33;;:31;:33::i;75091:724::-;75253:35;75267:5;75274:3;75279:8;75253:13;:35::i;:::-;75303:16;:3;-1:-1:-1;;;;;75303:14:0;;:16::i;:::-;75299:509;;;75369:176;;-1:-1:-1;;;75369:176:0;;75336:13;;-1:-1:-1;;;;;75369:37:0;;;;;:176;;75429:10;;75462:5;;75490:8;;75521:5;;75369:176;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;75336:209;-1:-1:-1;;;;;;;75586:29:0;;-1:-1:-1;;;75586:29:0;;:62;;-1:-1:-1;;;;;;;75619:29:0;;-1:-1:-1;;;75619:29:0;75586:62;75560:200;;;;-1:-1:-1;;;75560:200:0;;;;;;;:::i;:::-;75775:21;75787:8;75775:11;:21::i;81287:764::-;81457:60;81470:5;81477:8;81487:14;81503:13;81457:12;:60::i;:::-;-1:-1:-1;;;;;81550:19:0;;81559:10;81550:19;;:99;;-1:-1:-1;81590:59:0;;-1:-1:-1;;;81590:59:0;;-1:-1:-1;;;;;81590:40:0;;;;;:59;;81631:5;;81638:10;;81590:59;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;81550:201;;;-1:-1:-1;81670:50:0;;-1:-1:-1;;;81670:50:0;;81741:10;;-1:-1:-1;;;;;81670:35:0;;;;;:50;;81706:13;;81670:50;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;81670:81:0;;81550:201;81528:302;;;;-1:-1:-1;;;81528:302:0;;;;;;;:::i;:::-;81841:123;;-1:-1:-1;;;81841:123:0;;-1:-1:-1;;;;;81841:36:0;;;;;:123;;81892:5;;81920:4;;81940:13;;81841:123;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;82022:21;82034:8;82022:11;:21::i;79631:828::-;79808:64;79823:12;79837:3;79842:14;79858:13;79808:14;:64::i;:::-;80159:21;69231:37;80228:4;80234:13;80196:52;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;;;;;80196:52:0;;;;;;;-1:-1:-1;;;;;80196:52:0;;;;;;;;;;;80159:89;;80259:14;-1:-1:-1;;;;;80259:19:0;80279:8;80259:29;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;80301:71:0;;-1:-1:-1;;;80301:71:0;;-1:-1:-1;;;;;80301:36:0;;;-1:-1:-1;80301:36:0;;:71;;80346:4;;80353:3;;80358:13;;80301:71;;;:::i;93128:561::-;93302:1;93287:5;:12;:16;93265:162;;;;-1:-1:-1;;;93265:162:0;;;;;;;:::i;:::-;93460:9;93473:10;93460:23;;93438:134;;;;-1:-1:-1;;;93438:134:0;;;;;;;:::i;:::-;93583:15;93601:20;93615:5;93601:13;:20::i;:::-;93583:38;;93632:49;93646:5;93653:7;93662:10;93674:6;93632:13;:49::i;68544:372::-;68685:1;68645:28;;;:19;:28;;;;;;68611:13;;-1:-1:-1;;;;;68645:28:0;68637:105;;;;-1:-1:-1;;;68637:105:0;;;;;;;:::i;:::-;68753:23;68779:18;;;:9;:18;;;;;68753:44;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;68842:1;68822:9;68816:23;:27;68808:73;;;;-1:-1:-1;;;68808:73:0;;;;;;;:::i;67408:134::-;67482:7;67509:25;67519:3;67524:9;67509;:25::i;92083:1013::-;-1:-1:-1;;;;;92302:17:0;;92280:117;;;;-1:-1:-1;;;92280:117:0;;;;;;;:::i;:::-;92408:17;92452:21;92464:8;92452:11;:21::i;:::-;92444:30;-1:-1:-1;;;;;;92509:23:0;;92522:10;92509:23;;:88;;-1:-1:-1;;;;;;92553:32:0;;;;;;:21;:32;;;;;;;;92586:10;92553:44;;;;;;;;;;92509:88;:197;;;-1:-1:-1;;;;;;92618:47:0;;;;;;;:36;:47;;;;;;;;:57;;;;;;;;;;92696:10;92618:88;92509:197;92487:304;;;;-1:-1:-1;;;92487:304:0;;;;;;;:::i;:::-;92802:46;92814:8;92824:15;92841:6;92802:11;:46::i;:::-;92881:61;;-1:-1:-1;;;92881:61:0;;-1:-1:-1;;;;;92881:41:0;;;;;:61;;92923:3;;92928:6;;92936:5;;92881:61;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;92859:160;;;;-1:-1:-1;;;92859:160:0;;;;;;;:::i;:::-;93064:15;-1:-1:-1;;;;;93035:53:0;93059:3;-1:-1:-1;;;;;93035:53:0;93049:8;93035:53;93081:6;93035:53;;;;;;:::i;:::-;;;;;;;;92083:1013;;;;;;:::o;93697:213::-;93831:7;93863:23;;;:13;:23;;;;;;;;-1:-1:-1;;;;;93863:39:0;;;;;;;;;;;;;93697:213::o;73755:484::-;73884:4;-1:-1:-1;;;;;73928:20:0;;73906:125;;;;-1:-1:-1;;;73906:125:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;74064:23:0;;74042:131;;;;-1:-1:-1;;;74042:131:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;;74191:29:0;;;;;;;:21;:29;;;;;;;;:40;;;;;;;;;;;;;;;73755:484::o;84950:588::-;-1:-1:-1;;;;;85168:31:0;;85087:24;85168:31;;;:15;:31;;;;;;;;:46;;;;;;;;;85247:18;85225:109;;;;-1:-1:-1;;;85225:109:0;;;;;;;:::i;:::-;85345:31;85379:34;;;:19;:34;;;;;;-1:-1:-1;;;;;85379:34:0;-1:-1:-1;;;85468:50:0;;85379:34;;-1:-1:-1;85468:50:0;-1:-1:-1;;85433:96:0:o;70027:1787::-;70166:17;;-1:-1:-1;;;;;70240:28:0;;;70236:382;;70321:93;70353:14;70386:13;70321;:93::i;:::-;70285:129;-1:-1:-1;70285:129:0;-1:-1:-1;70236:382:0;;;-1:-1:-1;70466:34:0;;;;:19;:34;;;;;;-1:-1:-1;;;;;70466:34:0;70523:30;70515:91;;;;-1:-1:-1;;;70515:91:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;70695:33:0;;70723:4;70695:33;70688:200;;;70781:95;70813:16;70848:13;70781;:95::i;70688:200::-;70898:21;69330:46;71022:4;71046:13;70935:139;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;;;;;70935:139:0;;;;;;;-1:-1:-1;;;;;70935:139:0;;;;;;;;;;;70898:176;;71086:16;71104:17;71138:16;-1:-1:-1;;;;;71138:27:0;71166:8;71138:37;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;71085:90;;;;71190:11;71186:121;;;71275:4;71269;71265:15;71259:22;71246:35;;71227:69;71338:4;71323:19;;;;:126;;;;-1:-1:-1;;;;;;;71346:78:0;;-1:-1:-1;;;71346:103:0;71323:126;71319:488;;;71531:16;;;;;;71319:488;-1:-1:-1;;;;;;71738:43:0;;;-1:-1:-1;;;70027:1787:0:o;82059:844::-;82197:6;82238:16;82216:174;;;;-1:-1:-1;;;82216:174:0;;;;;;;:::i;:::-;82499:15;82517:20;82531:5;;82517:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;82517:13:0;;-1:-1:-1;;;82517:20:0:i;:::-;82499:38;;82548:55;82561:5;82568:7;82577:10;82589:13;82548:12;:55::i;:::-;82636:42;;-1:-1:-1;;;82636:42:0;;82690:1;;82644:10;;82636:27;;:42;;82664:13;;82636:42;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;82636:56:0;;;82614:166;;;;-1:-1:-1;;;82614:166:0;;;;;;;:::i;:::-;82838:20;82850:7;82838:11;:20::i;:::-;-1:-1:-1;;;;82876:19:0;82059:844;-1:-1:-1;;;;;;82059:844:0:o;1759:157::-;-1:-1:-1;;;;;;1868:40:0;;-1:-1:-1;;;1868:40:0;1759:157;;;:::o;95684:856::-;95905:1;95864:29;;;:19;:29;;;;;;-1:-1:-1;;;;;95864:29:0;95842:149;;;;-1:-1:-1;;;95842:149:0;;;;;;;:::i;:::-;96006:11;96002:50;;96034:7;;96002:50;96062:20;96085:23;;;:13;:23;;;;;;;;-1:-1:-1;;;;;96085:39:0;;;;;;;;;;96139:17;96135:174;;96181:24;;;;:14;:24;;;;;:44;;96210:14;96181:28;:44::i;:::-;96173:124;;;;-1:-1:-1;;;96173:124:0;;;;;;;:::i;:::-;96319:23;;;;:13;:23;;;;;;;;-1:-1:-1;;;;;96319:39:0;;;;;;;;;:49;;96362:6;;96319:23;:49;;96362:6;;96319:49;:::i;:::-;;;;-1:-1:-1;96379:83:0;;-1:-1:-1;96396:8:0;-1:-1:-1;;;;;96406:32:0;;96440:21;96455:6;96440:12;:21;:::i;:::-;96379:16;:83::i;:::-;96509:14;-1:-1:-1;;;;;96478:54:0;96499:8;96492:5;-1:-1:-1;;;;;96478:54:0;;96525:6;96478:54;;;;;;:::i;85546:1104::-;-1:-1:-1;;;;;85732:31:0;;85714:15;85732:31;;;:15;:31;;;;;;;;:46;;;;;;;;;85811:12;85789:134;;;;-1:-1:-1;;;85789:134:0;;;;;;;:::i;:::-;85967:12;85956:7;:23;85934:126;;;;-1:-1:-1;;;85934:126:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;86093:17:0;;86071:117;;;;-1:-1:-1;;;86071:117:0;;;;;;;:::i;:::-;86199:17;86243:20;86255:7;86243:11;:20::i;:::-;86235:29;-1:-1:-1;;;;;;86299:23:0;;86312:10;86299:23;;:88;;-1:-1:-1;;;;;;86343:32:0;;;;;;:21;:32;;;;;;;;86376:10;86343:44;;;;;;;;;;86299:88;:196;;;-1:-1:-1;;;;;;86408:47:0;;;;;;;:36;:47;;;;;;;;:56;;;;;;;;;;86485:10;86408:87;86299:196;86277:303;;;;-1:-1:-1;;;86277:303:0;;;;;;;:::i;:::-;86591:51;86603:7;86612:14;86628:13;86591:11;:51::i;59114:158::-;59188:7;59239:22;59243:3;59255:5;59239:3;:22::i;87110:403::-;87202:15;87384:4;87377:5;87373:16;87367:23;87356:34;;87430:2;87415:5;:12;:17;87411:95;;;87477:12;;:16;;87492:1;87477:16;:::i;:::-;87471:22;;:3;:22;:::i;:::-;87459:35;87110:403;;;:::o;89331:1325::-;89558:1;89517:29;;;:19;:29;;;;;;-1:-1:-1;;;;;89517:29:0;89495:149;;;;-1:-1:-1;;;89495:149:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;89677:31:0;;;;;;:15;:31;;;;;;;;:46;;;;;;;;;:58;;;89655:170;;;;-1:-1:-1;;;89655:170:0;;;;;;;:::i;:::-;89836:25;89877:21;;;:11;:21;;;;;;;;-1:-1:-1;;;;;89877:37:0;;;;;;;;;:46;;:44;:46::i;:::-;89836:87;-1:-1:-1;89938:22:0;89934:163;;89985:24;;;;:14;:24;;;;;:44;;90014:14;89985:28;:44::i;:::-;89977:108;;;;-1:-1:-1;;;89977:108:0;;;;;;;:::i;:::-;90115:21;;;;:11;:21;;;;;;;;-1:-1:-1;;;;;90115:37:0;;;;;;;;;:56;;90157:13;90115:41;:56::i;:::-;90107:119;;;;-1:-1:-1;;;90107:119:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;90237:31:0;;;;;;:15;:31;;;;;;;;:46;;;;;;;;:57;;;90335:4;90309:31;90305:267;;;90418:33;;;;:18;:33;;;;;;90357:95;;90374:8;;-1:-1:-1;;;;;90384:32:0;;;90357:16;:95::i;:::-;90305:267;;;90485:75;90502:8;90528:14;-1:-1:-1;;;;;90512:32:0;90546:13;90485:16;:75::i;:::-;90618:14;-1:-1:-1;;;;;90587:61:0;90608:8;90601:5;-1:-1:-1;;;;;90587:61:0;;90634:13;90587:61;;;;;;:::i;75823:2217::-;-1:-1:-1;;;;;75967:19:0;;75945:120;;;;-1:-1:-1;;;75945:120:0;;;;;;;:::i;:::-;76098:29;;;;:19;:29;;;;;;-1:-1:-1;;;;;76098:38:0;;;:29;;:38;76076:136;;;;-1:-1:-1;;;76076:136:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;76245:17:0;;76223:116;;;;-1:-1:-1;;;76223:116:0;;;;;;;:::i;:::-;76356:10;-1:-1:-1;;;;;76356:19:0;;;76352:1079;;76392:21;69330:46;76528:4;76556:8;76433:150;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;;;;;76433:150:0;;;;;;;-1:-1:-1;;;;;76433:150:0;;;;;;;;;;;76392:191;;76599:16;76617:17;76638:5;-1:-1:-1;;;;;76638:16:0;76655:8;76638:26;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;76598:66:0;;-1:-1:-1;76598:66:0;-1:-1:-1;76698:4:0;76683:19;;;;76679:453;;;76820:4;76810:15;;76804:22;-1:-1:-1;;;;;;76893:78:0;;-1:-1:-1;;;76893:103:0;;76863:253;;;;-1:-1:-1;;;76863:253:0;;;;;;;:::i;:::-;76679:453;;-1:-1:-1;;;;;77174:28:0;;;;;;:21;:28;;;;;;;;77203:10;77174:40;;;;;;;;;;;:153;;-1:-1:-1;;;;;;77239:43:0;;;;;;;:36;:43;;;;;;;;:53;;;;;;;;;;77317:10;77239:88;77174:153;77148:271;;;;-1:-1:-1;;;77148:271:0;;;;;;;:::i;:::-;76352:1079;;;;-1:-1:-1;;;;;77488:43:0;;;77553:1;77488:43;;;:36;:43;;;;;;;;:53;;;;;;;;;;:67;77470:241;;-1:-1:-1;;;;;77589:43:0;;;;;;:36;:43;;;;;;;;:53;;;;;;;;;77582:60;;-1:-1:-1;;;;;;77582:60:0;;;77662:37;77633:8;;77589:43;77662:37;;77589:43;;77662:37;77470:241;77774:3;-1:-1:-1;;;;;77765:12:0;:5;-1:-1:-1;;;;;77765:12:0;;77761:226;;-1:-1:-1;;;;;77801:29:0;;77833:1;77801:29;;;:22;:29;;;;;;77794:41;;-1:-1:-1;;;77794:41:0;;;;;;;;;-1:-1:-1;;;;;77850:29:0;;;;;;:22;:29;;;;;:31;;;;;;:::i;:::-;;;;-1:-1:-1;;77896:29:0;;;;:19;:29;;;;;;;;:35;;-1:-1:-1;;;;;;77896:35:0;-1:-1:-1;;;;;77896:35:0;;;;;;;;77946:27;;:22;:27;;;;;:29;;;;;;:::i;:::-;;;;;;77761:226;78023:8;78018:3;-1:-1:-1;;;;;78002:30:0;78011:5;-1:-1:-1;;;;;78002:30:0;;;;;;;;;;;75823:2217;;;:::o;60284:114::-;60344:7;60371:19;60379:3;60371:7;:19::i;67660:778::-;67735:7;-1:-1:-1;;;;;67763:17:0;;67755:65;;;;-1:-1:-1;;;67755:65:0;;;;;;;:::i;:::-;67831:10;:12;;;:10;:12;;;:::i;:::-;;;;-1:-1:-1;;67854:19:0;67876:10;;67897:32;;;:19;:32;;;;;;;;:38;;-1:-1:-1;;;;;;67897:38:0;-1:-1:-1;;;;;67897:38:0;;;;;;;;67946:27;;:22;:27;;;;;:29;;67876:10;;67946:29;;;:::i;:::-;;;;-1:-1:-1;;68087:10:0;;68037:61;;;;68078:4;;68037:61;;;:::i;:::-;;;;-1:-1:-1;;68037:61:0;;;;;;;;;68027:72;;68037:61;68027:72;;;;68019:81;68005:10;;67986:30;;:18;:30;;;;;:114;68115:23;;:27;68111:94;;68159:22;;;;:9;:22;;;;;;;;:34;;;;;;;;:::i;:::-;;68111:94;68222:38;;68248:11;;-1:-1:-1;;;;;68222:38:0;;;68239:1;;68222:38;;68239:1;;68222:38;68279:56;68310:1;68314:3;68319:11;68279:56;;;;;;;;;;;;:22;:56::i;:::-;68271:130;;;;-1:-1:-1;;;68271:130:0;;;;;;;:::i;43896:422::-;44263:20;44302:8;;;43896:422::o;96548:894::-;96684:11;96680:50;;96712:7;;96680:50;96740:20;96763:23;;;:13;:23;;;;;;;;-1:-1:-1;;;;;96763:39:0;;;;;;;;;;96835:22;;;;96813:119;;;;-1:-1:-1;;;96813:119:0;;;;;;;:::i;:::-;97009:23;97071;;;:13;:23;;;;;;;;-1:-1:-1;;;;;97071:39:0;;;;;;;;;97035:21;;;97071:57;;;;97147:20;97143:189;;97196:24;;;;:14;:24;;;;;:47;;97228:14;97196:31;:47::i;:::-;97188:128;;;;-1:-1:-1;;;97188:128:0;;;;;;;:::i;:::-;97346:77;97363:8;97389:14;-1:-1:-1;;;;;97373:32:0;97407:15;97346:16;:77::i;86658:444::-;-1:-1:-1;;;;;86858:31:0;;86777:24;86858:31;;;:15;:31;;;;;;;;:46;;;;;;;;;86937:18;86915:110;;;;-1:-1:-1;;;86915:110:0;;;;;;;:::i;:::-;87044:34;;;;:19;:34;;;;;;-1:-1:-1;;;;;87044:34:0;;-1:-1:-1;86658:444:0;;;;;;:::o;57828:152::-;57898:4;57922:50;57927:3;-1:-1:-1;;;;;57947:23:0;;57922:4;:50::i;98989:617::-;99090:21;99149:27;;;:18;:27;;;;;;;;;99132:68;;;;99178:14;;99194:5;;99132:68;;:::i;:::-;;;;-1:-1:-1;;99132:68:0;;;;;;;;;99122:79;;99132:68;99122:79;;;;99114:88;99213:27;;;:18;:27;;;;;:43;;;99122:79;-1:-1:-1;99267:332:0;99274:28;;;;:19;:28;;;;;;-1:-1:-1;;;;;99274:28:0;99314:4;99274:45;99267:332;;;99370:4;99346:30;;;;:15;:30;;;;;;;;:39;;;;;;;;;;99451:27;;;:18;:27;;;;;;;99434:93;;99346:39;;99434:93;;99451:27;;99370:4;;99513:13;;99434:93;;:::i;:::-;;;;-1:-1:-1;;99434:93:0;;;;;;;;;99424:104;;99434:93;99424:104;;;;99416:113;99544:27;;;:18;:27;;;;;:43;;;99424:104;-1:-1:-1;99267:332:0;;88370:953;88540:22;88578:21;;;:11;:21;;;;;;;;-1:-1:-1;;;;;88578:37:0;;;;;;;;;88627:1;;88578:46;;:44;:46::i;:::-;:50;;;;:::i;:::-;88647:21;;;;:11;:21;;;;;;;;-1:-1:-1;;;;;88647:37:0;;;;;;;;;88540:88;;-1:-1:-1;88647:59:0;;88692:13;88647:44;:59::i;:::-;88639:127;;;;-1:-1:-1;;;88639:127:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;88784:31:0;;;;;;:15;:31;;;;;;;;:46;;;;;;;;88777:53;88875:19;88871:168;;88919:24;;;;:14;:24;;;;;:47;;88951:14;88919:31;:47::i;:::-;88911:116;;;;-1:-1:-1;;;88911:116:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;89053:31:0;;89079:4;89053:31;89049:267;;;89162:33;;;;:18;:33;;;;;;89101:95;;89118:8;;-1:-1:-1;;;;;89128:32:0;;;89101:16;:95::i;:::-;89049:267;;;89229:75;89246:8;89272:14;-1:-1:-1;;;;;89256:32:0;89290:13;89229:16;:75::i;55780:204::-;55875:18;;55847:7;;55875:26;-1:-1:-1;55867:73:0;;;;-1:-1:-1;;;55867:73:0;;;;;;;:::i;:::-;55958:3;:11;;55970:5;55958:18;;;;;;-1:-1:-1;;;55958:18:0;;;;;;;;;;;;;;;;;55951:25;;55780:204;;;;:::o;59522:131::-;59589:4;59613:32;59618:3;59638:5;59613:4;:32::i;55327:109::-;55410:18;;55327:109::o;87521:841::-;87642:4;87668:15;:2;-1:-1:-1;;;;;87668:13:0;;:15::i;:::-;87664:691;;;87704:70;;-1:-1:-1;;;87704:70:0;;-1:-1:-1;;;;;87704:36:0;;;;;:70;;87741:10;;87753:4;;87759:7;;87768:5;;87704:70;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;87704:70:0;;;;;;;;-1:-1:-1;;87704:70:0;;;;;;;;;;;;:::i;:::-;;;87700:600;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;87948:13:0;;87944:341;;87991:60;;-1:-1:-1;;;87991:60:0;;;;;;;:::i;87944:341::-;88235:6;88229:13;88220:6;88216:2;88212:15;88205:38;87700:600;-1:-1:-1;;;;;;87825:55:0;-1:-1:-1;;;87825:55:0;;-1:-1:-1;87818:62:0;;87664:691;-1:-1:-1;88339:4:0;88332:11;;58156:158;58229:4;58253:53;58261:3;-1:-1:-1;;;;;58281:23:0;;58253:7;:53::i;52883:414::-;52946:4;52968:21;52978:3;52983:5;52968:9;:21::i;:::-;52963:327;;-1:-1:-1;53006:23:0;;;;;;;;:11;:23;;;;;;;;;;;;;53189:18;;53167:19;;;:12;;;:19;;;;;;:40;;;;53222:11;;52963:327;-1:-1:-1;53273:5:0;53266:12;;59829:137;59899:4;59923:35;59931:3;59951:5;53473:1553;53539:4;53678:19;;;:12;;;:19;;;;;;53714:15;;53710:1309;;54076:21;54100:14;54113:1;54100:10;:14;:::i;:::-;54149:18;;54076:38;;-1:-1:-1;54129:17:0;;54149:22;;54170:1;;54149:22;:::i;:::-;54129:42;;54416:17;54436:3;:11;;54448:9;54436:22;;;;;;-1:-1:-1;;;54436:22:0;;;;;;;;;;;;;;;;;54416:42;;54582:9;54553:3;:11;;54565:13;54553:26;;;;;;-1:-1:-1;;;54553:26:0;;;;;;;;;;;;;;;;;;;;:38;;;;54659:23;;;:12;;;:23;;;;;;:36;;;54820:17;;54659:3;;54820:17;;;-1:-1:-1;;;54820:17:0;;;;;;;;;;;;;;;;;;;;;;;;;;54915:3;:12;;:19;54928:5;54915:19;;;;;;;;;;;54908:26;;;54958:4;54951:11;;;;;;;;53710:1309;55002:5;54995:12;;;;;55112:129;55185:4;55209:19;;;:12;;;;;:19;;;;;;:24;;;55112:129::o;-1:-1:-1:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;14:607:1;;110:18;151:2;143:6;140:14;137:2;;;157:18;;:::i;:::-;206:2;200:9;279:2;256:17;;-1:-1:-1;;252:31:1;240:44;;286:4;236:55;306:18;;;326:22;;;303:46;300:2;;;352:18;;:::i;:::-;388:2;381:22;436;;;421:6;-1:-1:-1;421:6:1;473:16;;;470:25;-1:-1:-1;467:2:1;;;508:1;505;498:12;467:2;558:6;553:3;546:4;538:6;534:17;521:44;613:1;606:4;597:6;589;585:19;581:30;574:41;;;90:531;;;;;:::o;626:377::-;;;743:3;736:4;728:6;724:17;720:27;710:2;;768:8;758;751:26;710:2;-1:-1:-1;798:20:1;;841:18;830:30;;827:2;;;880:8;870;863:26;827:2;924:4;916:6;912:17;900:29;;976:3;969:4;960:6;952;948:19;944:30;941:39;938:2;;;993:1;990;983:12;1008:232;;1105:3;1098:4;1090:6;1086:17;1082:27;1072:2;;1127:5;1120;1113:20;1072:2;1153:81;1230:3;1221:6;1208:20;1201:4;1193:6;1189:17;1153:81;:::i;1245:259::-;;1357:2;1345:9;1336:7;1332:23;1328:32;1325:2;;;1378:6;1370;1363:22;1325:2;1422:9;1409:23;1441:33;1468:5;1441:33;:::i;1509:263::-;;1632:2;1620:9;1611:7;1607:23;1603:32;1600:2;;;1653:6;1645;1638:22;1600:2;1690:9;1684:16;1709:33;1736:5;1709:33;:::i;1777:402::-;;;1906:2;1894:9;1885:7;1881:23;1877:32;1874:2;;;1927:6;1919;1912:22;1874:2;1971:9;1958:23;1990:33;2017:5;1990:33;:::i;:::-;2042:5;-1:-1:-1;2099:2:1;2084:18;;2071:32;2112:35;2071:32;2112:35;:::i;:::-;2166:7;2156:17;;;1864:315;;;;;:::o;2184:470::-;;;;2330:2;2318:9;2309:7;2305:23;2301:32;2298:2;;;2351:6;2343;2336:22;2298:2;2395:9;2382:23;2414:33;2441:5;2414:33;:::i;:::-;2466:5;-1:-1:-1;2523:2:1;2508:18;;2495:32;2536:35;2495:32;2536:35;:::i;:::-;2288:366;;2590:7;;-1:-1:-1;;;2644:2:1;2629:18;;;;2616:32;;2288:366::o;2659:780::-;;;;;;2841:3;2829:9;2820:7;2816:23;2812:33;2809:2;;;2863:6;2855;2848:22;2809:2;2907:9;2894:23;2926:33;2953:5;2926:33;:::i;:::-;2978:5;-1:-1:-1;3035:2:1;3020:18;;3007:32;3048:35;3007:32;3048:35;:::i;:::-;3102:7;-1:-1:-1;3156:2:1;3141:18;;3128:32;;-1:-1:-1;3211:2:1;3196:18;;3183:32;3238:18;3227:30;;3224:2;;;3275:6;3267;3260:22;3224:2;3319:60;3371:7;3362:6;3351:9;3347:22;3319:60;:::i;:::-;2799:640;;;;-1:-1:-1;2799:640:1;;-1:-1:-1;3398:8:1;;3293:86;2799:640;-1:-1:-1;;;2799:640:1:o;3444:691::-;;;;;3616:3;3604:9;3595:7;3591:23;3587:33;3584:2;;;3638:6;3630;3623:22;3584:2;3682:9;3669:23;3701:33;3728:5;3701:33;:::i;:::-;3753:5;-1:-1:-1;3810:2:1;3795:18;;3782:32;3823:35;3782:32;3823:35;:::i;:::-;3877:7;-1:-1:-1;3931:2:1;3916:18;;3903:32;;-1:-1:-1;3986:2:1;3971:18;;3958:32;4013:18;4002:30;;3999:2;;;4050:6;4042;4035:22;3999:2;4078:51;4121:7;4112:6;4101:9;4097:22;4078:51;:::i;:::-;4068:61;;;3574:561;;;;;;;:::o;4140:539::-;;;;;4303:3;4291:9;4282:7;4278:23;4274:33;4271:2;;;4325:6;4317;4310:22;4271:2;4369:9;4356:23;4388:33;4415:5;4388:33;:::i;:::-;4440:5;-1:-1:-1;4497:2:1;4482:18;;4469:32;4510:35;4469:32;4510:35;:::i;:::-;4261:418;;4564:7;;-1:-1:-1;;;;4618:2:1;4603:18;;4590:32;;4669:2;4654:18;4641:32;;4261:418::o;4684:849::-;;;;;;;4883:3;4871:9;4862:7;4858:23;4854:33;4851:2;;;4905:6;4897;4890:22;4851:2;4949:9;4936:23;4968:33;4995:5;4968:33;:::i;:::-;5020:5;-1:-1:-1;5077:2:1;5062:18;;5049:32;5090:35;5049:32;5090:35;:::i;:::-;5144:7;-1:-1:-1;5198:2:1;5183:18;;5170:32;;-1:-1:-1;5249:2:1;5234:18;;5221:32;;-1:-1:-1;5304:3:1;5289:19;;5276:33;5332:18;5321:30;;5318:2;;;5369:6;5361;5354:22;5318:2;5413:60;5465:7;5456:6;5445:9;5441:22;5413:60;:::i;:::-;4841:692;;;;-1:-1:-1;4841:692:1;;-1:-1:-1;4841:692:1;;5492:8;;4841:692;-1:-1:-1;;;4841:692:1:o;5538:396::-;;;5664:2;5652:9;5643:7;5639:23;5635:32;5632:2;;;5685:6;5677;5670:22;5632:2;5729:9;5716:23;5748:33;5775:5;5748:33;:::i;:::-;5800:5;-1:-1:-1;5857:2:1;5842:18;;5829:32;5870;5829;5870;:::i;5939:619::-;;;6078:2;6066:9;6057:7;6053:23;6049:32;6046:2;;;6099:6;6091;6084:22;6046:2;6143:9;6130:23;6162:33;6189:5;6162:33;:::i;:::-;6214:5;-1:-1:-1;6270:2:1;6255:18;;6242:32;6297:18;6286:30;;6283:2;;;6334:6;6326;6319:22;6283:2;6362:22;;6415:4;6407:13;;6403:27;-1:-1:-1;6393:2:1;;6449:6;6441;6434:22;6393:2;6477:75;6544:7;6539:2;6526:16;6521:2;6517;6513:11;6477:75;:::i;:::-;6467:85;;;6036:522;;;;;:::o;6563:327::-;;;6692:2;6680:9;6671:7;6667:23;6663:32;6660:2;;;6713:6;6705;6698:22;6660:2;6757:9;6744:23;6776:33;6803:5;6776:33;:::i;:::-;6828:5;6880:2;6865:18;;;;6852:32;;-1:-1:-1;;;6650:240:1:o;6895:539::-;;;;;7058:3;7046:9;7037:7;7033:23;7029:33;7026:2;;;7080:6;7072;7065:22;7026:2;7124:9;7111:23;7143:33;7170:5;7143:33;:::i;:::-;7195:5;-1:-1:-1;7247:2:1;7232:18;;7219:32;;-1:-1:-1;7303:2:1;7288:18;;7275:32;7316:35;7275:32;7316:35;:::i;:::-;7016:418;;;;-1:-1:-1;7370:7:1;;7424:2;7409:18;7396:32;;-1:-1:-1;;7016:418:1:o;7439:636::-;;;;;7604:2;7592:9;7583:7;7579:23;7575:32;7572:2;;;7625:6;7617;7610:22;7572:2;7669:9;7656:23;7688:33;7715:5;7688:33;:::i;:::-;7740:5;-1:-1:-1;7792:2:1;7777:18;;7764:32;;-1:-1:-1;7847:2:1;7832:18;;7819:32;7874:18;7863:30;;7860:2;;;7911:6;7903;7896:22;7860:2;7955:60;8007:7;7998:6;7987:9;7983:22;7955:60;:::i;:::-;7562:513;;;;-1:-1:-1;8034:8:1;-1:-1:-1;;;;7562:513:1:o;8080:547::-;;;;8235:2;8223:9;8214:7;8210:23;8206:32;8203:2;;;8256:6;8248;8241:22;8203:2;8300:9;8287:23;8319:33;8346:5;8319:33;:::i;:::-;8371:5;-1:-1:-1;8423:2:1;8408:18;;8395:32;;-1:-1:-1;8478:2:1;8463:18;;8450:32;8505:18;8494:30;;8491:2;;;8542:6;8534;8527:22;8491:2;8570:51;8613:7;8604:6;8593:9;8589:22;8570:51;:::i;:::-;8560:61;;;8193:434;;;;;:::o;8632:257::-;;8752:2;8740:9;8731:7;8727:23;8723:32;8720:2;;;8773:6;8765;8758:22;8720:2;8810:9;8804:16;8829:30;8853:5;8829:30;:::i;8894:257::-;;9005:2;8993:9;8984:7;8980:23;8976:32;8973:2;;;9026:6;9018;9011:22;8973:2;9070:9;9057:23;9089:32;9115:5;9089:32;:::i;9156:261::-;;9278:2;9266:9;9257:7;9253:23;9249:32;9246:2;;;9299:6;9291;9284:22;9246:2;9336:9;9330:16;9355:32;9381:5;9355:32;:::i;9422:190::-;;9534:2;9522:9;9513:7;9509:23;9505:32;9502:2;;;9555:6;9547;9540:22;9502:2;-1:-1:-1;9583:23:1;;9492:120;-1:-1:-1;9492:120:1:o;9617:327::-;;;9746:2;9734:9;9725:7;9721:23;9717:32;9714:2;;;9767:6;9759;9752:22;9714:2;9808:9;9795:23;9785:33;;9868:2;9857:9;9853:18;9840:32;9881:33;9908:5;9881:33;:::i;9949:539::-;;;;;10112:3;10100:9;10091:7;10087:23;10083:33;10080:2;;;10134:6;10126;10119:22;10080:2;10175:9;10162:23;10152:33;;10235:2;10224:9;10220:18;10207:32;10248:33;10275:5;10248:33;:::i;:::-;10300:5;-1:-1:-1;10357:2:1;10342:18;;10329:32;10370:35;10329:32;10370:35;:::i;10493:760::-;;;;;;10682:3;10670:9;10661:7;10657:23;10653:33;10650:2;;;10704:6;10696;10689:22;10650:2;10745:9;10732:23;10722:33;;10805:2;10794:9;10790:18;10777:32;10818:33;10845:5;10818:33;:::i;:::-;10870:5;-1:-1:-1;10927:2:1;10912:18;;10899:32;10940:35;10899:32;10940:35;:::i;:::-;10994:7;-1:-1:-1;11048:2:1;11033:18;;11020:32;;-1:-1:-1;11103:3:1;11088:19;;11075:33;11131:18;11120:30;;11117:2;;;11168:6;11160;11153:22;11117:2;11196:51;11239:7;11230:6;11219:9;11215:22;11196:51;:::i;:::-;11186:61;;;10640:613;;;;;;;;:::o;11258:395::-;;;;11404:2;11392:9;11383:7;11379:23;11375:32;11372:2;;;11425:6;11417;11410:22;11372:2;11466:9;11453:23;11443:33;;11526:2;11515:9;11511:18;11498:32;11539:33;11566:5;11539:33;:::i;11658:829::-;;;;;;;11864:3;11852:9;11843:7;11839:23;11835:33;11832:2;;;11886:6;11878;11871:22;11832:2;11927:9;11914:23;11904:33;;11987:2;11976:9;11972:18;11959:32;12000:33;12027:5;12000:33;:::i;:::-;12052:5;-1:-1:-1;12104:2:1;12089:18;;12076:32;;-1:-1:-1;12160:2:1;12145:18;;12132:32;12173:35;12132:32;12173:35;:::i;:::-;12227:7;-1:-1:-1;12281:3:1;12266:19;;12253:33;;-1:-1:-1;12337:3:1;12322:19;;12309:33;12365:18;12354:30;;12351:2;;;12402:6;12394;12387:22;12351:2;12430:51;12473:7;12464:6;12453:9;12449:22;12430:51;:::i;:::-;12420:61;;;11822:665;;;;;;;;:::o;12492:258::-;;;12621:2;12609:9;12600:7;12596:23;12592:32;12589:2;;;12642:6;12634;12627:22;12589:2;-1:-1:-1;;12670:23:1;;;12740:2;12725:18;;;12712:32;;-1:-1:-1;12579:171:1:o;12755:259::-;;12836:5;12830:12;12863:6;12858:3;12851:19;12879:63;12935:6;12928:4;12923:3;12919:14;12912:4;12905:5;12901:16;12879:63;:::i;:::-;12996:2;12975:15;-1:-1:-1;;12971:29:1;12962:39;;;;13003:4;12958:50;;12806:208;-1:-1:-1;;12806:208:1:o;13019:274::-;;13186:6;13180:13;13202:53;13248:6;13243:3;13236:4;13228:6;13224:17;13202:53;:::i;:::-;13271:16;;;;;13156:137;-1:-1:-1;;13156:137:1:o;13298:247::-;13455:19;;;13499:2;13490:12;;13483:28;13536:2;13527:12;;13445:100::o;13550:312::-;13735:19;;;13779:2;13770:12;;13763:28;;;;13816:2;13807:12;;13800:28;13853:2;13844:12;;13725:137::o;13867:203::-;-1:-1:-1;;;;;14031:32:1;;;;14013:51;;14001:2;13986:18;;13968:102::o;14075:304::-;-1:-1:-1;;;;;14305:15:1;;;14287:34;;14357:15;;14352:2;14337:18;;14330:43;14237:2;14222:18;;14204:175::o;14384:375::-;-1:-1:-1;;;;;14642:15:1;;;14624:34;;14694:15;;;;14689:2;14674:18;;14667:43;14741:2;14726:18;;14719:34;;;;14574:2;14559:18;;14541:218::o;14764:490::-;-1:-1:-1;;;;;15033:15:1;;;15015:34;;15085:15;;15080:2;15065:18;;15058:43;15132:2;15117:18;;15110:34;;;15180:3;15175:2;15160:18;;15153:31;;;14764:490;;15201:47;;15228:19;;15220:6;15201:47;:::i;:::-;15193:55;14967:287;-1:-1:-1;;;;;;14967:287:1:o;15259:558::-;-1:-1:-1;;;;;15582:15:1;;;15564:34;;15634:15;;;;15629:2;15614:18;;15607:43;15681:2;15666:18;;15659:34;;;;15729:3;15724:2;15709:18;;15702:31;;;15259:558;15749:19;;;15742:33;15544:3;15792:19;;15516:301::o;15822:562::-;-1:-1:-1;;;;;16119:15:1;;;16101:34;;16171:15;;16166:2;16151:18;;16144:43;16218:2;16203:18;;16196:34;;;16261:2;16246:18;;16239:34;;;16081:3;16304;16289:19;;16282:32;;;15822:562;;16331:47;;16358:19;;16350:6;16331:47;:::i;:::-;16323:55;16053:331;-1:-1:-1;;;;;;;16053:331:1:o;16389:274::-;-1:-1:-1;;;;;16581:32:1;;;;16563:51;;16645:2;16630:18;;16623:34;16551:2;16536:18;;16518:145::o;16668:387::-;;16900:1;16896;16891:3;16887:11;16883:19;16875:6;16871:32;16860:9;16853:51;16940:6;16935:2;16924:9;16920:18;16913:34;16983:2;16978;16967:9;16963:18;16956:30;17003:46;17045:2;17034:9;17030:18;17022:6;17003:46;:::i;:::-;16995:54;16843:212;-1:-1:-1;;;;;16843:212:1:o;17060:187::-;17225:14;;17218:22;17200:41;;17188:2;17173:18;;17155:92::o;17252:177::-;17398:25;;;17386:2;17371:18;;17353:76::o;17687:202::-;-1:-1:-1;;;;;;17849:33:1;;;;17831:52;;17819:2;17804:18;;17786:103::o;18199:221::-;;18348:2;18337:9;18330:21;18368:46;18410:2;18399:9;18395:18;18387:6;18368:46;:::i;18425:420::-;18627:2;18609:21;;;18666:2;18646:18;;;18639:30;18705:34;18700:2;18685:18;;18678:62;18776:26;18771:2;18756:18;;18749:54;18835:3;18820:19;;18599:246::o;18850:415::-;19052:2;19034:21;;;19091:2;19071:18;;;19064:30;-1:-1:-1;;;;;;;;;;;19125:2:1;19110:18;;19103:62;-1:-1:-1;;;19196:2:1;19181:18;;19174:49;19255:3;19240:19;;19024:241::o;19270:414::-;19472:2;19454:21;;;19511:2;19491:18;;;19484:30;19550:34;19545:2;19530:18;;19523:62;-1:-1:-1;;;19616:2:1;19601:18;;19594:48;19674:3;19659:19;;19444:240::o;19689:398::-;19891:2;19873:21;;;19930:2;19910:18;;;19903:30;19969:34;19964:2;19949:18;;19942:62;-1:-1:-1;;;20035:2:1;20020:18;;20013:32;20077:3;20062:19;;19863:224::o;20092:480::-;20294:2;20276:21;;;20333:2;20313:18;;;20306:30;20372:34;20367:2;20352:18;;20345:62;20443:34;20438:2;20423:18;;20416:62;-1:-1:-1;;;20509:3:1;20494:19;;20487:43;20562:3;20547:19;;20266:306::o;20577:414::-;20779:2;20761:21;;;20818:2;20798:18;;;20791:30;20857:34;20852:2;20837:18;;20830:62;-1:-1:-1;;;20923:2:1;20908:18;;20901:48;20981:3;20966:19;;20751:240::o;20996:411::-;21198:2;21180:21;;;21237:2;21217:18;;;21210:30;21276:34;21271:2;21256:18;;21249:62;-1:-1:-1;;;21342:2:1;21327:18;;21320:45;21397:3;21382:19;;21170:237::o;21412:412::-;21614:2;21596:21;;;21653:2;21633:18;;;21626:30;21692:34;21687:2;21672:18;;21665:62;-1:-1:-1;;;21758:2:1;21743:18;;21736:46;21814:3;21799:19;;21586:238::o;21829:413::-;22031:2;22013:21;;;22070:2;22050:18;;;22043:30;-1:-1:-1;;;;;;;;;;;22104:2:1;22089:18;;22082:62;-1:-1:-1;;;22175:2:1;22160:18;;22153:47;22232:3;22217:19;;22003:239::o;22247:405::-;22449:2;22431:21;;;22488:2;22468:18;;;22461:30;22527:34;22522:2;22507:18;;22500:62;-1:-1:-1;;;22593:2:1;22578:18;;22571:39;22642:3;22627:19;;22421:231::o;22657:417::-;22859:2;22841:21;;;22898:2;22878:18;;;22871:30;-1:-1:-1;;;;;;;;;;;22932:2:1;22917:18;;22910:62;-1:-1:-1;;;23003:2:1;22988:18;;22981:51;23064:3;23049:19;;22831:243::o;23079:414::-;23281:2;23263:21;;;23320:2;23300:18;;;23293:30;23359:34;23354:2;23339:18;;23332:62;-1:-1:-1;;;23425:2:1;23410:18;;23403:48;23483:3;23468:19;;23253:240::o;23498:553::-;23700:2;23682:21;;;23739:3;23719:18;;;23712:31;-1:-1:-1;;;;;;;;;;;23774:2:1;23759:18;;23752:62;23850:34;23845:2;23830:18;;23823:62;23922:34;23916:3;23901:19;;23894:63;-1:-1:-1;;;23988:3:1;23973:19;;23966:43;24041:3;24026:19;;23672:379::o;24056:426::-;24258:2;24240:21;;;24297:2;24277:18;;;24270:30;24336:34;24331:2;24316:18;;24309:62;24407:32;24402:2;24387:18;;24380:60;24472:3;24457:19;;24230:252::o;24487:420::-;24689:2;24671:21;;;24728:2;24708:18;;;24701:30;24767:34;24762:2;24747:18;;24740:62;24838:26;24833:2;24818:18;;24811:54;24897:3;24882:19;;24661:246::o;24912:500::-;25114:2;25096:21;;;25153:2;25133:18;;;25126:30;;;25192:34;25187:2;25172:18;;25165:62;25263:34;25243:18;;;25236:62;25335:34;25329:3;25314:19;;25307:63;25402:3;25387:19;;25086:326::o;25417:407::-;25619:2;25601:21;;;25658:2;25638:18;;;25631:30;25697:34;25692:2;25677:18;;25670:62;-1:-1:-1;;;25763:2:1;25748:18;;25741:41;25814:3;25799:19;;25591:233::o;25829:417::-;26031:2;26013:21;;;26070:2;26050:18;;;26043:30;26109:34;26104:2;26089:18;;26082:62;-1:-1:-1;;;26175:2:1;26160:18;;26153:51;26236:3;26221:19;;26003:243::o;26251:424::-;26453:2;26435:21;;;26492:2;26472:18;;;26465:30;-1:-1:-1;;;;;;;;;;;26526:2:1;26511:18;;26504:62;26602:30;26597:2;26582:18;;26575:58;26665:3;26650:19;;26425:250::o;26680:471::-;26882:2;26864:21;;;26921:2;26901:18;;;26894:30;26960:34;26955:2;26940:18;;26933:62;27031:34;27026:2;27011:18;;27004:62;-1:-1:-1;;;27097:3:1;27082:19;;27075:34;27141:3;27126:19;;26854:297::o;27156:413::-;27358:2;27340:21;;;27397:2;27377:18;;;27370:30;27436:34;27431:2;27416:18;;27409:62;-1:-1:-1;;;27502:2:1;27487:18;;27480:47;27559:3;27544:19;;27330:239::o;27574:399::-;27776:2;27758:21;;;27815:2;27795:18;;;27788:30;27854:34;27849:2;27834:18;;27827:62;-1:-1:-1;;;27920:2:1;27905:18;;27898:33;27963:3;27948:19;;27748:225::o;27978:415::-;28180:2;28162:21;;;28219:2;28199:18;;;28192:30;28258:34;28253:2;28238:18;;28231:62;-1:-1:-1;;;28324:2:1;28309:18;;28302:49;28383:3;28368:19;;28152:241::o;28398:414::-;28600:2;28582:21;;;28639:2;28619:18;;;28612:30;-1:-1:-1;;;;;;;;;;;28673:2:1;28658:18;;28651:62;-1:-1:-1;;;28744:2:1;28729:18;;28722:48;28802:3;28787:19;;28572:240::o;28817:420::-;29019:2;29001:21;;;29058:2;29038:18;;;29031:30;-1:-1:-1;;;;;;;;;;;29092:2:1;29077:18;;29070:62;29168:26;29163:2;29148:18;;29141:54;29227:3;29212:19;;28991:246::o;29242:421::-;29444:2;29426:21;;;29483:2;29463:18;;;29456:30;-1:-1:-1;;;;;;;;;;;29517:2:1;29502:18;;29495:62;29593:27;29588:2;29573:18;;29566:55;29653:3;29638:19;;29416:247::o;29668:476::-;29870:2;29852:21;;;29909:2;29889:18;;;29882:30;-1:-1:-1;;;;;;;;;;;29943:2:1;29928:18;;29921:62;30019:34;30014:2;29999:18;;29992:62;-1:-1:-1;;;30085:3:1;30070:19;;30063:39;30134:3;30119:19;;29842:302::o;30149:420::-;30351:2;30333:21;;;30390:2;30370:18;;;30363:30;30429:34;30424:2;30409:18;;30402:62;30500:26;30495:2;30480:18;;30473:54;30559:3;30544:19;;30323:246::o;30574:421::-;30776:2;30758:21;;;30815:2;30795:18;;;30788:30;30854:34;30849:2;30834:18;;30827:62;30925:27;30920:2;30905:18;;30898:55;30985:3;30970:19;;30748:247::o;31000:420::-;31202:2;31184:21;;;31241:2;31221:18;;;31214:30;31280:34;31275:2;31260:18;;31253:62;31351:26;31346:2;31331:18;;31324:54;31410:3;31395:19;;31174:246::o;31425:412::-;31627:2;31609:21;;;31666:2;31646:18;;;31639:30;31705:34;31700:2;31685:18;;31678:62;-1:-1:-1;;;31771:2:1;31756:18;;31749:46;31827:3;31812:19;;31599:238::o;31842:425::-;32044:2;32026:21;;;32083:2;32063:18;;;32056:30;32122:34;32117:2;32102:18;;32095:62;32193:31;32188:2;32173:18;;32166:59;32257:3;32242:19;;32016:251::o;32272:411::-;32474:2;32456:21;;;32513:2;32493:18;;;32486:30;32552:34;32547:2;32532:18;;32525:62;-1:-1:-1;;;32618:2:1;32603:18;;32596:45;32673:3;32658:19;;32446:237::o;32688:415::-;32890:2;32872:21;;;32929:2;32909:18;;;32902:30;32968:34;32963:2;32948:18;;32941:62;-1:-1:-1;;;33034:2:1;33019:18;;33012:49;33093:3;33078:19;;32862:241::o;33108:423::-;33310:2;33292:21;;;33349:2;33329:18;;;33322:30;33388:34;33383:2;33368:18;;33361:62;33459:29;33454:2;33439:18;;33432:57;33521:3;33506:19;;33282:249::o;33536:553::-;33738:2;33720:21;;;33777:3;33757:18;;;33750:31;-1:-1:-1;;;;;;;;;;;33812:2:1;33797:18;;33790:62;33888:34;33883:2;33868:18;;33861:62;33960:34;33954:3;33939:19;;33932:63;-1:-1:-1;;;34026:3:1;34011:19;;34004:43;34079:3;34064:19;;33710:379::o;34094:420::-;34296:2;34278:21;;;34335:2;34315:18;;;34308:30;34374:34;34369:2;34354:18;;34347:62;34445:26;34440:2;34425:18;;34418:54;34504:3;34489:19;;34268:246::o;34519:405::-;34721:2;34703:21;;;34760:2;34740:18;;;34733:30;34799:34;34794:2;34779:18;;34772:62;-1:-1:-1;;;34865:2:1;34850:18;;34843:39;34914:3;34899:19;;34693:231::o;34929:425::-;35131:2;35113:21;;;35170:2;35150:18;;;35143:30;35209:34;35204:2;35189:18;;35182:62;35280:31;35275:2;35260:18;;35253:59;35344:3;35329:19;;35103:251::o;35359:406::-;35561:2;35543:21;;;35600:2;35580:18;;;35573:30;35639:34;35634:2;35619:18;;35612:62;-1:-1:-1;;;35705:2:1;35690:18;;35683:40;35755:3;35740:19;;35533:232::o;35770:405::-;35972:2;35954:21;;;36011:2;35991:18;;;35984:30;36050:34;36045:2;36030:18;;36023:62;-1:-1:-1;;;36116:2:1;36101:18;;36094:39;36165:3;36150:19;;35944:231::o;36180:424::-;36382:2;36364:21;;;36421:2;36401:18;;;36394:30;-1:-1:-1;;;;;;;;;;;36455:2:1;36440:18;;36433:62;36531:30;36526:2;36511:18;;36504:58;36594:3;36579:19;;36354:250::o;36609:480::-;36811:2;36793:21;;;36850:2;36830:18;;;36823:30;36889:34;36884:2;36869:18;;36862:62;36960:34;36955:2;36940:18;;36933:62;-1:-1:-1;;;37026:3:1;37011:19;;37004:43;37079:3;37064:19;;36783:306::o;37094:419::-;37296:2;37278:21;;;37335:2;37315:18;;;37308:30;37374:34;37369:2;37354:18;;37347:62;37445:25;37440:2;37425:18;;37418:53;37503:3;37488:19;;37268:245::o;37518:480::-;37720:2;37702:21;;;37759:2;37739:18;;;37732:30;-1:-1:-1;;;;;;;;;;;37793:2:1;37778:18;;37771:62;37869:34;37864:2;37849:18;;37842:62;-1:-1:-1;;;37935:3:1;37920:19;;37913:43;37988:3;37973:19;;37692:306::o;38003:414::-;38205:2;38187:21;;;38244:2;38224:18;;;38217:30;38283:34;38278:2;38263:18;;38256:62;-1:-1:-1;;;38349:2:1;38334:18;;38327:48;38407:3;38392:19;;38177:240::o;38422:419::-;38624:2;38606:21;;;38663:2;38643:18;;;38636:30;38702:34;38697:2;38682:18;;38675:62;38773:25;38768:2;38753:18;;38746:53;38831:3;38816:19;;38596:245::o;38846:472::-;39048:2;39030:21;;;39087:2;39067:18;;;39060:30;39126:34;39121:2;39106:18;;39099:62;39197:34;39192:2;39177:18;;39170:62;-1:-1:-1;;;39263:3:1;39248:19;;39241:35;39308:3;39293:19;;39020:298::o;39323:397::-;39525:2;39507:21;;;39564:2;39544:18;;;39537:30;39603:34;39598:2;39583:18;;39576:62;-1:-1:-1;;;39669:2:1;39654:18;;39647:31;39710:3;39695:19;;39497:223::o;39725:422::-;39927:2;39909:21;;;39966:2;39946:18;;;39939:30;40005:34;40000:2;39985:18;;39978:62;40076:28;40071:2;40056:18;;40049:56;40137:3;40122:19;;39899:248::o;40152:405::-;40354:2;40336:21;;;40393:2;40373:18;;;40366:30;40432:34;40427:2;40412:18;;40405:62;-1:-1:-1;;;40498:2:1;40483:18;;40476:39;40547:3;40532:19;;40326:231::o;40562:415::-;40764:2;40746:21;;;40803:2;40783:18;;;40776:30;40842:34;40837:2;40822:18;;40815:62;-1:-1:-1;;;40908:2:1;40893:18;;40886:49;40967:3;40952:19;;40736:241::o;40982:412::-;41184:2;41166:21;;;41223:2;41203:18;;;41196:30;41262:34;41257:2;41242:18;;41235:62;-1:-1:-1;;;41328:2:1;41313:18;;41306:46;41384:3;41369:19;;41156:238::o;41399:412::-;41601:2;41583:21;;;41640:2;41620:18;;;41613:30;-1:-1:-1;;;;;;;;;;;41674:2:1;41659:18;;41652:62;-1:-1:-1;;;41745:2:1;41730:18;;41723:46;41801:3;41786:19;;41573:238::o;41816:413::-;42018:2;42000:21;;;42057:2;42037:18;;;42030:30;42096:34;42091:2;42076:18;;42069:62;-1:-1:-1;;;42162:2:1;42147:18;;42140:47;42219:3;42204:19;;41990:239::o;42234:408::-;42436:2;42418:21;;;42475:2;42455:18;;;42448:30;42514:34;42509:2;42494:18;;42487:62;-1:-1:-1;;;42580:2:1;42565:18;;42558:42;42632:3;42617:19;;42408:234::o;42829:128::-;;42900:1;42896:6;42893:1;42890:13;42887:2;;;42906:18;;:::i;:::-;-1:-1:-1;42942:9:1;;42877:80::o;42962:168::-;;43068:1;43064;43060:6;43056:14;43053:1;43050:21;43045:1;43038:9;43031:17;43027:45;43024:2;;;43075:18;;:::i;:::-;-1:-1:-1;43115:9:1;;43014:116::o;43135:125::-;;43203:1;43200;43197:8;43194:2;;;43208:18;;:::i;:::-;-1:-1:-1;43245:9:1;;43184:76::o;43265:258::-;43337:1;43347:113;43361:6;43358:1;43355:13;43347:113;;;43437:11;;;43431:18;43418:11;;;43411:39;43383:2;43376:10;43347:113;;;43478:6;43475:1;43472:13;43469:2;;;-1:-1:-1;;43513:1:1;43495:16;;43488:27;43318:205::o;43528:136::-;;43595:5;43585:2;;43604:18;;:::i;:::-;-1:-1:-1;;;43640:18:1;;43575:89::o;43669:380::-;43754:1;43744:12;;43801:1;43791:12;;;43812:2;;43866:4;43858:6;43854:17;43844:27;;43812:2;43919;43911:6;43908:14;43888:18;43885:38;43882:2;;;43965:10;43960:3;43956:20;43953:1;43946:31;44000:4;43997:1;43990:15;44028:4;44025:1;44018:15;43882:2;;43724:325;;;:::o;44054:135::-;;-1:-1:-1;;44114:17:1;;44111:2;;;44134:18;;:::i;:::-;-1:-1:-1;44181:1:1;44170:13;;44101:88::o;44194:127::-;44255:10;44250:3;44246:20;44243:1;44236:31;44286:4;44283:1;44276:15;44310:4;44307:1;44300:15;44326:127;44387:10;44382:3;44378:20;44375:1;44368:31;44418:4;44415:1;44408:15;44442:4;44439:1;44432:15;44458:133;-1:-1:-1;;;;;44535:31:1;;44525:42;;44515:2;;44581:1;44578;44571:12;44515:2;44505:86;:::o;44596:120::-;44684:5;44677:13;44670:21;44663:5;44660:32;44650:2;;44706:1;44703;44696:12;44721:133;-1:-1:-1;;;;;;44797:32:1;;44787:43;;44777:2;;44844:1;44841;44834:12

Swarm Source

ipfs://15ff459bc4f58905da537b06bee1b19459690784b7679a4f977b1eebacd46b3d
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.