Summary
A reentrant risk occurs in the enroll section of the LevelOne.sol contract. This will cause losses to the users' funds.
Vulnerability Details
In the enroll method of LevelOne.sol, usdc.safeTransferFrom is the way to pay the tuition fee. However, at this time, the approach is to transfer in first and then mark, which may lead to the risk of re-entry and result in the user's funds being consumed.
function enroll() external notYetInSession {
if (isTeacher[msg.sender] || msg.sender == principal) {
revert HH__NotAllowed();
}
if (isStudent[msg.sender]) {
revert HH__StudentExists();
}
- usdc.safeTransferFrom(msg.sender, address(this), schoolFees);
listOfStudents.push(msg.sender);
isStudent[msg.sender] = true;
studentScore[msg.sender] = 100;
bursary += schoolFees;
emit Enrolled(msg.sender);
}
Impact
After the reentry risk occurs, it leads to the caller losing more funds.
Tools Used
Visual Studio Code
Recommendations
The code order should be adjusted. First, perform isStudent[msg.sender]=true, and then usdc.safeTransferFrom
function enroll() external notYetInSession {
if (isTeacher[msg.sender] || msg.sender == principal) {
revert HH__NotAllowed();
}
if (isStudent[msg.sender]) {
revert HH__StudentExists();
}
- usdc.safeTransferFrom(msg.sender, address(this), schoolFees);
+ isStudent[msg.sender] = true;
+ usdc.safeTransferFrom(msg.sender, address(this), schoolFees);
listOfStudents.push(msg.sender);
- isStudent[msg.sender] = true;
studentScore[msg.sender] = 100;
bursary += schoolFees;
emit Enrolled(msg.sender);
}