https://github.com/Cyfrin/2024-07-the-predicter/blob/main/src/ThePredicter.sol#L111-L145
In the withdraw function, the reward calculation involves potentially dangerous arithmetic operations
In the withdraw function, the reward calculation involves potentially dangerous arithmetic operations. Specifically, the calculation:
which is found here:
If totalShares is zero, this will result in a division by zero, causing the contract to revert or behave unexpectedly.
This can cause the contract to fail when trying to distribute rewards, leading to a denial of service.
Ensure totalShares is not zero before performing the division. Handle cases where totalShares is zero to prevent division by zero.
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;
}
if (maxScore > 0 && score <= 0) {
revert ThePredicter__NotEligibleForWithdraw();
}
- uint256 shares = uint8(score);
- uint256 totalShares = uint256(totalPositivePoints);
- uint256 reward = 0;
- if (totalShares > 0) {
- reward = maxScore < 0
- ? entranceFee
- : (shares * players.length * entranceFee) / totalShares;
- }
+ uint256 shares = uint256(score);
+ uint256 totalShares = uint256(totalPositivePoints);
+ // Ensure that the reward calculation is only done if `totalShares` is greater than zero
+ uint256 reward = maxScore < 0
+ ? entranceFee
+ : (totalShares > 0 ? (shares * players.length * entranceFee) / totalShares : 0);
if (reward > 0) {
scoreBoard.clearPredictionsCount(msg.sender);
(bool success, ) = msg.sender.call{value: reward}("");
require(success, "Failed to withdraw");
}
}