Raisebox Faucet

First Flight #50
Beginner FriendlySolidity
100 EXP
Submission Details
Impact: high
Likelihood: high

Permanent Daily-Limit DoS When No User Triggers 24-h Reset

Author Revealed upon completion

Root + Impact ****

Description

  • The faucet is expected to reset its daily claim counter every 24 hours so that users can claim again once a new day starts.

  • The daily counter (dailyClaimCount) is only reset if someone calls the function after lastFaucetDripDay + 1 days. If no transaction triggers the reset (e.g., low traffic, bot suppression, or intentional boycott), the count remains at dailyClaimLimit and all future claims revert, causing a permanent denial-of-service.

// @> Reset only happens inside claimFaucetTokens() and only when the caller lands after +1 days
if (block.timestamp > lastFaucetDripDay + 1 days) {
lastFaucetDripDay = block.timestamp;
dailyClaimCount = 0;
}

Risk

Likelihood:

  • Reason 1: Occurs naturally on low-activity chains or weekends when no user interacts with the faucet for 24 h.

  • Reason 2: A malicious actor can intentionally fill the daily quota at 23:59 UTC and then front-run any reset attempt the next day, locking the limit again.

Impact:

  • Impact 1: Complete DoS for every user until an altruistic caller successfully mines a transaction strictly after the 24-hour window.

  • Impact 2: Reputation damage and support-ticket overhead as users perceive the faucet as “broken”.

Proof of Concept

// Assume dailyClaimLimit = 100
contract LockBot {
function lock(RaiseBoxFaucet faucet) external {
// fill quota at the end of day 0
for (uint i = 0; i < 100; i++) {
faucet.claimFaucetTokens{gas: 120000}();
}
// from now on any call on day 1 will revert until somebody
// manages to mine a tx strictly > lastFaucetDripDay + 1 days
}
}

Recommended Mitigation

+ function _rollDay() internal {
+ uint256 today = block.timestamp / 1 days;
+ if (today > lastFaucetDripDay) {
+ lastFaucetDripDay = today;
+ dailyClaimCount = 0;
+ }
+ }
function claimFaucetTokens() public nonReentrant {
+ _rollDay(); // @> always execute at the very beginning
...
}

Support

FAQs

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