-
Notifications
You must be signed in to change notification settings - Fork 58
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: Patrick Collins <54278053+PatrickAlphaC@users.noreply.github.com> Co-authored-by: VItto Rivabella <72762629+Eversmile12@users.noreply.github.com> Co-authored-by: Daniel Zarifpour <dzarifpour@gmail.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Tilak Madichetti <tilak.madichetti@gmail.com>
- Loading branch information
1 parent
4f1bed4
commit d824cff
Showing
71 changed files
with
846 additions
and
757 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
/target | ||
.DS_Store |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,7 @@ | ||
[package] | ||
name = "aderyn" | ||
version = "0.0.6" | ||
edition = "2021" | ||
authors = ["Alex Roan <alex@cyfrin.io>"] | ||
description = "Rust based Solidity AST analyzer" | ||
license = "MIT" | ||
[workspace] | ||
members = [ | ||
"aderyn", | ||
"aderyn_core" | ||
] | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
clap = { version = "4.4.6", features = ["derive"] } | ||
eyre = "0.6.8" | ||
serde = { version = "1.0.160", features = ["derive"] } | ||
serde_json = "1.0.96" | ||
serde_repr = "0.1.12" | ||
tokei = "12.1.2" | ||
toml = "0.8.2" | ||
resolver="1" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
[package] | ||
name = "aderyn" | ||
version = "0.0.7" | ||
edition = "2021" | ||
authors = ["Alex Roan <alex@cyfrin.io>"] | ||
description = "Rust based Solidity AST analyzer" | ||
license = "MIT" | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
aderyn_core = { version = "0.0.7", path = "../aderyn_core" } | ||
clap = { version = "4.4.6", features = ["derive"] } | ||
rayon = "1.8.0" | ||
tokei = "12.1.2" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
pub mod process_foundry; | ||
pub mod process_hardhat; | ||
pub mod virtual_foundry; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
use aderyn::{process_foundry, process_hardhat, virtual_foundry}; | ||
use aderyn_core::run; | ||
use clap::Parser; | ||
use std::{fs::read_dir, path::PathBuf}; | ||
use tokei::{Config, LanguageType}; | ||
|
||
#[derive(Parser, Debug)] | ||
#[command(author, version, about, long_about = None)] | ||
struct Args { | ||
/// Foundry or Hardhat project root directory (or path to single solidity file) | ||
root: String, | ||
|
||
/// Desired file path for the final report (will overwrite existing one) | ||
#[arg(short, long, default_value = "report.md")] | ||
output: String, | ||
} | ||
|
||
enum Framework { | ||
Foundry, | ||
Hardhat, | ||
} | ||
|
||
fn main() { | ||
let args = Args::parse(); | ||
|
||
if !args.output.ends_with(".md") { | ||
eprintln!("Warning: output file lacks the \".md\" extension in its filename."); | ||
} | ||
|
||
let is_single_file = args.root.ends_with(".sol") && PathBuf::from(&args.root).is_file(); | ||
let mut safe_space = PathBuf::new(); | ||
|
||
let (src_path, mut context_loader) = { | ||
if is_single_file { | ||
safe_space = virtual_foundry::build_isolated_workspace_for_file(&args.root); | ||
process_foundry::with_project_root_at(&safe_space) | ||
} else { | ||
println!("Detecting framework..."); | ||
let root_path = PathBuf::from(&args.root); | ||
let framework = detect_framework(root_path.clone()).unwrap_or_else(|| { | ||
// Exit with a non-zero exit code | ||
eprintln!("Error detecting framework"); | ||
std::process::exit(1); | ||
}); | ||
|
||
// This whole block loads the solidity files and ASTs into the context loader | ||
// TODO: move much of this gutsy stuff into the foundry / hardhat modules. | ||
match framework { | ||
Framework::Foundry => process_foundry::with_project_root_at(&root_path), | ||
Framework::Hardhat => process_hardhat::with_project_root_at(&root_path), | ||
} | ||
} | ||
}; | ||
|
||
// Using the source path, get the sloc from tokei | ||
let mut languages = tokei::Languages::new(); | ||
let tokei_config = Config::default(); | ||
languages.get_statistics(&[src_path], &[], &tokei_config); | ||
context_loader.set_sloc_stats(languages[&LanguageType::Solidity].clone()); | ||
|
||
// Load the context loader into the run function, which runs the detectors | ||
run(context_loader, args.output).unwrap_or_else(|err| { | ||
// Exit with a non-zero exit code | ||
eprintln!("Error running aderyn"); | ||
eprintln!("{:?}", err); | ||
std::process::exit(1); | ||
}); | ||
|
||
if is_single_file { | ||
virtual_foundry::delete_safe_space(&safe_space); | ||
} | ||
} | ||
|
||
fn detect_framework(path: PathBuf) -> Option<Framework> { | ||
// Canonicalize the path | ||
let canonical_path = path.canonicalize().expect("Failed to canonicalize path"); | ||
|
||
// Check if the directory exists | ||
if !canonical_path.is_dir() { | ||
return None; | ||
} | ||
|
||
// Read the contents of the directory | ||
let entries = read_dir(&canonical_path).expect("Failed to read directory"); | ||
|
||
for entry in entries.flatten() { | ||
let filename = entry.file_name(); | ||
match filename.to_str() { | ||
Some("foundry.toml") => return Some(Framework::Foundry), | ||
Some("hardhat.config.js") | Some("hardhat.config.ts") => { | ||
return Some(Framework::Hardhat) | ||
} | ||
_ => {} | ||
} | ||
} | ||
|
||
None | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
use aderyn_core::{ | ||
context::loader::ContextLoader, | ||
framework::foundry::{load_foundry, read_foundry_output_file}, | ||
read_file_to_string, | ||
visitor::ast_visitor::Node, | ||
}; | ||
use rayon::prelude::*; | ||
use std::path::PathBuf; | ||
|
||
pub fn with_project_root_at(root_path: &PathBuf) -> (String, ContextLoader) { | ||
let mut context_loader = ContextLoader::default(); | ||
|
||
println!("Framework detected: Foundry mode engaged."); | ||
println!("Foundry root path: {:?}", root_path); | ||
let loaded_foundry = load_foundry(root_path).unwrap_or_else(|err| { | ||
// Exit with a non-zero exit code | ||
eprintln!("Error loading Foundry Root"); | ||
eprintln!("{:?}", err); | ||
std::process::exit(1); | ||
}); | ||
let src_path_buf = root_path.join(&loaded_foundry.src_path); | ||
let src_path = src_path_buf.to_str().unwrap().to_string(); | ||
println!("Foundry src path: {:?}", src_path); | ||
|
||
// Load the foundry output files into the context loader using the ASTs | ||
let foundry_intermediates = loaded_foundry | ||
.output_filepaths | ||
.par_iter() | ||
.map(|output_filepath| { | ||
if let Ok(foundry_output) = read_foundry_output_file(output_filepath.to_str().unwrap()) | ||
{ | ||
Some(foundry_output.ast) | ||
} else { | ||
eprintln!( | ||
"Error reading Foundry output file: {}", | ||
output_filepath.to_str().unwrap() | ||
); | ||
None | ||
} | ||
}) | ||
.collect::<Vec<_>>(); | ||
|
||
// read_foundry_output_file and print an error message if it fails | ||
foundry_intermediates.into_iter().flatten().for_each(|ast| { | ||
ast.accept(&mut context_loader).unwrap_or_else(|err| { | ||
// Exit with a non-zero exit code | ||
eprintln!("Error loading Foundry AST into ContextLoader"); | ||
eprintln!("{:?}", err); | ||
std::process::exit(1); | ||
}) | ||
}); | ||
|
||
// Load the solidity source files into memory, and assign the content to the source_unit.source | ||
for source_filepath in loaded_foundry.src_filepaths { | ||
match read_file_to_string(&source_filepath) { | ||
Ok(content) => { | ||
// Convert the full_path to a string | ||
let full_path_str = source_filepath.to_str().unwrap_or(""); | ||
|
||
// Find the index where "src/" starts | ||
let src_component = src_path_buf.file_name().unwrap().to_str().unwrap(); | ||
if let Some(start_index) = full_path_str.find(src_component) { | ||
let target_path = &full_path_str[start_index..]; | ||
|
||
// Search for a match and modify | ||
for unit in &context_loader.source_units { | ||
if let Some(ref abs_path) = unit.absolute_path { | ||
if abs_path == target_path { | ||
context_loader.set_source_unit_source_content(unit.id, content); | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
Err(err) => { | ||
eprintln!( | ||
"Error reading Solidity source file: {}", | ||
source_filepath.to_str().unwrap() | ||
); | ||
eprintln!("{:?}", err); | ||
} | ||
} | ||
} | ||
|
||
(src_path, context_loader) | ||
} |
Oops, something went wrong.