★ Public initialize() without initializer modifier
StakeWise v3's assessment for RD-F-022 — scored yellow on the v1.7.0 rubric. The evidence below is the curator's reasoning for this score.
Evidence summary #
VaultsRegistry (0x3a0008...) and Keeper (0x6B5815...) expose initialize(address _owner) functions. Etherscan source confirms these use a custom _initialized boolean flag (reverts with Errors.AccessDenied() on second call) rather than OZ's initializer modifier. These are direct non-upgradeable implementations (not proxy targets), so the one-tx proxy-takeover vector does not directly apply — they cannot be re-initialized through a proxy. EthVault and EthPrivVault proxy implementations correctly use _disableInitializers() in constructors and reinitializer(_version). The non-standard custom guard pattern reduces auditability and tool-detectability (Slither would flag this as missing-initializer-modifier) but contracts are currently initialized and not exploitable in the deployed state.
Sources #
- EtherscanVaultsRegistry Etherscan verified sourceVaultsRegistry 0x3a0008a588772446f6e656133C2D5029CC4FC20E #code — initialize(address _owner) function with custom _initialized flag, no OZ initializer modifierretrieved 2026-05-16
- Keeper Etherscan verified sourceKeeper 0x6B5815467da09DaA7DC83Db21c9239d98Bb487b5 #code — initialize(address _owner) with custom _initialized flag, no OZ initializer modifierretrieved 2026-05-16
- EthVault.sol — OZ-standard proxy initialization patternEthVault.sol constructor calls _disableInitializers(); initialize() uses reinitializer(_version) — correct OZ standard for proxy implementationsretrieved 2026-05-16
Methodology #
Determine whether any implementation contract exposes `initialize(…)` without the OpenZeppelin `initializer` modifier or equivalent initialization lock.
See the full factor methodology and distribution across all protocols →