Last Man Standing

First Flight #45
Beginner FriendlyFoundrySolidity
100 EXP
View results
Submission Details
Severity: medium
Valid

There is no functionality to send a small amount to the previous king.

Before fixing this bug, it is necessary to fix the vulnerability with currentKing

Root + Impact

Description

The description of the functionality states a small payout to the previous king, but the claimThrone() function lacks this functionality. This is also why the "Defensive check to ensure platformFee doesn't exceed available amount after previousKingPayout" is incorrectly checked.

function claimThrone() external payable gameNotEnded nonReentrant {
require(msg.value >= claimFee, "Game: Insufficient ETH sent to claim the throne.");
//@audit swap "==" to "!="
@> 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;
}

Risk

Likelihood:

  • A possible front-running scenario

Impact:

  • There is always one-last winner.

Proof of Concept

-

Recommended Mitigation

It is necessary to add a payout to the previous kings

// Game Parameters (Configurable by Owner)
uint256 public initialClaimFee; // The starting fee for a new game round
uint256 public feeIncreasePercentage; // Percentage by which the claimFee increases after each successful claim (e.g., 10 for 10%)
uint256 public platformFeePercentage; // Percentage of the claimFee that goes to the contract owner (deployer)
+ uint256 public prevKingRewardPercentage;
uint256 public initialGracePeriod; // The grace period set at the start of a new game round
...
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.");
+ require(msg.sender != currentKing, "Game: You are already the king. No need to re-claim.");
uint256 sentAmount = msg.value;
+ address previousKing = currentKing;
uint256 previousKingPayout = 0;
uint256 currentPlatformFee = 0;
uint256 amountToPot = 0;
// Calculate platform fee
currentPlatformFee = (sentAmount * platformFeePercentage) / 100;
+ // Calculate rewards previous king
+ if (previousKing != address(0)) {
+ previousKingPayout = (sentAmount * prevKingRewardPercentage) / 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;
+ // Sent reward previous king
+ if (previousKingPayout > 0) {
+ pendingWinnings[previousKing] += previousKingPayout;
+ }
emit ThroneClaimed(
msg.sender,
sentAmount,
claimFee,
pot,
block.timestamp
);
}
Updates

Appeal created

inallhonesty Lead Judge about 2 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Missing Previous King Payout Functionality

Support

FAQs

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