Skip to content

Commit

Permalink
merge dev
Browse files Browse the repository at this point in the history
  • Loading branch information
TilakMaddy committed Oct 4, 2024
2 parents c844824 + 8d5fdc3 commit e2114fa
Show file tree
Hide file tree
Showing 29 changed files with 186 additions and 242 deletions.
5 changes: 0 additions & 5 deletions .github/workflows/cargo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,6 @@ jobs:
run: |
git submodule update --init --recursive
- uses: Swatinem/rust-cache@v2
- name: Run cargo test
run: |
cargo test _by_loading_contract_directly
- uses: Swatinem/rust-cache@v2
- name: Run cargo test
run: |
Expand Down
20 changes: 11 additions & 9 deletions aderyn/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,21 +88,23 @@ fn right_pad(s: &str, by: usize) -> String {

pub static APP_USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"));

pub fn aderyn_is_currently_running_newest_version() -> Result<bool, reqwest::Error> {
pub fn aderyn_is_currently_running_newest_version() -> Option<bool> {
let client = reqwest::blocking::Client::builder()
.user_agent(APP_USER_AGENT)
.build()?;
.build()
.expect("client is unable to initialize");

let latest_version_checker = client
.get("https://api.github.com/repos/Cyfrin/aderyn/releases/latest")
.send()?;
.send()
.ok()?;

let data = latest_version_checker.json::<Value>()?;
let newest =
Version::parse(data["tag_name"].as_str().unwrap().replace('v', "").as_str()).unwrap();
let current = Version::parse(env!("CARGO_PKG_VERSION")).unwrap();
let data = latest_version_checker.json::<Value>().ok()?;
let version_string = data["tag_name"].as_str()?;
let newest = Version::parse(version_string.replace('v', "").as_str()).ok()?;
let current = Version::parse(env!("CARGO_PKG_VERSION")).expect("Pkg version not available");

Ok(current >= newest)
Some(current >= newest)
}

#[cfg(test)]
Expand All @@ -111,6 +113,6 @@ mod latest_version_checker_tests {

#[test]
fn can_get_latest_version_from_crate_registry() {
assert!(aderyn_is_currently_running_newest_version().is_ok())
assert!(aderyn_is_currently_running_newest_version().is_some())
}
}
2 changes: 1 addition & 1 deletion aderyn/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ fn main() {

// Check for updates
if !cmd_args.skip_update_check {
if let Ok(yes) = aderyn_is_currently_running_newest_version() {
if let Some(yes) = aderyn_is_currently_running_newest_version() {
if !yes {
println!();
println!("NEW VERSION OF ADERYN AVAILABLE! Please run `cyfrinup` to upgrade.");
Expand Down
62 changes: 35 additions & 27 deletions aderyn_core/src/detect/detector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub fn get_all_issue_detectors() -> Vec<Box<dyn IssueDetector>> {
Box::<UnspecificSolidityPragmaDetector>::default(),
Box::<ZeroAddressCheckDetector>::default(),
Box::<UselessPublicFunctionDetector>::default(),
Box::<ConstantsInsteadOfLiteralsDetector>::default(),
Box::<LiteralsInsteadOfConstantsDetector>::default(),
Box::<UnindexedEventsDetector>::default(),
Box::<RequireWithStringDetector>::default(),
Box::<NonReentrantBeforeOthersDetector>::default(),
Expand Down Expand Up @@ -124,8 +124,8 @@ pub(crate) enum IssueDetectorNamePool {
FunctionPointerInConstructor,
DeadCode,
FunctionSelectorCollision,
CacheArrayLength,
AssertStateChange,
ArrayLengthNotCached,
StateChangeInAssert,
CostlyOperationsInsideLoops,
ConstantFunctionChangingState,
BuiltinSymbolShadow,
Expand All @@ -134,18 +134,18 @@ pub(crate) enum IssueDetectorNamePool {
DelegateCallInLoop,
CentralizationRisk,
SolmateSafeTransferLib,
AvoidAbiEncodePacked,
Ecrecover,
HashCollisionDueToAbiEncodePacked,
SignatureMalleabilityDueToRawEcrecover,
DeprecatedOzFunctions,
UnsafeERC20Functions,
UnspecificSolidityPragma,
ZeroAddressCheck,
NoZeroAddressCheck,
UselessPublicFunction,
ConstantsInsteadOfLiterals,
UnindexedEvents,
RequireWithString,
NonReentrantBeforeOthers,
BlockTimestampDeadline,
RequireWithoutString,
NonReentrantIsNotBeforeOthers,
BlockTimestampIsWeakDeadline,
LiteralInsteadOfConstant,
UnsafeOzERC721Mint,
PushZeroOpcode,
ArbitraryTransferFrom,
Expand Down Expand Up @@ -175,8 +175,8 @@ pub(crate) enum IssueDetectorNamePool {
StateVariableShadowing,
UncheckedSend,
MisusedBoolean,
SendEtherNoChecks,
DelegateCallUncheckedAddress,
SendsEtherAwayWithoutCheckingAddress,
DelegateCallOnUncheckedAddress,
TautologicalCompare,
#[allow(clippy::upper_case_acronyms)]
RTLO,
Expand All @@ -192,7 +192,7 @@ pub(crate) enum IssueDetectorNamePool {
DeleteNestedMapping,
UnusedStateVariable,
ConstantFunctionsAssembly,
BooleanEquality,
RedundantBooleanEquality,
TxOriginUsedForAuth,
MsgValueInLoop,
ContractLocksEther,
Expand Down Expand Up @@ -231,15 +231,20 @@ pub fn request_issue_detector_by_name(detector_name: &str) -> Option<Box<dyn Iss
IssueDetectorNamePool::StateVariableCouldBeDeclaredConstant => {
Some(Box::<StateVariableCouldBeConstantDetector>::default())
}
IssueDetectorNamePool::LiteralInsteadOfConstant => {
Some(Box::<LiteralsInsteadOfConstantsDetector>::default())
}
IssueDetectorNamePool::FunctionPointerInConstructor => {
Some(Box::<FucntionPointerInConstructorDetector>::default())
}
IssueDetectorNamePool::DeadCode => Some(Box::<DeadCodeDetector>::default()),
IssueDetectorNamePool::FunctionSelectorCollision => {
Some(Box::<FunctionSelectorCollisionDetector>::default())
}
IssueDetectorNamePool::CacheArrayLength => Some(Box::<CacheArrayLengthDetector>::default()),
IssueDetectorNamePool::AssertStateChange => {
IssueDetectorNamePool::ArrayLengthNotCached => {
Some(Box::<CacheArrayLengthDetector>::default())
}
IssueDetectorNamePool::StateChangeInAssert => {
Some(Box::<AssertStateChangeDetector>::default())
}
IssueDetectorNamePool::CostlyOperationsInsideLoops => {
Expand Down Expand Up @@ -279,10 +284,12 @@ pub fn request_issue_detector_by_name(detector_name: &str) -> Option<Box<dyn Iss
IssueDetectorNamePool::SolmateSafeTransferLib => {
Some(Box::<SolmateSafeTransferLibDetector>::default())
}
IssueDetectorNamePool::AvoidAbiEncodePacked => {
IssueDetectorNamePool::HashCollisionDueToAbiEncodePacked => {
Some(Box::<AvoidAbiEncodePackedDetector>::default())
}
IssueDetectorNamePool::Ecrecover => Some(Box::<EcrecoverDetector>::default()),
IssueDetectorNamePool::SignatureMalleabilityDueToRawEcrecover => {
Some(Box::<EcrecoverDetector>::default())
}
IssueDetectorNamePool::DeprecatedOzFunctions => {
Some(Box::<DeprecatedOZFunctionsDetector>::default())
}
Expand All @@ -292,21 +299,20 @@ pub fn request_issue_detector_by_name(detector_name: &str) -> Option<Box<dyn Iss
IssueDetectorNamePool::UnspecificSolidityPragma => {
Some(Box::<UnspecificSolidityPragmaDetector>::default())
}
IssueDetectorNamePool::ZeroAddressCheck => Some(Box::<ZeroAddressCheckDetector>::default()),
IssueDetectorNamePool::NoZeroAddressCheck => {
Some(Box::<ZeroAddressCheckDetector>::default())
}
IssueDetectorNamePool::UselessPublicFunction => {
Some(Box::<UselessPublicFunctionDetector>::default())
}
IssueDetectorNamePool::ConstantsInsteadOfLiterals => {
Some(Box::<ConstantsInsteadOfLiteralsDetector>::default())
}
IssueDetectorNamePool::UnindexedEvents => Some(Box::<UnindexedEventsDetector>::default()),
IssueDetectorNamePool::RequireWithString => {
IssueDetectorNamePool::RequireWithoutString => {
Some(Box::<RequireWithStringDetector>::default())
}
IssueDetectorNamePool::NonReentrantBeforeOthers => {
IssueDetectorNamePool::NonReentrantIsNotBeforeOthers => {
Some(Box::<NonReentrantBeforeOthersDetector>::default())
}
IssueDetectorNamePool::BlockTimestampDeadline => {
IssueDetectorNamePool::BlockTimestampIsWeakDeadline => {
Some(Box::<BlockTimestampDeadlineDetector>::default())
}
IssueDetectorNamePool::UnsafeOzERC721Mint => {
Expand Down Expand Up @@ -383,10 +389,10 @@ pub fn request_issue_detector_by_name(detector_name: &str) -> Option<Box<dyn Iss
}
IssueDetectorNamePool::UncheckedSend => Some(Box::<UncheckedSendDetector>::default()),
IssueDetectorNamePool::MisusedBoolean => Some(Box::<MisusedBooleanDetector>::default()),
IssueDetectorNamePool::SendEtherNoChecks => {
IssueDetectorNamePool::SendsEtherAwayWithoutCheckingAddress => {
Some(Box::<SendEtherNoChecksDetector>::default())
}
IssueDetectorNamePool::DelegateCallUncheckedAddress => {
IssueDetectorNamePool::DelegateCallOnUncheckedAddress => {
Some(Box::<DelegateCallOnUncheckedAddressDetector>::default())
}
IssueDetectorNamePool::TautologicalCompare => {
Expand Down Expand Up @@ -422,7 +428,9 @@ pub fn request_issue_detector_by_name(detector_name: &str) -> Option<Box<dyn Iss
IssueDetectorNamePool::ConstantFunctionsAssembly => {
Some(Box::<ConstantFunctionContainsAssemblyDetector>::default())
}
IssueDetectorNamePool::BooleanEquality => Some(Box::<BooleanEqualityDetector>::default()),
IssueDetectorNamePool::RedundantBooleanEquality => {
Some(Box::<BooleanEqualityDetector>::default())
}
IssueDetectorNamePool::TxOriginUsedForAuth => {
Some(Box::<TxOriginUsedForAuthDetector>::default())
}
Expand Down
6 changes: 5 additions & 1 deletion aderyn_core/src/detect/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,16 @@ pub fn has_calls_that_sends_native_eth(ast_node: &ASTNode) -> bool {

// payable(address(..)).transfer(100)
// payable(address(..)).send(100)
// address.sendValue(..) (from openzeppelin)

let function_calls = ExtractFunctionCalls::from(ast_node).extracted;

for function_call in function_calls {
if let Expression::MemberAccess(member_access) = function_call.expression.as_ref() {
if member_access.member_name == "transfer" || member_access.member_name == "send" {
if member_access.member_name == "transfer"
|| member_access.member_name == "send"
|| member_access.member_name == "sendValue"
{
if let Some(type_description) = member_access.expression.type_descriptions() {
if type_description
.type_string
Expand Down
5 changes: 4 additions & 1 deletion aderyn_core/src/detect/high/avoid_abi_encode_packed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,10 @@ impl IssueDetector for AvoidAbiEncodePackedDetector {
}

fn name(&self) -> String {
format!("{}", IssueDetectorNamePool::AvoidAbiEncodePacked)
format!(
"{}",
IssueDetectorNamePool::HashCollisionDueToAbiEncodePacked
)
}
}

Expand Down
2 changes: 1 addition & 1 deletion aderyn_core/src/detect/high/block_timestamp_deadline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ impl IssueDetector for BlockTimestampDeadlineDetector {
}

fn name(&self) -> String {
format!("{}", IssueDetectorNamePool::BlockTimestampDeadline)
format!("{}", IssueDetectorNamePool::BlockTimestampIsWeakDeadline)
}
}

Expand Down
6 changes: 3 additions & 3 deletions aderyn_core/src/detect/high/delegate_call_no_address_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ impl IssueDetector for DelegateCallOnUncheckedAddressDetector {
}

fn title(&self) -> String {
String::from("Delegatecall made by the function without checks on any adress.")
String::from("Delegatecall made by the function without checks on any address.")
}

fn description(&self) -> String {
Expand All @@ -59,7 +59,7 @@ impl IssueDetector for DelegateCallOnUncheckedAddressDetector {
}

fn name(&self) -> String {
IssueDetectorNamePool::DelegateCallUncheckedAddress.to_string()
IssueDetectorNamePool::DelegateCallOnUncheckedAddress.to_string()
}
}

Expand Down Expand Up @@ -119,7 +119,7 @@ mod delegate_call_no_address_check_tests {
// assert the title is correct
assert_eq!(
detector.title(),
String::from("Delegatecall made by the function without checks on any adress.")
String::from("Delegatecall made by the function without checks on any address.")
);
// assert the description is correct
assert_eq!(
Expand Down
2 changes: 1 addition & 1 deletion aderyn_core/src/detect/high/send_ether_no_checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ impl IssueDetector for SendEtherNoChecksDetector {
}

fn name(&self) -> String {
IssueDetectorNamePool::SendEtherNoChecks.to_string()
IssueDetectorNamePool::SendsEtherAwayWithoutCheckingAddress.to_string()
}
}

Expand Down
2 changes: 1 addition & 1 deletion aderyn_core/src/detect/low/assert_state_change.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ impl IssueDetector for AssertStateChangeDetector {
}

fn name(&self) -> String {
format!("{}", IssueDetectorNamePool::AssertStateChange)
format!("{}", IssueDetectorNamePool::StateChangeInAssert)
}
}

Expand Down
2 changes: 1 addition & 1 deletion aderyn_core/src/detect/low/boolean_equality.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ issue_detector! {
severity: Low,
title: "Boolean equality is not required.",
desc: "If `x` is a boolean, there is no need to do `if(x == true)` or `if(x == false)`. Just use `if(x)` and `if(!x)` respectively.",
name: BooleanEquality,
name: RedundantBooleanEquality,

|context| {
for binary_operation in context.binary_operations() {
Expand Down
2 changes: 1 addition & 1 deletion aderyn_core/src/detect/low/cache_array_length.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ impl IssueDetector for CacheArrayLengthDetector {
}

fn name(&self) -> String {
format!("{}", IssueDetectorNamePool::CacheArrayLength)
format!("{}", IssueDetectorNamePool::ArrayLengthNotCached)
}
}

Expand Down
5 changes: 4 additions & 1 deletion aderyn_core/src/detect/low/ecrecover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ impl IssueDetector for EcrecoverDetector {
}

fn name(&self) -> String {
format!("{}", IssueDetectorNamePool::Ecrecover)
format!(
"{}",
IssueDetectorNamePool::SignatureMalleabilityDueToRawEcrecover
)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ use crate::{
use eyre::Result;

#[derive(Default)]
pub struct ConstantsInsteadOfLiteralsDetector {
pub struct LiteralsInsteadOfConstantsDetector {
// Keys are: [0] source file name, [1] line number, [2] character location of node.
// Do not add items manually, use `capture!` to add nodes to this BTreeMap.
found_instances: BTreeMap<(String, usize, String), NodeID>,
}

impl IssueDetector for ConstantsInsteadOfLiteralsDetector {
impl IssueDetector for LiteralsInsteadOfConstantsDetector {
fn detect(&mut self, context: &WorkspaceContext) -> Result<bool, Box<dyn Error>> {
// Get all contracts
// For each contract
Expand Down Expand Up @@ -128,26 +128,25 @@ impl IssueDetector for ConstantsInsteadOfLiteralsDetector {
}

fn name(&self) -> String {
format!("{}", IssueDetectorNamePool::ConstantsInsteadOfLiterals)
format!("{}", IssueDetectorNamePool::LiteralInsteadOfConstant)
}
}

#[cfg(test)]
mod constants_instead_of_literals_tests {
use serial_test::serial;

use super::LiteralsInsteadOfConstantsDetector;
use crate::detect::detector::IssueDetector;

use super::ConstantsInsteadOfLiteralsDetector;

#[test]
#[serial]
fn test_constants_instead_of_literals_by_loading_contract_directly() {
let context = crate::detect::test_utils::load_solidity_source_unit(
"../tests/contract-playground/src/ConstantsLiterals.sol",
);

let mut detector = ConstantsInsteadOfLiteralsDetector::default();
let mut detector = LiteralsInsteadOfConstantsDetector::default();
// assert that the detector finds the public Function
let found = detector.detect(&context).unwrap();
assert!(found);
Expand Down
Loading

0 comments on commit e2114fa

Please sign in to comment.