Last Man Standing

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

Incorrect Prize Amount in `GameEnded` Event Misleads External Systems

Description

  • The GameEnded event should emit the actual prize amount that the winner receives to provide accurate data for off-chain applications and monitoring systems.

  • The declareWinner function emits the event with prizeAmount set to pot after the pot has already been reset to 0, showing incorrect prize data.

function declareWinner() external gameNotEnded {
gameEnded = true;
pendingWinnings[currentKing] = pendingWinnings[currentKing] + pot; // Winner gets the pot
pot = 0; // @> Reset pot to 0 HERE
// @> Event emits pot which is now 0, not the actual prize amount
emit GameEnded(currentKing, pot, block.timestamp, gameRound);
}

Risk

Likelihood:

  • Every call to declareWinner() will emit incorrect prize data

  • External systems monitoring events will receive wrong information

Impact:

  • Off-chain applications and indexers receive incorrect prize data

  • Frontend applications display wrong winning amounts to users

  • Analytics and monitoring systems have inaccurate game statistics

  • User confusion when checking transaction logs

Proof of Concept

Looking at the declareWinner function:

function declareWinner() external gameNotEnded {
// ... validation checks ...
gameEnded = true;
pendingWinnings[currentKing] = pendingWinnings[currentKing] + pot; // Winner gets the pot
pot = 0; // Reset pot to 0 HERE
emit GameEnded(currentKing, pot, block.timestamp, gameRound); // pot is now 0!
}

Scenario:

  1. Current pot is 5 ETH from multiple claims

  2. Grace period expires, someone calls declareWinner()

  3. Winner receives 5 ETH in pendingWinnings

  4. pot is reset to 0

  5. Event emits GameEnded(winner, 0, ...) instead of GameEnded(winner, 5, ...)

Recommended Mitigation

Store the prize amount before resetting the pot:

function declareWinner() external gameNotEnded {
require(currentKing != address(0), "Game: No one has claimed the throne yet.");
require(
block.timestamp > lastClaimTime + gracePeriod,
"Game: Grace period has not expired yet."
);
gameEnded = true;
+ uint256 prizeAmount = pot; // Store prize amount before reset
pendingWinnings[currentKing] = pendingWinnings[currentKing] + pot;
pot = 0;
+ emit GameEnded(currentKing, prizeAmount, block.timestamp, gameRound); // Correct amount
}
Updates

Appeal created

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

Game::declareWinner emits GameEnded event with pot = 0 always

Support

FAQs

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