Last Man Standing

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

Misleading GameEnded event emits zero pot value

The declareWinner function resets the pot to zero before emitting the GameEnded event, resulting in the event always logging a pot value of zero regardless of the actual winnings transferred.

Description

  • In the declareWinner() function, the GameEnded event is emitted after the pot has already been assigned to the winner and reset to zero. This causes the emitted pot value to always be 0, which is misleading and does not reflect the actual value awarded.

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;
pendingWinnings[currentKing] = pendingWinnings[currentKing] + pot;
@> pot = 0; // Reset pot after assigning to winner's pending winnings
emit GameEnded(currentKing, pot, block.timestamp, gameRound);
}

Risk

Likelihood:

  • The issue occurs deterministically every time the game ends.

Impact:

  • Users and systems that rely on these logs will collect wrong information

Proof of Concept

Add this test to GameTest.t.sol

function test_misleading_event() public {
// Some players enter first way before grace period ends
vm.prank(player1);
game.claimThrone{value: INITIAL_CLAIM_FEE}();
vm.prank(player2);
game.claimThrone{value: 1.1e17}();
vm.warp(block.timestamp + 87000 seconds);
game.declareWinner();
}

Output traces:

├─ [50711] Game::declareWinner()
│ ├─ emit GameEnded(winner: player2: [0xEb0A3b7B96C1883858292F0039161abD287E3324], prizeAmount: 0, timestamp: 87001 [8.7e4], round: 1)
│ └─ ← [Stop]
└─ ← [Stop]

Recommended Mitigation

Reorder the statements in declareWinner so that the GameEnded event is emitted before resetting the pot:

- pot = 0; // Reset pot after assigning to winner's pending winnings
- emit GameEnded(currentKing, pot, block.timestamp, gameRound);
+ emit GameEnded(currentKing, pot, block.timestamp, gameRound);
+ pot = 0; // Reset pot after assigning to winner's pending winnings
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!