AuditBase
Sign InGet Started
infoNC025

2**<n> - 1 should be re-written as type(uint<n>).max

Discover how to improve Solidity code security by rewriting 2**<n> - 1 as type(uint<n>).max. Learn how to update earlier versions and optimize gas usage in your Solidity expressions.

Category

non-critical

Languages

solidity

Analysis Layer

static

Severity

info

Earlier versions of Solidity allow the use of uint&lt;n&gt;(-1) to represent the maximum value for an unsigned integer of bit-width n. However, with the introduction of Solidity 0.8.0, the recommended approach is to use type(uint&lt;n&gt;).max instead. This change not only improves code readability, but also avoids potential pitfalls.

Why the Change?

The decision to deprecate uint&lt;n&gt;(-1) in favor of type(uint&lt;n&gt;).max is mainly motivated by clarity and consistency. It aligns the syntax for representing the maximum value across different bit-widths, making code more understandable.

Furthermore, type(uint&lt;n&gt;).max provides additional type-safety guarantees. Using -1 could potentially lead to errors if accidentally used with a different type, such as a signed integer. The new approach eliminates this ambiguity.

Code Examples

Let's see some code examples to illustrate the recommended approach.

Older Solidity Versions (Deprecated)

uint8 maximumValue = uint8(-1);

In older versions of Solidity, -1 can be cast to uint8 to get the maximum value for an 8-bit unsigned integer.

Solidity 0.8.0 and Later (Recommended)

uint8 maximumValue = type(uint8).max;

Starting from Solidity 0.8.0, it is recommended to use type(uint8).max to explicitly represent the maximum value for an 8-bit unsigned integer.

Restructuring Expressions

In many cases, expressions involving 2**&lt;n&gt; - 1 can be restructured to accommodate the change, as shown in the following example:

function doSomething(uint8 x) external pure {
    require(x > type(uint8).max - 1, "Value exceeds maximum");
    // Rest of the code
}

By rewriting the expression as x > type(uint8).max - 1, we avoid the need to cast -1 explicitly, improving code comprehensibility. Additionally, it can result in minor gas savings when comparing values.

Conclusion

The deprecation of uint&lt;n&gt;(-1) in favor of type(uint&lt;n&gt;).max improves code readability, provides type safety guarantees, and promotes consistent syntax across different bit-widths. Whenever you encounter 2**&lt;n&gt; - 1 in your Solidity code, consider re-writing it using the recommended approach.