Last Man Standing

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

Fee Increase Percentage Set to Zero Disables Fee Escalation

Root + Impact

Description

  • Normal behavior:
    The feeIncreasePercentage parameter defines by what percentage the throne claim fee (claimFee) increases after each successful claim, implementing a progressive, escalating cost mechanism designed to encourage timely claiming and economically balance the game.

  • Specific issue:
    The contract allows feeIncreasePercentage to be set to zero during deployment or through the owner-updatable updateClaimFeeParameters method. When this happens, the claimFee never increases after claims, effectively disabling the escalating fee feature critical to the game’s balance and incentive structure.

// Fee increase percentage allowed to be zero in constructor and update method
require(_feeIncreasePercentage <= 100, "Game: Fee increase percentage must be 0-100."); // Zero allowed
// Fee increase calculation during claim
claimFee = claimFee + (claimFee * feeIncreasePercentage) / 100;

Risk

Likelihood: Moderate

  • The owner or deployer can easily set the feeIncreasePercentage to zero intentionally or by mistake during deployment or configuration updates.

  • Because the parameter is owner-controlled and also settable at deployment, this misconfiguration can persist unnoticed unless thoroughly tested.

Reasons:

  • This parameter is involved in every claim transaction that adjusts the claimFee.

  • The game mechanics rely heavily on increasing claim fees to maintain incentives and fair competition.

Impact: High (Game Logic Impact)

  • The claim fee remains constant at the initial value across all claims.

  • Players can repeatedly claim the throne at a low fixed fee, potentially enabling griefing attacks or economic stalling of the game.

  • The escalating “king of the hill” mechanic is disabled, potentially undermining the entire purpose of the game contract.

  • The pot and incentive structures may behave unexpectedly, reducing player engagement and platform revenue.

  • The game becomes predictable and easily gamed, harming fairness and sustainability.

Proof of Concept

function testClaimThrone_BugOnlyCurrentKingCanClaim() public {
// claim throne with player1 then try to claim again with player2
vm.startPrank(player1);
game.claimThrone{value: INITIAL_CLAIM_FEE}();
vm.stopPrank();
vm.startPrank(player2);
// player2 tries to claim the throne again and then maliciousActor tries to claim the throne
game.claimThrone{value: INITIAL_CLAIM_FEE}();
vm.stopPrank();
vm.startPrank(maliciousActor);
// maliciousActor tries to claim the throne
game.claimThrone{value: INITIAL_CLAIM_FEE}();
vm.stopPrank();
// declare winner and then check the balance of maliciousActor
address winner = game.currentKing();
assertEq(winner, maliciousActor, "The current king should be player1.");
}

Recommended Mitigation

Where to apply:

  • In the constructor, replace the existing require line checking _feeIncreasePercentage.

  • In the updateClaimFeeParameters function’s modifier / require block, apply the same stricter check.

- // Allow zero feeIncreasePercentage in constructor and update functions
- require(_feeIncreasePercentage <= 100, "Game: Fee increase percentage must be 0-100.");
+ // Enforce feeIncreasePercentage must be between 1 and 100 (no zero)
+ require(_feeIncreasePercentage > 0 && _feeIncreasePercentage <= 100, "Game: Fee increase percentage must be between 1 and 100.");
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.