Snowman Merkle Airdrop

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

[H-02] Unauthorized Token Drainage via Arbitrary from Address in safeTransferFrom

Summary
The SnowmanAirdrop contract allows any caller to specify an arbitrary from address when transferring tokens, enabling the theft of tokens from users who have previously approved the contract.

Vulnerability Detail
In src/SnowmanAirdrop.sol, the contract executes a token transfer using the following line:

Solidity

i_snow.safeTransferFrom(receiver, address(this), amount);
The receiver parameter is supplied directly by the caller of the function. In the standard ERC20.transferFrom (and its safe wrapper), the first argument represents the source of funds.

If a user has granted a token approval to the SnowmanAirdrop contract, an attacker can invoke this function and set the receiver parameter to the victim's address. Because the contract has the necessary approval, it will successfully "pull" tokens from the victim's wallet into the contract (or wherever the logic dictates) without the victim's consent.

Impact
This is a High-severity issue because it leads to a direct loss of funds for users. Any address that has interacted with and approved the protocol is at risk of having their SNOW tokens drained by a malicious actor.

Proof of Concept (PoC)

You can demonstrate this vulnerability by adding the following test case to your Foundry suite:

function testExploitArbitraryFrom() public {
// 1. Victim approves the airdrop contract
vm.prank(victim);
snow\.approve(address(airdrop), 1000 ether);
// 2. Attacker calls the claim function using victim's address as 'receiver'
vm.prank(attacker);
airdrop.claimSnowman(victim, 1000 ether, validProof);
// 3. Verification: Victim's tokens are gone
assertEq(snow\.balanceOf(victim), 0);
assertEq(snow\.balanceOf(address(airdrop)), 1000 ether);
}

Recommended Mitigation

The source of funds should always be the msg.sender to ensure that only the owner of the tokens (or someone they have authorized) can initiate a transfer.

Update the code as follows:

- i_snow.safeTransferFrom(receiver, address(this), amount);
+ i_snow.safeTransferFrom(msg.sender, address(this), amount);
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge 11 days 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!