diff --git a/heimdall/src/decompile/analyze.rs b/heimdall/src/decompile/analyze.rs index b7d093a0..3a80d87d 100644 --- a/heimdall/src/decompile/analyze.rs +++ b/heimdall/src/decompile/analyze.rs @@ -140,7 +140,7 @@ impl VMTrace { "emit Event_{}({}{});", match &logged_event.topics.first() { - Some(topic) => topic.get(0..8).unwrap(), + Some(topic) => topic, None => "00000000", }, match logged_event.topics.get(1..) { @@ -547,8 +547,7 @@ impl VMTrace { ) ); } else if opcode_name == "CALLDATALOAD" { - - let calldata_slot = (instruction.inputs[0].as_usize() - 4) / 32; + let calldata_slot = (instruction.inputs[0].as_usize().saturating_sub(4)) / 32; match function.arguments.get(&calldata_slot) { Some(_) => {} None => { @@ -556,7 +555,7 @@ impl VMTrace { calldata_slot, ( CalldataFrame { - slot: (instruction.inputs[0].as_usize() - 4) / 32, + slot: (instruction.inputs[0].as_usize().saturating_sub(4)) / 32, operation: instruction.input_operations[0].to_string(), mask_size: 32, heuristics: Vec::new(), diff --git a/heimdall/src/decompile/tests.rs b/heimdall/src/decompile/tests.rs index 6b19d3f8..e637574f 100644 --- a/heimdall/src/decompile/tests.rs +++ b/heimdall/src/decompile/tests.rs @@ -146,6 +146,7 @@ mod tests { "function Unresolved_d0e30db0() public payable {", "function Unresolved_dd62ed3e(address arg0, address arg1) public view returns (uint256) {" ] { + println!("{}", line); assert!(output.contains(line)); } @@ -178,6 +179,7 @@ mod tests { "function Unresolved_9b6deec4() public view payable returns (address) {", "function Unresolved_e834a834() public view payable returns (bool) {" ] { + println!("{}", line); assert!(output.contains(line)); } diff --git a/heimdall/src/decompile/util.rs b/heimdall/src/decompile/util.rs index ea62c858..c4721665 100644 --- a/heimdall/src/decompile/util.rs +++ b/heimdall/src/decompile/util.rs @@ -22,7 +22,7 @@ pub struct Function { // the function's entry point in the code. // the entry point is the instruction the dispatcher JUMPs to when called. - pub entry_point: u64, + pub entry_point: u128, // argument structure: // - key : slot operations of the argument. @@ -234,7 +234,7 @@ pub fn find_function_selectors(assembly: String) -> Vec { } // resolve a selector's function entry point from the EVM bytecode -pub fn resolve_entry_point(evm: &VM, selector: String) -> u64 { +pub fn resolve_entry_point(evm: &VM, selector: String) -> u128 { let mut vm = evm.clone(); // execute the EVM call to find the entry point for the given selector @@ -245,14 +245,20 @@ pub fn resolve_entry_point(evm: &VM, selector: String) -> u64 { // if the opcode is an JUMPI and it matched the selector, the next jumpi is the entry point if call.last_instruction.opcode == "57" { let jump_condition = call.last_instruction.input_operations[1].solidify(); - let jump_taken = call.last_instruction.inputs[1].as_u64(); + let jump_taken = match call.last_instruction.inputs[1].try_into() { + Ok(jump_taken) => jump_taken, + Err(_) => 1 + }; if jump_condition.contains(&selector) && jump_condition.contains("msg.data[0]") && jump_condition.contains(" == ") && jump_taken == 1 { - return call.last_instruction.inputs[0].as_u64(); + return match call.last_instruction.inputs[0].try_into() { + Ok(entry_point) => entry_point, + Err(_) => 0 + } } } @@ -268,7 +274,7 @@ pub fn resolve_entry_point(evm: &VM, selector: String) -> u64 { pub fn map_selector( evm: &VM, selector: String, - entry_point: u64, + entry_point: u128, ) -> (VMTrace, u32) { let mut vm = evm.clone(); vm.calldata = selector; diff --git a/heimdall/src/dump/util/threads/indexer.rs b/heimdall/src/dump/util/threads/indexer.rs index de6f2a88..a91c579e 100644 --- a/heimdall/src/dump/util/threads/indexer.rs +++ b/heimdall/src/dump/util/threads/indexer.rs @@ -1,5 +1,8 @@ +use std::time::Duration; + use ethers::types::{H160, Diff}; -use heimdall_common::utils::threading::task_pool; +use heimdall_common::{utils::threading::task_pool, io::logging::Logger}; +use indicatif::ProgressBar; use crate::dump::{util::get_storage_diff, constants::DUMP_STATE, structures::storage_slot::StorageSlot}; @@ -15,17 +18,39 @@ pub fn handle( // the number of threads cannot exceed the number of transactions let num_indexing_threads = std::cmp::min(transactions.len(), args.threads); + // get a new logger + let (logger, _) = Logger::new(args.verbose.log_level().unwrap().as_str()); + + // get a new progress bar + let transaction_list_progress = ProgressBar::new_spinner(); + transaction_list_progress.enable_steady_tick(Duration::from_millis(100)); + transaction_list_progress.set_style(logger.info_spinner()); + + if !args.no_tui { + transaction_list_progress.finish_and_clear(); + } + task_pool(transactions, num_indexing_threads, move |tx| { // get the storage diff for this transaction let state_diff = get_storage_diff(&tx, &args); - // unlock state let mut state = DUMP_STATE.lock().unwrap(); // find the transaction in the state + let all_txs = state.transactions.clone(); let txs = state.transactions.iter_mut().find(|t| t.hash == tx.hash).unwrap(); let block_number = tx.block_number.clone(); + + if args.no_tui { + let num_done = all_txs.iter().filter(|t| t.indexed).count(); + let total = all_txs.len(); + transaction_list_progress.set_message(format!("dumping storage. Progress {}/{} ({:.2}%)", num_done, total, (num_done as f64 / total as f64) * 100.0)); + + if num_done == total - 1{ + transaction_list_progress.finish_and_clear(); + } + } txs.indexed = true; // unwrap the state diff