evm_core/
stack.rs

1use crate::ExitError;
2use alloc::vec::Vec;
3use primitive_types::H256;
4
5/// EVM stack.
6#[derive(Clone, Debug)]
7pub struct Stack {
8	data: Vec<H256>,
9	limit: usize,
10}
11
12impl Stack {
13	/// Create a new stack with given limit.
14	pub fn new(limit: usize) -> Self {
15		Self {
16			data: Vec::new(),
17			limit,
18		}
19	}
20
21	#[inline]
22	/// Stack limit.
23	pub fn limit(&self) -> usize {
24		self.limit
25	}
26
27	#[inline]
28	/// Stack length.
29	pub fn len(&self) -> usize {
30		self.data.len()
31	}
32
33	#[inline]
34	/// Whether the stack is empty.
35	pub fn is_empty(&self) -> bool {
36		self.data.is_empty()
37	}
38
39	#[inline]
40	/// Stack data.
41	pub fn data(&self) -> &Vec<H256> {
42		&self.data
43	}
44
45	#[inline]
46	/// Pop a value from the stack. If the stack is already empty, returns the
47	/// `StackUnderflow` error.
48	pub fn pop(&mut self) -> Result<H256, ExitError> {
49		self.data.pop().ok_or(ExitError::StackUnderflow)
50	}
51
52	#[inline]
53	/// Push a new value into the stack. If it will exceed the stack limit,
54	/// returns `StackOverflow` error and leaves the stack unchanged.
55	pub fn push(&mut self, value: H256) -> Result<(), ExitError> {
56		if self.data.len() + 1 > self.limit {
57			return Err(ExitError::StackOverflow);
58		}
59		self.data.push(value);
60		Ok(())
61	}
62
63	#[inline]
64	/// Peek a value at given index for the stack, where the top of
65	/// the stack is at index `0`. If the index is too large,
66	/// `StackError::Underflow` is returned.
67	pub fn peek(&self, no_from_top: usize) -> Result<H256, ExitError> {
68		if self.data.len() > no_from_top {
69			Ok(self.data[self.data.len() - no_from_top - 1])
70		} else {
71			Err(ExitError::StackUnderflow)
72		}
73	}
74
75	#[inline]
76	/// Set a value at given index for the stack, where the top of the
77	/// stack is at index `0`. If the index is too large,
78	/// `StackError::Underflow` is returned.
79	pub fn set(&mut self, no_from_top: usize, val: H256) -> Result<(), ExitError> {
80		if self.data.len() > no_from_top {
81			let len = self.data.len();
82			self.data[len - no_from_top - 1] = val;
83			Ok(())
84		} else {
85			Err(ExitError::StackUnderflow)
86		}
87	}
88}