There is a severe memory slot layout inconsistency between the LevelOne and LevelTwo contracts during the upgrade process. The LevelTwo contract is missing several critical state variables that exist in the LevelOne contract, which will cause state variable misalignment after contract upgrade, leading to data reading errors and potential fund loss.
By comparing the state variable layouts of LevelOne.sol and LevelTwo.sol, we discovered that the LevelTwo contract is missing the following variables that exist in LevelOne:
uint256 schoolFees;
uint256 public immutable reviewTime = 1 weeks;
mapping(address => uint256) private reviewCount;
mapping(address => uint256) private lastReviewTime;
The contract uses the UUPS upgradeable proxy pattern for upgrades, but this pattern requires maintaining consistent state variable layouts in the upgraded contract, or it will lead to incorrect interpretation of state data.
In LevelOne.sol, state variables are stored in the following memory slots in order:
Whereas in LevelTwo.sol, the state variable order is:
When the LevelOne contract is upgraded to the LevelTwo contract through the graduateAndUpgrade function, it will result in the following serious consequences:
The sessionEnd variable will read the original value of schoolFees, causing errors in the session end time.
The bursary variable will read the original value of reviewTime (if it weren't immutable), potentially causing errors in fund allocation calculations.
All subsequent variables will be misread, including the critical cutOffScore and teacher/student identity and score mappings.
The reviewCount and lastReviewTime mapping data will be completely lost and inaccessible after the upgrade.
These issues may lead to:
Complete failure of contract business logic
Incorrect fund allocation calculations
Confusion in teacher and student identity information
Failure of the student scoring system
Manual code review
Add the missing variables to the LevelTwo contract to ensure that the state variable layout remains consistent with the LevelOne contract:
Even if the LevelTwo contract doesn't use these variables, they must be retained to maintain storage layout consistency. If you want to remove these variables, you must use placeholder variables to ensure that storage slots are not offset.
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.