Skip to content

Commit

Permalink
feat(decompile): proper constant decompilation, internal call decompi…
Browse files Browse the repository at this point in the history
…lation
  • Loading branch information
Jon-Becker committed Jun 22, 2024
1 parent b3b1deb commit b355c16
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 223 deletions.
3 changes: 2 additions & 1 deletion crates/common/src/ether/http_or_ws_or_ipc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ impl JsonRpcClient for HttpOrWsOrIpc {
async fn request<T, R>(&self, method: &str, params: T) -> Result<R, Self::Error>
where
T: Debug + Serialize + Send + Sync,
R: DeserializeOwned + Send, {
R: DeserializeOwned + Send,
{
let res = match self {
Self::Ws(ws) => JsonRpcClient::request(ws, method, params).await?,
Self::Ipc(ipc) => JsonRpcClient::request(ipc, method, params).await?,
Expand Down
5 changes: 3 additions & 2 deletions crates/common/src/ether/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use ethers::{
},
};
use heimdall_cache::{read_cache, store_cache};
use std::{str::FromStr, time::Duration};
use std::{io::Write, str::FromStr, time::Duration};
use tracing::{debug, error, trace};

/// Get the Provider object for RPC URL
Expand Down Expand Up @@ -335,7 +335,8 @@ pub async fn get_trace(transaction_hash: &str, rpc_url: &str) -> Result<BlockTra
"failed to replay and trace transaction '{}' . does your RPC provider support it?",
&transaction_hash
);
error!("error: '{}' .", e);
println!("e: {:#?}", e);

return Err(backoff::Error::Transient { err: (), retry_after: None })
}
};
Expand Down
186 changes: 0 additions & 186 deletions crates/core/src/heimdall.rs

This file was deleted.

12 changes: 6 additions & 6 deletions crates/decompile/src/core/out/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ pub fn build_abi(
// add functions
functions.iter().for_each(|f| {
// determine the state mutability of the function
let state_mutability = match f.payable {
true => StateMutability::Payable,
false => match f.pure {
true => StateMutability::Pure,
false => match f.view {
true => StateMutability::View,
let state_mutability = match f.pure {
true => StateMutability::Pure,
false => match f.view {
true => StateMutability::View,
false => match f.payable {
true => StateMutability::Payable,
false => StateMutability::NonPayable,
},
},
Expand Down
79 changes: 59 additions & 20 deletions crates/decompile/src/core/out/source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ pub fn build_source(
// write the header to the output file
source.extend(get_source_header(&analyzer_type));

// add storage variables
if analyzer_type == AnalyzerType::Solidity {
source.extend(get_constants(functions));
}

// add storage variables
if analyzer_type == AnalyzerType::Solidity {
source.extend(get_storage_variables(storage_variables, functions));
Expand All @@ -61,20 +66,27 @@ pub fn build_source(
}

// add functions
functions.iter().filter(|f| !f.fallback && f.maybe_getter_for.is_none()).for_each(|f| {
let mut function_source = Vec::new();
functions
.iter()
.filter(|f| {
!f.fallback
&& (analyzer_type == AnalyzerType::Yul
|| (f.maybe_getter_for.is_none() && !(f.pure && f.arguments.is_empty())))
})
.for_each(|f| {
let mut function_source = Vec::new();

// get the function header
function_source.extend(get_function_header(f));
function_source.extend(f.logic.clone());
function_source.push("}".to_string());
// get the function header
function_source.extend(get_function_header(f));
function_source.extend(f.logic.clone());
function_source.push("}".to_string());

let imbalance = get_indentation_imbalance(&function_source);
function_source.extend(vec!["}".to_string(); imbalance as usize]);
let imbalance = get_indentation_imbalance(&function_source);
function_source.extend(vec!["}".to_string(); imbalance as usize]);

// add the function to the source
source.extend(function_source);
});
// add the function to the source
source.extend(function_source);
});
if analyzer_type == AnalyzerType::Yul {
// add the fallback function, if it exists
if let Some(fallback) = functions.iter().find(|f| f.fallback) {
Expand Down Expand Up @@ -126,13 +138,13 @@ fn get_source_header(analyzer_type: &AnalyzerType) -> Vec<String> {

/// Helper function which will get the function header/signature for a given [`AnalyzedFunction`].
fn get_function_header(f: &AnalyzedFunction) -> Vec<String> {
// get the state mutability of the function
let state_mutability = match f.payable {
true => StateMutability::Payable,
false => match f.pure {
true => StateMutability::Pure,
false => match f.view {
true => StateMutability::View,
// determine the state mutability of the function
let state_mutability = match f.pure {
true => StateMutability::Pure,
false => match f.view {
true => StateMutability::View,
false => match f.payable {
true => StateMutability::Payable,
false => StateMutability::NonPayable,
},
},
Expand Down Expand Up @@ -212,14 +224,41 @@ fn get_function_header(f: &AnalyzedFunction) -> Vec<String> {
}
}

/// Helper function which will write constant variables to the source code.
fn get_constants(functions: &[AnalyzedFunction]) -> Vec<String> {
let mut output: Vec<String> = functions
.iter()
.filter_map(|f| {
if f.pure && f.arguments.is_empty() {
Some(format!(
"{} public constant {} = TMP;",
f.returns
.as_ref()
.unwrap_or(&"bytes".to_string())
.replacen("memory", "", 1)
.trim(),
f.resolved_function
.as_ref()
.map(|x| x.name.clone())
.unwrap_or("UNR".to_string())
))
} else {
None
}
})
.collect();
if !output.is_empty() {
output.push("".to_string());
}
output
}

/// Helper function which will write the storage variable declarations for the decompiled source
/// code.
fn get_storage_variables(
storage_variables: &HashMap<String, String>,
functions: &[AnalyzedFunction],
) -> Vec<String> {
println!("{:?}", storage_variables);

let mut output: Vec<String> = storage_variables
.iter()
.map(|(name, typ)| {
Expand Down
3 changes: 1 addition & 2 deletions crates/decompile/src/utils/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,7 @@ pragma solidity >=0.8.0;
/// @custom:github You can find the open-source decompiler here:
/// https://heimdall.rs
contract DecompiledContract {
".to_string();
contract DecompiledContract {".to_string();

/// the static header for decompiled yul contracts
pub static ref DECOMPILED_SOURCE_HEADER_YUL: String =
Expand Down
10 changes: 5 additions & 5 deletions crates/decompile/src/utils/heuristics/solidity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,10 @@ pub fn solidity_heuristic(

// perform a series of checks to determine if the condition
// is added by the compiler and can be ignored
if (conditional.contains("msg.data.length") && conditional.contains("0x04")) ||
VARIABLE_SIZE_CHECK_REGEX.is_match(&conditional).unwrap_or(false) ||
(conditional.replace('!', "") == "success") ||
(conditional == "!msg.value")
if (conditional.contains("msg.data.length") && conditional.contains("0x04"))
|| VARIABLE_SIZE_CHECK_REGEX.is_match(&conditional).unwrap_or(false)
|| (conditional.replace('!', "") == "success")
|| (conditional == "!msg.value")
{
return Ok(());
}
Expand Down Expand Up @@ -191,13 +191,13 @@ pub fn solidity_heuristic(
function.logic.push(format!(
"(bool success, bytes memory ret0) = address({}).{}{}(abi.encode({}));",
address,
modifier,
instruction
.opcode_details
.as_ref()
.expect("impossible")
.name
.to_lowercase(),
modifier,
calldata
.iter()
.map(|x| x.operation.solidify())
Expand Down
2 changes: 1 addition & 1 deletion crates/vm/src/ext/exec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ impl VM {
vm_trace.gas_used = vm.gas_used;

// if we encounter a JUMP(I), create children taking both paths and break
if last_instruction.opcode == 0x57 || last_instruction.opcode == 0x56 {
if last_instruction.opcode == 0x57 {
trace!(
"found branch due to JUMP{} instruction at {}",
if last_instruction.opcode == 0x57 { "I" } else { "" },
Expand Down

0 comments on commit b355c16

Please sign in to comment.