revm_interpreter/instructions/
macros.rs1#[macro_export]
5#[collapse_debuginfo(yes)]
6macro_rules! tri {
7 ($e:expr) => {
8 match $e {
9 Some(v) => v,
10 None => return None,
11 }
12 };
13}
14
15#[macro_export]
17#[collapse_debuginfo(yes)]
18macro_rules! require_non_staticcall {
19 ($interpreter:expr) => {
20 if $interpreter.runtime_flag.is_static() {
21 $interpreter.halt($crate::InstructionResult::StateChangeDuringStaticCall);
22 return;
23 }
24 };
25}
26
27#[macro_export]
30#[collapse_debuginfo(yes)]
31macro_rules! otry {
32 ($expression: expr) => {{
33 let Some(value) = $expression else {
34 return;
35 };
36 value
37 }};
38}
39
40#[macro_export]
42#[collapse_debuginfo(yes)]
43macro_rules! check {
44 ($interpreter:expr, $min:ident) => {
45 if !$interpreter
46 .runtime_flag
47 .spec_id()
48 .is_enabled_in(primitives::hardfork::SpecId::$min)
49 {
50 $interpreter.halt_not_activated();
51 return;
52 }
53 };
54}
55
56#[macro_export]
58#[collapse_debuginfo(yes)]
59macro_rules! gas {
60 ($interpreter:expr, $gas:expr) => {
61 $crate::gas!($interpreter, $gas, ())
62 };
63 ($interpreter:expr, $gas:expr, $ret:expr) => {
64 if !$interpreter.gas.record_cost($gas) {
65 $interpreter.halt_oog();
66 return $ret;
67 }
68 };
69}
70
71#[macro_export]
73#[collapse_debuginfo(yes)]
74macro_rules! berlin_load_account {
75 ($context:expr, $address:expr, $load_code:expr) => {
76 $crate::berlin_load_account!($context, $address, $load_code, ())
77 };
78 ($context:expr, $address:expr, $load_code:expr, $ret:expr) => {{
79 $crate::gas!($context.interpreter, WARM_STORAGE_READ_COST, $ret);
80 let skip_cold_load =
81 $context.interpreter.gas.remaining() < COLD_ACCOUNT_ACCESS_COST_ADDITIONAL;
82 match $context
83 .host
84 .load_account_info_skip_cold_load($address, $load_code, skip_cold_load)
85 {
86 Ok(account) => {
87 if account.is_cold {
88 $crate::gas!(
89 $context.interpreter,
90 COLD_ACCOUNT_ACCESS_COST_ADDITIONAL,
91 $ret
92 );
93 }
94 account
95 }
96 Err(LoadError::ColdLoadSkipped) => {
97 $context.interpreter.halt_oog();
98 return $ret;
99 }
100 Err(LoadError::DBError) => {
101 $context.interpreter.halt_fatal();
102 return $ret;
103 }
104 }
105 }};
106}
107
108#[macro_export]
110#[collapse_debuginfo(yes)]
111macro_rules! gas_or_fail {
112 ($interpreter:expr, $gas:expr) => {
113 $crate::gas_or_fail!($interpreter, $gas, ())
114 };
115 ($interpreter:expr, $gas:expr, $ret:expr) => {
116 match $gas {
117 Some(gas_used) => $crate::gas!($interpreter, gas_used, $ret),
118 None => {
119 $interpreter.halt_oog();
120 return $ret;
121 }
122 }
123 };
124}
125
126#[macro_export]
129#[collapse_debuginfo(yes)]
130macro_rules! resize_memory {
131 ($interpreter:expr, $offset:expr, $len:expr) => {
132 $crate::resize_memory!($interpreter, $offset, $len, ())
133 };
134 ($interpreter:expr, $offset:expr, $len:expr, $ret:expr) => {
135 if !$crate::interpreter::resize_memory(
136 &mut $interpreter.gas,
137 &mut $interpreter.memory,
138 $offset,
139 $len,
140 ) {
141 $interpreter.halt_memory_oog();
142 return $ret;
143 }
144 };
145}
146
147#[macro_export]
149#[collapse_debuginfo(yes)]
150macro_rules! popn {
151 ([ $($x:ident),* ],$interpreter:expr $(,$ret:expr)? ) => {
152 let Some([$( $x ),*]) = $interpreter.stack.popn() else {
153 $interpreter.halt_underflow();
154 return $($ret)?;
155 };
156 };
157}
158
159#[doc(hidden)]
160#[macro_export]
161#[collapse_debuginfo(yes)]
162macro_rules! _count {
163 (@count) => { 0 };
164 (@count $head:tt $($tail:tt)*) => { 1 + _count!(@count $($tail)*) };
165 ($($arg:tt)*) => { _count!(@count $($arg)*) };
166}
167
168#[macro_export]
170#[collapse_debuginfo(yes)]
171macro_rules! popn_top {
172 ([ $($x:ident),* ], $top:ident, $interpreter:expr $(,$ret:expr)? ) => {
173 if $interpreter.stack.len() < (1 + $crate::_count!($($x)*)) {
182 $interpreter.halt_underflow();
183 return $($ret)?;
184 }
185 let ([$( $x ),*], $top) = unsafe { $interpreter.stack.popn_top().unwrap_unchecked() };
186 };
187}
188
189#[macro_export]
191#[collapse_debuginfo(yes)]
192macro_rules! push {
193 ($interpreter:expr, $x:expr $(,$ret:item)?) => (
194 if !($interpreter.stack.push($x)) {
195 $interpreter.halt_overflow();
196 return $($ret)?;
197 }
198 )
199}
200
201#[macro_export]
203#[collapse_debuginfo(yes)]
204macro_rules! as_u64_saturated {
205 ($v:expr) => {
206 match $v.as_limbs() {
207 x => {
208 if (x[1] == 0) & (x[2] == 0) & (x[3] == 0) {
209 x[0]
210 } else {
211 u64::MAX
212 }
213 }
214 }
215 };
216}
217
218#[macro_export]
220#[collapse_debuginfo(yes)]
221macro_rules! as_usize_saturated {
222 ($v:expr) => {
223 usize::try_from($crate::as_u64_saturated!($v)).unwrap_or(usize::MAX)
224 };
225}
226
227#[macro_export]
229#[collapse_debuginfo(yes)]
230macro_rules! as_isize_saturated {
231 ($v:expr) => {
232 isize::try_from($crate::as_u64_saturated!($v)).unwrap_or(isize::MAX)
235 };
236}
237
238#[macro_export]
240#[collapse_debuginfo(yes)]
241macro_rules! as_usize_or_fail {
242 ($interpreter:expr, $v:expr) => {
243 $crate::as_usize_or_fail_ret!($interpreter, $v, ())
244 };
245 ($interpreter:expr, $v:expr, $reason:expr) => {
246 $crate::as_usize_or_fail_ret!($interpreter, $v, $reason, ())
247 };
248}
249
250#[macro_export]
253#[collapse_debuginfo(yes)]
254macro_rules! as_usize_or_fail_ret {
255 ($interpreter:expr, $v:expr, $ret:expr) => {
256 $crate::as_usize_or_fail_ret!(
257 $interpreter,
258 $v,
259 $crate::InstructionResult::InvalidOperandOOG,
260 $ret
261 )
262 };
263
264 ($interpreter:expr, $v:expr, $reason:expr, $ret:expr) => {
265 match $v.as_limbs() {
266 x => {
267 if (x[0] > usize::MAX as u64) | (x[1] != 0) | (x[2] != 0) | (x[3] != 0) {
268 $interpreter.halt($reason);
269 return $ret;
270 }
271 x[0] as usize
272 }
273 }
274 };
275}