Snowman Merkle Airdrop

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

Dynamic Balance Snapshot Problem — Non-Deterministic Leaf Generation

Summary

Merkle leaves are computed using the current balanceOf(receiver) which is mutable and can lead to verification failures.

Description

The Merkle tree should be constructed off-chain from static data.
The current design allows balances to drift over time, breaking Merkle proof verification.
If a user sends or receives tokens before claiming, their Merkle proof becomes permanently invalid.

POC

function testChangeSnowAmountFailMerkleVerifyPOC() public {
// Bob claim test
assert(nft.balanceOf(bob) == 0);
vm.prank(bob);
snow.approve(address(airdrop), 2);
// Get bob's digest
vm.warp(block.timestamp + 1 weeks);
vm.prank(bob);
snow.earnSnow();
uint256 bobSB = snow.balanceOf(bob);
bytes32 bobDigest = airdrop.getMessageHash(bob);
// bob signs a message
(uint8 bobV, bytes32 bobR, bytes32 bobS) = vm.sign(bobKey, bobDigest);
// satoshi calls claim on behalf of bob using his signed message
vm.prank(satoshi);
airdrop.claimSnowman(bob, BOB_PROOF, bobV, bobR, bobS);
assert(nft.balanceOf(bob) == 1);
assert(nft.ownerOf(0) == bob);
}

Impact

Frozen funds.
Merkle proof becomes useless if balances change.

Severity

HIGH

Likelihood

HIGH

Recommended mitigation

Build Merkle leaves off-chain using precomputed snapshot balances.
Include static amount in Merkle proof payload.
Modify function to accept uint256 amount as input parameter.

Updates

Lead Judging Commences

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

Invalid merkle-proof as a result of snow balance change before claim action

Claims use snow balance of receiver to compute the merkle leaf, making proofs invalid if the user’s balance changes (e.g., via transfers). Attackers can manipulate balances or frontrun claims to match eligible amounts, disrupting the airdrop.

Support

FAQs

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