4

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.

0

2 Answers 2

2

In contract DemoContract is ERC20,ERC20Detailed,ERC20Burnable,ERC20Mintable, ERC20Pausable:

Each one of contracts ERC20Detailed, ERC20Burnable, ERC20Mintable and ERC20Pausable already inherits from contract ERC20, so you should not inherit from this contract as well.

For example, compiling the following code gives the same error as yours:

pragma solidity 0.6.4;

contract Foo {
    uint x;
    function func(uint _x) public virtual {
        x = _x;
    }
}

contract Foo2 is Foo {
    function func(uint _x) public virtual override {
        super.func(2*_x);
    }
}

contract Foo3 is Foo, Foo2 {
    function func(uint _x) public virtual override {
        super.func(3*_x);
    }
}

Which is resolves when you change contract Foo3 is Foo, Foo2 to contract Foo3 is Foo2.

Note that this is not an issue in solc 0.4.x (after removing the virtual and override of course).

3
  • I modified DemoContract so it no longer inherits ERC20. However, the error contains to appear. I updated the question above to show the contract headings. Maybe I am doing something wrong there?
    – user58503
    Mar 14, 2020 at 15:32
  • @user58503: Obviously, because several contracts which your contract is iheriting from, are inheriting from the same contract (ERC20). You're experiencing what is known as The diamond-inheritance problem. The typical solutions are either virtual inheritance (C++), or prohibit that altogether (Java). I'm not sure what the solution in Solidity 0.6.x is. Obviously, this wasn't a problem in previous versions. Perhaps they (chriseth) have added support for virtual inheritance, in which case, the syntax would me more or less something like contract X is virtual Y, virtual Z. Give it a try... Mar 14, 2020 at 15:47
  • Thank you for your suggestions. When I completely remove ERC20Pausable from the DemoContract it compiles perfectly fine, although ERC20Detailed, ERCBurnable, and ERCMintable all inherit ERC20. Therefore, I do not think this is the issue.
    – user58503
    Mar 14, 2020 at 16:09
0

If I may use above example to extend my explanation, thanks

When you have two or more base classes define function with same name and parameter types you must override that function with override(baseContract1, baseContract2). Foo and Foo2 need not be necessarily inheriting from each other.

Try:

contract Foo3 is Foo, Foo2 {
    function func(uint _x) public virtual override(Foo, Foo2) {
        super.func(3*_x);
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.