Last Man Standing

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

M01. Previous King Payout Logic Declared but Not Implemented

Root + Impact

Description

Normal behavior:
In king-of-the-hill-style blockchain games, it is common practice to reward the previous king with a portion of the ETH used by the new challenger to claim the throne. This incentivizes early participation and increases player engagement, since dethroned players can still earn partial rewards.

Issue:
While the claimThrone() function defines a variable previousKingPayout and includes a defensive check to ensure the platform fee doesn't exceed available funds after such a payout, the actual logic to compute or transfer the previous king's share is completely missing. The previousKingPayout is never updated, and no ETH is reserved or assigned to the previous king.

This results in zero compensation for dethroned players, despite the code suggesting such a mechanism was intended.

function claimThrone() external payable gameNotEnded nonReentrant {
...
uint256 previousKingPayout = 0;
uint256 currentPlatformFee = 0;
uint256 amountToPot = 0;
// Calculate platform fee
currentPlatformFee = (sentAmount * platformFeePercentage) / 100;
// Defensive check to ensure platformFee doesn't exceed available amount after previousKingPayout
@> if (currentPlatformFee > (sentAmount - previousKingPayout)) {
@> currentPlatformFee = sentAmount - previousKingPayout;
}
platformFeesBalance = platformFeesBalance + currentPlatformFee;
// Remaining amount goes to the pot
amountToPot = sentAmount - currentPlatformFee;
pot = pot + amountToPot;
...
}

Risk

Likelihood:

  • Always occurs when a new player claims the throne.

  • The previousKingPayout variable is always 0, because it is never set.

Impact:

  • The previous king receives no compensation, which reduces the game’s fairness.

  • Players have less incentive to participate early, resulting in lower claim activity and smaller pots.

  • Misleads readers or developers expecting a previous-king payout due to the presence of related logic.


Proof of Concept

// Setup: Alice becomes king
game.claimThrone{value: 1 ether}();
address alice = game.currentKing();
// Bob claims the throne
vm.prank(bob);
game.claimThrone{value: game.claimFee()}();
// Check: Alice's balance should have increased — but it didn't
assert(game.pendingWinnings(alice) == 0);

Recommended Mitigation

Implement logic to allocate a portion of the new claim fee to the previous king, using a configurable percentage (previousKingRewardPercentage) or a fixed share:

+ uint256 previousKingPayout = 0;
+ address prevKing = currentKing;
+ if (prevKing != address(0)) {
+ previousKingPayout = (sentAmount * previousKingRewardPercentage) / 100;
+ pendingWinnings[prevKing] += previousKingPayout;
+ }
uint256 currentPlatformFee = (sentAmount * platformFeePercentage) / 100;
- if (currentPlatformFee > (sentAmount - previousKingPayout)) {
- currentPlatformFee = sentAmount - previousKingPayout;
- }
platformFeesBalance += currentPlatformFee;
uint256 amountToPot = sentAmount - currentPlatformFee - previousKingPayout;
pot += amountToPot;

You would also need to add a new state variable:

uint256 public previousKingRewardPercentage; // e.g., set to 10 (10%) solidity

And set it during the constructor or via an onlyOwner setter.

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.