Raisebox Faucet

First Flight #50
Beginner FriendlySolidity
100 EXP
Submission Details
Impact: medium
Likelihood: medium

Inconsistent ETH Refill Validation

Author Revealed upon completion

Root + Impact

Description

Expected Behavior:

The refillSepEth() function should reliably top up the faucet’s ETH balance for future claims. It should validate inputs strictly and emit an event confirming the refill.

Actual Behavior:

The function currently validates msg.value against the _amountToRefill argument, but this is redundant and can cause user confusion or failure if mismatched accidentally. Additionally, there’s no mechanism to handle overpayment, underpayment, or reject invalid transfers cleanly.

// Root cause in the codebase with @> marks to highlight the relevant section
function refillSepEth(uint256 amountToRefill) external payable onlyOwner {
require(amountToRefill > 0, "invalid eth amount");
@> require(msg.value == amountToRefill, "Refill amount must be same as value sent.");
emit SepEthRefilled(msg.sender, amountToRefill);
}

Risk

Likelihood

Medium :Owner-triggered, but likely to occur during manual refill operations or testing phases.

Impact

1.The function can fail even when ETH is sent correctly if the owner misinputs amount to refill.

2.The UX for the owner or scripts interacting with the contract worsens.

3.In a worst-case scenario, an invalid refill could delay faucet availability to users.

Proof of Concept

Explanation:

Even though the transaction sends 1 ETH, the call fails because amount ToRefill != msg.value, proving the redundant check breaks expected behavior.

pragma solidity ^0.8.30;
import "forge-std/Test.sol";
import "../src/RaiseBoxFaucet.sol";
contract RefillPoCTest is Test {
RaiseBoxFaucet faucet;
address owner = address(0x123);
function setUp() public {
vm.deal(owner, 5 ether);
vm.prank(owner);
faucet = new RaiseBoxFaucet("RaiseBox", "RBF", 100 ether, 0.01 ether, 1 ether);
}
function testFailRefillMismatch() public {
vm.startPrank(owner);
// Sends 1 ether but passes wrong parameter
faucet.refillSepEth{value: 1 ether}(2 ether);
vm.stopPrank();
}
}

Recommended Mitigation

Explanation


Removes the _amountToRefill parameter to avoid mismatch and simplify usage.

Relies solely on msg.value, the native and accurate ETH value indicator.

Keeps the event emission for transparency and tracking.

Improves UX, reduces call errors, and ensures seamless faucet operation.

- remove this code
+ add this code
@@
-function refillSepEth(uint256 amountToRefill) external payable onlyOwner {
- require(amountToRefill > 0, "invalid eth amount");
- require(msg.value == amountToRefill, "Refill amount must be same as value sent.");
- emit SepEthRefilled(msg.sender, amountToRefill);
-}
+function refillSepEth() external payable onlyOwner {
+ require(msg.value > 0, "invalid ETH amount");
+
+ // update faucet ETH balance by directly referencing msg.value
+ emit SepEthRefilled(msg.sender, msg.value);
+}

Support

FAQs

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