Snowman Merkle Airdrop

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

Spelling errors in SnowmanAirdrop's EIP-712 type hash make all standard wallet signatures invalid, breaking claimSnowman

Root + Impact

MESSAGE_TYPEHASH in SnowmanAirdrop has spelling errors, so signatures from standard EIP-712 wallets never match and claimSnowman always reverts.

Description

To let someone else claim on your behalf, the user signs a message from their wallet using the EIP-712 standard. The contract and the wallet must compute this message in exactly the same way.

However, the type string in the contract has two errors: it says "addres" (missing an "s"), and it has an extra space after the comma.

As a result, the wallet and the contract each use a different message. The signature never matches, and claimSnowman reverts with SA__InvalidSignature for every user who signs with a standard wallet.

@> bytes32 private constant MESSAGE_TYPEHASH = keccak256("SnowmanClaim(addres receiver, uint256 amount)");

According to EIP-712, the correct type string for the SnowmanClaim struct is:

"SnowmanClaim(address receiver,uint256 amount)"

Risk

Likelihood: High. It affects every user who signs with a standard wallet (eth_signTypedData_v4).

Impact: Medium. The signature-based claim flow, one of the main features of the airdrop, does not work. No funds are stolen, but users cannot claim their NFTs this way.

Proof of Concept

The test shows that the hash used by the contract is different from the correct EIP-712 type hash that wallets compute.

function testTypehashDoesNotMatchEip712() public pure {
bytes32 buggy = keccak256("SnowmanClaim(addres receiver, uint256 amount)");
bytes32 correct = keccak256("SnowmanClaim(address receiver,uint256 amount)");
​
assertTrue(buggy != correct);
}

A wallet signing a SnowmanClaim struct with eth_signTypedData_v4 uses the correct type hash, so the recovered signer in _isValidSignature will not equal the receiver, and claimSnowman reverts with SA__InvalidSignature.

Recommended Mitigation

Fix the type string to match the EIP-712 standard.

- bytes32 private constant MESSAGE_TYPEHASH = keccak256("SnowmanClaim(addres receiver, uint256 amount)");
+ bytes32 private constant MESSAGE_TYPEHASH = keccak256("SnowmanClaim(address receiver,uint256 amount)");
​
​
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 1 hour 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!