The refund function is vulnerable to a reentrancy attack that can completely drain the protocol of its funds harming both the users and the protocol itself.
In classic reentrancy fashion, the refund(uint256 playerIndex) function that starts on line 96 makes external interactions before updating the contract's state variables. This allows a bad actor contract to repeatedly withdraw ETH until the PuppyRaffle contract balance is completely empty.
This attack can be reproduced in the project repo by adding the following contract into PuppyRaffle.sol
Then, update line 6 of PuppyRaffleTest.t.sol to
And finally add the following test to PuppyRaffleTest.t.sol
Reentrancy is a very common and easy to perform hack, and will most certainly happen if it can be exploited. This attack will drain the protocol of all of its funds. This harms both the protocol, and all the users who put their ETH into the protocol.
Manual Review
Follow the CEI (Checks, Effects, Interactions) pattern when implementing functions.
Checks - Check to ensure proper user inputs.
Effects - Make updates to the contracts' state
Interactions - Interact with external contracts/EOAs
Also remember that it is important to keep the entire protocol invariants (Things that should always hold true) in mind when designing and implementing functions.
reentrancy in refund() function
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.