⚡ Storage Optimization: Pack Variables & Save Gas

Reduce storage costs by grouping small variables together

⚡ Storage Optimization Techniques

Optimizing storage can reduce gas costs by 40-80%. The key techniques are variable packing, caching, and choosing the right data structures for your use case.

🎯 Interactive: Variable Packing Simulator

Compare unoptimized vs. optimized storage layouts:

contract Unoptimized {
  uint256 a;      // Slot 0 (32 bytes)
  uint8 b;        // Slot 1 (1 byte, wastes 31!)
  uint256 c;      // Slot 2 (32 bytes)
  uint8 d;        // Slot 3 (1 byte, wastes 31!)
  address owner;  // Slot 4 (20 bytes, wastes 12!)
}
Slots Used
5
Wasted Bytes
74
Write Cost
100,000 gas
Read Cost
10,500 gas
Storage Layout:
Slot 0:
uint256 a
Slot 1:
uint8 b
unused (31B)
Slot 2:
uint256 c
Slot 3:
uint8 d
unused (31B)
Slot 4:
address owner
unused (12B)

🎯 Interactive: Gas Cost Comparison

See how optimization affects different operations:

Writing all variables (SSTORE)
Save 40,000 gas
(40% reduction)
❌ Unoptimized
100,000 gas
✅ Optimized
60,000 gas

Optimization Techniques

📦
Variable Packing

Group small variables together to fit in one slot:

✅ uint128 a; uint128 b; // Same slot
❌ uint256 x; uint8 y; // Different slots
💾
Memory Caching

Load storage into memory once, reuse it:

✅ uint temp = storageVar; // Cache
❌ storageVar + storageVar; // 2 SLOADs
🗜️
Data Compression

Use smallest type that fits your data:

✅ uint8 age; // 0-255
❌ uint256 age; // Overkill
🔄
Struct Packing

Order struct fields by size for packing:

✅ uint128, uint128, uint256
❌ uint256, uint128, uint128

Practical Example: User Profile

Unoptimized (5 slots)

struct User {
  address wallet;     // Slot 0
  uint256 balance;    // Slot 1
  bool active;        // Slot 2
  uint64 lastSeen;    // Slot 3
  uint8 level;        // Slot 4
}
Write cost: ~100,000 gas
Wasted: 75 bytes

Optimized (2 slots)

struct User {
  uint256 balance;    // Slot 0
  address wallet;     // Slot 1 (20 bytes)
  uint64 lastSeen;    // Slot 1 (8 bytes)
  uint8 level;        // Slot 1 (1 byte)
  bool active;        // Slot 1 (1 byte)
  // 2 bytes unused
}
Write cost: ~40,000 gas (60% savings!)
Wasted: 2 bytes only

Advanced: Bit Packing

For ultimate optimization, pack multiple values into a single uint256 using bitwise operations:

// Pack 4 uint64 values into one uint256
uint256 packed = 
  (uint256(a) << 192) | 
  (uint256(b) << 128) | 
  (uint256(c) << 64) | 
  uint256(d);

// Unpack values
uint64 a = uint64(packed >> 192);
uint64 b = uint64(packed >> 128);
uint64 c = uint64(packed >> 64);
uint64 d = uint64(packed);
💡 Result:
  • • 4 values in 1 slot instead of 4 slots (75% storage reduction)
  • • Single SLOAD reads all 4 values (75% read cost reduction)
  • • Single SSTORE writes all 4 values (75% write cost reduction)
  • • Tradeoff: More complex code, higher gas for packing/unpacking operations

💡 Optimization Checklist

Order variables by size (largest to smallest)
Group small types (uint8, bool, address) together
Cache storage reads in memory variables
Use smallest type that fits your data range
Minimize storage writes (most expensive operation)
Use events for historical data (50x cheaper)
Consider bit packing for frequently accessed groups
Delete unused storage slots for gas refunds