Last Man Standing

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

Owner can keep the entire amount from a `claimThrone()` call

Root + Impact

Description

The owner in Game can front-run a player calling the claimThrone() function and update the platformFeePercentage value to 100.

function claimThrone() external payable gameNotEnded nonReentrant {
require(msg.value >= claimFee, "Game: Insufficient ETH sent to claim the throne.");
require(msg.sender != currentKing, "Game: You are already the king. No need to re-claim.");
uint256 sentAmount = msg.value;
uint256 previousKingPayout = 0;
uint256 currentPlatformFee = 0;
uint256 amountToPot = 0;
// Calculate platform fee
@> currentPlatformFee = (sentAmount * platformFeePercentage) / 100;
// Defensive check to ensure platformFee doesn't exceed available amount after previousKingPayout
@> if (currentPlatformFee > (sentAmount - previousKingPayout)) {
currentPlatformFee = sentAmount - previousKingPayout;
}
platformFeesBalance = platformFeesBalance + currentPlatformFee;
// Remaining amount goes to the pot
@> amountToPot = sentAmount - currentPlatformFee;
pot = pot + amountToPot;
// Update game state
currentKing = msg.sender;
lastClaimTime = block.timestamp;
playerClaimCount[msg.sender] = playerClaimCount[msg.sender] + 1;
totalClaims = totalClaims + 1;
// Increase the claim fee for the next player
claimFee = claimFee + (claimFee * feeIncreasePercentage) / 100;
emit ThroneClaimed(
msg.sender,
sentAmount,
claimFee,
pot,
block.timestamp
);
}

Risk

Likelihood:

It is a fairly simple execution for the owner to do this. Thus, the likelihood is pretty high. Owner will receive more funds, so he is also incentivized to do so.

Impact:

  • Platform fee becomes 100% of the sentAmount and owner gets to keep it entirely

  • Nothing is added to the pot even though throne was claimed successfully

Proof of Concept

Here's a test case proving the claim:

function test_OwnerTakesEverything() public {
vm.prank(player2);
game.claimThrone{value: 0.2 ether}();
vm.prank(player3);
game.claimThrone{value: 0.3 ether}();
uint256 potBefore = game.pot();
vm.prank(deployer);
game.updatePlatformFeePercentage(100); // updates platform fee to 100%
vm.prank(player1);
game.claimThrone{value: 1 ether}(); // entire amount gets added to platformFeesBalance
uint256 potAfter = game.pot();
assert(potBefore == potAfter);
}

Recommended Mitigation

There should be a maximum threshold for the platform fee value

Updates

Appeal created

inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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

Give us feedback!