Last Man Standing

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

Missing Grace Period Enforcement in claimThrone()

Root + Impact

Description

  • The claimThrone() function should only allow a new player to claim the throne after the grace period has not passed since the last claim. This gives the current king a fair chance to remain king if no one challenges them during the Graceperiod.

  • Problem: The function does not check whether the grace period has expired. As a result, a new player can claim throne even after the graceperiod ends after the lastclaimTime.

Risk

Likelihood:

  • This will occur every time someone calls claimThrone() immediately after another claim, without waiting for the grace period to expire.

Impact:

  • Undermines the core mechanic of the game by removing the “GracePeriod" time check.

  • Players have option to claim throne whenever they want.

Proof of Concept

The follwoing POc demonstarte that due to the absence of the timecheck the player2 had the ability to call the claimThrone() even after the GracePeriod ends.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Test, console2} from "forge-std/Test.sol";
import {Game} from "../src/Game.sol";
contract GameTest is Test {
Game public game;
address public deployer;
address public player1;
address public player2;
// Initial game parameters for testing
uint256 public constant INITIAL_CLAIM_FEE = 0.1 ether; // 0.1 ETH
uint256 public constant GRACE_PERIOD = 1 days; // 1 day in seconds
uint256 public constant FEE_INCREASE_PERCENTAGE = 10; // 10%
uint256 public constant PLATFORM_FEE_PERCENTAGE = 5; // 5%
function setUp() public {
deployer = makeAddr("deployer");
player1 = makeAddr("player1");
player2 = makeAddr("player2");
vm.deal(deployer, 10 ether);
vm.deal(player1, 10 ether);
vm.prank(deployer);
game = new Game(
INITIAL_CLAIM_FEE,
GRACE_PERIOD,
FEE_INCREASE_PERCENTAGE,
PLATFORM_FEE_PERCENTAGE
);
}
function test_claimmthrone() external{
vm.prank(player1);
game.claimThrone{value: 1 ether}();
vm.warp(86600);
vm.prank(player2);
game.claimThrone{value: 4 ether}();
assertEq(game.currentKing(),player2);
}
}

Recommended Mitigation

By adding the check on time , the msiuse of the claimThron() can be mitigated.

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.");
+ require(!block.timestamp > lastClaimTime + Graceperiod, ""Game Ended ,Call the winner");
uint256 sentAmount = msg.value;
Updates

Appeal created

inallhonesty Lead Judge about 1 month ago
Submission Judgement Published
Validated
Assigned finding tags:

Game::claimThrone can still be called regardless of the grace period

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.