Quiz — A Mini EVM Stack
Question
Reproduce EVM stack operations in a Rust Vec. pop + push + wrapping arithmetic + the unwrap_unchecked safety pattern — the same mechanics power Revm's hot path.
Principle (minimum model)
Vec::popreturnsOption<T>. Empty →None,Some(v)→ value. The null check is enforced by the type system.- EVM stack limit = 1024. Revm has
pub const STACK_LIMIT: usize = 1024;. Exceeding →StackOverflow. - EVM ADD uses
wrapping_add. mod 2²⁵⁶.saturating_addorchecked_addare off-consensus.+diverges between debug and release. unwrap_unchecked()+unsafe. When the length was just checked, the panic path becomes dead code →unwrap_uncheckedremoves it from the hot path. Hand-check + encode the invariant inunsafe.- Stack machine vs register machine, redux. Smaller instruction set + simpler operand encoding → easier to ZK-circuit / formally verify; runtime speed trades for verifiability.
Worked example + steps
Quiz: a mini EVM stack
Build a tiny Rust EVM-style stack with three operations:
push(n)— push a numberadd()— pop two, push their sumpeek()— read the top without removing it
You're building the same shape as the real Revm Stack you read in the previous lesson — just with i64 instead of U256 to keep things simple.
What you'll need
- A
structthat wraps aVec<i64> - An
implblock withnew(),push(&mut self, n),add(&mut self),peek(&self) - Knowledge of
Vec::popandVec::lastreturn types — what does Rust hand you when the vector is empty? - Underflow handling: what should
add()do when there are fewer than 2 items?
For the EVM-faithful version, addition wraps modulo (it doesn't saturate or panic on overflow). Look up the right method on integers.
Try it yourself
In Rust Playground, start with this scaffold:
struct MiniEvmStack {
data: Vec<i64>,
}
impl MiniEvmStack {
fn new() -> Self {
Self { data: Vec::new() }
}
// TODO: push, add, peek
}
fn main() {
let mut s = MiniEvmStack::new();
s.push(100);
s.push(200);
s.add().unwrap();
println!("{:?}", s.peek()); // Should print: Some(300)
}
Hints:
Vec::popreturnsOption<T>— empty case is encoded in the return typeVec::lastreturnsOption<&T>— borrowed, not copied (cheap)addshould return aResult<(), &'static str>so you can do.ok_or("stack underflow")?on the pop calls- For EVM-correct addition, the integer method whose name says "wrap" is what you want
Once it works, mentally compare your design to the real Revm Stack from the previous lesson — they have the same shape.
Quiz
Summary (3 lines)
Vec::pop -> Option<T>enforces the empty check at the type level. EVM stack limit 1024 (RevmSTACK_LIMIT). ADD iswrapping_add.unwrap_unchecked+unsafe= post-guard hot-path optimisation. Encode the invariant inunsafe.- Stack-machine choice trades raw runtime speed for verifiability. Next: async + traits + generics.