Token MetaLine MysteryBox Semi-fungible Token
Overview ERC-1155
Total Supply:
0 MLMB
Holders:
1,888 addresses
Transfers:
-
Contract:
[ Download CSV Export ]
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
MysteryBox1155
Compiler Version
v0.8.7+commit.e28d00a7
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (access/AccessControl.sol) pragma solidity ^0.8.0; import "./IAccessControl.sol"; import "../utils/Context.sol"; import "../utils/Strings.sol"; import "../utils/introspection/ERC165.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ``` * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ``` * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view virtual override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `_msgSender()` is missing `role`. * Overriding this function changes the behavior of the {onlyRole} modifier. * * Format of the revert message is described in {_checkRole}. * * _Available since v4.6._ */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", Strings.toHexString(uint160(account), 20), " is missing role ", Strings.toHexString(uint256(role), 32) ) ) ); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) public virtual override { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== * * NOTE: This function is deprecated in favor of {_grantRole}. */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Grants `role` to `account`. * * Internal function without access restriction. */ function _grantRole(bytes32 role, address account) internal virtual { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. */ function _revokeRole(bytes32 role, address account) internal virtual { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { require(!paused(), "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { require(paused(), "Pausable: not paused"); _; } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC1155/ERC1155.sol) pragma solidity ^0.8.0; import "./IERC1155.sol"; import "./IERC1155Receiver.sol"; import "./extensions/IERC1155MetadataURI.sol"; import "../../utils/Address.sol"; import "../../utils/Context.sol"; import "../../utils/introspection/ERC165.sol"; /** * @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(); uint256[] memory ids = _asSingletonArray(id); uint256[] memory amounts = _asSingletonArray(amount); _beforeTokenTransfer(operator, from, to, ids, amounts, 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); _afterTokenTransfer(operator, from, to, ids, amounts, data); _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); _afterTokenTransfer(operator, from, to, ids, amounts, data); _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(); uint256[] memory ids = _asSingletonArray(id); uint256[] memory amounts = _asSingletonArray(amount); _beforeTokenTransfer(operator, address(0), to, ids, amounts, data); _balances[id][to] += amount; emit TransferSingle(operator, address(0), to, id, amount); _afterTokenTransfer(operator, address(0), to, ids, amounts, data); _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); _afterTokenTransfer(operator, address(0), to, ids, amounts, data); _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(); uint256[] memory ids = _asSingletonArray(id); uint256[] memory amounts = _asSingletonArray(amount); _beforeTokenTransfer(operator, from, address(0), ids, amounts, ""); 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); _afterTokenTransfer(operator, from, address(0), ids, amounts, ""); } /** * @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); _afterTokenTransfer(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 {} /** * @dev Hook that is called after 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 _afterTokenTransfer( 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; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/ERC1155Burnable.sol) pragma solidity ^0.8.0; import "../ERC1155.sol"; /** * @dev Extension of {ERC1155} that allows token holders to destroy both their * own tokens and those that they have been approved to use. * * _Available since v3.1._ */ abstract contract ERC1155Burnable is ERC1155 { function burn( address account, uint256 id, uint256 value ) public virtual { require( account == _msgSender() || isApprovedForAll(account, _msgSender()), "ERC1155: caller is not owner nor approved" ); _burn(account, id, value); } function burnBatch( address account, uint256[] memory ids, uint256[] memory values ) public virtual { require( account == _msgSender() || isApprovedForAll(account, _msgSender()), "ERC1155: caller is not owner nor approved" ); _burnBatch(account, ids, values); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/ERC1155Pausable.sol) pragma solidity ^0.8.0; import "../ERC1155.sol"; import "../../../security/Pausable.sol"; /** * @dev ERC1155 token with pausable token transfers, minting and burning. * * Useful for scenarios such as preventing trades until the end of an evaluation * period, or having an emergency switch for freezing all token transfers in the * event of a large bug. * * _Available since v3.1._ */ abstract contract ERC1155Pausable is ERC1155, Pausable { /** * @dev See {ERC1155-_beforeTokenTransfer}. * * Requirements: * * - the contract must not be paused. */ function _beforeTokenTransfer( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual override { super._beforeTokenTransfer(operator, from, to, ids, amounts, data); require(!paused(), "ERC1155Pausable: token transfer while paused"); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC1155/extensions/ERC1155Supply.sol) pragma solidity ^0.8.0; import "../ERC1155.sol"; /** * @dev Extension of ERC1155 that adds tracking of total supply per id. * * Useful for scenarios where Fungible and Non-fungible tokens have to be * clearly identified. Note: While a totalSupply of 1 might mean the * corresponding is an NFT, there is no guarantees that no other token with the * same id are not going to be minted. */ abstract contract ERC1155Supply is ERC1155 { mapping(uint256 => uint256) private _totalSupply; /** * @dev Total amount of tokens in with a given id. */ function totalSupply(uint256 id) public view virtual returns (uint256) { return _totalSupply[id]; } /** * @dev Indicates whether any token exist with a given id, or not. */ function exists(uint256 id) public view virtual returns (bool) { return ERC1155Supply.totalSupply(id) > 0; } /** * @dev See {ERC1155-_beforeTokenTransfer}. */ function _beforeTokenTransfer( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual override { super._beforeTokenTransfer(operator, from, to, ids, amounts, data); if (from == address(0)) { for (uint256 i = 0; i < ids.length; ++i) { _totalSupply[ids[i]] += amounts[i]; } } if (to == address(0)) { for (uint256 i = 0; i < ids.length; ++i) { uint256 id = ids[i]; uint256 amount = amounts[i]; uint256 supply = _totalSupply[id]; require(supply >= amount, "ERC1155: burn amount exceeds totalSupply"); unchecked { _totalSupply[id] = supply - amount; } } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol) pragma solidity ^0.8.0; import "../IERC1155.sol"; /** * @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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @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; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @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. * * NOTE: 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. * * NOTE: 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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.0; import "./IERC20.sol"; import "./extensions/IERC20Metadata.sol"; import "../../utils/Context.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20, IERC20Metadata { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * The default value of {decimals} is 18. To select a different value for * {decimals} you should overload it. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless this function is * overridden; * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address to, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _transfer(owner, to, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _approve(owner, spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. * - the caller must have allowance for ``from``'s tokens of at least * `amount`. */ function transferFrom( address from, address to, uint256 amount ) public virtual override returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, amount); _transfer(from, to, amount); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, allowance(owner, spender) + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { address owner = _msgSender(); uint256 currentAllowance = allowance(owner, spender); require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(owner, spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `sender` to `recipient`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. */ function _transfer( address from, address to, uint256 amount ) internal virtual { require(from != address(0), "ERC20: transfer from the zero address"); require(to != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(from, to, amount); uint256 fromBalance = _balances[from]; require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[from] = fromBalance - amount; } _balances[to] += amount; emit Transfer(from, to, amount); _afterTokenTransfer(from, to, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; _balances[account] += amount; emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; } _totalSupply -= amount; emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve( address owner, address spender, uint256 amount ) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Updates `owner` s allowance for `spender` based on spent `amount`. * * Does not update the allowance amount in case of infinite allowance. * Revert if not enough allowance is available. * * Might emit an {Approval} event. */ function _spendAllowance( address owner, address spender, uint256 amount ) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { require(currentAllowance >= amount, "ERC20: insufficient allowance"); unchecked { _approve(owner, spender, currentAllowance - amount); } } } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 amount ) internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Burnable.sol) pragma solidity ^0.8.0; import "../ERC20.sol"; import "../../../utils/Context.sol"; /** * @dev Extension of {ERC20} that allows token holders to destroy both their own * tokens and those that they have an allowance for, in a way that can be * recognized off-chain (via event analysis). */ abstract contract ERC20Burnable is Context, ERC20 { /** * @dev Destroys `amount` tokens from the caller. * * See {ERC20-_burn}. */ function burn(uint256 amount) public virtual { _burn(_msgSender(), amount); } /** * @dev Destroys `amount` tokens from `account`, deducting from the caller's * allowance. * * See {ERC20-_burn} and {ERC20-allowance}. * * Requirements: * * - the caller must have allowance for ``accounts``'s tokens of at least * `amount`. */ function burnFrom(address account, uint256 amount) public virtual { _spendAllowance(account, _msgSender(), amount); _burn(account, amount); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/ERC721.sol) pragma solidity ^0.8.0; import "./IERC721.sol"; import "./IERC721Receiver.sol"; import "./extensions/IERC721Metadata.sol"; import "../../utils/Address.sol"; import "../../utils/Context.sol"; import "../../utils/Strings.sol"; import "../../utils/introspection/ERC165.sol"; /** * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including * the Metadata extension, but not including the Enumerable extension, which is available separately as * {ERC721Enumerable}. */ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata { using Address for address; using Strings for uint256; // Token name string private _name; // Token symbol string private _symbol; // Mapping from token ID to owner address mapping(uint256 => address) private _owners; // Mapping owner address to token count mapping(address => uint256) private _balances; // Mapping from token ID to approved address mapping(uint256 => address) private _tokenApprovals; // Mapping from owner to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; /** * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC721Metadata).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view virtual override returns (uint256) { require(owner != address(0), "ERC721: balance query for the zero address"); return _balances[owner]; } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view virtual override returns (address) { address owner = _owners[tokenId]; require(owner != address(0), "ERC721: owner query for nonexistent token"); return owner; } /** * @dev See {IERC721Metadata-name}. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev See {IERC721Metadata-symbol}. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev See {IERC721Metadata-tokenURI}. */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token"); string memory baseURI = _baseURI(); return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : ""; } /** * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each * token will be the concatenation of the `baseURI` and the `tokenId`. Empty * by default, can be overridden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ""; } /** * @dev See {IERC721-approve}. */ function approve(address to, uint256 tokenId) public virtual override { address owner = ERC721.ownerOf(tokenId); require(to != owner, "ERC721: approval to current owner"); require( _msgSender() == owner || isApprovedForAll(owner, _msgSender()), "ERC721: approve caller is not owner nor approved for all" ); _approve(to, tokenId); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { require(_exists(tokenId), "ERC721: approved query for nonexistent token"); return _tokenApprovals[tokenId]; } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev See {IERC721-transferFrom}. */ function transferFrom( address from, address to, uint256 tokenId ) public virtual override { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); _transfer(from, to, tokenId); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId ) public virtual override { safeTransferFrom(from, to, tokenId, ""); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes memory _data ) public virtual override { require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); _safeTransfer(from, to, tokenId, _data); } /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * `_data` is additional data, it has no specified format and it is sent in call to `to`. * * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g. * implement alternative mechanisms to perform token transfer, such as signature-based. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeTransfer( address from, address to, uint256 tokenId, bytes memory _data ) internal virtual { _transfer(from, to, tokenId); require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer"); } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted (`_mint`), * and stop existing when they are burned (`_burn`). */ function _exists(uint256 tokenId) internal view virtual returns (bool) { return _owners[tokenId] != address(0); } /** * @dev Returns whether `spender` is allowed to manage `tokenId`. * * Requirements: * * - `tokenId` must exist. */ function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) { require(_exists(tokenId), "ERC721: operator query for nonexistent token"); address owner = ERC721.ownerOf(tokenId); return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender); } /** * @dev Safely mints `tokenId` and transfers it to `to`. * * Requirements: * * - `tokenId` must not exist. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeMint(address to, uint256 tokenId) internal virtual { _safeMint(to, tokenId, ""); } /** * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. */ function _safeMint( address to, uint256 tokenId, bytes memory _data ) internal virtual { _mint(to, tokenId); require( _checkOnERC721Received(address(0), to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer" ); } /** * @dev Mints `tokenId` and transfers it to `to`. * * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible * * Requirements: * * - `tokenId` must not exist. * - `to` cannot be the zero address. * * Emits a {Transfer} event. */ function _mint(address to, uint256 tokenId) internal virtual { require(to != address(0), "ERC721: mint to the zero address"); require(!_exists(tokenId), "ERC721: token already minted"); _beforeTokenTransfer(address(0), to, tokenId); _balances[to] += 1; _owners[tokenId] = to; emit Transfer(address(0), to, tokenId); _afterTokenTransfer(address(0), to, tokenId); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId) internal virtual { address owner = ERC721.ownerOf(tokenId); _beforeTokenTransfer(owner, address(0), tokenId); // Clear approvals _approve(address(0), tokenId); _balances[owner] -= 1; delete _owners[tokenId]; emit Transfer(owner, address(0), tokenId); _afterTokenTransfer(owner, address(0), tokenId); } /** * @dev Transfers `tokenId` from `from` to `to`. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * * Emits a {Transfer} event. */ function _transfer( address from, address to, uint256 tokenId ) internal virtual { require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); require(to != address(0), "ERC721: transfer to the zero address"); _beforeTokenTransfer(from, to, tokenId); // Clear approvals from the previous owner _approve(address(0), tokenId); _balances[from] -= 1; _balances[to] += 1; _owners[tokenId] = to; emit Transfer(from, to, tokenId); _afterTokenTransfer(from, to, tokenId); } /** * @dev Approve `to` to operate on `tokenId` * * Emits a {Approval} event. */ function _approve(address to, uint256 tokenId) internal virtual { _tokenApprovals[tokenId] = to; emit Approval(ERC721.ownerOf(tokenId), to, tokenId); } /** * @dev 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, "ERC721: approve to caller"); _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. * The call is not executed if the target address is not a contract. * * @param from address representing the previous owner of the given token ID * @param to target address that will receive the tokens * @param tokenId uint256 ID of the token to be transferred * @param _data bytes optional data to send along with the call * @return bool whether the call correctly returned the expected magic value */ function _checkOnERC721Received( address from, address to, uint256 tokenId, bytes memory _data ) private returns (bool) { if (to.isContract()) { try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) { return retval == IERC721Receiver.onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { revert("ERC721: transfer to non ERC721Receiver implementer"); } else { assembly { revert(add(32, reason), mload(reason)) } } } } else { return true; } } /** * @dev Hook that is called before any token transfer. This includes minting * and burning. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, ``from``'s `tokenId` will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 tokenId ) internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Burnable.sol) pragma solidity ^0.8.0; import "../ERC721.sol"; import "../../../utils/Context.sol"; /** * @title ERC721 Burnable Token * @dev ERC721 Token that can be irreversibly burned (destroyed). */ abstract contract ERC721Burnable is Context, ERC721 { /** * @dev Burns `tokenId`. See {ERC721-_burn}. * * Requirements: * * - The caller must own `tokenId` or be an approved operator. */ function burn(uint256 tokenId) public virtual { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721Burnable: caller is not owner nor approved"); _burn(tokenId); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Enumerable.sol) pragma solidity ^0.8.0; import "../ERC721.sol"; import "./IERC721Enumerable.sol"; /** * @dev This implements an optional extension of {ERC721} defined in the EIP that adds * enumerability of all the token ids in the contract as well as all token ids owned by each * account. */ abstract contract ERC721Enumerable is ERC721, IERC721Enumerable { // Mapping from owner to list of owned token IDs mapping(address => mapping(uint256 => uint256)) private _ownedTokens; // Mapping from token ID to index of the owner tokens list mapping(uint256 => uint256) private _ownedTokensIndex; // Array with all token ids, used for enumeration uint256[] private _allTokens; // Mapping from token id to position in the allTokens array mapping(uint256 => uint256) private _allTokensIndex; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) { return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}. */ function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) { require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds"); return _ownedTokens[owner][index]; } /** * @dev See {IERC721Enumerable-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _allTokens.length; } /** * @dev See {IERC721Enumerable-tokenByIndex}. */ function tokenByIndex(uint256 index) public view virtual override returns (uint256) { require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds"); return _allTokens[index]; } /** * @dev Hook that is called before any token transfer. This includes minting * and burning. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, ``from``'s `tokenId` will be burned. * - `from` cannot be the zero address. * - `to` cannot be the zero address. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual override { super._beforeTokenTransfer(from, to, tokenId); if (from == address(0)) { _addTokenToAllTokensEnumeration(tokenId); } else if (from != to) { _removeTokenFromOwnerEnumeration(from, tokenId); } if (to == address(0)) { _removeTokenFromAllTokensEnumeration(tokenId); } else if (to != from) { _addTokenToOwnerEnumeration(to, tokenId); } } /** * @dev Private function to add a token to this extension's ownership-tracking data structures. * @param to address representing the new owner of the given token ID * @param tokenId uint256 ID of the token to be added to the tokens list of the given address */ function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private { uint256 length = ERC721.balanceOf(to); _ownedTokens[to][length] = tokenId; _ownedTokensIndex[tokenId] = length; } /** * @dev Private function to add a token to this extension's token tracking data structures. * @param tokenId uint256 ID of the token to be added to the tokens list */ function _addTokenToAllTokensEnumeration(uint256 tokenId) private { _allTokensIndex[tokenId] = _allTokens.length; _allTokens.push(tokenId); } /** * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for * gas optimizations e.g. when performing a transfer operation (avoiding double writes). * This has O(1) time complexity, but alters the order of the _ownedTokens array. * @param from address representing the previous owner of the given token ID * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address */ function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private { // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = ERC721.balanceOf(from) - 1; uint256 tokenIndex = _ownedTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary if (tokenIndex != lastTokenIndex) { uint256 lastTokenId = _ownedTokens[from][lastTokenIndex]; _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index } // This also deletes the contents at the last position of the array delete _ownedTokensIndex[tokenId]; delete _ownedTokens[from][lastTokenIndex]; } /** * @dev Private function to remove a token from this extension's token tracking data structures. * This has O(1) time complexity, but alters the order of the _allTokens array. * @param tokenId uint256 ID of the token to be removed from the tokens list */ function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private { // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = _allTokens.length - 1; uint256 tokenIndex = _allTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding // an 'if' statement (like in _removeTokenFromOwnerEnumeration) uint256 lastTokenId = _allTokens[lastTokenIndex]; _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index // This also deletes the contents at the last position of the array delete _allTokensIndex[tokenId]; _allTokens.pop(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Pausable.sol) pragma solidity ^0.8.0; import "../ERC721.sol"; import "../../../security/Pausable.sol"; /** * @dev ERC721 token with pausable token transfers, minting and burning. * * Useful for scenarios such as preventing trades until the end of an evaluation * period, or having an emergency switch for freezing all token transfers in the * event of a large bug. */ abstract contract ERC721Pausable is ERC721, Pausable { /** * @dev See {ERC721-_beforeTokenTransfer}. * * Requirements: * * - the contract must not be paused. */ function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual override { super._beforeTokenTransfer(from, to, tokenId); require(!paused(), "ERC721Pausable: token transfer while paused"); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol) pragma solidity ^0.8.0; import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Enumerable is IERC721 { /** * @dev Returns the total amount of tokens stored by the contract. */ function totalSupply() external view returns (uint256); /** * @dev Returns a token ID owned by `owner` at a given `index` of its token list. * Use along with {balanceOf} to enumerate all of ``owner``'s tokens. */ function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256); /** * @dev Returns a token ID at a given `index` of all the tokens stored by the contract. * Use along with {totalSupply} to enumerate all tokens. */ function tokenByIndex(uint256 index) external view returns (uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^0.8.0; import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @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 * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 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); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Counters.sol) pragma solidity ^0.8.0; /** * @title Counters * @author Matt Condon (@shrugs) * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number * of elements in a mapping, issuing ERC721 ids, or counting request ids. * * Include with `using Counters for Counters.Counter;` */ library Counters { struct Counter { // This variable should never be directly accessed by users of the library: interactions must be restricted to // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add // this feature: see https://github.com/ethereum/solidity/issues/4637 uint256 _value; // default: 0 } function current(Counter storage counter) internal view returns (uint256) { return counter._value; } function increment(Counter storage counter) internal { unchecked { counter._value += 1; } } function decrement(Counter storage counter) internal { uint256 value = counter._value; require(value > 0, "Counter: decrement overflow"); unchecked { counter._value = value - 1; } } function reset(Counter storage counter) internal { counter._value = 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @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; } }
// SPDX-License-Identifier: MIT // 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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } }
// SPDX-License-Identifier: MIT // Mateline Contracts (Extendable1155.sol) pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol"; import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Pausable.sol"; import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Supply.sol"; import "@openzeppelin/contracts/access/AccessControl.sol"; import "@openzeppelin/contracts/utils/Context.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "../interface/ERC/IERC2981Royalties.sol"; import "../utility/TransferHelper.sol"; /** * @dev {ERC1155} token, including: * * - ability for holders to burn (destroy) their tokens * - a minter role that allows for token minting (creation) * - a pauser role that allows to stop all token transfers * * This contract uses {AccessControl} to lock permissioned functions using the * different roles - head to its documentation for details. * * The account that deploys the contract will be granted the minter and pauser * roles, as well as the default admin role, which will let it grant both minter * and pauser roles to other accounts. */ contract ERC1155PresetMinterPauser is Context, AccessControl, ERC1155Burnable, ERC1155Pausable, ERC1155Supply, IERC2981Royalties { bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); // Token name string private _name; // Token symbol string private _symbol; // erc2981 royalty fee, /10000 uint256 public _royalties; /** * @dev Grants `DEFAULT_ADMIN_ROLE`, `MINTER_ROLE`, and `PAUSER_ROLE` to the account that * deploys the contract. */ constructor( string memory name_, string memory symbol_, string memory uri ) ERC1155(uri) { _name = name_; _symbol = symbol_; _royalties = 500; // 5% _setupRole(DEFAULT_ADMIN_ROLE, _msgSender()); _setupRole(MINTER_ROLE, _msgSender()); _setupRole(PAUSER_ROLE, _msgSender()); } /** * @dev As 1155 contract name for some dApp which read name from contract, See {IERC721Metadata-name}. */ function name() public view virtual returns (string memory) { return _name; } /** * @dev As 1155 contract symbol for some dApp which read symbol from contract, See {IERC721Metadata-symbol}. */ function symbol() public view virtual returns (string memory) { return _symbol; } /** * @dev update base token uri, See {IERC1155MetadataURI-uri}. * * Requirements: * * - the caller must have the `MINTER_ROLE`. */ function updateURI(string calldata newuri) public virtual { require(hasRole(MINTER_ROLE, _msgSender()), "ERC1155PresetMinterPauser: must have minter role to update"); _setURI(newuri); } /** * @dev Creates `amount` new tokens for `to`, of token type `id`. * * See {ERC1155-_mint}. * * Requirements: * * - the caller must have the `MINTER_ROLE`. */ function mint( address to, uint256 id, uint256 amount, bytes memory data ) public virtual { require(hasRole(MINTER_ROLE, _msgSender()), "ERC1155PresetMinterPauser: must have minter role to mint"); _mint(to, id, amount, data); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] variant of {mint}. */ function mintBatch( address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) public virtual { require(hasRole(MINTER_ROLE, _msgSender()), "ERC1155PresetMinterPauser: must have minter role to mint"); _mintBatch(to, ids, amounts, data); } /** * @dev Pauses all token transfers. * * See {ERC1155Pausable} and {Pausable-_pause}. * * Requirements: * * - the caller must have the `PAUSER_ROLE`. */ function pause() public virtual { require(hasRole(PAUSER_ROLE, _msgSender()), "ERC1155PresetMinterPauser: must have pauser role to pause"); _pause(); } /** * @dev Unpauses all token transfers. * * See {ERC1155Pausable} and {Pausable-_unpause}. * * Requirements: * * - the caller must have the `PAUSER_ROLE`. */ function unpause() public virtual { require(hasRole(PAUSER_ROLE, _msgSender()), "ERC1155PresetMinterPauser: must have pauser role to unpause"); _unpause(); } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControl, ERC1155) returns (bool) { return interfaceId == type(IERC2981Royalties).interfaceId || super.supportsInterface(interfaceId); } function _beforeTokenTransfer( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual override(ERC1155, ERC1155Pausable, ERC1155Supply) { super._beforeTokenTransfer(operator, from, to, ids, amounts, data); } // set royalties function setRoyalties(uint256 royalties) external { require(hasRole(MINTER_ROLE, _msgSender()), "ERC1155PresetMinterPauser: must have minter role"); _royalties = royalties; } /// @inheritdoc IERC2981Royalties function royaltyInfo(uint256, uint256 value) external view override returns (address receiver, uint256 royaltyAmount) { receiver = address(this); royaltyAmount = (value * _royalties) / 10000; } // fetch royalty income function fetchIncome(address erc20) external { require(hasRole(MINTER_ROLE, _msgSender()), "ERC1155PresetMinterPauser: must have minter role"); uint256 amount = IERC20(erc20).balanceOf(address(this)); if(amount > 0) { TransferHelper.safeTransfer(erc20, _msgSender(), amount); } } function fetchIncomeEth() external { require(hasRole(MINTER_ROLE, _msgSender()), "ERC1155PresetMinterPauser: must have minter role"); // send eth (bool sent, ) = _msgSender().call{value:address(this).balance}(""); require(sent, "ERC1155PresetMinterPauser: transfer error"); } } contract Extendable1155 is ERC1155PresetMinterPauser { bytes32 public constant DATA_ROLE = keccak256("DATA_ROLE"); /** * @dev emit when token data section changed * @param id 1155 id which data has been changed * @param extendData data after change */ event Extendable1155Modify(uint256 indexed id, bytes extendData); mapping(uint256=>bytes) _extendDatas; constructor( string memory name_, string memory symbol_, string memory uri) ERC1155PresetMinterPauser(name_, symbol_, uri) { } /** * @dev modify extend 1155 data, emit {Extendable1155Modify} event * * Requirements: * - caller must have general `DATA_ROLE` * * @param id 1155 id to modify extend data * @param extendData extend data in bytes, use a codec to encode or decode the bytes data outside */ function modifyExtendData( uint256 id, bytes memory extendData ) external whenNotPaused { require( hasRole(DATA_ROLE, _msgSender()), "R6" ); require( exists(id), "E4" ); // modify extend data _extendDatas[id] = extendData; emit Extendable1155Modify(id, extendData); } /** * @dev get extend 1155 data * * @param id 1155 id to get extend data * @return extend data in bytes, use a codec to encode or decode the bytes data outside */ function getTokenExtendNftData(uint256 id) external view returns (bytes memory) { require(exists(id), "E6"); return _extendDatas[id]; } }
// SPDX-License-Identifier: MIT // Mateline Contracts (ExtendableNFT.sol) pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Pausable.sol"; import "@openzeppelin/contracts/access/AccessControl.sol"; import "@openzeppelin/contracts/utils/Context.sol"; import "@openzeppelin/contracts/utils/Counters.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "../interface/ERC/IERC2981Royalties.sol"; import "../utility/TransferHelper.sol"; /** * @dev {ERC721} token, including: * * - ability for holders to burn (destroy) their tokens * - a minter role that allows for token minting (creation) * - a pauser role that allows to stop all token transfers * - token ID and URI autogeneration * * This contract uses {AccessControl} to lock permissioned functions using the * different roles - head to its documentation for details. * * The account that deploys the contract will be granted the minter and pauser * roles, as well as the default admin role, which will let it grant both minter * and pauser roles to other accounts. */ contract ERC721PresetMinterPauserAutoId is Context, AccessControl, ERC721Enumerable, ERC721Burnable, ERC721Pausable, IERC2981Royalties { bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); string internal _baseTokenURI; // erc2981 royalty fee, /10000 uint256 public _royalties; /** * @dev Grants `DEFAULT_ADMIN_ROLE`, `MINTER_ROLE` and `PAUSER_ROLE` to the * account that deploys the contract. * * Token URIs will be autogenerated based on `baseURI` and their token IDs. * See {ERC721-tokenURI}. */ constructor( string memory name, string memory symbol, string memory baseTokenURI ) ERC721(name, symbol) { _baseTokenURI = baseTokenURI; _royalties = 500; // 5% _setupRole(DEFAULT_ADMIN_ROLE, _msgSender()); _setupRole(MINTER_ROLE, _msgSender()); _setupRole(PAUSER_ROLE, _msgSender()); } function _baseURI() internal view virtual override returns (string memory) { return _baseTokenURI; } /** * @dev update base token uri. * * Requirements: * * - the caller must have the `MINTER_ROLE`. */ function updateURI(string calldata baseTokenURI) public virtual { require(hasRole(MINTER_ROLE, _msgSender()), "M1"); _baseTokenURI = baseTokenURI; } /** * @dev Pauses all token transfers. * * See {ERC721Pausable} and {Pausable-_pause}. * * Requirements: * * - the caller must have the `PAUSER_ROLE`. */ function pause() public virtual { require(hasRole(PAUSER_ROLE, _msgSender()), "P1"); _pause(); } /** * @dev Unpauses all token transfers. * * See {ERC721Pausable} and {Pausable-_unpause}. * * Requirements: * * - the caller must have the `PAUSER_ROLE`. */ function unpause() public virtual { require(hasRole(PAUSER_ROLE, _msgSender()), "P2"); _unpause(); } function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual override(ERC721, ERC721Enumerable, ERC721Pausable) { super._beforeTokenTransfer(from, to, tokenId); } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControl, ERC721, ERC721Enumerable) returns (bool) { return interfaceId == type(IERC2981Royalties).interfaceId || super.supportsInterface(interfaceId); } // set royalties function setRoyalties(uint256 royalties) external { require(hasRole(MINTER_ROLE, _msgSender()), "M1"); _royalties = royalties; } /// @inheritdoc IERC2981Royalties function royaltyInfo(uint256, uint256 value) external view override returns (address receiver, uint256 royaltyAmount) { receiver = address(this); royaltyAmount = (value * _royalties) / 10000; } // fetch royalty income function fetchIncome(address erc20) external { require(hasRole(MINTER_ROLE, _msgSender()), "M1"); uint256 amount = IERC20(erc20).balanceOf(address(this)); if(amount > 0) { TransferHelper.safeTransfer(erc20, _msgSender(), amount); } } function fetchIncomeEth() external { require(hasRole(MINTER_ROLE, _msgSender()), "ERC1155PresetMinterPauser: must have minter role"); // send eth (bool sent, ) = _msgSender().call{value:address(this).balance}(""); require(sent, "ERC1155PresetMinterPauser: transfer error"); } } /** * @dev Extension of {ERC721PresetMinterPauserAutoId} that allows token dynamic extend data section */ contract ExtendableNFT is ERC721PresetMinterPauserAutoId { bytes32 public constant DATA_ROLE = keccak256("DATA_ROLE"); bytes32 public constant FREEZE_ROLE = keccak256("FREEZE_ROLE"); /** * @dev emit when token has been freezed or unfreeze * @param tokenId freezed token id * @param freeze freezed or not */ event NFTFreeze(uint256 indexed tokenId, bool freeze); /** * @dev emit when new data section created * @param extendName new data section name * @param nameBytes data section name after keccak256 */ event NFTExtendName(string extendName, bytes32 nameBytes); /** * @dev emit when token data section changed * @param tokenId tokenid which data has been changed * @param nameBytes data section name after keccak256 * @param extendData data after change */ event NFTExtendModify(uint256 indexed tokenId, bytes32 nameBytes, bytes extendData); // record of token already extended data section struct NFTExtendsNames{ bytes32[] NFTExtendDataNames; // array of data sectioin name after keccak256 } // extend data mapping struct NFTExtendData { bool _exist; mapping(uint256 => bytes) ExtendDatas; // tokenid => data mapping } mapping(uint256 => bool) private _nftFreezed; // tokenid => is freezed mapping(uint256 => NFTExtendsNames) private _nftExtendNames; // tokenid => extended data sections mapping(bytes32 => NFTExtendData) private _nftExtendDataMap; // extend name => extend datas mapping constructor( string memory name, string memory symbol, string memory baseTokenURI) ERC721PresetMinterPauserAutoId(name, symbol, baseTokenURI) { } /** * @dev freeze token, emit {NFTFreeze} event * * Requirements: * - caller must have `FREEZE_ROLE` * * @param tokenId token to freeze */ function freeze(uint256 tokenId) external { require(hasRole(FREEZE_ROLE, _msgSender()), "R2"); _nftFreezed[tokenId] = true; emit NFTFreeze(tokenId, true); } /** * @dev unfreeze token, emit {NFTFreeze} event * * Requirements: * - caller must have `FREEZE_ROLE` * * @param tokenId token to unfreeze */ function unfreeze(uint256 tokenId) external { require(hasRole(FREEZE_ROLE, _msgSender()), "R3"); delete _nftFreezed[tokenId]; emit NFTFreeze(tokenId, false); } /** * @dev check token, return true if not freezed * * @param tokenId token to check * @return ture if token is not freezed */ function notFreezed(uint256 tokenId) public view returns (bool) { return !_nftFreezed[tokenId]; } /** * @dev check token, return true if it's freezed * * @param tokenId token to check * @return ture if token is freezed */ function isFreezed(uint256 tokenId) public view returns (bool) { return _nftFreezed[tokenId]; } /** * @dev check token, return true if it exists * * @param tokenId token to check * @return ture if token exists */ function exists(uint256 tokenId) public view returns (bool) { return _exists(tokenId); } /** * @dev add new token data section, emit {NFTExtendName} event * * Requirements: * - caller must have `MINTER_ROLE` * * @param extendName string of new data section name */ function extendNftData(string memory extendName) external { require(hasRole(MINTER_ROLE, _msgSender()), "R5"); bytes32 nameBytes = keccak256(bytes(extendName)); NFTExtendData storage extendData = _nftExtendDataMap[nameBytes]; extendData._exist = true; emit NFTExtendName(extendName, nameBytes); } /** * @dev add extend token data with specify 'extendName', emit {NFTExtendModify} event * * Requirements: * - caller must have general `DATA_ROLE` or `DATA_ROLE` with the specify `extendName` * * @param tokenId token to add extend data * @param extendName data section name in string * @param extendData extend data in bytes, use a codec to encode or decode the bytes data outside */ function addTokenExtendNftData( uint256 tokenId, string memory extendName, bytes memory extendData ) external whenNotPaused { require( hasRole(DATA_ROLE, _msgSender()) || hasRole( keccak256(abi.encodePacked("DATA_ROLE", extendName)), _msgSender() ), "R6" ); bytes32 nameBytes = keccak256(bytes(extendName)); require(_extendNameExist(nameBytes), "E1"); require(!_tokenExtendNameExist(tokenId, nameBytes), "E2"); // modify extend data NFTExtendData storage extendDatas = _nftExtendDataMap[nameBytes]; extendDatas.ExtendDatas[tokenId] = extendData; // save token extend data names NFTExtendsNames storage nftData = _nftExtendNames[tokenId]; nftData.NFTExtendDataNames.push(nameBytes); emit NFTExtendModify(tokenId, nameBytes, extendData); } /** * @dev modify extend token data with specify 'extendName', emit {NFTExtendModify} event * * Requirements: * - caller must have general `DATA_ROLE` or `DATA_ROLE` with the specify `extendName` * * @param tokenId token to modify extend data * @param extendName data section name in string * @param extendData extend data in bytes, use a codec to encode or decode the bytes data outside */ function modifyTokenExtendNftData( uint256 tokenId, string memory extendName, bytes memory extendData ) external whenNotPaused { require( hasRole(DATA_ROLE, _msgSender()) || hasRole( keccak256(abi.encodePacked("DATA_ROLE", extendName)), _msgSender() ), "R6" ); bytes32 nameBytes = keccak256(bytes(extendName)); require(_extendNameExist(nameBytes), "E4"); require(_tokenExtendNameExist(tokenId, nameBytes), "E5"); // modify extend data NFTExtendData storage extendDatas = _nftExtendDataMap[nameBytes]; extendDatas.ExtendDatas[tokenId] = extendData; emit NFTExtendModify(tokenId, nameBytes, extendData); } /** * @dev get extend token data with specify 'extendName' * * @param tokenId token to get extend data * @param extendName data section name in string * @return extend data in bytes, use a codec to encode or decode the bytes data outside */ function getTokenExtendNftData(uint256 tokenId, string memory extendName) external view returns (bytes memory) { bytes32 nameBytes = keccak256(bytes(extendName)); require(_extendNameExist(nameBytes), "E6"); NFTExtendData storage extendDatas = _nftExtendDataMap[nameBytes]; return extendDatas.ExtendDatas[tokenId]; } function _extendNameExist(bytes32 nameBytes) internal view returns (bool) { return _nftExtendDataMap[nameBytes]._exist; } function _tokenExtendNameExist(uint256 tokenId, bytes32 nameBytes) internal view returns(bool) { NFTExtendsNames memory nftData = _nftExtendNames[tokenId]; for(uint i=0; i<nftData.NFTExtendDataNames.length; ++i){ if(nftData.NFTExtendDataNames[i] == nameBytes){ return true; } } return false; } function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual override { require(notFreezed(tokenId), "F1"); super._beforeTokenTransfer(from, to, tokenId); if (to == address(0)) { // delete token extend datas; NFTExtendsNames memory nftData = _nftExtendNames[tokenId]; for(uint i = 0; i< nftData.NFTExtendDataNames.length; ++i){ NFTExtendData storage extendData = _nftExtendDataMap[nftData.NFTExtendDataNames[i]]; delete extendData.ExtendDatas[tokenId]; } // delete token datas delete _nftExtendNames[tokenId]; } } }
// SPDX-License-Identifier: MIT // Mateline Contracts (HeroNFT.sol) pragma solidity ^0.8.0; import "./utility/ResetableCounters.sol"; import "./core/ExtendableNFT.sol"; import "./HeroNFTCodec.sol"; /** * @dev Extension of {ExtendableNFT} that with fixed token data struct */ contract HeroNFT is ExtendableNFT { using ResetableCounters for ResetableCounters.Counter; /** * @dev emit when new token has been minted, see {HeroNFTDataBase} * * @param to owner of new token * @param tokenId new token id * @param data token data see {HeroNFTDataBase} */ event HeroNFTMint(address indexed to, uint256 indexed tokenId, HeroNFTDataBase data); ResetableCounters.Counter internal _tokenIdTracker; address public _codec; address public _attrSource; mapping(uint256 => HeroNFTDataBase) private _nftDatas; // token id => nft data stucture constructor( uint256 idStart, string memory name, string memory symbol, string memory baseTokenURI) ExtendableNFT(name, symbol, baseTokenURI) { _tokenIdTracker.reset(idStart); mint(_msgSender(), HeroNFTDataBase({ fixedData:0, writeableData:0 })); // mint first token to notify event scan _setupRole(DEFAULT_ADMIN_ROLE, _msgSender()); _setupRole(DATA_ROLE, _msgSender()); } function setAttrSource(address a) external { require( hasRole(DATA_ROLE, _msgSender()), "R1" ); _attrSource = a; } function getAttrSource() external view returns(address a) { return _attrSource; } function setCodec(address c) external { require( hasRole(DATA_ROLE, _msgSender()), "R1" ); _codec = c; } function getCodec() external view returns(address c) { return _codec; } /** * @dev Creates a new token for `to`, emit {HeroNFTMint}. Its token ID will be automatically * assigned (and available on the emitted {IERC721-Transfer} event), and the token * URI autogenerated based on the base URI passed at construction. * * See {ERC721-_mint}. * * Requirements: * * - the caller must have the `MINTER_ROLE`. * * @param to new token owner address * @param data token data see {HeroNFTDataBase} * @return new token id */ function mint(address to, HeroNFTDataBase memory data) public returns(uint256) { require(hasRole(MINTER_ROLE, _msgSender()), "R1"); // We cannot just use balanceOf to create the new tokenId because tokens // can be burned (destroyed), so we need a separate counter. uint256 curID = _tokenIdTracker.current(); _mint(to, curID); // Save token datas _nftDatas[curID] = data; emit HeroNFTMint(to, curID, data); // increase token id _tokenIdTracker.increment(); return curID; } /** * @dev Creates a new token for `to`, emit {HeroNFTMint}. Its token ID give by caller * (and available on the emitted {IERC721-Transfer} event), and the token * URI autogenerated based on the base URI passed at construction. * * See {ERC721-_mint}. * * Requirements: * * - the caller must have the `MINTER_ROLE`. * * @param id new token id * @param to new token owner address * @param data token data see {HeroNFTDataBase} * @return new token id */ function mintFixedID( uint256 id, address to, HeroNFTDataBase memory data ) public returns (uint256) { require(hasRole(MINTER_ROLE, _msgSender()), "R1"); require(!_exists(id), "RE"); _mint(to, id); // Save token datas _nftDatas[id] = data; emit HeroNFTMint(to, id, data); return id; } /** * @dev modify token data * * @param tokenId token id * @param writeableData token data see {HeroNFTDataBase} */ function modNftData(uint256 tokenId, uint256 writeableData) external { require(hasRole(DATA_ROLE, _msgSender()), "R1"); _nftDatas[tokenId].writeableData = writeableData; } /** * @dev get token data * * @param tokenId token id * @param data token data see {HeroNFTDataBase} */ function getNftData(uint256 tokenId) external view returns(HeroNFTDataBase memory data){ require(_exists(tokenId), "T1"); data = _nftDatas[tokenId]; } }
// SPDX-License-Identifier: MIT // Mateline Contracts (HeroNFTCodec.sol) pragma solidity ^0.8.0; /** * @dev base struct of hero nft data */ struct HeroNFTDataBase { uint256 fixedData; uint256 writeableData; } /** * @dev hero fixed nft data version 1 */ struct HeroNFTFixedData_V1 { uint8 job; uint8 grade; uint16 minerAttr; uint16 battleAttr; } /** * @dev hero writeable nft data version 1 */ struct HeroNFTWriteableData_V1 { uint8 starLevel; uint16 level; uint64 exp; } /** * @dev hero nft data codec interface */ interface IHeroNFTCodec_V1 { /** * @dev encode HeroNFTFixedData to HeroNFTDataBase * @param data input data of HeroNFTFixedData_V1 * @return basedata output data of HeroNFTDataBase */ function fromHeroNftFixedData(HeroNFTFixedData_V1 memory data) external pure returns (HeroNFTDataBase memory basedata); /** * @dev encode HeroNFTFixedData to HeroNFTDataBase * @param fdata input data of HeroNFTFixedData_V1 * @param wdata input data of HeroNFTWriteableData_V1 * @return basedata output data of HeroNFTDataBase */ function fromHeroNftFixedAnWriteableData(HeroNFTFixedData_V1 memory fdata, HeroNFTWriteableData_V1 memory wdata) external pure returns (HeroNFTDataBase memory basedata); /** * @dev decode HeroNFTData from HeroNFTDataBase * @param data input data of HeroNFTDataBase * @return hndata output data of HeroNFTFixedData_V1 */ function getHeroNftFixedData(HeroNFTDataBase memory data) external pure returns(HeroNFTFixedData_V1 memory hndata); /** * @dev decode HeroNFTData from HeroNFTDataBase * @param data input data of HeroNFTDataBase * @return hndata output data of HeroNFTWriteableData_V1 */ function getHeroNftWriteableData(HeroNFTDataBase memory data) external pure returns(HeroNFTWriteableData_V1 memory hndata); /** * @dev get character id from HeroNFTDataBase * @param data input data of HeroNFTDataBase * @return characterId character id */ function getCharacterId(HeroNFTDataBase memory data) external pure returns (uint16 characterId); } /** * @dev hero nft data codec v1 implement */ contract HeroNFTCodec_V1 is IHeroNFTCodec_V1 { function fromHeroNftFixedData(HeroNFTFixedData_V1 memory data) external pure override returns (HeroNFTDataBase memory basedata) { basedata.fixedData = uint256(data.job) | (uint256(data.grade) << 8) | (uint256(data.minerAttr) << (8 + 8)) | (uint256(data.battleAttr) << (8 + 8 + 16)); basedata.writeableData = 0; } function fromHeroNftFixedAnWriteableData(HeroNFTFixedData_V1 memory fdata, HeroNFTWriteableData_V1 memory wdata) external pure override returns (HeroNFTDataBase memory basedata) { basedata.fixedData = uint256(fdata.job) | (uint256(fdata.grade) << 8) | (uint256(fdata.minerAttr) << (8 + 8)) | (uint256(fdata.battleAttr) << (8 + 8 + 16)); basedata.writeableData = (uint256(wdata.starLevel)) | (uint256(wdata.level << 8)) | (uint256(wdata.exp << (8 + 16))); } function getHeroNftFixedData(HeroNFTDataBase memory data) external pure override returns (HeroNFTFixedData_V1 memory hndata) { hndata.job = uint8(data.fixedData & 0xff); hndata.grade = uint8((data.fixedData >> 8) & 0xff); hndata.minerAttr = uint16((data.fixedData >> (8 + 8)) & 0xffff); hndata.battleAttr = uint16((data.fixedData >> (8 + 8 + 16)) & 0xffff); } function getHeroNftWriteableData(HeroNFTDataBase memory data) external pure override returns(HeroNFTWriteableData_V1 memory hndata) { hndata.starLevel = uint8(data.writeableData & 0xff); hndata.level = uint16((data.writeableData >> 8) & 0xffff); hndata.exp = uint64((data.writeableData >> 8 + 16) & 0xffffffffffffffff); } function getCharacterId(HeroNFTDataBase memory data) external pure override returns (uint16 characterId) { return uint16(data.fixedData & 0xffff); // job << 8 | grade; } }
// SPDX-License-Identifier: MIT // DreamIdol Contracts (HeroNFTMysteryBox.sol) pragma solidity ^0.8.0; import "./HeroNFTCodec.sol"; import "./HeroNFT.sol"; import "./mysterybox/MBRandomSourceBase.sol"; import "./mysterybox/MysteryBoxBase.sol"; contract HeroNFTMysteryBoxRandSource is MBRandomSourceBase { using RandomPoolLib for RandomPoolLib.RandomPool; HeroNFT public _heroNFTContract; constructor(address heroNftAddr) { _setupRole(DEFAULT_ADMIN_ROLE, _msgSender()); _setupRole(MINTER_ROLE, _msgSender()); _heroNFTContract = HeroNFT(heroNftAddr); } function randomAndMint(uint256 r, uint32 mysteryTp, address to) virtual override external returns(MBContentMinter1155Info[] memory sfts, MBContentMinterNftInfo[] memory nfts) { require(hasRole(MINTER_ROLE, _msgSender()), "ownership error"); uint32[] storage poolIDArray = _mbRandomSets[mysteryTp]; require(poolIDArray.length == 17, "mb type config wrong"); HeroNFTDataBase memory baseData = _getSingleRandHero(r, poolIDArray); // mint uint256 newId = _heroNFTContract.mint(to, baseData); nfts = new MBContentMinterNftInfo[](1); // 1 nft sfts = new MBContentMinter1155Info[](0); // no sft nfts[0] = MBContentMinterNftInfo({ addr : address(_heroNFTContract), tokenIds : new uint256[](1) }); nfts[0].tokenIds[0] = newId; } function _getSingleRandHero( uint256 r, uint32[] storage poolIDArray ) internal view returns (HeroNFTDataBase memory baseData) { uint32 index = 0; NFTRandPool storage pool = _randPools[poolIDArray[0]]; // index 0 : job rand (1-10) require(pool.exist, "job pool not exist"); uint8 job = uint8(pool.randPool.random(r)); r = _rand.nextRand(++index, r); pool = _randPools[poolIDArray[1]]; // index 1 : grade rand (1-5) require(pool.exist, "grade pool not exist"); uint8 grade = uint8(pool.randPool.random(r)); if(job <= 8){ pool = _randPools[poolIDArray[1 + grade]]; // index 2-6 : job(1-8) mineAttr rand by grade } else{ pool = _randPools[poolIDArray[6 + grade]]; // index 7-11 : job(9-10) mineAttr rand by grade } r = _rand.nextRand(++index, r); require(pool.exist, "mineAttr pool not exist"); uint16 mineAttr = uint8(pool.randPool.random(r)); pool = _randPools[poolIDArray[11 + grade]]; // index 12-16 : battleAttr rand by grade r = _rand.nextRand(++index, r); require(pool.exist, "battleAttr pool not exist"); uint16 battleAttr = uint8(pool.randPool.random(r)); HeroNFTFixedData_V1 memory fdata = HeroNFTFixedData_V1({ job : job, grade : grade, minerAttr : mineAttr, battleAttr : battleAttr }); HeroNFTWriteableData_V1 memory wdata = HeroNFTWriteableData_V1({ starLevel: 0, level : 1, exp : 0 }); IHeroNFTCodec_V1 codec = IHeroNFTCodec_V1(_heroNFTContract.getCodec()); baseData = codec.fromHeroNftFixedAnWriteableData(fdata, wdata); } function batchRandomAndMint(uint256 r, uint32 mysteryTp, address to, uint8 batchCount) virtual override external returns(MBContentMinter1155Info[] memory sfts, MBContentMinterNftInfo[] memory nfts) { require(hasRole(MINTER_ROLE, _msgSender()), "ownership error"); uint32[] storage poolIDArray = _mbRandomSets[mysteryTp]; require(poolIDArray.length == 17, "mb type config wrong"); nfts = new MBContentMinterNftInfo[](1); // 1 nft sfts = new MBContentMinter1155Info[](0); // no sft record nfts[0] = MBContentMinterNftInfo({ addr : address(_heroNFTContract), tokenIds : new uint256[](batchCount) }); for(uint8 i=0; i< batchCount; ++i) { r = _rand.nextRand(i, r); HeroNFTDataBase memory baseData = _getSingleRandHero(r, poolIDArray); // mint uint256 newId = _heroNFTContract.mint(to, baseData); nfts[0].tokenIds[i] = newId; } } } contract HeroNFTMysteryBox is MysteryBoxBase { function getName() external virtual override returns(string memory) { return "Hero NFT Mystery Box"; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title IERC2981Royalties /// @dev Interface for the ERC2981 - Token Royalty standard interface IERC2981Royalties { /// @notice Called with the sale price to determine how much royalty // is owed and to whom. /// @param _tokenId - the NFT asset queried for royalty information /// @param _value - the sale price of the NFT asset specified by _tokenId /// @return _receiver - address of who should be sent the royalty payment /// @return _royaltyAmount - the royalty payment amount for value sale price function royaltyInfo(uint256 _tokenId, uint256 _value) external view returns (address _receiver, uint256 _royaltyAmount); }
// SPDX-License-Identifier: MIT // Mateline Contracts (MBRandomSourceBase.sol) pragma solidity ^0.8.0; import "@openzeppelin/contracts/access/AccessControl.sol"; import "@openzeppelin/contracts/utils/Context.sol"; import "../utility/Random.sol"; import "../utility/RandomPoolLib.sol"; struct MBContentMinter1155Info { address addr; uint256[] tokenIds; uint256[] tokenValues; } struct MBContentMinterNftInfo { address addr; uint256[] tokenIds; } abstract contract MBRandomSourceBase is Context, AccessControl { using RandomPoolLib for RandomPoolLib.RandomPool; bytes32 public constant MANAGER_ROLE = keccak256("MANAGER_ROLE"); bytes32 public constant RANDOM_ROLE = keccak256("RANDOM_ROLE"); bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); struct NFTRandPool{ bool exist; RandomPoolLib.RandomPool randPool; } Random _rand; mapping(uint32 => NFTRandPool) _randPools; // poolID => nft data random pools mapping(uint32 => uint32[]) _mbRandomSets; // mystery type => poolID array constructor() { _setupRole(DEFAULT_ADMIN_ROLE, _msgSender()); _setupRole(MANAGER_ROLE, _msgSender()); _setupRole(RANDOM_ROLE, _msgSender()); } function setRandSource(address randAddr) external { require(hasRole(MANAGER_ROLE, _msgSender())); _rand = Random(randAddr); } function getRandSource() external view returns(address) { // require(hasRole(MANAGER_ROLE, _msgSender())); return address(_rand); } function _addPool(uint32 poolID, RandomPoolLib.RandomSet[] memory randSetArray) internal { NFTRandPool storage rp = _randPools[poolID]; rp.exist = true; for(uint i=0; i<randSetArray.length; ++i){ rp.randPool.pool.push(randSetArray[i]); } rp.randPool.initRandomPool(); } function addPool(uint32 poolID, RandomPoolLib.RandomSet[] memory randSetArray) external { require(hasRole(MANAGER_ROLE, _msgSender()),"not a manager"); require(!_randPools[poolID].exist,"rand pool already exist"); _addPool(poolID, randSetArray); } function modifyPool(uint32 poolID, RandomPoolLib.RandomSet[] memory randSetArray) external { require(hasRole(MANAGER_ROLE, _msgSender()),"not a manager"); require(_randPools[poolID].exist,"rand pool not exist"); NFTRandPool storage rp = _randPools[poolID]; delete rp.randPool.pool; for(uint i=0; i<randSetArray.length; ++i){ rp.randPool.pool.push(randSetArray[i]); } rp.randPool.initRandomPool(); } function removePool(uint32 poolID) external { require(hasRole(MANAGER_ROLE, _msgSender()),"not a manager"); require(_randPools[poolID].exist, "rand pool not exist"); delete _randPools[poolID]; } function getPool(uint32 poolID) public view returns(NFTRandPool memory) { require(_randPools[poolID].exist, "rand pool not exist"); return _randPools[poolID]; } function hasPool(uint32 poolID) external view returns(bool){ return (_randPools[poolID].exist); } function setRandomSet(uint32 mbTypeID, uint32[] calldata poolIds) external { require(hasRole(MANAGER_ROLE, _msgSender()),"not a manager"); delete _mbRandomSets[mbTypeID]; uint32[] storage poolIDArray = _mbRandomSets[mbTypeID]; for(uint i=0; i< poolIds.length; ++i){ poolIDArray.push(poolIds[i]); } } function unsetRandomSet(uint32 mysteryTp) external { require(hasRole(MANAGER_ROLE, _msgSender()),"not a manager"); delete _mbRandomSets[mysteryTp]; } function getRandomSet(uint32 mysteryTp) external view returns(uint32[] memory poolIds) { return _mbRandomSets[mysteryTp]; } function randomAndMint(uint256 r, uint32 mysteryTp, address to) virtual external returns(MBContentMinter1155Info[] memory sfts, MBContentMinterNftInfo[] memory nfts); function batchRandomAndMint(uint256 r, uint32 mysteryTp, address to, uint8 batchCount) virtual external returns(MBContentMinter1155Info[] memory sfts, MBContentMinterNftInfo[] memory nfts); }
// SPDX-License-Identifier: MIT // Mateline Contracts (MysteryBox1155.sol) pragma solidity ^0.8.0; import "../core/Extendable1155.sol"; // 1155 id : combine with randomType(uint32) << 32 | mysteryType(uint32) contract MysteryBox1155 is Extendable1155 { constructor(string memory uri) Extendable1155("MetaLine MysteryBox Semi-fungible Token", "MLMB", uri) { mint(_msgSender(), 0, 1, new bytes(0)); // mint first token to notify event scan } }
// SPDX-License-Identifier: MIT // Mateline Contracts (MysteryBoxBase.sol) pragma solidity ^0.8.0; import "@openzeppelin/contracts/access/AccessControl.sol"; import "@openzeppelin/contracts/security/Pausable.sol"; import "@openzeppelin/contracts/utils/Context.sol"; import "../utility/GasFeeCharger.sol"; import "./MysteryBox1155.sol"; import "./MBRandomSourceBase.sol"; abstract contract MysteryBoxBase is Context, Pausable, AccessControl, IOracleRandComsumer { using GasFeeCharger for GasFeeCharger.MethodExtraFees; bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); bytes32 public constant MANAGER_ROLE = keccak256("MANAGER_ROLE"); bytes32 public constant RAND_ROLE = keccak256("RAND_ROLE"); event OracleOpenMysteryBox(uint256 oracleRequestId, uint256 indexed mbTokenId, address indexed owner); event OpenMysteryBox(address indexed owner, uint256 indexed mbTokenId, MBContentMinter1155Info[] sfts, MBContentMinterNftInfo[] nfts); event BatchOracleOpenMysteryBox(uint256 oracleRequestId, uint256 indexed mbTokenId, address indexed owner, uint8 batchCount); event BatchOpenMysteryBox(address indexed owner, uint256 indexed mbTokenId, MBContentMinter1155Info[] sfts, MBContentMinterNftInfo[] nfts); struct UserData{ address owner; uint32 randomType; uint32 mysteryType; uint8 count; uint256 tokenId; } MysteryBox1155 public _mb1155; mapping(uint32=>address) _randomSources; // random type => random source mapping(uint256 => UserData) public _oracleUserData; // indexed by oracle request id // Method extra fee // For smart contract method which need extra transaction by other service, we define extra fee // extra fee charge by method call tx with `value` paramter, and send to target service wallet address GasFeeCharger.MethodExtraFees _methodExtraFees; constructor() { _setupRole(DEFAULT_ADMIN_ROLE, _msgSender()); _setupRole(PAUSER_ROLE, _msgSender()); _setupRole(MANAGER_ROLE, _msgSender()); _setupRole(RAND_ROLE, _msgSender()); } function getName() external virtual returns(string memory); function pause() public virtual { require(hasRole(PAUSER_ROLE, _msgSender()), "MysteryBox: must have pauser role to pause"); _pause(); } function unpause() public virtual { require(hasRole(PAUSER_ROLE, _msgSender()), "MysteryBox: must have pauser role to unpause"); _unpause(); } function setNftAddress(address nftAddr) external { require(hasRole(MANAGER_ROLE, _msgSender()), "MysteryBox: must have manager role to manage"); _mb1155 = MysteryBox1155(nftAddr); } function getNftAddress() external view returns(address) { return address(_mb1155); } function setRandomSource(uint32 randomType, address randomSrc) external { require(hasRole(MANAGER_ROLE, _msgSender()), "MysteryBox: must have manager role to manage"); _randomSources[randomType] = randomSrc; } function getRandomSource(uint32 randomType) external view returns(address){ return _randomSources[randomType]; } /** * @dev set smart contract method invoke by transaction with extra fee * * Requirements: * - caller must have `MANAGER_ROLE` * * @param methodKey key of which method need extra fee * @param value extra fee value * @param target target address where extra fee goes to */ function setMethodExtraFee(uint8 methodKey, uint256 value, address target) external { require( hasRole(MANAGER_ROLE, _msgSender()), "MysteryBox: must have manager role" ); _methodExtraFees.setMethodExtraFee(methodKey, value, target); } /** * @dev cancel smart contract method invoke by transaction with extra fee * * Requirements: * - caller must have `MANAGER_ROLE` * * @param methodKey key of which method need cancel extra fee */ function removeMethodExtraFee(uint8 methodKey) external { require( hasRole(MANAGER_ROLE, _msgSender()), "MysteryBox: must have manager role" ); _methodExtraFees.removeMethodExtraFee(methodKey); } /** * @dev open mystery box, emit {OracleOpenMysteryBox} * call `oracleRand` in {Random} of address from `getRandSource` in {MBRandomSource} * send a oracle random request and emit {OracleRandRequest} * * Extrafees: * - `oracleOpenMysteryBox` call need charge extra fee for `fulfillRandom` in {Random} call by oracle service * - methodKey = 1, extra gas fee = 0.0013 with tx.value needed * * Requirements: * - caller must out side contract, not from contract * - caller must owner of `tokenId` in {MysteryBox1155} * - contract not paused * * @param tokenId token id of {MysteryBox1155}, if succeed, token will be burned */ function oracleOpenMysteryBox(uint256 tokenId) external payable whenNotPaused { require(tx.origin == _msgSender(), "MysteryBox: only for outside account"); require(_mb1155.balanceOf(_msgSender(), tokenId) >= 1, "MysteryBox: insufficient mb"); // check mb 1155 type uint32 randomType = (uint32)((tokenId >> 32) & 0xffffffff); address randSrcAddr = _randomSources[randomType]; require(randSrcAddr != address(0), "MysteryBox: not a mystry box"); address rndAddr = MBRandomSourceBase(randSrcAddr).getRandSource(); require(rndAddr != address(0), "MysteryBox: rand address wrong"); _methodExtraFees.chargeMethodExtraFee(1); // charge oracleOpenMysteryBox extra fee _mb1155.burn(_msgSender(), tokenId, 1); uint256 reqid = Random(rndAddr).oracleRand(); UserData storage userData = _oracleUserData[reqid]; userData.owner = _msgSender(); userData.randomType = randomType; userData.mysteryType = (uint32)(tokenId & 0xffffffff); userData.tokenId = tokenId; userData.count = 1; emit OracleOpenMysteryBox(reqid, tokenId, _msgSender()); } /** * @dev batch open mystery box, emit {BatchOracleOpenMysteryBox} * call `oracleRand` in {Random} of address from `getRandSource` in {MBRandomSource} * send a oracle random request and emit {OracleRandRequest} * * Extrafees: * - `batchOracleOpenMysteryBox` call need charge extra fee for `fulfillRandom` in {Random} call by oracle service * - methodKey = 2, extra gas fee = 0.0065 with tx.value needed * * Requirements: * - caller must out side contract, not from contract * - caller must owner of `tokenId` in {MysteryBox1155} * - contract not paused * * @param tokenId token id of {MysteryBox1155}, if succeed, token will be burned */ function batchOracleOpenMysteryBox(uint256 tokenId, uint8 batchCount) external payable whenNotPaused { require(tx.origin == _msgSender(), "MysteryBox: only for outside account"); require(batchCount <= 10, "MysteryBox: batch count overflow"); require(_mb1155.balanceOf(_msgSender(), tokenId) >= batchCount, "MysteryBox: insufficient mb"); // check mb 1155 type uint32 randomType = (uint32)((tokenId >> 32) & 0xffffffff); address randSrcAddr = _randomSources[randomType]; require(randSrcAddr != address(0), "MysteryBox: not a mystry box"); address rndAddr = MBRandomSourceBase(randSrcAddr).getRandSource(); require(rndAddr != address(0), "MysteryBox: rand address wrong"); _methodExtraFees.chargeMethodExtraFee(2); // charge batchOracleOpenMysteryBox extra fee _mb1155.burn(_msgSender(), tokenId, batchCount); uint256 reqid = Random(rndAddr).oracleRand(); UserData storage userData = _oracleUserData[reqid]; userData.owner = _msgSender(); userData.randomType = randomType; userData.mysteryType = (uint32)(tokenId & 0xffffffff); userData.tokenId = tokenId; userData.count = batchCount; emit BatchOracleOpenMysteryBox(reqid, tokenId, _msgSender(), batchCount); } // call back from random contract which triger by service call {fulfillOracleRand} function function oracleRandResponse(uint256 reqid, uint256 randnum) override external { require(hasRole(RAND_ROLE, _msgSender()), "MysteryBox: must have rand role"); UserData storage userData = _oracleUserData[reqid]; require(userData.owner != address(0), "MysteryBox: nftdata owner not exist"); address randSrcAddr = _randomSources[userData.randomType]; require(randSrcAddr != address(0), "MysteryBox: not a mystry box"); if(userData.count > 1) { (MBContentMinter1155Info[] memory sfts, MBContentMinterNftInfo[] memory nfts) = MBRandomSourceBase(randSrcAddr).batchRandomAndMint(randnum, userData.mysteryType, userData.owner, userData.count); emit BatchOpenMysteryBox(userData.owner, userData.tokenId, sfts, nfts); } else { (MBContentMinter1155Info[] memory sfts, MBContentMinterNftInfo[] memory nfts) = MBRandomSourceBase(randSrcAddr).randomAndMint(randnum, userData.mysteryType, userData.owner); emit OpenMysteryBox(userData.owner, userData.tokenId, sfts, nfts); } delete _oracleUserData[reqid]; } }
// SPDX-License-Identifier: MIT // Mateline Contracts (MysteryBoxShop.sol) pragma solidity ^0.8.0; import "@openzeppelin/contracts/access/AccessControl.sol"; import "@openzeppelin/contracts/security/Pausable.sol"; import "@openzeppelin/contracts/utils/Context.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol"; import "./MysteryBox1155.sol"; contract MysteryBoxShop is Context, Pausable, AccessControl { struct OnSaleMysterBox{ // config data -------------------------------------------------------- address mysteryBox1155Addr; // mystery box address uint256 mbTokenId; // mystery box token id address tokenAddr; // charge token addr, could be 20 or 1155 uint256 tokenId; // =0 means 20 token, else 1155 token uint256 price; // price value bool isBurn; // = ture means charge token will be burned, else charge token save in this contract uint64 beginTime; // start sale timeStamp in seconds since unix epoch, =0 ignore this condition uint64 endTime; // end sale timeStamp in seconds since unix epoch, =0 ignore this condition uint64 renewTime; // how long in seconds for each renew uint256 renewCount; // how many count put on sale for each renew uint32 whitelistId; // = 0 means open sale, else will check if buyer address in white list address nftholderCheck; // = address(0) won't check, else will check if buyer hold some other nft uint32 perAddrLimit; // = 0 means no limit, else means each user address max buying count } struct OnSaleMysterBoxRunTime { // runtime data ------------------------------------------------------- uint64 nextRenewTime; // after this timeStamp in seconds since unix epoch, will put at max [renewCount] on sale // config & runtime data ---------------------------------------------- uint256 countLeft; // how many boxies left } bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); bytes32 public constant MANAGER_ROLE = keccak256("MANAGER_ROLE"); bytes32 public constant OPERATER_ROLE = keccak256("OPERATER_ROLE"); event SetOnSaleMysterBox(string indexed pairName, OnSaleMysterBox saleConfig, OnSaleMysterBoxRunTime saleData); event UnsetOnSaleMysterBox(string indexed pairName, OnSaleMysterBox saleConfig, OnSaleMysterBoxRunTime saleData); event SetOnSaleMBCheckCondition( string indexed pairName, uint256 price, uint32 whitelistId, address nftholderCheck, uint32 perAddrLimit); event SetOnSaleMBCountleft(string indexed pairName, uint countLeft); event PerAddrBuyCountChange(string indexed pairName, address indexed userAddr, uint32 count); event BuyMysteryBox(address indexed userAddr, string indexed pairName, OnSaleMysterBox saleConfig, OnSaleMysterBoxRunTime saleData); event BatchBuyMysteryBox(address indexed userAddr, string indexed pairName, OnSaleMysterBox saleConfig, OnSaleMysterBoxRunTime saleData, uint256 count); mapping(string=>OnSaleMysterBox) public _onSaleMysterBoxes; mapping(string=>OnSaleMysterBoxRunTime) public _onSaleMysterBoxDatas; mapping(string=>mapping(address=>uint32)) public _perAddrBuyCount; address public _receiveIncomAddress; mapping(uint32=>mapping(address=>bool)) public _whitelists; constructor() { _setupRole(DEFAULT_ADMIN_ROLE, _msgSender()); _setupRole(PAUSER_ROLE, _msgSender()); _setupRole(MANAGER_ROLE, _msgSender()); _setupRole(OPERATER_ROLE, _msgSender()); } function pause() public virtual { require(hasRole(PAUSER_ROLE, _msgSender()), "P1"); _pause(); } function unpause() public virtual { require(hasRole(PAUSER_ROLE, _msgSender()), "P2"); _unpause(); } function addWitheList(uint32 wlId, address[] memory whitelist) external { require(hasRole(MANAGER_ROLE, _msgSender()), "MysteryBoxShop: must have manager role to manage"); mapping(address=>bool) storage wl = _whitelists[wlId]; for(uint i=0; i< whitelist.length; ++i){ wl[whitelist[i]] = true; } } function removeWhiteList(uint32 wlId, address[] memory whitelist) external { require(hasRole(MANAGER_ROLE, _msgSender()), "MysteryBoxShop: must have manager role to manage"); mapping(address=>bool) storage wl = _whitelists[wlId]; for(uint i=0; i< whitelist.length; ++i){ delete wl[whitelist[i]]; } } function setOnSaleMysteryBox(string calldata pairName, OnSaleMysterBox memory saleConfig, OnSaleMysterBoxRunTime memory saleData) external whenNotPaused { require(hasRole(MANAGER_ROLE, _msgSender()), "MysteryBoxShop: must have manager role to manage"); if(saleConfig.renewTime > 0) { saleData.nextRenewTime = (uint64)(block.timestamp + saleConfig.renewTime); } _onSaleMysterBoxes[pairName] = saleConfig; _onSaleMysterBoxDatas[pairName] = saleData; emit SetOnSaleMysterBox(pairName, saleConfig, saleData); } function unsetOnSaleMysteryBox(string calldata pairName) external whenNotPaused { require(hasRole(MANAGER_ROLE, _msgSender()), "MysteryBoxShop: must have manager role to manage"); OnSaleMysterBox storage onSalePair = _onSaleMysterBoxes[pairName]; OnSaleMysterBoxRunTime storage onSalePairData = _onSaleMysterBoxDatas[pairName]; emit UnsetOnSaleMysterBox(pairName, onSalePair, onSalePairData); delete _onSaleMysterBoxes[pairName]; delete _onSaleMysterBoxDatas[pairName]; } function setOnSaleMBCheckCondition( string calldata pairName, uint256 price, uint32 whitelistId, address nftholderCheck, uint32 perAddrLimit ) external { require(hasRole(OPERATER_ROLE, _msgSender()), "MysteryBoxShop: must have operater role"); OnSaleMysterBox storage onSalePair = _onSaleMysterBoxes[pairName]; onSalePair.price = price; onSalePair.whitelistId = whitelistId; onSalePair.nftholderCheck = nftholderCheck; onSalePair.perAddrLimit = perAddrLimit; emit SetOnSaleMBCheckCondition(pairName, price, whitelistId, nftholderCheck, perAddrLimit); } function setOnSaleMBCountleft(string calldata pairName, uint countLeft) external { require(hasRole(OPERATER_ROLE, _msgSender()), "MysteryBoxShop: must have operater role"); OnSaleMysterBoxRunTime storage onSalePairData = _onSaleMysterBoxDatas[pairName]; onSalePairData.countLeft = countLeft; emit SetOnSaleMBCountleft(pairName, countLeft); } function setReceiveIncomeAddress(address incomAddr) external { require(hasRole(MANAGER_ROLE, _msgSender()), "MysteryBoxShop: must have manager role to manage"); _receiveIncomAddress = incomAddr; } function _checkSellCondition(OnSaleMysterBox storage onSalePair, OnSaleMysterBoxRunTime storage onSalePairData) internal { if(onSalePair.beginTime > 0) { require(block.timestamp >= onSalePair.beginTime, "MysteryBoxShop: sale not begin"); } if(onSalePair.endTime > 0) { require(block.timestamp <= onSalePair.endTime, "MysteryBoxShop: sale finished"); } if(onSalePair.whitelistId > 0) { require(_whitelists[onSalePair.whitelistId][_msgSender()], "MysteryBoxShop: not in whitelist"); } if(onSalePair.nftholderCheck != address(0)) { require(IERC721(onSalePair.nftholderCheck).balanceOf(_msgSender()) > 0, "MysteryBoxShop: no authority"); } if(onSalePair.renewTime > 0) { if(block.timestamp > onSalePairData.nextRenewTime) { onSalePairData.nextRenewTime = (uint64)(onSalePairData.nextRenewTime + onSalePair.renewTime * (1 + ((block.timestamp - onSalePairData.nextRenewTime) / onSalePair.renewTime))); onSalePairData.countLeft = onSalePair.renewCount; } } } function _chargeByDesiredCount( string calldata pairName, OnSaleMysterBox storage onSalePair, OnSaleMysterBoxRunTime storage onSalePairData, uint256 count) internal returns (uint256 realCount) { realCount = count; if(realCount > onSalePairData.countLeft) { realCount = onSalePairData.countLeft; } if(onSalePair.perAddrLimit > 0) { uint32 buyCount = _perAddrBuyCount[pairName][_msgSender()]; uint32 buyCountLeft = (onSalePair.perAddrLimit > buyCount)? (onSalePair.perAddrLimit - buyCount) : 0; if(buyCountLeft < realCount){ realCount = buyCountLeft; } if(realCount > 0){ buyCount += uint32(realCount); _perAddrBuyCount[pairName][_msgSender()] = buyCount; emit PerAddrBuyCountChange(pairName, _msgSender(), buyCount); } } require(realCount > 0, "MysteryBoxShop: insufficient mystery box"); onSalePairData.countLeft -= realCount; if(onSalePair.price > 0){ uint256 realPrice = onSalePair.price * realCount; if(onSalePair.tokenAddr == address(0)){ require(msg.value >= realPrice, "MysteryBoxShop: insufficient value"); // receive eth (bool sent, ) = _receiveIncomAddress.call{value:msg.value}(""); require(sent, "MysteryBoxShop: transfer income error"); } else if(onSalePair.tokenId > 0) { // 1155 require(IERC1155(onSalePair.tokenAddr).balanceOf( _msgSender(), onSalePair.tokenId) >= realPrice , "MysteryBoxShop: erc1155 insufficient token"); if(onSalePair.isBurn) { // burn ERC1155Burnable(onSalePair.tokenAddr).burn(_msgSender(), onSalePair.tokenId, realPrice); } else { // charge IERC1155(onSalePair.tokenAddr).safeTransferFrom(_msgSender(), address(this), onSalePair.tokenId, realPrice, "buy mb"); } } else{ // 20 require(IERC20(onSalePair.tokenAddr).balanceOf(_msgSender()) >= realPrice , "MysteryBoxShop: erc20 insufficient token"); if(onSalePair.isBurn) { // burn ERC20Burnable(onSalePair.tokenAddr).burnFrom(_msgSender(), realPrice); } else { // charge TransferHelper.safeTransferFrom(onSalePair.tokenAddr, _msgSender(), address(this), realPrice); } } } } function buyMysteryBox(string calldata pairName) external payable whenNotPaused { OnSaleMysterBox storage onSalePair = _onSaleMysterBoxes[pairName]; OnSaleMysterBoxRunTime storage onSalePairData = _onSaleMysterBoxDatas[pairName]; require(address(onSalePair.mysteryBox1155Addr) != address(0), "MysteryBoxShop: mystery box not on sale"); _checkSellCondition(onSalePair, onSalePairData); _chargeByDesiredCount(pairName, onSalePair, onSalePairData, 1); MysteryBox1155(onSalePair.mysteryBox1155Addr).mint(_msgSender(), onSalePair.mbTokenId, 1, "buy mb"); emit BuyMysteryBox(_msgSender(), pairName, onSalePair, onSalePairData); } function batchBuyMysterBox(string calldata pairName, uint32 count) external payable whenNotPaused { OnSaleMysterBox storage onSalePair = _onSaleMysterBoxes[pairName]; OnSaleMysterBoxRunTime storage onSalePairData = _onSaleMysterBoxDatas[pairName]; require(address(onSalePair.mysteryBox1155Addr) != address(0), "MysteryBoxShop: mystery box not on sale"); _checkSellCondition(onSalePair, onSalePairData); uint256 realCount = _chargeByDesiredCount(pairName, onSalePair, onSalePairData, count); MysteryBox1155(onSalePair.mysteryBox1155Addr).mint(_msgSender(), onSalePair.mbTokenId, realCount, "buy mb"); emit BatchBuyMysteryBox(_msgSender(), pairName, onSalePair, onSalePairData, realCount); } function fetchIncome(address tokenAddr, uint256 value) external { require(hasRole(MANAGER_ROLE, _msgSender()), "MysteryBoxShop: must have manager role to manage"); IERC20 token = IERC20(tokenAddr); if(value <= 0){ value = token.balanceOf(address(this)); } require(value > 0, "MysteryBoxShop: zero value"); TransferHelper.safeTransfer(tokenAddr, _receiveIncomAddress, value); } function fetchIncome1155(address tokenAddr, uint256 tokenId, uint256 value) external { require(hasRole(MANAGER_ROLE, _msgSender()), "MysteryBoxShop: must have manager role to manage"); IERC1155 token = IERC1155(tokenAddr); if(value <= 0){ value = token.balanceOf(address(this), tokenId); } require(value > 0, "MysteryBoxShop: zero value"); token.safeTransferFrom(address(this), _receiveIncomAddress, tokenId, value, "fetch income"); } }
// SPDX-License-Identifier: MIT // Mateline Contracts (GasFeeCharger.sol) pragma solidity ^0.8.0; library GasFeeCharger { struct MethodWithExrtraFee { address target; uint256 value; } struct MethodExtraFees { mapping(uint8=>MethodWithExrtraFee) extraFees; } function setMethodExtraFee(MethodExtraFees storage extraFees, uint8 methodKey, uint256 value, address target) internal { MethodWithExrtraFee storage fee = extraFees.extraFees[methodKey]; fee.value = value; fee.target = target; } function removeMethodExtraFee(MethodExtraFees storage extraFees, uint8 methodKey) internal { delete extraFees.extraFees[methodKey]; } function chargeMethodExtraFee(MethodExtraFees storage extraFees, uint8 methodKey) internal returns(bool) { MethodWithExrtraFee storage fee = extraFees.extraFees[methodKey]; if(fee.target == address(0)){ return true; // no need charge fee } require(msg.value >= fee.value, "msg fee not enough"); // Call returns a boolean value indicating success or failure. // This is the current recommended method to use. (bool sent, ) = fee.target.call{value: msg.value}(""); require(sent, "Trans fee err"); return sent; } }
// SPDX-License-Identifier: MIT // Mateline Contracts (Random.sol) pragma solidity ^0.8.0; import "@openzeppelin/contracts/access/AccessControl.sol"; import "@openzeppelin/contracts/utils/Context.sol"; interface IOracleRandComsumer { function oracleRandResponse(uint256 reqid, uint256 randnum) external; } /** * @dev A random source contract provids `seedRand`, `sealedRand` and `oracleRand` methods */ contract Random is Context, AccessControl { bytes32 public constant MANAGER_ROLE = keccak256("MANAGER_ROLE"); bytes32 public constant ORACLE_ROLE = keccak256("ORACLE_ROLE"); // an auto increased number by each _seedRand call uint32 _nonce; // an auto increased number by each setSealed call uint32 _sealedNonce; // an random seed set by manager uint256 _randomSeed; // an auto increased number by each oracleRand call uint256 _orcacleReqIDSeed; // sealed random seed data structure struct RandomSeed { uint32 sealedNonce; uint256 sealedNumber; uint256 seed; uint256 h1; } mapping(uint256 => RandomSeed) _sealedRandom; // _encodeSealedKey(addr) => sealed random seed data structure mapping(uint256 => address) _oracleRandRequests; // oracle rand request id => caller address /** * @dev emit when `oracleRand` called * @param reqid oracle rand request id * @param requestAddress caller address */ event OracleRandRequest(uint256 reqid, address indexed requestAddress); /** * @dev emit when `fulfillOracleRand` called * @param reqid oracle rand request id * @param randnum random number feed to request caller * @param requestAddress `oracleRand` requrest caller address */ event OracleRandResponse(uint256 reqid, uint256 randnum, address indexed requestAddress); constructor() { _setupRole(DEFAULT_ADMIN_ROLE, _msgSender()); _setupRole(MANAGER_ROLE, _msgSender()); _setupRole(ORACLE_ROLE, _msgSender()); } /** * @dev check address is sealed, usually call by contract to check user seal status * * @param addr user addr * @return ture if user is sealed */ function isSealed(address addr) external view returns (bool) { return _isSealedDirect(_encodeSealedKey(addr)); } /** * @dev set random seed * * Requirements: * - caller must have `MANAGER_ROLE` * * @param s random seed */ function setRandomSeed(uint256 s) external { require(hasRole(MANAGER_ROLE, _msgSender()),"not manager"); _randomSeed = s; } /** * @dev set user sealed, usually call by contract to seal a user * this function will `_encodeSealedKey` by tx.orgin and `_msgSender` * if success call this function, then user can call `sealedRand` */ function setSealed() external { require(block.number >= 100,"block is too small"); uint256 sealedKey = _encodeSealedKey(tx.origin); require(!_isSealedDirect(sealedKey),"should not sealed"); _sealedNonce++; RandomSeed storage rs = _sealedRandom[sealedKey]; rs.sealedNumber = block.number + 1; rs.sealedNonce = _sealedNonce; rs.seed = _randomSeed; uint256 seed = uint256( keccak256( abi.encodePacked(block.number, block.timestamp, _sealedNonce) ) ); uint32 n1 = uint32(seed % 100); rs.h1 = uint256(blockhash(block.number - n1)); } /** * @dev seal rand and get a random number * * Requirements: * - caller must call `setSealed` first * * @return ret random number */ function sealedRand() external returns (uint256 ret) { return _sealedRand(); } /** * @dev input a seed and get a random number depends on seed * * @param inputSeed random seed * @return ret random number depends on seed */ function seedRand(uint256 inputSeed) external returns (uint256 ret) { return _seedRand(inputSeed); } /** * @dev start an oracle rand, emit {OracleRandRequest}, call by contract * oracle service wait on {OracleRandRequest} event and call `fulfillOracleRand` * * Requirements: * - caller must implements `oracleRandResponse` of {IOracleRandComsumer} * * @return reqid is request id of oracle rand request */ function oracleRand() external returns (uint256) { _orcacleReqIDSeed = _orcacleReqIDSeed + 1; uint256 reqid = _orcacleReqIDSeed; //console.log("[sol]reqid=",reqid); _oracleRandRequests[reqid] = _msgSender(); emit OracleRandRequest(reqid, _msgSender()); return reqid; } /** * @dev fulfill an oracle rand, emit {OracleRandResponse} * call by oracle when it get {OracleRandRequest}, feed with an random number * * Requirements: * - caller must have `ORACLE_ROLE` * * @param reqid request id of oracle rand request * @param randnum random number feed by oracle * @return rand number */ function fulfillOracleRand(uint256 reqid, uint256 randnum) external returns (uint256 rand) { require(hasRole(ORACLE_ROLE, _msgSender()),"need oracle role"); require(_oracleRandRequests[reqid] != address(0),"reqid not exist"); rand = _seedRand(randnum); IOracleRandComsumer comsumer = IOracleRandComsumer(_oracleRandRequests[reqid]); comsumer.oracleRandResponse(reqid, rand); delete _oracleRandRequests[reqid]; emit OracleRandResponse(reqid, rand, address(comsumer)); return rand; } /** * @dev input index and random number, return with new random number depends on input * use chain blockhash as random array, we can fetch many random number with a seed in one transaction * * @param index a number increased by caller, make sure that we don't get same outcome * @param randomNum random number as seed * @return ret is new rand number */ function nextRand(uint32 index, uint256 randomNum) external view returns(uint256 ret){ uint256 n1 = (randomNum + index) % block.number; uint256 h1 = uint256(blockhash(n1)); return uint256( keccak256( abi.encodePacked(index, n1, h1) ) ); } function _seedRand(uint256 inputSeed) internal returns (uint256 ret) { require(block.number >= 1000,"block.number need >=1000"); uint256 seed = uint256( keccak256(abi.encodePacked(block.number, block.timestamp, inputSeed)) ); uint32 n1 = uint32(seed % 100); uint32 n2 = uint32(seed % 1000); uint256 h1 = uint256(blockhash(block.number - n1)); uint256 h2 = uint256(blockhash(block.number - n2)); _nonce++; uint256 v = uint256( keccak256(abi.encodePacked(_randomSeed, h1, h2, _nonce)) ); return v; } // addr usually be tx.origin function _encodeSealedKey(address addr) internal view returns (uint256 key) { return uint256( keccak256( abi.encodePacked(addr, _msgSender()) ) ); } function _sealedRand() internal returns (uint256 ret) { uint256 sealedKey = _encodeSealedKey(tx.origin); bool v = _isSealedDirect(sealedKey); require(v == true,"should sealed"); RandomSeed storage rs = _sealedRandom[sealedKey]; uint256 h2 = uint256(blockhash(rs.sealedNumber)); ret = uint256( keccak256( abi.encodePacked( rs.seed, rs.h1, h2, block.difficulty, rs.sealedNonce ) ) ); delete _sealedRandom[sealedKey]; return ret; } function _isSealedDirect(uint256 sealedKey) internal view returns (bool){ return _sealedRandom[sealedKey].sealedNumber != 0; } }
// SPDX-License-Identifier: MIT // Mateline Contracts (RandomPoolLib.sol) pragma solidity ^0.8.0; import "./Random.sol"; /** * @dev Random pool that allow user random in different rate section */ library RandomPoolLib { // random set with rate and range struct RandomSet { uint32 rate; uint rangMin; uint rangMax; } // random pool with an array of random set struct RandomPool { uint32 totalRate; RandomSet[] pool; } // initialize a random pool function initRandomPool(RandomPool storage pool) external { for(uint i=0; i< pool.pool.length; ++i){ pool.totalRate += pool.pool[i].rate; } require(pool.totalRate > 0); } // use and randomNum to fetch a random result in the random set array function random(RandomPool storage pool, uint256 r) external view returns(uint ret) { require(pool.totalRate > 0); uint32 rate = uint32((r>>224) % pool.totalRate); uint32 curRate = 0; for(uint i=0; i<pool.pool.length; ++i){ curRate += pool.pool[i].rate; if(rate > curRate){ continue; } return randBetween(pool.pool[i].rangMin, pool.pool[i].rangMax, r); } } // input r and min,max, return a number between [min, max] with r function randBetween( uint256 min, uint256 max, uint256 r ) public pure returns (uint256 ret) { if(min >= max) { return min; } uint256 rang = (max+1) - min; return uint256(min + (r % rang)); } }
// SPDX-License-Identifier: MIT // Override from OpenZeppelin Contracts v4.4.1 (utils/Counters.sol) pragma solidity ^0.8.0; /** * @title ResetableCounters * @author Matt Condon (@shrugs) * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number * of elements in a mapping, issuing ERC721 ids, or counting request ids. * * Include with `using Counters for Counters.Counter;` */ library ResetableCounters { struct Counter { // This variable should never be directly accessed by users of the library: interactions must be restricted to // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add // this feature: see https://github.com/ethereum/solidity/issues/4637 uint256 _value; // default: 0 } function current(Counter storage counter) internal view returns (uint256) { return counter._value; } function increment(Counter storage counter) internal { unchecked { counter._value += 1; } } function decrement(Counter storage counter) internal { uint256 value = counter._value; require(value > 0, "Counter: decrement overflow"); unchecked { counter._value = value - 1; } } function reset(Counter storage counter, uint256 v) internal { counter._value = v; } }
// contracts/TransferHelper.sol // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; library TransferHelper { function safeApprove(address token, address to, uint value) internal { // bytes4(keccak256(bytes('approve(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED'); } function safeTransfer(address token, address to, uint value) internal { // bytes4(keccak256(bytes('transfer(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED'); } function safeTransferFrom(address token, address from, address to, uint value) internal { // bytes4(keccak256(bytes('transferFrom(address,address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED'); } function safeTransferETH(address to, uint value) internal { (bool success,) = to.call{value:value}(new bytes(0)); require(success, 'TransferHelper: ETH_TRANSFER_FAILED'); } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "metadata": { "useLiteralContent": true } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"string","name":"uri","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"extendData","type":"bytes"}],"name":"Extendable1155Modify","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"DATA_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_royalties","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"burnBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"erc20","type":"address"}],"name":"fetchIncome","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fetchIncomeEth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getTokenExtendNftData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"mintBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"extendData","type":"bytes"}],"name":"modifyExtendData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"royaltyAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"royalties","type":"uint256"}],"name":"setRoyalties","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"newuri","type":"string"}],"name":"updateURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b5060405162003f0138038062003f01833981016040819052620000349162000976565b60405180606001604052806027815260200162003eda6027913960408051808201909152600481526326a626a160e11b60208201528282828280620000798162000155565b506004805460ff191690558251620000999060069060208601906200089d565b508151620000af9060079060208501906200089d565b506101f4600855620000c360003362000172565b620000ef7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a63362000172565b6200011b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a3362000172565b5050505050506200014e620001356200016e60201b60201c565b604080516000808252602082019092526001906200017e565b5062000c64565b80516200016a9060039060208401906200089d565b5050565b3390565b6200016a82826200023c565b3360009081527f0781d7cac9c378efa22a7481e4d4d29704a680ddf504b3bc50b517700ee11e6c602052604090205460ff16620002285760405162461bcd60e51b815260206004820152603860248201527f455243313135355072657365744d696e7465725061757365723a206d7573742060448201527f68617665206d696e74657220726f6c6520746f206d696e74000000000000000060648201526084015b60405180910390fd5b6200023684848484620002dc565b50505050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff166200016a576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055620002983390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6001600160a01b0384166200033e5760405162461bcd60e51b815260206004820152602160248201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b60648201526084016200021f565b3360006200034c856200040d565b905060006200035b856200040d565b90506200036e836000898585896200045b565b60008681526001602090815260408083206001600160a01b038b16845290915281208054879290620003a290849062000aa2565b909155505060408051878152602081018790526001600160a01b03808a1692600092918716917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a462000404836000898989896200047e565b50505050505050565b604080516001808252818301909252606091600091906020808301908036833701905050905082816000815181106200044a576200044a62000b8c565b602090810291909101015292915050565b620004768686868686866200065b60201b620010da1760201c565b505050505050565b6200049d846001600160a01b03166200080960201b6200126b1760201c565b15620004765760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190620004d9908990899088908890889060040162000a46565b602060405180830381600087803b158015620004f457600080fd5b505af192505050801562000527575060408051601f3d908101601f19168201909252620005249181019062000943565b60015b620005e8576200053662000bb8565b806308c379a014156200057757506200054e62000bd5565b806200055b575062000579565b8060405162461bcd60e51b81526004016200021f919062000a8d565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e204552433131353560448201527f526563656976657220696d706c656d656e74657200000000000000000000000060648201526084016200021f565b6001600160e01b0319811663f23a6e6160e01b14620004045760405162461bcd60e51b815260206004820152602860248201527f455243313135353a204552433131353552656365697665722072656a656374656044820152676420746f6b656e7360c01b60648201526084016200021f565b620006768686868686866200081860201b6200127a1760201c565b6001600160a01b0385166200070a5760005b83518110156200070857828181518110620006a757620006a762000b8c565b602002602001015160056000868481518110620006c857620006c862000b8c565b602002602001015181526020019081526020016000206000828254620006ef919062000aa2565b909155506200070090508162000b58565b905062000688565b505b6001600160a01b038416620004765760005b8351811015620004045760008482815181106200073d576200073d62000b8c565b6020026020010151905060008483815181106200075e576200075e62000b8c565b6020026020010151905060006005600084815260200190815260200160002054905081811015620007e35760405162461bcd60e51b815260206004820152602860248201527f455243313135353a206275726e20616d6f756e74206578636565647320746f74604482015267616c537570706c7960c01b60648201526084016200021f565b60009283526005602052604090922091039055620008018162000b58565b90506200071c565b6001600160a01b03163b151590565b620008338686868686866200047660201b620012631760201c565b60045460ff1615620004765760405162461bcd60e51b815260206004820152602c60248201527f455243313135355061757361626c653a20746f6b656e207472616e736665722060448201526b1dda1a5b19481c185d5cd95960a21b60648201526084016200021f565b828054620008ab9062000aec565b90600052602060002090601f016020900481019282620008cf57600085556200091a565b82601f10620008ea57805160ff19168380011785556200091a565b828001600101855582156200091a579182015b828111156200091a578251825591602001919060010190620008fd565b50620009289291506200092c565b5090565b5b808211156200092857600081556001016200092d565b6000602082840312156200095657600080fd5b81516001600160e01b0319811681146200096f57600080fd5b9392505050565b6000602082840312156200098957600080fd5b81516001600160401b0380821115620009a157600080fd5b818401915084601f830112620009b657600080fd5b815181811115620009cb57620009cb62000ba2565b6040519150620009e6601f8201601f19166020018362000b29565b808252856020828501011115620009fc57600080fd5b62000a0f81602084016020860162000abd565b50949350505050565b6000815180845262000a3281602086016020860162000abd565b601f01601f19169290920160200192915050565b6001600160a01b03868116825285166020820152604081018490526060810183905260a06080820181905260009062000a829083018462000a18565b979650505050505050565b6020815260006200096f602083018462000a18565b6000821982111562000ab85762000ab862000b76565b500190565b60005b8381101562000ada57818101518382015260200162000ac0565b83811115620002365750506000910152565b600181811c9082168062000b0157607f821691505b6020821081141562000b2357634e487b7160e01b600052602260045260246000fd5b50919050565b601f8201601f191681016001600160401b038111828210171562000b515762000b5162000ba2565b6040525050565b600060001982141562000b6f5762000b6f62000b76565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600060033d111562000bd25760046000803e5060005160e01c5b90565b600060443d101562000be45790565b6040516003193d81016004833e81513d6001600160401b03808311602484018310171562000c1457505050505090565b828501915081518181111562000c2d5750505050505090565b843d870101602082850101111562000c485750505050505090565b62000c596020828601018762000b29565b509095945050505050565b6132668062000c746000396000f3fe608060405234801561001057600080fd5b506004361061021b5760003560e01c806366faf1f511610125578063a22cb465116100ad578063d547741f1161007c578063d547741f146104b9578063e63ab1e9146104cc578063e985e9c5146104f3578063f242432a1461052f578063f5298aca1461054257600080fd5b8063a22cb4651461045e578063bd85b03914610471578063c30f4a5a14610491578063d5391393146104a457600080fd5b806389f83e4e116100f457806389f83e4e1461042057806391d148541461043357806395d89b411461044657806399e751231461044e578063a217fddf1461045657600080fd5b806366faf1f5146103cb5780636b20c454146103f2578063731133e9146104055780638456cb591461041857600080fd5b80632eb2c2d6116101a85780633f4ba83a116101775780633f4ba83a146103635780634e1273f41461036b5780634f558e791461038b5780635c975abb146103ad5780635e03d937146103b857600080fd5b80632eb2c2d6146103175780632f2ff15d1461032a57806336568abe1461033d57806338429fde1461035057600080fd5b80630e89341c116101ef5780630e89341c146102875780631f7fdffa1461029a578063248a9ca3146102af5780632a55205a146102d25780632b80183f1461030457600080fd5b8062fdd58e1461022057806301ffc9a71461024657806306fdde03146102695780630977fd731461027e575b600080fd5b61023361022e366004612800565b610555565b6040519081526020015b60405180910390f35b6102596102543660046129da565b6105ee565b604051901515815260200161023d565b610271610619565b60405161023d9190612cd8565b61023360085481565b61027161029536600461299e565b6106ab565b6102ad6102a8366004612731565b61073f565b005b6102336102bd36600461299e565b60009081526020819052604090206001015490565b6102e56102e0366004612ada565b610785565b604080516001600160a01b03909316835260208301919091520161023d565b6102ad61031236600461299e565b6107ae565b6102ad6103253660046125b1565b6107e7565b6102ad6103383660046129b7565b61087e565b6102ad61034b3660046129b7565b6108a8565b6102ad61035e366004612a9e565b610926565b6102ad610a63565b61037e6103793660046128b1565b610af7565b60405161023d9190612c97565b61025961039936600461299e565b600090815260056020526040902054151590565b60045460ff16610259565b6102716103c636600461299e565b610c20565b6102337fa5b103c755210dd1215ce1308341380ccede082cd9202427c960290e230cba7881565b6102ad6104003660046126be565b610c7c565b6102ad61041336600461285d565b610cbf565b6102ad610cff565b6102ad61042e36600461256c565b610d91565b6102596104413660046129b7565b610e52565b610271610e7b565b6102ad610e8a565b610233600081565b6102ad61046c3660046127c9565b610f6b565b61023361047f36600461299e565b60009081526005602052604090205490565b6102ad61049f366004612a14565b610f76565b61023360008051602061321183398151915281565b6102ad6104c73660046129b7565b61102d565b6102337f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b610259610501366004612587565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205460ff1690565b6102ad61053d36600461265a565b611052565b6102ad61055036600461282a565b611097565b60006001600160a01b0383166105c65760405162461bcd60e51b815260206004820152602b60248201527f455243313135353a2062616c616e636520717565727920666f7220746865207a60448201526a65726f206164647265737360a81b60648201526084015b60405180910390fd5b5060009081526001602090815260408083206001600160a01b03949094168352929052205490565b60006001600160e01b0319821663152a902d60e11b14806106135750610613826112e2565b92915050565b60606006805461062890613063565b80601f016020809104026020016040519081016040528092919081815260200182805461065490613063565b80156106a15780601f10610676576101008083540402835291602001916106a1565b820191906000526020600020905b81548152906001019060200180831161068457829003601f168201915b5050505050905090565b6060600380546106ba90613063565b80601f01602080910402602001604051908101604052809291908181526020018280546106e690613063565b80156107335780601f1061070857610100808354040283529160200191610733565b820191906000526020600020905b81548152906001019060200180831161071657829003601f168201915b50505050509050919050565b61075760008051602061321183398151915233610e52565b6107735760405162461bcd60e51b81526004016105bd90612e86565b61077f84848484611322565b50505050565b60085430906000906127109061079b9085613001565b6107a59190612fdf565b90509250929050565b6107c660008051602061321183398151915233610e52565b6107e25760405162461bcd60e51b81526004016105bd90612d33565b600855565b6001600160a01b03851633148061080357506108038533610501565b61086a5760405162461bcd60e51b815260206004820152603260248201527f455243313135353a207472616e736665722063616c6c6572206973206e6f74206044820152711bdddb995c881b9bdc88185c1c1c9bdd995960721b60648201526084016105bd565b610877858585858561147d565b5050505050565b60008281526020819052604090206001015461089981611622565b6108a3838361162c565b505050565b6001600160a01b03811633146109185760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084016105bd565b61092282826116b0565b5050565b60045460ff161561096c5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016105bd565b6109967fa5b103c755210dd1215ce1308341380ccede082cd9202427c960290e230cba7833610e52565b6109c75760405162461bcd60e51b8152602060048201526002602482015261291b60f11b60448201526064016105bd565b600082815260056020526040902054610a075760405162461bcd60e51b8152602060048201526002602482015261114d60f21b60448201526064016105bd565b60008281526009602090815260409091208251610a26928401906123cd565b50817f01eb9f446224820ea672f6cae3910a8b4056363f1aa0ac27623d72eeb3d99d0b82604051610a579190612cd8565b60405180910390a25050565b610a8d7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a33610e52565b610aed5760405162461bcd60e51b815260206004820152603b60248201526000805160206131f183398151915260448201527f686176652070617573657220726f6c6520746f20756e7061757365000000000060648201526084016105bd565b610af5611715565b565b60608151835114610b5c5760405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e677468604482015268040dad2e6dac2e8c6d60bb1b60648201526084016105bd565b600083516001600160401b03811115610b7757610b77613111565b604051908082528060200260200182016040528015610ba0578160200160208202803683370190505b50905060005b8451811015610c1857610beb858281518110610bc457610bc46130fb565b6020026020010151858381518110610bde57610bde6130fb565b6020026020010151610555565b828281518110610bfd57610bfd6130fb565b6020908102919091010152610c11816130ca565b9050610ba6565b509392505050565b600081815260056020526040902054606090610c635760405162461bcd60e51b8152602060048201526002602482015261229b60f11b60448201526064016105bd565b600082815260096020526040902080546106ba90613063565b6001600160a01b038316331480610c985750610c988333610501565b610cb45760405162461bcd60e51b81526004016105bd90612db5565b6108a38383836117a8565b610cd760008051602061321183398151915233610e52565b610cf35760405162461bcd60e51b81526004016105bd90612e86565b61077f84848484611947565b610d297f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a33610e52565b610d895760405162461bcd60e51b815260206004820152603960248201526000805160206131f183398151915260448201527f686176652070617573657220726f6c6520746f2070617573650000000000000060648201526084016105bd565b610af5611a29565b610da960008051602061321183398151915233610e52565b610dc55760405162461bcd60e51b81526004016105bd90612d33565b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a082319060240160206040518083038186803b158015610e0757600080fd5b505afa158015610e1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e3f9190612a85565b9050801561092257610922823383611aa4565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b60606007805461062890613063565b610ea260008051602061321183398151915233610e52565b610ebe5760405162461bcd60e51b81526004016105bd90612d33565b604051600090339047908381818185875af1925050503d8060008114610f00576040519150601f19603f3d011682016040523d82523d6000602084013e610f05565b606091505b5050905080610f685760405162461bcd60e51b815260206004820152602960248201527f455243313135355072657365744d696e7465725061757365723a207472616e736044820152683332b91032b93937b960b91b60648201526084016105bd565b50565b610922338383611bb8565b610f8e60008051602061321183398151915233610e52565b610fee5760405162461bcd60e51b815260206004820152603a60248201526000805160206131f183398151915260448201527f68617665206d696e74657220726f6c6520746f2075706461746500000000000060648201526084016105bd565b61092282828080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c9992505050565b60008281526020819052604090206001015461104881611622565b6108a383836116b0565b6001600160a01b03851633148061106e575061106e8533610501565b61108a5760405162461bcd60e51b81526004016105bd90612db5565b6108778585858585611cac565b6001600160a01b0383163314806110b357506110b38333610501565b6110cf5760405162461bcd60e51b81526004016105bd90612db5565b6108a3838383611de8565b6110e886868686868661127a565b6001600160a01b03851661116f5760005b835181101561116d57828181518110611114576111146130fb565b602002602001015160056000868481518110611132576111326130fb565b6020026020010151815260200190815260200160002060008282546111579190612fc7565b909155506111669050816130ca565b90506110f9565b505b6001600160a01b0384166112635760005b835181101561126157600084828151811061119d5761119d6130fb565b6020026020010151905060008483815181106111bb576111bb6130fb565b602002602001015190506000600560008481526020019081526020016000205490508181101561123e5760405162461bcd60e51b815260206004820152602860248201527f455243313135353a206275726e20616d6f756e74206578636565647320746f74604482015267616c537570706c7960c01b60648201526084016105bd565b6000928352600560205260409092209103905561125a816130ca565b9050611180565b505b505050505050565b6001600160a01b03163b151590565b60045460ff16156112635760405162461bcd60e51b815260206004820152602c60248201527f455243313135355061757361626c653a20746f6b656e207472616e736665722060448201526b1dda1a5b19481c185d5cd95960a21b60648201526084016105bd565b60006001600160e01b03198216636cdb3d1360e11b148061131357506001600160e01b031982166303a24d0760e21b145b80610613575061061382611f04565b6001600160a01b0384166113485760405162461bcd60e51b81526004016105bd90612f63565b81518351146113695760405162461bcd60e51b81526004016105bd90612f1b565b3361137981600087878787611f39565b60005b845181101561141557838181518110611397576113976130fb565b6020026020010151600160008784815181106113b5576113b56130fb565b602002602001015181526020019081526020016000206000886001600160a01b03166001600160a01b0316815260200190815260200160002060008282546113fd9190612fc7565b9091555081905061140d816130ca565b91505061137c565b50846001600160a01b031660006001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8787604051611466929190612caa565b60405180910390a461087781600087878787611f47565b815183511461149e5760405162461bcd60e51b81526004016105bd90612f1b565b6001600160a01b0384166114c45760405162461bcd60e51b81526004016105bd90612dfe565b336114d3818787878787611f39565b60005b84518110156115bc5760008582815181106114f3576114f36130fb565b602002602001015190506000858381518110611511576115116130fb565b60209081029190910181015160008481526001835260408082206001600160a01b038e1683529093529190912054909150818110156115625760405162461bcd60e51b81526004016105bd90612ed1565b60008381526001602090815260408083206001600160a01b038e8116855292528083208585039055908b168252812080548492906115a1908490612fc7565b92505081905550505050806115b5906130ca565b90506114d6565b50846001600160a01b0316866001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb878760405161160c929190612caa565b60405180910390a4611263818787878787611f47565b610f6881336120b2565b6116368282610e52565b610922576000828152602081815260408083206001600160a01b03851684529091529020805460ff1916600117905561166c3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6116ba8282610e52565b15610922576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60045460ff1661175e5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016105bd565b6004805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b0383166117ce5760405162461bcd60e51b81526004016105bd90612e43565b80518251146117ef5760405162461bcd60e51b81526004016105bd90612f1b565b600033905061181281856000868660405180602001604052806000815250611f39565b60005b83518110156118da576000848281518110611832576118326130fb565b602002602001015190506000848381518110611850576118506130fb565b60209081029190910181015160008481526001835260408082206001600160a01b038c1683529093529190912054909150818110156118a15760405162461bcd60e51b81526004016105bd90612d71565b60009283526001602090815260408085206001600160a01b038b16865290915290922091039055806118d2816130ca565b915050611815565b5060006001600160a01b0316846001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb868660405161192b929190612caa565b60405180910390a460408051602081019091526000905261077f565b6001600160a01b03841661196d5760405162461bcd60e51b81526004016105bd90612f63565b33600061197985612116565b9050600061198685612116565b905061199783600089858589611f39565b60008681526001602090815260408083206001600160a01b038b168452909152812080548792906119c9908490612fc7565b909155505060408051878152602081018790526001600160a01b03808a1692600092918716917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a461126183600089898989612161565b60045460ff1615611a6f5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016105bd565b6004805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861178b3390565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691611b009190612b63565b6000604051808303816000865af19150503d8060008114611b3d576040519150601f19603f3d011682016040523d82523d6000602084013e611b42565b606091505b5091509150818015611b6c575080511580611b6c575080806020019051810190611b6c9190612981565b6108775760405162461bcd60e51b815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c45440060448201526064016105bd565b816001600160a01b0316836001600160a01b03161415611c2c5760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c20737461747573604482015268103337b91039b2b63360b91b60648201526084016105bd565b6001600160a01b03838116600081815260026020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b80516109229060039060208401906123cd565b6001600160a01b038416611cd25760405162461bcd60e51b81526004016105bd90612dfe565b336000611cde85612116565b90506000611ceb85612116565b9050611cfb838989858589611f39565b60008681526001602090815260408083206001600160a01b038c16845290915290205485811015611d3e5760405162461bcd60e51b81526004016105bd90612ed1565b60008781526001602090815260408083206001600160a01b038d8116855292528083208985039055908a16825281208054889290611d7d908490612fc7565b909155505060408051888152602081018890526001600160a01b03808b16928c821692918816917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a4611ddd848a8a8a8a8a612161565b505050505050505050565b6001600160a01b038316611e0e5760405162461bcd60e51b81526004016105bd90612e43565b336000611e1a84612116565b90506000611e2784612116565b9050611e4783876000858560405180602001604052806000815250611f39565b60008581526001602090815260408083206001600160a01b038a16845290915290205484811015611e8a5760405162461bcd60e51b81526004016105bd90612d71565b60008681526001602090815260408083206001600160a01b038b81168086529184528285208a8703905582518b81529384018a90529092908816917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a4604080516020810190915260009052611261565b60006001600160e01b03198216637965db0b60e01b148061061357506301ffc9a760e01b6001600160e01b0319831614610613565b6112638686868686866110da565b6001600160a01b0384163b156112635760405163bc197c8160e01b81526001600160a01b0385169063bc197c8190611f8b9089908990889088908890600401612bf4565b602060405180830381600087803b158015611fa557600080fd5b505af1925050508015611fd5575060408051601f3d908101601f19168201909252611fd2918101906129f7565b60015b61208257611fe1613127565b806308c379a0141561201b5750611ff6613143565b80612001575061201d565b8060405162461bcd60e51b81526004016105bd9190612cd8565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e20455243313135356044820152732932b1b2b4bb32b91034b6b83632b6b2b73a32b960611b60648201526084016105bd565b6001600160e01b0319811663bc197c8160e01b146112615760405162461bcd60e51b81526004016105bd90612ceb565b6120bc8282610e52565b610922576120d4816001600160a01b0316601461222b565b6120df83602061222b565b6040516020016120f0929190612b7f565b60408051601f198184030181529082905262461bcd60e51b82526105bd91600401612cd8565b60408051600180825281830190925260609160009190602080830190803683370190505090508281600081518110612150576121506130fb565b602090810291909101015292915050565b6001600160a01b0384163b156112635760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e61906121a59089908990889088908890600401612c52565b602060405180830381600087803b1580156121bf57600080fd5b505af19250505080156121ef575060408051601f3d908101601f191682019092526121ec918101906129f7565b60015b6121fb57611fe1613127565b6001600160e01b0319811663f23a6e6160e01b146112615760405162461bcd60e51b81526004016105bd90612ceb565b6060600061223a836002613001565b612245906002612fc7565b6001600160401b0381111561225c5761225c613111565b6040519080825280601f01601f191660200182016040528015612286576020820181803683370190505b509050600360fc1b816000815181106122a1576122a16130fb565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106122d0576122d06130fb565b60200101906001600160f81b031916908160001a90535060006122f4846002613001565b6122ff906001612fc7565b90505b6001811115612377576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110612333576123336130fb565b1a60f81b828281518110612349576123496130fb565b60200101906001600160f81b031916908160001a90535060049490941c936123708161304c565b9050612302565b5083156123c65760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016105bd565b9392505050565b8280546123d990613063565b90600052602060002090601f0160209004810192826123fb5760008555612441565b82601f1061241457805160ff1916838001178555612441565b82800160010185558215612441579182015b82811115612441578251825591602001919060010190612426565b5061244d929150612451565b5090565b5b8082111561244d5760008155600101612452565b80356001600160a01b038116811461247d57600080fd5b919050565b600082601f83011261249357600080fd5b813560206124a082612fa4565b6040516124ad828261309e565b8381528281019150858301600585901b870184018810156124cd57600080fd5b60005b858110156124ec578135845292840192908401906001016124d0565b5090979650505050505050565b600082601f83011261250a57600080fd5b81356001600160401b0381111561252357612523613111565b60405161253a601f8301601f19166020018261309e565b81815284602083860101111561254f57600080fd5b816020850160208301376000918101602001919091529392505050565b60006020828403121561257e57600080fd5b6123c682612466565b6000806040838503121561259a57600080fd5b6125a383612466565b91506107a560208401612466565b600080600080600060a086880312156125c957600080fd5b6125d286612466565b94506125e060208701612466565b935060408601356001600160401b03808211156125fc57600080fd5b61260889838a01612482565b9450606088013591508082111561261e57600080fd5b61262a89838a01612482565b9350608088013591508082111561264057600080fd5b5061264d888289016124f9565b9150509295509295909350565b600080600080600060a0868803121561267257600080fd5b61267b86612466565b945061268960208701612466565b9350604086013592506060860135915060808601356001600160401b038111156126b257600080fd5b61264d888289016124f9565b6000806000606084860312156126d357600080fd5b6126dc84612466565b925060208401356001600160401b03808211156126f857600080fd5b61270487838801612482565b9350604086013591508082111561271a57600080fd5b5061272786828701612482565b9150509250925092565b6000806000806080858703121561274757600080fd5b61275085612466565b935060208501356001600160401b038082111561276c57600080fd5b61277888838901612482565b9450604087013591508082111561278e57600080fd5b61279a88838901612482565b935060608701359150808211156127b057600080fd5b506127bd878288016124f9565b91505092959194509250565b600080604083850312156127dc57600080fd5b6127e583612466565b915060208301356127f5816131cc565b809150509250929050565b6000806040838503121561281357600080fd5b61281c83612466565b946020939093013593505050565b60008060006060848603121561283f57600080fd5b61284884612466565b95602085013595506040909401359392505050565b6000806000806080858703121561287357600080fd5b61287c85612466565b9350602085013592506040850135915060608501356001600160401b038111156128a557600080fd5b6127bd878288016124f9565b600080604083850312156128c457600080fd5b82356001600160401b03808211156128db57600080fd5b818501915085601f8301126128ef57600080fd5b813560206128fc82612fa4565b604051612909828261309e565b8381528281019150858301600585901b870184018b101561292957600080fd5b600096505b848710156129535761293f81612466565b83526001969096019591830191830161292e565b509650508601359250508082111561296a57600080fd5b5061297785828601612482565b9150509250929050565b60006020828403121561299357600080fd5b81516123c6816131cc565b6000602082840312156129b057600080fd5b5035919050565b600080604083850312156129ca57600080fd5b823591506107a560208401612466565b6000602082840312156129ec57600080fd5b81356123c6816131da565b600060208284031215612a0957600080fd5b81516123c6816131da565b60008060208385031215612a2757600080fd5b82356001600160401b0380821115612a3e57600080fd5b818501915085601f830112612a5257600080fd5b813581811115612a6157600080fd5b866020828501011115612a7357600080fd5b60209290920196919550909350505050565b600060208284031215612a9757600080fd5b5051919050565b60008060408385031215612ab157600080fd5b8235915060208301356001600160401b03811115612ace57600080fd5b612977858286016124f9565b60008060408385031215612aed57600080fd5b50508035926020909101359150565b600081518084526020808501945080840160005b83811015612b2c57815187529582019590820190600101612b10565b509495945050505050565b60008151808452612b4f816020860160208601613020565b601f01601f19169290920160200192915050565b60008251612b75818460208701613020565b9190910192915050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351612bb7816017850160208801613020565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351612be8816028840160208801613020565b01602801949350505050565b6001600160a01b0386811682528516602082015260a060408201819052600090612c2090830186612afc565b8281036060840152612c328186612afc565b90508281036080840152612c468185612b37565b98975050505050505050565b6001600160a01b03868116825285166020820152604081018490526060810183905260a060808201819052600090612c8c90830184612b37565b979650505050505050565b6020815260006123c66020830184612afc565b604081526000612cbd6040830185612afc565b8281036020840152612ccf8185612afc565b95945050505050565b6020815260006123c66020830184612b37565b60208082526028908201527f455243313135353a204552433131353552656365697665722072656a656374656040820152676420746f6b656e7360c01b606082015260800190565b60208082526030908201526000805160206131f183398151915260408201526f68617665206d696e74657220726f6c6560801b606082015260800190565b60208082526024908201527f455243313135353a206275726e20616d6f756e7420657863656564732062616c604082015263616e636560e01b606082015260800190565b60208082526029908201527f455243313135353a2063616c6c6572206973206e6f74206f776e6572206e6f7260408201526808185c1c1c9bdd995960ba1b606082015260800190565b60208082526025908201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604082015264647265737360d81b606082015260800190565b60208082526023908201527f455243313135353a206275726e2066726f6d20746865207a65726f206164647260408201526265737360e81b606082015260800190565b60208082526038908201526000805160206131f183398151915260408201527f68617665206d696e74657220726f6c6520746f206d696e740000000000000000606082015260800190565b6020808252602a908201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60408201526939103a3930b739b332b960b11b606082015260800190565b60208082526028908201527f455243313135353a2069647320616e6420616d6f756e7473206c656e677468206040820152670dad2e6dac2e8c6d60c31b606082015260800190565b60208082526021908201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736040820152607360f81b606082015260800190565b60006001600160401b03821115612fbd57612fbd613111565b5060051b60200190565b60008219821115612fda57612fda6130e5565b500190565b600082612ffc57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561301b5761301b6130e5565b500290565b60005b8381101561303b578181015183820152602001613023565b8381111561077f5750506000910152565b60008161305b5761305b6130e5565b506000190190565b600181811c9082168061307757607f821691505b6020821081141561309857634e487b7160e01b600052602260045260246000fd5b50919050565b601f8201601f191681016001600160401b03811182821017156130c3576130c3613111565b6040525050565b60006000198214156130de576130de6130e5565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600060033d11156131405760046000803e5060005160e01c5b90565b600060443d10156131515790565b6040516003193d81016004833e81513d6001600160401b03816024840111818411171561318057505050505090565b82850191508151818111156131985750505050505090565b843d87010160208285010111156131b25750505050505090565b6131c16020828601018761309e565b509095945050505050565b8015158114610f6857600080fd5b6001600160e01b031981168114610f6857600080fdfe455243313135355072657365744d696e7465725061757365723a206d757374209f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6a2646970667358221220a8c9bbcfb8536ce6099f41433f0f109b8b9cf62951d560c7163d5289d945210964736f6c634300080700334d6574614c696e65204d797374657279426f782053656d692d66756e6769626c6520546f6b656e0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002668747470733a2f2f6d657461646174612e6d6574616c696e652e67616d65732f612f7b69647d0000000000000000000000000000000000000000000000000000
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002668747470733a2f2f6d657461646174612e6d6574616c696e652e67616d65732f612f7b69647d0000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : uri (string): https://metadata.metaline.games/a/{id}
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000026
Arg [2] : 68747470733a2f2f6d657461646174612e6d6574616c696e652e67616d65732f
Arg [3] : 612f7b69647d0000000000000000000000000000000000000000000000000000
Deployed ByteCode Sourcemap
220:254:35:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2185:228:3;;;;;;:::i;:::-;;:::i;:::-;;;15474:25:43;;;15462:2;15447:18;2185:228:3;;;;;;;;4909:294:31;;;;;;:::i;:::-;;:::i;:::-;;;15301:14:43;;15294:22;15276:41;;15264:2;15249:18;4909:294:31;15136:187:43;2385:91:31;;;:::i;:::-;;;;;;;:::i;1704:25::-;;;;;;1940:103:3;;;;;;:::i;:::-;;:::i;3722:325:31:-;;;;;;:::i;:::-;;:::i;:::-;;4391:129:0;;;;;;:::i;:::-;4465:7;4491:12;;;;;;;;;;:22;;;;4391:129;5839:257:31;;;;;;:::i;:::-;;:::i;:::-;;;;-1:-1:-1;;;;;14313:32:43;;;14295:51;;14377:2;14362:18;;14355:34;;;;14268:18;5839:257:31;14121:274:43;5595:197:31;;;;;;:::i;:::-;;:::i;4060:430:3:-;;;;;;:::i;:::-;;:::i;4770:145:0:-;;;;;;:::i;:::-;;:::i;5787:214::-;;;;;;:::i;:::-;;:::i;7704:416:31:-;;;;;;:::i;:::-;;:::i;4657:180::-;;;:::i;2570:508:3:-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;901:120:8:-;;;;;;:::i;:::-;958:4;785:16;;;:12;:16;;;;;;-1:-1:-1;;;901:120:8;1098:84:2;1168:7;;;;1098:84;;8322:192:31;;;;;;:::i;:::-;;:::i;6865:58::-;;6901:22;6865:58;;709:342:6;;;;;;:::i;:::-;;:::i;3322:293:31:-;;;;;;:::i;:::-;;:::i;4263:174::-;;;:::i;6133:335::-;;;;;;:::i;:::-;;:::i;2895:145:0:-;;;;;;:::i;:::-;;:::i;2616:95:31:-;;;:::i;6474:318::-;;;:::i;2027:49:0:-;;2072:4;2027:49;;3146:153:3;;;;;;:::i;:::-;;:::i;697:111:8:-;;;;;;:::i;:::-;759:7;785:16;;;:12;:16;;;;;;;697:111;2892:208:31;;;;;;:::i;:::-;;:::i;1428:62::-;;-1:-1:-1;;;;;;;;;;;1428:62:31;;5149:147:0;;;;;;:::i;:::-;;:::i;1497:62:31:-;;1535:24;1497:62;;3366:166:3;;;;;;:::i;:::-;-1:-1:-1;;;;;3488:27:3;;;3465:4;3488:27;;;:18;:27;;;;;;;;:37;;;;;;;;;;;;;;;3366:166;3599:389;;;;;;:::i;:::-;;:::i;393:310:6:-;;;;;;:::i;:::-;;:::i;2185:228:3:-;2271:7;-1:-1:-1;;;;;2298:21:3;;2290:77;;;;-1:-1:-1;;;2290:77:3;;18475:2:43;2290:77:3;;;18457:21:43;18514:2;18494:18;;;18487:30;18553:34;18533:18;;;18526:62;-1:-1:-1;;;18604:18:43;;;18597:41;18655:19;;2290:77:3;;;;;;;;;-1:-1:-1;2384:13:3;;;;:9;:13;;;;;;;;-1:-1:-1;;;;;2384:22:3;;;;;;;;;;;;2185:228::o;4909:294:31:-;5063:4;-1:-1:-1;;;;;;5092:50:31;;-1:-1:-1;;;5092:50:31;;:103;;;5159:36;5183:11;5159:23;:36::i;:::-;5085:110;4909:294;-1:-1:-1;;4909:294:31:o;2385:91::-;2430:13;2463:5;2456:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2385:91;:::o;1940:103:3:-;2000:13;2032:4;2025:11;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1940:103;;;:::o;3722:325:31:-;3897:34;-1:-1:-1;;;;;;;;;;;719:10:23;2895:145:0;:::i;3897:34:31:-;3889:103;;;;-1:-1:-1;;;3889:103:31;;;;;;;:::i;:::-;4005:34;4016:2;4020:3;4025:7;4034:4;4005:10;:34::i;:::-;3722:325;;;;:::o;5839:257::-;6069:10;;6028:4;;5952:16;;6083:5;;6061:18;;:5;:18;:::i;:::-;6060:28;;;;:::i;:::-;6044:44;;5839:257;;;;;:::o;5595:197::-;5664:34;-1:-1:-1;;;;;;;;;;;719:10:23;2895:145:0;:::i;5664:34:31:-;5656:95;;;;-1:-1:-1;;;5656:95:31;;;;;;;:::i;:::-;5762:10;:22;5595:197::o;4060:430:3:-;-1:-1:-1;;;;;4285:20:3;;719:10:23;4285:20:3;;:60;;-1:-1:-1;4309:36:3;4326:4;719:10:23;3366:166:3;:::i;4309:36::-;4264:157;;;;-1:-1:-1;;;4264:157:3;;21606:2:43;4264:157:3;;;21588:21:43;21645:2;21625:18;;;21618:30;21684:34;21664:18;;;21657:62;-1:-1:-1;;;21735:18:43;;;21728:48;21793:19;;4264:157:3;21404:414:43;4264:157:3;4431:52;4454:4;4460:2;4464:3;4469:7;4478:4;4431:22;:52::i;:::-;4060:430;;;;;:::o;4770:145:0:-;4465:7;4491:12;;;;;;;;;;:22;;;2505:16;2516:4;2505:10;:16::i;:::-;4883:25:::1;4894:4;4900:7;4883:10;:25::i;:::-;4770:145:::0;;;:::o;5787:214::-;-1:-1:-1;;;;;5882:23:0;;719:10:23;5882:23:0;5874:83;;;;-1:-1:-1;;;5874:83:0;;27246:2:43;5874:83:0;;;27228:21:43;27285:2;27265:18;;;27258:30;27324:34;27304:18;;;27297:62;-1:-1:-1;;;27375:18:43;;;27368:45;27430:19;;5874:83:0;27044:411:43;5874:83:0;5968:26;5980:4;5986:7;5968:11;:26::i;:::-;5787:214;;:::o;7704:416:31:-;1168:7:2;;;;1411:9;1403:38;;;;-1:-1:-1;;;1403:38:2;;20855:2:43;1403:38:2;;;20837:21:43;20894:2;20874:18;;;20867:30;-1:-1:-1;;;20913:18:43;;;20906:46;20969:18;;1403:38:2;20653:340:43;1403:38:2;7848:32:31::1;6901:22;719:10:23::0;2895:145:0;:::i;7848:32:31:-:1;7826:84;;;::::0;-1:-1:-1;;;7826:84:31;;26105:2:43;7826:84:31::1;::::0;::::1;26087:21:43::0;26144:1;26124:18;;;26117:29;-1:-1:-1;;;26162:18:43;;;26155:32;26204:18;;7826:84:31::1;25903:325:43::0;7826:84:31::1;958:4:8::0;785:16;;;:12;:16;;;;;;7923:62:31::1;;;::::0;-1:-1:-1;;;7923:62:31;;24529:2:43;7923:62:31::1;::::0;::::1;24511:21:43::0;24568:1;24548:18;;;24541:29;-1:-1:-1;;;24586:18:43;;;24579:32;24628:18;;7923:62:31::1;24327:325:43::0;7923:62:31::1;8029:16;::::0;;;:12:::1;:16;::::0;;;;;;;:29;;::::1;::::0;;::::1;::::0;::::1;:::i;:::-;;8097:2;8076:36;8101:10;8076:36;;;;;;:::i;:::-;;;;;;;;7704:416:::0;;:::o;4657:180::-;4710:34;1535:24;719:10:23;2895:145:0;:::i;4710:34:31:-;4702:106;;;;-1:-1:-1;;;4702:106:31;;24101:2:43;4702:106:31;;;24083:21:43;24140:2;24120:18;;;24113:30;-1:-1:-1;;;;;;;;;;;24159:18:43;;;24152:62;24250:29;24230:18;;;24223:57;24297:19;;4702:106:31;23899:423:43;4702:106:31;4819:10;:8;:10::i;:::-;4657:180::o;2570:508:3:-;2721:16;2780:3;:10;2761:8;:15;:29;2753:83;;;;-1:-1:-1;;;2753:83:3;;25695:2:43;2753:83:3;;;25677:21:43;25734:2;25714:18;;;25707:30;25773:34;25753:18;;;25746:62;-1:-1:-1;;;25824:18:43;;;25817:39;25873:19;;2753:83:3;25493:405:43;2753:83:3;2847:30;2894:8;:15;-1:-1:-1;;;;;2880:30:3;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;2880:30:3;;2847:63;;2926:9;2921:120;2945:8;:15;2941:1;:19;2921:120;;;3000:30;3010:8;3019:1;3010:11;;;;;;;;:::i;:::-;;;;;;;3023:3;3027:1;3023:6;;;;;;;;:::i;:::-;;;;;;;3000:9;:30::i;:::-;2981:13;2995:1;2981:16;;;;;;;;:::i;:::-;;;;;;;;;;:49;2962:3;;;:::i;:::-;;;2921:120;;;-1:-1:-1;3058:13:3;2570:508;-1:-1:-1;;;2570:508:3:o;8322:192:31:-;958:4:8;785:16;;;:12;:16;;;;;;8415:12:31;;8445:25;;;;-1:-1:-1;;;8445:25:31;;20525:2:43;8445:25:31;;;20507:21:43;20564:1;20544:18;;;20537:29;-1:-1:-1;;;20582:18:43;;;20575:32;20624:18;;8445:25:31;20323:325:43;8445:25:31;8490:16;;;;:12;:16;;;;;8483:23;;;;;:::i;709:342:6:-;-1:-1:-1;;;;;868:23:6;;719:10:23;868:23:6;;:66;;-1:-1:-1;895:39:6;912:7;719:10:23;3366:166:3;:::i;895:39:6:-;847:154;;;;-1:-1:-1;;;847:154:6;;;;;;;:::i;:::-;1012:32;1023:7;1032:3;1037:6;1012:10;:32::i;3322:293:31:-;3472:34;-1:-1:-1;;;;;;;;;;;719:10:23;2895:145:0;:::i;3472:34:31:-;3464:103;;;;-1:-1:-1;;;3464:103:31;;;;;;;:::i;:::-;3580:27;3586:2;3590;3594:6;3602:4;3580:5;:27::i;4263:174::-;4314:34;1535:24;719:10:23;2895:145:0;:::i;4314:34:31:-;4306:104;;;;-1:-1:-1;;;4306:104:31;;24859:2:43;4306:104:31;;;24841:21:43;24898:2;24878:18;;;24871:30;-1:-1:-1;;;;;;;;;;;24917:18:43;;;24910:62;25008:27;24988:18;;;24981:55;25053:19;;4306:104:31;24657:421:43;4306:104:31;4421:8;:6;:8::i;6133:335::-;6197:34;-1:-1:-1;;;;;;;;;;;719:10:23;2895:145:0;:::i;6197:34:31:-;6189:95;;;;-1:-1:-1;;;6189:95:31;;;;;;;:::i;:::-;6314:38;;-1:-1:-1;;;6314:38:31;;6346:4;6314:38;;;12663:51:43;6297:14:31;;-1:-1:-1;;;;;6314:23:31;;;;;12636:18:43;;6314:38:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;6297:55;-1:-1:-1;6366:10:31;;6363:98;;6393:56;6421:5;719:10:23;6442:6:31;6393:27;:56::i;2895:145:0:-;2981:4;3004:12;;;;;;;;;;;-1:-1:-1;;;;;3004:29:0;;;;;;;;;;;;;;;2895:145::o;2616:95:31:-;2663:13;2696:7;2689:14;;;;;:::i;6474:318::-;6528:34;-1:-1:-1;;;;;;;;;;;719:10:23;2895:145:0;:::i;6528:34:31:-;6520:95;;;;-1:-1:-1;;;6520:95:31;;;;;;;:::i;:::-;6665:50;;6650:9;;719:10:23;;6689:21:31;;6650:9;6665:50;6650:9;6665:50;6689:21;719:10:23;6665:50:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6649:66;;;6734:4;6726:58;;;;-1:-1:-1;;;6726:58:31;;20115:2:43;6726:58:31;;;20097:21:43;20154:2;20134:18;;;20127:30;20193:34;20173:18;;;20166:62;-1:-1:-1;;;20244:18:43;;;20237:39;20293:19;;6726:58:31;19913:405:43;6726:58:31;6509:283;6474:318::o;3146:153:3:-;3240:52;719:10:23;3273:8:3;3283;3240:18;:52::i;2892:208:31:-;2969:34;-1:-1:-1;;;;;;;;;;;719:10:23;2895:145:0;:::i;2969:34:31:-;2961:105;;;;-1:-1:-1;;;2961:105:31;;22025:2:43;2961:105:31;;;22007:21:43;22064:2;22044:18;;;22037:30;-1:-1:-1;;;;;;;;;;;22083:18:43;;;22076:62;22174:28;22154:18;;;22147:56;22220:19;;2961:105:31;21823:422:43;2961:105:31;3077:15;3085:6;;3077:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;3077:7:31;;-1:-1:-1;;;3077:15:31:i;5149:147:0:-;4465:7;4491:12;;;;;;;;;;:22;;;2505:16;2516:4;2505:10;:16::i;:::-;5263:26:::1;5275:4;5281:7;5263:11;:26::i;3599:389:3:-:0;-1:-1:-1;;;;;3799:20:3;;719:10:23;3799:20:3;;:60;;-1:-1:-1;3823:36:3;3840:4;719:10:23;3366:166:3;:::i;3823:36::-;3778:148;;;;-1:-1:-1;;;3778:148:3;;;;;;;:::i;:::-;3936:45;3954:4;3960:2;3964;3968:6;3976:4;3936:17;:45::i;393:310:6:-;-1:-1:-1;;;;;527:23:6;;719:10:23;527:23:6;;:66;;-1:-1:-1;554:39:6;571:7;719:10:23;3366:166:3;:::i;554:39:6:-;506:154;;;;-1:-1:-1;;;506:154:6;;;;;;;:::i;:::-;671:25;677:7;686:2;690:5;671;:25::i;1091:904:8:-;1322:66;1349:8;1359:4;1365:2;1369:3;1374:7;1383:4;1322:26;:66::i;:::-;-1:-1:-1;;;;;1403:18:8;;1399:156;;1442:9;1437:108;1461:3;:10;1457:1;:14;1437:108;;;1520:7;1528:1;1520:10;;;;;;;;:::i;:::-;;;;;;;1496:12;:20;1509:3;1513:1;1509:6;;;;;;;;:::i;:::-;;;;;;;1496:20;;;;;;;;;;;;:34;;;;;;;:::i;:::-;;;;-1:-1:-1;1473:3:8;;-1:-1:-1;1473:3:8;;:::i;:::-;;;1437:108;;;;1399:156;-1:-1:-1;;;;;1569:16:8;;1565:424;;1606:9;1601:378;1625:3;:10;1621:1;:14;1601:378;;;1660:10;1673:3;1677:1;1673:6;;;;;;;;:::i;:::-;;;;;;;1660:19;;1697:14;1714:7;1722:1;1714:10;;;;;;;;:::i;:::-;;;;;;;1697:27;;1742:14;1759:12;:16;1772:2;1759:16;;;;;;;;;;;;1742:33;;1811:6;1801;:16;;1793:69;;;;-1:-1:-1;;;1793:69:8;;23692:2:43;1793:69:8;;;23674:21:43;23731:2;23711:18;;;23704:30;23770:34;23750:18;;;23743:62;-1:-1:-1;;;23821:18:43;;;23814:38;23869:19;;1793:69:8;23490:404:43;1793:69:8;1912:16;;;;:12;:16;;;;;;1931:15;;1912:34;;1637:3;;;:::i;:::-;;;1601:378;;;;1565:424;1091:904;;;;;;:::o;1175:320:22:-;-1:-1:-1;;;;;1465:19:22;;:23;;;1175:320::o;709:381:7:-;1168:7:2;;;;1025:9:7;1017:66;;;;-1:-1:-1;;;1017:66:7;;19292:2:43;1017:66:7;;;19274:21:43;19331:2;19311:18;;;19304:30;19370:34;19350:18;;;19343:62;-1:-1:-1;;;19421:18:43;;;19414:42;19473:19;;1017:66:7;19090:408:43;1236:305:3;1338:4;-1:-1:-1;;;;;;1373:41:3;;-1:-1:-1;;;1373:41:3;;:109;;-1:-1:-1;;;;;;;1430:52:3;;-1:-1:-1;;;1430:52:3;1373:109;:161;;;;1498:36;1522:11;1498:23;:36::i;9684:791::-;-1:-1:-1;;;;;9856:16:3;;9848:62;;;;-1:-1:-1;;;9848:62:3;;;;;;;:::i;:::-;9942:7;:14;9928:3;:10;:28;9920:81;;;;-1:-1:-1;;;9920:81:3;;;;;;;:::i;:::-;719:10:23;10054:66:3;719:10:23;10012:16:3;10097:2;10101:3;10106:7;10115:4;10054:20;:66::i;:::-;10136:9;10131:101;10155:3;:10;10151:1;:14;10131:101;;;10211:7;10219:1;10211:10;;;;;;;;:::i;:::-;;;;;;;10186:9;:17;10196:3;10200:1;10196:6;;;;;;;;:::i;:::-;;;;;;;10186:17;;;;;;;;;;;:21;10204:2;-1:-1:-1;;;;;10186:21:3;-1:-1:-1;;;;;10186:21:3;;;;;;;;;;;;;:35;;;;;;;:::i;:::-;;;;-1:-1:-1;10167:3:3;;-1:-1:-1;10167:3:3;;;:::i;:::-;;;;10131:101;;;;10283:2;-1:-1:-1;;;;;10247:53:3;10279:1;-1:-1:-1;;;;;10247:53:3;10261:8;-1:-1:-1;;;;;10247:53:3;;10287:3;10292:7;10247:53;;;;;;;:::i;:::-;;;;;;;;10387:81;10423:8;10441:1;10445:2;10449:3;10454:7;10463:4;10387:35;:81::i;6233:1115::-;6453:7;:14;6439:3;:10;:28;6431:81;;;;-1:-1:-1;;;6431:81:3;;;;;;;:::i;:::-;-1:-1:-1;;;;;6530:16:3;;6522:66;;;;-1:-1:-1;;;6522:66:3;;;;;;;:::i;:::-;719:10:23;6641:60:3;719:10:23;6672:4:3;6678:2;6682:3;6687:7;6696:4;6641:20;:60::i;:::-;6717:9;6712:411;6736:3;:10;6732:1;:14;6712:411;;;6767:10;6780:3;6784:1;6780:6;;;;;;;;:::i;:::-;;;;;;;6767:19;;6800:14;6817:7;6825:1;6817:10;;;;;;;;:::i;:::-;;;;;;;;;;;;6842:19;6864:13;;;:9;:13;;;;;;-1:-1:-1;;;;;6864:19:3;;;;;;;;;;;;6817:10;;-1:-1:-1;6905:21:3;;;;6897:76;;;;-1:-1:-1;;;6897:76:3;;;;;;;:::i;:::-;7015:13;;;;:9;:13;;;;;;;;-1:-1:-1;;;;;7015:19:3;;;;;;;;;;7037:20;;;7015:42;;7085:17;;;;;;;:27;;7037:20;;7015:13;7085:27;;7037:20;;7085:27;:::i;:::-;;;;;;;;6753:370;;;6748:3;;;;:::i;:::-;;;6712:411;;;;7168:2;-1:-1:-1;;;;;7138:47:3;7162:4;-1:-1:-1;;;;;7138:47:3;7152:8;-1:-1:-1;;;;;7138:47:3;;7172:3;7177:7;7138:47;;;;;;;:::i;:::-;;;;;;;;7266:75;7302:8;7312:4;7318:2;7322:3;7327:7;7336:4;7266:35;:75::i;3334:103:0:-;3400:30;3411:4;719:10:23;3400::0;:30::i;7244:233::-;7327:22;7335:4;7341:7;7327;:22::i;:::-;7322:149;;7365:6;:12;;;;;;;;;;;-1:-1:-1;;;;;7365:29:0;;;;;;;;;:36;;-1:-1:-1;;7365:36:0;7397:4;7365:36;;;7447:12;719:10:23;;640:96;7447:12:0;-1:-1:-1;;;;;7420:40:0;7438:7;-1:-1:-1;;;;;7420:40:0;7432:4;7420:40;;;;;;;;;;7244:233;;:::o;7602:234::-;7685:22;7693:4;7699:7;7685;:22::i;:::-;7681:149;;;7755:5;7723:12;;;;;;;;;;;-1:-1:-1;;;;;7723:29:0;;;;;;;;;;:37;;-1:-1:-1;;7723:37:0;;;7779:40;719:10:23;;7723:12:0;;7779:40;;7755:5;7779:40;7602:234;;:::o;2110:117:2:-;1168:7;;;;1669:41;;;;-1:-1:-1;;;1669:41:2;;18126:2:43;1669:41:2;;;18108:21:43;18165:2;18145:18;;;18138:30;-1:-1:-1;;;18184:18:43;;;18177:50;18244:18;;1669:41:2;17924:344:43;1669:41:2;2168:7:::1;:15:::0;;-1:-1:-1;;2168:15:2::1;::::0;;2198:22:::1;719:10:23::0;2207:12:2::1;2198:22;::::0;-1:-1:-1;;;;;12681:32:43;;;12663:51;;12651:2;12636:18;2198:22:2::1;;;;;;;2110:117::o:0;11695:943:3:-;-1:-1:-1;;;;;11842:18:3;;11834:66;;;;-1:-1:-1;;;11834:66:3;;;;;;;:::i;:::-;11932:7;:14;11918:3;:10;:28;11910:81;;;;-1:-1:-1;;;11910:81:3;;;;;;;:::i;:::-;12002:16;719:10:23;12002:31:3;;12044:66;12065:8;12075:4;12089:1;12093:3;12098:7;12044:66;;;;;;;;;;;;:20;:66::i;:::-;12126:9;12121:364;12145:3;:10;12141:1;:14;12121:364;;;12176:10;12189:3;12193:1;12189:6;;;;;;;;:::i;:::-;;;;;;;12176:19;;12209:14;12226:7;12234:1;12226:10;;;;;;;;:::i;:::-;;;;;;;;;;;;12251:19;12273:13;;;:9;:13;;;;;;-1:-1:-1;;;;;12273:19:3;;;;;;;;;;;;12226:10;;-1:-1:-1;12314:21:3;;;;12306:70;;;;-1:-1:-1;;;12306:70:3;;;;;;;:::i;:::-;12418:13;;;;:9;:13;;;;;;;;-1:-1:-1;;;;;12418:19:3;;;;;;;;;;12440:20;;12418:42;;12157:3;;;;:::i;:::-;;;;12121:364;;;;12538:1;-1:-1:-1;;;;;12500:55:3;12524:4;-1:-1:-1;;;;;12500:55:3;12514:8;-1:-1:-1;;;;;12500:55:3;;12542:3;12547:7;12500:55;;;;;;;:::i;:::-;;;;;;;;12566:65;;;;;;;;;12610:1;12566:65;;;1091:904:8;8630:709:3;-1:-1:-1;;;;;8777:16:3;;8769:62;;;;-1:-1:-1;;;8769:62:3;;;;;;;:::i;:::-;719:10:23;8842:16:3;8906:21;8924:2;8906:17;:21::i;:::-;8883:44;;8937:24;8964:25;8982:6;8964:17;:25::i;:::-;8937:52;;9000:66;9021:8;9039:1;9043:2;9047:3;9052:7;9061:4;9000:20;:66::i;:::-;9077:13;;;;:9;:13;;;;;;;;-1:-1:-1;;;;;9077:17:3;;;;;;;;;:27;;9098:6;;9077:13;:27;;9098:6;;9077:27;:::i;:::-;;;;-1:-1:-1;;9119:52:3;;;27816:25:43;;;27872:2;27857:18;;27850:34;;;-1:-1:-1;;;;;9119:52:3;;;;9152:1;;9119:52;;;;;;27789:18:43;9119:52:3;;;;;;;9258:74;9289:8;9307:1;9311:2;9315;9319:6;9327:4;9258:30;:74::i;1863:115:2:-;1168:7;;;;1411:9;1403:38;;;;-1:-1:-1;;;1403:38:2;;20855:2:43;1403:38:2;;;20837:21:43;20894:2;20874:18;;;20867:30;-1:-1:-1;;;20913:18:43;;;20906:46;20969:18;;1403:38:2;20653:340:43;1403:38:2;1922:7:::1;:14:::0;;-1:-1:-1;;1922:14:2::1;1932:4;1922:14;::::0;;1951:20:::1;1958:12;719:10:23::0;;640:96;489:361:42;684:45;;;-1:-1:-1;;;;;14313:32:43;;;684:45:42;;;14295:51:43;14362:18;;;;14355:34;;;684:45:42;;;;;;;;;;14268:18:43;;;;684:45:42;;;;;;;-1:-1:-1;;;;;684:45:42;-1:-1:-1;;;684:45:42;;;673:57;;-1:-1:-1;;;;673:10:42;;;;:57;;684:45;673:57;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;637:93;;;;749:7;:57;;;;-1:-1:-1;761:11:42;;:16;;:44;;;792:4;781:24;;;;;;;;;;;;:::i;:::-;741:101;;;;-1:-1:-1;;;741:101:42;;17349:2:43;741:101:42;;;17331:21:43;17388:2;17368:18;;;17361:30;17427:33;17407:18;;;17400:61;17478:18;;741:101:42;17147:355:43;12773:323:3;12923:8;-1:-1:-1;;;;;12914:17:3;:5;-1:-1:-1;;;;;12914:17:3;;;12906:71;;;;-1:-1:-1;;;12906:71:3;;25285:2:43;12906:71:3;;;25267:21:43;25324:2;25304:18;;;25297:30;25363:34;25343:18;;;25336:62;-1:-1:-1;;;25414:18:43;;;25407:39;25463:19;;12906:71:3;25083:405:43;12906:71:3;-1:-1:-1;;;;;12987:25:3;;;;;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;:46;;-1:-1:-1;;12987:46:3;;;;;;;;;;13048:41;;15276::43;;;13048::3;;15249:18:43;13048:41:3;;;;;;;12773:323;;;:::o;8171:86::-;8237:13;;;;:4;;:13;;;;;:::i;4940:947::-;-1:-1:-1;;;;;5121:16:3;;5113:66;;;;-1:-1:-1;;;5113:66:3;;;;;;;:::i;:::-;719:10:23;5190:16:3;5254:21;5272:2;5254:17;:21::i;:::-;5231:44;;5285:24;5312:25;5330:6;5312:17;:25::i;:::-;5285:52;;5348:60;5369:8;5379:4;5385:2;5389:3;5394:7;5403:4;5348:20;:60::i;:::-;5419:19;5441:13;;;:9;:13;;;;;;;;-1:-1:-1;;;;;5441:19:3;;;;;;;;;;5478:21;;;;5470:76;;;;-1:-1:-1;;;5470:76:3;;;;;;;:::i;:::-;5580:13;;;;:9;:13;;;;;;;;-1:-1:-1;;;;;5580:19:3;;;;;;;;;;5602:20;;;5580:42;;5642:17;;;;;;;:27;;5602:20;;5580:13;5642:27;;5602:20;;5642:27;:::i;:::-;;;;-1:-1:-1;;5685:46:3;;;27816:25:43;;;27872:2;27857:18;;27850:34;;;-1:-1:-1;;;;;5685:46:3;;;;;;;;;;;;;;27789:18:43;5685:46:3;;;;;;;5812:68;5843:8;5853:4;5859:2;5863;5867:6;5875:4;5812:30;:68::i;:::-;5103:784;;;;4940:947;;;;;:::o;10715:786::-;-1:-1:-1;;;;;10837:18:3;;10829:66;;;;-1:-1:-1;;;10829:66:3;;;;;;;:::i;:::-;719:10:23;10906:16:3;10970:21;10988:2;10970:17;:21::i;:::-;10947:44;;11001:24;11028:25;11046:6;11028:17;:25::i;:::-;11001:52;;11064:66;11085:8;11095:4;11109:1;11113:3;11118:7;11064:66;;;;;;;;;;;;:20;:66::i;:::-;11141:19;11163:13;;;:9;:13;;;;;;;;-1:-1:-1;;;;;11163:19:3;;;;;;;;;;11200:21;;;;11192:70;;;;-1:-1:-1;;;11192:70:3;;;;;;;:::i;:::-;11296:13;;;;:9;:13;;;;;;;;-1:-1:-1;;;;;11296:19:3;;;;;;;;;;;;11318:20;;;11296:42;;11364:54;;27816:25:43;;;27857:18;;;27850:34;;;11296:19:3;;11364:54;;;;;;27789:18:43;11364:54:3;;;;;;;11429:65;;;;;;;;;11473:1;11429:65;;;1091:904:8;2606:202:0;2691:4;-1:-1:-1;;;;;;2714:47:0;;-1:-1:-1;;;2714:47:0;;:87;;-1:-1:-1;;;;;;;;;;937:40:26;;;2765:36:0;829:155:26;5211:354:31;5491:66;5518:8;5528:4;5534:2;5538:3;5543:7;5552:4;5491:26;:66::i;16127:792:3:-;-1:-1:-1;;;;;16359:13:3;;1465:19:22;:23;16355:558:3;;16394:79;;-1:-1:-1;;;16394:79:3;;-1:-1:-1;;;;;16394:43:3;;;;;:79;;16438:8;;16448:4;;16454:3;;16459:7;;16468:4;;16394:79;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;16394:79:3;;;;;;;;-1:-1:-1;;16394:79:3;;;;;;;;;;;;:::i;:::-;;;16390:513;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;16779:6;16772:14;;-1:-1:-1;;;16772:14:3;;;;;;;;:::i;16390:513::-;;;16826:62;;-1:-1:-1;;;16826:62:3;;16158:2:43;16826:62:3;;;16140:21:43;16197:2;16177:18;;;16170:30;16236:34;16216:18;;;16209:62;-1:-1:-1;;;16287:18:43;;;16280:50;16347:19;;16826:62:3;15956:416:43;16390:513:3;-1:-1:-1;;;;;;16552:60:3;;-1:-1:-1;;;16552:60:3;16548:157;;16636:50;;-1:-1:-1;;;16636:50:3;;;;;;;:::i;3718:492:0:-;3806:22;3814:4;3820:7;3806;:22::i;:::-;3801:403;;3989:41;4017:7;-1:-1:-1;;;;;3989:41:0;4027:2;3989:19;:41::i;:::-;4101:38;4129:4;4136:2;4101:19;:38::i;:::-;3896:265;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;3896:265:0;;;;;;;;;;-1:-1:-1;;;3844:349:0;;;;;;;:::i;16925:193:3:-;17044:16;;;17058:1;17044:16;;;;;;;;;16991;;17019:22;;17044:16;;;;;;;;;;;;-1:-1:-1;17044:16:3;17019:41;;17081:7;17070:5;17076:1;17070:8;;;;;;;;:::i;:::-;;;;;;;;;;:18;17106:5;16925:193;-1:-1:-1;;16925:193:3:o;15396:725::-;-1:-1:-1;;;;;15603:13:3;;1465:19:22;:23;15599:516:3;;15638:72;;-1:-1:-1;;;15638:72:3;;-1:-1:-1;;;;;15638:38:3;;;;;:72;;15677:8;;15687:4;;15693:2;;15697:6;;15705:4;;15638:72;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;15638:72:3;;;;;;;;-1:-1:-1;;15638:72:3;;;;;;;;;;;;:::i;:::-;;;15634:471;;;;:::i;:::-;-1:-1:-1;;;;;;15759:55:3;;-1:-1:-1;;;15759:55:3;15755:152;;15838:50;;-1:-1:-1;;;15838:50:3;;;;;;;:::i;1588:441:25:-;1663:13;1688:19;1720:10;1724:6;1720:1;:10;:::i;:::-;:14;;1733:1;1720:14;:::i;:::-;-1:-1:-1;;;;;1710:25:25;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1710:25:25;;1688:47;;-1:-1:-1;;;1745:6:25;1752:1;1745:9;;;;;;;;:::i;:::-;;;;:15;-1:-1:-1;;;;;1745:15:25;;;;;;;;;-1:-1:-1;;;1770:6:25;1777:1;1770:9;;;;;;;;:::i;:::-;;;;:15;-1:-1:-1;;;;;1770:15:25;;;;;;;;-1:-1:-1;1800:9:25;1812:10;1816:6;1812:1;:10;:::i;:::-;:14;;1825:1;1812:14;:::i;:::-;1800:26;;1795:132;1832:1;1828;:5;1795:132;;;-1:-1:-1;;;1879:5:25;1887:3;1879:11;1866:25;;;;;;;:::i;:::-;;;;1854:6;1861:1;1854:9;;;;;;;;:::i;:::-;;;;:37;-1:-1:-1;;;;;1854:37:25;;;;;;;;-1:-1:-1;1915:1:25;1905:11;;;;;1835:3;;;:::i;:::-;;;1795:132;;;-1:-1:-1;1944:10:25;;1936:55;;;;-1:-1:-1;;;1936:55:25;;16579:2:43;1936:55:25;;;16561:21:43;;;16598:18;;;16591:30;16657:34;16637:18;;;16630:62;16709:18;;1936:55:25;16377:356:43;1936:55:25;2015:6;1588:441;-1:-1:-1;;;1588:441:25:o;-1:-1:-1:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;14:173:43;82:20;;-1:-1:-1;;;;;131:31:43;;121:42;;111:70;;177:1;174;167:12;111:70;14:173;;;:::o;192:735::-;246:5;299:3;292:4;284:6;280:17;276:27;266:55;;317:1;314;307:12;266:55;353:6;340:20;379:4;402:43;442:2;402:43;:::i;:::-;474:2;468:9;486:31;514:2;506:6;486:31;:::i;:::-;552:18;;;586:15;;;;-1:-1:-1;621:15:43;;;671:1;667:10;;;655:23;;651:32;;648:41;-1:-1:-1;645:61:43;;;702:1;699;692:12;645:61;724:1;734:163;748:2;745:1;742:9;734:163;;;805:17;;793:30;;843:12;;;;875;;;;766:1;759:9;734:163;;;-1:-1:-1;915:6:43;;192:735;-1:-1:-1;;;;;;;192:735:43:o;932:555::-;974:5;1027:3;1020:4;1012:6;1008:17;1004:27;994:55;;1045:1;1042;1035:12;994:55;1081:6;1068:20;-1:-1:-1;;;;;1103:2:43;1100:26;1097:52;;;1129:18;;:::i;:::-;1178:2;1172:9;1190:67;1245:2;1226:13;;-1:-1:-1;;1222:27:43;1251:4;1218:38;1172:9;1190:67;:::i;:::-;1281:2;1273:6;1266:18;1327:3;1320:4;1315:2;1307:6;1303:15;1299:26;1296:35;1293:55;;;1344:1;1341;1334:12;1293:55;1408:2;1401:4;1393:6;1389:17;1382:4;1374:6;1370:17;1357:54;1455:1;1431:15;;;1448:4;1427:26;1420:37;;;;1435:6;932:555;-1:-1:-1;;;932:555:43:o;1492:186::-;1551:6;1604:2;1592:9;1583:7;1579:23;1575:32;1572:52;;;1620:1;1617;1610:12;1572:52;1643:29;1662:9;1643:29;:::i;1683:260::-;1751:6;1759;1812:2;1800:9;1791:7;1787:23;1783:32;1780:52;;;1828:1;1825;1818:12;1780:52;1851:29;1870:9;1851:29;:::i;:::-;1841:39;;1899:38;1933:2;1922:9;1918:18;1899:38;:::i;1948:943::-;2102:6;2110;2118;2126;2134;2187:3;2175:9;2166:7;2162:23;2158:33;2155:53;;;2204:1;2201;2194:12;2155:53;2227:29;2246:9;2227:29;:::i;:::-;2217:39;;2275:38;2309:2;2298:9;2294:18;2275:38;:::i;:::-;2265:48;;2364:2;2353:9;2349:18;2336:32;-1:-1:-1;;;;;2428:2:43;2420:6;2417:14;2414:34;;;2444:1;2441;2434:12;2414:34;2467:61;2520:7;2511:6;2500:9;2496:22;2467:61;:::i;:::-;2457:71;;2581:2;2570:9;2566:18;2553:32;2537:48;;2610:2;2600:8;2597:16;2594:36;;;2626:1;2623;2616:12;2594:36;2649:63;2704:7;2693:8;2682:9;2678:24;2649:63;:::i;:::-;2639:73;;2765:3;2754:9;2750:19;2737:33;2721:49;;2795:2;2785:8;2782:16;2779:36;;;2811:1;2808;2801:12;2779:36;;2834:51;2877:7;2866:8;2855:9;2851:24;2834:51;:::i;:::-;2824:61;;;1948:943;;;;;;;;:::o;2896:606::-;3000:6;3008;3016;3024;3032;3085:3;3073:9;3064:7;3060:23;3056:33;3053:53;;;3102:1;3099;3092:12;3053:53;3125:29;3144:9;3125:29;:::i;:::-;3115:39;;3173:38;3207:2;3196:9;3192:18;3173:38;:::i;:::-;3163:48;;3258:2;3247:9;3243:18;3230:32;3220:42;;3309:2;3298:9;3294:18;3281:32;3271:42;;3364:3;3353:9;3349:19;3336:33;-1:-1:-1;;;;;3384:6:43;3381:30;3378:50;;;3424:1;3421;3414:12;3378:50;3447:49;3488:7;3479:6;3468:9;3464:22;3447:49;:::i;3507:669::-;3634:6;3642;3650;3703:2;3691:9;3682:7;3678:23;3674:32;3671:52;;;3719:1;3716;3709:12;3671:52;3742:29;3761:9;3742:29;:::i;:::-;3732:39;;3822:2;3811:9;3807:18;3794:32;-1:-1:-1;;;;;3886:2:43;3878:6;3875:14;3872:34;;;3902:1;3899;3892:12;3872:34;3925:61;3978:7;3969:6;3958:9;3954:22;3925:61;:::i;:::-;3915:71;;4039:2;4028:9;4024:18;4011:32;3995:48;;4068:2;4058:8;4055:16;4052:36;;;4084:1;4081;4074:12;4052:36;;4107:63;4162:7;4151:8;4140:9;4136:24;4107:63;:::i;:::-;4097:73;;;3507:669;;;;;:::o;4181:868::-;4326:6;4334;4342;4350;4403:3;4391:9;4382:7;4378:23;4374:33;4371:53;;;4420:1;4417;4410:12;4371:53;4443:29;4462:9;4443:29;:::i;:::-;4433:39;;4523:2;4512:9;4508:18;4495:32;-1:-1:-1;;;;;4587:2:43;4579:6;4576:14;4573:34;;;4603:1;4600;4593:12;4573:34;4626:61;4679:7;4670:6;4659:9;4655:22;4626:61;:::i;:::-;4616:71;;4740:2;4729:9;4725:18;4712:32;4696:48;;4769:2;4759:8;4756:16;4753:36;;;4785:1;4782;4775:12;4753:36;4808:63;4863:7;4852:8;4841:9;4837:24;4808:63;:::i;:::-;4798:73;;4924:2;4913:9;4909:18;4896:32;4880:48;;4953:2;4943:8;4940:16;4937:36;;;4969:1;4966;4959:12;4937:36;;4992:51;5035:7;5024:8;5013:9;5009:24;4992:51;:::i;:::-;4982:61;;;4181:868;;;;;;;:::o;5054:315::-;5119:6;5127;5180:2;5168:9;5159:7;5155:23;5151:32;5148:52;;;5196:1;5193;5186:12;5148:52;5219:29;5238:9;5219:29;:::i;:::-;5209:39;;5298:2;5287:9;5283:18;5270:32;5311:28;5333:5;5311:28;:::i;:::-;5358:5;5348:15;;;5054:315;;;;;:::o;5374:254::-;5442:6;5450;5503:2;5491:9;5482:7;5478:23;5474:32;5471:52;;;5519:1;5516;5509:12;5471:52;5542:29;5561:9;5542:29;:::i;:::-;5532:39;5618:2;5603:18;;;;5590:32;;-1:-1:-1;;;5374:254:43:o;5633:322::-;5710:6;5718;5726;5779:2;5767:9;5758:7;5754:23;5750:32;5747:52;;;5795:1;5792;5785:12;5747:52;5818:29;5837:9;5818:29;:::i;:::-;5808:39;5894:2;5879:18;;5866:32;;-1:-1:-1;5945:2:43;5930:18;;;5917:32;;5633:322;-1:-1:-1;;;5633:322:43:o;5960:531::-;6055:6;6063;6071;6079;6132:3;6120:9;6111:7;6107:23;6103:33;6100:53;;;6149:1;6146;6139:12;6100:53;6172:29;6191:9;6172:29;:::i;:::-;6162:39;;6248:2;6237:9;6233:18;6220:32;6210:42;;6299:2;6288:9;6284:18;6271:32;6261:42;;6354:2;6343:9;6339:18;6326:32;-1:-1:-1;;;;;6373:6:43;6370:30;6367:50;;;6413:1;6410;6403:12;6367:50;6436:49;6477:7;6468:6;6457:9;6453:22;6436:49;:::i;6496:1219::-;6614:6;6622;6675:2;6663:9;6654:7;6650:23;6646:32;6643:52;;;6691:1;6688;6681:12;6643:52;6731:9;6718:23;-1:-1:-1;;;;;6801:2:43;6793:6;6790:14;6787:34;;;6817:1;6814;6807:12;6787:34;6855:6;6844:9;6840:22;6830:32;;6900:7;6893:4;6889:2;6885:13;6881:27;6871:55;;6922:1;6919;6912:12;6871:55;6958:2;6945:16;6980:4;7003:43;7043:2;7003:43;:::i;:::-;7075:2;7069:9;7087:31;7115:2;7107:6;7087:31;:::i;:::-;7153:18;;;7187:15;;;;-1:-1:-1;7222:11:43;;;7264:1;7260:10;;;7252:19;;7248:28;;7245:41;-1:-1:-1;7242:61:43;;;7299:1;7296;7289:12;7242:61;7321:1;7312:10;;7331:169;7345:2;7342:1;7339:9;7331:169;;;7402:23;7421:3;7402:23;:::i;:::-;7390:36;;7363:1;7356:9;;;;;7446:12;;;;7478;;7331:169;;;-1:-1:-1;7519:6:43;-1:-1:-1;;7563:18:43;;7550:32;;-1:-1:-1;;7594:16:43;;;7591:36;;;7623:1;7620;7613:12;7591:36;;7646:63;7701:7;7690:8;7679:9;7675:24;7646:63;:::i;:::-;7636:73;;;6496:1219;;;;;:::o;7720:245::-;7787:6;7840:2;7828:9;7819:7;7815:23;7811:32;7808:52;;;7856:1;7853;7846:12;7808:52;7888:9;7882:16;7907:28;7929:5;7907:28;:::i;7970:180::-;8029:6;8082:2;8070:9;8061:7;8057:23;8053:32;8050:52;;;8098:1;8095;8088:12;8050:52;-1:-1:-1;8121:23:43;;7970:180;-1:-1:-1;7970:180:43:o;8155:254::-;8223:6;8231;8284:2;8272:9;8263:7;8259:23;8255:32;8252:52;;;8300:1;8297;8290:12;8252:52;8336:9;8323:23;8313:33;;8365:38;8399:2;8388:9;8384:18;8365:38;:::i;8414:245::-;8472:6;8525:2;8513:9;8504:7;8500:23;8496:32;8493:52;;;8541:1;8538;8531:12;8493:52;8580:9;8567:23;8599:30;8623:5;8599:30;:::i;8664:249::-;8733:6;8786:2;8774:9;8765:7;8761:23;8757:32;8754:52;;;8802:1;8799;8792:12;8754:52;8834:9;8828:16;8853:30;8877:5;8853:30;:::i;8918:592::-;8989:6;8997;9050:2;9038:9;9029:7;9025:23;9021:32;9018:52;;;9066:1;9063;9056:12;9018:52;9106:9;9093:23;-1:-1:-1;;;;;9176:2:43;9168:6;9165:14;9162:34;;;9192:1;9189;9182:12;9162:34;9230:6;9219:9;9215:22;9205:32;;9275:7;9268:4;9264:2;9260:13;9256:27;9246:55;;9297:1;9294;9287:12;9246:55;9337:2;9324:16;9363:2;9355:6;9352:14;9349:34;;;9379:1;9376;9369:12;9349:34;9424:7;9419:2;9410:6;9406:2;9402:15;9398:24;9395:37;9392:57;;;9445:1;9442;9435:12;9392:57;9476:2;9468:11;;;;;9498:6;;-1:-1:-1;8918:592:43;;-1:-1:-1;;;;8918:592:43:o;9700:184::-;9770:6;9823:2;9811:9;9802:7;9798:23;9794:32;9791:52;;;9839:1;9836;9829:12;9791:52;-1:-1:-1;9862:16:43;;9700:184;-1:-1:-1;9700:184:43:o;9889:388::-;9966:6;9974;10027:2;10015:9;10006:7;10002:23;9998:32;9995:52;;;10043:1;10040;10033:12;9995:52;10079:9;10066:23;10056:33;;10140:2;10129:9;10125:18;10112:32;-1:-1:-1;;;;;10159:6:43;10156:30;10153:50;;;10199:1;10196;10189:12;10153:50;10222:49;10263:7;10254:6;10243:9;10239:22;10222:49;:::i;10282:248::-;10350:6;10358;10411:2;10399:9;10390:7;10386:23;10382:32;10379:52;;;10427:1;10424;10417:12;10379:52;-1:-1:-1;;10450:23:43;;;10520:2;10505:18;;;10492:32;;-1:-1:-1;10282:248:43:o;10535:435::-;10588:3;10626:5;10620:12;10653:6;10648:3;10641:19;10679:4;10708:2;10703:3;10699:12;10692:19;;10745:2;10738:5;10734:14;10766:1;10776:169;10790:6;10787:1;10784:13;10776:169;;;10851:13;;10839:26;;10885:12;;;;10920:15;;;;10812:1;10805:9;10776:169;;;-1:-1:-1;10961:3:43;;10535:435;-1:-1:-1;;;;;10535:435:43:o;10975:257::-;11016:3;11054:5;11048:12;11081:6;11076:3;11069:19;11097:63;11153:6;11146:4;11141:3;11137:14;11130:4;11123:5;11119:16;11097:63;:::i;:::-;11214:2;11193:15;-1:-1:-1;;11189:29:43;11180:39;;;;11221:4;11176:50;;10975:257;-1:-1:-1;;10975:257:43:o;11237:274::-;11366:3;11404:6;11398:13;11420:53;11466:6;11461:3;11454:4;11446:6;11442:17;11420:53;:::i;:::-;11489:16;;;;;11237:274;-1:-1:-1;;11237:274:43:o;11726:786::-;12137:25;12132:3;12125:38;12107:3;12192:6;12186:13;12208:62;12263:6;12258:2;12253:3;12249:12;12242:4;12234:6;12230:17;12208:62;:::i;:::-;-1:-1:-1;;;12329:2:43;12289:16;;;12321:11;;;12314:40;12379:13;;12401:63;12379:13;12450:2;12442:11;;12435:4;12423:17;;12401:63;:::i;:::-;12484:17;12503:2;12480:26;;11726:786;-1:-1:-1;;;;11726:786:43:o;12725:826::-;-1:-1:-1;;;;;13122:15:43;;;13104:34;;13174:15;;13169:2;13154:18;;13147:43;13084:3;13221:2;13206:18;;13199:31;;;13047:4;;13253:57;;13290:19;;13282:6;13253:57;:::i;:::-;13358:9;13350:6;13346:22;13341:2;13330:9;13326:18;13319:50;13392:44;13429:6;13421;13392:44;:::i;:::-;13378:58;;13485:9;13477:6;13473:22;13467:3;13456:9;13452:19;13445:51;13513:32;13538:6;13530;13513:32;:::i;:::-;13505:40;12725:826;-1:-1:-1;;;;;;;;12725:826:43:o;13556:560::-;-1:-1:-1;;;;;13853:15:43;;;13835:34;;13905:15;;13900:2;13885:18;;13878:43;13952:2;13937:18;;13930:34;;;13995:2;13980:18;;13973:34;;;13815:3;14038;14023:19;;14016:32;;;13778:4;;14065:45;;14090:19;;14082:6;14065:45;:::i;:::-;14057:53;13556:560;-1:-1:-1;;;;;;;13556:560:43:o;14400:261::-;14579:2;14568:9;14561:21;14542:4;14599:56;14651:2;14640:9;14636:18;14628:6;14599:56;:::i;14666:465::-;14923:2;14912:9;14905:21;14886:4;14949:56;15001:2;14990:9;14986:18;14978:6;14949:56;:::i;:::-;15053:9;15045:6;15041:22;15036:2;15025:9;15021:18;15014:50;15081:44;15118:6;15110;15081:44;:::i;:::-;15073:52;14666:465;-1:-1:-1;;;;;14666:465:43:o;15510:217::-;15657:2;15646:9;15639:21;15620:4;15677:44;15717:2;15706:9;15702:18;15694:6;15677:44;:::i;16738:404::-;16940:2;16922:21;;;16979:2;16959:18;;;16952:30;17018:34;17013:2;16998:18;;16991:62;-1:-1:-1;;;17084:2:43;17069:18;;17062:38;17132:3;17117:19;;16738:404::o;17507:412::-;17709:2;17691:21;;;17748:2;17728:18;;;17721:30;-1:-1:-1;;;;;;;;;;;17782:2:43;17767:18;;17760:62;-1:-1:-1;;;17853:2:43;17838:18;;17831:46;17909:3;17894:19;;17507:412::o;18685:400::-;18887:2;18869:21;;;18926:2;18906:18;;;18899:30;18965:34;18960:2;18945:18;;18938:62;-1:-1:-1;;;19031:2:43;19016:18;;19009:34;19075:3;19060:19;;18685:400::o;19503:405::-;19705:2;19687:21;;;19744:2;19724:18;;;19717:30;19783:34;19778:2;19763:18;;19756:62;-1:-1:-1;;;19849:2:43;19834:18;;19827:39;19898:3;19883:19;;19503:405::o;20998:401::-;21200:2;21182:21;;;21239:2;21219:18;;;21212:30;21278:34;21273:2;21258:18;;21251:62;-1:-1:-1;;;21344:2:43;21329:18;;21322:35;21389:3;21374:19;;20998:401::o;22250:399::-;22452:2;22434:21;;;22491:2;22471:18;;;22464:30;22530:34;22525:2;22510:18;;22503:62;-1:-1:-1;;;22596:2:43;22581:18;;22574:33;22639:3;22624:19;;22250:399::o;22654:420::-;22856:2;22838:21;;;22895:2;22875:18;;;22868:30;-1:-1:-1;;;;;;;;;;;22929:2:43;22914:18;;22907:62;23005:26;23000:2;22985:18;;22978:54;23064:3;23049:19;;22654:420::o;23079:406::-;23281:2;23263:21;;;23320:2;23300:18;;;23293:30;23359:34;23354:2;23339:18;;23332:62;-1:-1:-1;;;23425:2:43;23410:18;;23403:40;23475:3;23460:19;;23079:406::o;26233:404::-;26435:2;26417:21;;;26474:2;26454:18;;;26447:30;26513:34;26508:2;26493:18;;26486:62;-1:-1:-1;;;26579:2:43;26564:18;;26557:38;26627:3;26612:19;;26233:404::o;26642:397::-;26844:2;26826:21;;;26883:2;26863:18;;;26856:30;26922:34;26917:2;26902:18;;26895:62;-1:-1:-1;;;26988:2:43;26973:18;;26966:31;27029:3;27014:19;;26642:397::o;27895:183::-;27955:4;-1:-1:-1;;;;;27980:6:43;27977:30;27974:56;;;28010:18;;:::i;:::-;-1:-1:-1;28055:1:43;28051:14;28067:4;28047:25;;27895:183::o;28083:128::-;28123:3;28154:1;28150:6;28147:1;28144:13;28141:39;;;28160:18;;:::i;:::-;-1:-1:-1;28196:9:43;;28083:128::o;28216:217::-;28256:1;28282;28272:132;;28326:10;28321:3;28317:20;28314:1;28307:31;28361:4;28358:1;28351:15;28389:4;28386:1;28379:15;28272:132;-1:-1:-1;28418:9:43;;28216:217::o;28438:168::-;28478:7;28544:1;28540;28536:6;28532:14;28529:1;28526:21;28521:1;28514:9;28507:17;28503:45;28500:71;;;28551:18;;:::i;:::-;-1:-1:-1;28591:9:43;;28438:168::o;28611:258::-;28683:1;28693:113;28707:6;28704:1;28701:13;28693:113;;;28783:11;;;28777:18;28764:11;;;28757:39;28729:2;28722:10;28693:113;;;28824:6;28821:1;28818:13;28815:48;;;-1:-1:-1;;28859:1:43;28841:16;;28834:27;28611:258::o;28874:136::-;28913:3;28941:5;28931:39;;28950:18;;:::i;:::-;-1:-1:-1;;;28986:18:43;;28874:136::o;29015:380::-;29094:1;29090:12;;;;29137;;;29158:61;;29212:4;29204:6;29200:17;29190:27;;29158:61;29265:2;29257:6;29254:14;29234:18;29231:38;29228:161;;;29311:10;29306:3;29302:20;29299:1;29292:31;29346:4;29343:1;29336:15;29374:4;29371:1;29364:15;29228:161;;29015:380;;;:::o;29400:249::-;29510:2;29491:13;;-1:-1:-1;;29487:27:43;29475:40;;-1:-1:-1;;;;;29530:34:43;;29566:22;;;29527:62;29524:88;;;29592:18;;:::i;:::-;29628:2;29621:22;-1:-1:-1;;29400:249:43:o;29654:135::-;29693:3;-1:-1:-1;;29714:17:43;;29711:43;;;29734:18;;:::i;:::-;-1:-1:-1;29781:1:43;29770:13;;29654:135::o;29794:127::-;29855:10;29850:3;29846:20;29843:1;29836:31;29886:4;29883:1;29876:15;29910:4;29907:1;29900:15;29926:127;29987:10;29982:3;29978:20;29975:1;29968:31;30018:4;30015:1;30008:15;30042:4;30039:1;30032:15;30058:127;30119:10;30114:3;30110:20;30107:1;30100:31;30150:4;30147:1;30140:15;30174:4;30171:1;30164:15;30190:179;30225:3;30267:1;30249:16;30246:23;30243:120;;;30313:1;30310;30307;30292:23;-1:-1:-1;30350:1:43;30344:8;30339:3;30335:18;30243:120;30190:179;:::o;30374:671::-;30413:3;30455:4;30437:16;30434:26;30431:39;;;30374:671;:::o;30431:39::-;30497:2;30491:9;-1:-1:-1;;30562:16:43;30558:25;;30555:1;30491:9;30534:50;30613:4;30607:11;30637:16;-1:-1:-1;;;;;30743:2:43;30736:4;30728:6;30724:17;30721:25;30716:2;30708:6;30705:14;30702:45;30699:58;;;30750:5;;;;;30374:671;:::o;30699:58::-;30787:6;30781:4;30777:17;30766:28;;30823:3;30817:10;30850:2;30842:6;30839:14;30836:27;;;30856:5;;;;;;30374:671;:::o;30836:27::-;30940:2;30921:16;30915:4;30911:27;30907:36;30900:4;30891:6;30886:3;30882:16;30878:27;30875:69;30872:82;;;30947:5;;;;;;30374:671;:::o;30872:82::-;30963:57;31014:4;31005:6;30997;30993:19;30989:30;30983:4;30963:57;:::i;:::-;-1:-1:-1;31036:3:43;;30374:671;-1:-1:-1;;;;;30374:671:43:o;31050:118::-;31136:5;31129:13;31122:21;31115:5;31112:32;31102:60;;31158:1;31155;31148:12;31173:131;-1:-1:-1;;;;;;31247:32:43;;31237:43;;31227:71;;31294:1;31291;31284:12
Metadata Hash
ipfs://a8c9bbcfb8536ce6099f41433f0f109b8b9cf62951d560c7163d5289d9452109