Last Man Standing

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

Unbounded Fee Control by Owner — Centralization & Front-Running Risk


Description

The contract allows the owner to set the claimFee arbitrarily via a public setter function (setClaimFee(uint256 _claimFee)) without any bounds or constraints. This introduces a centralization risk, where a malicious or compromised owner could:
Set the fee too high, preventing further participation.
Set the fee too low, allowing front-running, manipulation, or fee griefing.
Set the fee strategically, just before interacting with the game (e.g., claiming the throne) to front-run other players or drain users unfairly.
Withdraw all accumulated fees with no accountability, further centralizing profit.
-> Vulnerable Code:
```javascript
function setClaimFee(uint256 _claimFee) external onlyOwner {
claimFee = _claimFee;
}
```
There are no validations, such as:
- No maximum cap (maxFee)
- No minimum cap (minFee)
- No time delay (e.g., timelock)
- No governance control
- No off-chain notice

Risk

Impact:

  1. Denial of Game Participation:
    Owner sets claimFee to an extremely high value (e.g., 1,000 ETH), making it impossible for players to become king.

  2. Front-Running Manipulation
    Owner monitors mempool and right before another player sends a claimThrone() tx:

    • Lowers claimFee to undercut them.

    • Sends their own tx with a lower fee.

    • Raises the fee back afterward.
      This allows the owner to front-run and dominate the game unfairly.


  3. Player Griefing or Lock-in
    Owner sets the claimFee to a low value while also being king, making it easy for bots or scripts to repeatedly claim throne, forcing gas wars or griefing legitimate players.


  4. Centralized Fund Drain
    Owner withdraws all platformFeesBalance via withdrawPlatformFees() without restrictions or caps, with no requirement to redistribute or prove fairness.

Proof of Concept

- Owner deploys the contract and becomes initial currentKing.
- Monitors the mempool for a user sending claimThrone() with fee X.
- Calls setClaimFee(X - 1 wei) and sends own claimThrone() with that value.
- Reverts the fee or increases it to lock out others.
- Later, calls withdrawPlatformFees() and drains funds.

Recommended Mitigation

=> Add Fee Bounds:
```javascript
require(_claimFee >= minFee && _claimFee <= maxFee, "Fee out of range");
```
=> Add Delay for Fee Changes:
Schedule changes with a delay (e.g., 1 hour) to allow fair notice.
=> Emit Events for Fee Updates:
Improve transparency.
=> Limit Owner Withdrawals:
Allow withdrawals only under certain conditions (e.g., after grace period or only a percentage at a time).
Consider multi-sig governance or DAO control.
=> Document Risks:
If design is intended to be centralized, clearly document this for users.
Updates

Appeal created

inallhonesty Lead Judge 16 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.