Weired compiler issues when compiling ERC721PresetMinterPauserAutoIdUpgradeable

I want to build my own ERC721based Custom Preset that is similar to the ERC721PresetMinterPauserAutoIdUpgradeable from OZ but follows some custom rules, especially when it comes to the minting.

I started to copy over the ERC721PresetMinterPauserAutoIdUpgradeable from OpenZeppelin into my project and addjusted all imports so that they would work.

However, when compiling the very same code, i face issues like:

TypeError: Function has override specified but does not override anything.
   --> contracts/lib/presets/ERC721PresetMinterPauserAutoIdUpgradeable.sol:142:24:
    |
142 |     ) internal virtual override(ERC721Upgradeable, ERC721EnumerableUpgradeable, ERC721PausableUpgradeable) {
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


TypeError: Invalid contracts specified in override list: "ERC721EnumerableUpgradeable", "ERC721PausableUpgradeable" and "ERC721Upgradeable".
   --> contracts/lib/presets/ERC721PresetMinterPauserAutoIdUpgradeable.sol:142:24:
    |
142 |     ) internal virtual override(ERC721Upgradeable, ERC721EnumerableUpgradeable, ERC721PausableUpgradeable) {
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note: This contract: 
  --> @openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721EnumerableUpgradeable.sol:15:1:
   |
15 | abstract contract ERC721EnumerableUpgradeable is Initializable, ERC721Upgradeable, IERC721EnumerableUpgradeable {
   | ^ (Relevant source part starts here and spans across multiple lines).
Note: This contract: 
  --> @openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721PausableUpgradeable.sol:17:1:
   |
17 | abstract contract ERC721PausableUpgradeable is Initializable, ERC721Upgradeable, PausableUpgradeable {
   | ^ (Relevant source part starts here and spans across multiple lines).


TypeError: Derived contract must override function "_beforeConsecutiveTokenTransfer". Two or more base classes define function with same name and parameter types.
  --> contracts/lib/presets/ERC721PresetMinterPauserAutoIdUpgradeable.sol:32:1:
   |
32 | contract ERC721PresetMinterPauserAutoIdUpgradeable is
   | ^ (Relevant source part starts here and spans across multiple lines).
Note: Definition in "ERC721Upgradeable": 
   --> @openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:502:5:
    |
502 |     function _beforeConsecutiveTokenTransfer(
    |     ^ (Relevant source part starts here and spans across multiple lines).
Note: Definition in "ERC721EnumerableUpgradeable": 
   --> @openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721EnumerableUpgradeable.sol:111:5:
    |
111 |     function _beforeConsecutiveTokenTransfer(
    |     ^ (Relevant source part starts here and spans across multiple lines).
Note: Definition in "ERC721PausableUpgradeable": 
  --> @openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721PausableUpgradeable.sol:41:5:

Why is this code compiling with OpenZeppelin-Repository but not on my own side?

Steps to reproduce:

  1. Copy contracts/token/ERC721/presets/ERC721PresetMinterPauserAutoIdUpgradeable.sol into own project
  2. Adjust the Import-statements so that base contracts can be found:
import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721EnumerableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721BurnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721PausableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
  1. The actual contract stays unmodified like:
contract ERC721PresetMinterPauserAutoIdUpgradeable is
    Initializable, ContextUpgradeable,
    AccessControlEnumerableUpgradeable,
    ERC721EnumerableUpgradeable,
    ERC721BurnableUpgradeable,
    ERC721PausableUpgradeable
{
    function initialize(
        string memory name,
        string memory symbol,
        string memory baseTokenURI
    ) public virtual initializer {
        __ERC721PresetMinterPauserAutoId_init(name, symbol, baseTokenURI);
    }
    using CountersUpgradeable for CountersUpgradeable.Counter;

    ..... // and so on and so forth

  1. Just compile the project.

The error messages reported above will immediately appear.
Why happens this here and how can I solve this?

It seems like there is a function you need to override but you do nothing.

It seems to be a version-conflict. Hooks like _beforeConsecutiveTokenTransfer were introduced with OpenZeppelin 4.8.
If you have copied over the official code of Preset-Contract, you probably have copied from main-branch which still points to 4.7 which is using the "old" hooks _beforeTokenTransfer.

Please have a look into your package.json and either copy over the code from 4.8rc1 or still downgrade to openzepplin 4.7

2 Likes