referrerpolicy=no-referrer-when-downgrade

pallet_revive/vm/evm/instructions/
memory.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18use super::Context;
19use crate::vm::Ext;
20use core::cmp::max;
21use revm::{
22	interpreter::{
23		gas as revm_gas,
24		interpreter_types::{MemoryTr, RuntimeFlag, StackTr},
25	},
26	primitives::U256,
27};
28
29/// Implements the MLOAD instruction.
30///
31/// Loads a 32-byte word from memory.
32pub fn mload<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
33	gas_legacy!(context.interpreter, revm_gas::VERYLOW);
34	popn_top!([], top, context.interpreter);
35	let offset: usize = as_usize_or_fail!(context.interpreter, top);
36	resize_memory!(context.interpreter, offset, 32);
37	*top =
38		U256::try_from_be_slice(context.interpreter.memory.slice_len(offset, 32).as_ref()).unwrap()
39}
40
41/// Implements the MSTORE instruction.
42///
43/// Stores a 32-byte word to memory.
44pub fn mstore<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
45	gas_legacy!(context.interpreter, revm_gas::VERYLOW);
46	popn!([offset, value], context.interpreter);
47	let offset = as_usize_or_fail!(context.interpreter, offset);
48	resize_memory!(context.interpreter, offset, 32);
49	context.interpreter.memory.set(offset, &value.to_be_bytes::<32>());
50}
51
52/// Implements the MSTORE8 instruction.
53///
54/// Stores a single byte to memory.
55pub fn mstore8<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
56	gas_legacy!(context.interpreter, revm_gas::VERYLOW);
57	popn!([offset, value], context.interpreter);
58	let offset = as_usize_or_fail!(context.interpreter, offset);
59	resize_memory!(context.interpreter, offset, 1);
60	context.interpreter.memory.set(offset, &[value.byte(0)]);
61}
62
63/// Implements the MSIZE instruction.
64///
65/// Gets the size of active memory in bytes.
66pub fn msize<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
67	gas_legacy!(context.interpreter, revm_gas::BASE);
68	push!(context.interpreter, U256::from(context.interpreter.memory.size()));
69}
70
71/// Implements the MCOPY instruction.
72///
73/// EIP-5656: Memory copying instruction that copies memory from one location to another.
74pub fn mcopy<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
75	check!(context.interpreter, CANCUN);
76	popn!([dst, src, len], context.interpreter);
77
78	// Into usize or fail
79	let len = as_usize_or_fail!(context.interpreter, len);
80	// Deduce gas
81	gas_or_fail_legacy!(context.interpreter, revm_gas::copy_cost_verylow(len));
82	if len == 0 {
83		return;
84	}
85
86	let dst = as_usize_or_fail!(context.interpreter, dst);
87	let src = as_usize_or_fail!(context.interpreter, src);
88	// Resize memory
89	resize_memory!(context.interpreter, max(dst, src), len);
90	// Copy memory in place
91	context.interpreter.memory.copy(dst, src, len);
92}