This contract has been partially verified via Sourcify.
View contract in Sourcify repository
- Contract name:
- RegistryExtended
- Optimization enabled
- true
- Compiler version
- v0.8.4+commit.c7e474f2
- Optimization runs
- 200
- EVM Version
- istanbul
- Verified at
- 2025-07-18T16:31:51.079749Z
RegistryExtended.sol
//./packages/traceability/issuer/contracts$ truffle-flattener RegistryExtended.sol
// File: @openzeppelin/contracts/utils/introspection/IERC165.sol
//
// OpenZeppelin Contracts v4.4.1 (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: @openzeppelin/contracts/token/ERC1155/IERC1155.sol
//
// OpenZeppelin Contracts v4.4.1 (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: @openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol
//
// OpenZeppelin Contracts v4.4.1 (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: @openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol
//
// OpenZeppelin Contracts v4.4.1 (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: @openzeppelin/contracts/utils/Address.sol
//
// OpenZeppelin Contracts v4.4.1 (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: @openzeppelin/contracts/utils/Context.sol
//
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
// File: @openzeppelin/contracts/utils/introspection/ERC165.sol
//
// OpenZeppelin Contracts v4.4.1 (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: @openzeppelin/contracts/token/ERC1155/ERC1155.sol
//
// OpenZeppelin Contracts v4.4.1 (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 {
_setApprovalForAll(_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 `to`.
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
* acceptance magic value.
*/
function _mint(
address to,
uint256 id,
uint256 amount,
bytes memory data
) internal virtual {
require(to != address(0), "ERC1155: mint to the zero address");
address operator = _msgSender();
_beforeTokenTransfer(operator, address(0), to, _asSingletonArray(id), _asSingletonArray(amount), data);
_balances[id][to] += amount;
emit TransferSingle(operator, address(0), to, id, amount);
_doSafeTransferAcceptanceCheck(operator, address(0), to, 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 `from`
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `from` must have at least `amount` tokens of token type `id`.
*/
function _burn(
address from,
uint256 id,
uint256 amount
) internal virtual {
require(from != address(0), "ERC1155: burn from the zero address");
address operator = _msgSender();
_beforeTokenTransfer(operator, from, address(0), _asSingletonArray(id), _asSingletonArray(amount), "");
uint256 fromBalance = _balances[id][from];
require(fromBalance >= amount, "ERC1155: burn amount exceeds balance");
unchecked {
_balances[id][from] = fromBalance - amount;
}
emit TransferSingle(operator, from, 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 from,
uint256[] memory ids,
uint256[] memory amounts
) internal virtual {
require(from != address(0), "ERC1155: burn from the zero address");
require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
address operator = _msgSender();
_beforeTokenTransfer(operator, from, address(0), ids, amounts, "");
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: burn amount exceeds balance");
unchecked {
_balances[id][from] = fromBalance - amount;
}
}
emit TransferBatch(operator, from, address(0), ids, amounts);
}
/**
* @dev Approve `operator` to operate on all of `owner` tokens
*
* Emits a {ApprovalForAll} event.
*/
function _setApprovalForAll(
address owner,
address operator,
bool approved
) internal virtual {
require(owner != operator, "ERC1155: setting approval status for self");
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
/**
* @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/ERC1888/IERC1888.sol
//
pragma solidity 0.8.4;
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;
/// @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
// SPDX-License-Identifier: MIT
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
0x608060405234801561001057600080fd5b50600436106101365760003560e01c80638673605a116100b8578063ba688a941161007c578063ba688a94146102c9578063c48238b0146102dc578063c5308dd814610307578063d6878ffb1461031a578063e985e9c51461033d578063f242432a1461037957600080fd5b80638673605a1461026a5780638838a9d71461027d5780638ed8707514610290578063a22cb465146102a3578063b93bbaa0146102b657600080fd5b80634e1273f4116100ff5780634e1273f4146101ee57806351640fee1461020e578063543d526d14610231578063760c6caf14610244578063836a10401461025757600080fd5b8062fdd58e1461013b57806301ffc9a7146101615780630e89341c146101845780632eb2c2d6146101a45780633ebbaaa5146101b9575b600080fd5b61014e610149366004614497565b61038c565b6040519081526020015b60405180910390f35b61017461016f366004614808565b610423565b6040519015158152602001610158565b610197610192366004614840565b610475565b6040516101589190614d30565b6101b76101b2366004614159565b610509565b005b61014e6101c7366004614497565b60009081526004602090815260408083206001600160a01b03949094168352929052205490565b6102016101fc366004614722565b6105a0565b6040516101589190614cbf565b61022161021c366004614840565b610701565b6040516101589493929190614b66565b61014e61023f366004614407565b6108ca565b6101b7610252366004614077565b610aed565b6101b7610265366004614892565b611056565b610201610278366004614300565b61129c565b61020161028b3660046144c0565b6116e8565b61020161029e3660046146ba565b611c63565b6101b76102b13660046143d1565b611e3a565b6101b76102c43660046144c0565b611e49565b6101b76102d7366004614584565b612482565b61014e6102ea366004614870565b600460209081526000928352604080842090915290825290205481565b6101b76103153660046141fe565b612dd6565b61032d610328366004614840565b613119565b6040516101589493929190614f67565b61017461034b366004614045565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205460ff1690565b6101b761038736600461429e565b61325c565b60006001600160a01b0383166103fd5760405162461bcd60e51b815260206004820152602b60248201527f455243313135353a2062616c616e636520717565727920666f7220746865207a60448201526a65726f206164647265737360a81b60648201526084015b60405180910390fd5b506000908152602081815260408083206001600160a01b03949094168352929052205490565b60006001600160e01b03198216636cdb3d1360e11b148061045457506001600160e01b031982166303a24d0760e21b145b8061046f57506301ffc9a760e01b6001600160e01b03198316145b92915050565b60606002805461048490615073565b80601f01602080910402602001604051908101604052809291908181526020018280546104b090615073565b80156104fd5780601f106104d2576101008083540402835291602001916104fd565b820191906000526020600020905b8154815290600101906020018083116104e057829003601f168201915b50505050509050919050565b6001600160a01b0385163314806105255750610525853361034b565b61058c5760405162461bcd60e51b815260206004820152603260248201527f455243313135353a207472616e736665722063616c6c6572206973206e6f74206044820152711bdddb995c881b9bdc88185c1c1c9bdd995960721b60648201526084016103f4565b61059985858585856132e3565b5050505050565b606081518351146106055760405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e677468604482015268040dad2e6dac2e8c6d60bb1b60648201526084016103f4565b600083516001600160401b0381111561062e57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610657578160200160208202803683370190505b50905060005b84518110156106f9576106be85828151811061068957634e487b7160e01b600052603260045260246000fd5b60200260200101518583815181106106b157634e487b7160e01b600052603260045260246000fd5b602002602001015161038c565b8282815181106106de57634e487b7160e01b600052603260045260246000fd5b60209081029190910101526106f2816150da565b905061065d565b509392505050565b60008060608060055485111561074d5760405162461bcd60e51b81526020600482015260116024820152705f6964206f7574206f6620626f756e647360781b60448201526064016103f4565b600085815260036020908152604080832081516080810183528154815260018201546001600160a01b031693810193909352600281018054919284019161079390615073565b80601f01602080910402602001604051908101604052809291908181526020018280546107bf90615073565b801561080c5780601f106107e15761010080835404028352916020019161080c565b820191906000526020600020905b8154815290600101906020018083116107ef57829003601f168201915b5050505050815260200160038201805461082590615073565b80601f016020809104026020016040519081016040528092919081815260200182805461085190615073565b801561089e5780601f106108735761010080835404028352916020019161089e565b820191906000526020600020905b81548152906001019060200180831161088157829003601f168201915b505050919092525050506020810151815160408301516060909301519199909850919650945092505050565b60006001600160a01b0388166108f25760405162461bcd60e51b81526004016103f490614f38565b6109323388888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061349b92505050565b600560008154610941906150da565b9182905550905061098188828660005b6040519080825280601f01601f19166020018201604052801561097b576020820181803683370190505b50613563565b60405180608001604052808681526020016109993390565b6001600160a01b0316815260200188888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250604080516020601f87018190048102820181019092528581529181019190869086908190840183828082843760009201829052509390945250508381526003602090815260409182902084518155848201516001820180546001600160a01b0319166001600160a01b03909216919091179055918401518051929350610a6f9260028501929190910190613e05565b5060608201518051610a8b916003840191602090910190613e05565b5090505084610a973390565b6001600160a01b03167f19fdba3b3fa810260206510aa7278c70ea23c0d104195bed67bfb27a3d82fbfe8387604051610ada929190918252602082015260400190565b60405180910390a3979650505050505050565b6001600160a01b038916610b435760405162461bcd60e51b815260206004820152601c60248201527f5f746f2061646472657373206d757374206265206e6f6e2d7a65726f0000000060448201526064016103f4565b6001600160a01b038a16610b995760405162461bcd60e51b815260206004820152601e60248201527f5f66726f6d2061646472657373206d757374206265206e6f6e2d7a65726f000060448201526064016103f4565b868514610bb85760405162461bcd60e51b81526004016103f490614e7f565b848114610bd75760405162461bcd60e51b81526004016103f490614e48565b6001600160a01b038a16331480610bf35750610bf38a3361034b565b610c0f5760405162461bcd60e51b81526004016103f490614d8b565b86610c585760405162461bcd60e51b81526020600482015260196024820152781b9bc818d95c9d1a599a58d85d195cc81cdc1958da599a5959603a1b60448201526064016103f4565b866000816001600160401b03811115610c8157634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610caa578160200160208202803683370190505b50905060005b82811015610e9a576000600360008d8d85818110610cde57634e487b7160e01b600052603260045260246000fd5b6020908102929092013583525081810192909252604090810160002081516080810183528154815260018201546001600160a01b0316938101939093526002810180549192840191610d2f90615073565b80601f0160208091040260200160405190810160405280929190818152602001828054610d5b90615073565b8015610da85780601f10610d7d57610100808354040283529160200191610da8565b820191906000526020600020905b815481529060010190602001808311610d8b57829003601f168201915b50505050508152602001600382018054610dc190615073565b80601f0160208091040260200160405190810160405280929190818152602001828054610ded90615073565b8015610e3a5780601f10610e0f57610100808354040283529160200191610e3a565b820191906000526020600020905b815481529060010190602001808311610e1d57829003601f168201915b5050505050815250509050610e578160200151826040015161349b565b8060000151838381518110610e7c57634e487b7160e01b600052603260045260246000fd5b60209081029190910101525080610e92816150da565b915050610cb0565b508a6001600160a01b03168c6001600160a01b031614610f6857610f688c8c8c8c80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508b8b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020601f8f018190048102820181019092528d815292508d91508c908190840183828082843760009201919091525061050992505050565b60005b82811015610fdc57610fca8c8c8c84818110610f9757634e487b7160e01b600052603260045260246000fd5b905060200201358b8b85818110610fbe57634e487b7160e01b600052603260045260246000fd5b90506020020135613633565b80610fd4816150da565b915050610f6b565b5080604051610feb9190614a71565b60405180910390208b6001600160a01b03168d6001600160a01b03167f61a69d58bffe77be60879031f7e6d3d17fab9c88a681899a549d20ae8a39f8d08d8d8d8d8b8b60405161104096959493929190614c76565b60405180910390a4505050505050505050505050565b6001600160a01b03821661107c5760405162461bcd60e51b81526004016103f490614f38565b600081116110cc5760405162461bcd60e51b815260206004820152601a60248201527f5f7175616e74697479206d7573742062652061626f766520302e00000000000060448201526064016103f4565b600083815260036020908152604080832081516080810183528154815260018201546001600160a01b031693810193909352600281018054919284019161111290615073565b80601f016020809104026020016040519081016040528092919081815260200182805461113e90615073565b801561118b5780601f106111605761010080835404028352916020019161118b565b820191906000526020600020905b81548152906001019060200180831161116e57829003601f168201915b505050505081526020016003820180546111a490615073565b80601f01602080910402602001604051908101604052809291908181526020018280546111d090615073565b801561121d5780601f106111f25761010080835404028352916020019161121d565b820191906000526020600020905b81548152906001019060200180831161120057829003601f168201915b505050505081525050905080602001516001600160a01b031661123d3390565b6001600160a01b0316146112895760405162461bcd60e51b81526020600482015260136024820152722737ba1037b934b3b4b730b61034b9b9bab2b960691b60448201526064016103f4565b6112968385846000610951565b50505050565b60606001600160a01b038a166112c45760405162461bcd60e51b81526004016103f490614f38565b8184146112e35760405162461bcd60e51b81526004016103f490614e7f565b8388146113025760405162461bcd60e51b81526004016103f490614e7f565b836001600160401b0381111561132857634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611351578160200160208202803683370190505b5090503360005b8581116114255760055461136c9082615018565b611377906001615018565b83828151811061139757634e487b7160e01b600052603260045260246000fd5b602002602001018181525050611413828c8c848181106113c757634e487b7160e01b600052603260045260246000fd5b90506020028101906113d99190614fb1565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061349b92505050565b8061141d816150da565b915050611358565b506114948b8388888080602002602001604051908101604052809392919081815260200183836020028082843760009201829052509250611464915050565b6040519080825280601f01601f19166020018201604052801561148e576020820181803683370190505b50613698565b60005b825181101561167c5760405180608001604052808a8a848181106114cb57634e487b7160e01b600052603260045260246000fd5b905060200201358152602001836001600160a01b031681526020018c8c8481811061150657634e487b7160e01b600052603260045260246000fd5b90506020028101906115189190614fb1565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060200186868481811061157257634e487b7160e01b600052603260045260246000fd5b90506020028101906115849190614fb1565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052509390945250508551600392508690859081106115e057634e487b7160e01b600052603260045260246000fd5b602002602001015181526020019081526020016000206000820151816000015560208201518160010160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506040820151816002019080519060200190611649929190613e05565b5060608201518051611665916003840191602090910190613e05565b509050508080611674906150da565b915050611497565b50878760405161168d929190614a47565b6040518091039020816001600160a01b03167f4337762bcc37db59d5eea698d442c9782e625db731704f4f83ed376a09b64e6c8489896040516116d293929190614cd2565b60405180910390a3509998505050505050505050565b60608361172d5760405162461bcd60e51b81526020600482015260136024820152721b9bc81d985b1d595cc81cdc1958da599a5959606a1b60448201526064016103f4565b89821461174c5760405162461bcd60e51b81526004016103f490614e7f565b81841461176b5760405162461bcd60e51b81526004016103f490614e7f565b83881461178a5760405162461bcd60e51b81526004016103f490614e7f565b8786146117a95760405162461bcd60e51b81526004016103f490614e7f565b836001600160401b038111156117cf57634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156117f8578160200160208202803683370190505b5090503360005b858110156118df5760008d8d8381811061182957634e487b7160e01b600052603260045260246000fd5b905060200201602081019061183e9190614024565b6001600160a01b031614156118655760405162461bcd60e51b81526004016103f490614f38565b6005546118729082615018565b61187d906001615018565b83828151811061189d57634e487b7160e01b600052603260045260246000fd5b6020026020010181815250506118cd828c8c848181106113c757634e487b7160e01b600052603260045260246000fd5b806118d7816150da565b9150506117ff565b5060005b8251811015611bbb576119df8d8d8381811061190f57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906119249190614024565b84838151811061194457634e487b7160e01b600052603260045260246000fd5b602002602001015189898581811061196c57634e487b7160e01b600052603260045260246000fd5b9050602002013588888681811061199357634e487b7160e01b600052603260045260246000fd5b90506020028101906119a59190614fb1565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061356392505050565b60405180608001604052808a8a84818110611a0a57634e487b7160e01b600052603260045260246000fd5b905060200201358152602001836001600160a01b031681526020018c8c84818110611a4557634e487b7160e01b600052603260045260246000fd5b9050602002810190611a579190614fb1565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250602001868684818110611ab157634e487b7160e01b600052603260045260246000fd5b9050602002810190611ac39190614fb1565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250939094525050855160039250869085908110611b1f57634e487b7160e01b600052603260045260246000fd5b602002602001015181526020019081526020016000206000820151816000015560208201518160010160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506040820151816002019080519060200190611b88929190613e05565b5060608201518051611ba4916003840191602090910190613e05565b509050508080611bb3906150da565b9150506118e3565b508160018351611bcb9190615030565b81518110611be957634e487b7160e01b600052603260045260246000fd5b60200260200101516005819055508787604051611c07929190614a47565b6040518091039020816001600160a01b03167f4337762bcc37db59d5eea698d442c9782e625db731704f4f83ed376a09b64e6c848989604051611c4c93929190614cd2565b60405180910390a3509a9950505050505050505050565b6060838214611cb45760405162461bcd60e51b815260206004820152601e60248201527f6f776e65727320616e6420696473206c656e677468206d69736d61746368000060448201526064016103f4565b6000846001600160401b03811115611cdc57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611d05578160200160208202803683370190505b50905060005b85811015611e305730633ebbaaa5888884818110611d3957634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611d4e9190614024565b878785818110611d6e57634e487b7160e01b600052603260045260246000fd5b6040516001600160e01b031960e087901b1681526001600160a01b039094166004850152602002919091013560248301525060440160206040518083038186803b158015611dbb57600080fd5b505afa158015611dcf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611df39190614858565b828281518110611e1357634e487b7160e01b600052603260045260246000fd5b602090810291909101015280611e28816150da565b915050611d0b565b5095945050505050565b611e453383836137ff565b5050565b888714611e685760405162461bcd60e51b81526004016103f490614e7f565b868514611e875760405162461bcd60e51b81526004016103f490614e7f565b848314611ea65760405162461bcd60e51b81526004016103f490614e7f565b828114611ec55760405162461bcd60e51b81526004016103f490614e48565b60005b858110156122e15760008b8b83818110611ef257634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611f079190614024565b6001600160a01b03161415611f585760405162461bcd60e51b81526020600482015260176024820152762fb33937b69036bab9ba103132903737b716bd32b9379760491b60448201526064016103f4565b6000898983818110611f7a57634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611f8f9190614024565b6001600160a01b03161415611fb65760405162461bcd60e51b81526004016103f490614f38565b338b8b83818110611fd757634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611fec9190614024565b6001600160a01b0316148061203a575061203a8b8b8381811061201f57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906120349190614024565b3361034b565b6120565760405162461bcd60e51b81526004016103f490614d8b565b84848281811061207657634e487b7160e01b600052603260045260246000fd5b905060200201356120e18c8c848181106120a057634e487b7160e01b600052603260045260246000fd5b90506020020160208101906120b59190614024565b8989858181106120d557634e487b7160e01b600052603260045260246000fd5b9050602002013561038c565b101561212f5760405162461bcd60e51b815260206004820152601e60248201527f4e6f7420656e6f7567682062616c616e636520746f207472616e73666572000060448201526064016103f4565b60006003600089898581811061215557634e487b7160e01b600052603260045260246000fd5b6020908102929092013583525081810192909252604090810160002081516080810183528154815260018201546001600160a01b03169381019390935260028101805491928401916121a690615073565b80601f01602080910402602001604051908101604052809291908181526020018280546121d290615073565b801561221f5780601f106121f45761010080835404028352916020019161221f565b820191906000526020600020905b81548152906001019060200180831161220257829003601f168201915b5050505050815260200160038201805461223890615073565b80601f016020809104026020016040519081016040528092919081815260200182805461226490615073565b80156122b15780601f10612286576101008083540402835291602001916122b1565b820191906000526020600020905b81548152906001019060200180831161229457829003601f168201915b50505050508152505090506122ce8160200151826040015161349b565b50806122d9816150da565b915050611ec8565b503360005b86811015612425576124158c8c8381811061231157634e487b7160e01b600052603260045260246000fd5b90506020020160208101906123269190614024565b8b8b8481811061234657634e487b7160e01b600052603260045260246000fd5b905060200201602081019061235b9190614024565b8a8a8581811061237b57634e487b7160e01b600052603260045260246000fd5b905060200201358989868181106123a257634e487b7160e01b600052603260045260246000fd5b905060200201358888878181106123c957634e487b7160e01b600052603260045260246000fd5b90506020028101906123db9190614fb1565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506138e092505050565b61241e816150da565b90506122e6565b50806001600160a01b03167f9a17c5980bc0d14e313aaa844f04cd0ee291f743df00bf06337a3ce1db563be48c8c8c8c8c8c8c8c60405161246d989796959493929190614b9f565b60405180910390a25050505050505050505050565b866124cb5760405162461bcd60e51b81526020600482015260196024820152781b9bc818d95c9d1a599a58d85d195cc81cdc1958da599a5959603a1b60448201526064016103f4565b8a89146124ea5760405162461bcd60e51b81526004016103f490614e7f565b8887146125095760405162461bcd60e51b81526004016103f490614e7f565b8685146125285760405162461bcd60e51b81526004016103f490614e7f565b8483146125475760405162461bcd60e51b81526004016103f490614e48565b8281146125665760405162461bcd60e51b81526004016103f490614e48565b6000876001600160401b0381111561258e57634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156125b7578160200160208202803683370190505b50905060005b888110156129af5760008e8e838181106125e757634e487b7160e01b600052603260045260246000fd5b90506020020160208101906125fc9190614024565b6001600160a01b0316141561264d5760405162461bcd60e51b81526020600482015260176024820152762fb33937b69036bab9ba103132903737b716bd32b9379760491b60448201526064016103f4565b60008c8c8381811061266f57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906126849190614024565b6001600160a01b031614156126ab5760405162461bcd60e51b81526004016103f490614f38565b338e8e838181106126cc57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906126e19190614024565b6001600160a01b0316148061271457506127148e8e8381811061201f57634e487b7160e01b600052603260045260246000fd5b6127305760405162461bcd60e51b81526004016103f490614d8b565b87878281811061275057634e487b7160e01b600052603260045260246000fd5b905060200201356127af8f8f8481811061277a57634e487b7160e01b600052603260045260246000fd5b905060200201602081019061278f9190614024565b8c8c858181106120d557634e487b7160e01b600052603260045260246000fd5b10156127fd5760405162461bcd60e51b815260206004820152601b60248201527f4e6f7420656e6f7567682062616c616e636520746f20636c61696d000000000060448201526064016103f4565b6000600360008c8c8581811061282357634e487b7160e01b600052603260045260246000fd5b6020908102929092013583525081810192909252604090810160002081516080810183528154815260018201546001600160a01b031693810193909352600281018054919284019161287490615073565b80601f01602080910402602001604051908101604052809291908181526020018280546128a090615073565b80156128ed5780601f106128c2576101008083540402835291602001916128ed565b820191906000526020600020905b8154815290600101906020018083116128d057829003601f168201915b5050505050815260200160038201805461290690615073565b80601f016020809104026020016040519081016040528092919081815260200182805461293290615073565b801561297f5780601f106129545761010080835404028352916020019161297f565b820191906000526020600020905b81548152906001019060200180831161296257829003601f168201915b505050505081525050905061299c8160200151826040015161349b565b50806129a7816150da565b9150506125bd565b5060005b88811015612d67576000600360008c8c858181106129e157634e487b7160e01b600052603260045260246000fd5b6020908102929092013583525081810192909252604090810160002081516080810183528154815260018201546001600160a01b0316938101939093526002810180549192840191612a3290615073565b80601f0160208091040260200160405190810160405280929190818152602001828054612a5e90615073565b8015612aab5780601f10612a8057610100808354040283529160200191612aab565b820191906000526020600020905b815481529060010190602001808311612a8e57829003601f168201915b50505050508152602001600382018054612ac490615073565b80601f0160208091040260200160405190810160405280929190818152602001828054612af090615073565b8015612b3d5780601f10612b1257610100808354040283529160200191612b3d565b820191906000526020600020905b815481529060010190602001808311612b2057829003601f168201915b50505050508152505090508060000151838381518110612b6d57634e487b7160e01b600052603260045260246000fd5b6020026020010181815250508c8c83818110612b9957634e487b7160e01b600052603260045260246000fd5b9050602002016020810190612bae9190614024565b6001600160a01b03168f8f84818110612bd757634e487b7160e01b600052603260045260246000fd5b9050602002016020810190612bec9190614024565b6001600160a01b031614612cd557612cd58f8f84818110612c1d57634e487b7160e01b600052603260045260246000fd5b9050602002016020810190612c329190614024565b8e8e85818110612c5257634e487b7160e01b600052603260045260246000fd5b9050602002016020810190612c679190614024565b8d8d86818110612c8757634e487b7160e01b600052603260045260246000fd5b905060200201358c8c87818110612cae57634e487b7160e01b600052603260045260246000fd5b905060200201358b8b888181106123c957634e487b7160e01b600052603260045260246000fd5b612d548d8d84818110612cf857634e487b7160e01b600052603260045260246000fd5b9050602002016020810190612d0d9190614024565b8c8c85818110612d2d57634e487b7160e01b600052603260045260246000fd5b905060200201358b8b86818110610fbe57634e487b7160e01b600052603260045260246000fd5b5080612d5f816150da565b9150506129b3565b5080604051612d769190614a71565b60405180910390207f5fb4aec6c096dfcae3899570b7e14f9743bb4b1801780db6d8a9c4ffe21aaaac8e8e8e8e8e8e8e8e8c8c604051612dbf9a99989796959493929190614bff565b60405180910390a250505050505050505050505050565b600086815260036020908152604080832081516080810183528154815260018201546001600160a01b0316938101939093526002810180549192840191612e1c90615073565b80601f0160208091040260200160405190810160405280929190818152602001828054612e4890615073565b8015612e955780601f10612e6a57610100808354040283529160200191612e95565b820191906000526020600020905b815481529060010190602001808311612e7857829003601f168201915b50505050508152602001600382018054612eae90615073565b80601f0160208091040260200160405190810160405280929190818152602001828054612eda90615073565b8015612f275780601f10612efc57610100808354040283529160200191612f27565b820191906000526020600020905b815481529060010190602001808311612f0a57829003601f168201915b5050505050815250509050612f448160200151826040015161349b565b6001600160a01b038816612f6a5760405162461bcd60e51b81526004016103f490614f38565b6001600160a01b038916612fc05760405162461bcd60e51b815260206004820152601f60248201527f5f66726f6d2061646472657373206d757374206265206e6f6e2d7a65726f2e0060448201526064016103f4565b6001600160a01b038916331480612fdc5750612fdc893361034b565b612ff85760405162461bcd60e51b81526004016103f490614d8b565b856130038a8961038c565b10156130515760405162461bcd60e51b815260206004820152601e60248201527f5f66726f6d2062616c616e6365206c657373207468616e205f76616c7565000060448201526064016103f4565b876001600160a01b0316896001600160a01b0316146130ad576130ad8989898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061325c92505050565b6130b8888888613633565b8060000151886001600160a01b03168a6001600160a01b03167fde6a12665e566ee081354e23cd8474944fb8e89a25b46f2f9b50d378e7e536088a8a88886040516131069493929190614f91565b60405180910390a4505050505050505050565b60036020526000908152604090208054600182015460028301805492936001600160a01b039092169261314b90615073565b80601f016020809104026020016040519081016040528092919081815260200182805461317790615073565b80156131c45780601f10613199576101008083540402835291602001916131c4565b820191906000526020600020905b8154815290600101906020018083116131a757829003601f168201915b5050505050908060030180546131d990615073565b80601f016020809104026020016040519081016040528092919081815260200182805461320590615073565b80156132525780601f1061322757610100808354040283529160200191613252565b820191906000526020600020905b81548152906001019060200180831161323557829003601f168201915b5050505050905084565b6001600160a01b0385163314806132785750613278853361034b565b6132d65760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2063616c6c6572206973206e6f74206f776e6572206e6f7260448201526808185c1c1c9bdd995960ba1b60648201526084016103f4565b61059985858585856138e0565b81518351146133045760405162461bcd60e51b81526004016103f490614eaf565b6001600160a01b03841661332a5760405162461bcd60e51b81526004016103f490614db9565b3360005b845181101561342d57600085828151811061335957634e487b7160e01b600052603260045260246000fd5b60200260200101519050600085838151811061338557634e487b7160e01b600052603260045260246000fd5b602090810291909101810151600084815280835260408082206001600160a01b038e1683529093529190912054909150818110156133d55760405162461bcd60e51b81526004016103f490614dfe565b6000838152602081815260408083206001600160a01b038e8116855292528083208585039055908b16825281208054849290613412908490615018565b9250508190555050505080613426906150da565b905061332e565b50846001600160a01b0316866001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb878760405161347d929190614d02565b60405180910390a46134938187878787876139fd565b505050505050565b600080836001600160a01b0316836040516134b69190614aa7565b600060405180830381855afa9150503d80600081146134f1576040519150601f19603f3d011682016040523d82523d6000602084013e6134f6565b606091505b509150915081801561351757508080602001905181019061351791906147ec565b6112965760405162461bcd60e51b815260206004820152601b60248201527f526571756573742f636572746966696361746520696e76616c6964000000000060448201526064016103f4565b6001600160a01b0384166135895760405162461bcd60e51b81526004016103f490614ef7565b336135a38160008761359a88613b68565b61059988613b68565b6000848152602081815260408083206001600160a01b0389168452909152812080548592906135d3908490615018565b909155505060408051858152602081018590526001600160a01b0380881692600092918516917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a461059981600087878787613bc1565b61363e838383613c8b565b60008281526004602090815260408083206001600160a01b038716845290915290205461366c908290615018565b60009283526004602090815260408085206001600160a01b039096168552949052929091209190915550565b6001600160a01b0384166136be5760405162461bcd60e51b81526004016103f490614ef7565b81518351146136df5760405162461bcd60e51b81526004016103f490614eaf565b3360005b84518110156137975783818151811061370c57634e487b7160e01b600052603260045260246000fd5b602002602001015160008087848151811061373757634e487b7160e01b600052603260045260246000fd5b602002602001015181526020019081526020016000206000886001600160a01b03166001600160a01b03168152602001908152602001600020600082825461377f9190615018565b9091555081905061378f816150da565b9150506136e3565b50846001600160a01b031660006001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb87876040516137e8929190614d02565b60405180910390a4610599816000878787876139fd565b816001600160a01b0316836001600160a01b031614156138735760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c20737461747573604482015268103337b91039b2b63360b91b60648201526084016103f4565b6001600160a01b03838116600081815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6001600160a01b0384166139065760405162461bcd60e51b81526004016103f490614db9565b3361391681878761359a88613b68565b6000848152602081815260408083206001600160a01b038a168452909152902054838110156139575760405162461bcd60e51b81526004016103f490614dfe565b6000858152602081815260408083206001600160a01b038b8116855292528083208785039055908816825281208054869290613994908490615018565b909155505060408051868152602081018690526001600160a01b03808916928a821692918616917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a46139f4828888888888613bc1565b50505050505050565b6001600160a01b0384163b156134935760405163bc197c8160e01b81526001600160a01b0385169063bc197c8190613a419089908990889088908890600401614ac3565b602060405180830381600087803b158015613a5b57600080fd5b505af1925050508015613a8b575060408051601f3d908101601f19168201909252613a8891810190614824565b60015b613b3857613a97615121565b806308c379a01415613ad15750613aac615139565b80613ab75750613ad3565b8060405162461bcd60e51b81526004016103f49190614d30565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e20455243313135356044820152732932b1b2b4bb32b91034b6b83632b6b2b73a32b960611b60648201526084016103f4565b6001600160e01b0319811663bc197c8160e01b146139f45760405162461bcd60e51b81526004016103f490614d43565b60408051600180825281830190925260609160009190602080830190803683370190505090508281600081518110613bb057634e487b7160e01b600052603260045260246000fd5b602090810291909101015292915050565b6001600160a01b0384163b156134935760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190613c059089908990889088908890600401614b21565b602060405180830381600087803b158015613c1f57600080fd5b505af1925050508015613c4f575060408051601f3d908101601f19168201909252613c4c91810190614824565b60015b613c5b57613a97615121565b6001600160e01b0319811663f23a6e6160e01b146139f45760405162461bcd60e51b81526004016103f490614d43565b6001600160a01b038316613ced5760405162461bcd60e51b815260206004820152602360248201527f455243313135353a206275726e2066726f6d20746865207a65726f206164647260448201526265737360e81b60648201526084016103f4565b33613d1d81856000613cfe87613b68565b613d0787613b68565b5050604080516020810190915260009052505050565b6000838152602081815260408083206001600160a01b038816845290915290205482811015613d9a5760405162461bcd60e51b8152602060048201526024808201527f455243313135353a206275726e20616d6f756e7420657863656564732062616c604482015263616e636560e01b60648201526084016103f4565b6000848152602081815260408083206001600160a01b03898116808652918452828520888703905582518981529384018890529092908616917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a45050505050565b828054613e1190615073565b90600052602060002090601f016020900481019282613e335760008555613e79565b82601f10613e4c57805160ff1916838001178555613e79565b82800160010185558215613e79579182015b82811115613e79578251825591602001919060010190613e5e565b50613e85929150613e89565b5090565b5b80821115613e855760008155600101613e8a565b80356001600160a01b0381168114613eb557600080fd5b919050565b60008083601f840112613ecb578182fd5b5081356001600160401b03811115613ee1578182fd5b6020830191508360208260051b8501011115613efc57600080fd5b9250929050565b600082601f830112613f13578081fd5b81356020613f2082614ff5565b604051613f2d82826150ae565b8381528281019150858301600585901b87018401881015613f4c578586fd5b855b85811015613f6a57813584529284019290840190600101613f4e565b5090979650505050505050565b60008083601f840112613f88578182fd5b5081356001600160401b03811115613f9e578182fd5b602083019150836020828501011115613efc57600080fd5b600082601f830112613fc6578081fd5b81356001600160401b03811115613fdf57613fdf61510b565b604051613ff6601f8301601f1916602001826150ae565b81815284602083860101111561400a578283fd5b816020850160208301379081016020019190915292915050565b600060208284031215614035578081fd5b61403e82613e9e565b9392505050565b60008060408385031215614057578081fd5b61406083613e9e565b915061406e60208401613e9e565b90509250929050565b60008060008060008060008060008060c08b8d031215614095578586fd5b61409e8b613e9e565b99506140ac60208c01613e9e565b985060408b01356001600160401b03808211156140c7578788fd5b6140d38e838f01613eba565b909a50985060608d01359150808211156140eb578788fd5b6140f78e838f01613eba565b909850965060808d013591508082111561410f578586fd5b61411b8e838f01613f77565b909650945060a08d0135915080821115614133578384fd5b506141408d828e01613eba565b915080935050809150509295989b9194979a5092959850565b600080600080600060a08688031215614170578081fd5b61417986613e9e565b945061418760208701613e9e565b935060408601356001600160401b03808211156141a2578283fd5b6141ae89838a01613f03565b945060608801359150808211156141c3578283fd5b6141cf89838a01613f03565b935060808801359150808211156141e4578283fd5b506141f188828901613fb6565b9150509295509295909350565b60008060008060008060008060c0898b031215614219578384fd5b61422289613e9e565b975061423060208a01613e9e565b9650604089013595506060890135945060808901356001600160401b0380821115614259578586fd5b6142658c838d01613f77565b909650945060a08b013591508082111561427d578384fd5b5061428a8b828c01613f77565b999c989b5096995094979396929594505050565b600080600080600060a086880312156142b5578283fd5b6142be86613e9e565b94506142cc60208701613e9e565b9350604086013592506060860135915060808601356001600160401b038111156142f4578182fd5b6141f188828901613fb6565b600080600080600080600080600060a08a8c03121561431d578283fd5b6143268a613e9e565b985060208a01356001600160401b0380821115614341578485fd5b61434d8d838e01613eba565b909a50985060408c0135915080821115614365578485fd5b6143718d838e01613eba565b909850965060608c0135915080821115614389578485fd5b6143958d838e01613eba565b909650945060808c01359150808211156143ad578384fd5b506143ba8c828d01613eba565b915080935050809150509295985092959850929598565b600080604083850312156143e3578182fd5b6143ec83613e9e565b915060208301356143fc816151c2565b809150509250929050565b600080600080600080600060a0888a031215614421578081fd5b61442a88613e9e565b965060208801356001600160401b0380821115614445578283fd5b6144518b838c01613f77565b909850965060408a0135955060608a0135945060808a0135915080821115614477578283fd5b506144848a828b01613f77565b989b979a50959850939692959293505050565b600080604083850312156144a9578182fd5b6144b283613e9e565b946020939093013593505050565b60008060008060008060008060008060a08b8d0312156144de578384fd5b8a356001600160401b03808211156144f4578586fd5b6145008e838f01613eba565b909c509a5060208d0135915080821115614518578586fd5b6145248e838f01613eba565b909a50985060408d013591508082111561453c578586fd5b6145488e838f01613eba565b909850965060608d0135915080821115614560578586fd5b61456c8e838f01613eba565b909650945060808d0135915080821115614133578384fd5b60008060008060008060008060008060008060c08d8f0312156145a5578586fd5b6001600160401b038d3511156145b9578586fd5b6145c68e8e358f01613eba565b909c509a506001600160401b0360208e013511156145e2578586fd5b6145f28e60208f01358f01613eba565b909a5098506001600160401b0360408e0135111561460e578586fd5b61461e8e60408f01358f01613eba565b90985096506001600160401b0360608e0135111561463a578586fd5b61464a8e60608f01358f01613eba565b90965094506001600160401b0360808e01351115614666578081fd5b6146768e60808f01358f01613eba565b90945092506001600160401b0360a08e01351115614692578081fd5b6146a28e60a08f01358f01613eba565b81935080925050509295989b509295989b509295989b565b600080600080604085870312156146cf578182fd5b84356001600160401b03808211156146e5578384fd5b6146f188838901613eba565b90965094506020870135915080821115614709578384fd5b5061471687828801613eba565b95989497509550505050565b60008060408385031215614734578182fd5b82356001600160401b038082111561474a578384fd5b818501915085601f83011261475d578384fd5b8135602061476a82614ff5565b60405161477782826150ae565b8381528281019150858301600585901b870184018b1015614796578889fd5b8896505b848710156147bf576147ab81613e9e565b83526001969096019591830191830161479a565b50965050860135925050808211156147d5578283fd5b506147e285828601613f03565b9150509250929050565b6000602082840312156147fd578081fd5b815161403e816151c2565b600060208284031215614819578081fd5b813561403e816151d3565b600060208284031215614835578081fd5b815161403e816151d3565b600060208284031215614851578081fd5b5035919050565b600060208284031215614869578081fd5b5051919050565b60008060408385031215614882578182fd5b8235915061406e60208401613e9e565b6000806000606084860312156148a6578081fd5b833592506148b660208501613e9e565b9150604084013590509250925092565b81835260006020808501945082825b85811015614901576001600160a01b036148ee83613e9e565b16875295820195908201906001016148d5565b509495945050505050565b60008383855260208086019550808560051b83010184845b87811015613f6a57848303601f19018952813536889003601e19018112614949578687fd5b870180356001600160401b03811115614960578788fd5b80360389131561496e578788fd5b61497b85828885016149f2565b9a86019a9450505090830190600101614924565b81835260006001600160fb1b038311156149a7578081fd5b8260051b80836020870137939093016020019283525090919050565b6000815180845260208085019450808401835b83811015614901578151875295820195908201906001016149d6565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60008151808452614a33816020860160208601615047565b601f01601f19169290920160200192915050565b60006001600160fb1b03831115614a5c578081fd5b8260051b808584379190910190815292915050565b815160009082906020808601845b83811015614a9b57815185529382019390820190600101614a7f565b50929695505050505050565b60008251614ab9818460208701615047565b9190910192915050565b6001600160a01b0386811682528516602082015260a060408201819052600090614aef908301866149c3565b8281036060840152614b0181866149c3565b90508281036080840152614b158185614a1b565b98975050505050505050565b6001600160a01b03868116825285166020820152604081018490526060810183905260a060808201819052600090614b5b90830184614a1b565b979650505050505050565b60018060a01b0385168152836020820152608060408201526000614b8d6080830185614a1b565b8281036060840152614b5b8185614a1b565b608081526000614bb3608083018a8c6148c6565b8281036020840152614bc681898b6148c6565b90508281036040840152614bdb81878961498f565b90508281036060840152614bf081858761498f565b9b9a5050505050505050505050565b60a081526000614c1360a083018c8e6148c6565b8281036020840152614c26818b8d6148c6565b90508281036040840152614c3b81898b61498f565b90508281036060840152614c5081878961498f565b90508281036080840152614c6581858761490c565b9d9c50505050505050505050505050565b606081526000614c8a60608301888a61498f565b8281036020840152614c9d81878961498f565b90508281036040840152614cb281858761490c565b9998505050505050505050565b60208152600061403e60208301846149c3565b604081526000614ce560408301866149c3565b8281036020840152614cf881858761498f565b9695505050505050565b604081526000614d1560408301856149c3565b8281036020840152614d2781856149c3565b95945050505050565b60208152600061403e6020830184614a1b565b60208082526028908201527f455243313135353a204552433131353552656365697665722072656a656374656040820152676420746f6b656e7360c01b606082015260800190565b602080825260149082015273139bc81bdc195c985d1bdc88185c1c1c9bdd985b60621b604082015260600190565b60208082526025908201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604082015264647265737360d81b606082015260800190565b6020808252602a908201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60408201526939103a3930b739b332b960b11b606082015260800190565b60208082526017908201527f417272617973206e6f742073616d65206c656e6774682e000000000000000000604082015260600190565b602080825260169082015275082e4e4c2f2e640dcdee840e6c2daca40d8cadccee8d60531b604082015260600190565b60208082526028908201527f455243313135353a2069647320616e6420616d6f756e7473206c656e677468206040820152670dad2e6dac2e8c6d60c31b606082015260800190565b60208082526021908201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736040820152607360f81b606082015260800190565b6020808252601590820152742fba379036bab9ba103132903737b716bd32b9379760591b604082015260600190565b8481526001600160a01b0384166020820152608060408201819052600090614b8d90830185614a1b565b848152836020820152606060408201526000614cf86060830184866149f2565b6000808335601e19843603018112614fc7578283fd5b8301803591506001600160401b03821115614fe0578283fd5b602001915036819003821315613efc57600080fd5b60006001600160401b0382111561500e5761500e61510b565b5060051b60200190565b6000821982111561502b5761502b6150f5565b500190565b600082821015615042576150426150f5565b500390565b60005b8381101561506257818101518382015260200161504a565b838111156112965750506000910152565b600181811c9082168061508757607f821691505b602082108114156150a857634e487b7160e01b600052602260045260246000fd5b50919050565b601f8201601f191681016001600160401b03811182821017156150d3576150d361510b565b6040525050565b60006000198214156150ee576150ee6150f5565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600060033d111561513657600481823e5160e01c5b90565b600060443d10156151475790565b6040516003193d81016004833e81513d6001600160401b03816024840111818411171561517657505050505090565b828501915081518181111561518e5750505050505090565b843d87010160208285010111156151a85750505050505090565b6151b7602082860101876150ae565b509095945050505050565b80151581146151d057600080fd5b50565b6001600160e01b0319811681146151d057600080fdfea264697066735822122046750d6d1b96298264a7e23c3b8923a5608900dfbc4cbe71fef61ee1a98decd464736f6c63430008040033