-
Notifications
You must be signed in to change notification settings - Fork 34
CMTATUpgradeableUUPS contract may be not initializable #327
Description
Version affected: v3.0.0
Deployment version: UUPS
Severity: Medium
Fix: v3.1.0 ?
Reported by: Nethermind Audit Agent
The initialize function in CMTATUpgradeableUUPS overrides the one from its parent CMTATBaseRuleEngine and
attempts to call the parent's function directly. Both the child and parent initialize functions are decorated with
the initializer modifier from OpenZeppelin's Initializable contract.
When CMTATUpgradeableUUPS.initialize is called, its initializer modifier will run first, setting the contract's state to 'initialized'. Subsequently, the call to CMTATBaseRuleEngine.initialize will execute. This function also has an initializer modifier, which will check if the contract is already initialized. Since it is, the modifier will cause the transaction to revert, making it impossible to initialize any contract that inherits from CMTATUpgradeableUUPS .
-
Code snippet from CMTATUpgradeableUUPS.sol :
function initialize( address admin, ICMTATConstructor.ERC20Attributes memory ERC20Attributes_, ICMTATConstructor.ExtraInformationAttributes memory extraInformationAttributes_, ICMTATConstructor.Engine memory engines_ ) public override initializer { CMTATBaseRuleEngine.initialize( admin, ERC20Attributes_, extraInformationAttributes_, engines_); __UUPSUpgradeable_init_unchained(); } -
Code snippet from the parent CMTATBaseRuleEngine.sol :
function initialize( address admin, ICMTATConstructor.ERC20Attributes memory ERC20Attributes_, ICMTATConstructor.ExtraInformationAttributes memory extraInformationAttributes_, ICMTATConstructor.Engine memory engines_ ) public virtual initializer { __CMTAT_init( admin, ERC20Attributes_, extraInformationAttributes_, engines_ ); }
This nested initializer pattern makes the contract undeployable as its initialization will always fail.
Note
If the proxy is initialized after deployment, the following error will be generated: InvalidInitialization()
However, if the proxy is initialized in the same transaction as deploy, in this case, the function will not revert.
Note that it is recommanded to initialize the proxy at deployment to avoid a front-running initialization