Last Man Standing

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

The `claimThrone` function requires players to overpay the claim fee without refunding the excess, which is unreasonable.

Description

  • The protocol specification states that players must send enough ETH to match or exceed the current claimFee.

  • However, when player activity is high, most players cannot precisely predict the exact claimFee required at the time of their transaction.

  • As a result, during simultaneous participation between well-funded and less-funded players, those with limited funds may fail to claim the throne due to underpaying, even by a small margin.

Risk

Impact:

  • Well-funded players may feel compelled to consistently overpay significantly to ensure their transaction succeeds, leading to unnecessary capital expenditure.

  • Less-funded players face a higher risk of failure, as they cannot afford to overpay and are more sensitive to exact fee requirements.

  • This design unfairly disadvantages players with limited resources and may discourage participation, undermining the game's accessibility and fairness.

Proof of Concept

  1. This verification assumes the claimThrone function has already fixed the following two issues:

    1. Correct initial check: require(msg.sender != currentKing, "Game: You are already the king. No need to re-claim.");

    2. Proper handling of the previous king's reward: uint256 previousKingPayout = (sentAmount * previousKngFeePercentage) / 100;

  2. Admin deploys the contract.

  3. Player player_rich_1 sends 0.1 ether and successfully calls claimThrone.

  4. Player player_rich_2 sends 0.105 ether and successfully calls claimThrone.

  5. Players player_rich_3 and player_pool_1 attempt to claim simultaneously.

  6. Player player_rich_3 sends 0.155 ether and successfully claims the throne.

  7. Player player_pool_1 sends 0.115 ether, which is below the current claimFee, and the call reverts.

Recommended Mitigation

  • Implement a mechanism to refund excess ETH sent by the player. This allows players to safely send more than the required fee without financial penalty:

function claimThrone() external payable gameNotEnded nonReentrant {
...
- uint256 sentAmount = msg.value;
+ uint256 sentAmount = claimFee;
...
+ // Return the excess claim fee to the player.
+ if (msg.value > claimFee) {
+ pendingWinnings[msg.sender] = pendingWinnings[msg.sender] + (msg.value - claimFee);
+ }
...
}
Updates

Appeal created

inallhonesty Lead Judge about 1 month ago
Submission Judgement Published
Validated
Assigned finding tags:

Overpayment not refunded, included in pot, but not in claim fee

Support

FAQs

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