The claim() function follows a C-I-E-I pattern instead of the correct C-E-I pattern. The external call to verifier.verify() happens before claimsCount and claimed are updated. This means if a malicious or compromised verifier re-enters claim() during verification, the state has not yet been updated and all checks pass again. The nonReentrant modifier currently prevents this, but it is load-bearing for two independent reasons simultaneously — reentrancy protection AND replay protection (due to the broken claimed check in L-1). Removing or bypassing the guard would make the contract instantly drainable in a single transaction.
Likelihood:
Requires a malicious or compromised verifier contract
Owner is trusted, so verifier swap is unlikely to be malicious
Low likelihood under normal operation
Impact:
If nonReentrant is ever removed, a malicious verifier can reenter claim() before state updates and drain the contract in a single transaction
nonReentrant is currently carrying two separate responsibilities — removing it for any reason exposes both reentrancy and replay vectors simultaneously
Correct CEI costs nothing to implement
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.
The contest is complete and the rewards are being distributed.