Last Man Standing

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

Unplayable game

Root + Impact

Description

The throne could not be claimed by anyone because the claimThrone function reverts if the current king and the claimer are different. Since the address of the current king is address 0 at the initialization, the game is unplayable.

Moreover, the game can't be terminated or reset due to checks done on address 0 for the declareWinner function and on the state of the game for the resetGame function.

function claimThrone() external payable gameNotEnded nonReentrant {
...
require(
msg.sender == currentKing,
"Game: You are already the king. No need to re-claim."
);
...
}
function declareWinner() external gameNotEnded {
require(
currentKing != address(0),
"Game: No one has claimed the throne yet."
);
gameEnded = true;
...
}
function resetGame() external onlyOwner gameEndedOnly {}

Risk

Likelihood: This happen at the initialization of the smart contract

Impact: Game unplayable

Proof of Concept

function testUnplayableGame() public {
vm.prank(player1);
vm.expectRevert("Game: You are already the king. No need to re-claim.");
game.claimThrone{value: 0.5 ether}();
vm.expectRevert("Game: No one has claimed the throne yet.");
game.declareWinner();
vm.prank(deployer);
vm.expectRevert("Game: Game has not ended yet.");
game.resetGame();
}

Recommended Mitigation

function claimThrone() external payable gameNotEnded nonReentrant {
...
require(
- msg.sender == currentKing,
+ 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.