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)]
31#[deprecated(
32 since = "29.0.0",
33 note = "Prefer `let Some(x) = expr else { return; };` for early return in instruction functions"
34)]
35macro_rules! otry {
36 ($expression: expr) => {{
37 let Some(value) = $expression else {
38 return;
39 };
40 value
41 }};
42}
43
44#[macro_export]
46#[collapse_debuginfo(yes)]
47macro_rules! check {
48 ($interpreter:expr, $min:ident) => {
49 if !$interpreter
50 .runtime_flag
51 .spec_id()
52 .is_enabled_in(primitives::hardfork::SpecId::$min)
53 {
54 $interpreter.halt_not_activated();
55 return;
56 }
57 };
58}
59
60#[macro_export]
62#[collapse_debuginfo(yes)]
63macro_rules! gas {
64 ($interpreter:expr, $gas:expr) => {
65 $crate::gas!($interpreter, $gas, ())
66 };
67 ($interpreter:expr, $gas:expr, $ret:expr) => {
68 if !$interpreter.gas.record_cost($gas) {
69 $interpreter.halt_oog();
70 return $ret;
71 }
72 };
73}
74
75#[macro_export]
77#[collapse_debuginfo(yes)]
78macro_rules! berlin_load_account {
79 ($context:expr, $address:expr, $load_code:expr) => {
80 $crate::berlin_load_account!($context, $address, $load_code, ())
81 };
82 ($context:expr, $address:expr, $load_code:expr, $ret:expr) => {{
83 $crate::gas!($context.interpreter, WARM_STORAGE_READ_COST, $ret);
84 let skip_cold_load =
85 $context.interpreter.gas.remaining() < COLD_ACCOUNT_ACCESS_COST_ADDITIONAL;
86 match $context
87 .host
88 .load_account_info_skip_cold_load($address, $load_code, skip_cold_load)
89 {
90 Ok(account) => {
91 if account.is_cold {
92 $crate::gas!(
93 $context.interpreter,
94 COLD_ACCOUNT_ACCESS_COST_ADDITIONAL,
95 $ret
96 );
97 }
98 account
99 }
100 Err(LoadError::ColdLoadSkipped) => {
101 $context.interpreter.halt_oog();
102 return $ret;
103 }
104 Err(LoadError::DBError) => {
105 $context.interpreter.halt_fatal();
106 return $ret;
107 }
108 }
109 }};
110}
111
112#[macro_export]
114#[collapse_debuginfo(yes)]
115macro_rules! gas_or_fail {
116 ($interpreter:expr, $gas:expr) => {
117 $crate::gas_or_fail!($interpreter, $gas, ())
118 };
119 ($interpreter:expr, $gas:expr, $ret:expr) => {
120 match $gas {
121 Some(gas_used) => $crate::gas!($interpreter, gas_used, $ret),
122 None => {
123 $interpreter.halt_oog();
124 return $ret;
125 }
126 }
127 };
128}
129
130#[macro_export]
133#[collapse_debuginfo(yes)]
134macro_rules! resize_memory {
135 ($interpreter:expr, $offset:expr, $len:expr) => {
136 $crate::resize_memory!($interpreter, $offset, $len, ())
137 };
138 ($interpreter:expr, $offset:expr, $len:expr, $ret:expr) => {
139 #[cfg(feature = "memory_limit")]
140 if $interpreter.memory.limit_reached($offset, $len) {
141 $interpreter.halt_memory_limit_oog();
142 return $ret;
143 }
144 if !$crate::interpreter::resize_memory(
145 &mut $interpreter.gas,
146 &mut $interpreter.memory,
147 $offset,
148 $len,
149 ) {
150 $interpreter.halt_memory_oog();
151 return $ret;
152 }
153 };
154}
155
156#[macro_export]
158#[collapse_debuginfo(yes)]
159macro_rules! popn {
160 ([ $($x:ident),* ],$interpreter:expr $(,$ret:expr)? ) => {
161 let Some([$( $x ),*]) = $interpreter.stack.popn() else {
162 $interpreter.halt_underflow();
163 return $($ret)?;
164 };
165 };
166}
167
168#[doc(hidden)]
169#[macro_export]
170#[collapse_debuginfo(yes)]
171macro_rules! _count {
172 (@count) => { 0 };
173 (@count $head:tt $($tail:tt)*) => { 1 + _count!(@count $($tail)*) };
174 ($($arg:tt)*) => { _count!(@count $($arg)*) };
175}
176
177#[macro_export]
179#[collapse_debuginfo(yes)]
180macro_rules! popn_top {
181 ([ $($x:ident),* ], $top:ident, $interpreter:expr $(,$ret:expr)? ) => {
182 if $interpreter.stack.len() < (1 + $crate::_count!($($x)*)) {
191 $interpreter.halt_underflow();
192 return $($ret)?;
193 }
194 let ([$( $x ),*], $top) = unsafe { $interpreter.stack.popn_top().unwrap_unchecked() };
195 };
196}
197
198#[macro_export]
200#[collapse_debuginfo(yes)]
201macro_rules! push {
202 ($interpreter:expr, $x:expr $(,$ret:item)?) => (
203 if !($interpreter.stack.push($x)) {
204 $interpreter.halt_overflow();
205 return $($ret)?;
206 }
207 )
208}
209
210#[macro_export]
212#[collapse_debuginfo(yes)]
213macro_rules! as_u64_saturated {
214 ($v:expr) => {
215 match $v.as_limbs() {
216 x => {
217 if (x[1] == 0) & (x[2] == 0) & (x[3] == 0) {
218 x[0]
219 } else {
220 u64::MAX
221 }
222 }
223 }
224 };
225}
226
227#[macro_export]
229#[collapse_debuginfo(yes)]
230macro_rules! as_usize_saturated {
231 ($v:expr) => {
232 usize::try_from($crate::as_u64_saturated!($v)).unwrap_or(usize::MAX)
233 };
234}
235
236#[macro_export]
238#[collapse_debuginfo(yes)]
239macro_rules! as_isize_saturated {
240 ($v:expr) => {
241 isize::try_from($crate::as_u64_saturated!($v)).unwrap_or(isize::MAX)
244 };
245}
246
247#[macro_export]
249#[collapse_debuginfo(yes)]
250macro_rules! as_usize_or_fail {
251 ($interpreter:expr, $v:expr) => {
252 $crate::as_usize_or_fail_ret!($interpreter, $v, ())
253 };
254 ($interpreter:expr, $v:expr, $reason:expr) => {
255 $crate::as_usize_or_fail_ret!($interpreter, $v, $reason, ())
256 };
257}
258
259#[macro_export]
262#[collapse_debuginfo(yes)]
263macro_rules! as_usize_or_fail_ret {
264 ($interpreter:expr, $v:expr, $ret:expr) => {
265 $crate::as_usize_or_fail_ret!(
266 $interpreter,
267 $v,
268 $crate::InstructionResult::InvalidOperandOOG,
269 $ret
270 )
271 };
272
273 ($interpreter:expr, $v:expr, $reason:expr, $ret:expr) => {
274 match $v.as_limbs() {
275 x => {
276 if (x[0] > usize::MAX as u64) | (x[1] != 0) | (x[2] != 0) | (x[3] != 0) {
277 $interpreter.halt($reason);
278 return $ret;
279 }
280 x[0] as usize
281 }
282 }
283 };
284}