Beginner FriendlyFoundry
100 EXP
View results
Submission Details
Severity: low
Invalid

[L-1] Vulnerability is observed in `ThePredicter::withdraw` function where the external call to contract `ScoreBoard` for variable `getPlayerScore` is within a loop.

Summary: The external call to the ScoreBoard contract is within a loop in the ThePredicter::withdraw function. If the number of iterations to the external call increases it causes the risk of DOS attacks. Hence, it is crucial to consider the potential security risks associated with unbounded for-loops that make external calls in Solidity.

Vulnerability Details: The external call should not be inside a loop as an attacker could increase the number of iterations leading to flooding the system with large traffic, eventually leading to shutting of the system. The vulnerability can be found in the below code, where scoreBoard contract is being called and then teh score is being calcualted for each player.

function withdraw() public {
if (!scoreBoard.isEligibleForReward(msg.sender)) {
revert ThePredicter__NotEligibleForWithdraw();
}
int8 score = scoreBoard.getPlayerScore(msg.sender);
int8 maxScore = -1;
int256 totalPositivePoints = 0;
for (uint256 i = 0; i < players.length; ++i) {
int8 cScore = scoreBoard.getPlayerScore(players[i]);
if (cScore > maxScore) maxScore = cScore;
if (cScore > 0) totalPositivePoints += cScore;
}

Impact: It could lead to shutting down of the machine or network, making it inaccessible to its intended users. The DOS attack is accomplished by flooding the target with traffic, or sending the information that triggers a crash. In both instances, the attack deprives legitimate users of the service or resource they expected.

Tools Used: Slither, Aderyn, VScode and Foundry.

Recommendations: We could consider fetching scores for multiple players by implementing a batch processing mechanism. We can fetch scores for multiple players in a single external call rather than making multiple calls inside the loop. Once we have all the score, we could them to calculate the score of each player. The changes done in the code can be observed below.

function withdraw() public lock {
if (!scoreBoard.isEligibleForReward(msg.sender)) {
revert ThePredicter__NotEligibleForWithdraw();
}
int8 score = scoreBoard.getPlayerScore(msg.sender);
int8 maxScore = -1;
int256 totalPositivePoints = 0;
int8[] memory playerScores = new int8[](players.length);
for (uint256 i = 0; i < players.length; ++i) {
playerScores[i] = scoreBoard.getPlayerScore(players[i]);
}
for (uint256 i = 0; i < players.length; ++i) {
int8 cScore = playerScores[i];
if (cScore > maxScore) maxScore = cScore;
if (cScore > 0) totalPositivePoints += cScore;
}
Updates

Lead Judging Commences

NightHawK Lead Judge 12 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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