// File: node_modules\@openzeppelin\contracts\utils\introspection\IERC165.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
// File: @openzeppelin\contracts\token\ERC1155\IERC1155.sol
// SPDX_License_Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Required interface of an ERC1155 compliant contract, as defined in the
* https://eips.ethereum.org/EIPS/eip-1155[EIP].
*
* _Available since v3.1._
*/
interface IERC1155 is IERC165 {
/**
* @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.
*/
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
/**
* @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
* transfers.
*/
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] values
);
/**
* @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
* `approved`.
*/
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
/**
* @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
*
* If an {URI} event was emitted for `id`, the standard
* https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
* returned by {IERC1155MetadataURI-uri}.
*/
event URI(string value, uint256 indexed id);
/**
* @dev Returns the amount of tokens of token type `id` owned by `account`.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function balanceOf(address account, uint256 id) external view returns (uint256);
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
*
* Requirements:
*
* - `accounts` and `ids` must have the same length.
*/
function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)
external
view
returns (uint256[] memory);
/**
* @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
*
* Emits an {ApprovalForAll} event.
*
* Requirements:
*
* - `operator` cannot be the caller.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
*
* See {setApprovalForAll}.
*/
function isApprovedForAll(address account, address operator) external view returns (bool);
/**
* @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.
* - `from` must have a balance of tokens of type `id` of at least `amount`.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
* acceptance magic value.
*/
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes calldata data
) external;
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
*
* Emits a {TransferBatch} event.
*
* Requirements:
*
* - `ids` and `amounts` must have the same length.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
* acceptance magic value.
*/
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata amounts,
bytes calldata data
) external;
}
// File: contracts\model\IERC1155Views.sol
// SPDX_License_Identifier: MIT
pragma solidity >=0.7.0;
/**
* @title IERC1155Views - An optional utility interface to improve the ERC-1155 Standard.
* @dev This interface introduces some additional capabilities for ERC-1155 Tokens.
*/
interface IERC1155Views {
/**
* @dev Returns the total supply of the given token id
* @param itemId the id of the token whose availability you want to know
*/
function totalSupply(uint256 itemId) external view returns (uint256);
/**
* @dev Returns the name of the given token id
* @param itemId the id of the token whose name you want to know
*/
function name(uint256 itemId) external view returns (string memory);
/**
* @dev Returns the symbol of the given token id
* @param itemId the id of the token whose symbol you want to know
*/
function symbol(uint256 itemId) external view returns (string memory);
/**
* @dev Returns the decimals of the given token id
* @param itemId the id of the token whose decimals you want to know
*/
function decimals(uint256 itemId) external view returns (uint256);
/**
* @dev Returns the uri of the given token id
* @param itemId the id of the token whose uri you want to know
*/
function uri(uint256 itemId) external view returns (string memory);
}
// File: contracts\model\Item.sol
//SPDX_License_Identifier: MIT
pragma solidity >=0.7.0;
pragma abicoder v2;
struct Header {
address host;
string name;
string symbol;
string uri;
}
struct CreateItem {
Header header;
bytes32 collectionId;
uint256 id;
address[] accounts;
uint256[] amounts;
}
interface Item is IERC1155, IERC1155Views {
event CollectionItem(bytes32 indexed fromCollectionId, bytes32 indexed toCollectionId, uint256 indexed itemId);
function name() external view returns(string memory);
function symbol() external view returns(string memory);
function decimals() external view returns(uint256);
function burn(address account, uint256 itemId, uint256 amount) external;
function burnBatch(address account, uint256[] calldata itemIds, uint256[] calldata amounts) external;
function burn(address account, uint256 itemId, uint256 amount, bytes calldata data) external;
function burnBatch(address account, uint256[] calldata itemIds, uint256[] calldata amounts, bytes calldata data) external;
function mintItems(CreateItem[] calldata items) external returns(uint256[] memory itemIds);
function setItemsCollection(uint256[] calldata itemIds, bytes32[] calldata collectionIds) external returns(bytes32[] memory oldCollectionIds);
function setItemsMetadata(uint256[] calldata itemIds, Header[] calldata newValues) external returns(Header[] memory oldValues);
function interoperableOf(uint256 itemId) external view returns(address);
}
// File: contracts\model\IItemMainInterface.sol
//SPDX_License_Identifier: MIT
pragma solidity >=0.7.0;
struct ItemData {
bytes32 collectionId;
Header header;
bytes32 domainSeparator;
uint256 totalSupply;
mapping(address => uint256) balanceOf;
mapping(address => mapping(address => uint256)) allowance;
mapping(address => uint256) nonces;
}
interface IItemMainInterface is Item {
event Collection(address indexed from, address indexed to, bytes32 indexed collectionId);
function interoperableInterfaceModel() external view returns(address);
function uri() external view returns(string memory);
function plainUri() external view returns(string memory);
function dynamicUriResolver() external view returns(address);
function hostInitializer() external view returns(address);
function collection(bytes32 collectionId) external view returns(address host, string memory name, string memory symbol, string memory uri);
function collectionUri(bytes32 collectionId) external view returns(string memory);
function createCollection(Header calldata _collection, CreateItem[] calldata items) external returns(bytes32 collectionId, uint256[] memory itemIds);
function setCollectionsMetadata(bytes32[] calldata collectionIds, Header[] calldata values) external returns(Header[] memory oldValues);
function setApprovalForAllByCollectionHost(bytes32 collectionId, address account, address operator, bool approved) external;
function item(uint256 itemId) external view returns(bytes32 collectionId, Header memory header, bytes32 domainSeparator, uint256 totalSupply);
function mintTransferOrBurn(bool isMulti, bytes calldata data) external;
function allowance(address account, address spender, uint256 itemId) external view returns(uint256);
function approve(address account, address spender, uint256 amount, uint256 itemId) external;
function TYPEHASH_PERMIT() external view returns (bytes32);
function EIP712_PERMIT_DOMAINSEPARATOR_NAME_AND_VERSION() external view returns(string memory domainSeparatorName, string memory domainSeparatorVersion);
function permit(uint256 itemId, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;
function nonces(address owner, uint256 itemId) external view returns(uint256);
}
// File: @openzeppelin\contracts\token\ERC20\IERC20.sol
// SPDX_License_Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}
// File: @openzeppelin\contracts\token\ERC20\extensions\IERC20Metadata.sol
// SPDX_License_Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}
// File: @openzeppelin\contracts\token\ERC20\extensions\draft-IERC20Permit.sol
// SPDX_License_Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
// File: contracts\model\IItemInteroperableInterface.sol
//SPDX_License_Identifier: MIT
pragma solidity >=0.7.0;
interface IItemInteroperableInterface is IERC20, IERC20Metadata, IERC20Permit {
function init() external;
function mainInterface() external view returns(address);
function itemId() external view returns(uint256);
function emitEvent(bool forApprove, bool isMulti, bytes calldata data) external;
function burn(uint256 amount) external;
function burnFrom(address account, uint256 amount) external;
function EIP712_PERMIT_DOMAINSEPARATOR_NAME_AND_VERSION() external view returns(string memory name, string memory version);
}
// File: contracts\impl\ItemInteroperableInterface.sol
//SPDX_License_Identifier: MIT
pragma solidity >=0.7.0;
contract ItemInteroperableInterface is IItemInteroperableInterface {
address public override mainInterface;
function init() override external {
require(mainInterface == address(0));
mainInterface = msg.sender;
}
function DOMAIN_SEPARATOR() external override view returns (bytes32 domainSeparatorValue) {
(,,domainSeparatorValue,) = IItemMainInterface(mainInterface).item(itemId());
}
function EIP712_PERMIT_DOMAINSEPARATOR_NAME_AND_VERSION() external override view returns(string memory, string memory) {
return IItemMainInterface(mainInterface).EIP712_PERMIT_DOMAINSEPARATOR_NAME_AND_VERSION();
}
function itemId() override public view returns(uint256) {
return uint160(address(this));
}
function emitEvent(bool forApprove, bool isMulti, bytes calldata data) override external {
require(msg.sender == mainInterface, "Unauthorized");
if(isMulti) {
(address[] memory froms, address[] memory tos, uint256[] memory amounts) = abi.decode(data, (address[], address[], uint256[]));
for(uint256 i = 0; i < froms.length; i++) {
if(forApprove) {
emit Approval(froms[i], tos[i], amounts[i]);
} else {
emit Transfer(froms[i], tos[i], amounts[i]);
}
}
return;
}
(address from, address to, uint256 amount) = abi.decode(data, (address, address, uint256));
if(forApprove) {
emit Approval(from, to, amount);
} else {
emit Transfer(from, to, amount);
}
}
function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) override external {
IItemMainInterface(mainInterface).permit(itemId(), owner, spender, value, deadline, v, r, s);
emit Approval(owner, spender, value);
}
function burn(uint256 amount) override external {
IItemMainInterface(mainInterface).mintTransferOrBurn(false, abi.encode(msg.sender, msg.sender, address(0), itemId(), amount));
emit Transfer(msg.sender, address(0), amount);
}
function burnFrom(address account, uint256 amount) external override {
require(account != address(0), "burn zero address");
IItemMainInterface(mainInterface).mintTransferOrBurn(false, abi.encode(msg.sender, account, address(0), itemId(), amount));
emit Transfer(msg.sender, address(0), amount);
}
function name() override external view returns (string memory) {
(, Header memory header,,) = IItemMainInterface(mainInterface).item(itemId());
return header.name;
}
function symbol() override external view returns (string memory) {
(, Header memory header,,) = IItemMainInterface(mainInterface).item(itemId());
return header.symbol;
}
function decimals() override external pure returns (uint8) {
return 18;
}
function nonces(address owner) external override view returns(uint256) {
return IItemMainInterface(mainInterface).nonces(owner, itemId());
}
function totalSupply() override external view returns (uint256 totalSupplyValue) {
(,,, totalSupplyValue) = IItemMainInterface(mainInterface).item(itemId());
}
function balanceOf(address account) override external view returns (uint256) {
return IItemMainInterface(mainInterface).balanceOf(account, itemId());
}
function allowance(address owner, address spender) override external view returns (uint256) {
return IItemMainInterface(mainInterface).allowance(owner, spender, itemId());
}
function approve(address spender, uint256 amount) override external returns(bool) {
IItemMainInterface(mainInterface).approve(msg.sender, spender, amount, itemId());
emit Approval(msg.sender, spender, amount);
return true;
}
function transfer(address recipient, uint256 amount) override external returns(bool) {
return _transferFrom(msg.sender, recipient, amount);
}
function transferFrom(address sender, address recipient, uint256 amount) override external returns(bool) {
return _transferFrom(sender, recipient, amount);
}
function _transferFrom(address sender, address recipient, uint256 amount) private returns(bool) {
require(sender != address(0), "transfer from the zero address");
require(recipient != address(0), "transfer to the zero address");
IItemMainInterface(mainInterface).mintTransferOrBurn(false, abi.encode(msg.sender, sender, recipient, itemId(), amount));
emit Transfer(sender, recipient, amount);
return true;
}
}
{
"compilationTarget": {
"ItemInteroperableInterface.sol": "ItemInteroperableInterface"
},
"evmVersion": "berlin",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"domainSeparatorValue","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EIP712_PERMIT_DOMAINSEPARATOR_NAME_AND_VERSION","outputs":[{"internalType":"string","name":"","type":"string"},{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bool","name":"forApprove","type":"bool"},{"internalType":"bool","name":"isMulti","type":"bool"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"emitEvent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"itemId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mainInterface","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"totalSupplyValue","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]