example_custom_opcodes/
main.rs

1//! Custom opcodes example
2#![cfg_attr(not(test), warn(unused_crate_dependencies))]
3
4use revm::{
5    bytecode::opcode,
6    context::{Evm, TxEnv},
7    database::{BenchmarkDB, BENCH_TARGET},
8    handler::{instructions::EthInstructions, EthPrecompiles},
9    inspector::inspectors::TracerEip3155,
10    interpreter::{
11        interpreter::EthInterpreter,
12        interpreter_types::{Immediates, Jumps},
13        InstructionContext,
14    },
15    primitives::TxKind,
16    state::Bytecode,
17    Context, InspectEvm, MainContext,
18};
19
20/// Opcode hex value
21const MY_STATIC_JUMP: u8 = 0x0C;
22
23/// Demonstrates how to implement and use custom opcodes in REVM.
24/// This example shows how to create a custom static jump opcode that reads
25/// a 16-bit offset from the bytecode and performs a relative jump.
26pub fn main() {
27    let ctx = Context::mainnet().with_db(BenchmarkDB::new_bytecode(Bytecode::new_raw(
28        [
29            MY_STATIC_JUMP,
30            0x00,
31            0x03,
32            opcode::STOP,
33            opcode::JUMPDEST,
34            opcode::STOP,
35        ]
36        .into(),
37    )));
38
39    // Create a new instruction set with our mainnet opcodes.
40    let mut instructions = EthInstructions::new_mainnet();
41    // insert our custom opcode
42    instructions.insert_instruction(
43        MY_STATIC_JUMP,
44        |ctx: InstructionContext<'_, _, EthInterpreter>| {
45            let offset = ctx.interpreter.bytecode.read_i16();
46            ctx.interpreter.bytecode.relative_jump(offset as isize);
47        },
48    );
49
50    // Create a new EVM instance.
51    let mut evm = Evm::new(ctx, instructions, EthPrecompiles::default())
52        .with_inspector(TracerEip3155::new_stdout().without_summary());
53
54    // inspect the transaction.
55    let _ = evm.inspect_one_tx(TxEnv {
56        kind: TxKind::Call(BENCH_TARGET),
57        ..Default::default()
58    });
59
60    // Expected output where we can see that JUMPDEST is called.
61    /*
62    "{"pc":0,"op":12,"gas":"0x1c97178","gasCost":"0x0","stack":[],"depth":1,"returnData":"0x","refund":"0x0","memSize":"0x0"}
63    {"pc":4,"op":91,"gas":"0x1c97178","gasCost":"0x1","stack":[],"depth":1,"returnData":"0x","refund":"0x0","memSize":"0x0","opName":"JUMPDEST"}
64    {"pc":5,"op":0,"gas":"0x1c97177","gasCost":"0x0","stack":[],"depth":1,"returnData":"0x","refund":"0x0","memSize":"0x0","opName":"STOP"}
65    */
66}