Root + Impact
The require(msg.sender == currentKing) in Game::claimThrone function will always revert because variable currentKing is setted as address(0) ,causing there is no one can call claimThrone but the currentKing starts as address(0) should until first claim.And the Game::declareWinner function will always revert due to require(currentKing != address(0), "Game: No one has claimed the throne yet.");So the two function can not be called because currentKing always is address(0)
Description
When the game start, the currentKing is setted as address(0)
,but the currentKing = msg.sender; is the only way to change the currentKing,no one can call claimThrone succssfully.
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;
uint256 currentPlatformFee = 0;
uint256 amountToPot = 0;
currentPlatformFee = (sentAmount * platformFeePercentage) / 100;
if (currentPlatformFee > (sentAmount - previousKingPayout)) {
currentPlatformFee = sentAmount - previousKingPayout;
}
platformFeesBalance = platformFeesBalance + currentPlatformFee;
amountToPot = sentAmount - currentPlatformFee;
pot = pot + amountToPot;
@> currentKing = msg.sender;
lastClaimTime = block.timestamp;
playerClaimCount[msg.sender] = playerClaimCount[msg.sender] + 1;
totalClaims = totalClaims + 1;
claimFee = claimFee + (claimFee * feeIncreasePercentage) / 100;
emit ThroneClaimed(
msg.sender,
sentAmount,
claimFee,
pot,
block.timestamp
);
}
function declareWinner() external gameNotEnded {
@> require(currentKing != address(0), "Game: No one has claimed the throne yet.");
require(
block.timestamp > lastClaimTime + gracePeriod,
"Game: Grace period has not expired yet."
);
gameEnded = true;
pendingWinnings[currentKing] = pendingWinnings[currentKing] + pot;
pot = 0;
emit GameEnded(currentKing, pot, block.timestamp, gameRound);
}
Risk
Likelihood:
Impact:
claimThroneProof of Concept
paste the test in Game.t.sol
function testnoonecancall () public {
vm.prank(player1);
vm.expectRevert("Game: You are already the king. No need to re-claim.");
game.claimThrone{value:0.1 ether}();
vm.prank(player1);
vm.expectRevert("Game: No one has claimed the throne yet.");
game.declareWinner();
}
Recommended Mitigation