PuppyRaffle::refund allows an attacker to drain the entire contract balanceThe PuppyRaffle::refund function is vulnerable to a classic reentrancy attack. The function allows a player to withdraw their entrance fee, but it performs the external ETH transfer before updating the internal state that tracks the player's presence in the raffle.
The contract uses Address.sendValue to transfer ETH, which forwards a significant amount of gas to the recipient. If the recipient is a malicious smart contract, it can use its receive() or fallback() function to call refund() again. Because the first call has not yet reached the line where the player's index is set to address(0), the second call passes the require check again, leading to multiple withdrawals for a single entrance fee.
Likelihood: High. This is a common and well-documented vulnerability. Any user with basic smart contract knowledge can deploy an attacking contract to exploit this flaw.
Impact: Critical. A single attacker can drain the entire ETH balance of the PuppyRaffle contract, stealing the deposits of all other honest participants. This results in a total loss of funds for the protocol.
The vulnerability is caused by a violation of the Checks-Effects-Interactions (CEI) pattern. The "Interaction" (sending ETH) happens before the "Effect" (updating the players array).
The following Foundry test demonstrates how a malicious contract can enter the raffle and recursively call refund to drain the vault.
The most effective way to prevent reentrancy is to follow the Checks-Effects-Interactions (CEI) pattern. Update the state (mark the player as refunded) before performing the external ETH transfer.
Additionally, consider adding a ReentrancyGuard from OpenZeppelin and applying the nonReentrant modifier to all functions that handle ETH transfers.
The contest is live. Earn rewards by submitting a finding.
Submissions are being reviewed by our AI judge. Results will be available in a few minutes.
View all submissionsThe contest is complete and the rewards are being distributed.