There are 3 different concepts here:
- Initializing a proxy
- Re-initializing a proxy during an upgrade
- 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.