History & Versions

Before 0.8, every project used OpenZeppelin's SafeMath library to prevent overflow.

3.1 Timeline

Gavin Wood proposes Solidity Ethereum Frontier launch the dominant early version; The DAO hack (June 2016) shapes security culture

emit keyword for events; constructor keyword replaces same-name constructors explicit data locations, address payable, explicit function visibility required, emit mandatory, var removed

virtual / override, abstract contracts, try/catch, receive vs fallback split, array .push() no longer returns length

now removed (use block.timestamp), constructor visibility removed, {value: x, gas: y} call options (introduced in 0.6.2) replace .value()

checked arithmetic by default (overflow reverts), unchecked { } blocks, ABI coder v2 default, Panic(uint256) errors

custom errors (error InsufficientBalance(...)), bytes.concat

user-defined value types, override optional for single interface functions abi.encodeCall, string.concat

using ... for at file level with free functions; via-IR production-ready

block.prevrandao, selfdestruct deprecated user-defined operators for value types default EVM version Shanghai (PUSH0 opcode) immutables assignable more flexibly; events at file level; automatic unchecked loop-counter increments

Cancun support: tstore/tload in assembly (transient storage), mcopy, blobhash(), block.blobbasefee default EVM version Cancun; MCOPY used by code generator

require(condition, CustomError()); via-IR first (0.8.26), legacy pipeline (0.8.27)

transient state variables of value types custom storage layout (contract C layout at <slot> { }), EOF experimental support default EVM version Prague (Pectra)

Osaka (Fusaka) EVM support; deprecation warnings ahead of 0.9 (e.g., send/transfer, selfdestruct)

Always check the official release notes at soliditylang.org before relying on a minor-version feature. A 0.9.0 release with breaking changes is planned; until then, 0.8.x is the line every new project should use.

3.2 Before 0.8 vs after 0.8: arithmetic

Before 0.8, every project used OpenZeppelin's SafeMath library to prevent overflow. In 0.8+, SafeMath is unnecessary.

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

contract Arithmetic {
    function overflow() external pure returns (uint8) {
        uint8 x = 255;
        x += 1;            // 0.8+: reverts with Panic(0x11). Pre-0.8: silently wrapped to 0.
        return x;
    }

    function wrapping() external pure returns (uint8) {
        uint8 x = 255;
        unchecked { x += 1; }   // explicitly opt in to wrapping: returns 0
        return x;
    }
}

3.3 Which version should I use?

Use the latest stable 0.8.x your tooling and target chains support.

Check the target chain's EVM version: some L2s and alt-chains lag behind mainnet (e.g., no PUSH0 or transient storage). Set evmVersion explicitly in the compiler config when deploying to such chains.

Lock the pragma for deployed production contracts (pragma solidity 0.8.28;); use ranges (^0.8.20) for libraries.