Possible bug with Missing initializer calls / order of initializers error

Hi, I am trying to deploy transparent upgradable proxy which is inheriting other contract

Basically inherit tree is Proxy -> ProxyBase -> ProxySubBase -> ACL, ERC4626Upgradable

There are 2 problems:

  1. Validation of initializer call I get: Missing initializer calls for one or more parent contracts: ProxySubBase

  2. Order of initialization is not good: On Proxy and ProxyBase I get: Incorrect order of parent initializer calls.

What I noticed for 1. problem:

  • if ProxyBase is abstract contract it works ok, if it is "normal" contract I get above error

Regarding 2. problem. I am not sure that validator is actually correct:

  • if in my __ProxySubBase_init I have order like this which I think is correct, it throws error:

      __ERC20_init(name, symbol);
      __ERC4626_init(IERC20(asset));
      __ACL_init(msg.sender);
    
      __ProxySubBase_init_unchained();
    
  • if I have order like this it works:

      __ACL_init(msg.sender);
      __ERC20_init(name, symbol);
      __ERC4626_init(IERC20(asset));
    
      __ProxySubBase_init_unchained();
    

So __ACL_init seems must be first to initialize which for me is strange as my contract is defined as

abstract contract ProxySubBase is ACL, ERC4626Upgradeable

I would expect that initialization is from right to left

:1234: Code to reproduce

I made github repo you can checkout and test -> just run test Poc.ts

Github repo

:laptop: Environment

All is visible in github repo, but all tools are latest.

Hi, thanks for your post.

For 1., that looks like the same issue as https://github.com/OpenZeppelin/openzeppelin-upgrades/issues/1150. As a workaround for now, you can add /// @custom:oz-upgrades-unsafe-allow missing-initializer-call above the __ProxyBase_init_unchained function definition.

For 2., these are just warnings and whether the order matters will depend on your contracts, but the order in this case should be:

  __ACL_init(msg.sender);
  __ERC20_init(name, symbol);
  __ERC4626_init(IERC20(asset));

  __ProxySubBase_init_unchained();

since the initialization of the inherited contracts should be from left to right, meaning least derived to most derived.

1 Like