TypeError: Derived contract must override function "_beforeTokenTransfer"

I am trying to implement an ERC20 token that inherits ERC20.sol, ERC20Detailed.sol, ERC20Burnable.sol, ERC20Mintable.sol, and ERC20Pausable.sol.

contract DemoContract is ERC20,ERC20Detailed,ERC20Burnable,ERC20Mintable, ERC20Pausable {
    constructor(uint256 initialSupply) ERC20Detailed("Test Token", "TEST", 18) public {
        _mint(msg.sender, initialSupply);
    }
}

The function _beforeTokenTransfer is defined in ERC20.sol as follows:

function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }

and in ERC20Pausable.sol as follows:

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

        require(!paused(), "ERC20Pausable: token transfer while paused");
    }

When I try to compile my contracts using truffle framework, I get the following error:

TypeError: Derived contract must override function "_beforeTokenTransfer". Two or more base classes define function with same name and parameter types.

contract DemoContract is ERC20,ERC20Detailed,ERC20Burnable,ERC20Mintable, ERC20Pausable {
^ (Relevant source part starts here and spans across multiple lines).

I cannot seem to understand why this error occurs although override is used in the ERC20Pausable.sol.

Here are the new contracts after removing ERC20 from the DemoContract:

contract ERC20 is Context, IERC20

contract ERC20Detailed is ERC20

abstract contract ERC20Burnable is Context, ERC20

abstract contract ERC20Mintable is ERC20, MinterRole

abstract contract ERC20Pausable is ERC20, Pausable

contract DemoContract is ERC20Detailed,ERC20Burnable,ERC20Mintable, ERC20Pausable

However, the error still remains.

2 Likes

I have same problem too.

1 Like

Hello ebz,

I wrote a little bit different mechanism for pausable, capped features. It is working but I don’t make any test on it.

pragma solidity ^0.6.0; 

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20Detailed.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20Burnable.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/lifecycle/Pausable.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/SafeERC20.sol";

contract KSC is ERC20, ERC20Detailed, ERC20Burnable, Pausable {
    using SafeERC20 for KSC;
    
    event SupplyAmountSet(uint amount, address byOwner);
    
    uint256 private _cap;
    address deployer;
    
    mapping(address => uint8) mintedBy;
    mapping(address => bool) pausers;
    
    constructor() public ERC20Detailed("HzToken", "HZT", 2) {
        deployer = msg.sender;
        mintedBy[ deployer ] = 1;
        pausers[ deployer ] = true;
    }
    
    modifier ownerOnly() { 
        require(msg.sender == deployer, "This function could only be executed by the owner");
        _;
    }
    
    modifier pauserOnly() {
        require(pausers[ msg.sender ], "This function could only be executed by a pauser.");
        _;
    }

    modifier minterOnly() {
        require(mintedBy[ msg.sender ] > 0, "This function could only be executed by a minter, or you have already minted before");
        _;
    }
    
    function setAsMinter(address[] memory targets) public ownerOnly() {
        uint limit = targets.length;
        for (uint i = 0; i < limit; ++i) {
            mintedBy[ targets[ i ] ] = 1;
        }
    }
    
    function setAsPauser(address[] memory targets) public ownerOnly() {
        uint limit = targets.length;
        for (uint i = 0; i < limit; ++i) {
            pausers[ targets[ i ] ] = true;
        }
    }
    
    function setCap(uint256 amount) public ownerOnly() {
        require(_cap == 0, "Cap is already set");
        _cap = amount;
    }
    
    function unpause() public pauserOnly() {
        super._unpause();
    }
    
    function pause() public pauserOnly() {
        super._pause();
    }
    
    function setSupply(uint _amount) public minterOnly() returns(uint) {
        emit SupplyAmountSet(_amount, deployer);
        
        _mint(msg.sender, _amount);
        
        if (deployer != msg.sender) {
            mintedBy[ msg.sender ] = 0;
        }
        
        return _amount;
    }
    
    /// Copied from ERC20Pausable
    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {
        super._beforeTokenTransfer(from, to, amount);

        require(!paused(), "ERC20Pausable: token transfer while paused");
        
        if (from == address(0)) { // When minting tokens
            require(totalSupply().add(amount) <= _cap, "ERC20Capped: cap exceeded");
        }
    }
}
1 Like

Hi @ebz,

Welcome to the community :wave:

Which version of OpenZeppelin Contracts are you using?
I assume you are using a pre-release version of OpenZeppelin Contracts 3.0 but am not sure where you are getting ERC20Mintable from.

The issue that you are having is due to overriding when using multiple inheritance.
I will need to create an example of how to do this.

Hi @FerdiKurt,

Welcome to the community :wave:

You are currently importing the master branch of OpenZeppelin Contracts so you will be getting the work in progress of OpenZeppelin Contracts 3.0.

:warning: Note: You should only use code published in an official release of OpenZeppelin Contracts, the latest release is 2.5. When importing via GitHub on Remix you can specify the release tag, (otherwise you will get the latest code in the master branch).

See the following for an example: Deploy a simple ERC20 token in Remix

I can update this example when OpenZeppelin Contracts 3.0 is released.

1 Like

Yes, I am using the 3.0 release and have incorporated into it ERC20Minter.sol and MinterRole.sol from the 2.5 release. To make it work I did the following:

  1. I let ERC20.sol inherit Pausable.sol directly. Inside Pausable.sol, I also defined two new functions pause() and unpause() that call _pause() and _unpause() within the contract itself respectively. By that, the ERC20.sol looks as the following:

contract ERC20 is Context,Pausable {
...
}.

  1. In my example, since I will not need to override the function _beforeTokenTransfer() present in ERC20.sol (e.g. not using ERC20Capped.sol), I directly defined _beforeTokenTransfer into ERC20.sol as the following:
function _beforeTokenTransfer() internal view  {
require(!paused(), "ERC20Pausable: token transfer while paused");
}

and now I no longer need ERC20Pausable.sol.

  1. My DemoContract now looks like this:
contract DemoContract is ERC20Detailed,ERC20Burnable,ERC20Mintable {
    constructor(uint256 initialSupply) ERC20Detailed("Test Token", "TEST", 18) public {
        _mint(msg.sender, initialSupply);
    }
}

where ERC20Mintable.sol (and MinterRole.sol) is taken from the 2.5 release.

In summary, my contracts look as the following:
contract ERC20 is Context,Pausable{}

abstract contract ERC20Detailed{}

abstract contract ERC20Burnable is Context, ERC20 {}

abstract contract ERC20Mintable is MinterRole,ERC20 {}

contract MinterRole is Context{}

contract Pausable is PauserRole{}

contract PauserRole is Context {}

Hi @abcoathup,
Thank you sir, I’m just making some experiments on different standard including ERC777, ERC1820, ERC1155, ERC1400 etc. Open Zeppelin brings amazing stuffs on ERC20, ERC721 and ERC777. I hope I will contribute in near future when i finished all advanced concepts.

Thank you.

2 Likes

This is fairly old but I don’t see an answer here and ran into the same issue when trying to make a burnable and pausable token. Here how I’d resolve the compiler issue (minimal code not usable token like that), but curious if @abcoathup has a better solution:

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v3.3/contracts/token/ERC20/ERC20.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v3.3/contracts/token/ERC20/ERC20Pausable.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v3.3/contracts/token/ERC20/ERC20Burnable.sol";

contract MyToken is ERC20("Token", "TKn"), ERC20Pausable, ERC20Burnable {

    function _beforeTokenTransfer(address from, address to, uint256 amount) internal override(ERC20, ERC20Pausable) {
        ERC20Pausable._beforeTokenTransfer(from, to, amount);
    }

}
3 Likes

Hi @SCBuergel1,

We need to override the parent contracts implementations of the function and include each parent we are overriding in override(parent1, parent2)

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


As an aside, I noticed that you were importing from a release branch rather than a release tag in your GitHub imports:

:warning: Note: You should only use code published in an official release of OpenZeppelin Contracts, the latest release is 3.3. When importing via GitHub on Remix you can specify the release tag, (otherwise you will get the latest code in the master branch). The example below imports v3.3.0.

// SPDX-License-Identifier: MIT
pragma solidity ^0.6.2;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/token/ERC20/ERC20.sol";

contract Token is ERC20 {

    constructor () public ERC20("Token", "TKN") {
        _mint(msg.sender, 1000000 * (10 ** uint256(decimals())));
    }
}

Thanks for these spot-on comments @abcoathup !

We need to override the parent contracts implementations of the function and include each parent we are overriding in override(parent1, parent2)

In my case only the ERC20Pausable had an actual function body, so I omitted the empty ERC20 super call to _beforeTokenTransfer as I found it more explicit / readable. But as this is a general discussion this should of course be super._beforeTokenTransfer.

As an aside, I noticed that you were importing from a release branch rather than a release tag in your GitHub imports:

I indeed was confused what is a tag (v3.3.0) and what is a branch (release-v3.3.0). Updated and fixed example here again for future reference:

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/token/ERC20/ERC20.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/token/ERC20/ERC20Pausable.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/token/ERC20/ERC20Burnable.sol";

contract MyToken is ERC20("Token", "TKN"), ERC20Pausable, ERC20Burnable {

    function _beforeTokenTransfer(address from, address to, uint256 amount) internal override(ERC20, ERC20Pausable) {
        super._beforeTokenTransfer(from, to, amount);
    }

}
3 Likes

Was struggling with this conflict too, but your approach worked perfectly. Thanks!

1 Like

Some error:

This code from wizard:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/utils/Counters.sol";

contract MyToken is ERC721, ERC721Enumerable, ERC721URIStorage, AccessControl {
    using Counters for Counters.Counter;

    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
    Counters.Counter private _tokenIdCounter;

    constructor() ERC721("MyToken", "MTK") {
        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
        _grantRole(MINTER_ROLE, msg.sender);
    }

    function safeMint(address to, string memory uri) public onlyRole(MINTER_ROLE) {
        uint256 tokenId = _tokenIdCounter.current();
        _tokenIdCounter.increment();
        _safeMint(to, tokenId);
        _setTokenURI(tokenId, uri);
    }

    // The following functions are overrides required by Solidity.

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

    function _burn(uint256 tokenId) internal override(ERC721, ERC721URIStorage) {
        super._burn(tokenId);
    }

    function tokenURI(uint256 tokenId)
        public
        view
        override(ERC721, ERC721URIStorage)
        returns (string memory)
    {
        return super.tokenURI(tokenId);
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        override(ERC721, ERC721Enumerable, AccessControl)
        returns (bool)
    {
        return super.supportsInterface(interfaceId);
    }
}