revm_interpreter/interpreter_action/
call_inputs.rs

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