Skip to content

Integer Overflow and Underflow in Solidity

This example demonstrates how Solidity 0.8.0 handles integer overflow/underflow and the use of the unchecked block.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract IntegerOverflowUnderflow {
    // By default, all arithmetic operations in Solidity 0.8+ 
    // will automatically check for overflow/underflow
    uint8 public myUint8 = 255; // maximum value for uint8

    // This will fail with a panic error
    function increment() public {
        myUint8++; // This will revert because 255 + 1 overflows uint8
    }

    // This will fail with a panic error
    function decrement() public {
        myUint8--; // This will revert because 0 - 1 underflows uint8
    }

    // Using unchecked block to allow overflow/underflow
    function incrementUnchecked() public {
        unchecked {
            myUint8++; // This will wrap around to 0
        }
    }

    // Using unchecked block to allow overflow/underflow
    function decrementUnchecked() public {
        unchecked {
            myUint8--; // This will wrap around to 255
        }
    }

    // Demonstrate unchecked block in calculations
    function multiply(uint256 x, uint256 y) public pure returns (uint256) {
        // Normal checked multiplication
        uint256 result1 = x * y; // Will revert on overflow

        // Unchecked multiplication
        unchecked {
            uint256 result2 = x * y; // Will not revert, will wrap around
            return result2;
        }
    }
}

Key Concepts

  1. Default Behavior (Solidity >=0.8.0)

    • Automatically checks for overflow/underflow
    • Reverts transaction if overflow/underflow occurs
    • Provides safety by default
  2. Unchecked Block

    • Disables overflow/underflow checking
    • Allows wrap-around behavior
    • More gas efficient
    • Use with caution!
  3. Common Use Cases for Unchecked

    • Gas optimization when overflow is impossible
    • Implementing wrap-around behavior
    • Complex mathematical operations
    • Backward compatibility with <0.8.0 behavior

Best Practices

  1. Use default checked arithmetic unless you have a specific reason not to
  2. Document clearly when and why you use unchecked
  3. Consider using OpenZeppelin's SafeMath for versions <0.8.0
  4. Test thoroughly when using unchecked blocks
  5. Be aware that unchecked affects all arithmetic operations in its scope