Snowman Merkle Airdrop

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

Typographical Error in MESSAGE_TYPEHASH

Summary

The contract contains a critical typographical error in the EIP-712 struct definition used for signature verification, causing all claim attempts to fail.

Description

The MESSAGE_TYPEHASH constant contains a typo where "address" is misspelled as "addres". This hash is fundamental to EIP-712 signature verification. When users sign messages off-chain, they would use the correct spelling, but the contract uses the incorrect one. This mismatch in hashes means all signature verifications will fail, rendering the airdrop system completely non-functional.

EIP-712 signature verification requires that the type hash used for generating the signature off-chain exactly matches the one used for verification on-chain. The typographical error results in different hashes, causing the _isValidSignature() function to always fail.

Step-by-step Analysis

  1. A user obtains a correctly formatted signature off-chain with proper spelling: "SnowmanClaim(address receiver, uint256 amount)"

  2. The user submits this signature to the claimSnowman() function

  3. The contract attempts to verify this signature using its incorrectly spelled type hash: "SnowmanClaim(addres receiver, uint256 amount)"

  4. The verification fails because the hashes do not match, even with a legitimately signed message

  5. The transaction reverts with SA__InvalidSignature() error

  6. No user can successfully claim their Snowman NFTs

Severity Classification

  • Impact: High - The contract is entirely non-functional; no legitimate claims can be processed

  • Likelihood: High - This issue will affect 100% of claim attempts

File Name

src/SnowmanAirdrop.sol

Code with Issue

bytes32 private constant MESSAGE_TYPEHASH = keccak256("SnowmanClaim(addres receiver, uint256 amount)"); // keccak256 hash of the SnowmanClaim struct's type signature, used for EIP-712 compliant message signing

Recommendation

Correct the typographical error in the MESSAGE_TYPEHASH constant:

bytes32 private constant MESSAGE_TYPEHASH = keccak256("SnowmanClaim(address receiver, uint256 amount)"); // keccak256 hash of the SnowmanClaim struct's type signature, used for EIP-712 compliant message signing

This correction ensures that the hash used for verification on-chain matches the one used for signature generation off-chain, allowing legitimate claim attempts to succeed.

Proof of Concept

/**
* @notice POC demonstrating that all signature verifications fail due to MESSAGE_TYPEHASH typo
* @dev Shows how the typo "addres" instead of "address" breaks the entire airdrop system
*/
function test_POC_MessageTypeHashTypo() public {
console2.log("=== POC 1: MESSAGE_TYPEHASH Typographical Error ===");
uint256 aliceBalance = snow.balanceOf(alice);
console2.log("Alice's Snow balance:", aliceBalance);
// Create a mock Merkle proof (would be generated off-chain in reality)
bytes32[] memory merkleProof = new bytes32[](1);
merkleProof[0] = keccak256("mock_proof");
// Try to get message hash (this will work because it uses the broken typehash)
try airdrop.getMessageHash(alice) returns (bytes32 hash) {
console2.log("Contract generated message hash (with typo)");
// In reality, off-chain code would use correct typehash:
// "SnowmanClaim(address receiver, uint256 amount)"
// But contract uses: "SnowmanClaim(addres receiver, uint256 amount)"
// Simulate what would happen with a correct signature from off-chain
bytes32 correctTypehash = keccak256("SnowmanClaim(address receiver, uint256 amount)");
console2.log("Correct typehash should be for 'address', not 'addres'");
// Any real signature will fail because of the mismatch
vm.prank(alice);
vm.expectRevert(abi.encodeWithSignature("SA__InvalidSignature()"));
airdrop.claimSnowman(alice, merkleProof, 27, bytes32(0), bytes32(0));
console2.log("BUG DEMONSTRATED: All signature verifications fail");
console2.log("CAUSE: Typo in MESSAGE_TYPEHASH - 'addres' instead of 'address'");
console2.log("IMPACT: Complete system failure - no user can claim tokens");
} catch {
console2.log("Even getMessageHash fails due to the typo");
}
}
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.