Last Man Standing

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

Platform Fee Calculated on Overpayment Instead of Required Amount

Root + Impact

Description

  • Normal behavior:
    Platform fees should be calculated only on the required claim fee amount, not on any overpayment.

    Specific issue:
    The platform fee is calculated on the entire msg.value sent by the user, including any overpayment, resulting in higher platform fees than intended.

function claimThrone() external payable gameNotEnded nonReentrant {
require(msg.value >= claimFee, "Game: Insufficient ETH sent to claim the throne.");
uint256 sentAmount = msg.value; // @> Uses entire amount sent
// ...
currentPlatformFee = (sentAmount * platformFeePercentage) / 100; // @> Fee on overpayment
}

Risk

Likelihood:

  • Users frequently make mistakes with decimal places or copy-paste wrong amounts.

  • Wallet interfaces may have bugs that cause overpayments.

Impact:

  • Platform receives unintended extra fees from user mistakes.

  • Users pay more in platform fees than the documented percentage.

  • Unfair extraction of value from accidental overpayments.

Proof of Concept

The following test demonstrates that platform fees are calculated on overpayments:

function testPlatformFeeOnOverpayment() public {
uint256 requiredFee = game.claimFee(); // 0.1 ETH
uint256 overpayment = 1 ether; // Player sends 1 ETH instead of 0.1 ETH
uint256 initialPlatformBalance = game.platformFeesBalance();
vm.startPrank(player1);
game.claimThrone{value: overpayment}();
vm.stopPrank();
uint256 platformFeeCharged = game.platformFeesBalance() - initialPlatformBalance;
uint256 expectedFeeOnRequired = (requiredFee * 5) / 100; // Should be 0.005 ETH
uint256 actualFeeOnOverpayment = (overpayment * 5) / 100; // Is 0.05 ETH
assertEq(platformFeeCharged, actualFeeOnOverpayment, "Platform fee calculated on overpayment");
assertTrue(platformFeeCharged > expectedFeeOnRequired, "Platform fee should only be on required amount");
}

Recommended Mitigation

Calculate platform fees only on the required claim fee amount, not on overpayments:

function claimThrone() external payable gameNotEnded nonReentrant {
require(msg.value >= claimFee, "Game: Insufficient ETH sent to claim the throne.");
- uint256 sentAmount = msg.value;
+ uint256 sentAmount = claimFee; // Use only required amount for calculations
// ...
currentPlatformFee = (sentAmount * platformFeePercentage) / 100;
+ // Handle overpayment separately (refund or add to pot without platform fee)
+ if (msg.value > claimFee) {
+ uint256 excess = msg.value - claimFee;
+ pot += excess; // Add excess directly to pot without platform fee
+ }
}
Updates

Appeal created

inallhonesty Lead Judge 14 days ago
Submission Judgement Published
Invalidated
Reason: Design choice
r4y4n3 Submitter
14 days ago
inallhonesty Lead Judge
13 days ago
inallhonesty Lead Judge 10 days ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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