Hawk High

First Flight #39
Beginner FriendlySolidity
100 EXP
View results
Submission Details
Severity: medium
Valid

Storage layout mismatch between `LevelTwo` and `LevelOne`

Description:
The LevelTwo contract is missing three storage slots: schoolFees, reviewCount, and lastReviewTime.
As a result, subsequent slots are shifted upward, leading to mismatched values when accessing storage.

Impact: Storage misalignment leads to incorrect variable reads, potentially causing broken logic or unexpected behavior in the upgraded contract.

Proof of Concept: first need to fix the LevelTwo not implementing UUPSUpgradeable issue, then add the following test

modifier studentEnrolled() {
vm.startPrank(student_1);
usdc.approve(address(levelOneProxy), schoolFees);
levelOneProxy.enroll();
vm.stopPrank();
vm.startPrank(student_2);
usdc.approve(address(levelOneProxy), schoolFees);
levelOneProxy.enroll();
vm.stopPrank();
vm.startPrank(student_3);
usdc.approve(address(levelOneProxy), schoolFees);
levelOneProxy.enroll();
vm.stopPrank();
_;
}
modifier addTeachers() {
vm.startPrank(principal);
levelOneProxy.addTeacher(teacher_1);
levelOneProxy.addTeacher(teacher_2);
vm.stopPrank();
_;
}
modifier startSession() {
vm.startPrank(principal);
levelOneProxy.startSession(cutOffScore);
vm.stopPrank();
_;
}
...
function test_storage_misalignment() public studentEnrolled addTeachers startSession {
uint256 sessionEnd = levelOneProxy.sessionEnd();
uint256 bursary = levelOneProxy.bursary();
vm.startPrank(principal);
LevelTwo levelTwo = new LevelTwo();
levelOneProxy.upgradeToAndCall(address(levelTwo), abi.encodeWithSignature("graduate()"));
vm.stopPrank();
LevelTwo levelTwoProxy = LevelTwo(address(levelOneProxy));
// misalignment of storage slots
assertEq(levelTwoProxy.bursary(), sessionEnd);
assertEq(levelTwoProxy.cutOffScore(), bursary);
}

Recommended Mitigation:
Make sure the storage layout of LevelTwo is identical to LevelOne by adding the missing variables.

+ uint256 public schoolFees;
...
+ mapping(address => uint256) public reviewCount;
...
+ mapping(address => uint256) public lastReviewTime;
...
Updates

Lead Judging Commences

yeahchibyke Lead Judge 6 months ago
Submission Judgement Published
Validated
Assigned finding tags:

storage collision

Support

FAQs

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