ERC1155 uri function doesn't use the tokenID?

Hi @Dukr,

Welcome to the community :wave:.

I assume @dievardump cloned the ERC1155 implementation from OpenZeppelin Contracts and modified to their needs.

You can add to the discussion on making view functions virtual with your use case: https://github.com/OpenZeppelin/openzeppelin-contracts/issues/2154

1 Like

Hi @abcoathup,

Thank you for kind and fast response.

I already saw the issue open which would make view functions such as uri virtual so that we could modify for our use case. However, I wanted to ask if you know when (an estimation of time) this will get implemented and would be possible to use? So that we don’t copy the whole ERC1155 locally?

Thank you in advance.

1 Like

As @abcoathup said, I duplicated ERC1155 (and 721 too because I needed to update ApprovedForAll).

You can just start with a local copy, it’s absolutely not a big deal. It’s not as if you update your contracts all the time once they are deployed :slight_smile:

2 Likes

Great, thank you for you feedback. :slight_smile:

1 Like

Hi @Dukr,

This is planned to be looked at for the next release of OpenZeppelin Contracts.

In the mean time, you could clone the current implementation and add the URI functionality that you need. You will need to appropriately test and audit this.

I have seen this interesting thread regarding this function that does not replace the id parameter in the uri of the token.

I have a question.

The vast majority of developers substitute the id parameter of the uri in the front of the DApp, right?

like this:

uri.replace('id', '0000000000000000000000000000000000000000000000000000000000000004');

Or in any case, what is the most functional methodology for this substitution?

1 Like

Wondering the same. Can someone share how they modify the uri function to match the exact path of the metadata json file (including the 0 padding). Thanks in Advance!

The implementation of the URI interface that I have seen most made and that I share with you is the following:

function uri(uint256 _tokenId) override public view returns (string memory) {


        if(bytes(_URIS[_tokenId]).length != 0) {

         return string(_URIS[_tokenId]);

     }

        return string(

            abi.encodePacked(

            "https://baseURI/",

            Strings.toString(_tokenId),

            ".json"

           )

        );

      }

As a contract 1155 actually what it does is create serialized tokens with a balance, so for me strictly speaking they are not NFTs, we must create a mapping to be able to create unique NFTs.

mapping(uint => string) private _URIS;
So we create a token id with a unique balance and we already have an NFT
uint256 public constant NFT = 1;
The uri function will first check if there is a specific uri for that token, and if not, it will concatenate the id to receive the metada associated with the semi-fungible token, as shown above.

Thanks for sharing this. I've heard a lazier approach. Restrict who can mint, and simply don't mint more than 1. Ie. check is not mandatory but good to have.

Regarding the URI, I'm confused which of the following are compliant with ERC1155 standards if id=250.
ipfs://uri/250.json
ipfs://uri/fa.json
ipfs://uri/00000000000000000000000000000000000000000000000000000000000000fa.json

The EIP says:

  • The string format of the substituted hexadecimal ID MUST be lowercase alphanumeric: [0-9a-f] with no 0x prefix.
  • The string format of the substituted hexadecimal ID MUST be leading zero padded to 64 hex characters length if necessary.

So given a URI like ipfs://uri/{id}.json for token with id 250, a compliant client would have to use the last one you shared:

  • ipfs://uri/00000000000000000000000000000000000000000000000000000000000000fa.json
1 Like

Appreciate if anyone can share their implementation of the format frangio is advising on to output uri!

Here's an implementation in JavaScript:

const makeUri = (uri, id) => uri.replace('{id}', id.toString(16).padStart(64, '0'));
> makeUri('ipfs://uri/{id}.json', 250)
'ipfs://uri/00000000000000000000000000000000000000000000000000000000000000fa.json'
2 Likes

We know the reasons for doing this like this? I see that in some projects this rule is skipped. Why not leave the ids as in ERC721 contracts?

It allows for simpler Solidity code because more work is done by the client. But both things are supported by the EIP.

The "MUST" word It does not seem like a suggestion but a demand.
Is the 64 zeros to look like a hexadecimal account?

i tried what frangio said but never got it working. i'm totally new to solidity/javascript, but im pretty sure what he said is right.

starting to go off topic now, but when i tried i didnt know how to use "padStart" function. im compiling with remix solidity and that gave me an error. maybe missing some imports. i also tried importing the toString but that didnt fix it. hope you had better luck :slight_smile:

@NothingBurger26, It did not work for you because what you have shared @frangio is javascript code for your front.
It is not solidity code.

Think of your smart contract as the back of a web application. The data returned by the uri function must be manipulated so that they generate the recommended uri in the EIP

What you have to do is create the front of a dapp to receive the response from the uri function connecting to the blockchain through one of the most used javascript libraries: Ethers.js or Web3.js

You can also use either of the two most popular development environments:

Truffle - Web3 - React
Hardhat - Ethers - React

I personally recommend hardhat because it has a smoother learning curve and I find it much easier for the neophyte.

1 Like

Sharing a solution to getting URI function to output tokenURI with the padding and in hex without further modification on the front end! Let me know if you guys like it :slight_smile:

   bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";

  function toHexString(uint256 value, uint256 length) public pure returns (string memory) {
        bytes memory buffer = new bytes(length+2);
        for (uint256 i = length + 1; i > 1; --i) {
            buffer[i] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }

    function uri(uint256 _tokenID) override public view returns (string memory) {
       return string(abi.encodePacked(baseURI,toHexString(_tokenID,64),".json"));
    }

Cool. It looks like you used our toHexString implementation. :wink:

Looks exactly the same. I found it from an Ape project on Polygon. They probably found it from you lol. :smiling_face_with_three_hearts: