Summary
Global variables in LevelTwo are declared in a different order than in LevelOne.
schoolFees - not present anymore
mappings reviewCount, lastReviewTime - not present anymore
Results a shift in storage slot numbers.
Vulnerability Details
The proxy’s storage will no longer map correctly to the expected locations.
Impact
Undefined behavior and contract breakage.
Can cause loss of data/funds, calling functions with wrong data, security issues and incapacity to use the contract.
Tools Used
Manual Code Review
Recommendations
Refactor LevelTwo to match LevelOne.
Ensure that all variables from LevelOne are declared at the very top level of LevelTwo, followed only by new ones.
pragma solidity 0.8.26;
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
contract LevelTwo is Initializable {
using SafeERC20 for IERC20;
address principal;
bool inSession;
uint256 schoolFees;
uint256 public immutable reviewTime = 1 weeks;
uint256 public sessionEnd;
uint256 public bursary;
uint256 public cutOffScore;
mapping(address => bool) public isTeacher;
mapping(address => bool) public isStudent;
mapping(address => uint256) public studentScore;
mapping(address => uint256) private reviewCount;
mapping(address => uint256) private lastReviewTime;
address[] listOfStudents;
address[] listOfTeachers;
uint256 public constant TEACHER_WAGE_L2 = 40;
uint256 public constant PRINCIPAL_WAGE_L2 = 5;
uint256 public constant PRECISION = 100;
IERC20 public usdc;