Last Man Standing

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

Incorrect Prize Amount Emitted In GameEnded Event

Incorrect Prize Amount Emitted In GameEnded Event

Description

  • The declareWinner() function is designed to emit the correct prize amount when a winner is declared for monitoring and transparency purposes

  • The function emits pot value after it has been reset to 0, causing the event to always show 0 as the prize amount instead of the actual winnings

function declareWinner() external gameNotEnded {
// ... validation logic ...
gameEnded = true;
pendingWinnings[currentKing] = pendingWinnings[currentKing] + pot;
pot = 0; // @> Reset pot to 0 first
emit GameEnded(currentKing, pot, block.timestamp, gameRound); // @> Then emit 0 instead of actual prize
}

Risk

Likelihood: High

  • This bug is triggered every time declareWinner() is called

  • The event emission happens on every game round completion

Impact: Medium

  • Off-chain monitoring systems receive incorrect prize information (always 0)

  • Frontend applications cannot display accurate prize amounts to users

  • Game analytics and reporting will show false data

  • Users cannot verify the correct prize amounts from blockchain events

Proof of Concept

The test demonstrates that the GameEnded event should emit the actual prize amount, not zero:

function testDeclareWinner_EmitsCorrectPrizeAmount() public {
// Players claim throne to build up the pot
vm.prank(player1);
game.claimThrone{value: INITIAL_CLAIM_FEE}();
uint256 expectedPrizeAmount = game.pot(); // Save actual pot amount
assertGt(expectedPrizeAmount, 0); // Verify pot has funds
// Fast forward past grace period
vm.warp(block.timestamp + GRACE_PERIOD + 1);
// Expect GameEnded event with correct prize amount
vm.expectEmit(true, false, false, true);
emit GameEnded(player1, expectedPrizeAmount, block.timestamp, 1);
game.declareWinner();
}

Explanation: The test verifies that when a winner is declared, the GameEnded event emits the actual prize amount from the pot, not zero after the pot is reset.

Recommended Mitigation

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

Explanation: Store the pot value before resetting it to 0, then emit the actual prize amount in the event.

Updates

Appeal created

inallhonesty Lead Judge 10 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!