Snowman Merkle Airdrop

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

Third Party Claim Requires Approval, Blocking Functionality

Root + Impact

The claimSnowman() function requires pre-approved token transfers without offering alternative authorization methods, creating potential UX failures.

Description

  • Users cannot claim Snowman NFTs on behalf of others unless the Snow tokens were pre-approved

  • The transaction will always revert if the claimant forgot to call approve() first

  • No fallback mechanism exists (like EIP-2612 permit())

function claimSnowman(address receiver, bytes32[] calldata merkleProof, uint8 v, bytes32 r, bytes32 s)
external
nonReentrant
{
if (receiver == address(0)) {
revert SA__ZeroAddress();
}
if (i_snow.balanceOf(receiver) == 0) {
revert SA__ZeroAmount();
}
if (!_isValidSignature(receiver, getMessageHash(receiver), v, r, s)) {
revert SA__InvalidSignature();
}
uint256 amount = i_snow.balanceOf(receiver);
bytes32 leaf = keccak256(bytes.concat(keccak256(abi.encode(receiver, amount))));
if (!MerkleProof.verify(merkleProof, i_merkleRoot, leaf)) {
revert SA__InvalidProof();
}
@> i_snow.safeTransferFrom(receiver, address(this), amount); // send tokens to contract... akin to burning
s_hasClaimedSnowman[receiver] = true;
emit SnowmanClaimedSuccessfully(receiver, amount);
i_snowman.mintSnowman(receiver, amount);
}

Risk

Likelihood: HIGH

  • When someone else tries to claim a Snowman for a user, it will always revert if the proper approval wasn't given before.

Impact:

  • Will require the user to sign on-chain TX anyway to enable claiming.

  • Contracts or helpers cannot claim for users without pre-set approvals

Proof of Concept

Recommended Mitigation

Implement EIP-2612 permit() support alongside the existing flow, allowing seamless claims.

Updates

Lead Judging Commences

yeahchibyke Lead Judge 11 days ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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