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

Failure to Reward Single Correct Predictions

Relevant GitHub Link

https://github.com/Cyfrin/2024-07-the-predicter/blob/839bfa56fe0066e7f5610197a6b670c26a4c0879/src/ScoreBoard.sol#L97

Summary

The current implementation of the withdraw function fails to account for players who make only one correct prediction. As a result, these players are unable to receive their deserved rewards. The logic within the withdraw function does not properly handle cases where a player has a positive score but has made only one prediction.

Impact

Players making a single correct prediction are unfairly denied rewards.

PoC

function test_singlePredictionCannotGetReward() public {
address player1 = makeAddr("player1");
address player2 = makeAddr("player2");
vm.startPrank(player1);
vm.deal(player1, 1 ether);
vm.deal(player2, 1 ether);
vm.deal(address(thePredicter), 10 ether);
// Player1 makes multiple predictions.
thePredicter.makePrediction{value: 0.0001 ether}(
0,
ScoreBoard.Result.First
);
thePredicter.makePrediction{value: 0.0001 ether}(
1,
ScoreBoard.Result.First
);
vm.stopPrank();
// Player2 makes a single prediction.
vm.startPrank(player2);
thePredicter.makePrediction{value: 0.0001 ether}(
0,
ScoreBoard.Result.First
);
vm.stopPrank();
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();
// Player1 can get the reward
vm.prank(player1);
thePredicter.withdraw();
// Player2 can not get the reward
vm.startPrank(player2);
vm.expectRevert(abi.encodeWithSelector(ThePredicter__NotEligibleForWithdraw.selector));
thePredicter.withdraw();
}

Tools Used

Manual Reading, Foundry

Recommendations

To fix this problem, we need to change the condition to allow players who have made at least one prediction to be eligible for a reward.

function isEligibleForReward(address player) public view returns (bool) {
return
results[NUM_MATCHES - 1] != Result.Pending &&
- playersPredictions[player].predictionsCount > 1;
+ playersPredictions[player].predictionsCount >= 1;
}
Updates

Lead Judging Commences

NightHawK Lead Judge about 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

The eligibility criteria is wrong

Players with only one prediction cannot withdraw.

Support

FAQs

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