Elimination of redundant of ipfsHash[tokenId] mappings in ERC721

Here is a way to create an ipfsHash[tokenId] associative mapping, taken from this contract:

       //mint a nifty
       uint specificTokenId = _numNiftyMinted[niftyType].current();
       uint tokenId = bm.encodeTokenId(contractId, niftyType, specificTokenId);
       string memory tokenIdStr = bm.uint2str(tokenId);
       string memory tokenURI = bm.strConcat(baseURI, tokenIdStr);
       string memory ipfsHash = _niftyIPFSHashes[niftyType];
       //mint token
       _mint(collector_address, tokenId);
       _setTokenURI(tokenId, tokenURI);
       _setTokenIPFSHash(tokenId, ipfsHash);

the tokenId is created like so:

    function encodeTokenId(uint contractIdCalc, uint niftyType, uint specificNiftyNum) public view returns (uint) {
        return ((contractIdCalc * topLevelMultiplier) + (niftyType * midLevelMultiplier) + specificNiftyNum);

This creates some redundancy for tokens that are 1/n, part of a single edition, as seen here.

We end up with the following structure:

6200050050 -> QmdKektfKmAEw7f692D7G5yQbacQomeaRmgMDnpqG9bcJv 
6200050049 -> QmdKektfKmAEw7f692D7G5yQbacQomeaRmgMDnpqG9bcJv 
6200050001 -> QmdKektfKmAEw7f692D7G5yQbacQomeaRmgMDnpqG9bcJv

Would it be more efficient to create the mapping for a single edition without reference to the specificNiftyNum, so instead of fifty mappings of particular tokenId and a single ipfs hash we would have the lone:

62000500 -> QmdKektfKmAEw7f692D7G5yQbacQomeaRmgMDnpqG9bcJv

Perhaps by creating another function like this:

function createGeneralizedIpfsHashId(uint contractIdCalc, uint niftyType, uint specificNiftyNum) public view returns (uint) {
    return ((contractIdCalc * topLevelMultiplier) + (niftyType * midLevelMultiplier));

Does this make sense as a design decision? Would it be more efficient in terms of gas usage?

1 Like

Hi @bahlsenwitz,

The cheapest minting would be using centralized metadata (which could include an IPFS hash). You can create an encoding scheme (such as using the tokenID) to determine which collection you are using and store an IPFS hash per collection. Though I recommend trying it out on a testnet to see whether this makes a significant enough difference to be worth the complexity.

If you go down this path, I recommend documenting in the code and sharing with your community how this works.

Alternatively you could look at using ERC1155, which is a multi token standard. So if each item in a collection is fungible, and you don’t need the level of ecosystem support you get with ERC721, this may be suitable.