Last Man Standing

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

Owner Throne Claim + Mid-Game gracePeriod Update Enables Full Theft of Pot & Platform Fees (Centralized Abuse/Rug Potential)

Root + Impact

Description

  • Normal Behaviour: Per spec, players (non-owners) claimThrone to become king and build the pot fairly, with gracePeriod fixed per round for expiration/winner declaration—owner updates params but cannot manipulate mid-active game (limits like "cannot declare before expiry" assume stable rules).

  • Issue: Owner claims throne (no restriction), updates gracePeriod mid-game to shorten (e.g., 1s), forces expiry (timestamp manipulable), declares self-winner—steals pot (user fees) + platform fees (double-dip), bypassing competition and eroding trustlessness.

// Root cause in the codebase with @> marks to highlight the relevant section
// In claimThrone(): No owner block
require(msg.value >= claimFee, "Game: Insufficient ETH sent to claim the throne.");
require(msg.sender != currentKing, "Game: Already the king."); // Assumed fixed from prior
@> // Root cause part 1: No require(msg.sender != owner())—allows owner claim/king
// In updateGracePeriod(): No state restriction
function updateGracePeriod(uint256 _newGracePeriod) external onlyOwner {
require(_newGracePeriod > 0, "Game: New grace period must be greater than zero.");
@> gracePeriod = _newGracePeriod; // Root cause part 2: No gameEndedOnly—mid-game rig
emit GracePeriodUpdated(_newGracePeriod);
}

Risk

Likelihood:

  • Reason 1 : Triggers post-owner claim (deterministic if owner intends)—no "if" prevention on update or claim.

  • Reason 2: Scales with pot size (more claims = bigger theft). Miner help for short grace edges(delay blocks ~15s).

Impact:

  • Impact 1: Full fund theft—pot (95%+ user ETH) + platform fees to owner, breaking "fair competition" (web3 core: trustless rules violated).

  • Impact 2: Central authority erosion—users waste gas/deposits on rigged game; trust lost, protocol abandoned (real-world: Similar rugs in DeFi games cause 80%+ TVL drops, refunds/legal backlash).

Proof of Concept

This Foundry test simulates the full chain (Owner join/claim + rig update + expiry + withdraw)

Output: [PASS] gas:~250k—verifies central risk in blockchain time/determinism.

function testOwnerClaimAndGraceAbuseStealsAll() public {
// Assume inverted require fixed (!= currentKing)
// Owner joins/claims as king
vm.prank(deployer);
game.claimThrone{value: INITIAL_CLAIM_FEE}();
assertEq(game.currentKing(), deployer); // Owner as king (abuse start)
// Players add to pot (sim fair play, but owner rigs)
vm.prank(player1);
game.claimThrone{value: game.claimFee()}(); // Pot grows with fees
assertEq(game.currentKing(), player1);
// Owner re-claims (joins again)
vm.prank(deployer);
game.claimThrone{value: game.claimFee()}();
uint256 initialPot = game.pot(); // User fees
uint256 initialFees = game.platformFeesBalance(); // Owner cut
// Rig: Shorten grace mid-game
vm.prank(deployer);
game.updateGracePeriod(1);
// Sim expiry
vm.warp(block.timestamp + 2);
// Declare self-winner
vm.prank(deployer);
game.declareWinner();
assertTrue(game.gameEnded());
assertEq(game.pendingWinnings(deployer), initialPot); // Pot theft
// Withdraw pot + fees
vm.prank(deployer);
game.withdrawWinnings(); // Pot
game.withdrawPlatformFees(); // Fees
// Assert owner got pot + fees (theft proof)
}

Recommended Mitigation

  1. Add Owner claim block in claimThrone - prevents insider kings/collusion (to some extent). However, the owner can still join from other external accounts.

  2. Add gameEndedOnly to update gracePeriod - locks changes to postend (next round only).Prevents central authority to change the gracePeriod mid-game.

- function updateGracePeriod(uint256 _newGracePeriod) external onlyOwner {
+ (claim function) require(msg.sender != owner(), "Game: Owner cannot claim to avoid conflicts"); // Block owner join
+ function updateGracePeriod(uint256 _newGracePeriod) external onlyOwner gameEndedOnly { // Lock mid-game
Updates

Appeal created

inallhonesty Lead Judge about 2 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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