Summary
The claimThrone() function will always revert on the first call due to an incorrect equality check.
Description
In the original audit comment, the code shows:
require(msg.sender == currentKing, "Game: You are already the king. No need to re-claim.");
At initial state, currentKing is address(0). Since msg.sender can never be address(0) (it's always the caller's address), this require statement will ALWAYS fail on the first call, making the contract completely unusable.
Note: The provided contract code in the main analysis had this corrected to !=, but the original audit comment shows the problematic == operator.
Root Cause
Incorrect comparison operator in the require statement:
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.");
When currentKing is address(0) initially, no external address can ever equal address(0), so the require will always revert.
Impact
-
Complete Contract Failure: No one can ever claim the throne
-
Total Fund Loss: Contract becomes completely unusable after deployment
-
Deployment Waste: Entire contract deployment is wasted
-
Critical Business Logic Failure: Core functionality is broken
Proof of Concept
function testDOSAtInitialState() public {
vm.prank(deployer);
Game buggyGame = new Game(
INITIAL_CLAIM_FEE,
GRACE_PERIOD,
FEE_INCREASE_PERCENTAGE,
PLATFORM_FEE_PERCENTAGE
);
assertEq(buggyGame.currentKing(), address(0));
vm.prank(player1);
vm.expectRevert("Game: You are already the king. No need to re-claim.");
buggyGame.claimThrone{value: INITIAL_CLAIM_FEE}();
vm.prank(player2);
vm.expectRevert("Game: You are already the king. No need to re-claim.");
buggyGame.claimThrone{value: INITIAL_CLAIM_FEE}();
assertEq(buggyGame.currentKing(), address(0));
}
function testCorrectImplementationWorks() public {
vm.prank(player1);
game.claimThrone{value: INITIAL_CLAIM_FEE}();
assertEq(game.currentKing(), player1);
vm.prank(player1);
vm.expectRevert("Game: You are already the king. No need to re-claim.");
game.claimThrone{value: INITIAL_CLAIM_FEE * 2}();
}
Recommended Mitigation
Change the equality operator to inequality:
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.");
}