Raisebox Faucet

First Flight #50
Beginner FriendlySolidity
100 EXP
View results
Submission Details
Severity: high
Valid

Daily ETH cap can be bypassed

Root + Impact

Description

  • Normal behaviour: dailyDrips should represent the total ETH dripped for the current day and must not be reset arbitrarily

  • Problem: In claimFaucetTokens(), there is an else branch that sets dailyDrips = 0 whenever the top-level if (!hasClaimedEth[faucetClaimer] && !sepEthDripsPaused) condition is false. That means every call by an address that has already claimed (or when drips are paused) resets dailyDrips to zero — allowing the daily cap to be reset by arbitrary users and enabling attackers to force multiple users to receive ETH beyond the daily cap.

// Root cause with @> marks
...
if (!hasClaimedEth[faucetClaimer] && !sepEthDripsPaused) {
uint256 currentDay = block.timestamp / 24 hours;
if (currentDay > lastDripDay) {
lastDripDay = currentDay;
dailyDrips = 0;
}
if (dailyDrips + sepEthAmountToDrip <= dailySepEthCap && address(this).balance >= sepEthAmountToDrip) {
hasClaimedEth[faucetClaimer] = true;
dailyDrips += sepEthAmountToDrip;
(bool success,) = faucetClaimer.call{value: sepEthAmountToDrip}("");
...
} else {
emit SepEthDripSkipped(...);
}
} else {
// @> This resets running dailyDrips to 0 for non-first-time claimers
dailyDrips = 0;
}
...

Risk

Likelihood:

  • Any user who calls claimFaucetTokens() after already having hasClaimedEth set (or when sepEthDripsPaused is true) will reset dailyDrips to zero. An attacker can repeatedly trigger this reset to repeatedly allow others (or themselves if combined with reentrancy) to receive ETH beyond the intended dailySepEthCap.

Impact:

  • Daily ETH cap enforcement is broken — faucet ETH can be drained quickly beyond the intended daily amount.

  • Attackers can coordinate to reset and then claim to drain the faucet.

Proof of Concept

Attacker strategy:

  1. Attacker A calls claimFaucetTokens() (first time) → hasClaimedEth[A] = true.

  2. Attacker A calls claimFaucetTokens() again (no ETH will be sent because hasClaimedEth is true), but the else branch sets dailyDrips = 0.

  3. Victim B (or attacker B) then claims and receives ETH even though the daily cap should have been exhausted.

Recommended Mitigation

Remove that else { dailyDrips = 0; } and only reset dailyDrips when day changes (as currently done when currentDay > lastDripDay). dailyDrips should not be zeroed for normal non-first-time claims.

- } else {
- dailyDrips = 0;
- }
+ } // do NOT reset dailyDrips here

Also make lastDripDay and dailyDrips handling consistently using the same day metric (e.g., currentDay = block.timestamp / 1 days) and reset only when currentDay != lastDripDay.

Updates

Lead Judging Commences

inallhonesty Lead Judge 17 days ago
Submission Judgement Published
Validated
Assigned finding tags:

dailyDrips Reset Bug

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.