How to add public setURI on ERC1155?

Hi! I would like to have setURI public on my ERC1155, I’m using ERC1155PresetMinterPauserUpgradeable.

I added the following function, but not sure if something is missing, and what to do with the emit requiring an additional parameter for the ID.

     function setURI(string memory newuri) public {
         require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), "SoapPunkCollectibles: must have admin role to change uri");

         emit URI(newuri, 0);

         _setURI(newuri);
     }

Doing something like this, adding the ID parameter to setURI just for the emit would be fine?

     function setURI(string memory newuri, uint256 id) public {
         require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), "SoapPunkCollectibles: must have admin role to change uri");

         emit URI(newuri, id);

         _setURI(newuri);
     }

Thank you!

1 Like

Hi @Eibriel,

Welcome to the community :wave:

The OpenZeppelin Contracts ERC1155 implementation uses a single URI for the entire contract. See the following example: Create an ERC1155.

According to the EIP (see: https://eips.ethereum.org/EIPS/eip-1155#metadata):

  • Changes to the URI MUST emit the URI event if the change can be expressed with an event (i.e. it isn’t dynamic/programmatic).
  • An implementation MAY emit the URI event during a mint operation but it is NOT mandatory. An observer MAY fetch the metadata uri at mint time from the uri function if it was not emitted.
  • The uri function SHOULD be used to retrieve values if no event was emitted.
  • The uri function MUST return the same value as the latest event for an _id if it was emitted.

I interpret this as changing the uri for the contract would require emitting the event for each token ID. Though I recommend reading the EIP on this detail.

event URI(string _value, uint256 indexed _id);

Do you want to use a different uri per token ID?
Under what circumstances would you want to change the uri?

Thank you for the response. Then the second version, the one that requires a call to setURI for each ID seems appropriate for my project (maybe I could add an extra function allowing to set the uri for an array of IDs, emitting several events in one call).

I’m building a small game that will have an organic growth, instead of having a predefined clear roadmap.
Server migrations and web domain changes are a possibility in the future and I would like to avoid having to upgrade the contract.

1 Like

Hi @Eibriel,

My thoughts would be to keep it simple. Use a domain name that is future proof and update the DNS if you need to change servers/hosts/implementation.

That way you don’t need to change the URI and emit events when you do so.

1 Like

What would you suggest when using IPFS? If I have a directory that contains all token metadata and a new token id is added later on, the hash of the directory would change. I could publish an IPNS entry and set it as the URI once, but the IPNS entry is created using a centralized private key. You could also use a mutable file storage with IPFS, but I feel like this is even more centralized.

1 Like

Yep, I want to ask Can I set a URL for a specific ID?
For example , this? make sense?

     function setURI(string memory newuri, uint256 id) public {
         require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), "SoapPunkCollectibles: must have admin role to change uri");

         emit URI(newuri, id);

         _setURI(newuri,id);
     }

The ERC1155 standard is designed with only one URI for all token ids.
See the "metadata" section of reference document

So,,, there is no way to set single ID for now , right?