The normal behavior should emit the GameEnded event with the actual prize amount that the winner receives. However, the event is emitted after setting pot = 0
, causing the logged prize amount to always be 0 instead of the actual pot value. This provides incorrect data to off-chain systems, front-ends, and analytics platforms.
pragma solidity ^0.8.20;
import {Test, console2} from "forge-std/Test.sol";
import {Game} from "../src/Game.sol";
contract Finding3POC is Test {
Game public game;
address public deployer;
address public player1;
uint256 public constant INITIAL_CLAIM_FEE = 0.1 ether;
uint256 public constant GRACE_PERIOD = 1 days;
uint256 public constant FEE_INCREASE_PERCENTAGE = 10;
uint256 public constant PLATFORM_FEE_PERCENTAGE = 5;
event GameEnded(address indexed winner, uint256 prizeAmount);
function setUp() public {
deployer = makeAddr("deployer");
player1 = makeAddr("player1");
vm.deal(deployer, 10 ether);
vm.deal(player1, 10 ether);
vm.startPrank(deployer);
game = new Game(
INITIAL_CLAIM_FEE,
GRACE_PERIOD,
FEE_INCREASE_PERCENTAGE,
PLATFORM_FEE_PERCENTAGE
);
vm.stopPrank();
}
* @notice POC: Demonstrates the event logging issue through code analysis
* Note: Cannot test actual scenario due to Finding #1, but can analyze the logic
*/
function testPOC_GameEndedEventShowsZeroPrize() public {
console2.log("=== FINDING #3 POC: GAMENDED EVENT SHOWS WRONG PRIZE ===");
console2.log("");
uint256 simulatedPotValue = 5 ether;
uint256 simulatedWinnerPrize = simulatedPotValue;
console2.log("SCENARIO SIMULATION:");
console2.log("- Pot before declareWinner():", simulatedPotValue);
console2.log("- Prize winner should receive:", simulatedWinnerPrize);
console2.log("");
console2.log("CURRENT CONTRACT LOGIC IN declareWinner():");
console2.log("1. uint256 prize = pot; // Store current pot value");
console2.log("2. pot = 0; // Zero out pot BEFORE event emission");
console2.log("3. emit GameEnded(currentKing, pot); // Emits 0 instead of prize!");
console2.log("");
uint256 actualPrizeWon = simulatedPotValue;
uint256 eventLoggedAmount = 0;
console2.log("WHAT HAPPENS:");
console2.log("- Winner receives:", actualPrizeWon);
console2.log("- Event logs prize as:", eventLoggedAmount);
console2.log("- Discrepancy:", actualPrizeWon - eventLoggedAmount);
console2.log("");
assertNotEq(actualPrizeWon, eventLoggedAmount);
assertEq(eventLoggedAmount, 0);
console2.log("VULNERABILITY CONFIRMED:");
console2.log("- Event always shows 0 as prize amount");
console2.log("- Actual prize amount is lost in event data");
console2.log("- External systems cannot track real prizes");
}
* @notice POC: Shows impact on external systems and UIs
*/
function testPOC_ExternalSystemImpact() public {
console2.log("=== EXTERNAL SYSTEM IMPACT ANALYSIS ===");
console2.log("");
console2.log("AFFECTED SYSTEMS:");
console2.log("");
console2.log("1. FRONTEND APPLICATIONS:");
console2.log(" - Prize displays show $0.00");
console2.log(" - Leaderboards show no winnings");
console2.log(" - Statistics dashboards are wrong");
console2.log(" - User profiles show no earnings");
console2.log("");
console2.log("2. ANALYTICS PLATFORMS:");
console2.log(" - Total volume tracking incorrect");
console2.log(" - Average prize calculations wrong");
console2.log(" - ROI analysis impossible");
console2.log(" - Game health metrics skewed");
console2.log("");
console2.log("3. INTEGRATION APIS:");
console2.log(" - Third-party trackers show no prizes");
console2.log(" - Aggregator sites list game as worthless");
console2.log(" - Social media bots report $0 wins");
console2.log(" - Tax reporting tools missing data");
console2.log("");
console2.log("4. LEGAL/COMPLIANCE:");
console2.log(" - Audit trails incomplete");
console2.log(" - Prize reporting inaccurate");
console2.log(" - Regulatory compliance issues");
console2.log(" - Financial reconciliation problems");
}
* @notice POC: Simulates multiple game endings with wrong event data
*/
function testPOC_MultipleGameEndingsSimulation() public {
console2.log("=== MULTIPLE GAME ENDINGS SIMULATION ===");
console2.log("");
uint256[5] memory potValues = [
uint256(1 ether),
uint256(2.5 ether),
uint256(0.8 ether),
uint256(5 ether),
uint256(10 ether)
];
address[5] memory winners = [
makeAddr("alice"),
makeAddr("bob"),
makeAddr("charlie"),
makeAddr("diana"),
makeAddr("eve")
];
uint256 totalActualPrizes = 0;
uint256 totalEventLoggedPrizes = 0;
console2.log("SIMULATING GAME ENDINGS:");
console2.log("");
for (uint i = 0; i < 5; i++) {
uint256 actualPrize = potValues[i];
uint256 eventLoggedPrize = 0;
console2.log("Game", i + 1);
console2.log("- Winner:", winners[i]);
console2.log("- Actual prize won:", actualPrize);
console2.log("- Event logged prize:", eventLoggedPrize);
console2.log("- Data lost:", actualPrize);
console2.log("");
totalActualPrizes += actualPrize;
totalEventLoggedPrizes += eventLoggedPrize;
}
console2.log("CUMULATIVE IMPACT:");
console2.log("- Total actual prizes distributed:", totalActualPrizes);
console2.log("- Total shown in event logs:", totalEventLoggedPrizes);
console2.log("- Total data loss:", totalActualPrizes - totalEventLoggedPrizes);
console2.log("- Accuracy percentage:", (totalEventLoggedPrizes * 100) / totalActualPrizes, "%");
assertEq(totalEventLoggedPrizes, 0);
assertGt(totalActualPrizes, 0);
}
* @notice POC: Shows the correct implementation
*/
function testPOC_CorrectImplementation() public {
console2.log("=== CORRECT IMPLEMENTATION ===");
console2.log("");
uint256 examplePot = 3 ether;
console2.log("CURRENT (WRONG) IMPLEMENTATION:");
console2.log("function declareWinner() external {");
console2.log(" // ... validation code ...");
console2.log(" uint256 prize = pot;");
console2.log(" pot = 0; // <-- Zeroes pot first");
console2.log(" emit GameEnded(currentKing, pot); // <-- Emits 0!");
console2.log(" // ... transfer code ...");
console2.log("}");
console2.log("");
console2.log("CORRECT IMPLEMENTATION:");
console2.log("function declareWinner() external {");
console2.log(" // ... validation code ...");
console2.log(" uint256 prize = pot;");
console2.log(" emit GameEnded(currentKing, prize); // <-- Emit BEFORE zeroing");
console2.log(" pot = 0; // <-- Zero pot after event");
console2.log(" // ... transfer code ...");
console2.log("}");
console2.log("");
uint256 currentImplementationEvent = 0;
uint256 correctImplementationEvent = examplePot;
console2.log("EXAMPLE WITH", examplePot, "pot:");
console2.log("- Current implementation event logs:", currentImplementationEvent);
console2.log("- Correct implementation event logs:", correctImplementationEvent);
console2.log("");
console2.log("FIX IMPACT:");
console2.log("- External systems get accurate data");
console2.log("- UIs display correct prize amounts");
console2.log("- Analytics become meaningful");
console2.log("- Compliance requirements met");
console2.log("- Game transparency improved");
}
}