Raisebox Faucet

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

`RaiseBoxFaucet::claimFaucetTokens` does not reset `dailyClaimCount` after the daily limit

RaiseBoxFaucet::claimFaucetTokens does not reset dailyClaimCount after the daily limit

Description

The function should reset dailyClaimCount when 24 hours have passed (block.timestamp > lastFaucetDripDay + 1 days) so the faucet can accept new claims.

But the limit check (dailyClaimCount >= dailyClaimLimit) is done before the reset. When the counter reaches the limit, the function immediately reverts and the logic to reset dailyClaimCount never executes. From then on, no claim can ever succeed.

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

Risk

Likelihood: High

  • The faucet is designed to hit the limit every day, so the bug appears in normal use.

  • Any extra claim after the limit triggers the revert and prevents the reset from executing.

Impact: High

  • Once the limit is reached, the faucet is blocked indefinitely and no one can claim tokens.

  • Operations and onboarding are halted until a new version is deployed.

Proof of Concept

  1. Leave dailyClaimLimit at its default value (100). 100 different accounts claim consecutively until the limit is reached.

  2. Save the initial block.timestamp before starting to demonstrate the passing of a natural day.

  3. When the 100th claim exhausts the limit, advance time to start + 1 days + 1.

  4. Another account claims and sees it still reverts with RaiseBoxFaucet_DailyClaimLimitReached because the reset never executed.

function test_DailyClaimLimitNeverResets() public {
uint256 start = block.timestamp;
for (uint256 i = 1; i < 101; i++) {
address user = address(uint160(uint256(bytes32(keccak256(abi.encode(i))))));
vm.prank(user);
raiseBoxFaucet.claimFaucetTokens();
if (i == 100) {
vm.warp(start + 1 days + 1);
vm.prank(user1);
vm.expectRevert(RaiseBoxFaucet.RaiseBoxFaucet_DailyClaimLimitReached.selector);
raiseBoxFaucet.claimFaucetTokens();
}
}
}
Ran 1 test for test/RaiseBoxFaucet.t.sol:TestRaiseBoxFaucet
[PASS] test_DailyClaimLimitNeverResets() (gas: 11332935)
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 31.25ms (12.83ms CPU time)

Recommended Mitigation

Execute the reset before checking the limit or extract it to a reusable helper.

function claimFaucetTokens() public {
...
if (balanceOf(address(this)) <= faucetDrip) {
revert RaiseBoxFaucet_InsufficientContractBalance();
}
+ if (block.timestamp > lastFaucetDripDay + 1 days) {
+ lastFaucetDripDay = block.timestamp;
+ dailyClaimCount = 0;
+ }
if (dailyClaimCount >= dailyClaimLimit) {
revert RaiseBoxFaucet_DailyClaimLimitReached();
}
....
} else {
dailyDrips = 0;
}
- if (block.timestamp > lastFaucetDripDay + 1 days) {
- lastFaucetDripDay = block.timestamp;
- dailyClaimCount = 0;
- }
lastClaimTime[faucetClaimer] = block.timestamp;
dailyClaimCount++;
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 7 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.