From a6577813e259be2bd87b2b776451b58213a7e7f8 Mon Sep 17 00:00:00 2001 From: Jonathan Becker <64037729+Jon-Becker@users.noreply.github.com> Date: Wed, 15 Mar 2023 23:14:55 -0500 Subject: [PATCH 1/5] :wrench: fix: panic unwrapping entry point --- heimdall/src/decompile/util.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/heimdall/src/decompile/util.rs b/heimdall/src/decompile/util.rs index ea62c858..d364dd58 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: u128 = match call.last_instruction.inputs[1].try_into() { + Ok(jump_taken) => jump_taken, + Err(_) => 0, + }; 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[1].try_into() { + Ok(jump_taken) => jump_taken, + 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; From 68b5694a7c69f79b426cba7ad10559b56f6ec2c1 Mon Sep 17 00:00:00 2001 From: Jonathan Becker <64037729+Jon-Becker@users.noreply.github.com> Date: Wed, 15 Mar 2023 23:45:55 -0500 Subject: [PATCH 2/5] :wrench: fix: overflow --- heimdall/src/decompile/analyze.rs | 6 +++--- heimdall/src/decompile/tests.rs | 2 ++ heimdall/src/decompile/util.rs | 12 ++++++------ 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/heimdall/src/decompile/analyze.rs b/heimdall/src/decompile/analyze.rs index b7d093a0..df4f3cc1 100644 --- a/heimdall/src/decompile/analyze.rs +++ b/heimdall/src/decompile/analyze.rs @@ -547,8 +547,8 @@ impl VMTrace { ) ); } else if opcode_name == "CALLDATALOAD" { - - let calldata_slot = (instruction.inputs[0].as_usize() - 4) / 32; + println!("CALLDATALOAD: {:?}", instruction); + let calldata_slot = (instruction.inputs[0].as_usize().saturating_sub(4)) / 32; match function.arguments.get(&calldata_slot) { Some(_) => {} None => { @@ -556,7 +556,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 d364dd58..c4721665 100644 --- a/heimdall/src/decompile/util.rs +++ b/heimdall/src/decompile/util.rs @@ -245,9 +245,9 @@ pub fn resolve_entry_point(evm: &VM, selector: String) -> u128 { // 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: u128 = match call.last_instruction.inputs[1].try_into() { + let jump_taken = match call.last_instruction.inputs[1].try_into() { Ok(jump_taken) => jump_taken, - Err(_) => 0, + Err(_) => 1 }; if jump_condition.contains(&selector) && @@ -255,10 +255,10 @@ pub fn resolve_entry_point(evm: &VM, selector: String) -> u128 { jump_condition.contains(" == ") && jump_taken == 1 { - return match call.last_instruction.inputs[1].try_into() { - Ok(jump_taken) => jump_taken, - Err(_) => 0, - }; + return match call.last_instruction.inputs[0].try_into() { + Ok(entry_point) => entry_point, + Err(_) => 0 + } } } From 9a3cba2c6aac6d9094157c777be306731f1eb304 Mon Sep 17 00:00:00 2001 From: Jonathan Becker <64037729+Jon-Becker@users.noreply.github.com> Date: Wed, 15 Mar 2023 23:48:23 -0500 Subject: [PATCH 3/5] =?UTF-8?q?=F0=9F=A7=B9=20clean:=20remove=20debugging?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- heimdall/src/decompile/analyze.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/heimdall/src/decompile/analyze.rs b/heimdall/src/decompile/analyze.rs index df4f3cc1..16d751f1 100644 --- a/heimdall/src/decompile/analyze.rs +++ b/heimdall/src/decompile/analyze.rs @@ -547,7 +547,6 @@ impl VMTrace { ) ); } else if opcode_name == "CALLDATALOAD" { - println!("CALLDATALOAD: {:?}", instruction); let calldata_slot = (instruction.inputs[0].as_usize().saturating_sub(4)) / 32; match function.arguments.get(&calldata_slot) { Some(_) => {} From 0ff6cb108759c1dbf80d161a67aca896487595ac Mon Sep 17 00:00:00 2001 From: Jonathan Becker <64037729+Jon-Becker@users.noreply.github.com> Date: Thu, 16 Mar 2023 11:15:50 -0500 Subject: [PATCH 4/5] :wrench: fix: include full event selector in solidity output --- heimdall/src/decompile/analyze.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/heimdall/src/decompile/analyze.rs b/heimdall/src/decompile/analyze.rs index 16d751f1..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..) { From aa7a204f444a80db660221fdd5526c9159d1402f Mon Sep 17 00:00:00 2001 From: Jonathan Becker <64037729+Jon-Becker@users.noreply.github.com> Date: Thu, 16 Mar 2023 18:29:49 -0500 Subject: [PATCH 5/5] :wrench: fix: show progress in `--no-tui` mode --- heimdall/src/dump/util/threads/indexer.rs | 29 +++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) 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