Constructor calls _disableInitializers()
A code & audits factor in the v1.7.0 rubric. Measured per protocol on a s cadence.
Methodology how we score#
What this measures
This factor verifies that implementation contracts in the protocol's upgradeable proxy architecture call _disableInitializers() in their constructor, following the OpenZeppelin-recommended pattern to prevent direct initialization of the implementation contract itself. When _disableInitializers() is called in the constructor, the implementation contract's initializer is permanently locked at deployment time, preventing any subsequent caller from re-initializing it. The assessment is performed by static analysis of the implementation contract's constructor bytecode.
Why it matters
The _disableInitializers() constructor call is the defense-in-depth complement to the initializer modifier (assessed by RD-F-022). Even if an initializer modifier is present, a missing _disableInitializers() call in the constructor leaves a narrow race-condition window at deploy time where the implementation can be initialized directly before the proxy is set up. More importantly, it prevents the class of attack where a future OpenZeppelin library upgrade or a missed initializer modifier on a newly added initializer function creates a new unguarded entry point. The pattern was introduced precisely because the modifier alone was insufficient in complex inheritance hierarchies. Approximately three supporting instances in the T-01 evidence base motivate this factor.
Green / Yellow / Red
Green: all implementation contracts call _disableInitializers() in their constructor, confirmed by bytecode analysis of the deployed implementation. Yellow: the constructor does not call _disableInitializers() but all initialize() functions carry the initializer modifier, reducing -- but not eliminating -- the risk. Red: the constructor omits _disableInitializers() AND any initialize() function is missing the initializer modifier (this overlaps with RD-F-022 Red).
Common gray cases
This factor is gray for non-upgradeable protocols that do not use proxy patterns, or for protocols whose constructors cannot be inspected (unverified source).
Notable historical examples
No hacks are currently linked in the database for this specific factor as a standalone causal driver. The factor operates as a defense-in-depth check alongside RD-F-022, which captures the more common failure mode.
Measurement what to look for#
Determine whether implementation contract constructors call `_disableInitializers()` to prevent re-initialization of the implementation directly.