Raisebox Faucet

First Flight #50
Beginner FriendlySolidity
100 EXP
View results
Submission Details
Impact: high
Likelihood: medium
Invalid

Potential Unintended Pause of Faucet by Setting Daily Claim Limit to Zero in `RaiseBoxFaucet::adjustDailyClaimLimit`

Root + Impact

Description

The adjustDailyClaimLimit function modifies the dailyClaimLimit state variable, which controls the maximum number of daily claims allowed in claimFaucetTokens. When decreasing the limit (increaseClaimLimit = false), the function checks if (by > dailyClaimLimit) and reverts with RaiseBoxFaucet_CurrentClaimLimitIsLessThanBy if true, preventing underflow. However, if by == dailyClaimLimit, the check evaluates to false, allowing the subtraction dailyClaimLimit -= by to set the value to zero.

This zero value causes subsequent calls to claimFaucetTokens to immediately revert with RaiseBoxFaucet_DailyClaimLimitReached (since dailyClaimCount >= 0 is always true at the start of a new day), pausing the faucet without any explicit warning or separate error. While this might be intentional for administrative pausing, it risks accidental misuse, as the function does not distinguish between reducing to a positive value and fully disabling claims.

// @> Root cause in the codebase
function adjustDailyClaimLimit(uint256 by, bool increaseClaimLimit) public onlyOwner {
if (increaseClaimLimit) {
dailyClaimLimit += by;
} else {
// @> Check allows by == dailyClaimLimit, leading to zero without revert
if (by > dailyClaimLimit) {
revert RaiseBoxFaucet_CurrentClaimLimitIsLessThanBy();
}
dailyClaimLimit -= by;
}
}

Risk

Likelihood:

  • Medium: Owners may intentionally set to zero for maintenance, but accidental equality (e.g., via misread values or automated scripts) is plausible, especially without events for tracking.

  • The lack of a dedicated "pause" mechanism elsewhere increases the chance of relying on this edge case unintentionally.

Impact:

  • High: Setting to zero halts all claims, blocking users from receiving faucet tokens and first-time Sepolia ETH drips, which could frustrate testnet users relying on the faucet for gas fees.

  • No immediate on-chain indication (e.g., event or separate revert) means off-chain monitoring might miss the pause, leading to delayed recovery and poor UX.

Proof of Concept

The following Foundry test demonstrates the issue: Adjusting the limit to zero succeeds without revert, but subsequent claims revert due to the zero limit. This confirms the silent pause and its effect on claimFaucetTokens.

Add the following to the RaiseBoxFaucetTest.t.sol test:

Proof of Code
/// @notice Tests that adjusting daily claim limit to zero triggers the correct revert in claimFaucetTokens
function testAdjustDailyClaimLimitAndClaimReversion() public {
// Arrange: Set up the test conditions
// Ensure the owner is calling the function
vm.startPrank(owner);
// Get the current daily claim limit
uint256 initialLimit = raiseBoxFaucet.dailyClaimLimit();
// Act: Reduce dailyClaimLimit to 0
raiseBoxFaucet.adjustDailyClaimLimit(initialLimit, false);
// Assert: Verify that dailyClaimLimit is now 0
assertEq(raiseBoxFaucet.dailyClaimLimit(), 0, "Daily claim limit should be 0 after adjustment");
// Stop owner prank and switch to a user
vm.stopPrank();
// Arrange: Start a prank as a user
vm.startPrank(user1);
// Act & Assert: Expect revert when claiming tokens with zero limit
vm.expectRevert(RaiseBoxFaucet.RaiseBoxFaucet_DailyClaimLimitReached.selector);
raiseBoxFaucet.claimFaucetTokens();
vm.stopPrank();
}

Explanation

  • Setup: The test starts with the owner (vm.startPrank(owner)) and retrieves the initial dailyClaimLimit (assumed non-zero from deployment, e.g., 100).

  • Issue Demonstration: Calling adjustDailyClaimLimit(initialLimit, false) sets the limit to 0 without reverting, verified by assertEq.

  • Result: Switching to a user (vm.startPrank(user1)) and attempting claimFaucetTokens reverts with RaiseBoxFaucet_DailyClaimLimitReached, confirming the faucet is paused.

  • The test passes, proving the edge case allows silent zeroing and blocks claims, highlighting the risk of unintended pauses.

Recommended Mitigation

Modify the check to use >= to prevent setting the limit to zero, forcing a revert in the equality case and encouraging explicit pausing via other means if needed.

function adjustDailyClaimLimit(uint256 by, bool increaseClaimLimit) public onlyOwner {
if (increaseClaimLimit) {
dailyClaimLimit += by;
} else {
- if (by > dailyClaimLimit) {
+ if (by >= dailyClaimLimit) { // Prevent zeroing or underflow
revert RaiseBoxFaucet_CurrentClaimLimitIsLessThanBy();
}
dailyClaimLimit -= by;
}
}
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 8 days ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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