# Types, Mappings and Structs — Blockchain & Smart Contracts (Solidity)

Source: https://www.geekswithgeeks.com/en/solidity/s-types

> Use value types, arrays, mappings, structs and enums, and understand checked arithmetic.

## Solidity's type system

**Value types** include **`bool`**, **`uint256`** (unsigned integers in sizes from `uint8` to `uint256`, in steps of 8 bits; `uint` is an alias for `uint256`), **`int256`** (signed), **`address`** (20 bytes) and **`address payable`** (can receive ether), fixed-size **`bytes1`** to **`bytes32`**, and **enums**. Solidity has **no floating point**: represent fractional values as integers with a fixed number of decimals (tokens typically use 18, so 1.5 tokens is `1.5e18`). **Reference types** are **arrays** (fixed `uint[3]` or dynamic `uint[]`), **`bytes`** and **`string`** (dynamic), **structs** and **mappings**. A **`mapping(address => uint256)`** is a hash table where every possible key exists with a default zero value; mappings cannot be iterated or have their length taken, so track keys separately if needed. Since **Solidity 0.8**, arithmetic is **checked**: overflow and underflow revert automatically; use an `unchecked { ... }` block only when you have proven overflow impossible, to save gas. Integer division truncates, so **multiply before dividing** to preserve precision. Constants (`constant`) and **`immutable`** variables are embedded in bytecode and cost no storage reads.

## Types in a simple token-like ledger

Mappings, structs, enums and fixed-point arithmetic.

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

contract Ledger {
    enum Tier { Basic, Silver, Gold }

    struct Member {
        Tier tier;
        uint64 joinedAt;
        bool active;
    }

    uint8 public constant DECIMALS = 18;
    uint256 public constant FEE_BPS = 250;                 // 2.5% in basis points

    mapping(address => uint256) public balanceOf;         // default value 0 for every address
    mapping(address => Member) public members;
    mapping(address => mapping(address => uint256)) public allowance;   // nested mapping

    function join(Tier tier) external {
        members[msg.sender] = Member({tier: tier, joinedAt: uint64(block.timestamp), active: true});
    }

    function feeFor(uint256 amount) public pure returns (uint256) {
        return (amount * FEE_BPS) / 10_000;               // multiply first, then divide
    }

    function credit(address to, uint256 wholeTokens) external {
        balanceOf[to] += wholeTokens * 10 ** DECIMALS;     // reverts on overflow (0.8+)
    }

    function sumFirst(uint256[] calldata values, uint256 n) external pure returns (uint256 total) {
        for (uint256 i = 0; i < n && i < values.length; ) {
            total += values[i];
            unchecked { ++i; }                             // i cannot overflow here
        }
    }
}
```

## Paise, not rupees

Without decimals, Solidity is like a till that only counts paise. To represent Rs 1.50 you store 150 paise; tokens do the same with 18 decimal places, so every amount is a whole number of the smallest unit.

**Quiz:** What happens in Solidity 0.8+ when a uint256 subtraction would go below zero?

- [ ] It wraps around to a huge number
- [x] The transaction reverts
- [ ] It returns zero
- [ ] It becomes negative

*Answer:* The transaction reverts. Checked arithmetic reverts on overflow and underflow by default since 0.8.
