Last Man Standing

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

Missed Payout to Last King in `claimThrone()`

Description

The claimThrone() function fails to implement the partial payout mechanism promised in the documentation for the "last king."
According to the project docs, the previous currentKing should receive a small portion of the next player's claimFee when overthrown.
However, the current code contains no logic to transfer or credit such a payout, resulting in the last king never receiving their due portion.

From the game documentation:

"Receives a small payout from the next player's claimFee (if applicable)."

This means that in the claimThrone() flow:

  1. A player (previousKing) is dethroned.

  2. The new king pays the claimFee.

  3. A portion of this claimFee should be sent to the previousKing immediately or credited to their pendingWinnings.

However, in the current claimThrone() implementation:

The claimFee is split between the platform fee and the pot.
There is no allocation to the previousKing.
The dethroned king receives nothing unless they win the pot after the grace period, which is unrelated to the small payout mechanism.

Impact:
Broken game mechanics: This is a direct mismatch between the documentation and actual implementation, causing incorrect in-game economics.
Financial loss for players: Previous kings lose the payout they were promised when a new king takes the throne.
Loss of incentive: Players may be discouraged from participating, as the small payout from being dethroned is one of the incentives for claiming the throne early.
Trust issues: If the docs claim a feature exists but it does not function, it undermines trust in the game’s fairness.

Proof of Concept

But before running the test, you need to correct this issue in claimThrone():

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

A simple test can show the missing payout:

function testLastKingPayoutMissing() public {
// Player1 claims throne
vm.startPrank(player1);
game.claimThrone{value: 0.1 ether}();
vm.stopPrank();
// Player2 claims throne, should pay part of fee to player1
uint256 balanceBefore = player1.balance;
vm.startPrank(player2);
game.claimThrone{value: 0.11 ether}();
vm.stopPrank();
uint256 balanceAfter = player1.balance;
// Expected: balanceAfter > balanceBefore
// Actual: No change in balance
assertEq(balanceAfter, balanceBefore, "No payout given to last king");
}

Recommended Mitigation

Implement a payout mechanism in claimThrone() to transfer a percentage of the incoming claimFee to the dethroned currentKing.

Suggested Fix:

uint256 payoutToLastKing = (msg.value * lastKingPayoutPercentage) / 100;
if (currentKing != address(0)) {
pendingWinnings[currentKing] += payoutToLastKing;
}
uint256 remaining = msg.value - payoutToLastKing;
// Continue normal distribution logic for remaining amount
Updates

Appeal created

inallhonesty Lead Judge about 2 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Missing Previous King Payout Functionality

Support

FAQs

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