--- eip: 1155 title: Crypto Item Standard author: Witek Radomski , Andrew Cooke type: Standards Track category: ERC status: Draft created: 2018-06-17 discussions-to: https://github.com/ethereum/EIPs/issues/1155 --- ## Simple Summary A standard interface for multiple item/token definitions in a single deployed contract. ## Abstract This standard proposes a new monolithic token contract that can mint any quantity of Fungible and Non-Fungible tokens in the same contract. We call these "Items" as they differ from the existing standards by being full definitions and configurations of multiple tokens inside a single contract. Standards like ERC-20 require deployment of separate contracts per token. The ERC-721 standard's Token ID is a single non-fungible index and the group of these non-fungibles is deployed as a single contract with settings for the entire collection. Instead, the Crypto Item Standard allows for each Item ID to represent a new configurable token type, which may have its own totalSupply value and other such attributes. The `_itemId` parameter is named as such and placed at the beginning of each function. ## Motivation Tokens standards like ERC-20 and ERC-721 require a separate contract to be deployed for each fungible or NFT token/collection. This places a lot of redundant bytecode on the Ethereum blockchain and limits certain functionality by the nature of separating each token contract into its own permissioned address. With the rise of crypto games and platforms like [Enjin Coin](https://enjincoin.io/), game developers may be creating tens of thousands of items, and a new type of token standard is needed to support this. New functionality is possible with this design, such as transferring or approving multiple token types at once, saving on transaction costs. Trading (escrow / atomic swaps) of multiple tokens can be built on top of this standard and it removes the need to "approve" individual tokens separately. It is also easy to describe and mix multiple fungible or non-fungible tokens in a single contract. ## Specification ``` solidity interface ICryptoItems { // Events event Transfer(uint256 indexed _itemId, address indexed _from, address indexed _to, uint256 _value); event Approval(uint256 indexed _itemId, address indexed _owner, address indexed _spender, uint256 _value); // Required Functions function transfer(uint256[] _itemId, address[] _to, uint256[] _value) external returns (bool success); function transferFrom(uint256[] _itemId, address[] _from, address[] _to, uint256[] _value) external returns (bool success); function approve(uint256[] _itemId, address[] _spender, uint256[] _value) external returns (bool success); function increaseApproval(uint256[] _itemId, address[] _spender, uint256[] _addedValue) external returns (bool success); function decreaseApproval(uint256[] _itemId, address[] _spender, uint256[] _subtractedValue) external returns (bool success); // Required View Functions function totalSupply(uint256 _itemId) external view returns (uint256); function balanceOf(uint256 _itemId, address _owner) external view returns (uint256); function allowance(uint256 _itemId, address _owner, address _spender) external view returns (uint256); // Optional View Functions function name(uint256 _itemId) external view returns (string); function symbol(uint256 _itemId) external view returns (string); function decimals(uint256 _itemId) external view returns (uint8); // Optional Functions for Non-Fungible Items function ownerOf(uint256 _itemId) external view returns (address); function itemURI(uint256 _itemId) external view returns (string); function itemByIndex(uint256 _itemId, uint256 _index) external view returns (uint256); function itemOfOwnerByIndex(uint256 _itemId, address _owner, uint256 _index) external view returns (uint256); } ``` ### transfer Transfers quantities of each `_itemId[]` to the addresses specified. Each parameter array should be the same length, with each index correlating. MUST trigger `Transfer` event. ### transferFrom Transfers quantities of each `_itemId[]` from one or more `_from[]` addresses to the `_to[]` addresses specified. Each parameter array should be the same length, with each index correlating. MUST trigger `Transfer` event. ### approve Approves an account for the ability to transfer a maximum quantity of multiple `_itemId[]` on behalf of another account (using transferFrom). Each parameter array should be the same length, with each index correlating. MUST trigger `Approval` event. ### increaseApproval Increases the allowance amount of one or more items without requiring a reset to 0. Each parameter array should be the same length, with each index correlating. MUST trigger `Approval` event. ### decreaseApproval Decreases the allowance amount of one or more items without requiring a reset to 0. Each parameter array should be the same length, with each index correlating. MUST trigger `Approval` event. ### name Returns the Item ID's name. This function is OPTIONAL but highly recommended. ### symbol Returns the Item ID's symbol. This function is OPTIONAL. ### decimals Returns the Item ID's decimals. This function is OPTIONAL but highly recommended. ### totalSupply Returns the Item ID's totalSupply. ### balanceOf Returns an account's balance of specified Item ID. ### allowance Returns the allowance set by any of the approve functions. ### ownerOf For NFTs, this returns the owner of a specific `_itemId`. This function is OPTIONAL. ### itemURI Returns a distinct Uniform Resource Identifier (URI) for a given `_itemId`. This function is OPTIONAL. ### itemByIndex Enumerate valid NFTs. This function is OPTIONAL. ### itemOfOwnerByIndex Enumerate NFTs assigned to an owner. This function is OPTIONAL. ## Non-Fungible Items An example strategy to mix Fungible and Non-Fungible Items together in the same contract would be to pass the base item ID in the top 128 bits of the uint256 `_itemID` parameter and then use the bottom 128 bits for any extra data you wish to pass to the contract. Non-Fungible Items can be interacted with using an index based accessor into the contract/item data set. Therefore to access a particular item set within a mixed data contract and particular NFT within that set, `_itemID` could be passed as ``. Inside the contract code the two pieces of data needed to access the individual NFT can be extracted with uint128(~0) and the same mask shifted by 128. ### Example of split ID bits ``` uint256 baseToken = 12345 << 128; uint128 index = 50; balanceOf(baseToken, msg.sender); // Get balance of the base token balanceOf(baseToken + index, msg.sender); // Get balance of the Non-Fungible token index ``` ## Implementation - [Enjin Coin](https://enjincoin.io) ([github](https://github.com/enjin)) ## Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).