Last Man Standing

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

Deployer Can Drain the Pot

Description

The defensive check below does not work as intended:

if (currentPlatformFee > (sentAmount - previousKingPayout)) {
currentPlatformFee = sentAmount - previousKingPayout;
}

This is because previousKingPayout is set to 0 on every call. As a result, the deployer can make currentPlatformFee a very large amount by setting platformFeePercentage to a high value.

This check will always pass:

If platformFeePercentage is 50%, then:
0.55 > (1.1 - 1)currentPlatformFee = 0.1, which correctly limits the platform fee.
But if previousKingPayout is 0, then:
0.55 < (1.1 - 0)currentPlatformFee = 0.55,
which makes the platform fee exceed the available post-payout balance.

At some point, the platform fee exceeds the pot, leaving no incentive for new players to claim the throne due to the low or zero reward.

Proof of Concept

Before that, edit this value in Game.t.sol just to show the damage:

+ import "@openzeppelin/contracts/utils/Strings.sol";
- uint256 public constant FEE_INCREASE_PERCENTAGE = 10;
- uint256 public constant PLATFORM_FEE_PERCENTAGE = 5;
+ uint256 public constant FEE_INCREASE_PERCENTAGE = 20;
+ uint256 public constant PLATFORM_FEE_PERCENTAGE = 80;
+ address public randomPlayer;

then Add this to Game.t.sol:

function testclaimThrone() public {
console2.log("total pot amount:", game.pot() / 1e15);
console2.log("platform fees balance:", game.platformFeesBalance() / 1e15);
console2.log("claim fee:", game.claimFee() / 1e15);
console2.log("__________________________________________________________");
for (uint i = 0; i < 21; i++) {
randomPlayer = makeAddr(Strings.toString(i));
vm.deal(randomPlayer, 10 ether);
uint256 claimfee = game.claimFee();
vm.startPrank(randomPlayer);
game.claimThrone{value: claimfee}();
vm.stopPrank();
}
console2.log("total pot amount:", game.pot() / 1e15);
console2.log("platform fees balance:", game.platformFeesBalance() / 1e15);
console2.log("claim fee:", game.claimFee() / 1e15);
}

Then run:
forge test --match-test testclaimThrone -vv


🧾 Output

Logs:
total pot amount: 0
platform fees balance: 0
claim fee: 100
__________________________________________________________
total pot amount: 4500
platform fees balance: 18002
claim fee: 4600

As shown, the claimFee eventually becomes greater than the total pot,
which leads to no profit for claiming the throne — discouraging participation.

Recommended Mitigation

you need to make previousKingPayout state variable and update it at the end of claimThrone() , not setting it to 0 in every call of claimThrone()


You should declare `previousKingPayout` a state variable, and update it at the end of each `claimThrone()` call, instead of resetting it to `0` every time.
```diff
+ uint256 public previousKingPayout;
...
- uint256 previousKingPayout = 0;
...
+ previousKingPayout = sentAmount;
```
This ensures `currentPlatformFee` is always constrained by a realistic, up-to-date value.
Updates

Appeal created

inallhonesty Lead Judge about 1 month ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
alicrali33 Submitter
about 1 month ago
inallhonesty Lead Judge
about 1 month ago
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.