Pattern 8A
Replace dense-key mappings with arrays
Mappings hash each key to a slot scattered across the storage space. Consecutive logical indices land on different MIP-8 pages and pay a fresh cold-page cost each time.
Before
// Keys hash to keccak-scattered slots — consecutive
// indices land on different MIP-8 pages.
mapping(uint256 => uint256) private values;
function readEight(uint256 start) external view returns (uint256 sum) {
for (uint i = 0; i < 8; i++) {
sum += values[start + i]; // 8 cold-page loads
}
}After
// Adjacent slots — 8 entries fit comfortably in one page.
uint256[256] private values;
function readEight(uint256 start) external view returns (uint256 sum) {
for (uint i = 0; i < 8; i++) {
sum += values[start + i]; // 1 cold page + 7 warm
}
}The MIP-8 spec predicts a large saving here (8 cold pages → 1 cold + 7 warm, roughly 7× cheaper). Our mainnet measurement shows only a 0.5% difference: 116,281 gas scattered vs 115,729 gas packed. The page-locality charges the spec describes don't appear to differentiate these two layouts at the gas-schedule level on current Monad mainnet. Both tx hashes are linked so you can verify. For now, treat this pattern as forward-compatible (it will likely become a real win as MIP-8's full gas schedule lands), but don't refactor existing contracts expecting an immediate gas drop.