Raisebox Faucet

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

No events emitted for admin actions (burnFaucetTokens and adjustDailyClaimLimit)

No events emitted for important state variable changes

Description

  • Normal behavior: owner/admin actions that change important state (dailyClaimLimit, burning faucet tokens) should emit events so off-chain monitors, UIs and auditors can detect and verify the change.

  • Specific issue: two owner-only functions update critical state but emit no events, making changes silent on-chain and reducing transparency.

// @> adjustDailyClaimLimit updates dailyClaimLimit but emits no event
function adjustDailyClaimLimit(uint256 by, bool increaseClaimLimit) public onlyOwner {
if (increaseClaimLimit) {
dailyClaimLimit += by;
} else {
if (by > dailyClaimLimit) {
revert RaiseBoxFaucet_CurrentClaimLimitIsLessThanBy();
}
dailyClaimLimit -= by;
}
// @audit no event emitted
}
// @> burnFaucetTokens transfers/burns tokens but emits no event
function burnFaucetTokens(uint256 amountToBurn) public onlyOwner {
require(amountToBurn <= balanceOf(address(this)), "Faucet Token Balance: Insufficient");
// transfer faucet balance to owner first before burning
_transfer(address(this), msg.sender, balanceOf(address(this)));
_burn(msg.sender, amountToBurn);
// @audit no event emitted
}

Risk

Likelihood: Medium

  • Owner or automated processes will call these functions during maintenance; absence of events makes those changes silent. A compromised owner key can exploit this stealth.

Impact: Low

  • Off-chain monitoring and dashboards cannot detect or alert on critical config or supply changes.

  • Silent burns/transfers can mislead users and auditors; abuse by owner or attacker with owner privileges can go unnoticed for longer.

Proof of Concept

function test_noEventsForAdjustAndBurn() public {
vm.prank(owner);
raiseBoxFaucet.adjustDailyClaimLimit(10, true);
vm.prank(owner);
raiseBoxFaucet.burnFaucetTokens(1 * 10 ** 18);
// PoC expectations:
// - dailyClaimLimit changed but no on-chain event was emitted to signal the change
// - burnFaucetTokens moved tokens and burned only `amountToBurn`, and no FaucetBurned event was emitted
//
// To verify absence of events, run this test with verbose logs and inspect the transaction logs;
// there will be no DailyClaimLimitAdjusted or FaucetBurned topics emitted.
}

Run the test with:

forge test --match-test test_noEventsForAdjustAndBurn -vvvv

Recommended Mitigation

  • burnFaucetTokens: burn from contract and emit FaucetBurned

+ event FaucetBurned(uint256 amount);
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);
+ emit FaucetBurned(amountToBurn);
}
  • adjustDailyClaimLimit: emit DailyClaimLimitAdjusted

+ event DailyClaimLimitAdjusted(uint256 newLimit);
function adjustDailyClaimLimit(uint256 by, bool increaseClaimLimit) public onlyOwner {
if (increaseClaimLimit) {
dailyClaimLimit += by;
} else {
if (by > dailyClaimLimit) {
revert RaiseBoxFaucet_CurrentClaimLimitIsLessThanBy();
}
dailyClaimLimit -= by;
}
+ emit DailyClaimLimitAdjusted(dailyClaimLimit);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 10 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.