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 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!