Hawk High

First Flight #39
Beginner FriendlySolidity
100 EXP
View results
Submission Details
Impact: medium
Likelihood: low
Invalid

Loop-Based Teacher Payout (External Call in Loop + Denial-of-Service)

Description: In LevelOne::graduateAndUpgrade, the contract iterates over 'listOfTeachers' and calls 'usdc.safeTransfer(teacher, payPerTeacher)' in a single loop. Each transfer is an external call: if any teacher's address reverts (e.g. a malicious contract or a frozen account) or if the loop runs out of gas due to a large list, the entire graduation operation will revert. This blocks payouts for all teachers and the principal, and can permanently lock funds in the contract.

Impact:

  • A single malicious or misbehaving teacher can deny service to all other participants, preventing graduation and locking up the bursary.

  • If the teacher list grows too large, the loop may consume more gas than the block limit, causing out-of-gas reverts and effectively a DoS.

  • The principal cannot complete graduation, so neither teachers nor students can progress or be paid.

Recommended Mitigation: Use the pull-payment pattern instead of pushing payments in a loop. Record each teacher’s owed amount in a mapping and allow them to withdraw asynchronously:

contract LevelOne {
+ mapping(address => uint256) public pendingTeacherWithdrawals;
function graduateAndUpgrade(address _levelTwo, bytes memory data) public onlyPrincipal {
for (uint i = 0; i < listOfTeachers.length; i++) {
- usdc.safeTransfer(listOfTeachers[i], payPerTeacher);
+ pendingTeacherWithdrawals[listOfTeachers[i]] += payPerTeacher;
}
}
+ // Withdraw teacher wages
+ function withdrawTeacherWages() external {
+ uint256 amount = pendingTeacherWithdrawals[msg.sender];
+ require(amount > 0, "No funds to withdraw");
+ pendingTeacherWithdrawals[msg.sender] = 0;
+ usdc.safeTransfer(msg.sender, amount);
+ }
}
Updates

Lead Judging Commences

yeahchibyke Lead Judge 2 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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