Last Man Standing

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

Incorrect Conditional in `Game::claimThrone` Prevents Throne Claims

Incorrect Conditional in Game::claimThrone Prevents Throne Claims

Description

  • As per the protocol, anyone should be able to claim the throne as long as they meet the requiments.

  • The require statement in the Game::claimThrone function contains an incorrect condition that prevents any player from claiming the throne. This directly breaks the core functionality of the protocol, which states that anyone can claim the throne provided they send a sufficient amount of ETH and the game round is still active.

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;
...
}

Risk

Likelihood:

  • This will occur as soon as any user (other than the current king) tries to call Game::claimThrone, even with the correct fee and during an active game round.

  • The error will always trigger for every eligible player, making the function unusable under expected game conditions.

Impact:

  • No new player will be able to claim the throne.

  • The game becomes non-functional, breaking its core purpose and economic flow.

Proof of Concept

The following test demonstrates that a player is unable to claim the throne, even when sending the correct amount of ETH. The test sets up the scenario, attempts to claim the throne, and expects a revert with the incorrect error message. This confirms the bug in the require condition.

function testClaimThrone() public {
console2.log("Current King: ", game.currentKing());
vm.startPrank(player1);
vm.expectRevert("Game: You are already the king. No need to re-claim.");
game.claimThrone{value: 0.1 ether}();
vm.stopPrank();
console2.log("New King: ", game.currentKing());
}

Recommended Mitigation

The second require condition should be inverted. Currently, it only allows the current king to proceed, which contradicts the intended logic. By changing the condition to msg.sender != currentKing, the function will correctly block the current king from re-claiming the throne, while allowing all other players to participate.

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;
uint256 previousKingPayout = 0;
uint256 currentPlatformFee = 0;
uint256 amountToPot = 0;
// Calculate platform fee
currentPlatformFee = (sentAmount * platformFeePercentage) / 100;
...
}
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!