Christmas Dinner

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

HOST can withdraw tokens when event is going on, breaking the refund mechanism

[M-1] HOST can withdraw tokens when event is going on, breaking the refund mechanism

Description: host can withdraw tokens when event is going on, cause participants not being able to refund their tokens.

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)));
}
...
function refund() external nonReentrant beforeDeadline {
address payable _to = payable(msg.sender);
_refundERC20(_to);
_refundETH(_to);
emit Refunded(msg.sender);
}

if the contract does not have enough tokens to refund, the refund will be reverted.

Impact:
Participants may not be able to refund their tokens.

Proof of Concept:

  1. Participant sends some ERC20 token (in the whitelist) to the contract.

  2. Host withdraws all the tokens.

  3. Participant tries to refund the tokens.

import {IERC20Errors} from "../lib/openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol";
...
function test_hostWithdrawBeforeEventEndBreakParticipantRefund() public {
vm.prank(user1);
cd.deposit(address(wbtc), 5000);
vm.prank(deployer);
cd.withdraw();
vm.prank(user1);
vm.expectRevert(abi.encodeWithSelector(
IERC20Errors.ERC20InsufficientBalance.selector,
address(cd),
0, // Current balance
5000 // Attempted transfer amount
));
cd.refund();
}

Recommended Mitigation:
Add a modifier to prevent the host from withdrawing tokens when the event is going on.

+ modifier beforeEventEnd() {
+ require(block.timestamp <= deadline, "Event has ended");
+ _;
+ }
...
- function withdraw() external onlyHost {
+ function withdraw() external onlyHost EventEnded {
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)));
}
Updates

Lead Judging Commences

0xtimefliez Lead Judge 11 months ago
Submission Judgement Published
Validated
Assigned finding tags:

withdraw is callable before deadline ends

Support

FAQs

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