From e510a8fe64219e4fcb8b1b2b596c38f1535354c8 Mon Sep 17 00:00:00 2001 From: Tilak Madichetti Date: Wed, 26 Feb 2025 14:05:40 +0530 Subject: [PATCH] Post release master-merge (#808) --- .github/workflows/cargo.yml | 43 ++++++++++------------- .github/workflows/config.yml | 53 +++++++++++++++++++++++++++++ .github/workflows/dependencies.yml | 22 ++++++++++++ .github/workflows/reports.yml | 5 +++ Cargo.lock | 6 ++-- README.md | 39 +++++++-------------- aderyn/Cargo.toml | 4 +-- aderyn/src/lib.rs | 5 ++- aderyn/src/main.rs | 3 +- aderyn/templates/aderyn.toml | 42 ++++++++++++++--------- aderyn_core/Cargo.toml | 2 +- aderyn_driver/Cargo.toml | 4 +-- aderyn_driver/src/config_helpers.rs | 7 ++++ aderyn_driver/src/driver.rs | 2 +- aderyn_driver/src/lsp_report.rs | 16 ++++----- reports/report.sarif | 4 +-- tests/2024-05-Sablier | 2 +- tests/adhoc-sol-files/aderyn.toml | 1 + 18 files changed, 165 insertions(+), 95 deletions(-) create mode 100644 .github/workflows/config.yml create mode 100644 .github/workflows/dependencies.yml diff --git a/.github/workflows/cargo.yml b/.github/workflows/cargo.yml index 351eb0db2..e1cd41f2d 100644 --- a/.github/workflows/cargo.yml +++ b/.github/workflows/cargo.yml @@ -2,6 +2,10 @@ on: [push, pull_request, workflow_dispatch] name: Aderyn +concurrency: + group: ci-${{ github.ref }}-cargo + cancel-in-progress: true + jobs: check: name: Check @@ -31,42 +35,31 @@ jobs: runs-on: ubuntu-latest steps: - - name: foundry-toolchain + - name: Install Foundry Toolchain uses: foundry-rs/foundry-toolchain@v1.2.0 - - name: Checkout sources + - name: Checkout Sources uses: actions/checkout@v4 - - name: Install stable toolchain + - name: Install Rust Nightly (2025-01-01) uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: stable + toolchain: nightly-2025-01-01 override: true - - - uses: Swatinem/rust-cache@v2 - - name: Run cargo build - run: | - cargo build - - - uses: actions/checkout@v4 - - uses: pnpm/action-setup@v4 - with: - version: 8 - run_install: false - - - uses: actions/setup-node@v4 - with: - node-version: 20 - cache: 'npm' - - name: Submodule init - run: | - git submodule update --init --recursive + - name: Checkout Submodules + run: git submodule update --init --recursive - - uses: Swatinem/rust-cache@v2 - - name: Run cargo test + - name: Checkout Sources + uses: actions/checkout@v4 + + - name: Restore Rust Cache + uses: Swatinem/rust-cache@v2 + + - name: Run tests run: | + cargo build cargo test -- --nocapture lints: diff --git a/.github/workflows/config.yml b/.github/workflows/config.yml new file mode 100644 index 000000000..d48be13fa --- /dev/null +++ b/.github/workflows/config.yml @@ -0,0 +1,53 @@ +on: [push, pull_request, workflow_dispatch] + +name: Config + +concurrency: + group: ci-${{ github.ref }}-config + cancel-in-progress: true + +jobs: + reports-setup: + name: Check Config + runs-on: ubuntu-latest + outputs: + rust-nightly: nightly-2025-01-01 + + steps: + - name: Install Foundry Toolchain + uses: foundry-rs/foundry-toolchain@v1.2.0 + + - name: Checkout Sources + uses: actions/checkout@v4 + + - name: Install Rust Nightly (2025-01-01) + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: nightly-2025-01-01 + override: true + + - name: Cache Rust Dependencies + uses: Swatinem/rust-cache@v2 + + - name: Checkout Submodules + run: git submodule update --init --recursive + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'npm' + + - name: Checkout Sources + uses: actions/checkout@v4 + + - name: Restore Rust Cache + uses: Swatinem/rust-cache@v2 + + - name: Initialize config + run: | + mkdir config-test + cd config-test + cargo run -- init + diff ./aderyn.toml ../aderyn/templates/aderyn.toml diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml new file mode 100644 index 000000000..040053e78 --- /dev/null +++ b/.github/workflows/dependencies.yml @@ -0,0 +1,22 @@ +# Runs `cargo update` periodically. +# Reference: +# https://github.com/paradigmxyz/solar/blob/main/.github/workflows/dependencies.yml + +name: Dependencies + +on: + schedule: + # Run weekly + - cron: "0 0 * * SUN" + workflow_dispatch: + # Needed so we can run it manually + +permissions: + contents: write + pull-requests: write + +jobs: + update: + uses: ithacaxyz/ci/.github/workflows/cargo-update-pr.yml@dev + secrets: + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/reports.yml b/.github/workflows/reports.yml index 5aa320661..011bed438 100644 --- a/.github/workflows/reports.yml +++ b/.github/workflows/reports.yml @@ -2,6 +2,10 @@ on: [push, pull_request, workflow_dispatch] name: Reports Workflow +concurrency: + group: ci-${{ github.ref }}-reports + cancel-in-progress: true + jobs: reports-setup: name: Check Reports @@ -10,6 +14,7 @@ jobs: rust-nightly: nightly-2025-01-01 strategy: + fail-fast: false matrix: task: - report-workflow diff --git a/Cargo.lock b/Cargo.lock index 36d8c8717..f4b3ad607 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,7 +23,7 @@ dependencies = [ [[package]] name = "aderyn" -version = "0.4.2" +version = "0.4.3" dependencies = [ "aderyn_driver", "clap", @@ -44,7 +44,7 @@ dependencies = [ [[package]] name = "aderyn_core" -version = "0.4.2" +version = "0.4.3" dependencies = [ "crossbeam-channel", "cyfrin-foundry-compilers", @@ -70,7 +70,7 @@ dependencies = [ [[package]] name = "aderyn_driver" -version = "0.4.2" +version = "0.4.3" dependencies = [ "aderyn_core", "criterion", diff --git a/README.md b/README.md index 5b6f1309d..88c300297 100644 --- a/README.md +++ b/README.md @@ -56,62 +56,47 @@ You can read the [Cyfrin official documentation](https://docs.cyfrin.io) for an ## Installation > **NOTE** Windows users must have WSL installed - ### Using Cyfrinup #### Step 1: Install Cyfrinup - Cyfrinup is a CLI tool that simplifies the installation and management of Cyfrin tools. To install Cyfrinup, run the following command in your terminal: - ```sh curl -L https://raw.githubusercontent.com/Cyfrin/aderyn/dev/cyfrinup/install | bash ``` +If you get a `failed writing body` error in Windows, it's most likely because you are not using Windows Subsytem for Linux. -If you get a `failed writing body` error in Windows, it's most likely because you don't have Windows Distribution system. - -You can fix this by going to Microsoft Store, download Ubuntu, and have it running. #### Step 2: Update Path - The installer will prompt you to run a `source` command. Either run this command, or reload your terminal. #### Step 3: Install Aderyn using Cyfrinup - After installing Cyfrinup, you can use it to install Aderyn. Run the following command in your terminal: - -```sh -cyfrinup -``` - -#### Step 4: Verify installation - -```sh -aderyn --version -``` - -#### Future Updates - -To update Aderyn to the latest version, you can run the cyfrinup: ```sh cyfrinup ``` +Verify the installation by running `aderyn --version` -Cyfrinup will replace the existing version with the latest one. +##### Upgrade older versions by (re)running: `cyfrinup` +---------- ### Using Homebrew - -``` +```sh brew install cyfrin/tap/aderyn ``` +##### Upgrade older versions by running: `brew upgrade cyfrin/tap/aderyn` +---------- ### Using npm - -``` +```sh npm install @cyfrin/aderyn -g ``` +##### Upgrade older versions by (re)running: `npm install @cyfrin/aderyn -g` + +----------- If you are installing with Homebrew or npm, ensure that the correct version of Aderyn in your path comes from either the Homebrew or npm global packages directory. If an older version exists at `~/.cyfrin/bin/aderyn`, remove it using `rm -f ~/.cyfrin/bin/aderyn`, as this is no longer the default installation location. + ## Quick Start Once Aderyn is installed on your system, you can run it against your Foundry-based codebase to find vulnerabilities in your code. diff --git a/aderyn/Cargo.toml b/aderyn/Cargo.toml index 4c038f7f7..e2be24de7 100644 --- a/aderyn/Cargo.toml +++ b/aderyn/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aderyn" -version = "0.4.2" +version = "0.4.3" edition = "2021" authors = ["Cyfrin "] description = "Rust based Solidity AST analyzer" @@ -12,7 +12,7 @@ homepage = "https://github.com/cyfrin/aderyn" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -aderyn_driver = { path = "../aderyn_driver", version = "0.4.2" } +aderyn_driver = { path = "../aderyn_driver", version = "0.4.3" } clap = { version = "4.4.6", features = ["derive"] } reqwest = { version = "0.12.2", default-features = false, features = ["blocking", "json", "rustls-tls"] } semver = "1.0.22" diff --git a/aderyn/src/lib.rs b/aderyn/src/lib.rs index f69534b7e..e6dea7e15 100644 --- a/aderyn/src/lib.rs +++ b/aderyn/src/lib.rs @@ -11,7 +11,7 @@ pub fn create_aderyn_toml_file_at(directory: String) { let aderyn_toml_path = PathBuf::from_str(&directory).unwrap().join("aderyn.toml"); let mut file = File::create_new(aderyn_toml_path.clone()).expect("File already exists!"); file.write_all(include_bytes!("../templates/aderyn.toml")) - .expect("To write contents into aderyn.toml"); + .expect("unable to write to aderyn.toml"); println!("Created aderyn.toml at {}", aderyn_toml_path.display()); } @@ -98,7 +98,7 @@ pub fn aderyn_is_currently_running_newest_version() -> Option { let data = latest_version_checker.json::().ok()?; let version_string = data.get("tag_name")?.as_str()?; - let newest = Version::parse(version_string.replace('v', "").as_str()).ok()?; + let newest = Version::parse(version_string.replace("aderyn-v", "").as_str()).ok()?; let current = Version::parse(env!("CARGO_PKG_VERSION")).expect("Pkg version not available"); Some(current >= newest) @@ -108,7 +108,6 @@ pub fn aderyn_is_currently_running_newest_version() -> Option { mod latest_version_checker_tests { use super::*; - #[ignore = "TODO later in the interest of time"] #[test] fn can_get_latest_version_from_crate_registry() { assert!(aderyn_is_currently_running_newest_version().is_some()) diff --git a/aderyn/src/main.rs b/aderyn/src/main.rs index 7a588f764..8e7163a56 100644 --- a/aderyn/src/main.rs +++ b/aderyn/src/main.rs @@ -166,7 +166,8 @@ fn main() { if let Some(yes) = aderyn_is_currently_running_newest_version() { if !yes { println!(); - println!("NEW VERSION OF ADERYN AVAILABLE! Please run `cyfrinup` to upgrade."); + println!("NEW VERSION OF ADERYN AVAILABLE! Please upgrade aderyn by following the instruction here - https://github.com/cyfrin/aderyn"); + println!("NOTE: You can skip this check by passing --skip-update-check flag"); } } } diff --git a/aderyn/templates/aderyn.toml b/aderyn/templates/aderyn.toml index b127482cc..a16394cb0 100644 --- a/aderyn/templates/aderyn.toml +++ b/aderyn/templates/aderyn.toml @@ -1,34 +1,42 @@ # Aderyn Configuration File -# This is a sample configuration for Aderyn +# Help Aderyn work with more granular control -# The root directory of smart contracts -# root = "." +# DO NOT CHANGE version below. As of now, only 1 is supported +version = 1 -# By default, aderyn will try to extract the following values based on the framework that is being used. -# However, if you want to be explicit consider mentioning them. +# Read the description carefully and uncomment the examples in each paragraph should you consider using them. -# The source directory containing the Solidity contracts. -# This is often "contracts/" or "src/" +# Base path for resolving remappings and compiling smart contracts, relative to workspace-root (directory in which the editor is open) +# Most of the time, you want to point it to the directory containing foundry.toml or hardhat.config.js/ts. +root = "." + +# Path of source directory containing the contracts, relative to root (above) +# Aderyn traverse all the nested files inside scanning for vulnerabilities +# If not specified, Aderyn will try to extract it from the framework that is being used. (Foundry / Hardhat) +# That would be "contracts/" in case of Hardhat and in case of Foundry, it depends on foundry.toml and +# many other factors like FOUNDRY_PROFILE environment variable used when starting VS Code, etc. +# Please feel free to always specify the values explicitly. +# Example: # src = "src/" -# Contract files to include in the analysis. -# This is a list of strings representing the file paths of the contracts to include. +# Path segments of contract files to include in the analysis. # It can be a partial match like "/interfaces/", which will include all files with "/interfaces/" in the file path. -# Or it can be a full match like "Counter.sol", which will include only the file with the exact file. +# Or it can be a full match like "src/counters/Counter.sol", which will include only the file with the exact path. # If not specified, all contract files in the source directory will be included. # Example: -# include = ["Counter.sol"] -# include = [] +# include = ["src/counters/Counter.sol", "src/others/"] +# include = ["/interfaces/"] -# Contract files to exclude from the analysis. -# This is a list of strings representing the file paths of the contracts to exclude. +# Path segments of contract files to exclude in the analysis. # It can be a partial match like "/interfaces/", which will exclude all files with "/interfaces/" in the file path. -# Or it can be a full match like "Counter.sol", which will exclude only the file with the exact file. +# Or it can be a full match like "src/counters/Counter.sol", which will exclude only the file with the exact path. # If not specified, no contract files will be excluded. # Example: +# exclude = ["src/counters/Counter.sol", "src/others/"] # exclude = ["/interfaces/"] -# exclude = [] -## Remappings used for compiling the contracts. +# Remappings used for compiling the contracts. +# If not specified, Aderyn will try to derive the values from foundry.toml (if present.) +# That would be the result of calling `foundry remappings` # Example: # remappings = ["@oz/contracts=lib/openzeppelin-contracts/contracts"] diff --git a/aderyn_core/Cargo.toml b/aderyn_core/Cargo.toml index 5254277e0..ba5f4ef00 100644 --- a/aderyn_core/Cargo.toml +++ b/aderyn_core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aderyn_core" -version = "0.4.2" +version = "0.4.3" edition = "2021" authors = ["Cyfrin "] description = "Rust based Solidity AST analyzer backend" diff --git a/aderyn_driver/Cargo.toml b/aderyn_driver/Cargo.toml index fc4829a8e..a5c17a4bf 100644 --- a/aderyn_driver/Cargo.toml +++ b/aderyn_driver/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aderyn_driver" -version = "0.4.2" +version = "0.4.3" edition = "2021" authors = ["Cyfrin "] description = "Rust based Solidity AST analyzer driver" @@ -9,7 +9,7 @@ license = "MIT" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -aderyn_core = { path = "../aderyn_core", version = "0.4.2" } +aderyn_core = { path = "../aderyn_core", version = "0.4.3" } rayon = "1.8.0" cyfrin-foundry-compilers = { version = "0.3.20-aderyn", features = ["svm-solc"] } serde_json = { version = "1.0.96", features = ["preserve_order"] } diff --git a/aderyn_driver/src/config_helpers.rs b/aderyn_driver/src/config_helpers.rs index 081b042e7..bd4de5aa8 100644 --- a/aderyn_driver/src/config_helpers.rs +++ b/aderyn_driver/src/config_helpers.rs @@ -9,6 +9,8 @@ use serde::Deserialize; /// aderyn.toml structure #[derive(Deserialize, Clone)] pub struct AderynConfig { + /// By default we'll assume it's version 1 + pub version: usize, pub root: Option, pub src: Option, pub exclude: Option>, @@ -27,6 +29,10 @@ fn load_aderyn_config(root: &Path) -> Result { let mut config: AderynConfig = toml::from_str(&content).map_err(|err| format!("Error parsing config file: {}", err))?; + if config.version != 1 { + return Err("aderyn.toml version not supported".to_owned()); + } + // Clear empty vectors clear_empty_vectors(&mut config.exclude); clear_empty_vectors(&mut config.remappings); @@ -217,6 +223,7 @@ mod tests { #[test] fn test_interpret_aderyn_config_correctly_appends_and_replaces() { let config = super::AderynConfig { + version: 1, root: Some("CONFIG_ROOT".to_string()), src: Some("CONFIG_SRC".to_string()), exclude: Some(vec!["CONFIG_EXCLUDE".to_string()]), diff --git a/aderyn_driver/src/driver.rs b/aderyn_driver/src/driver.rs index da79c75c6..594fa57eb 100644 --- a/aderyn_driver/src/driver.rs +++ b/aderyn_driver/src/driver.rs @@ -76,7 +76,7 @@ pub fn drive_and_get_results(args: Args) -> Arc>> { if let Ok(report) = get_report(&cx_wrapper.contexts, &root_rel_path, detectors) { let high_issues = report.high_issues(&file_contents); let low_issues = report.low_issues(&file_contents); - let lsp_result = LspReport::from(low_issues, high_issues, args); + let lsp_result = LspReport::from(low_issues, high_issues, &root_rel_path); return Arc::new(tokio::sync::Mutex::new(Some(lsp_result))); } diff --git a/aderyn_driver/src/lsp_report.rs b/aderyn_driver/src/lsp_report.rs index 1c3bf9e97..0074aebd8 100644 --- a/aderyn_driver/src/lsp_report.rs +++ b/aderyn_driver/src/lsp_report.rs @@ -1,10 +1,7 @@ -use std::{collections::BTreeMap, path::PathBuf}; - use aderyn_core::report::{HighIssues, IssueBody, IssueInstance, LowIssues}; +use std::{collections::BTreeMap, path::Path}; use tower_lsp::lsp_types::{Diagnostic, DiagnosticSeverity, Position, Range, Url}; -use crate::driver::Args; - /// Report structure that is tailored to aid LSP pub struct LspReport { pub high_issues: HighIssues, @@ -13,12 +10,12 @@ pub struct LspReport { } impl LspReport { - pub fn from(low_issues: LowIssues, high_issues: HighIssues, args: Args) -> Self { + pub fn from(low_issues: LowIssues, high_issues: HighIssues, root_rel_path: &Path) -> Self { fn create_diagnostic_from_issue( - args: &Args, issue_body: &IssueBody, instance: &IssueInstance, severity: DiagnosticSeverity, + root_rel_path: &Path, ) -> Option<(Url, Diagnostic)> { // Line number let line_no = instance.line_no.checked_sub(1)?; @@ -62,10 +59,9 @@ impl LspReport { tags: None, data: None, }; - let mut full_contract_path = PathBuf::from(args.root.clone()); + let mut full_contract_path = root_rel_path.to_path_buf(); full_contract_path.push(instance.contract_path.clone()); let full_contract_path = full_contract_path.canonicalize().ok()?; - let full_contract_path_string = full_contract_path.to_string_lossy().to_string(); let file_uri = Url::parse(&format!("file://{}", &full_contract_path_string)).ok()?; @@ -77,10 +73,10 @@ impl LspReport { for issue_body in &high_issues.issues { for instance in &issue_body.instances { let Some((file_url, diagnostic)) = create_diagnostic_from_issue( - &args, issue_body, instance, DiagnosticSeverity::WARNING, + root_rel_path, ) else { continue; }; @@ -94,10 +90,10 @@ impl LspReport { for issue_body in &low_issues.issues { for instance in &issue_body.instances { let Some((file_url, diagnostic)) = create_diagnostic_from_issue( - &args, issue_body, instance, DiagnosticSeverity::INFORMATION, + root_rel_path, ) else { continue; }; diff --git a/reports/report.sarif b/reports/report.sarif index d83e6b58d..4f33e51ff 100644 --- a/reports/report.sarif +++ b/reports/report.sarif @@ -11921,8 +11921,8 @@ "informationUri": "https://github.com/Cyfrin/aderyn", "name": "Aderyn", "organization": "Cyfrin", - "semanticVersion": "0.4.2", - "version": "0.4.2" + "semanticVersion": "0.4.3", + "version": "0.4.3" } } } diff --git a/tests/2024-05-Sablier b/tests/2024-05-Sablier index 309659836..18c6448cc 160000 --- a/tests/2024-05-Sablier +++ b/tests/2024-05-Sablier @@ -1 +1 @@ -Subproject commit 30965983638926b3e8a5d6b0b7d39d32a32e310f +Subproject commit 18c6448cc61d424c2fef7e060a8e7577267a97f5 diff --git a/tests/adhoc-sol-files/aderyn.toml b/tests/adhoc-sol-files/aderyn.toml index f29dce1a5..a62d87dad 100644 --- a/tests/adhoc-sol-files/aderyn.toml +++ b/tests/adhoc-sol-files/aderyn.toml @@ -1,3 +1,4 @@ +version = 1 # src = "" exclude = ["lib/"] # remappings = []