The nonReentrant modifier contains a critical implementation error where it sets a value in storage slot 0 but checks for reentrancy by reading from storage slot 1, creating a disconnect between the lock setting and checking mechanisms. This effectively renders the reentrancy protection useless.
The issue is that:
The code checks if storage slot 1 is non-zero (tload(1)) to determine if reentrancy is happening
However, it sets the lock by writing to storage slot 0 (tstore(0, 1))
After returning from the protected function, it clears the lock in storage slot 0 (tstore(0, 0))
This vulnerability completely neutralizes the reentrancy protection mechanism. Functions intended to be protected by this modifier remain fully vulnerable to reentrancy attacks, which could lead to:
Funds being drained through multiple withdrawals before balances are updated
State corruption through unexpected reentrant calls
Logic exploitation in functions that assume they cannot be reentered
Manual review
Fix the storage slot inconsistency in the nonReentrant modifier by ensuring that the same slot is used for both setting and checking the lock:
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.