Last Man Standing

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

Locked Funds from Untracked ETH Transfers

Locked Funds from Untracked ETH Transfers

Description

The contract has a receive() function

receive() external payable {}

which allows anyone to send ETH directly to the contract without triggering any game logic.

However, the game’s accounting only updates pot and platformFeesBalance inside functions like claimThrone().
ETH sent directly to the contract is not tracked in any variable, nor is it accessible through existing withdrawal mechanisms (other than via withdrawPlatformFees() which only applies to platform fees).

As a result, ETH sent directly is effectively locked inside the contract — it cannot be withdrawn by players or the owner, and will never be part of the prize pot or fees.

Risk

Likelihood:

  • Medium — Possible to trigger accidentally by users sending funds directly.

  • High if attackers deliberately send funds to create a “honeypot” appearance in the UI

Impact:

  • Funds sent directly are permanently locked in the contract.

  • Contract balance grows without a corresponding mechanism to retrieve those funds.

  • Potential gas waste and user frustration.

Proof of Concept

Send Any amount of ETH to contract and its unredeemable

// Direct ETH transfer to contract
(bool success,) = payable(gameAddress).call{value: 10 ether}("");
require(success);
// The pot and platform fees remain unchanged
assertEq(game.pot(), 0);
assertEq(game.platformFeesBalance(), 0);
// 10 ETH is now stuck forever
assertEq(address(game).balance, 10 ether);

Recommended Mitigation

Devs can Implement an Owner Sweep for Untracked Funds or decide to prevent direct sending of ETH

function sweepUntrackedFunds() external onlyOwner {
uint256 untracked = address(this).balance - (pot + platformFeesBalance);
require(untracked > 0, "No untracked funds");
(bool success,) = payable(owner()).call{value: untracked}("");
require(success, "Sweep failed");
}
# Or Prevent Direct ETH Transfers
receive() external payable {
revert("Direct ETH transfers not allowed");
}
Updates

Appeal created

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

Give us feedback!