Puppy Raffle

AI First Flight #1
Beginner FriendlyFoundrySolidityNFT
EXP
View results
Submission Details
Impact: medium
Likelihood: medium
Invalid

External Call Before Minting in `PuppyRaffle::selectWinner` Violates Checks-Effects-Interactions

[M-03] External Call Before Minting in PuppyRaffle::selectWinner Violates Checks-Effects-Interactions

Description

  • In selectWinner(), the contract is designed to complete all state updates and mint the winner's NFT reward as part of the raffle finalization.

  • An external call winner.call{value: prizePool}("") is triggered before _safeMint(winner, tokenId). Because _safeMint makes an external callback to onERC721Received if the winner is a contract, this ordering violates the Checks-Effects-Interactions (CEI) principle and creates reentrancy exposure before the token state finishes updating.

function selectWinner() external {
...
@> (bool success,) = winner.call{value: prizePool}("");
require(success, "PuppyRaffle: Failed to send prize pool to winner");
@> _safeMint(winner, tokenId);
}

Risk

Likelihood:

  • A contract address is selected as the winner, receiving execution flow during call before _safeMint is invoked.

  • An unexpected external call occurs during token minting via IERC721Receiver.onERC721Received.

Impact:

  • Violates standard CEI guidelines and opens attack surfaces for reentrancy or inconsistent state inspection during transaction execution.

Proof of Concept

// In selectWinner:
// 1. External call: winner.call{value: prizePool}("") gives control to winner fallback
// 2. Token minting: _safeMint(winner, tokenId) executes after the external transfer
// An external winner can interact with other contract functions before the NFT is minted.

Recommended Mitigation

function selectWinner() external {
...
previousWinner = winner;
+ _safeMint(winner, tokenId);
(bool success,) = winner.call{value: prizePool}("");
require(success, "PuppyRaffle: Failed to send prize pool to winner");
- _safeMint(winner, tokenId);
}

Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 2 hours 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!