Raisebox Faucet

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

Missing Event for Critical State Change in adjustDailyClaimLimit

Root + Impact

Description

  • The adjustDailyClaimLimit() function modifies the dailyClaimLimit state variable without emitting an event. This makes it difficult for off-chain services to monitor changes to this critical parameter, reducing transparency and auditability.

  • The adjustDailyClaimLimit function, which can only be called by the owner, directly modifies the dailyClaimLimit state variable but does not emit an event to signal that the change has occurred.

function adjustDailyClaimLimit(uint256 by, bool increaseClaimLimit) public onlyOwner {
if (increaseClaimLimit) {
@> dailyClaimLimit += by; // State change without event
} else {
if (by > dailyClaimLimit) {
revert RaiseBoxFaucet_CurrentClaimLimitIsLessThanBy();
}
@> dailyClaimLimit -= by; // State change without event
}
}

Risk

Likelihood:

  • An administrator invokes the adjustDailyClaimLimit() function to modify the faucet's operational parameters.

Impact:

  • Lack of Transparency: Users and monitoring tools cannot easily track changes to one of the faucet's key parameters.

  • Difficulty for Off-Chain Services: Any off-chain service that needs to react to changes in the daily claim limit would have to constantly poll the contract, which is inefficient and slow.

Proof of Concept

  • The following Foundry test demonstrates that the adjustDailyClaimLimit function does not emit an event. The test uses vm.expectEmit to check for an event, and it will fail because the contract does not emit one.

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.30;
import {Test, console} from "forge-std/Test.sol";
import {RaiseBoxFaucet} from "../src/RaiseBoxFaucet.sol";
contract MissingEventsTest is Test {
RaiseBoxFaucet faucet;
address owner;
function setUp() public {
faucet = new RaiseBoxFaucet(
"RaiseBoxToken",
"RBT",
1000 * 10**18,
0.005 ether,
0.5 ether
);
owner = faucet.owner();
}
function testMissingEventOnAdjustDailyClaimLimit() public {
// We expect an event with the old and new limit.
// This test will fail because no event is emitted by the function.
vm.expectEmit(true, true, true, true);
emit DailyClaimLimitUpdated(faucet.dailyClaimLimit(), faucet.dailyClaimLimit() + 50, true);
vm.prank(owner);
faucet.adjustDailyClaimLimit(50, true);
}
// Event definition for the test to compile against
event DailyClaimLimitUpdated(uint256 oldLimit, uint256 newLimit, bool increase);
}

Test Result: The test fails as expected, confirming the absence of the event.

[FAIL: log != expected log] testMissingEventOnAdjustDailyClaimLimit() (gas: 24052)
Suite result: FAILED. 0 passed; 1 failed; 0 skipped; finished in 5.45ms (4.58ms CPU time)

Recommended Mitigation

An event should be emitted whenever the `dailyClaimLimit` is changed. This can be done by defining a `DailyClaimLimitUpdated` event and emitting it within the `adjustDailyClaimLimit` function.
```solidity
contract RaiseBoxFaucet is ERC20, Ownable {
// ...
event DailyClaimLimitUpdated(uint256 oldLimit, uint256 newLimit, bool increased);
function adjustDailyClaimLimit(uint256 by, bool increaseClaimLimit) public onlyOwner {
uint256 oldLimit = dailyClaimLimit;
if (increaseClaimLimit) {
dailyClaimLimit += by;
} else {
if (by > dailyClaimLimit) {
revert RaiseBoxFaucet_CurrentClaimLimitIsLessThanBy();
}
dailyClaimLimit -= by;
}
emit DailyClaimLimitUpdated(oldLimit, dailyClaimLimit, increaseClaimLimit);
}
// ...
}
Updates

Lead Judging Commences

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