SNARKeling Treasure Hunt

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

claim() emits msg.sender as the recipient in the Claimed event instead of recipient

The Claimed event is designed to record which address received the reward for a given treasureHash. The ETH transfer correctly targets recipient, but the emitted event logs msg.sender — the address that submitted the transaction — which may be an entirely different account.

(bool sent, ) = recipient.call{value: REWARD}("");
require(sent, "ETH_TRANSFER_FAILED");
// @> ETH went to `recipient`, but the event attributes it to msg.sender
emit Claimed(treasureHash, msg.sender);

Risk

Likelihood: High

  • This fires on every successful claim. Because recipient == msg.sender is explicitly blocked by the InvalidRecipient guard, the logged address and the actual payee are always different — this is not an edge case.

Impact: Medium

  • Off-chain indexers, subgraphs, and front-ends that rely on the Claimed event to display "who received this treasure" will always show the wrong address.

  • Treasury dashboards, tax reporting tools, and leaderboard UIs will attribute payouts incorrectly.

  • Auditors reviewing logs after the fact cannot reconstruct the true payment history from events alone.

Proof of Concept

Alice (msg.sender) submits a claim, designating Bob (recipient) to receive the ETH.
treasureHunt.claim(proof, treasureHash, bob);
Bob receives 10 ETH — correct.
Event emitted: Claimed(treasureHash, alice) — incorrect.
Any listener watching for Claimed(treasureHash, bob) receives nothing.

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!