Dria

Swan
NFTHardhat
21,000 USDC
View results
Submission Details
Severity: low
Invalid

Potential Infinite Loop in sqrt Function Due to Missing Termination Condition

Summary

The sqrt function within the Statistics library lacks a proper termination condition based on precision or iteration limits. This deficiency can lead to infinite loops or excessive gas consumption when processing certain inputs, potentially causing transactions to fail or enabling denial-of-service (DoS) attacks against the contract.

Vulnerability Details

function sqrt(uint256 x) internal pure returns (uint256 y) {
uint256 z = (x + 1) / 2;
y = x;
while (z < y) {
y = z;
z = (x / z + z) / 2;
}
}

The sqrt function employs the Babylonian method to calculate the square root of a given number x. The loop continues executing as long as z < y, where z and y are successive approximations of the square root. However, without a proper termination condition based on precision or a maximum number of iterations, there is no guarantee that the loop will terminate for all input values.

For certain values of x, especially large non-perfect squares, the values of z and y may not converge quickly. This can result in the loop executing indefinitely or for an excessive number of iterations, consuming all available gas and causing the transaction to revert.

Impact

An infinite or excessively long loop can render the contract unusable for certain inputs, as transactions will consistently fail due to gas exhaustion.

Tools Used

Manual Review

Recommendations

To mitigate this issue, implement a reliable termination condition in the sqrt function. Here are several approaches:

  • Consider utilizing a well-established library that provides safe and efficient implementations of mathematical functions. Such as OpenZeppelin's Math Library

  • Introduce a counter to limit the number of iterations, ensuring the loop cannot run indefinitely.

function sqrt(uint256 x) internal pure returns (uint256 y) {
if (x == 0) return 0;
uint256 z = (x + 1) / 2;
y = x;
uint256 iterations = 0;
while (z < y && iterations < 256) { // Set a maximum iteration limit
y = z;
z = (x / z + z) / 2;
iterations++;
}
}
  • Define a minimal acceptable difference between successive approximations to determine when to terminate the loop.

function sqrt(uint256 x) internal pure returns (uint256 y) {
if (x == 0) return 0;
uint256 z = (x + 1) / 2;
y = x;
while (z < y) {
y = z;
z = (x / z + z) / 2;
if (y - z <= 1) { // Terminate when the difference is minimal
break;
}
}
return y;
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 12 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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