Part III · Chapter 35 of 43 · Cancun · Deneb

EIP-5656: the memory-copy opcode the EVM never had

Copying a range of memory is one of the most basic things a program does — yet for years the EVM had no instruction for it. Contracts either ran a verbose MLOAD/MSTORE loop or abused the identity precompile as a roundabout memcpy. EIP-5656 finally adds MCOPY: one opcode, one copy.

Updated Jul 2, 2026 · 6 min
Assumed
  • the EVM's memory model
  • precompiles

Cancun / Deneb, March 2024. Here’s a humbling gap. In almost any programming environment, copying a block of bytes from one place to another is a single, cheap primitive — memcpy. The EVM has memory — a flat, expandable byte array — and contracts copy ranges of it constantly: assembling calldata, ABI-encoding return values, shuffling buffers in a hash function. And yet, for its entire history, the EVM had no memory-to-memory copy instruction. Developers worked around the hole in two awkward ways, both wasteful. EIP-5656 closes it with a single new opcode. Let’s derive it.

1 step No memcpy

The problem: the EVM had every way to copy memory except a good one

To copy N bytes of memory, a contract had two options, neither good. The first was a MLOAD/MSTORE loop Copying memory word by word: MLOAD reads 32 bytes onto the stack, MSTORE writes them to the destination, repeated for each word. It works, but it's many opcodes per copy — extra gas and extra bytecode for a trivial operation. : read 32 bytes with MLOAD, write them with MSTORE, and repeat, word by word. Correct, but it burns a pile of opcodes and gas and bloats the contract’s bytecode. The second was a notorious hack: the identity precompile The precompile at address 0x04 that returns its input unchanged. Because a call to it copies input to output, contracts abused it as a memcpy — paying full call overhead for a copy, and obscuring intent. at address 0x04 returns whatever you send it, so you could call it and use the returned data as a copy — paying call overhead to smuggle a memcpy out of a precompile that was never meant for it. That the ecosystem leaned on such tricks is the tell: a fundamental primitive was missing.

copy a range of memory — but there's no copy opcode option A: a loop MLOAD → MSTORE MLOAD → MSTORE MLOAD → MSTORE … many opcodes, lots of gas & bytecode option B: a hack CALL identity (0x04) misuse a precompile as memcpy call overhead, opaque, clumsy the most basic operation — memory copy — had no primitive
With no copy opcode, contracts either looped MLOAD then MSTORE word by word (many opcodes, extra gas and bytecode) or abused the identity precompile at 0x04 as a memcpy (call overhead, opaque). The most basic operation — copying memory — had no native primitive.

→ Step 2: add exactly that instruction.

2 step Add MCOPY

EIP-5656: one opcode, one copy

The fix is as direct as the problem. EIP-5656 adds the MCOPY Opcode 0x5e. Pops three stack items — destination offset, source offset, and length — and copies that many bytes within memory in one instruction, with correct handling of overlapping source and destination (like memmove). opcode (0x5e). It pops three values — destination, source, and length — and copies that many bytes of memory from source to destination in a single instruction. It handles overlapping regions correctly (the way memmove does), and it’s priced like the EVM’s other copy operations: a small base cost plus 3 gas per 32-byte word, plus any memory-expansion cost. No loop, no call, no hack — just the primitive, at its honest price.

MCOPY(dest, src, len): one opcode src dest copies len bytes at once — overlap handled like memmove priced like the other copy ops: 3 gas + 3 per word the primitive the EVM was missing
EIP-5656 adds MCOPY (0x5e): pop dest, src, len and copy that many bytes of memory in one opcode, with correct overlap semantics, priced like the other copy ops (3 gas + 3 per word). The primitive the EVM was missing.

→ Step 3: existing contracts get cheaper without lifting a finger.

3 step Cheaper for free

The payoff: a small opcode with broad reach

Because memory copying is everywhere — ABI encoding The standard way contracts lay out function arguments and return values in memory. It involves copying and relocating byte ranges constantly, so a cheaper memory copy makes a large share of ordinary contract execution cheaper. , string and array handling, and especially cryptographic code that shuffles buffers — a cheaper copy quietly makes a large fraction of contract execution cheaper and smaller. And the win is nearly automatic: compilers (Solidity, Vyper) emit MCOPY wherever they used to emit a copy loop, so contracts get cheaper and more compact simply by recompiling against a newer toolchain. The identity-precompile hack retires, intent becomes explicit in the bytecode, and the EVM finally has the memcpy it always should have. It’s the same spirit as PUSH0: give the machine the small, obvious primitive it lacked, and everything built on top gets a little leaner.

copies get cheaper — for free loop / hack MCOPY compilers emit it automatically — contracts get cheaper on recompile and the identity-precompile memcpy hack is retired
MCOPY makes memory copies cheaper and smaller, and compilers emit it automatically — so contracts get cheaper just by recompiling. The identity-precompile memcpy hack is retired. A tiny opcode with chain-wide reach, in the spirit of PUSH0.
04 Go Deeper Where to take it from here