Last Man Standing

First Flight #45
Beginner FriendlyFoundrySolidity
100 EXP
View results
Submission Details
Impact: high
Likelihood: medium
Invalid

Uninitialized gracePeriod allows instant throne takeovers with no delay

Root + Impact

Description

  • Describe the normal behavior in one or more sentences

Normally, the contract should enforce a delay between throne claims using the gracePeriod variable, preventing users from claiming the throne too frequently.

  • Explain the specific issue or problem in one or more sentences

However, gracePeriod is never initialized, so it defaults to zero. This allows anyone to bypass the intended delay and claim the throne repeatedly without restriction, breaking game fairness and enabling abuse.

// Constructor or any function should initialize gracePeriod, but it’s missing
// As a result, the value remains 0 (default for uint256)
contract Game is Ownable {
address public currentKing;
uint256 public lastClaimTime;
uint256 public gracePeriod; // @> Not initialized anywhere, defaults to 0
The gracePeriod variable is declared but never set, which causes the claim cooldown logic to be ineffective.

Risk

Likelihood:

  • Reason 1 // Describe WHEN this will occur (avoid using "if" statements)

This will occur every time a user calls claimThrone() since gracePeriod is not set and defaults to 0.

  • Reason 2

Any user can continuously claim the throne without restriction, regardless of how recently the last claim occurred.

Impact:

  • Impact 1

The intended time-based challenge is completely bypassed, removing any strategic gameplay or delay between claims.

  • Impact 2

  • A single player can monopolize the throne by spamming claims, leading to unfair gameplay and loss of engagement.


Proof of Concept

Deploy the contract without setting gracePeriod.

  • Call claimThrone() from any address, it will succeed.

  • Immediately call claimThrone() again from the same or a different address it will succeed again without delay.

  • Repeat this process multiple times within the same block or in rapid succession.

Since gracePeriod == 0, the check:

require(block.timestamp >= lastClaimTime + gracePeriod, "Wait for grace period to pass");
always passes, making the delay logic ineffective.

Recommended Mitigation

Set a non-zero gracePeriod during contract deployment or through a restricted setter function to ensure the time delay between claims is enforced as intended. This prevents users from spamming claimThrone() without restriction.

- remove this code
The issue is due to missing initialization, so nothing needs to be removed.
+ add this code
function setGracePeriod(uint256 _gracePeriod) external onlyOwner {
gracePeriod = _gracePeriod;
}
Updates

Lead Judging Commences

inallhonesty Lead Judge
5 months ago

Appeal created

inallhonesty Lead Judge 5 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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

Give us feedback!