RaiseBoxFaucet::dailyDrips Reset Logic Allows Bypass of RaiseBoxFaucet::dailySepEthCap, Enabling Full Contract DrainThe RaiseBoxFaucet contract limits daily Sepolia ETH distribution via dailySepEthCap, tracked by the dailyDrips counter, which is meant to reset to 0 daily to enforce this cap.
However, it doesn't work the way we expected. Actually, the contract has implemented two ways to reset dailyDrips to 0, but one of them is flawed. It works well when a user calls RaiseBoxFaucet::claimFaucetTokens for the first time, but if he calls it again after 3 days (because of the 3-day cooldown), the dailyDrips resets to 0 due to the if-else conditions on lines 185 and 211. This means, every user who has already claimed their sepEth once will be able to reset the dailyDrips to 0, even if the limit is reached, and thus, allowing the other first-time claimants to get their sepEth too. If this happened in a repeated scenario, then the whole contract will be drained with ease.
The vulnerability can be exploited after 3 days by any user who has already claimed their Sepolia ETH once, opening the door for repeated exploitation.
Even a single malicious actor can drain the entire contract over a few days by coordinating multiple addresses to claim Sepolia ETH repeatedly.
The entire Sepolia ETH balance can be drained over repeated cycles, violating the faucet’s purpose of controlled distribution.
It can lead to reputational damage for the protocol, as users may lose trust in the contract's security and reliability.
The contract may require manual intervention from the owner to pause Sepolia ETH drips, increasing centralisation risks and operational overhead.
This PoC demonstrates how the flawed reset logic allows the contract’s Sepolia ETH to be fully drained:
Setup: The owner deploys the RaiseBoxFaucet contract and funds it with a certain amount of Sepolia ETH (e.g., 0.03 Sepolia ETH). The dailySepEthCap is set to a lower value (e.g., 0.01 Sepolia ETH) for testing purposes.
First Claims: Users 1 and 2 (first-time claimants) claim tokens and 0.005 ETH each, hitting the 0.01 ETH dailySepEthCap.
Cooldown Period: Other users decide not to claim now, as the dailyDrips has already reached the limit. They wait for 3 days, instead of 1 day.
Post-Cooldown Claims: After 3 days, user1 calls claimFaucetTokens again, resetting dailyDrips to 0 (via the flawed else block).
Further Claims: Users 3 and 4 (first-time claimants) now claim 0.005 ETH each, hitting the cap again.
Cycle Repeats: User 2, post-cooldown, resets dailyDrips again, allowing Users 5 and 6 to claim, draining the remaining balance. Thus, the contract allowed sepEth more than the limit, and if this cycle is repeated again and again, the whole contract can be drained.
Note: Either this vulnerability can be intentionally exploited by a malicious actor, where he can spin up multiple addresses to claim Sepolia ETH repeatedly, or it can happen organically if the contract has a lot of users who have already claimed once and are trying to claim again after 3 days.
Add this test case to the existing RaiseBoxFaucet.t.sol file:
Run the above test using the following command:
Logs:
Remove the flawed else block that resets dailyDrips for non-first-time claimants, as the initial reset logic (lines 187-192) correctly handles daily resets. This ensures dailyDrips only resets when a new day begins, enforcing the dailySepEthCap.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.