Value Types

Value types are copied when assigned or passed as arguments.

7.1 Booleans

bool public isActive = true;
// operators: !  &&  ||  ==  !=   (&& and || short-circuit)

7.2 Integers

int8 … int256 and uint8 … uint256 in steps of 8 bits. uint = uint256, int = int256.

Number literals: 1_000_000, 1e18, 0xff, 2.5 ether (scientific notation and denominations are evaluated at compile time with arbitrary precision).

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

contract Integers {
    uint256 public maxU = type(uint256).max;
    int256 public minI = type(int256).min;
    uint8 public small = 200;

    function examples() external pure returns (uint256, int256, uint256) {
        uint256 a = 7 / 2;            // 3 — integer division truncates toward zero
        int256 b = -7 / 2;            // -3
        uint256 c = 2 ** 10;          // 1024
        // uint256 d = 1 / 0;         // compile-time error; runtime division by zero → Panic(0x12)
        return (a, b, c);
    }

    function conversions(uint256 big) external pure returns (uint8, uint256) {
        uint8 truncated = uint8(big);           // explicit narrowing keeps lowest 8 bits (no revert!)
        uint256 widened = uint256(truncated);   // widening is always safe (implicit also allowed)
        return (truncated, widened);
    }
}

7.3 Fixed-point numbers (note)

fixed / ufixed (e.g., ufixed128x18) are declared but not fully supported — you can declare them but not assign to them. In practice, use integers scaled by a power of ten (e.g., 18-decimal "WAD" math: 1e18 represents 1.0) or libraries such as PRBMath, Solady FixedPointMathLib, or ABDK.

7.4 Addresses

20-byte value; has .balance, .code, .codehash, .call, .delegatecall, .staticcall address payable same plus .transfer and .send

Address literals must pass the EIP-55 checksum test (mixed case), e.g. 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4. address(0) is the zero address — often a sentinel for "unset"; tokens sent there are effectively burned.

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

contract Addresses {
    function info(address a) external view returns (uint256 bal, uint256 codeSize, bytes32 codeHash) {
        return (a.balance, a.code.length, a.codehash);
    }

    function toPayable(address a) external pure returns (address payable) {
        return payable(a);              // explicit conversion
    }

    function fromUint(uint160 x) external pure returns (address) {
        return address(x);
    }
}

7.5 Fixed-size byte arrays

bytes1 … bytes32. Support comparison, bitwise operators, shifts, index access (b[i] read-only) and .length.

Prefer bytes32 over string for fixed short identifiers — it's cheaper.

bytes32 public hash = keccak256("hello");
bytes4 public selector = bytes4(keccak256("transfer(address,uint256)"));   // 0xa9059cbb
bytes1 public first = hash[0];

7.6 Enums

Converting an out-of-range integer to an enum reverts with Panic(0x21).

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

contract Order {
    enum Status { Pending, Shipped, Delivered, Cancelled }   // stored as uint8; Pending = 0
    Status public status;                                     // defaults to the first member

    function ship() external {
        require(status == Status.Pending, "not pending");
        status = Status.Shipped;
    }

    function limits() external pure returns (Status, Status) {
        return (type(Status).min, type(Status).max);          // Pending, Cancelled
    }
}

7.7 Default values

Every variable starts at its type's zero value: false, 0, address(0), bytes32(0), first enum member, empty string/bytes/array. There is no null or undefined.

7.8 Type conversions summary

uint8 → uint256 implicit (widening) uint256 → uint8 explicit; keeps low-order bits uint256 ↔ int256 explicit; reinterprets bits bytes32 → bytes4 explicit; keeps leftmost (high-order) bytes uint160 ↔ address address → address payable bytes → string

string(b) (explicit, no copy semantics change) contract → address