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.

1 Like

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.

1 Like