★ Public initialize() without initializer modifier
Convex Finance'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 #
ExtraRewardStashV3.initialize() uses require(gauge == address(0), '!init') rather than the OZ initializer modifier. The implementation contract starts with gauge=address(0), so anyone can initialize the implementation itself. This is a known proxy-clone pattern risk. In practice, the implementation holds no user TVL (value is in clones created by StashFactoryV2); exploiting this cannot drain user funds directly. No _disableInitializers() call equivalent exists (OZ 3.4.0 predates this pattern). Pattern deviates from the OZ standard but functional guard exists on clones.
Sources #
- GitHubConvex StashFactoryV2.sol raw source (proxy clone deployment with immediate initialization)StashFactoryV2 clone patternretrieved 2026-05-16
- Convex ExtraRewardStashV3.sol raw source (initialize without OZ initializer modifier)ExtraRewardStashV3.sol - initialize() with gauge==address(0) guard onlyretrieved 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 →