Pattern 3A
Stop using SSTORE as a within-tx scratchpad
When a function writes intermediate state to storage just to read it back later in the same call, you're paying state-growth and SLOAD costs for data that could live in memory.
Before
bytes32[64] private scratch;
function compute(bytes32 seed) external returns (uint256 sum) {
for (uint i = 0; i < 64; i++) {
scratch[i] = keccak256(abi.encode(seed, i)); // SSTORE
}
for (uint i = 0; i < 64; i++) {
sum += uint(scratch[i]); // SLOAD
}
}After
function compute(bytes32 seed) external pure returns (uint256 sum) {
bytes32[64] memory mem;
for (uint i = 0; i < 64; i++) {
mem[i] = keccak256(abi.encode(seed, i)); // MSTORE
}
for (uint i = 0; i < 64; i++) {
sum += uint(mem[i]); // MLOAD
}
}Measured on Monad mainnet: the storage variant cost 2,420,884 gas; the memory variant cost 57,003 gas, a 97.6% reduction. MIP-3 makes memory effectively free for typical workloads. Anywhere a function currently round-trips intermediate values through storage just to read them back in the same call, swap the storage variable for a memory variable. Both transaction hashes are linked below so you can verify the measurement.