DeFiHardhat
12,000 USDC
View results
Submission Details
Severity: low
Invalid

Scale factor `(10 ** n)` may cause overflow for large `n`

Summary

The scale factor 10 ** n is used to increase the precision of the nthRoot calculation by effectively shifting the decimal point of a to the right n times before computing the root. However, this can lead to overflow issues for large values of n because the result of 10 ** n grows exponentially.

Vulnerability Details

nthRoot()

function nthRoot(uint256 a, uint256 n) internal pure returns (uint256 root) {
assert(n > 1);
if (a == 0) return 0;
// Equivalent to "i % 2 == 0" but cheaper.
if (n & 1 == 0) {
if (n == 2) return sqrt(a); // shortcut for square root
if (n == 4) return sqrt(sqrt(a));
if (n == 8) return sqrt(sqrt(sqrt(a)));
if (n == 16) return sqrt(sqrt(sqrt(sqrt(a))));
}
// The scale factor is a crude way to turn everything into integer calcs.
// Actually do ((10 ^ n) * a) ^ (1/n)
uint256 a0 = (10 ** n) * a;
uint256 xNew = 10;
uint256 x;
while (xNew != x) {
x = xNew;
uint256 t0 = x ** (n - 1);
if (x * t0 > a0) {
xNew = x - (x - a0 / t0) / n;
} else {
xNew = x + (a0 / t0 - x) / n;
}
}
root = (xNew + 5) / 10;
}

Issue stems from the line:

uint256 a0 = (10 ** n) * a;

PoC

  • Maximum value for a uint256 is 2**256 - 1.

  • The maximum value that 10 ** n can reach without overflowing a uint256 is 10 ** 77 because 10 ** 78 > 2**256.

  • If n is greater than 77, 10 ** n will overflow.

Example of overflow:

Let's assume n = 78, which is just one more than the safe limit.

  • 10 ** 78 is 10 times larger than 10 ** 77.

  • 2 ** 256 is approximately 1.1579209e+77.

  • 10 ** 78 is approximately 1e+78.

  • Since 1e+78 is significantly larger than 1.1579209e+77, it's clear that 10 ** 78 will overflow a uint256.

Impact

In Solidity, an overflow in such an operation would cause the result to wrap around modulo 2**256, leading to an incorrect and very small number instead of the large expected value. This would completely distort the calculations that follow.

Since the code is written in Solidity version v0.8.x, automatic revert will take place.

Tools Used

Manual Review

Recommendations

Implement a check to ensure that n does not exceed a safe threshold.

  • Define a constant for the maximum allowed value of n to prevent overflow.

  • Use a require statement to enforce this limit before performing the calculation.

function nthRoot(uint256 a, uint256 n) internal pure returns (uint256 root) {
require(n > 1, "n must be greater than 1"); // @audit Use require statement
if (a == 0) return 0;
// @audit Define the maximum value for n to prevent overflow
uint256 maxN = 77; // This is the safe threshold for uint256 with base 10
require(n <= maxN, "n too large, would cause overflow");
// Existing implementation...
}
Updates

Lead Judging Commences

giovannidisiena Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Informational/Invalid

Support

FAQs

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