🎓 A1Learner
🔍
0 of 48 lessons completed

Solidity Storage Packing

Storage packing is the way small state variables share one 32-byte storage slot. Packing keeps related small values together instead of giving each one a whole slot.

Two small values share one slot

Two uint128 values fit side by side in one slot. The contract below stores both and reads both back.

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

contract PairPack {
    uint128 public first;
    uint128 public second;

    function set(uint128 a, uint128 b) public {
        first = a;
        second = b;
    }
}

Three small values share one slot

A uint128 plus two uint64 values also fit together. All three read back unchanged.

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

contract TrioPack {
    uint128 public big;
    uint64 public mid;
    uint64 public small;

    function set(uint128 a, uint64 b, uint64 c) public {
        big = a;
        mid = b;
        small = c;
    }
}

Small values pack around a large value

Small values group together even when a large value sits nearby. Each value still reads back correctly.

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

contract MixedPack {
    bool public active;
    uint8 public level;
    uint16 public score;
    uint256 public total;

    function set(bool a, uint8 l, uint16 s, uint256 t) public {
        active = a;
        level = l;
        score = s;
        total = t;
    }
}

Example

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

contract GameProfile {
    uint128 public coins;
    uint128 public gems;
    uint64 public level;
    uint64 public wins;
    bool public premium;

    function setProfile(uint128 c, uint128 g, uint64 l, uint64 w, bool p) public {
        coins = c;
        gems = g;
        level = l;
        wins = w;
        premium = p;
    }

    function addWin() public {
        wins += 1;
    }
}

Key points

  • Storage slot: one 32-byte home for state values.
  • Packing: small values declared next to each other can share one slot.
  • Declaration order: neighbours pack together, so group small values side by side.
  • Large values: a single uint256 still takes a whole slot on its own.
  • Reading back: packed values read back exactly as they were written.

In this example, a game profile stores coins and gems as uint128 values and level and wins as uint64 values with a premium flag beside them. Setting the profile and adding one win leaves every value reading back correctly.

Note

slot layout is a compiler detail, so prove packing by values read back and never by slot numbers.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Remix IDE

Exercise

Which declaration order packs best?