diff --git a/src/ethereum/cancun/vm/instructions/__init__.py b/src/ethereum/cancun/vm/instructions/__init__.py index 90af5d1171..64c5bd455f 100644 --- a/src/ethereum/cancun/vm/instructions/__init__.py +++ b/src/ethereum/cancun/vm/instructions/__init__.py @@ -189,6 +189,7 @@ class Ops(enum.Enum): MSTORE = 0x52 MSTORE8 = 0x53 MSIZE = 0x59 + MCOPY = 0x5E # Log Operations LOG0 = 0xA0 @@ -249,6 +250,7 @@ class Ops(enum.Enum): Ops.MSTORE: memory_instructions.mstore, Ops.MSTORE8: memory_instructions.mstore8, Ops.MSIZE: memory_instructions.msize, + Ops.MCOPY: memory_instructions.mcopy, Ops.ADDRESS: environment_instructions.address, Ops.BALANCE: environment_instructions.balance, Ops.ORIGIN: environment_instructions.origin, diff --git a/src/ethereum/cancun/vm/instructions/memory.py b/src/ethereum/cancun/vm/instructions/memory.py index eecac9c585..2aef5d1404 100644 --- a/src/ethereum/cancun/vm/instructions/memory.py +++ b/src/ethereum/cancun/vm/instructions/memory.py @@ -11,11 +11,13 @@ Implementations of the EVM Memory instructions. """ -from ethereum.base_types import U8_MAX_VALUE, U256, Bytes +from ethereum.base_types import U8_MAX_VALUE, U256, Bytes, Uint +from ethereum.utils.numeric import ceil32 from .. import Evm from ..gas import ( GAS_BASE, + GAS_COPY, GAS_VERY_LOW, calculate_gas_extend_memory, charge_gas, @@ -138,3 +140,36 @@ def msize(evm: Evm) -> None: # PROGRAM COUNTER evm.pc += 1 + + +def mcopy(evm: Evm) -> None: + """ + Copy the bytes in memory from one location to another. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + destination = pop(evm.stack) + source = pop(evm.stack) + length = pop(evm.stack) + + # GAS + words = ceil32(Uint(length)) // 32 + copy_gas_cost = GAS_COPY * words + + extend_memory = calculate_gas_extend_memory( + evm.memory, [(source, length), (destination, length)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = memory_read_bytes(evm.memory, source, length) + memory_write(evm.memory, destination, value) + + # PROGRAM COUNTER + evm.pc += 1 diff --git a/whitelist.txt b/whitelist.txt index 927fa8c0e4..50e5836c55 100644 --- a/whitelist.txt +++ b/whitelist.txt @@ -389,4 +389,6 @@ rlps jsons mem +mcopy + checkable \ No newline at end of file