# openzeppelin initializable with initializer modifier prevents re-initialization attacks on proxy contracts
The `initializer` modifier from OpenZeppelin's `Initializable` contract tracks whether initialization has occurred and reverts on subsequent calls. This addresses [[uninitialized proxy contracts are vulnerable to re-initialization attacks that hijack ownership|the re-initialization attack]] where an attacker calls an unguarded initializer to claim proxy ownership.
The modifier sets a boolean flag in a reserved storage slot that persists across delegatecall contexts, ensuring the initialization function can only execute once per proxy. Since [[delegatecall executes code from another contract using the callers storage context|delegatecall preserves the caller's storage]], this flag lives in the proxy's storage, not the implementation's. The `reinitializer(n)` variant allows controlled sequential initialization for version upgrades while still preventing unauthorized re-initialization.
The [[parity wallet hack demonstrated that selfdestruct in implementation contracts permanently bricks proxy systems|Parity wallet hack]] ($280M frozen) is the canonical case where this defense was absent — an unguarded initialization on the implementation contract itself allowed the attacker to claim ownership.
**Important limitation:** The `initializer` modifier prevents re-calling the initializer function, but it does not prevent CPIMP attacks that occur before initialization ever runs. Since [[non-atomic proxy deployment creates a front-running window where any actor can write to the ERC1967 implementation storage slot before the legitimate initialization transaction confirms]], an attacker can write a shadow implementation into the ERC1967 slot before the legitimate initialization transaction confirms. In this scenario, the `initializer` modifier never executes — the shadow implementation intercepts the initialization call first. The `initializer` guard and atomic deployment are complementary defenses addressing different attack phases: the guard prevents re-initialization after deployment; since [[atomic proxy deployment by passing initialization data to the ERC1967Proxy constructor eliminates the CPIMP front-running window because deployment and initialization occur within a single transaction]] prevents pre-initialization attacks by ensuring no window exists between deployment and initialization.
---
Relevant Notes:
- [[uninitialized proxy contracts are vulnerable to re-initialization attacks that hijack ownership]] — the attack this prevents
- [[parity wallet hack demonstrated that selfdestruct in implementation contracts permanently bricks proxy systems]] — the canonical exploit of missing initialization guards
- [[delegatecall executes code from another contract using the callers storage context]] — the mechanism requiring proxy-side initialization
- [[vyper module composition uses explicit uses initializes and exports keywords preventing accidental state coupling between modules]] — Vyper's language-level alternative: the `initializes` keyword enforces exactly-once module initialization without requiring library-level guards
- [[non-atomic proxy deployment creates a front-running window where any actor can write to the ERC1967 implementation storage slot before the legitimate initialization transaction confirms]] — the vulnerability the `initializer` modifier does NOT prevent; requires atomic deployment as the defense
- [[atomic proxy deployment by passing initialization data to the ERC1967Proxy constructor eliminates the CPIMP front-running window because deployment and initialization occur within a single transaction]] — the complementary defense that addresses the pre-initialization phase this modifier cannot cover
Topics:
- [[security-patterns]]