Last Man Standing

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

Logic Flaw in `Game::claimThrone()` Prevents Game from Starting

Description:

The Game::claimThrone() function contains an incorrect logic check:

function claimThrone() external payable gameNotEnded nonReentrant {
require(msg.value >= claimFee, "Game: Insufficient ETH sent to claim the throne.");
// incorrect logic
@> require(msg.sender != currentKing, "Game: You are already the king. No need to re-claim.");
}

This condition incorrectly restricts the ability to claim the throne to the currentKing only, which defeats the purpose of the game where new players should be able to challenge and claim the throne by paying the required fee. This results in the game being in a permanently blocked state after deployment.

Impact: HIGH

  • No player can successfully call claimThrone(), rendering the game non-functional.

  • The currentKing remains address(0), so no winner can be declared.

  • The game is in a blocked state from the beginning.

Proof of Concept:

function testNoOneCanClaimTheThrone() public {
console.log("Current king is", game.currentKing());
vm.startPrank(player1);
uint256 amount = 10 ether;
vm.expectRevert("Game: You are already the king. No need to re-claim.");
game.claimThrone{value: amount}();
}
[PASS] testNoOneCanClaimTheThrone() (gas: 50563)
Logs:
Current king is 0x0000000000000000000000000000000000000000
Traces:
[50563] GameTest::testNoOneCanClaimTheThrone()
├─ [2446] 0x8Ad159a275AEE56fb2334DBb69036E9c7baCEe9b::currentKing() [staticcall]
│ └─ ← [Return] 0x0000000000000000000000000000000000000000
├─ [0] console::log("Current king is", 0x0000000000000000000000000000000000000000) [staticcall]
│ └─ ← [Stop]
├─ [0] VM::startPrank(player1: [0x7026B763CBE7d4E72049EA67E89326432a50ef84])
│ └─ ← [Return]
├─ [0] VM::expectRevert(custom error 0xf28dceb3: Game: You are already the king. No need to re-claim.)
│ └─ ← [Return]
├─ [26959] 0x8Ad159a275AEE56fb2334DBb69036E9c7baCEe9b::claimThrone{value: 10000000000000000000}()
│ └─ ← [Revert] revert: Game: You are already the king. No need to re-claim.
└─ ← [Stop]

Recommended Mitigation:

Update the claim logic to prevent the current king from re-claiming, while allowing new challengers to participate.

function claimThrone() external payable gameNotEnded nonReentrant {
- 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 2 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.