Snowman Merkle Airdrop

First Flight #42
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Impact: low
Likelihood: low
Invalid

Missing Event Emissions in Core Contract Functions

Summary

Despite defining relevant events in the contract, the earnSnow() function does not emit the SnowEarned event and the collectFee() function does not emit the FeeCollected event, reducing transparency and breaking off-chain monitoring capabilities.

Description

Events in Ethereum smart contracts serve as an important mechanism for off-chain services to track on-chain activities. The Snow contract defines several events, including SnowEarned and FeeCollected, but fails to emit these events when the corresponding actions occur:

  1. The earnSnow() function defines logic for users to earn Snow tokens but does not emit the SnowEarned event after tokens are minted.

  2. The collectFee() function allows the collector to withdraw fees from the contract but does not emit the FeeCollected event after fees are transferred.

This inconsistency between defined events and their emissions breaks the expected contract behavior and affects off-chain monitoring systems that might rely on these events for tracking purposes.

Severity Classification

Impact: Low

  • Does not directly affect on-chain functionality or token security

  • Reduces transparency and traceability of contract activities

  • Disrupts off-chain monitoring and analytics systems

  • Inconsistent with contract's declared behavior

Likelihood: High

  • Occurs consistently with every function call

  • Affects all users of these functions

  • Present in the current implementation without any conditions

File Name

src/Snow.sol

Code with Issue

function earnSnow() external canFarmSnow {
if (s_earnTimer != 0 && block.timestamp < (s_earnTimer + 1 weeks)) {
revert S__Timer();
}
_mint(msg.sender, 1);
s_earnTimer = block.timestamp;
// Missing event emission
}
function collectFee() external onlyCollector {
uint256 collection = i_weth.balanceOf(address(this));
i_weth.transfer(s_collector, collection);
(bool collected,) = payable(s_collector).call{value: address(this).balance}("");
require(collected, "Fee collection failed!!!");
// Missing event emission
}

Recommendation

Add the missing event emissions:

function earnSnow() external canFarmSnow {
if (s_userEarnTimer[msg.sender] != 0 &&
block.timestamp < (s_userEarnTimer[msg.sender] + 1 weeks)) {
revert S__Timer();
}
_mint(msg.sender, 1);
s_userEarnTimer[msg.sender] = block.timestamp;
emit SnowEarned(msg.sender, 1); // Add this line
}
function collectFee() external onlyCollector {
uint256 wethBalance = i_weth.balanceOf(address(this));
uint256 ethBalance = address(this).balance;
// Effects before interactions
emit FeeCollected(); // Add this line
// Interactions
if (wethBalance > 0) {
i_weth.safeTransfer(s_collector, wethBalance);
}
if (ethBalance > 0) {
(bool collected,) = payable(s_collector).call{value: ethBalance}("");
require(collected, "Fee collection failed!!!");
}
}

This change ensures that events are properly emitted, maintaining contract transparency and enabling effective off-chain monitoring.

Proof of Concept

function test_POC_MissingEvents() public {
console2.log("=== POC 4: Missing Event Emissions ===");
// Test missing SnowEarned event
vm.recordLogs();
vm.prank(alice);
snow.earnSnow();
Vm.Log[] memory logs = vm.getRecordedLogs();
// Look for SnowEarned event (should exist but doesn't)
bool snowEarnedEventFound = false;
for (uint i = 0; i < logs.length; i++) {
if (logs[i].topics[0] == keccak256("SnowEarned(address,uint256)")) {
snowEarnedEventFound = true;
break;
}
}
console2.log("SnowEarned event emitted:");
console2.log(snowEarnedEventFound);
console2.log("BUG: SnowEarned event should be emitted but is missing");
console2.log("IMPACT: Off-chain monitoring and integrations will not work properly");
}
Updates

Lead Judging Commences

yeahchibyke Lead Judge 3 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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