Raisebox Faucet

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

Claims blocked indefinitely when daily Faucet claim limit reached

Root + Impact / Claims blocked indefinitely when daily Faucet claim limit reached

Description

  • When the RaiseBoxFaucet::dailyClaimLimit is reached, the RaiseBoxFaucet::dailyClaimCount should reset after one day has passed, allowing users to claim again.

  • Currently, the reset of dailyClaimCount is performed only when the dailyClaimLimit has not been reached and 24 hours have passed since the last update of lastFaucetDripDay. This logic prevents the count from ever resetting once the limit is reached, effectively blocking further claims indefinitely.

function claimFaucetTokens() public {
...
@> if (dailyClaimCount >= dailyClaimLimit) {
revert RaiseBoxFaucet_DailyClaimLimitReached();
}
...
@> if (block.timestamp > lastFaucetDripDay + 1 days) {
lastFaucetDripDay = block.timestamp;
dailyClaimCount = 0;
}

Risk

Likelihood:

  • The issue occurs the first time the dailyClaimLimit is reached.

Impact:

  • The protocol fails to reset the dailyClaimCount, permanently halting all future claims. This makes the faucet non-operational and prevents users from claiming tokens as intended.

Proof of Concept

Add the following test to RaiseBoxFaucet.t.sol to reproduce the issue:

function test_audit_claimsBlockedIndefinitelyWhenDailyFaucetClaimLimitReached()
public
{
vm.prank(owner);
// Current limit is 100, reduce it to 1
raiseBoxFaucet.adjustDailyClaimLimit(99, false);
vm.prank(user1);
raiseBoxFaucet.claimFaucetTokens();
// Expected revert
vm.prank(user2);
vm.expectRevert(
RaiseBoxFaucet.RaiseBoxFaucet_DailyClaimLimitReached.selector
);
raiseBoxFaucet.claimFaucetTokens();
// After 3 days
advanceBlockTime(block.timestamp + 3 days);
// Not expected revert - the Faucet box is stacked
vm.prank(user3);
vm.expectRevert(
RaiseBoxFaucet.RaiseBoxFaucet_DailyClaimLimitReached.selector
);
raiseBoxFaucet.claimFaucetTokens();
}

Recommended Mitigation

  • Under RaiseBoxFaucet::claimFaucetTokens move the reset functionality to occur before checking whether the limit has been reached. It is good idea to reset Faucet and ETH all together in order to be consistent. This ensures the reset happens correctly after the 24-hour period, regardless of the previous day’s claim activity.

function claimFaucetTokens() public {
// Checks
faucetClaimer = msg.sender;
+ // Use same variable lastDripDay for both - ETH and Faucet token to simplify and make sure they are in sync
+ if (block.timestamp > lastDripDay + 1 days) {
+ lastDripDay = block.timestamp;
+ dailyClaimCount = 0; // Faucet token
+ dailyDrips = 0; // ETH
+ }
if (!hasClaimedEth[faucetClaimer] && !sepEthDripsPaused) {
- uint256 currentDay = block.timestamp / 24 hours;
- if (currentDay > lastDripDay) {
- lastDripDay = currentDay;
- dailyDrips = 0;
- // dailyClaimCount = 0;
- }
- if (block.timestamp > lastFaucetDripDay + 1 days) {
- lastFaucetDripDay = block.timestamp;
- dailyClaimCount = 0;
- }
// Effects
Updates

Lead Judging Commences

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

dailyClaimCount Reset Bug

Support

FAQs

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