[Ethereum] the best way to handle multiple NFTs of the same collection in ERC1155

erc-1155erc-20erc-721nfttokens

I'm learning ERC1155, and I'm a bit confused.

This is OpenZeppelin's example of an ERC1155 Contract:

Open Zeppelin ERC1155 Example

They state that Thor's Hammer is an NFT (because only 1 was minted), while Gold is Fungible.

Therefore this example contains several Fungible Tokens:

  • Gold
  • Silver
  • Sword
  • Shield

And only one Non-Fungible Token:

  • Thor's Hammer

But what if I want my ERC1155 contract to have multiple Collections of Non-Fungible Tokens?

For example, say I want to create a Football Game with:

  • 2 types of Fungible Tokens:
    • Gold
    • Silver
  • 4 Collections of NFTs:
    • Players
    • Coaches
    • Jerseys
    • Stadiums

Example code:

//SPDX-License-Identifier: UNLICENSED
pragma solidity 0.7.0;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/solc-0.7/contracts/token/ERC1155/ERC1155.sol";

contract FootballGame is ERC1155 {
    
    address public admin;
    
    // Non-Fungibles
    uint8 public constant PLAYER = 1;
    uint8 public constant COACH = 2;
    uint8 public constant JERSEY = 3;
    uint8 public constant STADIUM = 4;
    
    // Fungibles
    uint8 public constant GOLD = 5;
    uint8 public constant SILVER = 6;
    
    constructor() ERC1155("https://example.json") {
        admin = msg.sender;
    }
    
    modifier onlyAdmin() {
        require(msg.sender == admin, "This operation is only for Admins");
        _;
    }
    
    function mintCoins(uint _coinId, uint _amount) onlyAdmin external {
        require(_coinId == GOLD || _coinId == SILVER, "Invalid Coin ID");
        _mint(msg.sender, _coinId, _amount, "");
    }
    
    function mintNFT(uint _tokenId) onlyAdmin external {
        require(_tokenId == PLAYER || _tokenId == COACH || _tokenId == JERSEY || _tokenId == STADIUM, "Invalid Token ID");
        _mint(msg.sender, _tokenId, 1, "");
    }
}

Is this right?

The constant variables are supposed to be IDs that represent each type of token, right? Or wrong?

For instance, if I want to create multiple Stadiums can I just mint multiple NFTs with the ID of the Stadium collection?

Or do I have to mint Stadium A with ID 22, Stadium B with ID 23, Stadium C with ID 24, and so on?

For NFTs in ERC1155, is an ID for each NFT? Or is it for each Collection of NFTs?

Best Answer

The short answer is that it looks like the latter, unique id for each NFT, regardless of grouping (eg stadium). But to have NFT-like grouping there are a couple of considerations:

The nft example implementation uses an IS_NFT bit for id's with single supplies. Notice that mint uses a packId. Perhaps this can be done more simply for your use case, or you can just use the example code.

And, from the spec's metadata section...

This JSON schema is loosely based on the "ERC721 Metadata JSON Schema", but includes optional formatting to allow for ID substitution by clients. If the string {id} exists in any JSON value, it MUST be replaced with the actual token ID, by all client software that follows this standard.

Which presumably is a cosmetic different to not have large, unwieldy id's.