ERC721PresetMinterPauserAutoId mint() function and tokenId

I’m inheriting ERC721PresetMinterPauserAutoId, and using mint(to) function inside my contract.
I would like to know how to get the autogenerated tokenId?

:computer: Environment

OpenZeppelin v3.0.1
Truffle v5.1.24
Ganache-cli v6.9.1
:memo:Details

I’m tring to get tokenId, after calling mint(to), I’ve tried using totalSupply() but is returning the number of tokenIds, and tokenOfOwnerByIndex() need the index to return the tokenId but I don’t know what to put as index??? 0? how to keep track of that?
:1234: Code to reproduce

pragma solidity 0.6.6;

import “@openzeppelin/contracts/presets/ERC721PresetMinterPauserAutoId.sol”;

contract MyContract is ERC721PresetMinterPauserAutoId {
constructor() 
ERC721PresetMinterPauserAutoId("Token", "TKN", "https://example.com/token/")
public {}
  
modifier onlyMinter() {
      require(hasRole(MINTER_ROLE, msg.sender), "Caller is not a minter");
      _;
 }

function myFunction(address to) public onlyMinter returns (uint256 _tokenId) {

mint(to);
//_tokenId = totalSupply(); ??? return lenght of tokenIds 
// _tokenId = tokenOfOwnerByIndex(to, index) ??? index value???
}
1 Like

Hi @naszam,

We can extend ERC721PresetMinterPauserAutoId as follows:

MyNFT.sol

pragma solidity ^0.6.0;

import "@openzeppelin/contracts/presets/ERC721PresetMinterPauserAutoId.sol";


contract MyNFT is ERC721PresetMinterPauserAutoId {
    constructor()
        public
        ERC721PresetMinterPauserAutoId(
            "My NFT",
            "NFT",
            "https://example.com/token/"
        )
    {}
}

Deploy

Using OpenZeppelin CLI (can use other tools such as Truffle)

$ npx oz deploy
✓ Compiled contracts with solc 0.6.6 (commit.6c089d02)
? Choose the kind of deployment regular
? Pick a network development
? Pick a contract to deploy MyNFT
✓ Deployed instance of MyNFT
0xe78A0F7E598Cc8b0Bb87894B0F60dD2a88d6a8Ab

Mint

Call the mint function with the address to mint a token to.
An automatic token id will be used, starting at zero.

$ npx oz send-tx
? Pick a network development
? Pick an instance MyNFT at 0xe78A0F7E598Cc8b0Bb87894B0F60dD2a88d6a8Ab
? Select which function mint(to: address)
? to: address: 0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0
✓ Transaction successful. Transaction hash: 0x40f3bf5d44b482d2f89ca8ab5adcf451f0511c156db894081a20915659b48563
Events emitted:
 - Transfer(0x0000000000000000000000000000000000000000, 0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0, 0)

Token URI

We can get the tokenURI by providing the tokenID

$ npx oz call
? Pick a network development
? Pick an instance MyNFT at 0xe78A0F7E598Cc8b0Bb87894B0F60dD2a88d6a8Ab
? Select which function tokenURI(tokenId: uint256)
? tokenId: uint256: 0
✓ Method 'tokenURI(uint256)' returned: https://example.com/token/0
https://example.com/token/0
1 Like

Thanks!
I’ve asked because I was testing on Truffle.
Anyway, now I’ve opted for the basic ERC721.sol with an autogenerated tokenId to keep track of.
Also, what about ERC721Holder.sol? Benefits? Applications? (Should I open a new topic?)
Thanks!

1 Like

Hi @naszam,

What weren’t you able to do with extending ERC721PresetMinterPauserAutoId that meant you needed to inherit from ERC721 instead?

I have created a new topic for: What are the benefits of ERC721Holder.sol? as I think it is best for the future community when looking for an answer to have a question per topic.

1 Like

I had to use the basic ERC721.sol cause in my case I needed to extend its behaviour so don’t need the preset, the mint() function I’m implementing is different, with tokenURI, the tokenId is hard to keep track of for the design of my contact, and also the access management is different. I would say that the preset is great as a standalone but to be extended not so sure.
Thanks!

1 Like

Hi @naszam,

Feel free to share your requirements, as it would be good to know what the community needs above and beyond ERC721PresetMinterPauserAutoId.

For the two NFTs I have created previously the ERC721PresetMinterPauserAutoId would have suited me perfectly. The only thing I may have extended, is access control to change the baseURI.

1 Like

I would say a mint() function with tokenURI (_setTokenURI()).
Having a way to change baseURI once deployed would be great!

1 Like

I’d like to add that not declaring only emitting the generated tokenId as an event makes extending the mint function very difficult, and, in my case, implementing a separate Counter is necessary to get around this limitation, and completely ignoring the provided mint function.

Were _mint (as opposed to mint) to return uint256 (the generated tokenId), extended logic could be performed post-minting.

I’m leaving this so others may learn from my stupidiy, but mint will never be extendable since it’s not declared as a virtual function in the base ERC721 Contract. Rolling your own is the only way (I guess).

To add to this, given that mint is not specified in the ERC721 standard, it’d be nice if we could override it!

I created a PR for this: https://github.com/OpenZeppelin/openzeppelin-contracts-ethereum-package/pull/90 :sweat_smile:

Update: PR closed and moved to: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2257

2 Likes