Last Man Standing

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

Current King Can Block All Future Claims

Current King Prevents All Other Players From Claiming the Throne

Description

  • The game is designed so that any player can claim the throne by sending the required ETH fee, with the throne passing to the new player after payment

  • There's a critical logic error in the claimThrone() function that prevents anyone except the current king from claiming the throne, effectively breaking the core game mechanics

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."); // @> This check prevents anyone else from becoming king
// Rest of the function logic...
}

Risk

Likelihood: High

  • This vulnerability is triggered whenever any player (other than the current king) attempts to claim the throne

  • The incorrect logic check happens on every throne claiming attempt

  • Once someone becomes the first king, the game becomes permanently locked

Impact: High

  • Complete breakdown of the core game functionality - no throne changes can occur

  • First king becomes permanent winner as no one else can ever claim the throne

  • All ETH sent by other players attempting to claim the throne will be reverted

  • Game becomes unplayable after the first successful claim

Proof of Concept

// After deployment, player1 becomes the first king
vm.prank(player1);
game.claimThrone{value: INITIAL_CLAIM_FEE}(); // This succeeds
// Now player2 tries to claim with sufficient funds
vm.prank(player2);
vm.expectRevert("Game: You are already the king. No need to re-claim.");
game.claimThrone{value: nextClaimFee}(); // This will always fail
// The game is now permanently broken - only player1 can call claimThrone

Explanation: The require statement incorrectly uses == instead of !=, allowing only the current king to call the function. This breaks the core game mechanic where other players should overthrow the king.

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.");
// Rest of function logic remains the same...
}

Explanation: Change == to != so only non-kings can claim the throne, restoring the competitive gameplay where players can overthrow the current king.

Updates

Appeal created

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

Game::claimThrone `msg.sender == currentKing` check is busted

Support

FAQs

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

Give us feedback!