Last Man Standing

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

`getRemainingTime()` returns wrong remaining time

Description

The problem is that when someone claims the throne, the remaining time resets to the gracePeriod, which leads to incorrect calculation of the remaining time and can cause the game to not finish after the grace period, or even never finish at all.

In this POC, we show the Remaining Time when player1 claims the throne immediately after the game starts, and player2 claims it after half a day has passed.

Proof of Concept

But before running the test, you need to correct this issue in claimThrone():

- 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.");

Then, add this test to Game.t.sol:

function testGetRemainingTime() public {
vm.startPrank(player1);
uint256 lastClaimTime = game.lastClaimTime();
uint256 currentTimestamp = block.timestamp;
uint256 remainingTime = game.getRemainingTime();
console2.log("When game started:");
console2.log("Last Claim Time:", lastClaimTime);
console2.log("Current Block Timestamp:", currentTimestamp);
console2.log("Grace Time:", GRACE_PERIOD);
console2.log("=> Remaining Time:", remainingTime);
vm.stopPrank();
vm.warp(block.timestamp + 43200);
vm.startPrank(player2);
game.claimThrone{value: 0.1 ether}();
uint256 newLastClaimTime = game.lastClaimTime();
uint256 newTimestamp = block.timestamp;
uint256 newRemainingTime = game.getRemainingTime();
console2.log("______________________________________________________");
console2.log("User claims throne after half a day:");
console2.log("New Last Claim Time:", newLastClaimTime);
console2.log("New Current Block Timestamp:", newTimestamp);
console2.log("Grace Time:", GRACE_PERIOD);
console2.log("=> New Remaining Time:", newRemainingTime);
vm.stopPrank();
}

Then run:

forge test --match-test testGetRemainingTime -vvv

Output

Ran 1 test for test/Game.t.sol:GameTest
[PASS] testGetRemainingTime() (gas: 175102)
Logs:
When game started:
Last Claim Time: 1
Current Block Timestamp: 1
Grace Time: 86400
=> Remaining Time: 86400
______________________________________________________
User claims throne after half a day:
New Last Claim Time: 43201
New Current Block Timestamp: 43201
Grace Time: 86400
=> New Remaining Time: 86400

As we see in the output, the remaining time did not decrease correctly.

Recommended Mitigation

You need to separate the game's startTime from lastClaimTime. Do not update it when the throne is claimed. Just declare it once at the start of the game using block.timestamp.

+ uint256 public startGame;
- lastClaimTime = block.timestamp;
+ startGame = block.timestamp;
- uint256 endTime = lastClaimTime + gracePeriod;
+ uint256 endTime = startGame + gracePeriod;
Updates

Appeal created

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

declareWinner time check is not properly done

0xalipede Auditor
about 1 month ago
nem0thefinder Auditor
about 1 month ago
alicrali33 Submitter
about 1 month ago
inallhonesty Lead Judge
about 1 month ago
inallhonesty Lead Judge about 1 month ago
Submission Judgement Published
Validated
Assigned finding tags:

declareWinner time check is not properly done

Support

FAQs

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