How to call initialize on implementation when upgrading with OZ Upgrades?

There are 3 different concepts here:

  1. Initializing a proxy
  2. Re-initializing a proxy during an upgrade
  3. Initializing the implementation itself to prevent someone else from initializing it

1 and 2 are done by initializers or reinitializers (see https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable).

Initializers or reinitializers can be called from deployProxy or upgradeProxy as in your example above -- these happen in the context of the proxy's address.

3 is done by having a constructor like the below, which happens in the context of the implementation. See https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable#initializing_the_implementation_contract

/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
    _disableInitializers();
}

This sets the initialized version to the maximum value for the implementation itself, which prevents someone from calling an initializer or reinitializer in the context of the implementation address.

1 Like