1#[macro_use]
4pub mod macros;
5pub mod arithmetic;
7pub mod bitwise;
9pub mod block_info;
11pub mod contract;
13pub mod control;
15pub mod host;
17pub mod i256;
19pub mod memory;
21pub mod stack;
23pub mod system;
25pub mod tx_info;
27pub mod utility;
29
30pub use context_interface::cfg::gas::{self, *};
31
32use crate::{interpreter_types::InterpreterTypes, Host, InstructionContext, InstructionExecResult};
33use primitives::hardfork::SpecId;
34
35#[derive(Debug)]
37pub struct Instruction<W: InterpreterTypes, H: ?Sized> {
38 fn_: fn(InstructionContext<'_, H, W>) -> InstructionExecResult,
39}
40
41impl<W: InterpreterTypes, H: Host + ?Sized> Instruction<W, H> {
42 #[inline]
44 pub const fn new(fn_: fn(InstructionContext<'_, H, W>) -> InstructionExecResult) -> Self {
45 Self { fn_ }
46 }
47
48 #[inline]
50 pub const fn unknown() -> Self {
51 Self {
52 fn_: control::unknown,
53 }
54 }
55
56 #[inline(always)]
58 pub fn execute(self, ctx: InstructionContext<'_, H, W>) -> InstructionExecResult {
59 (self.fn_)(ctx)
60 }
61}
62
63impl<W: InterpreterTypes, H: Host + ?Sized> Copy for Instruction<W, H> {}
64impl<W: InterpreterTypes, H: Host + ?Sized> Clone for Instruction<W, H> {
65 fn clone(&self) -> Self {
66 *self
67 }
68}
69
70pub type InstructionTable<W, H> = [Instruction<W, H>; 256];
72
73pub type GasTable = [u16; 256];
75
76#[inline]
78pub const fn instruction_table<WIRE: InterpreterTypes, H: Host>() -> InstructionTable<WIRE, H> {
79 const { instruction_table_impl::<WIRE, H>() }
80}
81
82#[inline]
84pub const fn gas_table() -> GasTable {
85 const { gas_table_impl() }
86}
87
88#[inline]
90pub const fn gas_table_spec(spec: SpecId) -> GasTable {
91 use bytecode::opcode::*;
92 use SpecId::*;
93 let mut table = gas_table();
94
95 if spec.is_enabled_in(TANGERINE) {
96 table[SLOAD as usize] = 200;
98 table[BALANCE as usize] = 400;
99 table[EXTCODESIZE as usize] = 700;
100 table[EXTCODECOPY as usize] = 700;
101 table[CALL as usize] = 700;
102 table[CALLCODE as usize] = 700;
103 table[DELEGATECALL as usize] = 700;
104 table[STATICCALL as usize] = 700;
105 table[SELFDESTRUCT as usize] = 5000;
106 }
107
108 if spec.is_enabled_in(ISTANBUL) {
109 table[SLOAD as usize] = gas::ISTANBUL_SLOAD_GAS as u16;
111 table[BALANCE as usize] = 700;
112 table[EXTCODEHASH as usize] = 700;
113 }
114
115 if spec.is_enabled_in(BERLIN) {
116 table[SLOAD as usize] = gas::WARM_STORAGE_READ_COST as u16;
118 table[BALANCE as usize] = gas::WARM_STORAGE_READ_COST as u16;
119 table[EXTCODESIZE as usize] = gas::WARM_STORAGE_READ_COST as u16;
120 table[EXTCODEHASH as usize] = gas::WARM_STORAGE_READ_COST as u16;
121 table[EXTCODECOPY as usize] = gas::WARM_STORAGE_READ_COST as u16;
122 table[CALL as usize] = gas::WARM_STORAGE_READ_COST as u16;
123 table[CALLCODE as usize] = gas::WARM_STORAGE_READ_COST as u16;
124 table[DELEGATECALL as usize] = gas::WARM_STORAGE_READ_COST as u16;
125 table[STATICCALL as usize] = gas::WARM_STORAGE_READ_COST as u16;
126 }
127
128 if spec.is_enabled_in(AMSTERDAM) {
129 let warm = primitives::eip8038::WARM_ACCESS as u16;
136 table[EXTCODESIZE as usize] = warm + warm;
137 table[EXTCODECOPY as usize] = warm + warm;
138 }
139
140 table
141}
142
143const fn instruction_table_impl<WIRE: InterpreterTypes, H: Host>() -> InstructionTable<WIRE, H> {
144 use bytecode::opcode::*;
145 let mut table = [Instruction::unknown(); 256];
146
147 table[STOP as usize] = Instruction::new(control::stop);
148 table[ADD as usize] = Instruction::new(arithmetic::add);
149 table[MUL as usize] = Instruction::new(arithmetic::mul);
150 table[SUB as usize] = Instruction::new(arithmetic::sub);
151 table[DIV as usize] = Instruction::new(arithmetic::div);
152 table[SDIV as usize] = Instruction::new(arithmetic::sdiv);
153 table[MOD as usize] = Instruction::new(arithmetic::rem);
154 table[SMOD as usize] = Instruction::new(arithmetic::smod);
155 table[ADDMOD as usize] = Instruction::new(arithmetic::addmod);
156 table[MULMOD as usize] = Instruction::new(arithmetic::mulmod);
157 table[EXP as usize] = Instruction::new(arithmetic::exp);
158 table[SIGNEXTEND as usize] = Instruction::new(arithmetic::signextend);
159
160 table[LT as usize] = Instruction::new(bitwise::lt);
161 table[GT as usize] = Instruction::new(bitwise::gt);
162 table[SLT as usize] = Instruction::new(bitwise::slt);
163 table[SGT as usize] = Instruction::new(bitwise::sgt);
164 table[EQ as usize] = Instruction::new(bitwise::eq);
165 table[ISZERO as usize] = Instruction::new(bitwise::iszero);
166 table[AND as usize] = Instruction::new(bitwise::bitand);
167 table[OR as usize] = Instruction::new(bitwise::bitor);
168 table[XOR as usize] = Instruction::new(bitwise::bitxor);
169 table[NOT as usize] = Instruction::new(bitwise::not);
170 table[BYTE as usize] = Instruction::new(bitwise::byte);
171 table[SHL as usize] = Instruction::new(bitwise::shl);
172 table[SHR as usize] = Instruction::new(bitwise::shr);
173 table[SAR as usize] = Instruction::new(bitwise::sar);
174 table[CLZ as usize] = Instruction::new(bitwise::clz);
175
176 table[KECCAK256 as usize] = Instruction::new(system::keccak256);
177
178 table[ADDRESS as usize] = Instruction::new(system::address);
179 table[BALANCE as usize] = Instruction::new(host::balance);
180 table[ORIGIN as usize] = Instruction::new(tx_info::origin);
181 table[CALLER as usize] = Instruction::new(system::caller);
182 table[CALLVALUE as usize] = Instruction::new(system::callvalue);
183 table[CALLDATALOAD as usize] = Instruction::new(system::calldataload);
184 table[CALLDATASIZE as usize] = Instruction::new(system::calldatasize);
185 table[CALLDATACOPY as usize] = Instruction::new(system::calldatacopy);
186 table[CODESIZE as usize] = Instruction::new(system::codesize);
187 table[CODECOPY as usize] = Instruction::new(system::codecopy);
188
189 table[GASPRICE as usize] = Instruction::new(tx_info::gasprice);
190 table[EXTCODESIZE as usize] = Instruction::new(host::extcodesize);
191 table[EXTCODECOPY as usize] = Instruction::new(host::extcodecopy);
192 table[RETURNDATASIZE as usize] = Instruction::new(system::returndatasize);
193 table[RETURNDATACOPY as usize] = Instruction::new(system::returndatacopy);
194 table[EXTCODEHASH as usize] = Instruction::new(host::extcodehash);
195 table[BLOCKHASH as usize] = Instruction::new(host::blockhash);
196 table[COINBASE as usize] = Instruction::new(block_info::coinbase);
197 table[TIMESTAMP as usize] = Instruction::new(block_info::timestamp);
198 table[NUMBER as usize] = Instruction::new(block_info::block_number);
199 table[DIFFICULTY as usize] = Instruction::new(block_info::difficulty);
200 table[GASLIMIT as usize] = Instruction::new(block_info::gaslimit);
201 table[CHAINID as usize] = Instruction::new(block_info::chainid);
202 table[SELFBALANCE as usize] = Instruction::new(host::selfbalance);
203 table[BASEFEE as usize] = Instruction::new(block_info::basefee);
204 table[BLOBHASH as usize] = Instruction::new(tx_info::blob_hash);
205 table[BLOBBASEFEE as usize] = Instruction::new(block_info::blob_basefee);
206 table[SLOTNUM as usize] = Instruction::new(block_info::slot_num);
207
208 table[POP as usize] = Instruction::new(stack::pop);
209 table[MLOAD as usize] = Instruction::new(memory::mload);
210 table[MSTORE as usize] = Instruction::new(memory::mstore);
211 table[MSTORE8 as usize] = Instruction::new(memory::mstore8);
212 table[SLOAD as usize] = Instruction::new(host::sload);
213 table[SSTORE as usize] = Instruction::new(host::sstore);
214 table[JUMP as usize] = Instruction::new(control::jump);
215 table[JUMPI as usize] = Instruction::new(control::jumpi);
216 table[PC as usize] = Instruction::new(control::pc);
217 table[MSIZE as usize] = Instruction::new(memory::msize);
218 table[GAS as usize] = Instruction::new(system::gas);
219 table[JUMPDEST as usize] = Instruction::new(control::jumpdest);
220 table[TLOAD as usize] = Instruction::new(host::tload);
221 table[TSTORE as usize] = Instruction::new(host::tstore);
222 table[MCOPY as usize] = Instruction::new(memory::mcopy);
223
224 table[PUSH0 as usize] = Instruction::new(stack::push0);
225 table[PUSH1 as usize] = Instruction::new(stack::push::<1, _, _>);
226 table[PUSH2 as usize] = Instruction::new(stack::push::<2, _, _>);
227 table[PUSH3 as usize] = Instruction::new(stack::push::<3, _, _>);
228 table[PUSH4 as usize] = Instruction::new(stack::push::<4, _, _>);
229 table[PUSH5 as usize] = Instruction::new(stack::push::<5, _, _>);
230 table[PUSH6 as usize] = Instruction::new(stack::push::<6, _, _>);
231 table[PUSH7 as usize] = Instruction::new(stack::push::<7, _, _>);
232 table[PUSH8 as usize] = Instruction::new(stack::push::<8, _, _>);
233 table[PUSH9 as usize] = Instruction::new(stack::push::<9, _, _>);
234 table[PUSH10 as usize] = Instruction::new(stack::push::<10, _, _>);
235 table[PUSH11 as usize] = Instruction::new(stack::push::<11, _, _>);
236 table[PUSH12 as usize] = Instruction::new(stack::push::<12, _, _>);
237 table[PUSH13 as usize] = Instruction::new(stack::push::<13, _, _>);
238 table[PUSH14 as usize] = Instruction::new(stack::push::<14, _, _>);
239 table[PUSH15 as usize] = Instruction::new(stack::push::<15, _, _>);
240 table[PUSH16 as usize] = Instruction::new(stack::push::<16, _, _>);
241 table[PUSH17 as usize] = Instruction::new(stack::push::<17, _, _>);
242 table[PUSH18 as usize] = Instruction::new(stack::push::<18, _, _>);
243 table[PUSH19 as usize] = Instruction::new(stack::push::<19, _, _>);
244 table[PUSH20 as usize] = Instruction::new(stack::push::<20, _, _>);
245 table[PUSH21 as usize] = Instruction::new(stack::push::<21, _, _>);
246 table[PUSH22 as usize] = Instruction::new(stack::push::<22, _, _>);
247 table[PUSH23 as usize] = Instruction::new(stack::push::<23, _, _>);
248 table[PUSH24 as usize] = Instruction::new(stack::push::<24, _, _>);
249 table[PUSH25 as usize] = Instruction::new(stack::push::<25, _, _>);
250 table[PUSH26 as usize] = Instruction::new(stack::push::<26, _, _>);
251 table[PUSH27 as usize] = Instruction::new(stack::push::<27, _, _>);
252 table[PUSH28 as usize] = Instruction::new(stack::push::<28, _, _>);
253 table[PUSH29 as usize] = Instruction::new(stack::push::<29, _, _>);
254 table[PUSH30 as usize] = Instruction::new(stack::push::<30, _, _>);
255 table[PUSH31 as usize] = Instruction::new(stack::push::<31, _, _>);
256 table[PUSH32 as usize] = Instruction::new(stack::push::<32, _, _>);
257
258 table[DUP1 as usize] = Instruction::new(stack::dup::<1, _, _>);
259 table[DUP2 as usize] = Instruction::new(stack::dup::<2, _, _>);
260 table[DUP3 as usize] = Instruction::new(stack::dup::<3, _, _>);
261 table[DUP4 as usize] = Instruction::new(stack::dup::<4, _, _>);
262 table[DUP5 as usize] = Instruction::new(stack::dup::<5, _, _>);
263 table[DUP6 as usize] = Instruction::new(stack::dup::<6, _, _>);
264 table[DUP7 as usize] = Instruction::new(stack::dup::<7, _, _>);
265 table[DUP8 as usize] = Instruction::new(stack::dup::<8, _, _>);
266 table[DUP9 as usize] = Instruction::new(stack::dup::<9, _, _>);
267 table[DUP10 as usize] = Instruction::new(stack::dup::<10, _, _>);
268 table[DUP11 as usize] = Instruction::new(stack::dup::<11, _, _>);
269 table[DUP12 as usize] = Instruction::new(stack::dup::<12, _, _>);
270 table[DUP13 as usize] = Instruction::new(stack::dup::<13, _, _>);
271 table[DUP14 as usize] = Instruction::new(stack::dup::<14, _, _>);
272 table[DUP15 as usize] = Instruction::new(stack::dup::<15, _, _>);
273 table[DUP16 as usize] = Instruction::new(stack::dup::<16, _, _>);
274
275 table[SWAP1 as usize] = Instruction::new(stack::swap::<1, _, _>);
276 table[SWAP2 as usize] = Instruction::new(stack::swap::<2, _, _>);
277 table[SWAP3 as usize] = Instruction::new(stack::swap::<3, _, _>);
278 table[SWAP4 as usize] = Instruction::new(stack::swap::<4, _, _>);
279 table[SWAP5 as usize] = Instruction::new(stack::swap::<5, _, _>);
280 table[SWAP6 as usize] = Instruction::new(stack::swap::<6, _, _>);
281 table[SWAP7 as usize] = Instruction::new(stack::swap::<7, _, _>);
282 table[SWAP8 as usize] = Instruction::new(stack::swap::<8, _, _>);
283 table[SWAP9 as usize] = Instruction::new(stack::swap::<9, _, _>);
284 table[SWAP10 as usize] = Instruction::new(stack::swap::<10, _, _>);
285 table[SWAP11 as usize] = Instruction::new(stack::swap::<11, _, _>);
286 table[SWAP12 as usize] = Instruction::new(stack::swap::<12, _, _>);
287 table[SWAP13 as usize] = Instruction::new(stack::swap::<13, _, _>);
288 table[SWAP14 as usize] = Instruction::new(stack::swap::<14, _, _>);
289 table[SWAP15 as usize] = Instruction::new(stack::swap::<15, _, _>);
290 table[SWAP16 as usize] = Instruction::new(stack::swap::<16, _, _>);
291
292 table[DUPN as usize] = Instruction::new(stack::dupn);
293 table[SWAPN as usize] = Instruction::new(stack::swapn);
294 table[EXCHANGE as usize] = Instruction::new(stack::exchange);
295
296 table[LOG0 as usize] = Instruction::new(host::log::<0, _>);
297 table[LOG1 as usize] = Instruction::new(host::log::<1, _>);
298 table[LOG2 as usize] = Instruction::new(host::log::<2, _>);
299 table[LOG3 as usize] = Instruction::new(host::log::<3, _>);
300 table[LOG4 as usize] = Instruction::new(host::log::<4, _>);
301
302 table[CREATE as usize] = Instruction::new(contract::create::<false, _, _>);
303 table[CALL as usize] = Instruction::new(contract::call::<CALL, _, _>);
304 table[CALLCODE as usize] = Instruction::new(contract::call::<CALLCODE, _, _>);
305 table[RETURN as usize] = Instruction::new(control::ret);
306 table[DELEGATECALL as usize] = Instruction::new(contract::call::<DELEGATECALL, _, _>);
307 table[CREATE2 as usize] = Instruction::new(contract::create::<true, _, _>);
308
309 table[STATICCALL as usize] = Instruction::new(contract::call::<STATICCALL, _, _>);
310 table[REVERT as usize] = Instruction::new(control::revert);
311 table[INVALID as usize] = Instruction::new(control::invalid);
312 table[SELFDESTRUCT as usize] = Instruction::new(host::selfdestruct);
313 table
314}
315
316const fn gas_table_impl() -> GasTable {
317 use bytecode::opcode::*;
318 let mut table = [0u16; 256];
319
320 table[STOP as usize] = 0;
321 table[ADD as usize] = 3;
322 table[MUL as usize] = 5;
323 table[SUB as usize] = 3;
324 table[DIV as usize] = 5;
325 table[SDIV as usize] = 5;
326 table[MOD as usize] = 5;
327 table[SMOD as usize] = 5;
328 table[ADDMOD as usize] = 8;
329 table[MULMOD as usize] = 8;
330 table[EXP as usize] = gas::EXP as u16; table[SIGNEXTEND as usize] = 5;
332
333 table[LT as usize] = 3;
334 table[GT as usize] = 3;
335 table[SLT as usize] = 3;
336 table[SGT as usize] = 3;
337 table[EQ as usize] = 3;
338 table[ISZERO as usize] = 3;
339 table[AND as usize] = 3;
340 table[OR as usize] = 3;
341 table[XOR as usize] = 3;
342 table[NOT as usize] = 3;
343 table[BYTE as usize] = 3;
344 table[SHL as usize] = 3;
345 table[SHR as usize] = 3;
346 table[SAR as usize] = 3;
347 table[CLZ as usize] = 5;
348
349 table[KECCAK256 as usize] = gas::KECCAK256 as u16;
350
351 table[ADDRESS as usize] = 2;
352 table[BALANCE as usize] = 20;
353 table[ORIGIN as usize] = 2;
354 table[CALLER as usize] = 2;
355 table[CALLVALUE as usize] = 2;
356 table[CALLDATALOAD as usize] = 3;
357 table[CALLDATASIZE as usize] = 2;
358 table[CALLDATACOPY as usize] = 3;
359 table[CODESIZE as usize] = 2;
360 table[CODECOPY as usize] = 3;
361
362 table[GASPRICE as usize] = 2;
363 table[EXTCODESIZE as usize] = 20;
364 table[EXTCODECOPY as usize] = 20;
365 table[RETURNDATASIZE as usize] = 2;
366 table[RETURNDATACOPY as usize] = 3;
367 table[EXTCODEHASH as usize] = 400;
368 table[BLOCKHASH as usize] = 20;
369 table[COINBASE as usize] = 2;
370 table[TIMESTAMP as usize] = 2;
371 table[NUMBER as usize] = 2;
372 table[DIFFICULTY as usize] = 2;
373 table[GASLIMIT as usize] = 2;
374 table[CHAINID as usize] = 2;
375 table[SELFBALANCE as usize] = 5;
376 table[BASEFEE as usize] = 2;
377 table[BLOBHASH as usize] = 3;
378 table[BLOBBASEFEE as usize] = 2;
379 table[SLOTNUM as usize] = 2;
380
381 table[POP as usize] = 2;
382 table[MLOAD as usize] = 3;
383 table[MSTORE as usize] = 3;
384 table[MSTORE8 as usize] = 3;
385 table[SLOAD as usize] = 50;
386 table[SSTORE as usize] = 0;
389 table[JUMP as usize] = 8;
390 table[JUMPI as usize] = 10;
391 table[PC as usize] = 2;
392 table[MSIZE as usize] = 2;
393 table[GAS as usize] = 2;
394 table[JUMPDEST as usize] = 1;
395 table[TLOAD as usize] = 100;
396 table[TSTORE as usize] = 100;
397 table[MCOPY as usize] = 3; table[PUSH0 as usize] = 2;
400 table[PUSH1 as usize] = 3;
401 table[PUSH2 as usize] = 3;
402 table[PUSH3 as usize] = 3;
403 table[PUSH4 as usize] = 3;
404 table[PUSH5 as usize] = 3;
405 table[PUSH6 as usize] = 3;
406 table[PUSH7 as usize] = 3;
407 table[PUSH8 as usize] = 3;
408 table[PUSH9 as usize] = 3;
409 table[PUSH10 as usize] = 3;
410 table[PUSH11 as usize] = 3;
411 table[PUSH12 as usize] = 3;
412 table[PUSH13 as usize] = 3;
413 table[PUSH14 as usize] = 3;
414 table[PUSH15 as usize] = 3;
415 table[PUSH16 as usize] = 3;
416 table[PUSH17 as usize] = 3;
417 table[PUSH18 as usize] = 3;
418 table[PUSH19 as usize] = 3;
419 table[PUSH20 as usize] = 3;
420 table[PUSH21 as usize] = 3;
421 table[PUSH22 as usize] = 3;
422 table[PUSH23 as usize] = 3;
423 table[PUSH24 as usize] = 3;
424 table[PUSH25 as usize] = 3;
425 table[PUSH26 as usize] = 3;
426 table[PUSH27 as usize] = 3;
427 table[PUSH28 as usize] = 3;
428 table[PUSH29 as usize] = 3;
429 table[PUSH30 as usize] = 3;
430 table[PUSH31 as usize] = 3;
431 table[PUSH32 as usize] = 3;
432
433 table[DUP1 as usize] = 3;
434 table[DUP2 as usize] = 3;
435 table[DUP3 as usize] = 3;
436 table[DUP4 as usize] = 3;
437 table[DUP5 as usize] = 3;
438 table[DUP6 as usize] = 3;
439 table[DUP7 as usize] = 3;
440 table[DUP8 as usize] = 3;
441 table[DUP9 as usize] = 3;
442 table[DUP10 as usize] = 3;
443 table[DUP11 as usize] = 3;
444 table[DUP12 as usize] = 3;
445 table[DUP13 as usize] = 3;
446 table[DUP14 as usize] = 3;
447 table[DUP15 as usize] = 3;
448 table[DUP16 as usize] = 3;
449
450 table[SWAP1 as usize] = 3;
451 table[SWAP2 as usize] = 3;
452 table[SWAP3 as usize] = 3;
453 table[SWAP4 as usize] = 3;
454 table[SWAP5 as usize] = 3;
455 table[SWAP6 as usize] = 3;
456 table[SWAP7 as usize] = 3;
457 table[SWAP8 as usize] = 3;
458 table[SWAP9 as usize] = 3;
459 table[SWAP10 as usize] = 3;
460 table[SWAP11 as usize] = 3;
461 table[SWAP12 as usize] = 3;
462 table[SWAP13 as usize] = 3;
463 table[SWAP14 as usize] = 3;
464 table[SWAP15 as usize] = 3;
465 table[SWAP16 as usize] = 3;
466
467 table[DUPN as usize] = 3;
468 table[SWAPN as usize] = 3;
469 table[EXCHANGE as usize] = 3;
470
471 table[LOG0 as usize] = gas::LOG as u16;
472 table[LOG1 as usize] = gas::LOG as u16;
473 table[LOG2 as usize] = gas::LOG as u16;
474 table[LOG3 as usize] = gas::LOG as u16;
475 table[LOG4 as usize] = gas::LOG as u16;
476
477 table[CREATE as usize] = 0;
478 table[CALL as usize] = 40;
479 table[CALLCODE as usize] = 40;
480 table[RETURN as usize] = 0;
481 table[DELEGATECALL as usize] = 40;
482 table[CREATE2 as usize] = 0;
483
484 table[STATICCALL as usize] = 40;
485 table[REVERT as usize] = 0;
486 table[INVALID as usize] = 0;
487 table[SELFDESTRUCT as usize] = 0;
488 table
489}
490
491#[cfg(test)]
492mod tests {
493 use super::instruction_table;
494 use crate::{host::DummyHost, interpreter::EthInterpreter};
495 use bytecode::opcode::*;
496
497 #[test]
498 fn all_instructions_and_opcodes_used() {
499 let unknown_instruction = 0x0C_usize;
501 let instr_table = instruction_table::<EthInterpreter, DummyHost>();
502
503 let unknown_istr = instr_table[unknown_instruction];
504 for (i, instr) in instr_table.iter().enumerate() {
505 let is_opcode_unknown = OpCode::new(i as u8).is_none();
506 let is_instr_unknown = std::ptr::fn_addr_eq(instr.fn_, unknown_istr.fn_);
508 assert_eq!(
509 is_instr_unknown, is_opcode_unknown,
510 "Opcode 0x{i:X?} is not handled",
511 );
512 }
513 }
514
515 #[test]
516 fn amsterdam_eip8038_ext_family_second_read() {
517 use super::gas_table_spec;
518 use primitives::hardfork::SpecId;
519
520 let warm = primitives::eip8038::WARM_ACCESS as u16;
521 let table = gas_table_spec(SpecId::AMSTERDAM);
522 assert_eq!(table[EXTCODESIZE as usize], warm + warm);
525 assert_eq!(table[EXTCODECOPY as usize], warm + warm);
526 assert_eq!(table[EXTCODEHASH as usize], warm);
528 assert_eq!(table[BALANCE as usize], warm);
529 assert_eq!(table[SLOAD as usize], warm);
530 let prague = gas_table_spec(SpecId::PRAGUE);
532 assert_eq!(prague[EXTCODESIZE as usize], prague[EXTCODEHASH as usize]);
533 }
534}