Search code examples
soliditysmartcontractsopenzeppelin

OpenZeppelin: TypeError: Function has override specified but does not override anything


After an update from @openzeppelin/contracts in Version 4.6 to 4.8, the solidity compiler complains about the _beforeTokenTransfer-function, that I had to override:

TypeError: Function has override specified but does not override anything.

) internal virtual override (ERC721, ERC721Enumerable, ERC721Pausable) {

And:

TypeError: Invalid contracts specified in override list: "ERC721", "ERC721Enumerable" and "ERC721Pausable".

     ) internal virtual override (ERC721, ERC721Enumerable, ERC721Pausable) {
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note: This contract: 
  --> @openzeppelin/contracts/token/ERC721/ERC721.sol:19:1:

19 | contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
   | ^ (Relevant source part starts here and spans across multiple lines).
Note: This contract: 
  --> @openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol:14:1:
   |
14 | abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
   | ^ (Relevant source part starts here and spans across multiple lines).
Note: This contract: 
  --> @openzeppelin/contracts/token/ERC721/extensions/ERC721Pausable.sol:22:1:
   |
22 | abstract contract ERC721Pausable is ERC721, Pausable {
   | ^ (Relevant source part starts here and spans across multiple lines).

My contract inherits from the following:

contract XYZ is
    ERC721,
    ERC721Enumerable,
    ERC721Burnable,
    ERC721Pausable,
    ERC721URIStorage,
    Ownable,
    AccessControlEnumerable
{
}

Since I have to override _beforeTokenTransfer, I have the following code:

function _beforeTokenTransfer(
    address from,
    address to,
    uint256 amount
) internal virtual override (ERC721, ERC721Enumerable, ERC721Pausable) {
    super._beforeTokenTransfer(from, to, amount);
}

With older OpenZeppelin, it works and compiles. What happend?


Solution

  • There's a breaking change in OpenZeppelin 4.8. They've changed the signature of the function _beforeTokenTransfer.

    You have to do it like this:

    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 firstTokenId,
        uint256 batchSize
    ) internal virtual override (ERC721, ERC721Enumerable, ERC721Pausable) {
        super._beforeTokenTransfer(from, to, firstTokenId, batchSize);
    }