Hi! I am writing a smart contract that inherits from ERC721PresetMinterPauserAutoId.sol
.
I want to emit my own MintEvent so it's easy to discern in a web3 client after a new token has been minted. The problem with using the Transfer
event is that it doesn't only get emitted after a mint.
The problem I have is when I create my own mint function, and call the parent mint function in ERC721PresetMinterPauserAutoId.sol, I do not get the current tokenId as a return value. The preset uses this mint implementation:
function mint(address to) public virtual {
require(hasRole(MINTER_ROLE, _msgSender()), "ERC721PresetMinterPauserAutoId: must have minter role to mint");
// We cannot just use balanceOf to create the new tokenId because tokens
// can be burned (destroyed), so we need a separate counter.
_mint(to, _tokenIdTracker.current());
_tokenIdTracker.increment();
}
Unfortunately _tokenIdTracker
is private, so I cannot access it.
What's the best way for me to get the newly minted tokenId in my caller, which looks like this:
function myMint() public {
mint(msg.sender); // call inherited mint function, no tokenId in ret value
emit MyMintEvent(/* I need a tokenId to pass here */)
}
I could keep my own count, but that's a problem for two reasons:
- Managing the same state in two different locations in storage. Problematic.
- Double the gas costs when writing to storage. Problematic.
Is there a proper way to access the latest tokenId after mint within my contract?
**** NOTE *****
After further digging, this is the cleanest solution I can come up with. I overrode the _beforeTokenTransfer
hook. Is there a better way of approaching this or is this fine? The reason I ask is because this hook is triggered before balances are updated.
function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual override {
if (from == address(0)) {
emit MyMintEvent(tokenId, to);
}
super._beforeTokenTransfer(from, to, tokenId); // Call parent hook
}