revm_interpreter/interpreter_action/call_inputs.rs
1use core::ops::Range;
2use primitives::{Address, Bytes, U256};
3
4/// Input enum for a call.
5///
6/// As CallInput uses shared memory buffer it can get overridden if not used directly when call happens.
7#[derive(Clone, Debug, PartialEq, Eq)]
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9pub enum CallInput {
10 /// The Range points to the SharedMemory buffer. Buffer can be found in [`context_interface::LocalContextTr::shared_memory_buffer_slice`] function.
11 /// And can be accessed with `evm.ctx().local().shared_memory_buffer()`
12 ///
13 /// # Warning
14 ///
15 /// Use it with caution, CallInput shared buffer can be overridden if context from child call is returned so
16 /// recommendation is to fetch buffer at first Inspector call and clone it from [`context_interface::LocalContextTr::shared_memory_buffer_slice`] function.
17 SharedBuffer(Range<usize>),
18 /// Bytes of the call data.
19 Bytes(Bytes),
20}
21
22impl CallInput {
23 /// Returns the length of the call input.
24 pub fn len(&self) -> usize {
25 match self {
26 Self::Bytes(bytes) => bytes.len(),
27 Self::SharedBuffer(range) => range.len(),
28 }
29 }
30
31 /// Returns `true` if the call input is empty.
32 pub fn is_empty(&self) -> bool {
33 self.len() == 0
34 }
35}
36
37impl Default for CallInput {
38 /// Returns a default `CallInput` with an empty `Bytes`.
39 #[inline]
40 fn default() -> Self {
41 CallInput::Bytes(Bytes::default())
42 }
43}
44
45/// Inputs for a call.
46#[derive(Clone, Debug, PartialEq, Eq)]
47#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
48pub struct CallInputs {
49 /// The call data of the call.
50 pub input: CallInput,
51 /// The return memory offset where the output of the call is written.
52 ///
53 /// In EOF, this range is invalid as EOF calls do not write output to memory.
54 pub return_memory_offset: Range<usize>,
55 /// The gas limit of the call.
56 pub gas_limit: u64,
57 /// The account address of bytecode that is going to be executed.
58 ///
59 /// Previously `context.code_address`.
60 pub bytecode_address: Address,
61 /// Target address, this account storage is going to be modified.
62 ///
63 /// Previously `context.address`.
64 pub target_address: Address,
65 /// This caller is invoking the call.
66 ///
67 /// Previously `context.caller`.
68 pub caller: Address,
69 /// Call value.
70 ///
71 /// **Note**: This value may not necessarily be transferred from caller to callee, see [`CallValue`].
72 ///
73 /// Previously `transfer.value` or `context.apparent_value`.
74 pub value: CallValue,
75 /// The call scheme.
76 ///
77 /// Previously `context.scheme`.
78 pub scheme: CallScheme,
79 /// Whether the call is a static call, or is initiated inside a static call.
80 pub is_static: bool,
81 /// Whether the call is initiated from EOF bytecode.
82 pub is_eof: bool,
83}
84
85impl CallInputs {
86 /// Returns `true` if the call will transfer a non-zero value.
87 #[inline]
88 pub fn transfers_value(&self) -> bool {
89 self.value.transfer().is_some_and(|x| x > U256::ZERO)
90 }
91
92 /// Returns the transfer value.
93 ///
94 /// This is the value that is transferred from caller to callee, see [`CallValue`].
95 #[inline]
96 pub const fn transfer_value(&self) -> Option<U256> {
97 self.value.transfer()
98 }
99
100 /// Returns the **apparent** call value.
101 ///
102 /// This value is not actually transferred, see [`CallValue`].
103 #[inline]
104 pub const fn apparent_value(&self) -> Option<U256> {
105 self.value.apparent()
106 }
107
108 /// Returns the address of the transfer source account.
109 ///
110 /// This is only meaningful if `transfers_value` is `true`.
111 #[inline]
112 pub const fn transfer_from(&self) -> Address {
113 self.caller
114 }
115
116 /// Returns the address of the transfer target account.
117 ///
118 /// This is only meaningful if `transfers_value` is `true`.
119 #[inline]
120 pub const fn transfer_to(&self) -> Address {
121 self.target_address
122 }
123
124 /// Returns the call value, regardless of the transfer value type.
125 ///
126 /// **Note**: This value may not necessarily be transferred from caller to callee, see [`CallValue`].
127 #[inline]
128 pub const fn call_value(&self) -> U256 {
129 self.value.get()
130 }
131}
132
133/// Call scheme.
134#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
135#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
136pub enum CallScheme {
137 /// `CALL`.
138 Call,
139 /// `CALLCODE`
140 CallCode,
141 /// `DELEGATECALL`
142 DelegateCall,
143 /// `STATICCALL`
144 StaticCall,
145 /// `EXTCALL`
146 ExtCall,
147 /// `EXTSTATICCALL`
148 ExtStaticCall,
149 /// `EXTDELEGATECALL`
150 ExtDelegateCall,
151}
152
153impl CallScheme {
154 /// Returns true if it is EOF EXT*CALL.
155 pub fn is_ext(&self) -> bool {
156 matches!(
157 self,
158 Self::ExtCall | Self::ExtStaticCall | Self::ExtDelegateCall
159 )
160 }
161
162 /// Returns true if it is ExtDelegateCall.
163 pub fn is_ext_delegate_call(&self) -> bool {
164 matches!(self, Self::ExtDelegateCall)
165 }
166}
167
168/// Call value.
169#[derive(Clone, Debug, PartialEq, Eq, Hash)]
170#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
171pub enum CallValue {
172 /// Concrete value, transferred from caller to callee at the end of the transaction.
173 Transfer(U256),
174 /// Apparent value, that is **not** actually transferred.
175 ///
176 /// Set when in a `DELEGATECALL` call type, and used by the `CALLVALUE` opcode.
177 Apparent(U256),
178}
179
180impl Default for CallValue {
181 #[inline]
182 fn default() -> Self {
183 CallValue::Transfer(U256::ZERO)
184 }
185}
186
187impl CallValue {
188 /// Returns the call value, regardless of the type.
189 #[inline]
190 pub const fn get(&self) -> U256 {
191 match *self {
192 Self::Transfer(value) | Self::Apparent(value) => value,
193 }
194 }
195
196 /// Returns the transferred value, if any.
197 #[inline]
198 pub const fn transfer(&self) -> Option<U256> {
199 match *self {
200 Self::Transfer(transfer) => Some(transfer),
201 Self::Apparent(_) => None,
202 }
203 }
204
205 /// Returns whether the call value will be transferred.
206 #[inline]
207 pub const fn is_transfer(&self) -> bool {
208 matches!(self, Self::Transfer(_))
209 }
210
211 /// Returns the apparent value, if any.
212 #[inline]
213 pub const fn apparent(&self) -> Option<U256> {
214 match *self {
215 Self::Transfer(_) => None,
216 Self::Apparent(apparent) => Some(apparent),
217 }
218 }
219
220 /// Returns whether the call value is apparent, and not actually transferred.
221 #[inline]
222 pub const fn is_apparent(&self) -> bool {
223 matches!(self, Self::Apparent(_))
224 }
225}