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}