revme/cmd/
bytecode.rs

1use clap::Parser;
2use revm::primitives::{hex, Bytes};
3
4/// `bytecode` subcommand - simplified to handle legacy bytecode only.
5#[derive(Parser, Debug)]
6pub struct Cmd {
7    /// Bytecode in hex format string.
8    #[arg()]
9    bytes: Option<String>,
10}
11
12#[inline]
13fn trim_decode(input: &str) -> Option<Bytes> {
14    let trimmed = input.trim().trim_start_matches("0x");
15    hex::decode(trimmed).ok().map(Into::into)
16}
17
18impl Cmd {
19    /// Runs bytecode command.
20    pub fn run(&self) {
21        if let Some(input_bytes) = &self.bytes {
22            let Some(bytes) = trim_decode(input_bytes) else {
23                eprintln!("Invalid hex string");
24                return;
25            };
26
27            if bytes.starts_with(&[0xEF, 0x00]) {
28                eprintln!(
29                    "EOF bytecode is not supported - EOF has been removed from ethereum plan."
30                );
31                return;
32            }
33
34            println!("Legacy bytecode:");
35            println!("  Length: {} bytes", bytes.len());
36            println!("  Hex: 0x{}", hex::encode(&bytes));
37
38            // Basic analysis
39            let mut opcodes = Vec::new();
40            let mut i = 0;
41            while i < bytes.len() {
42                let opcode = bytes[i];
43                opcodes.push(format!("{opcode:02x}"));
44
45                // Skip immediate bytes for PUSH instructions
46                if (0x60..=0x7f).contains(&opcode) {
47                    let push_size = (opcode - 0x5f) as usize;
48                    i += push_size;
49                }
50                i += 1;
51            }
52
53            println!("  Opcodes: {}", opcodes.join(" "));
54        } else {
55            println!("No bytecode provided. EOF interactive mode has been removed.");
56            println!("Please provide bytecode as a hex string argument.");
57        }
58    }
59}