Last Man Standing

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

Unauthorized participation of `deployer` in the game, allows him to earn regular prizes

Root + Impact

Unauthorized participation of deployer in the game, allows him to earn regular prizes

Description

Uncomplete validation within function claimThone() allows the Deployer to participate in the game and claim the throne. Thus Deployer is eligible to earn regular rewards like all other participants in the game. But granting them an unfair and unauthorized competitive advantage, since as an Owner he can changes the game parameters.

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.");
@> // missing validation check: msg.sender != owner()

According to the protocol requirements:

### 1. Owner (Deployer)
**Powers:**
* Deploys the `Game` contract.
* Can update game parameters: `gracePeriod`, `initialClaimFee`, `feeIncreasePercentage`, `platformFeePercentage`.
* Can `resetGame()` to start a new round after a winner has been declared.
* Can `withdrawPlatformFees()` accumulated from claims.
**Limitations:**

It is not explicitly stated that the Deployer is allowed to invoke the claimThrone() function. This omission leads to a misalignment between the intended design and the actual implementation, where the claimThrone() method permits the Deployer to become the King, effectively making them a participant in the game and eligible to receive rewards.

A potential exploit scenario is as follows:

  1. The Deployer calls claimThrone(), becomes the current King, and pays the required claimFee.

  2. Having privileged control over the game parameters, the Deployer can then significantly reduce the gracePeriod

  3. Subsequently secures the prize by invoking declareWinner() — either through a standard transaction or by monitoring the mempool and executing a front-running attack to preempt other participants.

This behavior violates the protocol’s role separation expectations and introduces a centralization risk, where the Deployer can manipulate game outcomes for personal gain.

Risk

Likelihood: High

Impact:

  • The claimThrone() implementation breaches the protocol’s intended role separation, introducing centralization and trust risks.

  • The Deployer can become King, effectively participating as a player and receiving rewards.

  • With privileged control over game parameters, the Deployer can manipulate outcomes for personal benefit.

Proof of Concept

function testClaimThrone_DeployerIsAbleToClaimTheThrone() public {
// dump deployer address
console2.log("deployer: ", deployer);
// initil king -> initial address(0)
address initialKing = game.currentKing();
console2.log("initialKing: ", initialKing);
// deployer claims the trone
vm.prank(deployer);
game.claimThrone{value: 1 ether}();
// current king is now deployer
address newKing = game.currentKing();
console2.log("newKing: ", newKing);
}

Tools Used

Manual review
Foundry

Recommended Mitigation

Add validation to claimThone() function as follows:

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(msg.sender != owner(), "Game: Owner is not allowed to claim the throne and become a king.");

This change ensures the Deployer adheres to their designated role within the game, eliminating their ability to become King and participate as a regular player. It prevents them from earning rewards while retaining the unfair advantage of being the contract Owner.

Updates

Appeal created

inallhonesty Lead Judge 29 days ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
vladich0x Submitter
28 days ago
inallhonesty Lead Judge
26 days ago
inallhonesty Lead Judge 25 days ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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