Serving a 32-byte storage read may require page-sized backend I/O. MIP-8 makes the EVM account for that page-sized reality.
The information on this page should not be quoted. Please refer to MIP-8 for the authoritative spec.
waiting...
128 slots × 32 bytes = 4,096 bytes = 1 page
127 sibling slots stay unused in this example
MIP-8 is live
Monad mainnet activated MIP-8 with MONAD_TEN on September 2, 2026 at 14:30 UTC. This read-only check verifies the active gas schedule on mainnet and testnet without sending a transaction.
Checking Mainnet…
Checking Testnet…
Same struct, different cost model
Solidity lays out struct fields at contiguous slots, but trie/backend hashing can scatter them across different physical locations. In this worst-case illustration, each field lands on a separate backend page. MIP-8 groups contiguous slots into one page.
Click each field to load it and compare the gas cost side by side. Cold read costs 8,100 gas, warm read costs 100 gas on Monad.
struct Token {owner,balance,timestamp,approved }
No fields loaded yet. Load fields to compare the pre-MIP-8 model with the current MIP-8 schedule.
Pre-MIP-8
0 cold reads
page 0x7a2f...
page 0x3e81...
page 0xb4c5...
page 0x91d7...
0 x 8,100
0
MIP-8 (current)
0
page 0 (contiguous)
0
0
Compare the cost
Select a scenario to compare the pre-MIP-8 slot-based model with Monad's current page-aware model.
These read-only examples compare the storage-access component: 8,100 gas for the first read from a page and 100 gas for each subsequent read. They are not total transaction-gas estimates.
Loading 4 contiguous struct fields that fit in one page
Pre-MIP-8
32,400
storage-access gas
4 × 8,100 (distinct cold slots before MIP-8)
MIP-8 (current)
8,400
storage-access gas
1 × 8,100 (first page touch) + 3 × 100 (warm reads in same page)
Storage-access gas savings
74% cheaper
SavedPre-MIP-8
Reference data structures
Reusable Solidity primitives that make MIP-8 page boundaries explicit instead of relying on accidental storage alignment.
These implementations optimize locality when one call touches several related values. A single lookup is not inherently cheaper, and every net-new slot still pays state-growth cost.
Dense bitmap
32,768 bits per page
slot 0128 slots · one pageslot 127
Stores consecutive 256-bit buckets in consecutive slots, avoiding the locality loss of mapping-backed bitmap buckets.
Good for: claim flags, permissions, dense IDs, epochs
Step through real contract code line by line. Each SLOAD/SSTORE lights up the corresponding storage slot and shows whether it's a cold or warm access under MIP-8.
Totals include only the 8,100/100 storage-access component. For SSTORE, they exclude the 2,800 first-write charge and any 17,000 state-growth charge.
Pair storage slots share one page, but balanceOf() reads execute in two separate token contracts. This simplified trace treats each balance page as untouched, so both token reads start cold; earlier token calls in a full transaction could warm them.
Uniswap V2 swap()
0 unique slots accessed
1
// UniswapV2Pair.sol
2
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external lock {
Uniswap V2 swap() is ready. 9 storage operations are available.
Design for pages, cut access gas 10X+
MIP-8 opens a new design space where page-aware storage can reduce the storage-access component by an order of magnitude.
Consider an ERC-1155 multi-token contract. The standard implementation hashes each token balance to a random storage location. In this example, an aligned page-aware design stores balances contiguously, so batch operations read one page instead of N scattered slots.
Standard ERC-1155
// balances scattered by keccak256
mapping(uint256 =>
mapping(address => uint256))
balances;
Each token ID hashes to a different page
page 0x7a..
page 0x3e..
page 0xb4..
page 0x91..
20 tokens = 20 cold reads = 162,000 storage-access gas
Page-aware design
// balances packed contiguously
uint256[128] balances; // base slot 0
// as the first state field, slots 0-127 form one page
20 tokens use 162,000 storage-access gas in the standard layout and 10,000 storage-access gas in the page-aware layout, saving 94% of the storage-access component.
This access-gas example places the balances array at aligned base slot 0 instead of using a double mapping. With MIP-8, reads that remain in the same page cost 100 gas per additional slot instead of 8,100. Other transaction costs are excluded.
Slot → Page mapping
Every slot maps deterministically to a page. The math is simple: shift right by 7 bits to get the page, mask the low 7 bits to get the offset within it.
0127255383511
page_index(slot) = slot >> 7
0 >> 7 = 0
offset(slot) = slot & 0x7F
0 & 127 = 0
Storage slot 0 maps to page 0 at offset 0.
Page 0
Page 1
Page 2
Page 3
Try your own contract
Paste a GitHub repo URL or Solidity source to see how your contract's storage layout maps to pages.
Works best with small-to-medium repos. Large repos with many dependencies (e.g. Aave, Chainlink) may time out.
Try:
What this means for you
Structs get cheaper
Solidity stores struct members and array elements contiguously. Under MIP-8, a contiguous run that fits in one page is typically 1 cold page touch plus N - 1 warm slot accesses instead of N cold slot accesses.
Mappings change less
Mappings still derive storage locations from keccak256, so unrelated keys almost always land on different pages. MIP-8 rarely helps or hurts truly random access; it mostly rewards contiguous layouts.
New optimization patterns
Page-aware arrays, careful packing, and low-level layouts that keep related data inside the same 128-slot page open a new optimization space for page-aware gas costs.
Execution stays compatible
At the opcode level, execution semantics stay the same: SLOAD still returns 32 bytes and SSTORE still writes 32 bytes. What changes is the storage commitment/proof layer and the gas model, which become page-aware. The effective key space narrows from 2²⁵⁶ hashed slots to 2²⁴⁹ page indices.
Contracts that read consecutive storage slots often get cheaper because Solidity stores struct members, fixed arrays, and runs of dynamic-array elements contiguously once their base location is known. Mappings still use hashed locations, so mapping-heavy access patterns tend to change less. Contracts that hardcode storage-opcode gas assumptions are at risk, regardless of access pattern.
Each 4,096-byte page is committed with an induced BLAKE3-based subtree over occupied 64-byte slot pairs. Empty branches are bypassed, and a 128-bit occupancy bitmap seals the exact positions. The bitmap plus sibling hashes is at most 208 bytes, excluding the target value and the outer MPT proof.
Continue the discussion on Monad Forum
Questions, feedback, or a better idea? Weigh in on the forum thread.