Snowman Merkle Airdrop

First Flight #42
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Severity: high
Valid

EIP-712 Typehash Typo Breaks Signature Verification

Root + Impact

Description

  • The contract implements EIP-712 signature verification using a type hash for the SnowmanClaim struct, which is intended to allow users to claim tokens by presenting a valid off-chain signature.

  • However, the type string used to generate the MESSAGE_TYPEHASH contains a typo (addres instead of address), causing the on-chain type hash to differ from the one used off-chain. This results in all EIP-712 signature verifications failing, making the claim functionality unusable.

// Root cause in the codebase with @> marks to highlight the relevant section
bytes32 private constant MESSAGE_TYPEHASH = keccak256("SnowmanClaim(@>addres<@ receiver, uint256 amount)");

Risk

Likelihood:

  • This will occur whenever a user attempts to claim using a valid EIP-712 signature generated off-chain with the correct struct definition.

  • The issue will persist for all users and all claims, as the on-chain and off-chain type hashes will never match.

Impact:

  • All legitimate claims will fail signature verification, preventing users from claiming their tokens.

  • The airdrop or claim mechanism is effectively bricked, resulting in loss of trust and potential financial or reputational damage.

Proof of Concept

The on-chain and off-chain type hashes are different due to the typo, so any signature generated off-chain will never be valid on-chain.

// Off-chain, a user signs the correct struct:
// "SnowmanClaim(address receiver, uint256 amount)"
// On-chain, the contract expects:
// "SnowmanClaim(addres receiver, uint256 amount)"
// The hashes do not match, so verification always fails.
assert(
keccak256("SnowmanClaim(address receiver, uint256 amount)") !=
keccak256("SnowmanClaim(addres receiver, uint256 amount)")
); // This assertion passes, demonstrating the mismatch.

Recommended Mitigation

Correct the typo in the type string to ensure the on-chain and off-chain type hashes match. This will restore proper EIP-712 signature verification and allow users to claim as intended.

- 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

yeahchibyke Lead Judge 3 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Inconsistent MESSAGE_TYPEHASH with standard EIP-712 declaration

A typo in the `MESSAGE_TYPEHASH` variable of the `SnowmanAirdrop` contract will prevent signature verification claims. Used `addres` instead of `address`

Support

FAQs

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