Specification
## Abstract Redefine memory expansion cost to be linear and enforce an explicit maximum memory usage per transaction. ## Motivation Currently, EVM memory usage is bounded by a quadratic expansion cost and the 63/64 rule. The theoretical memory limit of a transaction is at least 26 MB. Historical transaction analysis shows that average memory usage is ~2 KB and maximum observed memory usage is ~2 MB. Benchmarks also indicate that the current memory expansion formula overcharges for actual resource usage. This update aligns cost with actual resource consumption. It makes memory usage more predictable, particularly for contracts that rely on large memory allocations. ## Specification Memory expansion cost is redefined as: ```python memory_size_words = (memory_byte_size + 31) // 32 memory_cost = memory_size_words // 2 ``` The max memory usage is capped at 8 MB. Memory allocation is bounded across call contexts with the following rule: 1. Let `k` be the memory used by the current call, and `j` the memory used by parent calls. 2. The remaining memory available to a child call is: ```python remaining_memory = 8 * 1024 * 1024 - j - k ``` 3. Once a call returns, the memory is returned to the pool. 4. If a call exceeds the remaining memory limit, it reverts. ## Backwards Compatibility This proposal is highly compatible with existing contracts. Almost all standard EVM operations remain valid and ERC-4337 contracts continue to function correctly, as child call memory is released upon completion. Replay testing of historical Ethereum transactions will be used to quantify compatibility. However, contracts that allocate more than 8 MB of memory will now revert. ## Security Considerations The cost to expand memory to the 8MB ceiling is 131,072 gas. The result is that it is cheaper to expand memory than current costs. Potentially concurrency limits for RPC nodes should be adjusted to prevent OOM issue. ## Acknowledgements The proposals in this MIP are based on two previous EIP documents. Additionally, conversations with Charles Cooper were instructive in developing the Monad memory model: - [EIP-7686](https://eips.ethereum.org/EIPS/eip-7686) (@vbuterin) - [EIP-7923](https://eips.ethereum.org/EIPS/eip-7923) (@charles-cooper, @qizhou) MIP-3 differs from EIP-7686 in that EIP-7686 defines a direct relationship between memory limit and gas limit, and from EIP-7923 in that MIP-3 does not adopt the page-based thrashing cost model. ## Copyright Copyright and related rights waived via [CC0](../LICENSE.md).
Forum discussion
-
MIP3 - Linear EVM memory cost This proposal reprices EVM memory expansion from a quadratic cost model to a linear one. To bound total memory usage within a block, each transaction is explicitly limited by its peak memory usage. The motivation is to better align EVM gas costs with real resource usage and to introduce an explicit invariant on total memory usage at the block level. Any feedback or discussion is appreciated on: - the proposed linear memory cost model - the explicit per-transaction memory limit - potential DoS concerns - developer ergonomics and usage concerns
-
Hello, I have questions to the design and spec: 1. How does the call which exceeds memory exit? revert or exceptionally halt? If revert, does the gas to extend memory get charged before reverting? and other instruction gas charges (esp. *CALL )? exceptionally halt is more consistent with current OOM behavior (out-of-gas), but revert is more friendly. The spec says “revert” but I want to confirm that’s what was meant and spec out the fine details. 2. For all calculation related to memory limit, the memory size isn’t rounded up to the nearest word, i.e. if caller frame allocates `limit - 1byte` memory, callee frame can still allocate `1byte` of memory? This is in the spec, but want to confirm.
-
- Can we expand discussion with EIP-7686 and EIP-7923 in the Rationale section, i.e. why is MIP-3 chosen over them? (my understanding is that EIP-7686 would combine unfavorably with Monad’s “charge-gas-limit” rule, what about the paging from EIP-7923?) - Similar to EIP-7923, behavior of MSIZE after the activation should be confirmed (esp. given the lack of rounding to word in memory limit calculation.) In other words - would MSIZE return limit or limit - 1byte in the case mentioned in (2.)?
-
Some Responses: - Exceeding the memory limit causes the current call frame to revert rather than halt. One rationale for this decision is compatibility with ERC-4337 bundlers for the following reason: if exceeding the memory limit resulted in an exceptional halt a transaction could DOS erc4337 bundlers by using the memory limit. If compatibility with erc4337 is not necessary then this can be changed to halt.
-
- Expansion cost remains in terms of 32 byte word expansion. This will be defined more explicitly in the MIP. - EIP-7686 and EIP-7923 are designed for ethereum execution specifically. For example in EIP-7686, it defines a strict bound on memory expansion via gas. This defines the amount of expandable memory to be linearly dependent on the amount of gas forwarded in the call. This is not compatible to the constraints of Monad execution. As it would cause a higher memory footprint per transaction. - MSIZE semantics are unchanged. It returns the size of active memory in bytes. So the case where caller frame allocates limit - 1byte memory is rounded up to the limit memory. The child call would not have any remaining memory to allocate.