SNARKeling Treasure Hunt

First Flight #59
Beginner FriendlyGameFiFoundry
100 EXP
View results
Submission Details
Severity: low
Valid

Claimed event emits msg.sender instead of recipient

Root + Impact: contracts/src/TreasureHunt.sol-> emit Claimed(treasureHash, msg.sender) emits the submitter instead of the reward recipient

Description

  • The reward goes to recipient but the event logs msg.sender. Off-chain indexers, explorers, and front-ends tracking reward recipients will display incorrect data.

(bool sent, ) = recipient.call{value: REWARD}("");
require(sent, "ETH_TRANSFER_FAILED");
// @> logs msg.sender but ETH was sent to recipient
// @> msg.sender == recipient is explicitly blocked, so this is always wrong
emit Claimed(treasureHash, msg.sender);

Risk

Likelihood:

  • Every successful claim() call emits the wrong address , this occurs 100% of the time since msg.sender == recipient is explicitly blocked by the InvalidRecipient check

  • Any off-chain system relying on the event receives incorrect data from the very first claim

Impact:

  • Block explorers, front-ends, and indexers display the submitter instead of the reward recipient, misleading all participants

  • Automated systems reading Claimed events to verify payouts always report the wrong recipient

Proof of Concept

1. Alice (msg.sender) calls claim(proof, treasureHash, Bob (recipient))
2. Bob receives 10 ETH
3. Event emits Claimed(treasureHash, Alice) instead of Claimed(treasureHash, Bob)
4. Any listener watching Claimed events records Alice as the reward recipient
5. Bob has no on-chain event proving he received the reward

Recommended Mitigation

- emit Claimed(treasureHash, msg.sender);
+ emit Claimed(treasureHash, recipient);
Updates

Lead Judging Commences

s3mvl4d Lead Judge 18 days ago
Submission Judgement Published
Validated
Assigned finding tags:

incorrect event parameter

The event is declared as event `Claimed(bytes32 indexed treasureHash, address indexed recipient);`, which clearly indicates that the second indexed field is meant to represent the reward recipient, but `claim()` emits `Claimed(treasureHash, msg.sender)` instead of `Claimed(treasureHash, recipient)`, even though the ETH transfer is sent to recipient and the proof itself is constructed around the public inputs (treasureHash, recipient). As a standalone finding, this is appropriately low severity because it is fundamentally an event/accounting inconsistency rather than a direct loss-of-funds issue: the core state transition and payout still follow the intended recipient, but off-chain consumers reading the event log will observe incorrect metadata about who was associated with the claim.

Support

FAQs

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

Give us feedback!