Summary
Incorrect comparision of time for making a Prediction in ScoreBoard::setPrediction
Vulnerability Details
The formula used following is wrong as per README
function setPrediction(
address player,
uint256 matchNumber,
Result result
) public {
=> 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;
}
}
Similar mistake in ThePredicter::makePrediction
:
function makePrediction(
uint256 matchNumber,
ScoreBoard.Result prediction
) public payable {
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);
}
For matchNumber = 0 , you can make a bet only till 19 hrs before START_TIME , i.e. , 1 AM 15 Aug,2024 UTC
For matchNumber = 1 , you can make a bet till START_TIME , i.e. , 8 PM 15 Aug,2024 UTC
For matchNumber = 2 , you can make a bet only till 19 hrs after START_TIME , i.e. , 3 PM 16 Aug,2024 UTC
.
.
.
But according to documentation , we can make a bet till 7 PM on the day of the match , which is obviously not the case here
Impact
People will not be able to place bets in the timeframe that the protocol tells them, causing confusion and decreased user participation
Tools Used
Manual Auditing , Slither , Aderyn
Recommendations
Change the formula
function setPrediction(
address player,
uint256 matchNumber,
Result result
) public {
- if (block.timestamp <= START_TIME + matchNumber * 68400 - 68400)
+ if(block.timestamp <= START_TIME + matchNumber*86400 - 3600)
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;
}
}
function makePrediction(
uint256 matchNumber,
ScoreBoard.Result prediction
) public payable {
if (msg.value != predictionFee) {
revert ThePredicter__IncorrectPredictionFee();
}
- if (block.timestamp > START_TIME + matchNumber * 68400 - 68400) {
+ if(block.timestamp > START_TIME + matchNumber*86400 - 3600){
revert ThePredicter__PredictionsAreClosed();
}
scoreBoard.confirmPredictionPayment(msg.sender, matchNumber);
scoreBoard.setPrediction(msg.sender, matchNumber, prediction);
}
}
Explanation
-3600
is to decrease time by 1 hr
matchNumber*86400
will move time ahead by 86400 seconds(i.e. 24 hrs) each day
Since START_TIME
represents 8 PM on 15 Aug,2024 UTC , this formula will allow betting till 7 PM UTC on 15 Aug , 16 Aug , ...