SNARKeling Treasure Hunt

First Flight #59
Beginner FriendlyGameFiFoundry
100 EXP
Submission Details
Impact: medium
Likelihood: high

(MEDIUM) `recipient == msg.sender` is rejected, forcing legitimate finders to use a second wallet or relayer with no added security.

Author Revealed upon completion

Location: contracts/src/TreasureHunt.sol:86

Description

The claim function explicitly rejects recipient == msg.sender:

if (recipient == address(0) || recipient == address(this) || recipient == owner || recipient == msg.sender) revert InvalidRecipient();

The protocol already binds the proof to the recipient as a public input, which prevents front-running. Blocking recipient == msg.sender does not add any security property: a finder who wants to pay themselves can simply create a second EOA, use that as the submitter, and sidestep the check. The net effect is worse UX.

Risk (M)

Likelihood: High. Every legitimate single-wallet user hits this restriction on their first attempt.

Impact: Low. No fund loss; the friction pushes users toward relayers or second wallets.

Proof of Concept

function test_SelfClaimReverts() public {
(bytes memory proof, bytes32 treasureHash, address payable recipient) = _loadFixture();
// Pretend msg.sender == recipient (the natural way to self-claim).
vm.expectRevert(TreasureHunt.InvalidRecipient.selector);
vm.prank(recipient);
hunt.claim(proof, treasureHash, recipient);
}

Run:

forge test --match-test test_SelfClaimReverts -vv

The test passes, confirming the revert.

Recommended Mitigation

Remove the recipient == msg.sender

- if (recipient == address(0) || recipient == address(this) || recipient == owner || recipient == msg.sender) revert InvalidRecipient();
+ if (recipient == address(0) || recipient == address(this) || recipient == owner) revert InvalidRecipient();

Support

FAQs

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

Give us feedback!