Loss of funds due to reentrancy attack through refunds.
An attacker can drain the balance of the PuppRaffle contract through PuppyRaffle::refund function because the state of the player is updated after the transaction of funds.
This enables the attacker to trigger the transaction multiple times and drain the contract balance.
First attacker needs to deploy the Attacker.sol contract and pass in the address of PuppyRaffle.
By calling the Attacker::attack function the contract will enter the PuppyRaffle as one of the players through the PuppyRaffle::enterRaffle function.
Afterward, the PuppyRaffle::refund function is called and the initial entrance fee is sent back to the Attacker contract.
This triggers Attacker:receive function and it calls the PuppyRaffle::refund function again. This cycle repeats until all the funds are drained from the PuppyRaffle contract.
Attacker.sol:
Attack execution:
Foundry
Follow CEI - Checks Effects Interactions pattern.
First update the player state player state (effects) players[playerIndex] = address(0); (L103),
and then execute the transaction (interaction) payable(msg.sender).sendValue(entranceFee); (L101) at the end of the PuppyRaffle::refund function.
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.