Hawk High

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

Role State Persistence After Upgrade

Summary

The graduateAndUpgrade function in the LevelOne contract fails to reset role-related state variables (isStudent, isTeacher, listOfStudents, and listOfTeachers) before upgrading to LevelTwo. This allows legacy role assignments and lists to persist in storage, corrupting access control and data integrity in LevelTwo.

Vulnerability Details

In UUPS upgradeable contracts, storage slots retain their values unless explicitly cleared. The graduateAndUpgrade function upgrades to LevelTwo without resetting:

  1. Role Mappings: isStudent and isTeacher retain their boolean flags.

  2. Role Arrays: listOfStudents and listOfTeachers preserve old addresses.

Code Reference:

// LevelOne.sol (No reset of roles/arrays)
function graduateAndUpgrade(address _levelTwo, bytes memory) public onlyPrincipal {
// Transfers funds but does NOT clear roles or lists
_authorizeUpgrade(_levelTwo);
}

LevelTwo inherits these variables but lacks logic to handle stale data:

// LevelTwo.sol (Partial Snippet)
mapping(address => bool) public isStudent; // Inherits LevelOne's values
mapping(address => bool) public isTeacher; // Inherits LevelOne's values
address[] listOfStudents; // Retains LevelOne's array entries

Impact

  1. Unauthorized Access: Expelled students or removed teachers from LevelOne retain access to LevelTwo functions.

  2. Data Pollution: Obsolete students/teachers appear in LevelTwo’s lists, breaking UI/UX and internal logic (e.g., rewards distribution).

Tools Used

Manual review

Recommendations

Modify graduateAndUpgrade to reset role states before upgrading:

function graduateAndUpgrade(address _levelTwo, bytes memory) public onlyPrincipal {
// Reset role mappings
for (uint256 i = 0; i < listOfStudents.length; i++) {
isStudent[listOfStudents[i]] = false;
}
for (uint256 i = 0; i < listOfTeachers.length; i++) {
isTeacher[listOfTeachers[i]] = false;
}
// Clear arrays
delete listOfStudents;
delete listOfTeachers;
_authorizeUpgrade(_levelTwo);
// Rest of logic...
}
Updates

Lead Judging Commences

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

cut-off criteria not applied

All students are graduated when the graduation function is called as the cut-off criteria is not applied.

storage collision

Support

FAQs

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