Raisebox Faucet

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

Missing Event Emission for Critical State Changes

Author Revealed upon completion

Root + Impact

Description:

Expected Behavior:

Every critical state change such as minting, burning, or adjusting limits should emit an event to enhance transparency and support off-chain monitoring.

Actual Behavior:

Functions like burnFaucetTokens() and adjustDailyClaimLimit() modify significant contract states without emitting events when decreasing limits or burning tokens. This makes it harder for frontends or monitoring systems to detect these important state transitions.

// Root cause in the codebase with @> marks to highlight the relevant section
function burnFaucetTokens(uint256 amountToBurn) public onlyOwner {
require(amountToBurn <= balanceOf(address(this)), "Faucet Token Balance: Insufficient");
// transfer faucet balance to owner first before burning
// ensures owner has a balance before _burn (owner only function) can be called successfully
@> _transfer(address(this), msg.sender, balanceOf(address(this)));
@> _burn(msg.sender, amountToBurn); // No event emitted here to signal burn
}
function adjustDailyClaimLimit(uint256 by, bool increaseClaimLimit) public onlyOwner {
if (increaseClaimLimit) {
@> dailyClaimLimit += by; // No event emitted for updated limit
} else {
if (by > dailyClaimLimit) {
revert RaiseBoxFaucet_CurrentClaimLimitIsLessThanBy();
}
@> dailyClaimLimit -= by; // Also missing event emission
}
}

Risk

Likelihood

Medium:The functions are not called often, but when they are, missing logs can lead to data inconsistencies and audit difficulties.


Impact

1.Reduces transparency and traceability of token supply and configuration changes.

2.Frontend dashboards may display outdated information.

3.Off-chain monitoring systems (e.g., alert bots) won’t know when claim limits or faucet tokens change.



Proof of Concept

Explanation:

This PoC shows that vm.expectEmit() does not detect any events when the functions are called, proving event emissions are missing.

pragma solidity ^0.8.30;
import "forge-std/Test.sol";
import "../src/RaiseBoxFaucet.sol";
contract EventTest is Test {
RaiseBoxFaucet faucet;
function setUp() public {
faucet = new RaiseBoxFaucet("RaiseBox", "RBF", 100 ether, 0.01 ether, 1 ether);
}
function testMissingEvents() public {
// Expect no events to be emitted
vm.expectEmit(false, false, false, false);
faucet.burnFaucetTokens(10 ether);
// Expect no events for claim limit changes
faucet.adjustDailyClaimLimit(5, true);
}
}

Recommended Mitigation

Explanation

FaucetTokensBurned logs every burn operation, providing visibility into supply reductions.

DailyClaimLimitAdjusted notifies external systems whenever the faucet’s claim rate changes.

This fix follows best-practice observability patterns: every critical change must be auditable through events.

- remove this code
+ add this code
function burnFaucetTokens(uint256 amountToBurn) public onlyOwner {
require(amountToBurn <= balanceOf(address(this)), "Faucet Token Balance: Insufficient");
_transfer(address(this), msg.sender, balanceOf(address(this)));
_burn(msg.sender, amountToBurn);
- // no event emitted
+ emit FaucetTokensBurned(msg.sender, amountToBurn);
}
function adjustDailyClaimLimit(uint256 by, bool increaseClaimLimit) public onlyOwner {
if (increaseClaimLimit) {
dailyClaimLimit += by;
} else {
if (by > dailyClaimLimit) {
revert RaiseBoxFaucet_CurrentClaimLimitIsLessThanBy();
}
dailyClaimLimit -= by;
}
- // missing event notification
+ emit DailyClaimLimitAdjusted(dailyClaimLimit);
}
+event FaucetTokensBurned(address indexed burner, uint256 amount);
+event DailyClaimLimitAdjusted(uint256 newLimit);

Support

FAQs

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