Christmas Dinner

First Flight #31
Beginner FriendlyFoundrySolidity
100 EXP
View results
Submission Details
Severity: high
Valid

Locked Ether After Deadline

Summary

The contract allows users to participate in the dinner event by sending Ether through its receive function. If users wish to withdraw their Ether, they can do so using the refund function before the deadline passes. However, if a user has decided to participate with Ether, after the deadline passes, they will be unable to withdraw their Ether. Additionally, the host will not be able to withdraw the Ether through the withdraw function, as the function currently only handles ERC20 token transfers, leaving the Ether locked in the contract.

Vulnerability Details

The withdraw function does not handle the withdrawal of Ether, which leads to a critical issue if Ether is sent to the contract. The function currently only transfers ERC20 tokens like WETH, WBTC, and USDC to the host. Ether deposited by users is not included in the withdrawal process, causing it to be locked if the deadline passes.

Here’s the current withdraw function:

function withdraw() external onlyHost {
address _host = getHost();
i_WETH.safeTransfer(_host, i_WETH.balanceOf(address(this)));
i_WBTC.safeTransfer(_host, i_WBTC.balanceOf(address(this)));
i_USDC.safeTransfer(_host, i_USDC.balanceOf(address(this))); // Ether is not withdrawn here
}

This function needs to be updated to also allow the host to withdraw Ether, otherwise, Ether remains inaccessible after the deadline.

Impact

Scenario: Alice and Bob's Participation

  • Alice decides to participate in the event using Ether. She sends 1 Ether to the contract. Alice’s participation is recorded, and she can refund her Ether anytime before the deadline.

  • Bob also participates using Ether and sends 0.5 Ether to the contract. Both Alice and Bob can refund their Ether as long as the deadline has not passed.

However, after the deadline passes:

  • Alice and Bob can no longer use the refund function to withdraw their Ether, since the function is locked due to the passed deadline.

  • The host cannot withdraw the Ether, either, because the withdraw function does not handle Ether transfers.

In this situation, both Alice and Bob’s Ether, along with any Ether in the contract, remains locked indefinitely, resulting in the loss of funds.

Tools Used

Manual review

Recommendations

To resolve this issue, update the withdraw function to handle Ether withdrawals in addition to ERC20 tokens. Here's a suggestion on how to modify the function:

function withdraw() external onlyHost {
address _host = getHost();
// Withdraw ERC20 tokens
i_WETH.safeTransfer(_host, i_WETH.balanceOf(address(this)));
i_WBTC.safeTransfer(_host, i_WBTC.balanceOf(address(this)));
i_USDC.safeTransfer(_host, i_USDC.balanceOf(address(this)));
// Withdraw Ether (add this part)
uint256 etherBalance = address(this).balance;
if (etherBalance > 0) {
payable(_host).call{value: etherBalance}("");
}
}

This modification allows the host to withdraw Ether by using the call method, which is more flexible than transfer and avoids issues with gas limits.

Updates

Lead Judging Commences

0xtimefliez Lead Judge about 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

withdraw function lacks functionality to send ether

Support

FAQs

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

Give us feedback!