The claimFaucetTokens() function violates the Checks-Effects-Interactions (CEI) pattern by updating the lastClaimTime state variable AFTER external interactions. This allows malicious contracts to re-enter the function and claim tokens multiple times before the cooldown timestamp is recorded, completely bypassing the 3-day cooldown mechanism.
The function performs external calls via low-level .call() to transfer ETH before updating critical state variables.
When faucetClaimer is a malicious contract, its receive() or fallback() function gains control during the ETH transfer. At this point, lastClaimTime[attacker] is still 0 (for first-time claimers) or contains an old timestamp (for repeat claimers after cooldown), allowing the cooldown check to pass again in the re-entered call.
This violates CEI pattern where Effects (state updates) must happen before Interactions (external calls).
Likelihood:
High risk - The attack is trivial to execute.
Any user can deploy a contract with a receive() function that calls claimFaucetTokens() again. No special conditions or timing required.
Impact:
Cooldown bypass: Attacker claims tokens multiple times in single transaction
Token drainage: Faucet balance depleted rapidly
Economic damage: Rate-limiting completely broken
Loss of trust: Faucet becomes unusable for legitimate users
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.