What if memory cost scaled linearly?

EVM memory has a quadratic cost curve. MIP-3 makes it linear.

The information on this page should not be quoted. Please refer to MIP-3 for the authoritative spec.

Allocating memory...

32 B

Quadratic (current)

3 gas

Linear (MIP-3)

0 gas

Expanding to 32 B...

The quadratic wall

Ethereum charges words²/512 + 3*words for memory. MIP-3 charges words/2. Drag the slider to see how they diverge.

16 KB

32 B8 MB

Quadratic (ETH)

2.0K

gas

Linear (MIP-3)

256

gas

Improvement

8.0x

88% cheaper

Gas cost across memory sizes (log scale, capped at 30M for visibility)

32 B
60 B
111 B
208 B
388 B
724 B
1.3 KB
2.5 KB
4.6 KB
8.6 KB
16 KB
30 KB
56 KB
104 KB
194 KB
362 KB
676 KB
1.2 MB
2.3 MB
4.3 MB
8.0 MB
QuadraticLinear (MIP-3)30M gas block limit shown as 100%

Compare the cost

Select a scenario to see the memory expansion gas under the current quadratic model versus MIP-3's linear model.

Average memory usage observed on Ethereum mainnet. ABI encoding a few parameters.

Quadratic (ETH)

200

gas

words²/512 + 3 * words

64 words

Linear (MIP-3)

32

gas

words / 2

64 words

Memory expansion savings

6.3x cheaper

MIP-3: 32Quadratic: 200

What to write differently

Concrete Solidity patterns that benefit from linear memory pricing, each backed by a real Monad mainnet transaction.

Each suggestion below is backed by a transaction on Monad mainnet. Click any link to verify the gas cost on-chain.

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
    }
}

Before

2,420,884 gas

Verify on Monadscan

After

57,003 gas

Verify on Monadscan

Savings

−98%

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.

Pattern 3B

Allocate memory liberally, 1 MB is cheap

Ethereum's quadratic memory cost trained devs to avoid large in-memory buffers. On Monad, that constraint is gone.

Before

// On Ethereum, allocating 1 MB of memory is effectively
// impossible — the quadratic formula charges ~2.3 M gas for
// memory expansion alone, before you store a single byte.
// Devs work around this by chunking, splitting across txs,
// or keeping intermediate state in storage.

After

// On Monad, the same 1 MB allocation costs ~16 K gas total —
// linear in size. You can write the straight-line algorithm.
function process(bytes32 seed) external pure returns (uint256) {
    bytes memory buf = new bytes(1 << 20);  // 1 MB
    // ... fill, process, fold ...
}

Before

No equivalent 'before' tx on Monad — the same source runs on both chains. The qualitative contrast: this call would likely exceed Ethereum's 30 M block gas limit due to quadratic memory expansion of the intermediate keccak buffers.

After

13,512,834 gas

Verify on Monadscan

Savings

The 'after' tx allocates a 1 MB memory buffer, fills it with 32,768 keccak256 outputs, and folds them, all in one call, in 13.5 M gas (well within a single block). The same logic on Ethereum L1 would pay quadratic memory expansion costs for the intermediate keccak buffers and likely exceed the 30 M block gas limit, forcing devs to chunk the work across multiple transactions. There is no equivalent 'before' tx to deploy on Monad: the same code runs the same way; the difference is which chain can afford it. Reach for the straight-line algorithm.

Shared memory pool

Under MIP-3, child calls share the same 8 MB memory pool with their parent. When a call returns, its memory is released back.

On the current EVM, each call context gets fresh isolated memory. MIP-3 pools it, so nested calls don't waste the budget.

8 MB Transaction Pool

8 MB free

0 MB4 MB8 MB

0

MB used

8

MB free

0

calls deep

Call stack

No active calls

Transaction starts with 8 MB pool

Step 1 / 7

What this means for developers

Predictable costs

Linear pricing means doubling your memory doubles your cost. No quadratic surprises. Gas budgeting for memory-intensive operations becomes straightforward.

Large buffers are feasible

1 MB of working memory costs 16,384 gas. On-chain sorting, decompression, proof verification, and batch processing become practical within a single transaction.

Shared memory pool

Child calls borrow from the same 8 MB pool instead of getting isolated memory. When a call returns, its memory is released back. Nested calls no longer waste the budget.

Backwards compatible

All memory opcodes work identically: MLOAD, MSTORE, MSTORE8, MCOPY. What changes: expansion gas becomes linear, an 8 MB hard cap is enforced, and child calls share a memory pool with their parent instead of getting isolated memory.

Existing contracts get cheaper, not broken. Average memory usage is around 2 KB, which drops from 200 gas to 32 gas. The only contracts at risk are those hardcoding gas assumptions about memory expansion costs.

When the 8 MB limit is exceeded, the call fails with an out-of-gas error within the call frame, not a Solidity-level revert, so no return data is produced.

All memory-expanding opcodes use the new linear cost:

MLOADMSTOREMSTORE8MCOPYKECCAK256CALLDATACOPYCODECOPYRETURNDATACOPYEXTCODECOPYLOG0-LOG4CREATECREATE2CALLCALLCODEDELEGATECALLSTATICCALLRETURNREVERT

Continue the discussion on Monad Forum

Questions, feedback, or a better idea? Weigh in on the forum thread.

Open forum thread