Last Man Standing

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

Owner Can Raise `platformFeePercentage` Mid-Round to Drain Player Funds

Root + Impact

Description

  • The platformFeePercentage determines what portion of each throne claim is taken by the platform (owner) as a fee. It is deducted from every new player's payment before the remaining amount is added to the game pot.

  • However, the contract allows the owner to modify this fee at any time using the updatePlatformFeePercentage() function. This mutability introduces a significant rug-pull potential: the owner can increase the platform fee to nearly 100%, effectively draining all the users' future payments without warning. Users have no protection against this mid-game change, and may unknowingly interact with an unfair version of the game.

function updatePlatformFeePercentage(uint256 _newPlatformFeePercentage)
external
onlyOwner
isValidPercentage(_newPlatformFeePercentage)
{
@> platformFeePercentage = _newPlatformFeePercentage;
emit PlatformFeePercentageUpdated(_newPlatformFeePercentage);
}

Risk

Likelihood:

  • Can occur in any contract where the owner has malicious intent or is not publicly accountable. Since the owner is often considered trustworthy, the likelihood is rather low.

  • Also possible unintentionally through human error or careless administration (e.g., updating to 100 instead of 10).

Impact:

  • After the owner increases the platform fee to 100% mid-round, claiming the throne does not increase the pot amount anymore.

  • Unaware players might not have realized the platform fee update and unknowingly participate anyway, resulting in a bad risk-reward ratio.

  • The game becomes economically broken, as new players pay in but receive nothing in return - all funds go to the owner, creating the appearance of a scam or rug pull.

Proof of Concept

// Initial setup
game.claimThrone{value: 1 ether}(); // Player Alice pays 1 ETH
// Platform fee = 3%, pot = 0.97 ETH
// Owner maliciously increases the fee to 100%
game.updatePlatformFeePercentage(100);
// Player Bob is unaware of the fee update and claims the throne
game.claimThrone{value: 1.2 ether}();
// 100% of 1.2 ETH goes to owner, 0 ETH added to pot

Even if the round ends now and Bob wins the game, his payout would be 0.97 ETH (pot), which is less than his investment of 1.2 ETH.

Recommended Mitigation

The vulnerability can be mitigated by allowing the owner to update future round parameters at any time, but preventing the change from taking effect mid-round, preserving game integrity.

+ uint256 public nextRoundPlatformFeePercentage; // The platform fee for the next new round
...
constructor(
uint256 _initialClaimFee,
uint256 _gracePeriod,
uint256 _feeIncreasePercentage,
uint256 _platformFeePercentage
) Ownable(msg.sender) { // Set deployer as owner
...
+ nextRoundPlatformFeePercentage = _platformFeePercentage;
...
}
...
function resetGame() external onlyOwner gameEndedOnly {
currentKing = address(0);
lastClaimTime = block.timestamp;
pot = 0;
claimFee = initialClaimFee;
gracePeriod = initialGracePeriod;
+ platformFeePercentage = nextRoundPlatformFeePercentage;
gameEnded = false;
gameRound = gameRound + 1;
// totalClaims is cumulative across rounds, not reset here, but could be if desired.
emit GameReset(gameRound, block.timestamp);
}
...
function updatePlatformFeePercentage(uint256 _newPlatformFeePercentage)
external
onlyOwner
isValidPercentage(_newPlatformFeePercentage)
{
- platformFeePercentage = _newPlatformFeePercentage;
+ nextRoundPlatformFeePercentage = _newPlatformFeePercentage;
emit PlatformFeePercentageUpdated(_newPlatformFeePercentage);
}
...
Updates

Appeal created

inallhonesty Lead Judge about 1 month ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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