Christmas Dinner

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

H-04: `ChristmasDinner::withdraw()` does not check for block.timestamp and allows host to withdraw before deadline, preventing users to get refund of ERC20 tokens

Summary

ChristmasDinner::withdraw() is missing the check for block.timestamp, allowing the host to withdraw the tokens before deadline and users will not be able to get a refund before deadline.

Vulnerability Details

The check for current block.timestamp is missing. Allowing host to withdraw before deadline and users will not be able to get a refund as the ERC20 tokens are already withdrawn

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)));
}

Impact

  1. User1 Deposit some tokens

  2. Host withdraw before deadline

  3. User1 wants to back out and refund before deadline, but transaction fails and revert

function testWithdrawBeforeDeadline() public {
// User1 deposits 2e18 WBTC
vm.startPrank(user1);
cd.deposit(address(wbtc), 2e18);
vm.stopPrank();
console.log("CD WBTC: ", wbtc.balanceOf(address(cd)));
// Deployer withdraw the funds before deadline
vm.startPrank(deployer);
cd.withdraw();
console.log("CD WBTC: ", wbtc.balanceOf(address(cd)));
vm.stopPrank();
// User1 tries to call refund() but transaction reverts because the WBTC token has already been withdrawn
vm.startPrank(user1);
vm.expectRevert();
cd.refund();
vm.stopPrank();
}

Results

[PASS] testWithdrawBeforeDeadline() (gas: 148964)
Logs:
CD WBTC: 2000000000000000000
CD WBTC: 0
Traces:
....
....
....
├─ [12230] ChristmasDinner::refund()
│ ├─ [5310] ERC20Mock::transfer(user1: [0x29E3b139f4393aDda86303fcdAa35F60Bb7092bF], 0)
│ │ ├─ emit Transfer(from: ChristmasDinner: [0x8Ad159a275AEE56fb2334DBb69036E9c7baCEe9b], to: user1: [0x29E3b139f4393aDda86303fcdAa35F60Bb7092bF], value: 0)
│ │ └─ ← [Return] true
│ ├─ [919] ERC20Mock::transfer(user1: [0x29E3b139f4393aDda86303fcdAa35F60Bb7092bF], 2000000000000000000 [2e18])
-> │ │ └─ ← [Revert] ERC20InsufficientBalance(0x8Ad159a275AEE56fb2334DBb69036E9c7baCEe9b, 0, 2000000000000000000 [2e18])
│ └─ ← [Revert] ERC20InsufficientBalance(0x8Ad159a275AEE56fb2334DBb69036E9c7baCEe9b, 0, 2000000000000000000 [2e18])
├─ [0] VM::stopPrank()
│ └─ ← [Return]
└─ ← [Stop]
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 5.51s (263.19ms CPU time)

Tools Used

Foundry

Recommendations

Include check if block.timestamp is > deadline

function withdraw() external onlyHost {
+ require(block.timestamp > deadline);
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 about 1 year 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.

Give us feedback!