Last Man Standing

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

`Game::claimThrone` Missing payout logic for previous king

Description

  • In the description of Game::claimThrone it says that the previous king should receive a small portion of the new claim fee. The mentioned logic is not implemented.

function claimThrone() external payable gameNotEnded nonReentrant {
@> uint256 previousKingPayout = 0; // Always 0
}

Risk

Likelihood:

  • Everytime a contestant claims the throne the issue will occur

Impact:

  • Previous kings get no compensation, breaking the expected "King of the Hill" economics.

  • All funds incorrectly flow to pot instead of proper distribution

Proof of Concept

Note this is based on the mitigation displayed below

function testPreviousKingPayout() public {
vm.prank(player1);
game.claimThrone{value: 1 ether}();
uint256 player1BalanceBefore = player1.balance;
console2.log("Player 1 balance before:", player1BalanceBefore);
assertEq(game.currentKing(), player1);
assertEq(game.pot(), 0.95 ether); // 95% of 1 ether goes to the pot
assertEq(game.platformFeesBalance(), 0.05 ether); // 5% platform fee
vm.prank(player2);
game.claimThrone{value: 1.5 ether}();
assertEq(game.currentKing(), player2);
assertEq(game.pot(), 2.2325 ether);
assertEq(game.platformFeesBalance(), 0.1175 ether); // 0.05 + 0.0675 = 0.1175 ether -> because of the fee increase
uint256 player1BalanceAfter = player1.balance;
console2.log("Player 1 balance after:", player1BalanceAfter);
}

Recommended Mitigation

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.");
+ require(msg.sender != currentKing, "Game: You are already the king. No need to re-claim.");
uint256 sentAmount = msg.value;
+ address previousKing = currentKing;
+ if (previousKing != address(0)) {
+ previousKingPayout = (sentAmount * 10) / 100; // 10% to previous king
+ }
- currentPlatformFee = (sentAmount * platformFeePercentage) / 100;
+ uint256 remainingAmount = sentAmount - previousKingPayout;
+ currentPlatformFee = (remainingAmount * platformFeePercentage) / 100;
- if (currentPlatformFee > (sentAmount - previousKingPayout)) {
- currentPlatformFee = sentAmount - previousKingPayout;
- }
platformFeesBalance = platformFeesBalance + currentPlatformFee;
- amountToPot = sentAmount - currentPlatformFee;
+ amountToPot = remainingAmount - currentPlatformFee;
pot = pot + amountToPot;
+ // Pay previous king immediately
+ if (previousKingPayout > 0) {
+ (bool success, ) = payable(previousKing).call{value: previousKingPayout}("");
+ require(success, "Game: Failed to pay previous king");
+ }
// ... rest of function remains the same
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.