Santa's List

AI First Flight #3
Beginner FriendlyFoundry
EXP
View results
Submission Details
Impact: high
Likelihood: low
Invalid

Missing Event Emissions for Critical State Changes

Root + Impact

Description

  • The collectPresent and buyPresent functions perform critical state changes including minting NFTs and burning tokens, but neither emits custom events to track these operations.

  • While the inherited ERC721 and ERC20 contracts emit Transfer events, there are no application-specific events that capture the business logic context such as which user collected a present, whether they received bonus tokens, or who purchased a present for whom.

  • This makes off-chain monitoring, analytics, and incident response significantly more difficult.

// Root cause in the codebase with @> marks to highlight the relevant section
function collectPresent() external {
// ... checks and state changes ...
_mintAndIncrement();
if (status == Status.EXTRA_NICE) {
i_santaToken.mint(msg.sender);
}
@> // No event emitted for present collection
}
function buyPresent(address presentReceiver) external {
i_santaToken.burn(presentReceiver);
_mintAndIncrement();
@> // No event emitted for present purchase
}

Risk

Likelihood: High

  • Reason 1 // Every collection and purchase lacks application-level events

  • Reason 2 // Guaranteed to affect all users of the protocol

Impact: Low

  • Off-chain indexers cannot easily track present collections

  • Analytics dashboards require complex ERC721/ERC20 event parsing

  • Incident response and forensics become more difficult

  • Frontend applications cannot efficiently subscribe to protocol-specific events

  • Audit trails for EXTRA_NICE bonus distributions are incomplete

Proof of Concept

The following test demonstrates that no protocol-specific events are emitted during present collection, making it impossible to distinguish business logic operations from regular token transfers.

function test_MissingEvents() public {
vm.startPrank(santa);
santasList.checkList(user, SantasList.Status.EXTRA_NICE);
santasList.checkTwice(user, SantasList.Status.EXTRA_NICE);
vm.stopPrank();
vm.warp(santasList.CHRISTMAS_2023_BLOCK_TIME() + 1);
vm.prank(user);
santasList.collectPresent();
// No way to verify via events:
// 1. That this was a collectPresent() vs regular transfer
// 2. That user was EXTRA_NICE vs NICE
// 3. That bonus tokens were distributed
// Only inherited ERC721 Transfer(address(0), user, tokenId) exists
assertEq(santasList.balanceOf(user), 1);
assertEq(santaToken.balanceOf(user), 1e18);
}

Recommended Mitigation

Add descriptive events for all critical protocol operations to enable proper off-chain tracking and monitoring.

+ event PresentCollected(address indexed recipient, uint256 indexed tokenId, Status status);
+ event PresentPurchased(address indexed buyer, address indexed recipient, uint256 indexed tokenId);
function collectPresent() external {
// ... existing logic ...
+ uint256 tokenId = s_tokenCounter;
_mintAndIncrement();
if (status == Status.EXTRA_NICE) {
i_santaToken.mint(msg.sender);
}
+ emit PresentCollected(msg.sender, tokenId, status);
}
function buyPresent(address presentReceiver) external {
+ uint256 tokenId = s_tokenCounter;
i_santaToken.burn(msg.sender); // Also fix the burn address
_mintAndIncrement();
+ emit PresentPurchased(msg.sender, presentReceiver, tokenId);
}
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 20 hours ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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

Give us feedback!