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

Low Detector: Solidity 0.8.23 introduces MCOPY opcode #738

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions aderyn_core/src/detect/detector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ pub fn get_all_issue_detectors() -> Vec<Box<dyn IssueDetector>> {
Box::<FucntionPointerInConstructorDetector>::default(),
Box::<StateVariableCouldBeConstantDetector>::default(),
Box::<StateVariableChangesWithoutEventDetector>::default(),
Box::<MCOPYOpcodeDetector>::default(),
]
}

Expand All @@ -112,6 +113,7 @@ pub fn get_all_detectors_names() -> Vec<String> {
#[derive(Debug, PartialEq, EnumString, Display)]
#[strum(serialize_all = "kebab-case")]
pub(crate) enum IssueDetectorNamePool {
MCOPYOpcode,
StateVariableChangesWithoutEvents,
MissingInheritance,
UnusedImport,
Expand Down Expand Up @@ -216,6 +218,7 @@ pub fn request_issue_detector_by_name(detector_name: &str) -> Option<Box<dyn Iss
IssueDetectorNamePool::LocalVariableShadowing => {
Some(Box::<LocalVariableShadowingDetector>::default())
}
IssueDetectorNamePool::MCOPYOpcode => Some(Box::<MCOPYOpcodeDetector>::default()),
IssueDetectorNamePool::UnusedImport => Some(Box::<UnusedImportDetector>::default()),
IssueDetectorNamePool::VoidConstructor => Some(Box::<VoidConstructorDetector>::default()),
IssueDetectorNamePool::StateVariableCouldBeDeclaredConstant => {
Expand Down
94 changes: 94 additions & 0 deletions aderyn_core/src/detect/low/mcopy_opcode.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
use std::{collections::BTreeMap, error::Error, str::FromStr};

use crate::{
ast::NodeID,
capture,
context::workspace_context::WorkspaceContext,
detect::{
detector::{IssueDetector, IssueDetectorNamePool, IssueSeverity},
helpers::pragma_directive_to_semver,
},
};
use eyre::Result;
use semver::{Version, VersionReq};

#[derive(Default)]
pub struct MCOPYOpcodeDetector {
// 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 MCOPYOpcodeDetector {
fn detect(&mut self, context: &WorkspaceContext) -> Result<bool, Box<dyn Error>> {
for pragma_directive in context.pragma_directives() {
let req = pragma_directive_to_semver(pragma_directive)?;
if version_req_allows_0_8_23_and_above(&req) {
capture!(self, context, pragma_directive);
}
}
Ok(!self.found_instances.is_empty())
}

fn severity(&self) -> IssueSeverity {
IssueSeverity::Low
}

fn title(&self) -> String {
String::from("PUSH0 is not supported by all chains")
}

fn description(&self) -> String {
String::from("MCOPY opcode is introduced in Solidity 0.8.23 so it's very likely that not all chains support it yet. Consider using using older version of solidity.")
}

fn instances(&self) -> BTreeMap<(String, usize, String), NodeID> {
self.found_instances.clone()
}

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

fn version_req_allows_0_8_23_and_above(version_req: &VersionReq) -> bool {
// If it matches any above 0.8.23 return true
// TODO: Every time a solidity version is released, please increment the below counter by 1
let current_highest_version = 27;
for i in 23..=current_highest_version {
let version = Version::from_str(&format!("0.8.{}", i)).unwrap();
if version_req.matches(&version) {
return true;
}
}

// Else, return false
false
}

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

use crate::detect::detector::IssueDetector;

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

let mut detector = super::MCOPYOpcodeDetector::default();
let found = detector.detect(&context).unwrap();
// assert that it found something
assert!(found);
// assert that the number of instances is correct
assert_eq!(detector.instances().len(), 1);
// assert that the severity is low
assert_eq!(
detector.severity(),
crate::detect::detector::IssueSeverity::Low
);
}
}
2 changes: 2 additions & 0 deletions aderyn_core/src/detect/low/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub(crate) mod function_pointer_in_constructor;
pub(crate) mod inconsistent_type_names;
pub(crate) mod large_literal_value;
pub(crate) mod local_variable_shadowing;
pub(crate) mod mcopy_opcode;
pub(crate) mod missing_inheritance;
pub(crate) mod non_reentrant_before_others;
pub(crate) mod public_variable_read_in_external_context;
Expand Down Expand Up @@ -61,6 +62,7 @@ pub use function_pointer_in_constructor::FucntionPointerInConstructorDetector;
pub use inconsistent_type_names::InconsistentTypeNamesDetector;
pub use large_literal_value::LargeLiteralValueDetector;
pub use local_variable_shadowing::LocalVariableShadowingDetector;
pub use mcopy_opcode::MCOPYOpcodeDetector;
pub use missing_inheritance::MissingInheritanceDetector;
pub use non_reentrant_before_others::NonReentrantBeforeOthersDetector;
pub use public_variable_read_in_external_context::PublicVariableReadInExternalContextDetector;
Expand Down
62 changes: 61 additions & 1 deletion reports/adhoc-sol-files-report.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ This report was generated by [Aderyn](https://github.com/Cyfrin/aderyn), a stati
- [L-19: Unused Imports](#l-19-unused-imports)
- [L-20: State variable could be declared constant](#l-20-state-variable-could-be-declared-constant)
- [L-21: State variable changes but no event is emitted.](#l-21-state-variable-changes-but-no-event-is-emitted)
- [L-22: PUSH0 is not supported by all chains](#l-22-push0-is-not-supported-by-all-chains)


# Summary
Expand Down Expand Up @@ -78,7 +79,7 @@ This report was generated by [Aderyn](https://github.com/Cyfrin/aderyn), a stati
| Category | No. of Issues |
| --- | --- |
| High | 4 |
| Low | 21 |
| Low | 22 |


# High Issues
Expand Down Expand Up @@ -936,3 +937,62 @@ State variable changes in this function but no event is emitted.



## L-22: PUSH0 is not supported by all chains

MCOPY opcode is introduced in Solidity 0.8.23 so it's very likely that not all chains support it yet. Consider using using older version of solidity.

<details><summary>8 Found Instances</summary>


- Found in Counter.sol [Line: 2](../tests/adhoc-sol-files/Counter.sol#L2)

```solidity
pragma solidity ^0.8.13;
```

- Found in DemoASTNodes.sol [Line: 2](../tests/adhoc-sol-files/DemoASTNodes.sol#L2)

```solidity
pragma solidity >=0.8.0;
```

- Found in Helper.sol [Line: 2](../tests/adhoc-sol-files/Helper.sol#L2)

```solidity
pragma solidity >=0.8.0;
```

- Found in InconsistentUints.sol [Line: 1](../tests/adhoc-sol-files/InconsistentUints.sol#L1)

```solidity
pragma solidity ^0.8.24;
```

- Found in inheritance/IContractInheritance.sol [Line: 2](../tests/adhoc-sol-files/inheritance/IContractInheritance.sol#L2)

```solidity
pragma solidity >=0.8.0;
```

- Found in inheritance/InheritanceBase.sol [Line: 2](../tests/adhoc-sol-files/inheritance/InheritanceBase.sol#L2)

```solidity
pragma solidity ^0.8.0;
```

- Found in multiple-versions/0.8/A.sol [Line: 2](../tests/adhoc-sol-files/multiple-versions/0.8/A.sol#L2)

```solidity
pragma solidity ^0.8.0;
```

- Found in multiple-versions/0.8/B.sol [Line: 2](../tests/adhoc-sol-files/multiple-versions/0.8/B.sol#L2)

```solidity
pragma solidity ^0.8.0;
```

</details>



Loading
Loading