The faucet allows first-time users to receive an amount of Sepolia ETH equal to the sepEthAmountToDrip variable. This is regulated by the dailyDrips variable which tracks cumulative ETH distributed and enforces the daily cap. Every 24 hours, the dailyDrips variable is reset to 0, allowing new ETH distributions up to the daily cap. Users who have already claimed ETH (hasClaimedEth[user] == true) are not eligible for additional ETH distributions.
Line 212 of the RaiseBoxFaucet.sol contract will reset the dailyDrips to 0 if hasClaimedEth[faucetClaimer] == true or sepEthDripsPaused == true. This creates a scenario where the contract will continue distributing Sepolia ETH beyond the intended cap set by dailySepEthCap. If the dailyClaimLimit is sufficiently high, then the contract could be drained of its entire ETH balance via an orchestrated attack where previously-claimed users periodically reset the counter while new users claim ETH.
Likelihood:
The higher the dailyClaimLimit is set the more likely a user will exploit this vulnerability.
The claimFaucetTokens function is a public function increasing the likelihood of this exploit.
Impact:
The magnitude of the exploit is bottlenecked by the dailyClaimLimit. If the dailyClaimLimit is sufficiently high the entire balance of Sepolia ETH can be drained from the contract.
Each time a previous user calls the claimFaucetTokens function the dailyDrips variable will be reset to 0 before the 24 hour period has elapsed.
Phase 1: Legitimate Claims
Creates 200 new users (user10 to user209)
Each user makes their first claim, receiving 0.005 ETH
dailyDrips accumulates to 200 × 0.005 ETH = 1 ETH (hitting the daily cap)
All users now have hasClaimedEth[user] = true
Phase 2: The Exploit
The Exploit Mechanism:
Creates 1800 new users (user211 to user2010)
Each new user claims tokens - but since dailyDrips is at the cap (1 ETH), they don't receive ETH
Every 100 iterations (at positions 99, 199, 299, etc.):
Uses a user from Phase 1 (who has hasClaimedEth[user] = true)
This triggers the else block in the contract (lines 225-228)
Resets dailyDrips to 0
Now the next 100 new users can claim ETH again
Attack Pattern:
Iterations 211-310: 100 new users claim, no ETH (cap reached)
Iteration 310: user10 (from Phase 1) claims → dailyDrips = 0
Iterations 311-410: 100 new users claim, each gets 0.005 ETH
Iteration 410: user11 claims → dailyDrips = 0
Iterations 411-510: 100 new users claim, each gets 0.005 ETH
Pattern repeats until contract is drained
The exploit works because users who have already claimed ETH can reset the daily counter by making additional claims, allowing unlimited ETH distribution beyond the intended daily cap. This transforms a rate-limited faucet into a drainable contract.
Add this test into RaiseBoxFaucet.t.sol . Initialize the third parameter of raiseBoxFaucet with 1 ether, and run using forge test --match-test testDailyDripResetExploit -vvv
Remove the else block that resets the dailyDrips to 0.
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.