Skip to content

State Initialised in Constructor of Upgradeable Contract

SAFE-0129 Upgradeability Checked automatically by the scanner
1

What goes wrong

An upgradeable (proxy-based) contract sets state in a constructor. Constructor code runs in the implementation's own context, never in the proxy's storage, so the proxy is left uninitialised — owner is zero, guards are off — and an attacker can seize it.

2

The vulnerable pattern

proof of concept — how it is exploited
// implementation constructor sets owner = msg.sender (deployer).
// through the proxy, owner is still 0 (constructor never ran there).
// attacker calls initialize()/unprotected setter -> becomes owner.
3

How to fix it

the pattern that is safe
// use an initializer, not a constructor, and lock the implementation
constructor() { _disableInitializers(); }
function initialize(address o) external initializer { __Ownable_init(o); }
Proxies ignore constructors; use initializer + _disableInitializers.
Check your own contract for this

The SaferICO scanner runs 201 detectors over your Solidity source, SAFE-0129 among them. Paste an address or the source itself — a small per-scan fee, shown before you sign, or unlimited on any plan.

Run the scanner See how it is attacked Read the docs