4

I'm looking to build an ERC1155 smart contract (I'm using OpenZeppelin) that will contain NFTs whose metadata will be hosted on IPFS. About 4,000 images for now, all unique (all amount of 1). An important requirement is the ability to add new NFTs regularly.

My issue is that if the IPFS uri is being set in the constructor, I would need to update the uri every time I add files to that IPFS folder, which I don't want to do.

I've been looking for the best way to tackle this so here are the options I see so far:

  1. host all the files (metadata files + NFTs) in the cloud somewhere (but that's centralised and quite a weak solution)
    constructor() public ERC1155("https://game.example/api/item/{id}.json") {
  2. host all the NFT files on IPFS but the metadata files in the cloud (still too centralised)
    constructor() public ERC1155("https://game.example/api/item/{id}.json") {
    but the metadata would look like
{
    "description": "Friendly OpenSea Creature that enjoys long swims in the ocean.", 
    "external_url": "https://openseacreatures.io/3", 
    "image": "ipfs://bafybeic6o5aktpj53nhe3qninp2z7yl2aohxbrqiunc7kvmu57ulsoxjsj/dave.jpeg", 
    "name": "Dave Starbelly",
    "attributes": [ ... ], 
}
  1. Put all the metadata files in the same IPFS folder and update the uri using setUri every time I mint new items (not too sure people will be too happy if the URL to the metadata changes all the time). This seems to be the classic solution if the items set is fixed.
    constructor() public ERC1155("ipfs:/bafybeic6o5aktpj53nhe3qninp2z7yl2aohxbrqiunc7kvmu57ulsoxjsj/items/{id}.json") {

  2. Use IPNS (also quite centralised)

  3. Use the solution described here: https://soenkeba.medium.com/truly-decentralized-nfts-by-erc-1155-b9be28db2aae where basically the NFTs and metadata files are pushed to IPFS, not necessarily in the same folder, and their CID is used to generate unique identifiers.
    So for each CID, a unique token id is "calculated" and when the uri() function is called, the token id is used to recalculate the CID and given to the client. Quite a cool solution and the only one that works, although it still feels a bit hacky.
    constructor() public ERC1155("ipfs://f0{id}") {

I'm not convinced by any of these solutions, does anyone have any other ideas on how achieve what I want?

1 Answer 1

3

Actually, since the openzeppelin URI function is virtual, you can override it to change the URI each time you mint tokens. See https://medium.com/coinsbench/fully-decentralized-erc-721-and-erc-1155-nfts-6c229adf9c9b

contract MyNFT_ERC1155 is ERC1155 {
    mapping (uint256 => string) private _tokenURIs;

    constructor() ERC1155("Anything_you_want") {} 

    function uri(uint256 tokenId) override public view 
    returns (string memory) { 
        return(_tokenURIs[tokenId]); 
    } 
    function _setTokenUri(uint256 tokenId, string memory tokenURI)
    private {
         _tokenURIs[tokenId] = tokenURI; 
    } 
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.