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, 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	gas_legacy!(context.interpreter, revm_gas::BASE);
43	push!(context.interpreter, U256::ZERO);
44}
45
46/// Implements the PUSH1-PUSH32 instructions.
47///
48/// Pushes N bytes from bytecode onto the stack as a 32-byte value.
49pub fn push<'ext, const N: usize, E: Ext>(context: Context<'_, 'ext, E>) {
50	gas_legacy!(context.interpreter, revm_gas::VERYLOW);
51	push!(context.interpreter, U256::ZERO);
52	popn_top!([], top, context.interpreter);
53
54	let imm = context.interpreter.bytecode.read_slice(N);
55	cast_slice_to_u256(imm, top);
56
57	// Can ignore return. as relative N jump is safe operation
58	context.interpreter.bytecode.relative_jump(N as isize);
59}
60
61/// Implements the DUP1-DUP16 instructions.
62///
63/// Duplicates the Nth stack item to the top of the stack.
64pub fn dup<'ext, const N: usize, E: Ext>(context: Context<'_, 'ext, E>) {
65	gas_legacy!(context.interpreter, revm_gas::VERYLOW);
66	if !context.interpreter.stack.dup(N) {
67		context.interpreter.halt(InstructionResult::StackOverflow);
68	}
69}
70
71/// Implements the SWAP1-SWAP16 instructions.
72///
73/// Swaps the top stack item with the Nth stack item.
74pub fn swap<'ext, const N: usize, E: Ext>(context: Context<'_, 'ext, E>) {
75	gas_legacy!(context.interpreter, revm_gas::VERYLOW);
76	assert!(N != 0);
77	if !context.interpreter.stack.exchange(0, N) {
78		context.interpreter.halt(InstructionResult::StackOverflow);
79	}
80}