Skip to main content

revm_interpreter/instructions/
memory.rs

1use crate::interpreter::resize_memory;
2use crate::interpreter_types::{InterpreterTypes as ITy, MemoryTr, RuntimeFlag, StackTr};
3use crate::{InstructionContext as Ictx, InstructionExecResult as Result};
4use context_interface::Host;
5use core::cmp::max;
6use primitives::U256;
7
8/// Implements the MLOAD instruction.
9///
10/// Loads a 32-byte word from memory.
11pub fn mload<IT: ITy, H: Host + ?Sized>(context: Ictx<'_, H, IT>) -> Result {
12    popn_top!([], top, context.interpreter);
13    let offset = as_usize_or_fail!(context.interpreter, top);
14    resize_memory(
15        &mut context.interpreter.gas,
16        &mut context.interpreter.memory,
17        context.host.gas_params(),
18        offset,
19        32,
20    )?;
21    *top =
22        U256::try_from_be_slice(context.interpreter.memory.slice_len(offset, 32).as_ref()).unwrap();
23    Ok(())
24}
25
26/// Implements the MSTORE instruction.
27///
28/// Stores a 32-byte word to memory.
29pub fn mstore<IT: ITy, H: Host + ?Sized>(context: Ictx<'_, H, IT>) -> Result {
30    popn!([offset, value], context.interpreter);
31    let offset = as_usize_or_fail!(context.interpreter, offset);
32    context
33        .interpreter
34        .resize_memory(context.host.gas_params(), offset, 32)?;
35    context
36        .interpreter
37        .memory
38        .set(offset, &value.to_be_bytes::<32>());
39    Ok(())
40}
41
42/// Implements the MSTORE8 instruction.
43///
44/// Stores a single byte to memory.
45pub fn mstore8<IT: ITy, H: Host + ?Sized>(context: Ictx<'_, H, IT>) -> Result {
46    popn!([offset, value], context.interpreter);
47    let offset = as_usize_or_fail!(context.interpreter, offset);
48    context
49        .interpreter
50        .resize_memory(context.host.gas_params(), offset, 1)?;
51    context.interpreter.memory.set(offset, &[value.byte(0)]);
52    Ok(())
53}
54
55/// Implements the MSIZE instruction.
56///
57/// Gets the size of active memory in bytes.
58pub fn msize<IT: ITy, H: ?Sized>(context: Ictx<'_, H, IT>) -> Result {
59    push!(
60        context.interpreter,
61        U256::from(context.interpreter.memory.size())
62    );
63    Ok(())
64}
65
66/// Implements the MCOPY instruction.
67///
68/// EIP-5656: Memory copying instruction that copies memory from one location to another.
69pub fn mcopy<IT: ITy, H: Host + ?Sized>(context: Ictx<'_, H, IT>) -> Result {
70    check!(context.interpreter, CANCUN);
71    popn!([dst, src, len], context.interpreter);
72
73    // Into usize or fail
74    let len = as_usize_or_fail!(context.interpreter, len);
75    // Deduce gas
76    gas!(
77        context.interpreter,
78        context.host.gas_params().mcopy_cost(len)
79    );
80
81    if len == 0 {
82        return Ok(());
83    }
84
85    let dst = as_usize_or_fail!(context.interpreter, dst);
86    let src = as_usize_or_fail!(context.interpreter, src);
87    // Resize memory
88    context
89        .interpreter
90        .resize_memory(context.host.gas_params(), max(dst, src), len)?;
91    // Copy memory in place
92    context.interpreter.memory.copy(dst, src, len);
93    Ok(())
94}