Last Man Standing

First Flight #45
Beginner FriendlyFoundrySolidity
100 EXP
View results
Submission Details
Impact: medium
Likelihood: medium
Invalid

Contract Can Receive ETH That Becomes Permanently Locked

Root + Impact

Description

The Game contract includes a receive() function that allows it to accept ETH through plain transfers:

receive() external payable {}

However, this ETH is not tracked in platformFeesBalance or pendingWinnings, and there is no mechanism to withdraw or recover it.

Only two functions allow ETH withdrawals:

  • withdrawWinnings(): For players with pending winnings

  • withdrawPlatformFees(): For the owner to withdraw tracked platform fees


    Any ETH sent directly (e.g., by mistake or from a bot) will be permanently stuck in the contract.

Risk

Impact:

  • Funds are not lost by the contract, but they become inaccessible.

  • ETH could accumulate over time, unnoticed.

Proof of Concept

function test__StuckETH() public {
// Directly send ETH to the contract using the receive() function
(bool sent,) = address(game).call{value: 1 ether}("");
require(sent);
// ETH is now in the contract, but not withdrawable
assertEq(address(game).balance, 1 ether);
assertEq(game.platformFeesBalance(), 0); // not tracked
}

Recommended Mitigation

Option 1: Remove the recievefunction

receive() external payable {}

This will prevent plain ETH transfers and reduce confusion.

Option 2: Add a withdrawal mechanism for all contract balance

Either approach would prevent ETH from being permanently locked in the contract.

Updates

Appeal created

inallhonesty Lead Judge about 2 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Direct ETH transfers - User mistake

There is no reason for a user to directly send ETH or anything to this contract. Basic user mistake, info, invalid according to CH Docs.

Support

FAQs

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