Hi @Damien_Teo,
I'd like to clarify the concepts here on constructors vs. initializers:
- Generally an upgradeable implementation should not have a constructor. You should use an initializer to initialize your contract's logic.
- For deployProxy,
args
andinitializer
are for the initializer's arguments and name, respectively. - For upgradeProxy, if you need to call a function during the upgrade process, that is done with the
call?: string | { fn: string; args?: unknown[] },
option as you mentioned. This could be a function marked as reinitializer so that it can only be called once. - A constructor with the below content is still recommended for disabling initialization of the implementation contract itself (at the implementation's address). The reasoning is described in this post.
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}