Last Man Standing

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

Unbounded `claimFee` Growth Can Make Game Inaccessible

Unbounded claimFee Growth Can Make Game Inaccessible

Description

The claimThrone() function increases claimFee by a fixed percentage after each successful claim:

claimFee = claimFee + (claimFee * feeIncreasePercentage) / 100;

Because this update is compounding and unbounded, the claim fee grows exponentially over time. There is no upper cap to stop the growth.

claimFeen​=claimFee0​×(1+100feeIncreasePercentage​)n

Where:

  • claimFee0 = initial claim fee

  • feeIncreasePercentage = % increase per claim

  • n = number of throne claims so far


    Initial = 0.1 ETH, feeIncreasePercentage = 10%

    | Claim # | Claim Fee (ETH) |

    | ------- | --------------- |

    | 1 | 0.1000 |

    | 2 | 0.1100 |

    | 3 | 0.1210 |

    | 4 | 0.1331 |

    | 5 | 0.14641 |

    | 10 | 0.25937 |

    | 20 | 0.67275 |

    | 30 | 1.745 |


By claim 30, the fee is already ~1.75 ETH.

Risk

Likelihood: High

  • This occurs every game session as long as the throne is actively claimed multiple times.

  • No special conditions are needed; the natural game mechanic causes it.

Impact: High

  • Economic Barrier: The game becomes prohibitively expensive for new players, killing participation.

  • Wealth Concentration: Early players (or colluding addresses) can inflate fees to lock out others.

  • Game Stagnation: Pot growth stalls if no one is willing to pay the high fee.

Proof of Concept

From the below demonstration fee's continually grow and can potentially discourage players.

function test_ClaimFeeGrowth_To100ETH() public {
uint256 targetFee = 100 ether;
uint256 claimCount = 0;
address[2] memory players = [makeAddr("player1"), makeAddr("player2")];
vm.deal(players[0], 1000 ether);
vm.deal(players[1], 1000 ether);
uint256 playerIndex = 0;
while (game.claimFee() < targetFee) {
vm.startPrank(players[playerIndex]);
game.claimThrone{value: game.claimFee()}();
vm.stopPrank();
claimCount++;
playerIndex = (playerIndex + 1) % players.length;
}
console2.log("Reached fee (ETH):", game.claimFee() / 1e18);
console2.log("Claims needed:", claimCount);
}
[PASS] test_ClaimFeeGrowth_To100ETH() (gas: 2448199)
Logs:
Reached fee (ETH): 105
Claims needed: 73
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 7.59ms (5.79ms CPU time)

Recommended Mitigation

Introduce a maximum claim fee cap to prevent exponential growth from making the game inaccessible:

claimFee = claimFee + (claimFee * feeIncreasePercentage) / 100;
+ if (claimFee > maxClaimFee) {
+ claimFee = maxClaimFee;
+ }
Updates

Appeal created

inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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

Give us feedback!