Last Man Standing

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

Missing Previous King Payout Contradicts Documentation and Game Economics

Description

The Game::claimThrone() function promises in its documentation to distribute "a small portion of the new claim fee" to the dethroned king. However, the implementation hardcodes previousKingPayout = 0 and contains no logic to calculate or transfer funds to previous kings. This creates a critical discrepancy where:

  • Documentation misleads players about game mechanics

  • Previous kings receive zero compensation despite protocol promises

  • Game economics are broken, as early kings subsidize the pot without reward

// Root cause in the codebase with @> marks to highlight the relevant section
/**
* @dev Allows a player to claim the throne by sending the required claim fee.
* If there's a previous king, a small portion of the new claim fee is sent to them.
* A portion also goes to the platform owner, and the rest adds to the pot.
*/
function claimThrone() external payable gameNotEnded nonReentrant {
require(msg.value >= claimFee, "Game: Insufficient ETH sent to claim the throne.");
require(msg.sender == currentKing, "Game: You are already the king. No need to re-claim.");
uint256 sentAmount = msg.value;
@> 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;
// Update game state
currentKing = msg.sender;
lastClaimTime = block.timestamp;
playerClaimCount[msg.sender] = playerClaimCount[msg.sender] + 1;
totalClaims = totalClaims + 1;
// Increase the claim fee for the next player
claimFee = claimFee + (claimFee * feeIncreasePercentage) / 100;
emit ThroneClaimed(
msg.sender,
sentAmount,
claimFee,
pot,
block.timestamp
);
}

The variable previousKingPayout is declared but never initialized with actual payout logic. The code only allocates funds to the platform fee and pot, completely ignoring payouts to dethroned kings.

Risk

Likelihood:

  • Affects 100% of throne claims after the first king

  • Easily verifiable by reading the function logic

  • No conditionals bypass the flaw

Impact:

  • Previous kings lose expected ETH payouts

  • Documentation describes nonexistent mechanics

  • Disincentivizes early participation; breaks core "King of the Hill" dynamic

Proof of Concept

uint256 previousKingPayout = 0; // Hardcoded to zero
// ...
currentPlatformFee = (sentAmount * platformFeePercentage) / 100;
pot = pot + (sentAmount - currentPlatformFee); // Rest goes to pot

No transfers to currentKing before it gets overwritten.

Simulation:

King A claims throne with 1 ETH
→ Pot = 0.95 ETH (assuming 5% platform fee)

King B overthrows with 1.1 ETH
King A receives 0 ETH
→ Pot grows to 2.045 ETH (0.95 + [1.1 - 5% fee])

Mathematical Proof:
The payout formula never executes:

// EXPECTED: (Missing in code)
uint256 kingPayout = (msg.value * KING_PAYOUT_PERCENT) / 100;
payable(previousKing).transfer(kingPayout);

Recommended Mitigation

Implement the documented payout logic:

// Add after fee calculation
if (currentKing != address(0)) {
uint256 kingPayout = (msg.value * KING_PAYOUT_PERCENT) / 100; // e.g., 10%
payable(currentKing).transfer(kingPayout);
amountToPot = sentAmount - currentPlatformFee - kingPayout;
} else {
amountToPot = sentAmount - currentPlatformFee;
}
pot += amountToPot;

Add checks:

  • Ensure kingPayout doesn’t exceed (sentAmount - platformFee)

  • Use call{value} over transfer() for reentrancy safety

Updates

Appeal created

inallhonesty Lead Judge about 1 month 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.