The contract implements linear searches over unbounded dynamic arrays in its removeTeacher
, expel
, and graduateAndUpgrade
functions, causing gas consumption to grow proportionally with the number of entries and ultimately exceeding Ethereum’s per‑block gas limit, resulting in irreversible reverts and denial of service. This behavior is catalogued as “Denial of Service with Block Gas Limit” and falls under DoS through unbounded operations. Because these loops can disrupt core administrative and upgrade flows without direct theft of funds, this would be categorized as a Medium finding.
Every invocation of removeTeacher
iterates through listOfTeachers
to locate and remove a teacher address, executing an O(N) search and swap on storage arrays. The expel
function mirrors this pattern on the student list and the graduateAndUpgrade
function similarly loops over teachers to distribute USDC payments in a push fashion, compounding gas costs on large cohorts. As the number of teachers or expelled students grows, these unbounded loops incrementally consume more gas until the operation surpasses the block gas limit and reverts.
Once array sizes cross the threshold where loop gas exceeds the block limit, the principal loses the ability to remove teachers, expel students, or perform payments towards himself and the teachers, effectively stranding USDC in the contract and halting protocol evolution.
Foundry
Manual Review
Aderyn
Place the following test into LevelOneAndGraduateTest.t.sol
:
Running this test will give us the following output:
We can see that gas consumption is significantly higher when removing a teacher because the function must loop through the entire array of fifty‑plus addresses. The same issue arises in the student context: expelling a non‑existent or end‑of‑array entry from a fifty‑element student list would likewise incur a very costly operation.
Consider using a mapping
for both teachers and students instead of an ever‑growing address[]
plus boolean flags, so that adding or removing an entry is just a constant‑time write or delete and lookups never scan the array.
Altenatively, you can use OpenZeppelin’s EnumerableSet
—its add/remove/contains operations remain O(1) and you only pay the cost of turning its small snapshot into an array when necessary.
Unbounded loops in teacher lists could result in high gas usage when trying to remove a teacher when teachers are plenty. This could result in a possible DoS
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.