Snowman Merkle Airdrop

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

Tokens Are Locked, Not Burned, After Claiming Snowman NFTs

Root + Impact

Description

  • Normally, when users claim Snowman NFTs by transferring their Snow tokens, those tokens should be permanently removed from circulation (burned), reducing the total supply and aligning with user expectations.

  • In the current implementation, Snow tokens are only transferred to the contract address and are not actually burned. While there is no function to withdraw or use these tokens now, they remain part of the total supply and could potentially be accessed in the future if a withdrawal function is added.

// Root cause in the codebase with @> marks to highlight the relevant section
i_snow.safeTransferFrom(receiver, address(this), amount); // @> Tokens are sent to contract, not burned <@

Risk

Likelihood:

  • This will occur whenever a user claims Snowman NFTs, as the contract always transfers tokens to itself instead of burning them.

  • The risk increases if the contract is upgraded or modified to include a withdrawal or transfer function.

Impact:

  • The total supply of Snow tokens does not decrease as users might expect, potentially affecting tokenomics.

  • Locked tokens could be withdrawn or reused in the future, undermining trust and expectations of permanent removal.

Proof of Concept

This PoC demonstrates that after a user claims, their tokens are not destroyed but simply moved to the contract. If a withdrawal function is ever added, these tokens can be returned to circulation, which is not the intended behavior if users expect tokens to be burned.

// User claims Snowman NFTs:
uint256 userBalanceBefore = i_snow.balanceOf(user);
snowmanAirdrop.claimSnowman(user, proof, v, r, s);
uint256 contractBalance = i_snow.balanceOf(address(snowmanAirdrop));
assert(contractBalance == userBalanceBefore); // Tokens are held by contract, not burned
// If a withdrawal function is added in the future:
i_snow.transfer(owner, contractBalance); // All "burned" tokens are now back in circulation

Recommended Mitigation

To ensure tokens are permanently removed from circulation, update the contract to burn tokens when users claim NFTs. This can be done by transferring tokens to the zero address or, preferably, by calling a burnFrom function if the ERC20 token supports it. This aligns the contract’s behavior with user expectations and prevents any possibility of the tokens being reused or withdrawn in the future.

- i_snow.safeTransferFrom(receiver, address(this), amount);
+ i_snow.safeTransferFrom(receiver, address(0), amount); // Burn tokens by sending to zero address
Updates

Lead Judging Commences

yeahchibyke Lead Judge
3 months ago
yeahchibyke Lead Judge 3 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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