Multiple Inheritance in OpenZeppelin Contracts Upgradeable

Sorry for dumb question.
How to make Upgradeable contract both Pausable and Burnable

Compiler error:

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

function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
//import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/SafeERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20PausableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";

contract SomeToken is
    ERC20Upgradeable,
    ERC20PausableUpgradeable,
    ERC20BurnableUpgradeable
//    OwnableUpgradeable
{
    function initialize() public initializer {
        __ERC20_init("Some Token", "CX");
        __ERC20Pausable_init();
    }
}
1 Like

Not dumb at all. Multiple inheritance doesn't play nice with initializers. From the contracts-upgradeable repo README:

Use with multiple inheritance requires special care. Initializer functions are not linearized by the compiler like constructors. Because of this, each __{ContractName}_init function embeds the linearized calls to all parent initializers. As a consequence, calling two of these init functions can potentially initialize the same contract twice.

The function __{ContractName}_init_unchained found in every contract is the initializer function minus the calls to parent initializers, and can be used to avoid the double initialization problem, but doing this manually is not recommended. We hope to be able to implement safety checks for this in future versions of the Upgrades Plugins.

Consider using presets instead, like ERC20PresetMinterPauserUpgradeable which is also burnable.

3 Likes

Thank you. Yes, I’ve used the preset

2 Likes