aderyn_core/detect/low/
require_with_string.rs1use std::{collections::BTreeMap, error::Error};
2
3use crate::{
4 ast::NodeID,
5 capture,
6 context::workspace_context::WorkspaceContext,
7 detect::detector::{IssueDetector, IssueDetectorNamePool, IssueSeverity},
8};
9use eyre::Result;
10
11#[derive(Default)]
12pub struct RequireWithStringDetector {
13 found_instances: BTreeMap<(String, usize, String), NodeID>,
16}
17
18impl IssueDetector for RequireWithStringDetector {
19 fn detect(&mut self, context: &WorkspaceContext) -> Result<bool, Box<dyn Error>> {
20 let requires_and_reverts = context
22 .identifiers()
23 .into_iter()
24 .filter(|&id| id.name == "revert" || id.name == "require");
25
26 for id in requires_and_reverts {
27 if (id.name == "revert" && id.argument_types.as_ref().unwrap().is_empty())
28 || (id.name == "require" && id.argument_types.as_ref().unwrap().len() == 1)
29 {
30 capture!(self, context, id);
31 }
32 }
33
34 Ok(!self.found_instances.is_empty())
35 }
36
37 fn title(&self) -> String {
38 String::from("Empty `require()` / `revert()` statements")
39 }
40
41 fn description(&self) -> String {
42 String::from("Use descriptive reason strings or custom errors for revert paths.")
43 }
44
45 fn severity(&self) -> IssueSeverity {
46 IssueSeverity::Low
47 }
48
49 fn instances(&self) -> BTreeMap<(String, usize, String), NodeID> {
50 self.found_instances.clone()
51 }
52
53 fn name(&self) -> String {
54 format!("{}", IssueDetectorNamePool::RequireWithString)
55 }
56}
57
58#[cfg(test)]
59mod require_with_string_tests {
60 use serial_test::serial;
61
62 use crate::detect::detector::IssueDetector;
63
64 use super::RequireWithStringDetector;
65
66 #[test]
67 #[serial]
68 fn test_require_with_string_by_loading_contract_directly() {
69 let context = crate::detect::test_utils::load_solidity_source_unit(
70 "../tests/contract-playground/src/DeprecatedOZFunctions.sol",
71 );
72
73 let mut detector = RequireWithStringDetector::default();
74 let found = detector.detect(&context).unwrap();
76 assert!(found);
77 assert_eq!(detector.instances().len(), 2);
79 assert_eq!(
81 detector.severity(),
82 crate::detect::detector::IssueSeverity::Low
83 );
84 assert_eq!(
86 detector.title(),
87 String::from("Empty `require()` / `revert()` statements")
88 );
89 assert_eq!(
91 detector.description(),
92 String::from("Use descriptive reason strings or custom errors for revert paths.")
93 );
94 }
95}