1use revm::{bytecode::Bytecode, primitives::Bytes};
2
3pub mod stats;
4pub use stats::{Stats, StatsError, compute_stats};
5pub mod abi;
6pub mod storage;
7
8pub use revm::bytecode::OpCode;
10
11#[derive(Debug)]
12pub enum DisassemblyError {
13 InvalidBytecode(String),
14 EmptyBytecode,
15 MalformedInstruction { position: usize, byte: u8 },
16}
17
18impl std::fmt::Display for DisassemblyError {
19 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
20 match self {
21 DisassemblyError::InvalidBytecode(msg) => write!(f, "Invalid bytecode: {msg}"),
22 DisassemblyError::EmptyBytecode => write!(f, "Bytecode is empty"),
23 DisassemblyError::MalformedInstruction { position, byte } => {
24 write!(
25 f,
26 "Malformed instruction at position {position}: invalid opcode 0x{byte:02x}"
27 )
28 }
29 }
30 }
31}
32
33impl std::error::Error for DisassemblyError {}
34
35pub fn disassemble(bytes: &[u8]) -> Result<Vec<(usize, OpCode)>, DisassemblyError> {
63 if bytes.is_empty() {
64 return Err(DisassemblyError::EmptyBytecode);
65 }
66
67 let bytecode = match Bytecode::new_raw_checked(Bytes::from(bytes.to_vec())) {
68 Ok(bytecode) => bytecode,
69 Err(e) => return Err(DisassemblyError::InvalidBytecode(e.to_string())),
70 };
71
72 let mut result: Vec<(usize, OpCode)> = Vec::new();
73 let mut bytecode_iter = bytecode.iter_opcodes();
74
75 while let Some(opcode) = bytecode_iter.peek_opcode() {
76 result.push((bytecode_iter.position(), opcode));
77 bytecode_iter.next();
78 }
79
80 if result.is_empty() {
81 return Err(DisassemblyError::InvalidBytecode(
82 "No valid opcodes found".to_string(),
83 ));
84 }
85
86 Ok(result)
87}
88
89pub fn get_stats(bytes: &[u8]) -> Result<Stats, DisassemblyError> {
114 if bytes.is_empty() {
115 return Err(DisassemblyError::EmptyBytecode);
116 }
117
118 let bytecode = match Bytecode::new_raw_checked(Bytes::from(bytes.to_vec())) {
119 Ok(bytecode) => bytecode,
120 Err(e) => return Err(DisassemblyError::InvalidBytecode(e.to_string())),
121 };
122
123 compute_stats(&bytecode).map_err(|e| match e {
124 StatsError::UnknownOpcode(opcode) => DisassemblyError::MalformedInstruction {
125 position: 0, byte: opcode,
127 },
128 })
129}
130#[cfg(test)]
131mod tests {
132 use super::*;
133
134 #[test]
135 fn push1_push2_stop() {
136 let bytes = hex::decode("60FF61ABCD00").unwrap(); let ops = disassemble(&bytes).unwrap();
138 assert_eq!(ops.len(), 3);
139 assert_eq!(ops[0].0, 0);
140 assert_eq!(ops[0].1, OpCode::PUSH1);
141 assert_eq!(ops[1].0, 2);
142 assert_eq!(ops[1].1, OpCode::PUSH2);
143 assert_eq!(ops[2].0, 5);
144 assert_eq!(ops[2].1, OpCode::STOP);
145 }
146
147 #[test]
148 fn memory_operations() {
149 let bytes = hex::decode("602060005260005100").unwrap();
151 let ops = disassemble(&bytes).unwrap();
152 assert_eq!(ops.len(), 6);
153 assert_eq!(ops[0], (0, OpCode::PUSH1)); assert_eq!(ops[1], (2, OpCode::PUSH1)); assert_eq!(ops[2], (4, OpCode::MSTORE)); assert_eq!(ops[3], (5, OpCode::PUSH1)); assert_eq!(ops[4], (7, OpCode::MLOAD)); assert_eq!(ops[5], (8, OpCode::STOP)); }
160
161 #[test]
162 fn stack_operations() {
163 let bytes = hex::decode("6001600280900100").unwrap();
165 let ops = disassemble(&bytes).unwrap();
166 assert_eq!(ops.len(), 6);
167 assert_eq!(ops[0], (0, OpCode::PUSH1)); assert_eq!(ops[1], (2, OpCode::PUSH1)); assert_eq!(ops[2], (4, OpCode::DUP1)); assert_eq!(ops[3], (5, OpCode::SWAP1)); assert_eq!(ops[4], (6, OpCode::ADD)); assert_eq!(ops[5], (7, OpCode::STOP)); }
174
175 #[test]
176 fn storage_and_crypto() {
177 let bytes = hex::decode("60426000556000542000").unwrap();
179 let ops = disassemble(&bytes).unwrap();
180 assert_eq!(ops.len(), 7);
181 assert_eq!(ops[0], (0, OpCode::PUSH1)); assert_eq!(ops[1], (2, OpCode::PUSH1)); assert_eq!(ops[2], (4, OpCode::SSTORE)); assert_eq!(ops[3], (5, OpCode::PUSH1)); assert_eq!(ops[4], (7, OpCode::SLOAD)); assert_eq!(ops[5], (8, OpCode::KECCAK256)); assert_eq!(ops[6], (9, OpCode::STOP)); }
189
190 #[test]
191 fn empty_bytecode_error() {
192 let bytes = vec![];
193 let result = disassemble(&bytes);
194 assert!(result.is_err());
195 match result.unwrap_err() {
196 DisassemblyError::EmptyBytecode => {} _ => panic!("Expected EmptyBytecode error"),
198 }
199 }
200
201 #[test]
202 fn test_get_stats() {
203 let bytes = hex::decode("60FF60010100").unwrap();
205 let stats = get_stats(&bytes).unwrap();
206
207 assert_eq!(stats.byte_len, 6);
208 assert_eq!(stats.opcode_count, 4);
209 assert!(stats.max_stack_depth > 0);
210 }
211
212 #[test]
213 fn test_stats_with_empty_bytecode() {
214 let bytes = vec![];
215 let result = get_stats(&bytes);
216 assert!(result.is_err());
217 match result.unwrap_err() {
218 DisassemblyError::EmptyBytecode => {} _ => panic!("Expected EmptyBytecode error"),
220 }
221 }
222}