Last Man Standing

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

Critical Logic Vulnerability in claimThrone() Allows Permanent Denial of Service on “Last Man Standing” Game Contract

Root + Impact

Description

  • Normal Behavior:
    The intended game logic is that any new player can pay the required claimFee to replace the current king. Over time, the claim fee increases, and once the gracePeriod expires, the current king wins the accumulated 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.");
...
}

Risk


  • Likelihood:

    • This will occur immediately on the first claim attempt after deployment since currentKing defaults to address(0) and no user can ever equal address(0).

    • Even if somehow a king is set, no subsequent players will ever be able to participate because they will always fail the condition.

    Impact:

    • The game becomes completely unusable (Denial of Service).

    • Users’ ETH is locked in a contract with no functional game flow.

    • The owner cannot successfully run a game round, making the entire system broken.

Proof of Concept

function test_DoS_ByFirstKing() public {
Game game = new Game(1 ether, 60, 10, 5);
// First player tries to claim the throne
vm.deal(address(0xBEEF), 1 ether);
vm.prank(address(0xBEEF));
vm.expectRevert("Game: You are already the king. No need to re-claim.");
game.claimThrone{value: 1 ether}(); // Always reverts
}

Recommended Mitigation

- 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.");
Updates

Appeal created

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