Hawk High

First Flight #39
Beginner FriendlySolidity
100 EXP
View results
Submission Details
Impact: high
Likelihood: high
Invalid

Storage layout inconsistency between implementations causes data corruption

Description:

There is a critical inconsistency in the storage layout between LevelOne and LevelTwo contracts. While both contracts declare similar state variables, their order and slot assignments differ, which will cause data corruption after an upgrade.

In LevelOne:

address principal; // slot0
bool inSession; // slot0
uint256 schoolFees; // slot1
uint256 public immutable reviewTime = 1 weeks;
uint256 public sessionEnd; // slot2
uint256 public bursary; // slot3
uint256 public cutOffScore; // slot4
mapping(address => bool) public isTeacher; // slot5
mapping(address => bool) public isStudent; // slot6
mapping(address => uint256) public studentScore; // slot7
mapping(address => uint256) private reviewCount; // slot8
mapping(address => uint256) private lastReviewTime; // slot9
address[] listOfStudents; // slot10
address[] listOfTeachers; // slot11
IERC20 usdc; // slot12

In LevelTwo:

address principal; // slot0
bool inSession; // slot0
uint256 public sessionEnd; // slot1
uint256 public bursary; // slot2
uint256 public cutOffScore; // slot3
mapping(address => bool) public isTeacher; // slot4
mapping(address => bool) public isStudent; // slot5
mapping(address => uint256) public studentScore; // slot6
address[] listOfStudents; // slot7
address[] listOfTeachers; // slot8
IERC20 usdc; // slot9

Key differences:

  1. LevelOne has schoolFees in slot1, while LevelTwo has sessionEnd in slot1

  2. The slots for all subsequent variables are shifted

  3. LevelTwo is missing reviewCount and lastReviewTime mappings

  4. Array slots are different: listOfStudents is slot10 in LevelOne but slot7 in LevelTwo

Attack path:

  1. The school operates using LevelOne with data stored in specific storage slots

  2. When upgraded to LevelTwo, the proxy's storage remains unchanged

  3. LevelTwo tries to access variables using its own storage layout

  4. This causes data to be read from incorrect slots:

    • sessionEnd in LevelTwo reads from schoolFees in LevelOne

    • bursary in LevelTwo reads from sessionEnd in LevelOne

    • All mappings and arrays are completely misaligned


Impact:

  • Complete data corruption after upgrade

  • Student and teacher records become inaccessible or corrupted

  • Financial data (bursary) is misinterpreted

  • The graduate() function in LevelTwo would operate on corrupted data

  • Students may lose their academic records and status

  • The entire school system becomes non-functional after upgrade

Recommended Mitigation:

Ensure storage layout compatibility between implementations by maintaining the same variable order and types

Updates

Lead Judging Commences

yeahchibyke Lead Judge 19 days ago
Submission Judgement Published
Invalidated
Reason: Lack of quality

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.