The LevelOne → LevelTwo UUPS upgradeable contracts suffer from a storage‐layout collision: after slot 0, every variable in LevelTwo shifts and reinterprets the proxy’s existing storage, corrupting state. This latent bug lies dormant until the proxy is correctly upgraded, at which point schoolFees
(slot 1) becomes sessionEnd
, sessionEnd
(slot 2) becomes bursary
, and so on, silently overwriting balances, scores, and mappings. If exploited or simply triggered by a future upgrade, this will break business logic and could cause substantial token loss. Mitigation requires aligning storage (inheritance or gaps) and adding automated CI checks.
Storage Layout Comparison
Slot | LevelOne | LevelTwo |
---|---|---|
0 | address principalbool bool inSession |
address principalbool bool inSession |
1 | uint256 schoolFees |
uint256 sessionEnd |
2 | uint256 sessionEnd |
uint256 bursary |
3 | uint256 bursary |
uint256 cutOffScore |
4 | uint256 cutOffScore |
mapping(address=>bool) isTeacher |
… | … | … |
Because LevelTwo neither inherits LevelOne nor reserves unused slots, every subsequent variable is repurposed on upgrade, leading to storage collision
Critical fields like bursary
(accumulated USDC) may map to a student’s cut‑off score or teacher wage slots, enabling arbitrary transfers or lost funds.
Student scores, session flags, and teacher/ student rosters vanish or invert, halting core school operations.
Foundry
Manual Review
Delegatecall Semantics: A proxy’s delegatecall
means the implementation reads/writes the proxy’s storage.
Mismatched Definitions: Changing order, removing, or adding fields without reserving gaps shifts all downstream slots.
Silent Corruption: No compiler or runtime error—existing state is simply misinterpreted under the new layout.
If the upgrade to LevelTwo issue would be fixed, then the following test holds true:
Either have LevelTwo
inherit LevelOne
so state variables preserve exact slot positions, like this:
Or use blank storage variables in order to align storage state.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.