defirisk.co
rubric v1.7.0

Public initialize() without initializer modifier

A code & audits factor in the v1.7.0 rubric. Measured per protocol on a s cadence.

Critical factor. A Red on this factor alone is sufficient to gate a protocol to grade D or F regardless of other category rollups.

Methodology how we score#

What this measures
This factor assesses whether any implementation contract in the protocol's proxy architecture exposes an initialize() function (or equivalent setup function) without OpenZeppelin's initializer modifier or an equivalent one-time-call guard. The static analyzer checks deployed bytecode for the presence of a function selector matching initialize(...) on implementation contracts (not proxies) and verifies whether the modifier's revert-if-already-initialized guard is present.

Why it matters
An unguarded initialize() on an implementation contract allows any caller to invoke it directly, resetting ownership or critical parameters to attacker-controlled values in a single transaction. This is a known one-transaction exploit class: because the implementation's storage is separate from the proxy's storage, the attack does not affect proxy state -- but it can redirect upgrade authority or allow the attacker to call selfdestruct on the implementation, bricking all proxies pointing to it. Industry proxy pattern research has documented that unstructured storage patterns in upgradeable contracts hinder static analysis, making manual curator review of initialization guards especially important. The Parity wallet freeze ($150M locked permanently) is the canonical example of an unguarded initWallet() on a library contract called by any user.

Green / Yellow / Red
Green: all implementation contracts either call _disableInitializers() in the constructor (the OpenZeppelin-recommended pattern) or carry the initializer modifier on any initialize-type function, confirmed by static analysis of deployed bytecode. Yellow: the initializer modifier is present but the constructor does not call _disableInitializers(), leaving a narrow race condition window at deploy time. Red: an implementation contract exposes a public initialize() or similar function with no one-time-call guard, allowing any address to claim ownership or reset protocol parameters.

Common gray cases
Curators legitimately cannot grade this factor when the protocol's source code is not verified on any explorer, making static analysis of the initialization path impossible.

Notable historical examples
No hacks are currently linked in the database for this specific factor (the pattern has been exploited in ecosystem incidents outside this dataset, most notably the 2017 Parity wallet freeze). The factor is retained as ★ critical based on its one-transaction exploit class and ~4 documented precursor instances in the T-01 evidence base.

* Critical factor
This factor is critical under rubric v1.5: a single Red assessment is sufficient to trigger a D or F grade regardless of all other category scores, because an unguarded initialize() represents a one-transaction total-compromise vector on the protocol's upgrade authority.

Measurement what to look for#

Determine whether any implementation contract exposes `initialize(…)` without the OpenZeppelin `initializer` modifier or equivalent initialization lock.

Data & output #

Data source
Slither `uninitialized-local` + `missing-zero-check` + `unprotected-upgrade` detectors + source search for `initialize` function signature
Output format
Green / Yellow / Red · critical gate active
Evidence artifact
Slither output JSON + function signature + modifier list
Confidence signal
green = all `initialize` functions protected by `initializer` or equivalent; red = any unprotected `initialize` on a live implementation; gray = source unverified

Scored protocols 0 carry this factor#

No protocols have been scored for this factor yet.

Linked hacks 1 historical incident#

illustrativeBalancer V2 (Composable Stable Pools): `_upscale()` rounding-down compounded across 65+ micro-swaps2025-11-03 · $128M · `_upscale()` rounding-down compounded across 65+ micro-swaps · Cat 9 hygiene pattern: audited but not stress-tested under batch composition; live 4+ years before vector discovered
rubric_version v1.7.0factor RD-F-022category 1carried 0critical yes