Inheriting upgradeable contracts and initialize function

Hello, when writing an upgradeable contract I find it convenient to have 3 functions. __{ContractName}_init function to init the whole contract and its parent, __{ContractName}_init_unchained to init the contract without calling parents initalizers and an initialize function that simply call __{ContractName}_init to simplify the call to the “constructor”.

However, when having multiple inheritance of upgradeable contracts that all have an initialize functions the compiler doesn’t like it and ask that you override the inherited functions somewhere. But this is not what I want. Is there any other way than not having the initialize to handle this ? This isn’t only related to OZ upgrades but I guess others might also be in the same case sooner or later.

Sample code to reproduce the error:

// SPDX-License-Identifier: SEE LICENSE IN LICENSE
pragma experimental ABIEncoderV2;
pragma solidity 0.6.12;

import "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol";

contract Hello is Initializable {
    function initialize(address _admin) public initializer {
        __Hello_init(_admin);
    }

    function __Hello_init(address _admin) internal initializer {
        //
        __Hello_init_unchained(_admin);
    }

    function __Hello_init_unchained(address _admin) internal initializer {}
}

contract Bonjour is Initializable {
    function initialize() public initializer {
        __Bonjour_init();
    }

    function __Bonjour_init() internal initializer {
        //
        __Bonjour_init_unchained();
    }

    function __Bonjour_init_unchained() internal initializer {}
}

contract Escrow is Initializable, Hello, Bonjour {
    address admin;

    //
    function initialize(address _admin) public initializer {
        Hello.initialize(_admin);
        Bonjour.initialize();

        admin = _admin;
    }
}
1 Like

Hi @sshmaxime,

If we have any function with the same signature then we need to override.

In your example, we can make Hello initialize virtual and Escrow initialize override.

The following then compiles:

// SPDX-License-Identifier: SEE LICENSE IN LICENSE
pragma experimental ABIEncoderV2;
pragma solidity 0.6.12;

import "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol";

contract Hello is Initializable {
    function initialize(address _admin) public virtual initializer {
        __Hello_init(_admin);
    }

    function __Hello_init(address _admin) internal initializer {
        //
        __Hello_init_unchained(_admin);
    }

    function __Hello_init_unchained(address _admin) internal initializer {}
}

contract Bonjour is Initializable {
    function initialize() public initializer {
        __Bonjour_init();
    }

    function __Bonjour_init() internal initializer {
        //
        __Bonjour_init_unchained();
    }

    function __Bonjour_init_unchained() internal initializer {}
}

contract Escrow is Initializable, Hello, Bonjour {
    address admin;

    //
    function initialize(address _admin) public override initializer {
        Hello.initialize(_admin);
        Bonjour.initialize();

        admin = _admin;
    }
}