Santa's List

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

[M-1] buyPresent mints the NFT to msg.sender instead of presentReceiver

Root + Impact

Description

  • buyPresent is documented as a function to "Buy a present for someone else." The caller passes a presentReceiver address as the intended gift recipient, and the NFT should be delivered to that address.

  • However, _mintAndIncrement always mints to msg.sender, regardless of the presentReceiver argument. The recipient parameter is only used for the burn call (which is itself wrong, see H-3). The end result is that the caller buys a present and keeps it for themselves, while the designated recipient receives nothing.

function buyPresent(address presentReceiver) external {
i_santaToken.burn(presentReceiver);
// @> _mintAndIncrement always mints to msg.sender, ignoring presentReceiver
_mintAndIncrement();
}
function _mintAndIncrement() private {
// @> Always mints to msg.sender
_safeMint(msg.sender, s_tokenCounter++);
}

Risk

Likelihood:

  • Every call to buyPresent exhibits this behavior — the recipient parameter is never used for minting

  • There is no code path in buyPresent that delivers the NFT to presentReceiver

Impact:

  • The gifting feature is entirely non-functional

  • Users who intend to buy presents for others are misled by the function signature and NatSpec

  • Recipients are denied NFTs they were supposed to receive

Proof of Concept

A user calls buyPresent(recipient) expecting the recipient to receive an NFT. After the call, the recipient's NFT balance is 0 while the caller holds the NFT.

function testBuyPresentGoesToCaller() public {
address buyer = makeAddr("buyer");
address recipient = makeAddr("recipient");
// setup: buyer has sufficient SantaTokens
vm.prank(buyer);
santasList.buyPresent(recipient);
assertEq(santasList.balanceOf(recipient), 0); // recipient got nothing
assertEq(santasList.balanceOf(buyer), 1); // buyer kept the NFT
}

Recommended Mitigation

Mint directly to presentReceiver inside buyPresent rather than delegating to _mintAndIncrement, which hardcodes msg.sender as the recipient.

function buyPresent(address presentReceiver) external {
i_santaToken.burn(msg.sender); // also fixes H-3
- _mintAndIncrement();
+ _safeMint(presentReceiver, s_tokenCounter++);
}
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!