Last Man Standing

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

Previous King Never Receives Payout When Throne Changes

Previous King Never Receives Payout When Throne Changes

Description

  • Expected behaviour: When a new player claims the throne, a portion of their claimFee should be transferred to the previous king as a reward for holding the throne (per README lines 37-40).

  • Actual issue: previousKingPayout is hard-coded to 0 and never updated or transferred. Consequently the previous king’s balance remains unchanged when they are dethroned.

// Game.sol — claimThrone()
uint256 previousKingPayout = 0; // ← always zero
...
currentPlatformFee = (sentAmount * platformFeePercentage) / 100;
...
// No line updates previousKingPayout or pays it out

Risk

Likelihood:

  • Happens on every throne claim beyond the first round once the critical logic-reversal bug is fixed.

  • Players actively monitor rewards; once discovered they will perceive the game as unfair.

Impact:

  • Economic incentives break down; previous kings earn nothing, discouraging participation.

  • Reputation loss / potential fraud accusations because README promises a payout that is never delivered.

Proof of Concept

The Foundry test below simulates two players. After player 2 claims, player 1’s balance is exactly the same as before the claim, proving no payout occurred.

// Run with: forge test --match-contract PoCMissingPrevKingPayout -vvv
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Test} from "forge-std/Test.sol";
import {Game} from "../src/Game.sol";
/// @title PoC for Missing Previous King Payout
contract PoCMissingPrevKingPayout is Test {
Game internal game;
address internal player1 = address(0x1111);
address internal player2 = address(0x2222);
uint256 internal constant INITIAL_CLAIM_FEE = 0.1 ether;
uint256 internal constant GRACE_PERIOD = 1 days;
uint256 internal constant FEE_INCREASE_PERCENTAGE = 10;
uint256 internal constant PLATFORM_FEE_PERCENTAGE = 5;
function setUp() public {
vm.deal(player1, 10 ether);
vm.deal(player2, 10 ether);
game = new Game(
INITIAL_CLAIM_FEE,
GRACE_PERIOD,
FEE_INCREASE_PERCENTAGE,
PLATFORM_FEE_PERCENTAGE
);
// player1 becomes the initial king
vm.prank(player1);
game.claimThrone{value: INITIAL_CLAIM_FEE}();
}
function test_PreviousKingGetsZero() public {
// Snapshot player1 balance before second claim
uint256 balanceBefore = player1.balance;
// player2 claims with the updated claim fee
uint256 nextClaimFee = game.claimFee();
vm.prank(player2);
game.claimThrone{value: nextClaimFee}();
// player1 balance should be unchanged (no payout)
uint256 balanceAfter = player1.balance;
assertEq(balanceAfter, balanceBefore, "Previous king did not receive expected payout");
}
}

Recommended Mitigation

Either:

  1. Implement payout logic – decide on a percentage (e.g. 50 %) and credit the previous king before updating currentKing.

- uint256 previousKingPayout = 0;
+ uint256 previousKingPayout = (sentAmount * prevKingRewardPct) / 100;
+ pendingWinnings[currentKing] += previousKingPayout; // pull-based pattern
  1. Update documentation – if no payout is intended, remove the claim from the README and delete the dead previousKingPayout variable to avoid confusion.

Updates

Appeal created

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

Give us feedback!