Summary
Missing Player.Status check makes anyone can make prediction
Vulnerability Details
Function ThePredicter::makePrediction lacks of Player.Status check so anyone can make predictions even without registration
Proof of concept
Copy this tests to ThePredicter.test.sol
function test_anyoneCanMakePrediction() public{
vm.deal(stranger, 1 ether);
vm.startPrank(stranger);
vm.expectRevert();
thePredicter.makePrediction{value: 0.0001 ether}(
0,
ScoreBoard.Result.Draw
);
vm.stopPrank();
}
function test_cancelledPlayerCanMakePrediction() public{
vm.deal(stranger, 1 ether);
vm.startPrank(stranger);
thePredicter.register{value: thePredicter.entranceFee()}();
thePredicter.cancelRegistration();
vm.expectRevert();
thePredicter.makePrediction{value: 0.0001 ether}(
0,
ScoreBoard.Result.Draw
);
vm.stopPrank();
}
and run commands
forge test --mt test_anyoneCanMakePrediction -vvv
forge test --mt test_cancelledPlayerCanMakePrediction -vvv
Both tests will fail reverting. It means that player that didn't even register or cancelled registration can still make predictions
Impact
High, contract does not work as expected
Tools Used
Manual review
Recommendations
Add PlayerStatus check to ThePredicter::makePrediction
error ThePredicter__IncorrectEntranceFee();
error ThePredicter__RegistrationIsOver();
error ThePredicter__IncorrectPredictionFee();
error ThePredicter__AllPlacesAreTaken();
error ThePredicter__CannotParticipateTwice();
error ThePredicter__NotEligibleForWithdraw();
error ThePredicter__PredictionsAreClosed();
error ThePredicter__UnauthorizedAccess();
+ error ThePredicter__PlayerNotApproved();
function makePrediction(
uint256 matchNumber,
ScoreBoard.Result prediction
) public payable {
if (msg.value != predictionFee) {
revert ThePredicter__IncorrectPredictionFee();
}
+ if(playersStatus[msg.sender] != Status.Approved){
+ revert ThePredicter__PlayerNotApproved();
+ }
if (block.timestamp > START_TIME + matchNumber * 68400 - 68400) {
revert ThePredicter__PredictionsAreClosed();
}
scoreBoard.confirmPredictionPayment(msg.sender, matchNumber);
scoreBoard.setPrediction(msg.sender, matchNumber, prediction);
}