The LevelOne
contract only credits student tuition fees when the enroll()
function is called, which transfers USDC and increments bursary
. If someone transfers USDC directly to the proxy—bypassing enroll()
—the contract’s token balance rises, but bursary
remains unchanged. This breaks the invariant that “all collected fees are reflected in bursary
,” leading to stranded funds.
ERC-20 tokens sent by calling IERC20(usdc).transfer(address(levelOne), amount)
do increase usdc.balanceOf(levelOne)
, but because there is no hook or fallback to adjust bursary
, those tokens are never recorded or usable by any withdrawal or distribution logic.
While no attacker can withdraw those locked tokens, legitimate users or integrators may lose assets by accidentally sending fees outside the intended path. Locked funds degrade contract usability and trust. This can be considered a low issue because it does not lead to unauthorized access or direct financial loss via theft, only by misplacement.
Foundry
Manual Review
Aderyn
Because the primary fee token is USDC (ERC-20), the safest and simplest approach is to revert on any direct ERC-20 transfers. This ensures that, the user will not strand/lock their funds accidentally in the contract, and will have to call LevelOne::enroll()
.
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.