Santa's List

AI First Flight #3
Beginner FriendlyFoundry
EXP
View results
Submission Details
Impact: high
Likelihood: high
Invalid

Unauthorized burning of third-party SantaTokens allows NFT theft via buyPresent

Description

The function buyPresent(address presentReceiver) allows any user to burn SantaTokens belonging to an arbitrary address, as long as the SantasList contract has been approved to spend tokens.

However, the NFT minted by _mintAndIncrement() is always assigned to msg.sender, not to the owner of the burned SantaToken.

This creates a critical mismatch between the burned token owner and the NFT recipient, enabling theft of NFTs from legitimate token holders.


Vulnerability Details

Affected code

https://github.com/CodeHawks-Contests/ai-santas-list/blob/main/src/SantasList.sol#L168-L175

function buyPresent(address presentReceiver) external {
i_santaToken.burn(presentReceiver);
_mintAndIncrement();
}

Issue Breakdown

  1. The function burns SantaTokens from presentReceiver:

    i_santaToken.burn(presentReceiver);


    This assumes the caller is legitimately authorized to burn tokens of presentReceiver.

  2. No check is performed to ensure that msg.sender == presentReceiver.

  3. The NFT is minted to msg.sender:

    _mintAndIncrement();

  4. meaning the caller receives the NFT regardless of whose tokens were burned.


Impact

An attacker can:

  • Monitor the blockchain for approvals to the SantasList contract

  • Wait until a user approves token spending

  • Immediately call buyPresent(presentReceiver) using the victim address

  • Burn the victim’s SantaTokens

  • Mint and receive the NFT for themselves

Result:

➡️ Direct theft of NFTs from users who only approved token spending

This breaks fundamental assumptions of ownership and authorization.


Proof of Concept (attack scenario)

  1. Victim approves SantasList contract:

    santaToken.approve(address(SantasList), amount);
  2. Attacker monitors the blockchain and detects approval.

  3. Attacker calls:

    buyPresent(victimAddress);
  4. Outcome:

  • Victim’s SantaTokens are burned

  • Attacker receives NFT minted via _mintAndIncrement()


Root Cause

  • Missing authorization check on presentReceiver

  • Logical inconsistency between:

  • token burn source (presentReceiver)

  • NFT recipient (msg.sender)


Recommended Fix

Require that the caller is the owner of the tokens being burned:

function buyPresent(address presentReceiver) external {
require(msg.sender == presentReceiver, "Not token owner");
i_santaToken.burn(msg.sender);
_mintAndIncrement();
}

Alternatively, if delegated burning is intended, then NFT should be minted to presentReceiver instead:

_mintAndIncrement(presentReceiver);

Conclusion

This vulnerability allows any approved contract user to have their SantaTokens burned and lose NFT rewards, while an attacker profits. The inconsistency between burned token owner and NFT recipient leads to a high-severity asset theft issue.


Updates

Lead Judging Commences

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