Contract is not verified. However, we found a verified contract with the same bytecode in Blockscout DB 0x124213ac05c34e8ad3f1d2ca3084ca6f393e6b49.
All metadata displayed below is from that contract. In order to verify current contract, click Verify & Publish button
Verify & Publish
All metadata displayed below is from that contract. In order to verify current contract, click Verify & Publish button
- Contract name:
- RegistryExtended
- Optimization enabled
- true
- Compiler version
- v0.8.4+commit.c7e474f2
- Optimization runs
- 200
- Verified at
- 2021-12-23T17:31:40.335670Z
Contract source code
// File: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.3.3/contracts/utils/Context.sol pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } } // File: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.3.3/contracts/utils/Address.sol 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; assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } } // File: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.3.3/contracts/utils/introspection/IERC165.sol 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: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.3.3/contracts/utils/introspection/ERC165.sol 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: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.3.3/contracts/token/ERC1155/IERC1155Receiver.sol pragma solidity ^0.8.0; /** * @dev _Available since v3.1._ */ interface IERC1155Receiver is IERC165 { /** @dev Handles the receipt of a single ERC1155 token type. This function is called at the end of a `safeTransferFrom` after the balance has been updated. To accept the transfer, this must return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` (i.e. 0xf23a6e61, or its own function selector). @param operator The address which initiated the transfer (i.e. msg.sender) @param from The address which previously owned the token @param id The ID of the token being transferred @param value The amount of tokens being transferred @param data Additional data with no specified format @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed */ function onERC1155Received( address operator, address from, uint256 id, uint256 value, bytes calldata data ) external returns (bytes4); /** @dev Handles the receipt of a multiple ERC1155 token types. This function is called at the end of a `safeBatchTransferFrom` after the balances have been updated. To accept the transfer(s), this must return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` (i.e. 0xbc197c81, or its own function selector). @param operator The address which initiated the batch transfer (i.e. msg.sender) @param from The address which previously owned the token @param ids An array containing ids of each token being transferred (order and length must match values array) @param values An array containing amounts of each token being transferred (order and length must match ids array) @param data Additional data with no specified format @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed */ function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external returns (bytes4); } // File: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.3.3/contracts/token/ERC1155/IERC1155.sol pragma solidity ^0.8.0; /** * @dev Required interface of an ERC1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[EIP]. * * _Available since v3.1._ */ interface IERC1155 is IERC165 { /** * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`. */ event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); /** * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all * transfers. */ event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); /** * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to * `approved`. */ event ApprovalForAll(address indexed account, address indexed operator, bool approved); /** * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. * * If an {URI} event was emitted for `id`, the standard * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value * returned by {IERC1155MetadataURI-uri}. */ event URI(string value, uint256 indexed id); /** * @dev Returns the amount of tokens of token type `id` owned by `account`. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory); /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the caller. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) external; } // File: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.3.3/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol pragma solidity ^0.8.0; /** * @dev Interface of the optional ERC1155MetadataExtension interface, as defined * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP]. * * _Available since v3.1._ */ interface IERC1155MetadataURI is IERC1155 { /** * @dev Returns the URI for token type `id`. * * If the `\{id\}` substring is present in the URI, it must be replaced by * clients with the actual token type ID. */ function uri(uint256 id) external view returns (string memory); } // File: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.3.3/contracts/token/ERC1155/ERC1155.sol pragma solidity ^0.8.0; /** * @dev Implementation of the basic standard multi-token. * See https://eips.ethereum.org/EIPS/eip-1155 * Originally based on code by Enjin: https://github.com/enjin/erc-1155 * * _Available since v3.1._ */ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI { using Address for address; // Mapping from token ID to account balances mapping(uint256 => mapping(address => uint256)) private _balances; // Mapping from account to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json string private _uri; /** * @dev See {_setURI}. */ constructor(string memory uri_) { _setURI(uri_); } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC1155).interfaceId || interfaceId == type(IERC1155MetadataURI).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC1155MetadataURI-uri}. * * This implementation returns the same URI for *all* token types. It relies * on the token type ID substitution mechanism * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. * * Clients calling this function must replace the `\{id\}` substring with the * actual token type ID. */ function uri(uint256) public view virtual override returns (string memory) { return _uri; } /** * @dev See {IERC1155-balanceOf}. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) public view virtual override returns (uint256) { require(account != address(0), "ERC1155: balance query for the zero address"); return _balances[id][account]; } /** * @dev See {IERC1155-balanceOfBatch}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch(address[] memory accounts, uint256[] memory ids) public view virtual override returns (uint256[] memory) { require(accounts.length == ids.length, "ERC1155: accounts and ids length mismatch"); uint256[] memory batchBalances = new uint256[](accounts.length); for (uint256 i = 0; i < accounts.length; ++i) { batchBalances[i] = balanceOf(accounts[i], ids[i]); } return batchBalances; } /** * @dev See {IERC1155-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { require(_msgSender() != operator, "ERC1155: setting approval status for self"); _operatorApprovals[_msgSender()][operator] = approved; emit ApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC1155-isApprovedForAll}. */ function isApprovedForAll(address account, address operator) public view virtual override returns (bool) { return _operatorApprovals[account][operator]; } /** * @dev See {IERC1155-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes memory data ) public virtual override { require( from == _msgSender() || isApprovedForAll(from, _msgSender()), "ERC1155: caller is not owner nor approved" ); _safeTransferFrom(from, to, id, amount, data); } /** * @dev See {IERC1155-safeBatchTransferFrom}. */ function safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) public virtual override { require( from == _msgSender() || isApprovedForAll(from, _msgSender()), "ERC1155: transfer caller is not owner nor approved" ); _safeBatchTransferFrom(from, to, ids, amounts, data); } /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function _safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes memory data ) internal virtual { require(to != address(0), "ERC1155: transfer to the zero address"); address operator = _msgSender(); _beforeTokenTransfer(operator, from, to, _asSingletonArray(id), _asSingletonArray(amount), data); uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: insufficient balance for transfer"); unchecked { _balances[id][from] = fromBalance - amount; } _balances[id][to] += amount; emit TransferSingle(operator, from, to, id, amount); _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function _safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); require(to != address(0), "ERC1155: transfer to the zero address"); address operator = _msgSender(); _beforeTokenTransfer(operator, from, to, ids, amounts, data); for (uint256 i = 0; i < ids.length; ++i) { uint256 id = ids[i]; uint256 amount = amounts[i]; uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: insufficient balance for transfer"); unchecked { _balances[id][from] = fromBalance - amount; } _balances[id][to] += amount; } emit TransferBatch(operator, from, to, ids, amounts); _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data); } /** * @dev Sets a new URI for all token types, by relying on the token type ID * substitution mechanism * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. * * By this mechanism, any occurrence of the `\{id\}` substring in either the * URI or any of the amounts in the JSON file at said URI will be replaced by * clients with the token type ID. * * For example, the `https://token-cdn-domain/\{id\}.json` URI would be * interpreted by clients as * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json` * for token type ID 0x4cce0. * * See {uri}. * * Because these URIs cannot be meaningfully represented by the {URI} event, * this function emits no events. */ function _setURI(string memory newuri) internal virtual { _uri = newuri; } /** * @dev Creates `amount` tokens of token type `id`, and assigns them to `account`. * * Emits a {TransferSingle} event. * * Requirements: * * - `account` cannot be the zero address. * - If `account` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function _mint( address account, uint256 id, uint256 amount, bytes memory data ) internal virtual { require(account != address(0), "ERC1155: mint to the zero address"); address operator = _msgSender(); _beforeTokenTransfer(operator, address(0), account, _asSingletonArray(id), _asSingletonArray(amount), data); _balances[id][account] += amount; emit TransferSingle(operator, address(0), account, id, amount); _doSafeTransferAcceptanceCheck(operator, address(0), account, id, amount, data); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function _mintBatch( address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { require(to != address(0), "ERC1155: mint to the zero address"); require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); address operator = _msgSender(); _beforeTokenTransfer(operator, address(0), to, ids, amounts, data); for (uint256 i = 0; i < ids.length; i++) { _balances[ids[i]][to] += amounts[i]; } emit TransferBatch(operator, address(0), to, ids, amounts); _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data); } /** * @dev Destroys `amount` tokens of token type `id` from `account` * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens of token type `id`. */ function _burn( address account, uint256 id, uint256 amount ) internal virtual { require(account != address(0), "ERC1155: burn from the zero address"); address operator = _msgSender(); _beforeTokenTransfer(operator, account, address(0), _asSingletonArray(id), _asSingletonArray(amount), ""); uint256 accountBalance = _balances[id][account]; require(accountBalance >= amount, "ERC1155: burn amount exceeds balance"); unchecked { _balances[id][account] = accountBalance - amount; } emit TransferSingle(operator, account, address(0), id, amount); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}. * * Requirements: * * - `ids` and `amounts` must have the same length. */ function _burnBatch( address account, uint256[] memory ids, uint256[] memory amounts ) internal virtual { require(account != address(0), "ERC1155: burn from the zero address"); require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); address operator = _msgSender(); _beforeTokenTransfer(operator, account, address(0), ids, amounts, ""); for (uint256 i = 0; i < ids.length; i++) { uint256 id = ids[i]; uint256 amount = amounts[i]; uint256 accountBalance = _balances[id][account]; require(accountBalance >= amount, "ERC1155: burn amount exceeds balance"); unchecked { _balances[id][account] = accountBalance - amount; } } emit TransferBatch(operator, account, address(0), ids, amounts); } /** * @dev Hook that is called before any token transfer. This includes minting * and burning, as well as batched variants. * * The same hook is called on both single and batched variants. For single * transfers, the length of the `id` and `amount` arrays will be 1. * * Calling conditions (for each `id` and `amount` pair): * * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens * of token type `id` will be transferred to `to`. * - When `from` is zero, `amount` tokens of token type `id` will be minted * for `to`. * - when `to` is zero, `amount` of ``from``'s tokens of token type `id` * will be burned. * - `from` and `to` are never both zero. * - `ids` and `amounts` have the same, non-zero length. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual {} function _doSafeTransferAcceptanceCheck( address operator, address from, address to, uint256 id, uint256 amount, bytes memory data ) private { if (to.isContract()) { try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) { if (response != IERC1155Receiver.onERC1155Received.selector) { revert("ERC1155: ERC1155Receiver rejected tokens"); } } catch Error(string memory reason) { revert(reason); } catch { revert("ERC1155: transfer to non ERC1155Receiver implementer"); } } } function _doSafeBatchTransferAcceptanceCheck( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) private { if (to.isContract()) { try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns ( bytes4 response ) { if (response != IERC1155Receiver.onERC1155BatchReceived.selector) { revert("ERC1155: ERC1155Receiver rejected tokens"); } } catch Error(string memory reason) { revert(reason); } catch { revert("ERC1155: transfer to non ERC1155Receiver implementer"); } } } function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) { uint256[] memory array = new uint256[](1); array[0] = element; return array; } } // File: contracts/IERC1888.sol pragma solidity 0.8.4; // import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; interface ERC1888 is IERC1155 { struct Certificate { uint256 topic; address issuer; bytes validityData; bytes data; } event IssuanceSingle(address indexed _issuer, uint256 indexed _topic, uint256 _id, uint256 _value); event IssuanceBatch(address indexed _issuer, uint256[] indexed _topics, uint256[] _ids, uint256[] _values); event ClaimSingle(address indexed _claimIssuer, address indexed _claimSubject, uint256 indexed _topic, uint256 _id, uint256 _value, bytes _claimData); event ClaimBatch(address indexed _claimIssuer, address indexed _claimSubject, uint256[] indexed _topics, uint256[] _ids, uint256[] _values, bytes[] _claimData); function issue(address _to, bytes calldata _validityData, uint256 _topic, uint256 _value, bytes calldata _data) external returns (uint256 id); function batchIssue(address _to, bytes[] calldata _validityData, uint256[] calldata _topics, uint256[] calldata _values, bytes[] calldata _data) external returns (uint256[] memory ids); function safeTransferAndClaimFrom(address _from, address _to, uint256 _id, uint256 _value, bytes calldata _data, bytes calldata _claimData) external; function safeBatchTransferAndClaimFrom(address _from, address _to, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data, bytes[] calldata _claimData) external; function claimedBalanceOf(address _owner, uint256 _id) external view returns (uint256); function claimedBalanceOfBatch(address[] calldata _owners, uint256[] calldata _ids) external view returns (uint256[] memory); function getCertificate(uint256 _id) external view returns (address issuer, uint256 topic, bytes memory validityCall, bytes memory data); } // File: contracts/Registry.sol pragma solidity 0.8.4; // import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; /// @title Implementation of the Transferable Certificate standard ERC-1888. /// @dev Also complies to ERC-1155: https://eips.ethereum.org/EIPS/eip-1155. /// @dev ** Data set to 0 because there is no meaningful check yet to be done on the data contract Registry is ERC1155, ERC1888 { // Storage for the Certificate structs mapping(uint256 => Certificate) public certificateStorage; // Mapping from token ID to account balances mapping(uint256 => mapping(address => uint256)) public claimedBalances; // Incrementing nonce, used for generating certificate IDs uint256 internal _latestCertificateId; constructor(string memory _uri) ERC1155(_uri) { // Trigger ERC1155 constructor } /// @notice See {IERC1888-issue}. /// @dev `_to` cannot be the zero address. function issue(address _to, bytes calldata _validityData, uint256 _topic, uint256 _value, bytes calldata _data) external override returns (uint256 id) { require(_to != address(0x0), "_to must be non-zero."); _validate(_msgSender(), _validityData); id = ++_latestCertificateId; ERC1155._mint(_to, id, _value, new bytes(0)); // Check ** certificateStorage[id] = Certificate({ topic: _topic, issuer: _msgSender(), validityData: _validityData, data: _data }); emit IssuanceSingle(_msgSender(), _topic, id, _value); } /// @notice See {IERC1888-batchIssue}. /// @dev `_to` cannot be the zero address. /// @dev `_data`, `_values` and `_validityData` must have the same length. function batchIssue(address _to, bytes[] calldata _validityData, uint256[] calldata _topics, uint256[] calldata _values, bytes[] calldata _data) external override returns (uint256[] memory ids) { require(_to != address(0x0), "_to must be non-zero."); require(_data.length == _values.length, "Arrays not same length"); require(_values.length == _validityData.length, "Arrays not same length"); ids = new uint256[](_values.length); address operator = _msgSender(); for (uint256 i = 0; i <= _values.length; i++) { ids[i] = i + _latestCertificateId + 1; _validate(operator, _validityData[i]); } ERC1155._mintBatch(_to, ids, _values, new bytes(0)); // Check ** for (uint256 i = 0; i < ids.length; i++) { certificateStorage[ids[i]] = Certificate({ topic: _topics[i], issuer: operator, validityData: _validityData[i], data: _data[i] }); } emit IssuanceBatch(operator, _topics, ids, _values); } /// @notice Allows the issuer to mint more fungible tokens for existing ERC-188 certificates. /// @dev Allows batch issuing to an array of _to addresses. /// @dev `_to` cannot be the zero address. function mint(uint256 _id, address _to, uint256 _quantity) external { require(_to != address(0x0), "_to must be non-zero."); require(_quantity > 0, "_quantity must be above 0."); Certificate memory cert = certificateStorage[_id]; require(_msgSender() == cert.issuer, "Not original issuer"); ERC1155._mint(_to, _id, _quantity, new bytes(0)); // Check ** } /// @notice See {IERC1888-safeTransferAndClaimFrom}. /// @dev `_to` cannot be the zero address. /// @dev `_from` has to have a balance above or equal `_value`. function safeTransferAndClaimFrom( address _from, address _to, uint256 _id, uint256 _value, bytes calldata _data, bytes calldata _claimData ) external override { Certificate memory cert = certificateStorage[_id]; _validate(cert.issuer, cert.validityData); require(_to != address(0x0), "_to must be non-zero."); require(_from != address(0x0), "_from address must be non-zero."); require(_from == _msgSender() || ERC1155.isApprovedForAll(_from, _msgSender()), "No operator approval"); require(ERC1155.balanceOf(_from, _id) >= _value, "_from balance less than _value"); if (_from != _to) { safeTransferFrom(_from, _to, _id, _value, _data); } _burn(_to, _id, _value); emit ClaimSingle(_from, _to, cert.topic, _id, _value, _claimData); //_claimSubject address ?? } /// @notice See {IERC1888-safeBatchTransferAndClaimFrom}. /// @dev `_to` and `_from` cannot be the zero addresses. /// @dev `_from` has to have a balance above 0. function safeBatchTransferAndClaimFrom( address _from, address _to, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data, bytes[] calldata _claimData ) external override { require(_to != address(0x0), "_to address must be non-zero"); require(_from != address(0x0), "_from address must be non-zero"); require(_ids.length == _values.length, "Arrays not same length"); require(_values.length == _claimData.length, "Arrays not same length."); require(_from == _msgSender() || ERC1155.isApprovedForAll(_from, _msgSender()), "No operator approval"); require(_ids.length > 0, "no certificates specified"); uint256 numberOfClaims = _ids.length; uint256[] memory topics = new uint256[](numberOfClaims); for (uint256 i = 0; i < numberOfClaims; i++) { Certificate memory cert = certificateStorage[_ids[i]]; _validate(cert.issuer, cert.validityData); topics[i] = cert.topic; } if (_from != _to) { safeBatchTransferFrom(_from, _to, _ids, _values, _data); } for (uint256 i = 0; i < numberOfClaims; i++) { _burn(_to, _ids[i], _values[i]); } emit ClaimBatch(_from, _to, topics, _ids, _values, _claimData); } /// @notice See {IERC1888-claimedBalanceOf}. function claimedBalanceOf(address _owner, uint256 _id) external override view returns (uint256) { return claimedBalances[_id][_owner]; } /// @notice See {IERC1888-claimedBalanceOfBatch}. function claimedBalanceOfBatch(address[] calldata _owners, uint256[] calldata _ids) external override view returns (uint256[] memory) { require(_owners.length == _ids.length, "owners and ids length mismatch"); uint256[] memory batchClaimBalances = new uint256[](_owners.length); for (uint256 i = 0; i < _owners.length; i++) { batchClaimBalances[i] = this.claimedBalanceOf(_owners[i], _ids[i]); } return batchClaimBalances; } /// @notice See {IERC1888-getCertificate}. function getCertificate(uint256 _id) public view override returns (address issuer, uint256 topic, bytes memory validityCall, bytes memory data) { require(_id <= _latestCertificateId, "_id out of bounds"); Certificate memory certificate = certificateStorage[_id]; return (certificate.issuer, certificate.topic, certificate.validityData, certificate.data); } /// @notice Burn certificates after they've been claimed, and increase the claimed balance. function _burn(address _from, uint256 _id, uint256 _value) internal override { ERC1155._burn(_from, _id, _value); claimedBalances[_id][_from] = claimedBalances[_id][_from] + _value; } /// @notice Validate if the certificate is valid against an external `_verifier` contract. function _validate(address _verifier, bytes memory _validityData) internal view { (bool success, bytes memory result) = _verifier.staticcall(_validityData); require(success && abi.decode(result, (bool)), "Request/certificate invalid"); } } // File: contracts/RegistryExtended.sol pragma solidity 0.8.4; /// @title Extension of the Transferable Certificate standard ERC-1888. contract RegistryExtended is Registry { event TransferBatchMultiple(address indexed operator, address[] from, address[] to, uint256[] ids, uint256[] values); event ClaimBatchMultiple(address[] _claimIssuer, address[] _claimSubject, uint256[] indexed _topics, uint256[] _ids, uint256[] _values, bytes[] _claimData); constructor(string memory _uri) Registry(_uri) { // Trigger Registry constructor } /// @notice Similar to {IERC1888-batchIssue}, but not a part of the ERC-1888 standard. /// @dev Allows batch issuing to an array of _to addresses. /// @dev `_to` cannot be the zero addresses. /// @dev `_to`, `_data`, `_values`, `_topics` and `_validityData` must have the same length. function batchIssueMultiple(address[] calldata _to, bytes[] calldata _validityData, uint256[] calldata _topics, uint256[] calldata _values, bytes[] calldata _data) external returns (uint256[] memory ids) { require(_values.length > 0, "no values specified"); require(_to.length == _data.length, "Arrays not same length"); require(_data.length == _values.length, "Arrays not same length"); require(_values.length == _validityData.length, "Arrays not same length"); require(_validityData.length == _topics.length, "Arrays not same length"); ids = new uint256[](_values.length); address operator = _msgSender(); for (uint256 i = 0; i < _values.length; i++) { require(_to[i] != address(0x0), "_to must be non-zero."); ids[i] = i + _latestCertificateId + 1; _validate(operator, _validityData[i]); } for (uint256 i = 0; i < ids.length; i++) { ERC1155._mint(_to[i], ids[i], _values[i], _data[i]); // Check ** certificateStorage[ids[i]] = Certificate({ topic: _topics[i], issuer: operator, validityData: _validityData[i], data: _data[i] }); } _latestCertificateId = ids[ids.length - 1]; emit IssuanceBatch(operator, _topics, ids, _values); } /// @notice Similar to {ERC1155-safeBatchTransferFrom}, but not a part of the ERC-1155 standard. /// @dev Allows batch transferring to/from an array of addresses. function safeBatchTransferFromMultiple( address[] calldata _from, address[] calldata _to, uint256[] calldata _ids, uint256[] calldata _values, bytes[] calldata _data ) external { require(_from.length == _to.length, "Arrays not same length"); require(_to.length == _ids.length, "Arrays not same length"); require(_ids.length == _values.length, "Arrays not same length"); require(_values.length == _data.length, "Arrays not same length."); for (uint256 i = 0; i < _ids.length; i++) { require(_from[i] != address(0x0), "_from must be non-zero."); require(_to[i] != address(0x0), "_to must be non-zero."); require(_from[i] == _msgSender() || ERC1155.isApprovedForAll(_from[i], _msgSender()), "No operator approval"); require(ERC1155.balanceOf(_from[i], _ids[i]) >= _values[i], "Not enough balance to transfer"); Certificate memory cert = certificateStorage[_ids[i]]; _validate(cert.issuer, cert.validityData); } address operator = _msgSender(); for (uint256 i = 0; i < _ids.length; ++i) { _safeTransferFrom(_from[i], _to[i], _ids[i], _values[i], _data[i]); } emit TransferBatchMultiple(operator, _from, _to, _ids, _values); } /// @notice Similar to {IERC1888-safeBatchTransferAndClaimFrom}, but not a part of the ERC-1888 standard. /// @dev Allows batch claiming to/from an array of addresses. function safeBatchTransferAndClaimFromMultiple( address[] calldata _from, address[] calldata _to, uint256[] calldata _ids, uint256[] calldata _values, bytes[] calldata _data, bytes[] calldata _claimData ) external { require(_ids.length > 0, "no certificates specified"); require(_from.length == _to.length, "Arrays not same length"); require(_to.length == _ids.length, "Arrays not same length"); require(_ids.length == _values.length, "Arrays not same length"); require(_values.length == _data.length, "Arrays not same length."); require(_data.length == _claimData.length, "Arrays not same length."); uint256[] memory topics = new uint256[](_ids.length); for (uint256 i = 0; i < _ids.length; i++) { require(_from[i] != address(0x0), "_from must be non-zero."); require(_to[i] != address(0x0), "_to must be non-zero."); require(_from[i] == _msgSender() || ERC1155.isApprovedForAll(_from[i], _msgSender()), "No operator approval"); require(ERC1155.balanceOf(_from[i], _ids[i]) >= _values[i], "Not enough balance to claim"); Certificate memory cert = certificateStorage[_ids[i]]; _validate(cert.issuer, cert.validityData); } for (uint256 i = 0; i < _ids.length; i++) { Certificate memory cert = certificateStorage[_ids[i]]; topics[i] = cert.topic; if (_from[i] != _to[i]) { _safeTransferFrom(_from[i], _to[i], _ids[i], _values[i], _data[i]); } _burn(_to[i], _ids[i], _values[i]); } emit ClaimBatchMultiple(_from, _to, topics, _ids, _values, _claimData); } }
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"string","name":"_uri","internalType":"string"}]},{"type":"event","name":"ApprovalForAll","inputs":[{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"address","name":"operator","internalType":"address","indexed":true},{"type":"bool","name":"approved","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"ClaimBatch","inputs":[{"type":"address","name":"_claimIssuer","internalType":"address","indexed":true},{"type":"address","name":"_claimSubject","internalType":"address","indexed":true},{"type":"uint256[]","name":"_topics","internalType":"uint256[]","indexed":true},{"type":"uint256[]","name":"_ids","internalType":"uint256[]","indexed":false},{"type":"uint256[]","name":"_values","internalType":"uint256[]","indexed":false},{"type":"bytes[]","name":"_claimData","internalType":"bytes[]","indexed":false}],"anonymous":false},{"type":"event","name":"ClaimBatchMultiple","inputs":[{"type":"address[]","name":"_claimIssuer","internalType":"address[]","indexed":false},{"type":"address[]","name":"_claimSubject","internalType":"address[]","indexed":false},{"type":"uint256[]","name":"_topics","internalType":"uint256[]","indexed":true},{"type":"uint256[]","name":"_ids","internalType":"uint256[]","indexed":false},{"type":"uint256[]","name":"_values","internalType":"uint256[]","indexed":false},{"type":"bytes[]","name":"_claimData","internalType":"bytes[]","indexed":false}],"anonymous":false},{"type":"event","name":"ClaimSingle","inputs":[{"type":"address","name":"_claimIssuer","internalType":"address","indexed":true},{"type":"address","name":"_claimSubject","internalType":"address","indexed":true},{"type":"uint256","name":"_topic","internalType":"uint256","indexed":true},{"type":"uint256","name":"_id","internalType":"uint256","indexed":false},{"type":"uint256","name":"_value","internalType":"uint256","indexed":false},{"type":"bytes","name":"_claimData","internalType":"bytes","indexed":false}],"anonymous":false},{"type":"event","name":"IssuanceBatch","inputs":[{"type":"address","name":"_issuer","internalType":"address","indexed":true},{"type":"uint256[]","name":"_topics","internalType":"uint256[]","indexed":true},{"type":"uint256[]","name":"_ids","internalType":"uint256[]","indexed":false},{"type":"uint256[]","name":"_values","internalType":"uint256[]","indexed":false}],"anonymous":false},{"type":"event","name":"IssuanceSingle","inputs":[{"type":"address","name":"_issuer","internalType":"address","indexed":true},{"type":"uint256","name":"_topic","internalType":"uint256","indexed":true},{"type":"uint256","name":"_id","internalType":"uint256","indexed":false},{"type":"uint256","name":"_value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"TransferBatch","inputs":[{"type":"address","name":"operator","internalType":"address","indexed":true},{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256[]","name":"ids","internalType":"uint256[]","indexed":false},{"type":"uint256[]","name":"values","internalType":"uint256[]","indexed":false}],"anonymous":false},{"type":"event","name":"TransferBatchMultiple","inputs":[{"type":"address","name":"operator","internalType":"address","indexed":true},{"type":"address[]","name":"from","internalType":"address[]","indexed":false},{"type":"address[]","name":"to","internalType":"address[]","indexed":false},{"type":"uint256[]","name":"ids","internalType":"uint256[]","indexed":false},{"type":"uint256[]","name":"values","internalType":"uint256[]","indexed":false}],"anonymous":false},{"type":"event","name":"TransferSingle","inputs":[{"type":"address","name":"operator","internalType":"address","indexed":true},{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"id","internalType":"uint256","indexed":false},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"URI","inputs":[{"type":"string","name":"value","internalType":"string","indexed":false},{"type":"uint256","name":"id","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"balanceOf","inputs":[{"type":"address","name":"account","internalType":"address"},{"type":"uint256","name":"id","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"","internalType":"uint256[]"}],"name":"balanceOfBatch","inputs":[{"type":"address[]","name":"accounts","internalType":"address[]"},{"type":"uint256[]","name":"ids","internalType":"uint256[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256[]","name":"ids","internalType":"uint256[]"}],"name":"batchIssue","inputs":[{"type":"address","name":"_to","internalType":"address"},{"type":"bytes[]","name":"_validityData","internalType":"bytes[]"},{"type":"uint256[]","name":"_topics","internalType":"uint256[]"},{"type":"uint256[]","name":"_values","internalType":"uint256[]"},{"type":"bytes[]","name":"_data","internalType":"bytes[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256[]","name":"ids","internalType":"uint256[]"}],"name":"batchIssueMultiple","inputs":[{"type":"address[]","name":"_to","internalType":"address[]"},{"type":"bytes[]","name":"_validityData","internalType":"bytes[]"},{"type":"uint256[]","name":"_topics","internalType":"uint256[]"},{"type":"uint256[]","name":"_values","internalType":"uint256[]"},{"type":"bytes[]","name":"_data","internalType":"bytes[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"topic","internalType":"uint256"},{"type":"address","name":"issuer","internalType":"address"},{"type":"bytes","name":"validityData","internalType":"bytes"},{"type":"bytes","name":"data","internalType":"bytes"}],"name":"certificateStorage","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"claimedBalanceOf","inputs":[{"type":"address","name":"_owner","internalType":"address"},{"type":"uint256","name":"_id","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"","internalType":"uint256[]"}],"name":"claimedBalanceOfBatch","inputs":[{"type":"address[]","name":"_owners","internalType":"address[]"},{"type":"uint256[]","name":"_ids","internalType":"uint256[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"claimedBalances","inputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"issuer","internalType":"address"},{"type":"uint256","name":"topic","internalType":"uint256"},{"type":"bytes","name":"validityCall","internalType":"bytes"},{"type":"bytes","name":"data","internalType":"bytes"}],"name":"getCertificate","inputs":[{"type":"uint256","name":"_id","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isApprovedForAll","inputs":[{"type":"address","name":"account","internalType":"address"},{"type":"address","name":"operator","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"id","internalType":"uint256"}],"name":"issue","inputs":[{"type":"address","name":"_to","internalType":"address"},{"type":"bytes","name":"_validityData","internalType":"bytes"},{"type":"uint256","name":"_topic","internalType":"uint256"},{"type":"uint256","name":"_value","internalType":"uint256"},{"type":"bytes","name":"_data","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"mint","inputs":[{"type":"uint256","name":"_id","internalType":"uint256"},{"type":"address","name":"_to","internalType":"address"},{"type":"uint256","name":"_quantity","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"safeBatchTransferAndClaimFrom","inputs":[{"type":"address","name":"_from","internalType":"address"},{"type":"address","name":"_to","internalType":"address"},{"type":"uint256[]","name":"_ids","internalType":"uint256[]"},{"type":"uint256[]","name":"_values","internalType":"uint256[]"},{"type":"bytes","name":"_data","internalType":"bytes"},{"type":"bytes[]","name":"_claimData","internalType":"bytes[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"safeBatchTransferAndClaimFromMultiple","inputs":[{"type":"address[]","name":"_from","internalType":"address[]"},{"type":"address[]","name":"_to","internalType":"address[]"},{"type":"uint256[]","name":"_ids","internalType":"uint256[]"},{"type":"uint256[]","name":"_values","internalType":"uint256[]"},{"type":"bytes[]","name":"_data","internalType":"bytes[]"},{"type":"bytes[]","name":"_claimData","internalType":"bytes[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"safeBatchTransferFrom","inputs":[{"type":"address","name":"from","internalType":"address"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256[]","name":"ids","internalType":"uint256[]"},{"type":"uint256[]","name":"amounts","internalType":"uint256[]"},{"type":"bytes","name":"data","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"safeBatchTransferFromMultiple","inputs":[{"type":"address[]","name":"_from","internalType":"address[]"},{"type":"address[]","name":"_to","internalType":"address[]"},{"type":"uint256[]","name":"_ids","internalType":"uint256[]"},{"type":"uint256[]","name":"_values","internalType":"uint256[]"},{"type":"bytes[]","name":"_data","internalType":"bytes[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"safeTransferAndClaimFrom","inputs":[{"type":"address","name":"_from","internalType":"address"},{"type":"address","name":"_to","internalType":"address"},{"type":"uint256","name":"_id","internalType":"uint256"},{"type":"uint256","name":"_value","internalType":"uint256"},{"type":"bytes","name":"_data","internalType":"bytes"},{"type":"bytes","name":"_claimData","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"safeTransferFrom","inputs":[{"type":"address","name":"from","internalType":"address"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"id","internalType":"uint256"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"bytes","name":"data","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setApprovalForAll","inputs":[{"type":"address","name":"operator","internalType":"address"},{"type":"bool","name":"approved","internalType":"bool"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"supportsInterface","inputs":[{"type":"bytes4","name":"interfaceId","internalType":"bytes4"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"uri","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]}]
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106101365760003560e01c80638673605a116100b8578063ba688a941161007c578063ba688a94146102c9578063c48238b0146102dc578063c5308dd814610307578063d6878ffb1461031a578063e985e9c51461033d578063f242432a1461037957600080fd5b80638673605a1461026a5780638838a9d71461027d5780638ed8707514610290578063a22cb465146102a3578063b93bbaa0146102b657600080fd5b80634e1273f4116100ff5780634e1273f4146101ee57806351640fee1461020e578063543d526d14610231578063760c6caf14610244578063836a10401461025757600080fd5b8062fdd58e1461013b57806301ffc9a7146101615780630e89341c146101845780632eb2c2d6146101a45780633ebbaaa5146101b9575b600080fd5b61014e61014936600461447e565b61038c565b6040519081526020015b60405180910390f35b61017461016f3660046147ef565b610423565b6040519015158152602001610158565b610197610192366004614827565b610475565b6040516101589190614d17565b6101b76101b2366004614140565b610509565b005b61014e6101c736600461447e565b60009081526004602090815260408083206001600160a01b03949094168352929052205490565b6102016101fc366004614709565b6105a0565b6040516101589190614ca6565b61022161021c366004614827565b610701565b6040516101589493929190614b4d565b61014e61023f3660046143ee565b6108ca565b6101b761025236600461405e565b610aed565b6101b7610265366004614879565b611056565b6102016102783660046142e7565b61129c565b61020161028b3660046144a7565b6116e8565b61020161029e3660046146a1565b611c63565b6101b76102b13660046143b8565b611e3a565b6101b76102c43660046144a7565b611f11565b6101b76102d736600461456b565b61254a565b61014e6102ea366004614857565b600460209081526000928352604080842090915290825290205481565b6101b76103153660046141e5565b612e9e565b61032d610328366004614827565b6131e1565b6040516101589493929190614f4e565b61017461034b36600461402c565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205460ff1690565b6101b7610387366004614285565b613324565b60006001600160a01b0383166103fd5760405162461bcd60e51b815260206004820152602b60248201527f455243313135353a2062616c616e636520717565727920666f7220746865207a60448201526a65726f206164647265737360a81b60648201526084015b60405180910390fd5b506000908152602081815260408083206001600160a01b03949094168352929052205490565b60006001600160e01b03198216636cdb3d1360e11b148061045457506001600160e01b031982166303a24d0760e21b145b8061046f57506301ffc9a760e01b6001600160e01b03198316145b92915050565b6060600280546104849061505a565b80601f01602080910402602001604051908101604052809291908181526020018280546104b09061505a565b80156104fd5780601f106104d2576101008083540402835291602001916104fd565b820191906000526020600020905b8154815290600101906020018083116104e057829003601f168201915b50505050509050919050565b6001600160a01b0385163314806105255750610525853361034b565b61058c5760405162461bcd60e51b815260206004820152603260248201527f455243313135353a207472616e736665722063616c6c6572206973206e6f74206044820152711bdddb995c881b9bdc88185c1c1c9bdd995960721b60648201526084016103f4565b61059985858585856133ab565b5050505050565b606081518351146106055760405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e677468604482015268040dad2e6dac2e8c6d60bb1b60648201526084016103f4565b600083516001600160401b0381111561062e57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610657578160200160208202803683370190505b50905060005b84518110156106f9576106be85828151811061068957634e487b7160e01b600052603260045260246000fd5b60200260200101518583815181106106b157634e487b7160e01b600052603260045260246000fd5b602002602001015161038c565b8282815181106106de57634e487b7160e01b600052603260045260246000fd5b60209081029190910101526106f2816150c1565b905061065d565b509392505050565b60008060608060055485111561074d5760405162461bcd60e51b81526020600482015260116024820152705f6964206f7574206f6620626f756e647360781b60448201526064016103f4565b600085815260036020908152604080832081516080810183528154815260018201546001600160a01b03169381019390935260028101805491928401916107939061505a565b80601f01602080910402602001604051908101604052809291908181526020018280546107bf9061505a565b801561080c5780601f106107e15761010080835404028352916020019161080c565b820191906000526020600020905b8154815290600101906020018083116107ef57829003601f168201915b505050505081526020016003820180546108259061505a565b80601f01602080910402602001604051908101604052809291908181526020018280546108519061505a565b801561089e5780601f106108735761010080835404028352916020019161089e565b820191906000526020600020905b81548152906001019060200180831161088157829003601f168201915b505050919092525050506020810151815160408301516060909301519199909850919650945092505050565b60006001600160a01b0388166108f25760405162461bcd60e51b81526004016103f490614f1f565b6109323388888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061356392505050565b600560008154610941906150c1565b9182905550905061098188828660005b6040519080825280601f01601f19166020018201604052801561097b576020820181803683370190505b5061362b565b60405180608001604052808681526020016109993390565b6001600160a01b0316815260200188888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250604080516020601f87018190048102820181019092528581529181019190869086908190840183828082843760009201829052509390945250508381526003602090815260409182902084518155848201516001820180546001600160a01b0319166001600160a01b03909216919091179055918401518051929350610a6f9260028501929190910190613dec565b5060608201518051610a8b916003840191602090910190613dec565b5090505084610a973390565b6001600160a01b03167f19fdba3b3fa810260206510aa7278c70ea23c0d104195bed67bfb27a3d82fbfe8387604051610ada929190918252602082015260400190565b60405180910390a3979650505050505050565b6001600160a01b038916610b435760405162461bcd60e51b815260206004820152601c60248201527f5f746f2061646472657373206d757374206265206e6f6e2d7a65726f0000000060448201526064016103f4565b6001600160a01b038a16610b995760405162461bcd60e51b815260206004820152601e60248201527f5f66726f6d2061646472657373206d757374206265206e6f6e2d7a65726f000060448201526064016103f4565b868514610bb85760405162461bcd60e51b81526004016103f490614e66565b848114610bd75760405162461bcd60e51b81526004016103f490614e2f565b6001600160a01b038a16331480610bf35750610bf38a3361034b565b610c0f5760405162461bcd60e51b81526004016103f490614d72565b86610c585760405162461bcd60e51b81526020600482015260196024820152781b9bc818d95c9d1a599a58d85d195cc81cdc1958da599a5959603a1b60448201526064016103f4565b866000816001600160401b03811115610c8157634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610caa578160200160208202803683370190505b50905060005b82811015610e9a576000600360008d8d85818110610cde57634e487b7160e01b600052603260045260246000fd5b6020908102929092013583525081810192909252604090810160002081516080810183528154815260018201546001600160a01b0316938101939093526002810180549192840191610d2f9061505a565b80601f0160208091040260200160405190810160405280929190818152602001828054610d5b9061505a565b8015610da85780601f10610d7d57610100808354040283529160200191610da8565b820191906000526020600020905b815481529060010190602001808311610d8b57829003601f168201915b50505050508152602001600382018054610dc19061505a565b80601f0160208091040260200160405190810160405280929190818152602001828054610ded9061505a565b8015610e3a5780601f10610e0f57610100808354040283529160200191610e3a565b820191906000526020600020905b815481529060010190602001808311610e1d57829003601f168201915b5050505050815250509050610e5781602001518260400151613563565b8060000151838381518110610e7c57634e487b7160e01b600052603260045260246000fd5b60209081029190910101525080610e92816150c1565b915050610cb0565b508a6001600160a01b03168c6001600160a01b031614610f6857610f688c8c8c8c80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508b8b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020601f8f018190048102820181019092528d815292508d91508c908190840183828082843760009201919091525061050992505050565b60005b82811015610fdc57610fca8c8c8c84818110610f9757634e487b7160e01b600052603260045260246000fd5b905060200201358b8b85818110610fbe57634e487b7160e01b600052603260045260246000fd5b905060200201356136fb565b80610fd4816150c1565b915050610f6b565b5080604051610feb9190614a58565b60405180910390208b6001600160a01b03168d6001600160a01b03167f61a69d58bffe77be60879031f7e6d3d17fab9c88a681899a549d20ae8a39f8d08d8d8d8d8b8b60405161104096959493929190614c5d565b60405180910390a4505050505050505050505050565b6001600160a01b03821661107c5760405162461bcd60e51b81526004016103f490614f1f565b600081116110cc5760405162461bcd60e51b815260206004820152601a60248201527f5f7175616e74697479206d7573742062652061626f766520302e00000000000060448201526064016103f4565b600083815260036020908152604080832081516080810183528154815260018201546001600160a01b03169381019390935260028101805491928401916111129061505a565b80601f016020809104026020016040519081016040528092919081815260200182805461113e9061505a565b801561118b5780601f106111605761010080835404028352916020019161118b565b820191906000526020600020905b81548152906001019060200180831161116e57829003601f168201915b505050505081526020016003820180546111a49061505a565b80601f01602080910402602001604051908101604052809291908181526020018280546111d09061505a565b801561121d5780601f106111f25761010080835404028352916020019161121d565b820191906000526020600020905b81548152906001019060200180831161120057829003601f168201915b505050505081525050905080602001516001600160a01b031661123d3390565b6001600160a01b0316146112895760405162461bcd60e51b81526020600482015260136024820152722737ba1037b934b3b4b730b61034b9b9bab2b960691b60448201526064016103f4565b6112968385846000610951565b50505050565b60606001600160a01b038a166112c45760405162461bcd60e51b81526004016103f490614f1f565b8184146112e35760405162461bcd60e51b81526004016103f490614e66565b8388146113025760405162461bcd60e51b81526004016103f490614e66565b836001600160401b0381111561132857634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611351578160200160208202803683370190505b5090503360005b8581116114255760055461136c9082614fff565b611377906001614fff565b83828151811061139757634e487b7160e01b600052603260045260246000fd5b602002602001018181525050611413828c8c848181106113c757634e487b7160e01b600052603260045260246000fd5b90506020028101906113d99190614f98565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061356392505050565b8061141d816150c1565b915050611358565b506114948b8388888080602002602001604051908101604052809392919081815260200183836020028082843760009201829052509250611464915050565b6040519080825280601f01601f19166020018201604052801561148e576020820181803683370190505b50613760565b60005b825181101561167c5760405180608001604052808a8a848181106114cb57634e487b7160e01b600052603260045260246000fd5b905060200201358152602001836001600160a01b031681526020018c8c8481811061150657634e487b7160e01b600052603260045260246000fd5b90506020028101906115189190614f98565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060200186868481811061157257634e487b7160e01b600052603260045260246000fd5b90506020028101906115849190614f98565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052509390945250508551600392508690859081106115e057634e487b7160e01b600052603260045260246000fd5b602002602001015181526020019081526020016000206000820151816000015560208201518160010160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506040820151816002019080519060200190611649929190613dec565b5060608201518051611665916003840191602090910190613dec565b509050508080611674906150c1565b915050611497565b50878760405161168d929190614a2e565b6040518091039020816001600160a01b03167f4337762bcc37db59d5eea698d442c9782e625db731704f4f83ed376a09b64e6c8489896040516116d293929190614cb9565b60405180910390a3509998505050505050505050565b60608361172d5760405162461bcd60e51b81526020600482015260136024820152721b9bc81d985b1d595cc81cdc1958da599a5959606a1b60448201526064016103f4565b89821461174c5760405162461bcd60e51b81526004016103f490614e66565b81841461176b5760405162461bcd60e51b81526004016103f490614e66565b83881461178a5760405162461bcd60e51b81526004016103f490614e66565b8786146117a95760405162461bcd60e51b81526004016103f490614e66565b836001600160401b038111156117cf57634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156117f8578160200160208202803683370190505b5090503360005b858110156118df5760008d8d8381811061182957634e487b7160e01b600052603260045260246000fd5b905060200201602081019061183e919061400b565b6001600160a01b031614156118655760405162461bcd60e51b81526004016103f490614f1f565b6005546118729082614fff565b61187d906001614fff565b83828151811061189d57634e487b7160e01b600052603260045260246000fd5b6020026020010181815250506118cd828c8c848181106113c757634e487b7160e01b600052603260045260246000fd5b806118d7816150c1565b9150506117ff565b5060005b8251811015611bbb576119df8d8d8381811061190f57634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611924919061400b565b84838151811061194457634e487b7160e01b600052603260045260246000fd5b602002602001015189898581811061196c57634e487b7160e01b600052603260045260246000fd5b9050602002013588888681811061199357634e487b7160e01b600052603260045260246000fd5b90506020028101906119a59190614f98565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061362b92505050565b60405180608001604052808a8a84818110611a0a57634e487b7160e01b600052603260045260246000fd5b905060200201358152602001836001600160a01b031681526020018c8c84818110611a4557634e487b7160e01b600052603260045260246000fd5b9050602002810190611a579190614f98565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250602001868684818110611ab157634e487b7160e01b600052603260045260246000fd5b9050602002810190611ac39190614f98565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250939094525050855160039250869085908110611b1f57634e487b7160e01b600052603260045260246000fd5b602002602001015181526020019081526020016000206000820151816000015560208201518160010160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506040820151816002019080519060200190611b88929190613dec565b5060608201518051611ba4916003840191602090910190613dec565b509050508080611bb3906150c1565b9150506118e3565b508160018351611bcb9190615017565b81518110611be957634e487b7160e01b600052603260045260246000fd5b60200260200101516005819055508787604051611c07929190614a2e565b6040518091039020816001600160a01b03167f4337762bcc37db59d5eea698d442c9782e625db731704f4f83ed376a09b64e6c848989604051611c4c93929190614cb9565b60405180910390a3509a9950505050505050505050565b6060838214611cb45760405162461bcd60e51b815260206004820152601e60248201527f6f776e65727320616e6420696473206c656e677468206d69736d61746368000060448201526064016103f4565b6000846001600160401b03811115611cdc57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611d05578160200160208202803683370190505b50905060005b85811015611e305730633ebbaaa5888884818110611d3957634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611d4e919061400b565b878785818110611d6e57634e487b7160e01b600052603260045260246000fd5b6040516001600160e01b031960e087901b1681526001600160a01b039094166004850152602002919091013560248301525060440160206040518083038186803b158015611dbb57600080fd5b505afa158015611dcf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611df3919061483f565b828281518110611e1357634e487b7160e01b600052603260045260246000fd5b602090810291909101015280611e28816150c1565b915050611d0b565b5095945050505050565b336001600160a01b0383161415611ea55760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c20737461747573604482015268103337b91039b2b63360b91b60648201526084016103f4565b3360008181526001602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b888714611f305760405162461bcd60e51b81526004016103f490614e66565b868514611f4f5760405162461bcd60e51b81526004016103f490614e66565b848314611f6e5760405162461bcd60e51b81526004016103f490614e66565b828114611f8d5760405162461bcd60e51b81526004016103f490614e2f565b60005b858110156123a95760008b8b83818110611fba57634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611fcf919061400b565b6001600160a01b031614156120205760405162461bcd60e51b81526020600482015260176024820152762fb33937b69036bab9ba103132903737b716bd32b9379760491b60448201526064016103f4565b600089898381811061204257634e487b7160e01b600052603260045260246000fd5b9050602002016020810190612057919061400b565b6001600160a01b0316141561207e5760405162461bcd60e51b81526004016103f490614f1f565b338b8b8381811061209f57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906120b4919061400b565b6001600160a01b0316148061210257506121028b8b838181106120e757634e487b7160e01b600052603260045260246000fd5b90506020020160208101906120fc919061400b565b3361034b565b61211e5760405162461bcd60e51b81526004016103f490614d72565b84848281811061213e57634e487b7160e01b600052603260045260246000fd5b905060200201356121a98c8c8481811061216857634e487b7160e01b600052603260045260246000fd5b905060200201602081019061217d919061400b565b89898581811061219d57634e487b7160e01b600052603260045260246000fd5b9050602002013561038c565b10156121f75760405162461bcd60e51b815260206004820152601e60248201527f4e6f7420656e6f7567682062616c616e636520746f207472616e73666572000060448201526064016103f4565b60006003600089898581811061221d57634e487b7160e01b600052603260045260246000fd5b6020908102929092013583525081810192909252604090810160002081516080810183528154815260018201546001600160a01b031693810193909352600281018054919284019161226e9061505a565b80601f016020809104026020016040519081016040528092919081815260200182805461229a9061505a565b80156122e75780601f106122bc576101008083540402835291602001916122e7565b820191906000526020600020905b8154815290600101906020018083116122ca57829003601f168201915b505050505081526020016003820180546123009061505a565b80601f016020809104026020016040519081016040528092919081815260200182805461232c9061505a565b80156123795780601f1061234e57610100808354040283529160200191612379565b820191906000526020600020905b81548152906001019060200180831161235c57829003601f168201915b505050505081525050905061239681602001518260400151613563565b50806123a1816150c1565b915050611f90565b503360005b868110156124ed576124dd8c8c838181106123d957634e487b7160e01b600052603260045260246000fd5b90506020020160208101906123ee919061400b565b8b8b8481811061240e57634e487b7160e01b600052603260045260246000fd5b9050602002016020810190612423919061400b565b8a8a8581811061244357634e487b7160e01b600052603260045260246000fd5b9050602002013589898681811061246a57634e487b7160e01b600052603260045260246000fd5b9050602002013588888781811061249157634e487b7160e01b600052603260045260246000fd5b90506020028101906124a39190614f98565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506138c792505050565b6124e6816150c1565b90506123ae565b50806001600160a01b03167f9a17c5980bc0d14e313aaa844f04cd0ee291f743df00bf06337a3ce1db563be48c8c8c8c8c8c8c8c604051612535989796959493929190614b86565b60405180910390a25050505050505050505050565b866125935760405162461bcd60e51b81526020600482015260196024820152781b9bc818d95c9d1a599a58d85d195cc81cdc1958da599a5959603a1b60448201526064016103f4565b8a89146125b25760405162461bcd60e51b81526004016103f490614e66565b8887146125d15760405162461bcd60e51b81526004016103f490614e66565b8685146125f05760405162461bcd60e51b81526004016103f490614e66565b84831461260f5760405162461bcd60e51b81526004016103f490614e2f565b82811461262e5760405162461bcd60e51b81526004016103f490614e2f565b6000876001600160401b0381111561265657634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801561267f578160200160208202803683370190505b50905060005b88811015612a775760008e8e838181106126af57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906126c4919061400b565b6001600160a01b031614156127155760405162461bcd60e51b81526020600482015260176024820152762fb33937b69036bab9ba103132903737b716bd32b9379760491b60448201526064016103f4565b60008c8c8381811061273757634e487b7160e01b600052603260045260246000fd5b905060200201602081019061274c919061400b565b6001600160a01b031614156127735760405162461bcd60e51b81526004016103f490614f1f565b338e8e8381811061279457634e487b7160e01b600052603260045260246000fd5b90506020020160208101906127a9919061400b565b6001600160a01b031614806127dc57506127dc8e8e838181106120e757634e487b7160e01b600052603260045260246000fd5b6127f85760405162461bcd60e51b81526004016103f490614d72565b87878281811061281857634e487b7160e01b600052603260045260246000fd5b905060200201356128778f8f8481811061284257634e487b7160e01b600052603260045260246000fd5b9050602002016020810190612857919061400b565b8c8c8581811061219d57634e487b7160e01b600052603260045260246000fd5b10156128c55760405162461bcd60e51b815260206004820152601b60248201527f4e6f7420656e6f7567682062616c616e636520746f20636c61696d000000000060448201526064016103f4565b6000600360008c8c858181106128eb57634e487b7160e01b600052603260045260246000fd5b6020908102929092013583525081810192909252604090810160002081516080810183528154815260018201546001600160a01b031693810193909352600281018054919284019161293c9061505a565b80601f01602080910402602001604051908101604052809291908181526020018280546129689061505a565b80156129b55780601f1061298a576101008083540402835291602001916129b5565b820191906000526020600020905b81548152906001019060200180831161299857829003601f168201915b505050505081526020016003820180546129ce9061505a565b80601f01602080910402602001604051908101604052809291908181526020018280546129fa9061505a565b8015612a475780601f10612a1c57610100808354040283529160200191612a47565b820191906000526020600020905b815481529060010190602001808311612a2a57829003601f168201915b5050505050815250509050612a6481602001518260400151613563565b5080612a6f816150c1565b915050612685565b5060005b88811015612e2f576000600360008c8c85818110612aa957634e487b7160e01b600052603260045260246000fd5b6020908102929092013583525081810192909252604090810160002081516080810183528154815260018201546001600160a01b0316938101939093526002810180549192840191612afa9061505a565b80601f0160208091040260200160405190810160405280929190818152602001828054612b269061505a565b8015612b735780601f10612b4857610100808354040283529160200191612b73565b820191906000526020600020905b815481529060010190602001808311612b5657829003601f168201915b50505050508152602001600382018054612b8c9061505a565b80601f0160208091040260200160405190810160405280929190818152602001828054612bb89061505a565b8015612c055780601f10612bda57610100808354040283529160200191612c05565b820191906000526020600020905b815481529060010190602001808311612be857829003601f168201915b50505050508152505090508060000151838381518110612c3557634e487b7160e01b600052603260045260246000fd5b6020026020010181815250508c8c83818110612c6157634e487b7160e01b600052603260045260246000fd5b9050602002016020810190612c76919061400b565b6001600160a01b03168f8f84818110612c9f57634e487b7160e01b600052603260045260246000fd5b9050602002016020810190612cb4919061400b565b6001600160a01b031614612d9d57612d9d8f8f84818110612ce557634e487b7160e01b600052603260045260246000fd5b9050602002016020810190612cfa919061400b565b8e8e85818110612d1a57634e487b7160e01b600052603260045260246000fd5b9050602002016020810190612d2f919061400b565b8d8d86818110612d4f57634e487b7160e01b600052603260045260246000fd5b905060200201358c8c87818110612d7657634e487b7160e01b600052603260045260246000fd5b905060200201358b8b8881811061249157634e487b7160e01b600052603260045260246000fd5b612e1c8d8d84818110612dc057634e487b7160e01b600052603260045260246000fd5b9050602002016020810190612dd5919061400b565b8c8c85818110612df557634e487b7160e01b600052603260045260246000fd5b905060200201358b8b86818110610fbe57634e487b7160e01b600052603260045260246000fd5b5080612e27816150c1565b915050612a7b565b5080604051612e3e9190614a58565b60405180910390207f5fb4aec6c096dfcae3899570b7e14f9743bb4b1801780db6d8a9c4ffe21aaaac8e8e8e8e8e8e8e8e8c8c604051612e879a99989796959493929190614be6565b60405180910390a250505050505050505050505050565b600086815260036020908152604080832081516080810183528154815260018201546001600160a01b0316938101939093526002810180549192840191612ee49061505a565b80601f0160208091040260200160405190810160405280929190818152602001828054612f109061505a565b8015612f5d5780601f10612f3257610100808354040283529160200191612f5d565b820191906000526020600020905b815481529060010190602001808311612f4057829003601f168201915b50505050508152602001600382018054612f769061505a565b80601f0160208091040260200160405190810160405280929190818152602001828054612fa29061505a565b8015612fef5780601f10612fc457610100808354040283529160200191612fef565b820191906000526020600020905b815481529060010190602001808311612fd257829003601f168201915b505050505081525050905061300c81602001518260400151613563565b6001600160a01b0388166130325760405162461bcd60e51b81526004016103f490614f1f565b6001600160a01b0389166130885760405162461bcd60e51b815260206004820152601f60248201527f5f66726f6d2061646472657373206d757374206265206e6f6e2d7a65726f2e0060448201526064016103f4565b6001600160a01b0389163314806130a457506130a4893361034b565b6130c05760405162461bcd60e51b81526004016103f490614d72565b856130cb8a8961038c565b10156131195760405162461bcd60e51b815260206004820152601e60248201527f5f66726f6d2062616c616e6365206c657373207468616e205f76616c7565000060448201526064016103f4565b876001600160a01b0316896001600160a01b031614613175576131758989898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061332492505050565b6131808888886136fb565b8060000151886001600160a01b03168a6001600160a01b03167fde6a12665e566ee081354e23cd8474944fb8e89a25b46f2f9b50d378e7e536088a8a88886040516131ce9493929190614f78565b60405180910390a4505050505050505050565b60036020526000908152604090208054600182015460028301805492936001600160a01b03909216926132139061505a565b80601f016020809104026020016040519081016040528092919081815260200182805461323f9061505a565b801561328c5780601f106132615761010080835404028352916020019161328c565b820191906000526020600020905b81548152906001019060200180831161326f57829003601f168201915b5050505050908060030180546132a19061505a565b80601f01602080910402602001604051908101604052809291908181526020018280546132cd9061505a565b801561331a5780601f106132ef5761010080835404028352916020019161331a565b820191906000526020600020905b8154815290600101906020018083116132fd57829003601f168201915b5050505050905084565b6001600160a01b0385163314806133405750613340853361034b565b61339e5760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2063616c6c6572206973206e6f74206f776e6572206e6f7260448201526808185c1c1c9bdd995960ba1b60648201526084016103f4565b61059985858585856138c7565b81518351146133cc5760405162461bcd60e51b81526004016103f490614e96565b6001600160a01b0384166133f25760405162461bcd60e51b81526004016103f490614da0565b3360005b84518110156134f557600085828151811061342157634e487b7160e01b600052603260045260246000fd5b60200260200101519050600085838151811061344d57634e487b7160e01b600052603260045260246000fd5b602090810291909101810151600084815280835260408082206001600160a01b038e16835290935291909120549091508181101561349d5760405162461bcd60e51b81526004016103f490614de5565b6000838152602081815260408083206001600160a01b038e8116855292528083208585039055908b168252812080548492906134da908490614fff565b92505081905550505050806134ee906150c1565b90506133f6565b50846001600160a01b0316866001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8787604051613545929190614ce9565b60405180910390a461355b8187878787876139e4565b505050505050565b600080836001600160a01b03168360405161357e9190614a8e565b600060405180830381855afa9150503d80600081146135b9576040519150601f19603f3d011682016040523d82523d6000602084013e6135be565b606091505b50915091508180156135df5750808060200190518101906135df91906147d3565b6112965760405162461bcd60e51b815260206004820152601b60248201527f526571756573742f636572746966696361746520696e76616c6964000000000060448201526064016103f4565b6001600160a01b0384166136515760405162461bcd60e51b81526004016103f490614ede565b3361366b8160008761366288613b4f565b61059988613b4f565b6000848152602081815260408083206001600160a01b03891684529091528120805485929061369b908490614fff565b909155505060408051858152602081018590526001600160a01b0380881692600092918516917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a461059981600087878787613ba8565b613706838383613c72565b60008281526004602090815260408083206001600160a01b0387168452909152902054613734908290614fff565b60009283526004602090815260408085206001600160a01b039096168552949052929091209190915550565b6001600160a01b0384166137865760405162461bcd60e51b81526004016103f490614ede565b81518351146137a75760405162461bcd60e51b81526004016103f490614e96565b3360005b845181101561385f578381815181106137d457634e487b7160e01b600052603260045260246000fd5b60200260200101516000808784815181106137ff57634e487b7160e01b600052603260045260246000fd5b602002602001015181526020019081526020016000206000886001600160a01b03166001600160a01b0316815260200190815260200160002060008282546138479190614fff565b90915550819050613857816150c1565b9150506137ab565b50846001600160a01b031660006001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb87876040516138b0929190614ce9565b60405180910390a4610599816000878787876139e4565b6001600160a01b0384166138ed5760405162461bcd60e51b81526004016103f490614da0565b336138fd81878761366288613b4f565b6000848152602081815260408083206001600160a01b038a1684529091529020548381101561393e5760405162461bcd60e51b81526004016103f490614de5565b6000858152602081815260408083206001600160a01b038b811685529252808320878503905590881682528120805486929061397b908490614fff565b909155505060408051868152602081018690526001600160a01b03808916928a821692918616917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a46139db828888888888613ba8565b50505050505050565b6001600160a01b0384163b1561355b5760405163bc197c8160e01b81526001600160a01b0385169063bc197c8190613a289089908990889088908890600401614aaa565b602060405180830381600087803b158015613a4257600080fd5b505af1925050508015613a72575060408051601f3d908101601f19168201909252613a6f9181019061480b565b60015b613b1f57613a7e615108565b806308c379a01415613ab85750613a93615120565b80613a9e5750613aba565b8060405162461bcd60e51b81526004016103f49190614d17565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e20455243313135356044820152732932b1b2b4bb32b91034b6b83632b6b2b73a32b960611b60648201526084016103f4565b6001600160e01b0319811663bc197c8160e01b146139db5760405162461bcd60e51b81526004016103f490614d2a565b60408051600180825281830190925260609160009190602080830190803683370190505090508281600081518110613b9757634e487b7160e01b600052603260045260246000fd5b602090810291909101015292915050565b6001600160a01b0384163b1561355b5760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190613bec9089908990889088908890600401614b08565b602060405180830381600087803b158015613c0657600080fd5b505af1925050508015613c36575060408051601f3d908101601f19168201909252613c339181019061480b565b60015b613c4257613a7e615108565b6001600160e01b0319811663f23a6e6160e01b146139db5760405162461bcd60e51b81526004016103f490614d2a565b6001600160a01b038316613cd45760405162461bcd60e51b815260206004820152602360248201527f455243313135353a206275726e2066726f6d20746865207a65726f206164647260448201526265737360e81b60648201526084016103f4565b33613d0481856000613ce587613b4f565b613cee87613b4f565b5050604080516020810190915260009052505050565b6000838152602081815260408083206001600160a01b038816845290915290205482811015613d815760405162461bcd60e51b8152602060048201526024808201527f455243313135353a206275726e20616d6f756e7420657863656564732062616c604482015263616e636560e01b60648201526084016103f4565b6000848152602081815260408083206001600160a01b03898116808652918452828520888703905582518981529384018890529092908616917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a45050505050565b828054613df89061505a565b90600052602060002090601f016020900481019282613e1a5760008555613e60565b82601f10613e3357805160ff1916838001178555613e60565b82800160010185558215613e60579182015b82811115613e60578251825591602001919060010190613e45565b50613e6c929150613e70565b5090565b5b80821115613e6c5760008155600101613e71565b80356001600160a01b0381168114613e9c57600080fd5b919050565b60008083601f840112613eb2578182fd5b5081356001600160401b03811115613ec8578182fd5b6020830191508360208260051b8501011115613ee357600080fd5b9250929050565b600082601f830112613efa578081fd5b81356020613f0782614fdc565b604051613f148282615095565b8381528281019150858301600585901b87018401881015613f33578586fd5b855b85811015613f5157813584529284019290840190600101613f35565b5090979650505050505050565b60008083601f840112613f6f578182fd5b5081356001600160401b03811115613f85578182fd5b602083019150836020828501011115613ee357600080fd5b600082601f830112613fad578081fd5b81356001600160401b03811115613fc657613fc66150f2565b604051613fdd601f8301601f191660200182615095565b818152846020838601011115613ff1578283fd5b816020850160208301379081016020019190915292915050565b60006020828403121561401c578081fd5b61402582613e85565b9392505050565b6000806040838503121561403e578081fd5b61404783613e85565b915061405560208401613e85565b90509250929050565b60008060008060008060008060008060c08b8d03121561407c578586fd5b6140858b613e85565b995061409360208c01613e85565b985060408b01356001600160401b03808211156140ae578788fd5b6140ba8e838f01613ea1565b909a50985060608d01359150808211156140d2578788fd5b6140de8e838f01613ea1565b909850965060808d01359150808211156140f6578586fd5b6141028e838f01613f5e565b909650945060a08d013591508082111561411a578384fd5b506141278d828e01613ea1565b915080935050809150509295989b9194979a5092959850565b600080600080600060a08688031215614157578081fd5b61416086613e85565b945061416e60208701613e85565b935060408601356001600160401b0380821115614189578283fd5b61419589838a01613eea565b945060608801359150808211156141aa578283fd5b6141b689838a01613eea565b935060808801359150808211156141cb578283fd5b506141d888828901613f9d565b9150509295509295909350565b60008060008060008060008060c0898b031215614200578384fd5b61420989613e85565b975061421760208a01613e85565b9650604089013595506060890135945060808901356001600160401b0380821115614240578586fd5b61424c8c838d01613f5e565b909650945060a08b0135915080821115614264578384fd5b506142718b828c01613f5e565b999c989b5096995094979396929594505050565b600080600080600060a0868803121561429c578283fd5b6142a586613e85565b94506142b360208701613e85565b9350604086013592506060860135915060808601356001600160401b038111156142db578182fd5b6141d888828901613f9d565b600080600080600080600080600060a08a8c031215614304578283fd5b61430d8a613e85565b985060208a01356001600160401b0380821115614328578485fd5b6143348d838e01613ea1565b909a50985060408c013591508082111561434c578485fd5b6143588d838e01613ea1565b909850965060608c0135915080821115614370578485fd5b61437c8d838e01613ea1565b909650945060808c0135915080821115614394578384fd5b506143a18c828d01613ea1565b915080935050809150509295985092959850929598565b600080604083850312156143ca578182fd5b6143d383613e85565b915060208301356143e3816151a9565b809150509250929050565b600080600080600080600060a0888a031215614408578081fd5b61441188613e85565b965060208801356001600160401b038082111561442c578283fd5b6144388b838c01613f5e565b909850965060408a0135955060608a0135945060808a013591508082111561445e578283fd5b5061446b8a828b01613f5e565b989b979a50959850939692959293505050565b60008060408385031215614490578182fd5b61449983613e85565b946020939093013593505050565b60008060008060008060008060008060a08b8d0312156144c5578384fd5b8a356001600160401b03808211156144db578586fd5b6144e78e838f01613ea1565b909c509a5060208d01359150808211156144ff578586fd5b61450b8e838f01613ea1565b909a50985060408d0135915080821115614523578586fd5b61452f8e838f01613ea1565b909850965060608d0135915080821115614547578586fd5b6145538e838f01613ea1565b909650945060808d013591508082111561411a578384fd5b60008060008060008060008060008060008060c08d8f03121561458c578586fd5b6001600160401b038d3511156145a0578586fd5b6145ad8e8e358f01613ea1565b909c509a506001600160401b0360208e013511156145c9578586fd5b6145d98e60208f01358f01613ea1565b909a5098506001600160401b0360408e013511156145f5578586fd5b6146058e60408f01358f01613ea1565b90985096506001600160401b0360608e01351115614621578586fd5b6146318e60608f01358f01613ea1565b90965094506001600160401b0360808e0135111561464d578081fd5b61465d8e60808f01358f01613ea1565b90945092506001600160401b0360a08e01351115614679578081fd5b6146898e60a08f01358f01613ea1565b81935080925050509295989b509295989b509295989b565b600080600080604085870312156146b6578182fd5b84356001600160401b03808211156146cc578384fd5b6146d888838901613ea1565b909650945060208701359150808211156146f0578384fd5b506146fd87828801613ea1565b95989497509550505050565b6000806040838503121561471b578182fd5b82356001600160401b0380821115614731578384fd5b818501915085601f830112614744578384fd5b8135602061475182614fdc565b60405161475e8282615095565b8381528281019150858301600585901b870184018b101561477d578889fd5b8896505b848710156147a65761479281613e85565b835260019690960195918301918301614781565b50965050860135925050808211156147bc578283fd5b506147c985828601613eea565b9150509250929050565b6000602082840312156147e4578081fd5b8151614025816151a9565b600060208284031215614800578081fd5b8135614025816151ba565b60006020828403121561481c578081fd5b8151614025816151ba565b600060208284031215614838578081fd5b5035919050565b600060208284031215614850578081fd5b5051919050565b60008060408385031215614869578182fd5b8235915061405560208401613e85565b60008060006060848603121561488d578081fd5b8335925061489d60208501613e85565b9150604084013590509250925092565b81835260006020808501945082825b858110156148e8576001600160a01b036148d583613e85565b16875295820195908201906001016148bc565b509495945050505050565b60008383855260208086019550808560051b83010184845b87811015613f5157848303601f19018952813536889003601e19018112614930578687fd5b870180356001600160401b03811115614947578788fd5b803603891315614955578788fd5b61496285828885016149d9565b9a86019a945050509083019060010161490b565b81835260006001600160fb1b0383111561498e578081fd5b8260051b80836020870137939093016020019283525090919050565b6000815180845260208085019450808401835b838110156148e8578151875295820195908201906001016149bd565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60008151808452614a1a81602086016020860161502e565b601f01601f19169290920160200192915050565b60006001600160fb1b03831115614a43578081fd5b8260051b808584379190910190815292915050565b815160009082906020808601845b83811015614a8257815185529382019390820190600101614a66565b50929695505050505050565b60008251614aa081846020870161502e565b9190910192915050565b6001600160a01b0386811682528516602082015260a060408201819052600090614ad6908301866149aa565b8281036060840152614ae881866149aa565b90508281036080840152614afc8185614a02565b98975050505050505050565b6001600160a01b03868116825285166020820152604081018490526060810183905260a060808201819052600090614b4290830184614a02565b979650505050505050565b60018060a01b0385168152836020820152608060408201526000614b746080830185614a02565b8281036060840152614b428185614a02565b608081526000614b9a608083018a8c6148ad565b8281036020840152614bad81898b6148ad565b90508281036040840152614bc2818789614976565b90508281036060840152614bd7818587614976565b9b9a5050505050505050505050565b60a081526000614bfa60a083018c8e6148ad565b8281036020840152614c0d818b8d6148ad565b90508281036040840152614c2281898b614976565b90508281036060840152614c37818789614976565b90508281036080840152614c4c8185876148f3565b9d9c50505050505050505050505050565b606081526000614c7160608301888a614976565b8281036020840152614c84818789614976565b90508281036040840152614c998185876148f3565b9998505050505050505050565b60208152600061402560208301846149aa565b604081526000614ccc60408301866149aa565b8281036020840152614cdf818587614976565b9695505050505050565b604081526000614cfc60408301856149aa565b8281036020840152614d0e81856149aa565b95945050505050565b6020815260006140256020830184614a02565b60208082526028908201527f455243313135353a204552433131353552656365697665722072656a656374656040820152676420746f6b656e7360c01b606082015260800190565b602080825260149082015273139bc81bdc195c985d1bdc88185c1c1c9bdd985b60621b604082015260600190565b60208082526025908201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604082015264647265737360d81b606082015260800190565b6020808252602a908201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60408201526939103a3930b739b332b960b11b606082015260800190565b60208082526017908201527f417272617973206e6f742073616d65206c656e6774682e000000000000000000604082015260600190565b602080825260169082015275082e4e4c2f2e640dcdee840e6c2daca40d8cadccee8d60531b604082015260600190565b60208082526028908201527f455243313135353a2069647320616e6420616d6f756e7473206c656e677468206040820152670dad2e6dac2e8c6d60c31b606082015260800190565b60208082526021908201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736040820152607360f81b606082015260800190565b6020808252601590820152742fba379036bab9ba103132903737b716bd32b9379760591b604082015260600190565b8481526001600160a01b0384166020820152608060408201819052600090614b7490830185614a02565b848152836020820152606060408201526000614cdf6060830184866149d9565b6000808335601e19843603018112614fae578283fd5b8301803591506001600160401b03821115614fc7578283fd5b602001915036819003821315613ee357600080fd5b60006001600160401b03821115614ff557614ff56150f2565b5060051b60200190565b60008219821115615012576150126150dc565b500190565b600082821015615029576150296150dc565b500390565b60005b83811015615049578181015183820152602001615031565b838111156112965750506000910152565b600181811c9082168061506e57607f821691505b6020821081141561508f57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8201601f191681016001600160401b03811182821017156150ba576150ba6150f2565b6040525050565b60006000198214156150d5576150d56150dc565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600060033d111561511d57600481823e5160e01c5b90565b600060443d101561512e5790565b6040516003193d81016004833e81513d6001600160401b03816024840111818411171561515d57505050505090565b82850191508151818111156151755750505050505090565b843d870101602082850101111561518f5750505050505090565b61519e60208286010187615095565b509095945050505050565b80151581146151b757600080fd5b50565b6001600160e01b0319811681146151b757600080fdfea26469706673582212201fcc2a6d641dda60e8c8e8c5f20ec97063420fba03f88e88fe47cdf69e4ec9a264736f6c63430008040033