Christmas Dinner

First Flight #31
Beginner FriendlyFoundrySolidity
100 EXP
View results
Submission Details
Severity: medium
Invalid

Violation of the Correct Order of State Changes (CEI Pattern) in _refundERC20 and _refundETH Functions

Summary

The functions _refundERC20 and _refundETH in the ChristmasDinner contract do not follow the correct pattern of state changes (CEI - Consistency, Error-Checking, and Interaction). This violation could lead to unexpected behaviors and vulnerabilities, such as manipulation of contract state or unintended consequences in a reentrant call.

Vulnerability Details

Issue in _refundERC20 Function

The _refundERC20 function transfers the user's ERC20 balances first and then resets those balances to zero in the state variables. The function does not follow the CEI pattern, which could lead to race conditions or other unexpected issues:

function _refundERC20(address _to) internal {
i_WETH.safeTransfer(_to, balances[_to][address(i_WETH)]);
i_WBTC.safeTransfer(_to, balances[_to][address(i_WBTC)]);
i_USDC.safeTransfer(_to, balances[_to][address(i_USDC)]);
balances[_to][address(i_USDC)] = 0;
balances[_to][address(i_WBTC)] = 0;
balances[_to][address(i_WETH)] = 0;
}
  • Violation of CEI Pattern:

    • The state changes should be separated into three distinct steps:

      1. Consistency: Perform any error-checking operations to ensure the function preconditions are met (e.g., checking that balances are not zero before transferring).

      2. Error-Checking: Perform state changes to the contract state or updates to variables.

      3. Interaction: Perform the state-changing interactions (transfers in this case).

    • In the current implementation, the state changes are not correctly ordered, which can lead to the following problems:

      • Race Conditions: If the transfer of tokens fails (for example, due to insufficient funds), the state change will still occur, leaving the contract in an inconsistent state.

      • Double Withdrawals: In case of reentrant calls, the state might allow a double withdrawal, as the balance changes are performed after the actual transfers.

Issue in _refundETH Function

The _refundETH function exhibits the same pattern of inconsistent state changes:

function _refundETH(address payable _to) internal {
uint256 refundValue = etherBalance[_to];
_to.transfer(refundValue);
etherBalance[_to] = 0;
}
  • Violation of CEI Pattern:

    • The state change order is incorrect because the etherBalance[_to] is reset before the transfer occurs.

    • This can lead to race conditions where a reentrant call could manipulate the state between the reading of etherBalance[_to] and the subsequent transfer.
      Impact

Impact

  • Unexpected Behavior: The lack of CEI pattern compliance can lead to unexpected behaviors such as reentrancy vulnerabilities, double withdrawals, and state inconsistencies.

  • Reentrancy Vulnerability: If the refund functions are called in a reentrant manner, the contract’s state may allow for multiple transfers when it should only allow one.

  • Manipulation of State: An attacker could potentially exploit the order of state changes to manipulate balances and withdraw funds more than once.

Tools Used

  • Manual code review.

  • Analysis of best practices in Solidity development and the correct implementation of the CEI pattern.
    Recommendations

Recommendations

  1. Follow the CEI Pattern: Ensure that the functions _refundERC20 and _refundETH follow the correct order of state changes:

    • Consistency: Check that the balances are not zero or that they have a non-zero amount before transferring.

    • Error-Checking: Check any additional conditions to prevent incorrect state changes.

    • Interaction: Perform the transfer of funds.

  2. Revised Implementations:

    • For _refundERC20:

      function _refundERC20(address _to) internal {
      uint256 amountWethToRefund = balances[_to][address(i_WETH)];
      uint256 amountWbtcToRefund = balances[_to][address(i_WBTC)];
      uint256 amountUsdcToRefund = balances[_to][address(i_USDC)];
      balances[_to][address(i_USDC)] = 0;
      balances[_to][address(i_WBTC)] = 0;
      balances[_to][address(i_WETH)] = 0;
      i_WETH.safeTransfer(_to, amountWethToRefund);
      i_WBTC.safeTransfer(_to, amountWbtcToRefund);
      i_USDC.safeTransfer(_to, amountUsdcToRefund);
      }
    • For _refundETH:

      function _refundETH(address payable _to) internal {
      uint256 refundValue = etherBalance[_to];
      etherBalance[_to] = 0;
      _to.transfer(refundValue);
      }
  3. Review and Test: Conduct tests and ensure that the corrected functions are properly handling reentrancy scenarios and are robust against common vulnerabilities.

Conclusion

The violation of the CEI pattern in the _refundERC20 and _refundETH functions in the ChristmasDinner contract can lead to unexpected behaviors and vulnerabilities. Following the correct pattern will enhance the security and reliability of the contract by preventing manipulation and reentrancy attacks.

Updates

Lead Judging Commences

0xtimefliez Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
0xtimefliez Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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