referrerpolicy=no-referrer-when-downgrade

pallet_revive/vm/evm/instructions/
stack.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::{utility::cast_slice_to_u256, Context};
19use crate::vm::Ext;
20use revm::{
21	interpreter::{
22		gas as revm_gas,
23		interpreter_types::{Immediates, Jumps, RuntimeFlag, StackTr},
24		InstructionResult,
25	},
26	primitives::U256,
27};
28
29/// Implements the POP instruction.
30///
31/// Removes the top item from the stack.
32pub fn pop<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
33	gas_legacy!(context.interpreter, revm_gas::BASE);
34	// Can ignore return. as relative N jump is safe operation.
35	popn!([_i], context.interpreter);
36}
37
38/// EIP-3855: PUSH0 instruction
39///
40/// Introduce a new instruction which pushes the constant value 0 onto the stack.
41pub fn push0<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
42	check!(context.interpreter, SHANGHAI);
43	gas_legacy!(context.interpreter, revm_gas::BASE);
44	push!(context.interpreter, U256::ZERO);
45}
46
47/// Implements the PUSH1-PUSH32 instructions.
48///
49/// Pushes N bytes from bytecode onto the stack as a 32-byte value.
50pub fn push<'ext, const N: usize, E: Ext>(context: Context<'_, 'ext, E>) {
51	gas_legacy!(context.interpreter, revm_gas::VERYLOW);
52	push!(context.interpreter, U256::ZERO);
53	popn_top!([], top, context.interpreter);
54
55	let imm = context.interpreter.bytecode.read_slice(N);
56	cast_slice_to_u256(imm, top);
57
58	// Can ignore return. as relative N jump is safe operation
59	context.interpreter.bytecode.relative_jump(N as isize);
60}
61
62/// Implements the DUP1-DUP16 instructions.
63///
64/// Duplicates the Nth stack item to the top of the stack.
65pub fn dup<'ext, const N: usize, E: Ext>(context: Context<'_, 'ext, E>) {
66	gas_legacy!(context.interpreter, revm_gas::VERYLOW);
67	if !context.interpreter.stack.dup(N) {
68		context.interpreter.halt(InstructionResult::StackOverflow);
69	}
70}
71
72/// Implements the SWAP1-SWAP16 instructions.
73///
74/// Swaps the top stack item with the Nth stack item.
75pub fn swap<'ext, const N: usize, E: Ext>(context: Context<'_, 'ext, E>) {
76	gas_legacy!(context.interpreter, revm_gas::VERYLOW);
77	assert!(N != 0);
78	if !context.interpreter.stack.exchange(0, N) {
79		context.interpreter.halt(InstructionResult::StackOverflow);
80	}
81}