Last Man Standing

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

`GameEnded` Event Emits Incorrect `pot` amount in the `declareWinner`

GameEnded Event Emits Incorrect pot amount in the declareWinner

Description

In the declareWinner() function, the GameEnded event emits a prizeAmount value after the pot has already been reset to zero:

pendingWinnings[currentKing] = pendingWinnings[currentKing] + pot;
pot = 0; // Reset pot after assigning to winner's pending winnings
emit GameEnded(currentKing, pot, block.timestamp, gameRound);

This means the emitted prizeAmount will always be 0, regardless of how much ETH was actually won.
As a result, any off-chain services (frontends, analytics dashboards, indexers) relying on the GameEnded event to track prize amounts will display incorrect data.

Risk

Likelihood:

  • Always triggers whenever a game ends, since pot is reset before the event emission

Impact:

  • Event logs will misrepresent actual winnings, leading to:

    • Incorrect historical game records.

    • Misleading frontend displays.

    • Potential disputes if the event log is used for audits or marketing

Proof of Concept

A simple test to demonstrate the 0 error; try to test using `game.pot()`

function test_GameEndedEventPrizeAmountIncorrect() public {
// Player1 claims throne with 1 ETH
vm.startPrank(player1);
game.claimThrone{value: 1 ether}();
vm.stopPrank();
// Warp time to expire grace period
vm.warp(block.timestamp + GRACE_PERIOD + 1);
// Expect GameEnded to emit with prizeAmount == 0
vm.expectEmit(true, false, false, true);
emit GameEnded(player1, 0, block.timestamp, 1); // <@ if you set 2nd index to game.pot() it fails to show this error
game.declareWinner();
}
Compiler run successful!
Ran 1 test for test/Game.t.sol:GameTest
[PASS] test_GameEndedEventPrizeAmountIncorrect() (gas: 186799)
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 9.42ms (578.00µs CPU time)
Ran 1 test suite in 60.41ms (9.42ms CPU time): 1 tests passed, 0 failed, 0 skipped (1 total tests)

Recommended Mitigation

Store the pot in a temporary variable before zeroing it, and emit that value in the even

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 prize = pot;
pendingWinnings[currentKing] = pendingWinnings[currentKing] + pot;
pot = 0;
- emit GameEnded(currentKing, pot, block.timestamp, gameRound);
+ emit GameEnded(currentKing, prize, block.timestamp, gameRound);
}
Updates

Appeal created

inallhonesty Lead Judge 4 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.

Give us feedback!