Reinitialization Explained in Detail
Upgradeable contracts use initializers instead of constructors. Reinitializers let a new version set new state during an upgrade.
This is useful, but dangerous if an attacker can run setup logic or reuse an initializer version.
Smart contract example
function initializeV2() external reinitializer(2) {
newFeatureEnabled = true;
}
The version number should prevent the same initializer from running twice.
Reinitialization in Auditing
Reinitialization bugs can reset ownership, change roles, overwrite configuration, or activate unsafe modules. They are a common upgradeable-contract takeover path.
Auditors check who can call each initializer and whether the versioning is correct.
Red flags in code
-
initialize()remains callable after deployment. -
Implementation contract is not disabled.
-
Reinitializer version is reused.
-
Upgrade function accepts arbitrary initialization calldata without controls.
-
New variables are not initialized or are initialized by the wrong caller.
How to test or review it
-
Try calling every initializer twice.
-
Try initializing the implementation contract directly.
-
Upgrade with expected and malicious init calldata.
-
Verify owner, roles, and config after upgrade.
-
Check initializer version state across versions.