UNPKG

@bcoders.gr/evm-disassembler

Version:

A comprehensive EVM bytecode disassembler and analyzer with support for multiple EVM versions

196 lines (162 loc) 5.67 kB
#!/usr/bin/env node /** * CLI interface for EVM Disassembler */ const fs = require('fs'); const path = require('path'); const { EVMDisassembler } = require('./index'); // Parse command line arguments const args = process.argv.slice(2); // Help text const helpText = ` EVM Bytecode Disassembler CLI Usage: evm-disassembler [options] <bytecode|file> Options: -h, --help Show this help message -v, --version Show version -f, --format <format> Output format (text, json, assembly, markdown, csv) [default: text] -o, --output <file> Write output to file instead of stdout --evm <version> EVM version (homestead, byzantium, constantinople, istanbul, berlin, london, paris, shanghai, cancun, latest) [default: latest] --no-metadata Don't include metadata detection --no-functions Don't perform function analysis --no-security Don't perform security analysis --no-stack Don't perform stack analysis --full-metadata Don't stop at metadata boundary --summary Show only summary (JSON format only) Examples: evm-disassembler 0x6080604052... evm-disassembler contract.bin evm-disassembler -f json -o output.json contract.bin evm-disassembler --format assembly --evm london bytecode.txt evm-disassembler --summary -f json contract.bin Input can be: - Hex bytecode string (with or without 0x prefix) - File containing hex bytecode - Binary file containing bytecode `; // Version const packageJson = require('./package.json'); const version = packageJson.version; // Parse arguments let input = null; let options = { format: 'text', output: null, evmVersion: 'latest', includeMetadata: true, performFunctionAnalysis: true, performSecurityAnalysis: true, performStackAnalysis: true, stopAtMetadata: true, summaryOnly: false }; for (let i = 0; i < args.length; i++) { const arg = args[i]; switch (arg) { case '-h': case '--help': console.log(helpText); process.exit(0); break; case '-v': case '--version': console.log(`evm-disassembler v${version}`); process.exit(0); break; case '-f': case '--format': options.format = args[++i]; break; case '-o': case '--output': options.output = args[++i]; break; case '--evm': options.evmVersion = args[++i]; break; case '--no-metadata': options.includeMetadata = false; break; case '--no-functions': options.performFunctionAnalysis = false; break; case '--no-security': options.performSecurityAnalysis = false; break; case '--no-stack': options.performStackAnalysis = false; break; case '--full-metadata': options.stopAtMetadata = false; break; case '--summary': options.summaryOnly = true; break; default: if (arg.startsWith('-')) { console.error(`Unknown option: ${arg}`); console.error('Use --help for usage information'); process.exit(1); } input = arg; break; } } // Check if input was provided if (!input) { console.error('Error: No input provided'); console.error('Use --help for usage information'); process.exit(1); } // Main function async function main() { try { let bytecode = input; // Check if input is a file if (fs.existsSync(input)) { const content = fs.readFileSync(input); // Check if it's a text file or binary if (input.endsWith('.bin') || input.endsWith('.bytecode')) { // Binary file - convert to hex bytecode = content.toString('hex'); } else { // Text file - assume it contains hex string bytecode = content.toString('utf8').trim(); } } // Create disassembler const disassembler = new EVMDisassembler({ evmVersion: options.evmVersion, includeMetadata: options.includeMetadata, stopAtMetadata: options.stopAtMetadata, performStackAnalysis: options.performStackAnalysis, performFunctionAnalysis: options.performFunctionAnalysis, performSecurityAnalysis: options.performSecurityAnalysis }); // Disassemble const result = disassembler.disassemble(bytecode); // Format output let output; if (options.summaryOnly && options.format === 'json') { output = JSON.stringify(result.summary, null, 2); } else { output = disassembler.format(result, options.format, { pretty: true }); } // Write output if (options.output) { fs.writeFileSync(options.output, output); console.log(`Output written to: ${options.output}`); } else { console.log(output); } } catch (error) { console.error(`Error: ${error.message}`); if (process.env.DEBUG) { console.error(error.stack); } process.exit(1); } } // Run main function main();