Last Man Standing

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

ETH Sent Directly to Contract via `receive()` Will Be (Permanently Locked)

Description

The Game.sol contract includes an empty receive() external payable {} function. This allows the contract to accept direct ETH transfers from any user or contract.

While this behavior does not impact the core game logic—as all prize and fee calculations rely on internally tracked state variables (pot, platformFeesBalance) and not address(this).balance—it creates a situation where any ETH sent directly to the contract address becomes permanently locked. There is no function available for any user, including the owner, to withdraw these untracked funds.

// src/Game.sol
@> receive() external payable {}

Risk

Likelihood: Low

  • Users may accidentally send ETH to the contract address instead of calling claimThrone().

  • ETH can be forcibly sent to the contract via selfdestruct.

Impact: Low

  • This does not pose a security risk to the game's integrity or the funds of active players.

  • However, it leads to a permanent loss of funds for anyone who sends ETH directly to the contract. This can create user confusion and is generally considered poor practice.

Proof of Concept

A direct transfer of ETH to the contract address will increase address(this).balance but will not be reflected in any of the contract's accounting variables.

  1. An observer notes the initial contract balance is B1. The pot is P1 and platformFeesBalance is F1.

  2. A user accidentally sends 0.5 ETH directly to the contract address.

  3. The new contract balance B2 is now B1 + 0.5 ETH.

  4. The pot remains P1 and platformFeesBalance remains F1.

  5. There is no function that allows the withdrawal of this extra 0.5 ETH. It is permanently locked.

Recommended Mitigation

To prevent accidental loss of funds and ensure all value transfers are explicit, it is recommended to remove the receive() function or make it revert.

// src/Game.sol
- receive() external payable {}
+ receive() external payable {
+ revert("Direct ETH transfers are not allowed. Please use claimThrone().");
+ }

This change will prevent users from accidentally locking their funds and ensures that all ETH entering the contract is properly accounted for through the intended game mechanics.

Severity Justification

This issue is classified as Informational. It does not represent a vulnerability that can be exploited to harm the protocol or its users. However, it highlights a design flaw that will lead to a permanent loss of funds under foreseeable circumstances (user error) and should be addressed to improve the contract's robustness.

Updates

Appeal created

inallhonesty Lead Judge 9 days 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.