Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🔧 fix: decompile patches #79

Merged
merged 6 commits into from
Mar 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 3 additions & 4 deletions heimdall/src/decompile/analyze.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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..) {
Expand Down Expand Up @@ -547,16 +547,15 @@ 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 => {
function.arguments.insert(
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(),
Expand Down
2 changes: 2 additions & 0 deletions heimdall/src/decompile/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}

Expand Down Expand Up @@ -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));
}

Expand Down
16 changes: 11 additions & 5 deletions heimdall/src/decompile/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -234,7 +234,7 @@ pub fn find_function_selectors(assembly: String) -> Vec<String> {
}

// 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
Expand All @@ -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
}
}
}

Expand All @@ -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;
Expand Down
29 changes: 27 additions & 2 deletions heimdall/src/dump/util/threads/indexer.rs
Original file line number Diff line number Diff line change
@@ -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};

Expand All @@ -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
Expand Down