Beginner FriendlyFoundryNFT
100 EXP
View results
Submission Details
Severity: low
Invalid

Not following CEI Pattern

Summary

The refund function in the provided contract is indeed not following the "checks-effects-interactions" (CEI) pattern. Here's an explanation of why it deviates from the CEI pattern:

  1. Checks: The first two require statements are performing checks to ensure that the player's address matches the sender's address and that the player has not already been refunded or is not active. These checks are performed as expected in the "checks" phase.

  2. Effects: After the checks, the function modifies the state by calling payable(msg.sender).sendValue(entranceFee) to refund the entrance fee to the player. This part follows the "effects" phase where state changes are applied.

  3. Interactions: The issue with this function is in the "interactions" phase. The interaction with payable(msg.sender).sendValue(entranceFee) is problematic from a CEI perspective. Although sendValue is safer than a direct transfer method and provides some protection against reentrancy, it's still considered an interaction, and interactions should typically come after all state changes (effects) in the CEI pattern.

Ideally, in the CEI pattern, you should reorder the function as follows:

Checks: Perform all necessary checks first.
Effects: Update the contract state.
Interactions: Interact with external contracts or send Ether last.

Vulnerability 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");
// @audit-ok Did not follow CEI/ C validation is fine, but not vulnerable to reentrancy since it uses sendValue.
payable(msg.sender).sendValue(entranceFee);
players[playerIndex] = address(0);
emit RaffleRefunded(playerAddress);
}

Impact

Reentrancy Risk: While the refund function doesn't directly expose the contract to reentrancy attacks, its deviation from the "checks-effects-interactions" (CEI) pattern increases the potential risk. Any future interactions or changes to the contract's logic might introduce reentrancy vulnerabilities.

Security Risk: Not adhering to the CEI pattern makes the contract more susceptible to security risks and unexpected changes. It's essential to maintain best practices for contract security.

Tools Used

Manual Review

Recommendations

In this modified version, the state change is performed before the interaction, which aligns better with the CEI pattern. This can help reduce the risk of reentrancy vulnerabilities. While sendValue offers some protection, good coding practices are still essential to enhance security.

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); // Move state change before interaction
emit RaffleRefunded(playerAddress);
payable(msg.sender).sendValue(entranceFee); // Interaction is last
}
Updates

Lead Judging Commences

Hamiltonite Lead Judge almost 2 years ago
Submission Judgement Published
Invalidated
Reason: Other
thedoctor Submitter
almost 2 years ago
patrickalphac Lead Judge
almost 2 years ago
Hamiltonite Lead Judge almost 2 years ago
Submission Judgement Published
Invalidated
Reason: Other
Hamiltonite Lead Judge almost 2 years ago
Submission Judgement Published
Invalidated
Reason: Other

Support

FAQs

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