Passing URI for ERC721 token at mint

In order to have the tokenURI be an IPFS link, I am sending the URI as a parameter when minting. The issue is that users could potentially exploit this and send in their own URI parameter.

How does one get around this? Or is it common practice to do so in this manner regardless of?

2 Likes

Maybe you should add a permission for this function.

1 Like

can you expand on that?

1 Like

Hi @sovin,

Have a look at AccessControl: https://docs.openzeppelin.com/contracts/4.x/access-control

You can also experiment with AccessControl using the Contracts Wizard: https://zpl.in/wizard

Wouldn’t access control require me to know who will mint? In my case, I want to allow the public (anyone) to be able to mint a token.

1 Like

If you want to allow the public (anyone) to be able to mint a token, so there is no need to add permission.

1 Like

that’s my point. if anyone can mint, how can I prevent passing any URI to set as the tokenURI?

1 Like

Sorry, I am not sure what do you mean. You want to allow the public (anyone) to be able to mint a token, so you can not set any limitation, but at the same time, you also want to prevent passing any URI, so you have got to set some limitation.
Maybe it should be:

function mint() public {}              // no permission
function setURI() public onlyOwner {}  // has permission
1 Like

You URI will be set on contract deployement as the baseURI. After that, each NFT minted will have an ID. So if anyone create an NFT. They will add MetaData to it without changing the base URI.

Example:

A baseURI https://nft.madeindreams.org (this would be my base uri)

Every NFT created will have an ID and they will fetch your baseURI with the NFT ID like that.

https://nft.madeindreams.org/1

So this will display the metaData for that NFT.

So you don’t let the user set a base URI. You record the MetaData they provided with the NFT to your DB or what ever process you use to store the Data.

So the base URI remain the same but each id point to a record somewhere in a DB.

1 Like

Thanks for the reply. I understand that is how most projects handle public NFT mints. But then that makes it so that the NFT is forever dependent on the developer’s server. How can we do a public mint and also use IPFS?

1 Like

Wrote an article about it.

1 Like

Thx for replying. The article doesn’t talk about how to run a public mint using IPFS in a way that doesn’t allow others to exploit setting the tokenURI to w/e they want.

1 Like

The URI of an IPFS is the content. The URI could potentially be a risk centralized or not. You would still need to perform minimal security check, they would also depend of what your data is?
We don’t just rely on the file extension a user provider to validate it. The user is not setting the baseURI. This should be done on contract deployment by the owner. The user insert Meta Data Centralized/Decentralized. But they should not set the base URI or the Data. Once the user submit his NFT for a mint. This is where you send it on IPFS or a DataBase. Your Dapp would then served that data by pulling the contract up and fetching IPFS or a DB. You could come up with other process but they remain basically the same. The user provide MetaData for the NFT, not the base URI. In both cases they will provide path to content of what ever they like.

So if you don’t want user to specify what ever they like you would have to filter it and code your own sets of rules. Plus this kind of security check can hardly be done in the contract. So it would be more towards the UI that is loading your NFT in the end that would need to perform security check.

1 Like

That’s my current approach. I call my own servers via the UI for the IPFS link and then set it at mint which is exploitable but I don’t see any other way to do so. Just wanted to confirm that there was indeed no other way. Thanks for replying.

1 Like

Hey,

I'm having the exact same issue. I need to make sure that when people mint something as part of a collection that they are essentially minting 'approved' content and not anything they like as the token_uri.

Did you find a good solution for this?

I too am interested in the solution to your problem and @highrankin. I like the above suggestion of having a public mint function and an access controlled setURI function. I would be happy to help try to solve this with you.

I see your problem. There are multiple problems here.
Even I was sending URIs in the mint function for one of the contracts I wrote, but realised this can cause issues. Usually contracts do not pass uri as parameter and they just assign the .json as the URI inside the contract function and the base URI is same for all.
But there is a problem in above approach too. Anyone can predict a URI for metadata json before minting it. They can view the traits and accordingly do minting. So problem actually is, how to avoid predicting of metadata json prior to minting.

Hi @sovin, may I know how you achieve the function add uri at mint ?

function batch_mint(address to, uint256 amount, string memory token_IPFS_CIDs) public virtual {
        uint256 coming_token_id = totalSupply();
        require(amount > 0);
        for (uint256 i = 0; i < amount; i++) {
            _safeMint(to, coming_token_id + i);
            setTokenURI(
                coming_token_id + i,
                string(abi.encodePacked("https://ipfs.io/ipfs/", token_IPFS_CIDs))
            );
        }
    }

I am trying to do this way but always encounter "stack limit reached" error