Skip to main content

revm_handler/
frame_data.rs

1use context_interface::result::Output;
2use core::ops::Range;
3use interpreter::{CallOutcome, CreateOutcome, Gas, InstructionResult, InterpreterResult};
4use primitives::Address;
5
6/// Call Frame
7#[derive(Debug, Clone)]
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9pub struct CallFrame {
10    /// Call frame has return memory range where output will be stored.
11    pub return_memory_range: Range<usize>,
12}
13
14/// Create Frame
15#[derive(Debug, Clone)]
16#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
17pub struct CreateFrame {
18    /// Create frame has a created address.
19    pub created_address: Address,
20    /// EIP-8037: whether the created address was already alive (existing,
21    /// non-empty) before this CREATE. When true, no new account leaf is created,
22    /// so the upfront `create_state_gas` is refunded on a successful create.
23    pub target_was_alive: bool,
24}
25
26/// Frame Data
27///
28/// [`FrameData`] bundles different types of frames.
29#[derive(Debug, Clone)]
30#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
31pub enum FrameData {
32    /// Call frame data.
33    Call(CallFrame),
34    /// Create frame data.
35    Create(CreateFrame),
36}
37
38/// Frame Result
39#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
40#[derive(Debug, Clone)]
41pub enum FrameResult {
42    /// Call frame result.
43    Call(CallOutcome),
44    /// Create frame result.
45    Create(CreateOutcome),
46}
47
48impl FrameResult {
49    /// Creates a new call frame result for an out-of-gas error.
50    #[inline]
51    pub fn new_call_oog(
52        gas_limit: u64,
53        memory_offset: core::ops::Range<usize>,
54        reservoir: u64,
55    ) -> Self {
56        Self::Call(CallOutcome::new_oog(gas_limit, memory_offset, reservoir))
57    }
58
59    /// Creates a new create frame result for an out-of-gas error.
60    #[inline]
61    pub fn new_create_oog(gas_limit: u64, reservoir: u64) -> Self {
62        Self::Create(CreateOutcome::new_oog(gas_limit, reservoir))
63    }
64
65    /// Casts frame result to interpreter result.
66    #[inline]
67    pub fn into_interpreter_result(self) -> InterpreterResult {
68        match self {
69            FrameResult::Call(outcome) => outcome.result,
70            FrameResult::Create(outcome) => outcome.result,
71        }
72    }
73
74    /// Returns execution output.
75    #[inline]
76    pub fn output(&self) -> Output {
77        match self {
78            FrameResult::Call(outcome) => Output::Call(outcome.result.output.clone()),
79            FrameResult::Create(outcome) => {
80                Output::Create(outcome.result.output.clone(), outcome.address)
81            }
82        }
83    }
84
85    /// Returns reference to gas.
86    #[inline]
87    pub const fn gas(&self) -> &Gas {
88        match self {
89            FrameResult::Call(outcome) => &outcome.result.gas,
90            FrameResult::Create(outcome) => &outcome.result.gas,
91        }
92    }
93
94    /// Returns mutable reference to interpreter result.
95    #[inline]
96    pub const fn gas_mut(&mut self) -> &mut Gas {
97        match self {
98            FrameResult::Call(outcome) => &mut outcome.result.gas,
99            FrameResult::Create(outcome) => &mut outcome.result.gas,
100        }
101    }
102
103    /// Returns reference to interpreter result.
104    #[inline]
105    pub const fn interpreter_result(&self) -> &InterpreterResult {
106        match self {
107            FrameResult::Call(outcome) => &outcome.result,
108            FrameResult::Create(outcome) => &outcome.result,
109        }
110    }
111
112    /// Returns mutable reference to interpreter result.
113    #[inline]
114    pub const fn interpreter_result_mut(&mut self) -> &mut InterpreterResult {
115        match self {
116            FrameResult::Call(outcome) => &mut outcome.result,
117            FrameResult::Create(outcome) => &mut outcome.result,
118        }
119    }
120
121    /// Return Instruction result.
122    #[inline]
123    pub const fn instruction_result(&self) -> InstructionResult {
124        self.interpreter_result().result
125    }
126}
127
128impl FrameData {
129    /// Creates a new create frame data.
130    pub const fn new_create(created_address: Address) -> Self {
131        Self::Create(CreateFrame {
132            created_address,
133            target_was_alive: false,
134        })
135    }
136
137    /// Creates a new call frame data.
138    pub const fn new_call(return_memory_range: Range<usize>) -> Self {
139        Self::Call(CallFrame {
140            return_memory_range,
141        })
142    }
143
144    /// Returns true if frame is call frame.
145    pub const fn is_call(&self) -> bool {
146        matches!(self, Self::Call { .. })
147    }
148
149    /// Returns true if frame is create frame.
150    pub const fn is_create(&self) -> bool {
151        matches!(self, Self::Create { .. })
152    }
153
154    /// Returns created address if frame is create otherwise returns None.
155    pub const fn created_address(&self) -> Option<Address> {
156        match self {
157            Self::Create(create_frame) => Some(create_frame.created_address),
158            _ => None,
159        }
160    }
161}