More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 27 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Transfer ERC20 | 14320204 | 1083 days ago | IN | 0 ETH | 0.00152442 | ||||
Transfer ERC20 | 14320202 | 1083 days ago | IN | 0 ETH | 0.00188801 | ||||
Transfer ERC20 | 14320191 | 1083 days ago | IN | 0 ETH | 0.00234651 | ||||
Transfer ERC20 | 14320191 | 1083 days ago | IN | 0 ETH | 0.00234651 | ||||
Transfer ERC20 | 14320185 | 1083 days ago | IN | 0 ETH | 0.00222464 | ||||
Safe Transfer Ch... | 13773331 | 1167 days ago | IN | 0 ETH | 0.01118427 | ||||
Transfer ERC20 | 13773299 | 1167 days ago | IN | 0 ETH | 0.00609838 | ||||
Get ERC20 | 13685840 | 1181 days ago | IN | 0 ETH | 0.01717376 | ||||
Get Child | 13685792 | 1181 days ago | IN | 0 ETH | 0.03550408 | ||||
Get ERC20 | 13685673 | 1181 days ago | IN | 0 ETH | 0.01003722 | ||||
Get ERC20 | 13685643 | 1181 days ago | IN | 0 ETH | 0.01628708 | ||||
Get Child | 13685635 | 1181 days ago | IN | 0 ETH | 0.02696617 | ||||
Get ERC20 | 13685532 | 1181 days ago | IN | 0 ETH | 0.01892474 | ||||
Get ERC20 | 13685529 | 1181 days ago | IN | 0 ETH | 0.01933712 | ||||
Get ERC20 | 13685527 | 1181 days ago | IN | 0 ETH | 0.02126565 | ||||
Get ERC20 | 13685525 | 1181 days ago | IN | 0 ETH | 0.01704895 | ||||
Safe Mint | 13685482 | 1181 days ago | IN | 0 ETH | 0.01057291 | ||||
Safe Mint | 13685482 | 1181 days ago | IN | 0 ETH | 0.01057291 | ||||
Safe Mint | 13685482 | 1181 days ago | IN | 0 ETH | 0.01057291 | ||||
Safe Mint | 13685482 | 1181 days ago | IN | 0 ETH | 0.01057291 | ||||
Get ERC20 | 13685474 | 1181 days ago | IN | 0 ETH | 0.00657377 | ||||
Get ERC20 | 13685456 | 1181 days ago | IN | 0 ETH | 0.01380922 | ||||
Safe Transfer Fr... | 13685437 | 1181 days ago | IN | 0 ETH | 0.00507304 | ||||
Set Approval For... | 13685327 | 1181 days ago | IN | 0 ETH | 0.00603776 | ||||
Get Child | 13685240 | 1181 days ago | IN | 0 ETH | 0.02615442 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
ComposableTopDown
Compiler Version
v0.8.0+commit.c7dfd78e
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
- No Contract Security Audit Submitted- Submit Audit Here
[{"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"}]
Contract Creation Code
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
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $0.00171 | 800 | $1.37 |
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.