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}