ERC721PresetMinterPauserAutoId - remove ERC721Burnable

@abcoathup I have a contract based on ERC721PresetMinterPauserAutoId.

I removed ERC721Burnable from the import and contract definition.

Now for function _beforeTokenTransfer I get the error message

Compiling 18 files with 0.6.6
contracts/DTOParticipationNFT.sol:125:95: TypeError: Invalid contract specified in override list: "ERC721".
    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual override(ERC721, ERC721Pausable) {
                                                                                              ^------------------------------^
@openzeppelin/contracts/token/ERC721/ERC721.sol:21:1: This contract: 
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {
^ (Relevant source part starts here and spans across multiple lines).

1 Like

Hi @sven.meyer,

We can just do an override (no longer need to do this for multiple inheritance)

    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual override {
        super._beforeTokenTransfer(from, to, tokenId);
    }

See: https://docs.openzeppelin.com/contracts/3.x/extending-contracts#rules_of_hooks

I find Remix quick to check something like this out.

MyNFT.sol

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/access/AccessControl.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/GSN/Context.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/utils/Counters.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/token/ERC721/ERC721.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/token/ERC721/ERC721Pausable.sol";

contract MyNFT is Context, AccessControl, ERC721Pausable {
    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;

    /**
     * @dev Grants `DEFAULT_ADMIN_ROLE`, `MINTER_ROLE` and `PAUSER_ROLE` to the
     * account that deploys the contract.
     */
    constructor(string memory name, string memory symbol, string memory baseURI) public ERC721(name, symbol) {
        _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());

        _setupRole(MINTER_ROLE, _msgSender());
        _setupRole(PAUSER_ROLE, _msgSender());

        _setBaseURI(baseURI);
    }

    function mint(address to) public virtual {
        require(hasRole(MINTER_ROLE, _msgSender()), "MyNFT: 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();
    }

    function pause() public virtual {
        require(hasRole(PAUSER_ROLE, _msgSender()), "MyNFT: must have pauser role to pause");
        _pause();
    }

    function unpause() public virtual {
        require(hasRole(PAUSER_ROLE, _msgSender()), "MyNFT: must have pauser role to unpause");
        _unpause();
    }

    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual override {
        super._beforeTokenTransfer(from, to, tokenId);
    }
}

@abcoathup Thanks a lot for the quick feedback, that really helped !!

Yes, I use Remix a lot, especially to try out new stuff, because it provides a nice UI to access all functions, so avoiding to develop an UI !

Remix is now fine with my code, just in VS Code, there is a remaining warning for the constructor

constructor(string memory name, string memory symbol, string memory baseURI) public ERC721(name, symbol) {
Visibility for constructor is ignored. If you want the contract to be non-deployable, 
making it "abstract" is sufficient

Should I care ?

1 Like

Hi @sven.meyer ,

In Solidity 0.7

Visibility ( public / external ) is not needed for constructors anymore
_From: https://docs.soliditylang.org/en/v0.8.0/070-breaking-changes.html#functions-and-events_

If you are compiling with Solidity 0.7 you can remove public.

@abcoathup , I think it’s because I am using solc 0.6.6 atm …

thanks for the reminder !

1 Like