Skip to main content

EVM -Storage

Storage Layout

1.


contract X  {
uint256 public a = 1; // Slot 0
uint128 public b = 2; // Slot 1 (partially filled)
uint128 public c = 3; // Slot 1 (same as 'b', packed)
bool public d = true; // Slot 2 (partially filled)
address public e = msg.sender; // Slot 3

struct Data {
uint256 x;
uint256 y;
}
Data public data = Data(10, 20); // Slot 4 & 5 (separate storage)

mapping(address => uint256) public balances; // Uses keccak256(address + slot)

string public text = "Hello"; // Stored separately, reference stored in slot 6
}

Every Slot has: 256 bits (32 Bytes)

SlotData
Slot 0a (32 bytes)
Slot 1b and c (16+16 bytes)
Slot 2d (1 byte) (31 waste)
Slot 3e
Slot 4x in struct
Slot 5y in struct

2.


contract x {
struct User {
uint128 id; // 16 bytes
bool active; // 1 byte
uint8 level; // 1 byte
uint256 score; // 32 bytes (New slot)
}
}
SlotData
Slot 0id (uint128) + active (bool) + level (uint8)
Slot 1score (uint256)

3.


contract {
mapping(address => uint256) public balances; // Slot 0

function setBalance(address user, uint256 amount) public {
balances[user] = amount;
}
}

Storage slot = keccak256(abi.encode(0xABC, 0))

SlotData
Slot 0
Slot n

Gas Optimization


1.


Unsafe:

uint128 a; // Slot 0
uint256 b; // Slot 1
uint128 c; // Slot 2

Safe:

uint128 a;
uint128 c;
uint256 b; // This ensures `a` and `c` are packed into one slot.

Rule For Storage

  1. Every storage slot can store up to 32 bytes of data.
  2. If a variable is ≤ 32 bytes, it fits into a single slot.
  3. If a variable is > 32 bytes, it gets its own slot and additional storage.