ERC20 Compile issue in Remix

Compiling error: TypeError: Overriding function visibility differs

:computer: Environment
OpenZeppelin 2.5,
Solidity 0.5.0,
Remix

:memo:Details
I have a token contract that is importing & inheriting the v2.5.0 version of ERC20 and ERC20 Detailed, and I’m getting the following compiling error: TypeError: Overriding function visibility differs for the transfer function and balanceOf function. Both of these functions use public in the ERC20 contract but external in the IERC20 contract. I have my own interface for my token contract and because of the public vs external different in the ERC20 and IERC20 contract, I can’t get past this error. Not sure what to do.

:1234: Code to reproduce

pragma solidity ^0.5.0;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v2.5.0/contracts/token/ERC20/ERC20Detailed.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v2.5.0/contracts/token/ERC20/ERC20.sol";

contract ITestToken {
    function balanceOf(address who) external view returns (uint256);
    function transfer(address to, uint256 value) public returns (bool);
}

contract TestToken is ITestToken, ERC20, ERC20Detailed {

    modifier myModifier() {
        // custom logic
        _;
    }

  constructor () public ERC20Detailed("MyTestToken", "MTT", 18) {
        _mint(msg.sender, 100000000 * (10 ** uint256(decimals())));
    }


    function transfer(address to, uint256 value) public myModifier() returns (bool) {
        return super.transfer(to, value);
    }

}
1 Like

Oh, I think I need to inherit my Interface after ERC20 and ERC20Detailed?

1 Like

Hi @kseniya,

Do you need to declare your own ITestToken interface? If you need to interact with an instance using an interface you could use IERC20.

pragma solidity ^0.5.0;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v2.5.0/contracts/token/ERC20/ERC20Detailed.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v2.5.0/contracts/token/ERC20/ERC20.sol";

contract TestToken is ERC20, ERC20Detailed {

    modifier myModifier() {
        // custom logic
        _;
    }

  constructor () public ERC20Detailed("MyTestToken", "MTT", 18) {
        _mint(msg.sender, 100000000 * (10 ** uint256(decimals())));
    }


    function transfer(address to, uint256 value) public myModifier() returns (bool) {
        return super.transfer(to, value);
    }

}

@abcoathup I do need it because there are other functions in there (i left them out for simplicity). Smart contracts in my dapp are interfacing with my TestToken so I have an interface created for several functions. I thought you could override functions of smart contracts you are inheriting?
Why is ERC20 using public when the IERC20 using external?

1 Like

Hello @kseniya!

First, note that the error you’re getting is not because of TestToken, but ITestToken: you declared transfer as a public function there, but IERC20 declares it as external.

The reason why IERC20 declares it as external is because it is an interface (not a contract!), and those can only have external functions (which can be implemented using a public function).

If you change ITestToken's transfertoexternal, your code will compile. If ITestTokenis your token's interface however and it is ERC20-compliant, what you should do is make it inherit fromIERC20` and only add your custom functions to it.

As to why transfer is public, the reason is inheritance. Note that in your code you added an override for transfer to extend it, and called super.transfer: this is considered an internal call by Solidity, and can only be made if the function can be internally called (i.e. internal or public). If transfer's implementation in ERC20 was external, there would be no legal way to write that override.

Hope this helps!

2 Likes