This is my NFT contract
My question is about burn function, I am calling _burn function which is actually defined in ERC721 and transferring the token to address(0).
Now, I tried to decipher the linearization and hooks but still couldnt understand how the _beforeTokenTransfer in ERC721Enumerable is being called when i calling burn function of this contract.
Any relevant articles explaining this will also do.
contract FansNFT is
Context,
AccessControlEnumerable,
ERC2981,
ERC721Enumerable,
ERC721Pausable,
ERC721URIStorage
{
using Counters for Counters.Counter;
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
// Counters.Counter private _tokenIdTracker;
string private _baseTokenURI;
uint96 public royaltyValue = 500; //Makes it at 3% as feeDenominator in ERC2981 defaults
//to 10000 so fees are expressed in basis points,
/**
* @dev Grants `DEFAULT_ADMIN_ROLE`, `MINTER_ROLE` and `PAUSER_ROLE` to the
* account that deploys the contract.
*
* Token URIs will be autogenerated based on `baseURI` and their token IDs.
* See {ERC721-tokenURI}.
*/
constructor() ERC721("ama.fans", "AMAF") {
_setupRole(DEFAULT_ADMIN_ROLE, _msgSender());
super._setRoleAdmin(MINTER_ROLE, DEFAULT_ADMIN_ROLE);
super._setRoleAdmin(PAUSER_ROLE, DEFAULT_ADMIN_ROLE);
_setupRole(MINTER_ROLE, _msgSender());
_setupRole(PAUSER_ROLE, _msgSender());
}
function _baseURI() internal view override returns (string memory) {
return _baseTokenURI;
}
function setRoyaltyValue(uint96 _royaltyValue)
external
onlyRole(DEFAULT_ADMIN_ROLE){
royaltyValue = _royaltyValue;
}
/**
* @dev Creates a new token for `to`. Its token ID will be automatically
* assigned (and available on the emitted {IERC721-Transfer} event), and the token
* URI autogenerated based on the base URI passed at construction.
*
* See {ERC721-_mint}.
*
* Requirements:
*
* - the caller must have the `MINTER_ROLE`.
*/
function mint(address to, string memory _tokenURI)
public
whenNotPaused()
returns(uint256) {
require(hasRole(MINTER_ROLE, _msgSender()), "ERC721PresetMinterPauserAutoId: must have minter role to mint");
// _tokenIdTracker.increment();
// uint256 newNftTokenId = _tokenIdTracker.current();
// We cannot just use balanceOf to create the new tokenId because tokens
// can be burned (destroyed), so we need a separate counter.
_safeMint(to, totalSupply());
_setTokenURI(totalSupply(), _tokenURI);
_setTokenRoyalty(totalSupply(), to, royaltyValue);
return totalSupply();
}
/**
* @dev Pauses all token transfers.
*
* See {ERC721Pausable} and {Pausable-_pause}.
*
* Requirements:
*
* - the caller must have the `PAUSER_ROLE`.
*/
function pause() public virtual {
require(hasRole(PAUSER_ROLE, _msgSender()), "ERC721PresetMinterPauserAutoId: must have pauser role to pause");
_pause();
}
/**
* @dev Unpauses all token transfers.
*
* See {ERC721Pausable} and {Pausable-_unpause}.
*
* Requirements:
*
* - the caller must have the `PAUSER_ROLE`.
*/
function unpause() public virtual {
require(hasRole(PAUSER_ROLE, _msgSender()), "ERC721PresetMinterPauserAutoId: must have pauser role to unpause");
_unpause();
}
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal override(ERC721, ERC721Enumerable, ERC721Pausable) {
super._beforeTokenTransfer(from, to, tokenId);
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId)
public
view
override(AccessControlEnumerable, ERC2981, ERC721, ERC721Enumerable)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
function _burn(uint256 tokenId) internal pure override(ERC721, ERC721URIStorage) {
super._burn(tokenId);
super._resetTokenRoyalty(tokenId);
}
function tokenURI(uint256 tokenId) public view override(ERC721, ERC721URIStorage) returns (string memory) {
return super.tokenURI(tokenId);
}
}