How does inheritance work in upgradeable contracts?

Trying to understand how inheritance works when dealing with upgradeable contracts.
E.g., I want to make contract A , which inherit contract B and contract C, which in turn inherit other contracts. So, do I implement the OZ Upgradeability (i.e., import the UUPSUpgradeable.sol, Initializable.sol etc.) in all of these contracts, or just contract A?
Furthermore, how do I instantiate contract B in contract A? Currently, with contract A being non-upgradeable, I just call contract B's constructor in Contract A's like:

ContractA 
{
    constructor(address _arg1) ContractB(_arg1){  }

...}

So what would this part look like when I make ContractA upgradeable?

Would like comprehensive guidance in this matter (in the context of UUPS).

Thank you!

:computer: Environment

Hardhat

I think when you use the proxy pattern, you can not use the constructor to assign values when deploy contracts, you should write another function by yourself to do this. And for more details about the Proxy, I think you can look at the documentation: Upgrades - OpenZeppelin Docs

Thanks for the reply, Skyge :slight_smile:

I wonder; do I need to make every contract inherited by an upgradeable contract, upgradeable? I.e., upgradeability in contracts having multiple inheritance? OZ documentation says they would implement security checks in future for this. So is it even safe to use upgradeability in contracts with multiple inheritance? Need a comprehensive answer to these questions.

For me, I would like to use proxy pattern for all contracts that I will use, cause this will help to unify the code style, and there is a repo for OpenZeppelin contract with proxy pattern: openzeppelin-contracts-upgradeable | OpenZeppelin

Generally you will probably add UUPSUpgradeable only in A.

As for constructors/initializers, you can copy the pattern we use for our Upgradeable Contracts which would be something like this:

contract B is Initializable {
    function __init_B() onlyInitializing {}
}

contract A is Initializable, B {
    function initialize() initializer {
        __init_B();
    }
}
1 Like

Ok, so in contract B, I only inherit the Initializable.sol and not UUPSUpgradeable.sol? And, I change its constructor to function __init_B() onlyInitializing {}?

Yes that sounds right.