#
tokens: 49824/50000 45/1140 files (page 5/103)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 5 of 103. Use http://codebase.md/cyfrin/aderyn?lines=true&page={x} to view the full context.

# Directory Structure

```
├── .cargo
│   └── config.toml
├── .git-blame-ignore-revs
├── .gitattributes
├── .github
│   ├── images
│   │   ├── aderyn_logo.png
│   │   ├── poweredbycyfrinblack.png
│   │   └── poweredbycyfrinblue.png
│   ├── ISSUE_TEMPLATE
│   │   ├── bug_report.md
│   │   ├── false_positive_issue.md
│   │   └── feature_request.md
│   └── workflows
│       ├── cargo.yml
│       ├── dependencies.yml
│       ├── release.yml
│       ├── reports.yml
│       └── toml.yml
├── .gitignore
├── .gitmodules
├── .vscode
│   └── settings.json
├── aderyn
│   ├── Cargo.toml
│   ├── oranda.json
│   ├── README.md
│   ├── src
│   │   ├── birdsong.rs
│   │   ├── completions.rs
│   │   ├── lib.rs
│   │   ├── lsp.rs
│   │   ├── main.rs
│   │   ├── mcp.rs
│   │   └── panic.rs
│   └── templates
│       └── aderyn.toml
├── aderyn_core
│   ├── .gitignore
│   ├── Cargo.toml
│   ├── README.md
│   ├── src
│   │   ├── ast
│   │   │   ├── ast_nodes.rs
│   │   │   ├── ast.rs
│   │   │   ├── impls
│   │   │   │   ├── ctx
│   │   │   │   │   ├── utils.rs
│   │   │   │   │   └── workspace.rs
│   │   │   │   ├── ctx.rs
│   │   │   │   ├── disp
│   │   │   │   │   ├── blocks.rs
│   │   │   │   │   ├── contracts.rs
│   │   │   │   │   ├── enumerations.rs
│   │   │   │   │   ├── errors.rs
│   │   │   │   │   ├── events.rs
│   │   │   │   │   ├── expressions.rs
│   │   │   │   │   ├── functions.rs
│   │   │   │   │   ├── identifiers.rs
│   │   │   │   │   ├── literals.rs
│   │   │   │   │   ├── modifiers.rs
│   │   │   │   │   ├── statements.rs
│   │   │   │   │   ├── structures.rs
│   │   │   │   │   ├── types.rs
│   │   │   │   │   ├── user_defined_value_types.rs
│   │   │   │   │   ├── using_for_directives.rs
│   │   │   │   │   └── variables.rs
│   │   │   │   ├── disp.rs
│   │   │   │   ├── node
│   │   │   │   │   ├── blocks.rs
│   │   │   │   │   ├── contracts.rs
│   │   │   │   │   ├── documentation.rs
│   │   │   │   │   ├── enumerations.rs
│   │   │   │   │   ├── errors.rs
│   │   │   │   │   ├── events.rs
│   │   │   │   │   ├── expressions.rs
│   │   │   │   │   ├── functions.rs
│   │   │   │   │   ├── identifiers.rs
│   │   │   │   │   ├── import_directives.rs
│   │   │   │   │   ├── literals.rs
│   │   │   │   │   ├── modifiers.rs
│   │   │   │   │   ├── pragma_directives.rs
│   │   │   │   │   ├── source_units.rs
│   │   │   │   │   ├── statements.rs
│   │   │   │   │   ├── structures.rs
│   │   │   │   │   ├── types.rs
│   │   │   │   │   ├── user_defined_value_types.rs
│   │   │   │   │   ├── using_for_directives.rs
│   │   │   │   │   └── variables.rs
│   │   │   │   ├── node.rs
│   │   │   │   ├── own
│   │   │   │   │   ├── hashing.rs
│   │   │   │   │   ├── node_id.rs
│   │   │   │   │   ├── source_units.rs
│   │   │   │   │   └── utils.rs
│   │   │   │   └── own.rs
│   │   │   ├── impls.rs
│   │   │   ├── macros.rs
│   │   │   ├── magic.rs
│   │   │   ├── node_type.rs
│   │   │   └── yul.rs
│   │   ├── ast.rs
│   │   ├── audit
│   │   │   ├── attack_surface.rs
│   │   │   ├── auditor.rs
│   │   │   ├── entrypoint.rs
│   │   │   └── public_functions_no_sender.rs
│   │   ├── audit.rs
│   │   ├── context
│   │   │   ├── browser
│   │   │   │   ├── ancestral_line.rs
│   │   │   │   ├── closest_ancestor.rs
│   │   │   │   ├── external_calls.rs
│   │   │   │   ├── extractor.rs
│   │   │   │   ├── immediate_children.rs
│   │   │   │   ├── location.rs
│   │   │   │   ├── macros.rs
│   │   │   │   ├── parent.rs
│   │   │   │   ├── peek_over.rs
│   │   │   │   ├── peek_under.rs
│   │   │   │   ├── peek.rs
│   │   │   │   ├── siblings.rs
│   │   │   │   ├── sort_nodes.rs
│   │   │   │   └── storage_vars.rs
│   │   │   ├── browser.rs
│   │   │   ├── capturable.rs
│   │   │   ├── flow
│   │   │   │   ├── display.rs
│   │   │   │   ├── error.rs
│   │   │   │   ├── kind.rs
│   │   │   │   ├── primitives.rs
│   │   │   │   ├── reducibles.rs
│   │   │   │   ├── tests.rs
│   │   │   │   ├── utils.rs
│   │   │   │   ├── visualizer.rs
│   │   │   │   └── voids.rs
│   │   │   ├── flow.rs
│   │   │   ├── graph
│   │   │   │   ├── callgraph
│   │   │   │   │   ├── legacy.rs
│   │   │   │   │   ├── new.rs
│   │   │   │   │   ├── tests.rs
│   │   │   │   │   ├── utils.rs
│   │   │   │   │   └── visit.rs
│   │   │   │   ├── callgraph.rs
│   │   │   │   ├── preprocess
│   │   │   │   │   ├── legacy.rs
│   │   │   │   │   └── new.rs
│   │   │   │   ├── preprocess.rs
│   │   │   │   ├── traits.rs
│   │   │   │   └── utils.rs
│   │   │   ├── graph.rs
│   │   │   ├── macros.rs
│   │   │   ├── mcp
│   │   │   │   ├── callgraph
│   │   │   │   │   ├── render.rs
│   │   │   │   │   ├── tool.rs
│   │   │   │   │   └── utils.rs
│   │   │   │   ├── callgraph.rs
│   │   │   │   ├── contract_surface
│   │   │   │   │   ├── render.rs
│   │   │   │   │   ├── tool.rs
│   │   │   │   │   └── util.rs
│   │   │   │   ├── contract_surface.rs
│   │   │   │   ├── list_contracts
│   │   │   │   │   ├── render.rs
│   │   │   │   │   └── tool.rs
│   │   │   │   ├── list_contracts.rs
│   │   │   │   ├── node_finder
│   │   │   │   │   ├── render.rs
│   │   │   │   │   ├── tool.rs
│   │   │   │   │   └── utils.rs
│   │   │   │   ├── node_finder.rs
│   │   │   │   ├── node_summarizer
│   │   │   │   │   ├── render.rs
│   │   │   │   │   ├── tool.rs
│   │   │   │   │   └── utils.rs
│   │   │   │   ├── node_summarizer.rs
│   │   │   │   ├── project_overview
│   │   │   │   │   ├── render.rs
│   │   │   │   │   └── tool.rs
│   │   │   │   ├── project_overview.rs
│   │   │   │   ├── tool_guide
│   │   │   │   │   └── tool.rs
│   │   │   │   └── tool_guide.rs
│   │   │   ├── mcp.rs
│   │   │   ├── router
│   │   │   │   ├── external_calls.rs
│   │   │   │   ├── internal_calls.rs
│   │   │   │   ├── modifier_calls.rs
│   │   │   │   └── tests.rs
│   │   │   ├── router.rs
│   │   │   └── workspace.rs
│   │   ├── context.rs
│   │   ├── detect
│   │   │   ├── detector.rs
│   │   │   ├── entrypoint.rs
│   │   │   ├── helpers.rs
│   │   │   ├── high
│   │   │   │   ├── _template.rs
│   │   │   │   ├── abi_encode_packed_hash_collision.rs
│   │   │   │   ├── arbitrary_transfer_from.rs
│   │   │   │   ├── const_func_changes_state.rs
│   │   │   │   ├── contract_locks_ether.rs
│   │   │   │   ├── dangerous_unary_operator.rs
│   │   │   │   ├── delegate_call_unchecked_address.rs
│   │   │   │   ├── delete_nested_mapping.rs
│   │   │   │   ├── dynamic_array_length_assignment.rs
│   │   │   │   ├── enumerable_loop_removal.rs
│   │   │   │   ├── eth_send_unchecked_address.rs
│   │   │   │   ├── experimental_encoder.rs
│   │   │   │   ├── function_selector_collision.rs
│   │   │   │   ├── incorrect_caret_operator.rs
│   │   │   │   ├── incorrect_erc20_interface.rs
│   │   │   │   ├── incorrect_erc721_interface.rs
│   │   │   │   ├── incorrect_shift_order.rs
│   │   │   │   ├── misused_boolean.rs
│   │   │   │   ├── msg_value_in_loops.rs
│   │   │   │   ├── multiple_constructors.rs
│   │   │   │   ├── nested_struct_in_mapping.rs
│   │   │   │   ├── out_of_order_retryable.rs
│   │   │   │   ├── pre_declared_variable_usage.rs
│   │   │   │   ├── reentrancy_state_change.rs
│   │   │   │   ├── reused_contract_name.rs
│   │   │   │   ├── rtlo.rs
│   │   │   │   ├── selfdestruct.rs
│   │   │   │   ├── signed_integer_storage_array.rs
│   │   │   │   ├── state_variable_shadowing.rs
│   │   │   │   ├── storage_array_memory_edit.rs
│   │   │   │   ├── strict_equality_contract_balance.rs
│   │   │   │   ├── tautological_compare.rs
│   │   │   │   ├── tautology_or_contradiction.rs
│   │   │   │   ├── tx_origin_used_for_auth.rs
│   │   │   │   ├── unchecked_low_level_call.rs
│   │   │   │   ├── unchecked_send.rs
│   │   │   │   ├── unprotected_initializer.rs
│   │   │   │   ├── unsafe_casting.rs
│   │   │   │   ├── weak_randomness.rs
│   │   │   │   └── yul_return.rs
│   │   │   ├── high.rs
│   │   │   ├── low
│   │   │   │   ├── _template.rs
│   │   │   │   ├── assert_state_change.rs
│   │   │   │   ├── block_timestamp_deadline.rs
│   │   │   │   ├── boolean_equality.rs
│   │   │   │   ├── builtin_symbol_shadowing.rs
│   │   │   │   ├── centralization_risk.rs
│   │   │   │   ├── constant_function_contains_assembly.rs
│   │   │   │   ├── costly_loop.rs
│   │   │   │   ├── dead_code.rs
│   │   │   │   ├── delegatecall_in_loop.rs
│   │   │   │   ├── deprecated_oz_function.rs
│   │   │   │   ├── division_before_multiplication.rs
│   │   │   │   ├── ecrecover.rs
│   │   │   │   ├── empty_block.rs
│   │   │   │   ├── empty_require_revert.rs
│   │   │   │   ├── function_initializing_state.rs
│   │   │   │   ├── function_pointer_in_constructor.rs
│   │   │   │   ├── inconsistent_type_names.rs
│   │   │   │   ├── incorrect_modifier.rs
│   │   │   │   ├── internal_function_used_once.rs
│   │   │   │   ├── large_numeric_literal.rs
│   │   │   │   ├── literal_instead_of_constant.rs
│   │   │   │   ├── local_variable_shadowing.rs
│   │   │   │   ├── missing_inheritance.rs
│   │   │   │   ├── modifier_used_only_once.rs
│   │   │   │   ├── multiple_placeholders.rs
│   │   │   │   ├── non_reentrant_not_first.rs
│   │   │   │   ├── push_0_opcode.rs
│   │   │   │   ├── redundant_statement.rs
│   │   │   │   ├── require_revert_in_loop.rs
│   │   │   │   ├── return_bomb.rs
│   │   │   │   ├── solmate_safe_transfer_lib.rs
│   │   │   │   ├── state_change_without_event.rs
│   │   │   │   ├── state_no_address_check.rs
│   │   │   │   ├── state_variable_could_be_constant.rs
│   │   │   │   ├── state_variable_could_be_immutable.rs
│   │   │   │   ├── state_variable_read_external.rs
│   │   │   │   ├── storage_array_length_not_cached.rs
│   │   │   │   ├── todo.rs
│   │   │   │   ├── unchecked_return.rs
│   │   │   │   ├── uninitialized_local_variable.rs
│   │   │   │   ├── unsafe_erc20_operation.rs
│   │   │   │   ├── unsafe_oz_erc721_mint.rs
│   │   │   │   ├── unspecific_solidity_pragma.rs
│   │   │   │   ├── unused_error.rs
│   │   │   │   ├── unused_import.rs
│   │   │   │   ├── unused_public_function.rs
│   │   │   │   ├── unused_state_variable.rs
│   │   │   │   └── void_constructor.rs
│   │   │   ├── low.rs
│   │   │   └── test_utils.rs
│   │   ├── detect.rs
│   │   ├── lib.rs
│   │   ├── stats
│   │   │   ├── cloc.rs
│   │   │   ├── dbg_tips.txt
│   │   │   ├── ignore.rs
│   │   │   ├── token.rs
│   │   │   └── util.rs
│   │   ├── stats.rs
│   │   ├── test_utils
│   │   │   └── load_source_unit.rs
│   │   ├── test_utils.rs
│   │   ├── visitor
│   │   │   ├── ast_visitor.rs
│   │   │   ├── macros.rs
│   │   │   └── workspace_visitor.rs
│   │   └── visitor.rs
│   ├── templates
│   │   └── mcp-tool-response
│   │       ├── callgraph.md
│   │       ├── contract_surface.md
│   │       ├── list_contracts.md
│   │       ├── node_finder_get_all.md
│   │       ├── node_finder_grep.md
│   │       ├── node_finder_search.md
│   │       ├── node_summarizer.md
│   │       ├── project_overview.md
│   │       └── tool_guide.md
│   └── tests
│       ├── common
│       │   ├── ancestral_line.rs
│       │   ├── closest_ancestor.rs
│       │   ├── immediate_children.rs
│       │   ├── immediate_parent.rs
│       │   ├── mod.rs
│       │   ├── new_ast_nodes.rs
│       │   ├── peek_over.rs
│       │   └── sibling.rs
│       └── traversal.rs
├── aderyn_driver
│   ├── .gitignore
│   ├── benches
│   │   └── detectors.rs
│   ├── Cargo.toml
│   ├── README.md
│   ├── src
│   │   ├── compile.rs
│   │   ├── config.rs
│   │   ├── display.rs
│   │   ├── driver.rs
│   │   ├── interface
│   │   │   ├── json.rs
│   │   │   ├── lsp.rs
│   │   │   ├── markdown.rs
│   │   │   ├── mod.rs
│   │   │   ├── sarif.rs
│   │   │   ├── tables.rs
│   │   │   └── util.rs
│   │   ├── lib.rs
│   │   ├── mcp.rs
│   │   ├── process.rs
│   │   └── runner.rs
│   └── tests
│       └── astgen.rs
├── bacon.toml
├── benchmarks
│   ├── aderyn
│   │   ├── base
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   ├── change
│   │   │   └── estimates.json
│   │   ├── new
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   └── report
│   │       ├── both
│   │       │   ├── iteration_times.svg
│   │       │   └── pdf.svg
│   │       ├── change
│   │       │   ├── mean.svg
│   │       │   ├── median.svg
│   │       │   └── t-test.svg
│   │       ├── index.html
│   │       ├── iteration_times_small.svg
│   │       ├── iteration_times.svg
│   │       ├── MAD.svg
│   │       ├── mean.svg
│   │       ├── median.svg
│   │       ├── pdf_small.svg
│   │       ├── pdf.svg
│   │       ├── relative_iteration_times_small.svg
│   │       ├── relative_pdf_small.svg
│   │       ├── SD.svg
│   │       └── typical.svg
│   ├── arbitrary-transfer-from
│   │   ├── base
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   ├── change
│   │   │   └── estimates.json
│   │   ├── new
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   └── report
│   │       ├── both
│   │       │   ├── pdf.svg
│   │       │   └── regression.svg
│   │       ├── change
│   │       │   ├── mean.svg
│   │       │   ├── median.svg
│   │       │   └── t-test.svg
│   │       ├── index.html
│   │       ├── MAD.svg
│   │       ├── mean.svg
│   │       ├── median.svg
│   │       ├── pdf_small.svg
│   │       ├── pdf.svg
│   │       ├── regression_small.svg
│   │       ├── regression.svg
│   │       ├── relative_pdf_small.svg
│   │       ├── relative_regression_small.svg
│   │       ├── SD.svg
│   │       ├── slope.svg
│   │       └── typical.svg
│   ├── avoid-abi-encode-packed
│   │   ├── base
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   ├── change
│   │   │   └── estimates.json
│   │   ├── new
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   └── report
│   │       ├── both
│   │       │   ├── pdf.svg
│   │       │   └── regression.svg
│   │       ├── change
│   │       │   ├── mean.svg
│   │       │   ├── median.svg
│   │       │   └── t-test.svg
│   │       ├── index.html
│   │       ├── MAD.svg
│   │       ├── mean.svg
│   │       ├── median.svg
│   │       ├── pdf_small.svg
│   │       ├── pdf.svg
│   │       ├── regression_small.svg
│   │       ├── regression.svg
│   │       ├── relative_pdf_small.svg
│   │       ├── relative_regression_small.svg
│   │       ├── SD.svg
│   │       ├── slope.svg
│   │       └── typical.svg
│   ├── block-timestamp-deadline
│   │   ├── base
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   ├── change
│   │   │   └── estimates.json
│   │   ├── new
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   └── report
│   │       ├── both
│   │       │   ├── pdf.svg
│   │       │   └── regression.svg
│   │       ├── change
│   │       │   ├── mean.svg
│   │       │   ├── median.svg
│   │       │   └── t-test.svg
│   │       ├── index.html
│   │       ├── MAD.svg
│   │       ├── mean.svg
│   │       ├── median.svg
│   │       ├── pdf_small.svg
│   │       ├── pdf.svg
│   │       ├── regression_small.svg
│   │       ├── regression.svg
│   │       ├── relative_pdf_small.svg
│   │       ├── relative_regression_small.svg
│   │       ├── SD.svg
│   │       ├── slope.svg
│   │       └── typical.svg
│   ├── centralization-risk
│   │   ├── base
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   ├── change
│   │   │   └── estimates.json
│   │   ├── new
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   └── report
│   │       ├── both
│   │       │   ├── pdf.svg
│   │       │   └── regression.svg
│   │       ├── change
│   │       │   ├── mean.svg
│   │       │   ├── median.svg
│   │       │   └── t-test.svg
│   │       ├── index.html
│   │       ├── MAD.svg
│   │       ├── mean.svg
│   │       ├── median.svg
│   │       ├── pdf_small.svg
│   │       ├── pdf.svg
│   │       ├── regression_small.svg
│   │       ├── regression.svg
│   │       ├── relative_pdf_small.svg
│   │       ├── relative_regression_small.svg
│   │       ├── SD.svg
│   │       ├── slope.svg
│   │       └── typical.svg
│   ├── constants-instead-of-literals
│   │   ├── base
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   ├── change
│   │   │   └── estimates.json
│   │   ├── new
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   └── report
│   │       ├── both
│   │       │   ├── pdf.svg
│   │       │   └── regression.svg
│   │       ├── change
│   │       │   ├── mean.svg
│   │       │   ├── median.svg
│   │       │   └── t-test.svg
│   │       ├── index.html
│   │       ├── MAD.svg
│   │       ├── mean.svg
│   │       ├── median.svg
│   │       ├── pdf_small.svg
│   │       ├── pdf.svg
│   │       ├── regression_small.svg
│   │       ├── regression.svg
│   │       ├── relative_pdf_small.svg
│   │       ├── relative_regression_small.svg
│   │       ├── SD.svg
│   │       ├── slope.svg
│   │       └── typical.svg
│   ├── delegate-call-in-loop
│   │   ├── base
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   ├── change
│   │   │   └── estimates.json
│   │   ├── new
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   └── report
│   │       ├── both
│   │       │   ├── pdf.svg
│   │       │   └── regression.svg
│   │       ├── change
│   │       │   ├── mean.svg
│   │       │   ├── median.svg
│   │       │   └── t-test.svg
│   │       ├── index.html
│   │       ├── MAD.svg
│   │       ├── mean.svg
│   │       ├── median.svg
│   │       ├── pdf_small.svg
│   │       ├── pdf.svg
│   │       ├── regression_small.svg
│   │       ├── regression.svg
│   │       ├── relative_pdf_small.svg
│   │       ├── relative_regression_small.svg
│   │       ├── SD.svg
│   │       ├── slope.svg
│   │       └── typical.svg
│   ├── deprecated-oz-functions
│   │   ├── base
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   ├── change
│   │   │   └── estimates.json
│   │   ├── new
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   └── report
│   │       ├── both
│   │       │   ├── pdf.svg
│   │       │   └── regression.svg
│   │       ├── change
│   │       │   ├── mean.svg
│   │       │   ├── median.svg
│   │       │   └── t-test.svg
│   │       ├── index.html
│   │       ├── MAD.svg
│   │       ├── mean.svg
│   │       ├── median.svg
│   │       ├── pdf_small.svg
│   │       ├── pdf.svg
│   │       ├── regression_small.svg
│   │       ├── regression.svg
│   │       ├── relative_pdf_small.svg
│   │       ├── relative_regression_small.svg
│   │       ├── SD.svg
│   │       ├── slope.svg
│   │       └── typical.svg
│   ├── ecrecover
│   │   ├── base
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   ├── change
│   │   │   └── estimates.json
│   │   ├── new
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   └── report
│   │       ├── both
│   │       │   ├── pdf.svg
│   │       │   └── regression.svg
│   │       ├── change
│   │       │   ├── mean.svg
│   │       │   ├── median.svg
│   │       │   └── t-test.svg
│   │       ├── index.html
│   │       ├── MAD.svg
│   │       ├── mean.svg
│   │       ├── median.svg
│   │       ├── pdf_small.svg
│   │       ├── pdf.svg
│   │       ├── regression_small.svg
│   │       ├── regression.svg
│   │       ├── relative_pdf_small.svg
│   │       ├── relative_regression_small.svg
│   │       ├── SD.svg
│   │       ├── slope.svg
│   │       └── typical.svg
│   ├── empty-block
│   │   ├── base
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   ├── change
│   │   │   └── estimates.json
│   │   ├── new
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   └── report
│   │       ├── both
│   │       │   ├── pdf.svg
│   │       │   └── regression.svg
│   │       ├── change
│   │       │   ├── mean.svg
│   │       │   ├── median.svg
│   │       │   └── t-test.svg
│   │       ├── index.html
│   │       ├── MAD.svg
│   │       ├── mean.svg
│   │       ├── median.svg
│   │       ├── pdf_small.svg
│   │       ├── pdf.svg
│   │       ├── regression_small.svg
│   │       ├── regression.svg
│   │       ├── relative_pdf_small.svg
│   │       ├── relative_regression_small.svg
│   │       ├── SD.svg
│   │       ├── slope.svg
│   │       └── typical.svg
│   ├── hello_world
│   │   ├── base
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   ├── new
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   └── report
│   │       ├── index.html
│   │       ├── MAD.svg
│   │       ├── mean.svg
│   │       ├── median.svg
│   │       ├── pdf_small.svg
│   │       ├── pdf.svg
│   │       ├── regression_small.svg
│   │       ├── regression.svg
│   │       ├── SD.svg
│   │       ├── slope.svg
│   │       └── typical.svg
│   ├── inconsistent-type-names
│   │   ├── base
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   ├── change
│   │   │   └── estimates.json
│   │   ├── new
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   └── report
│   │       ├── both
│   │       │   ├── pdf.svg
│   │       │   └── regression.svg
│   │       ├── change
│   │       │   ├── mean.svg
│   │       │   ├── median.svg
│   │       │   └── t-test.svg
│   │       ├── index.html
│   │       ├── MAD.svg
│   │       ├── mean.svg
│   │       ├── median.svg
│   │       ├── pdf_small.svg
│   │       ├── pdf.svg
│   │       ├── regression_small.svg
│   │       ├── regression.svg
│   │       ├── relative_pdf_small.svg
│   │       ├── relative_regression_small.svg
│   │       ├── SD.svg
│   │       ├── slope.svg
│   │       └── typical.svg
│   ├── large-numeric-literal
│   │   ├── base
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   ├── change
│   │   │   └── estimates.json
│   │   ├── new
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   └── report
│   │       ├── both
│   │       │   ├── pdf.svg
│   │       │   └── regression.svg
│   │       ├── change
│   │       │   ├── mean.svg
│   │       │   ├── median.svg
│   │       │   └── t-test.svg
│   │       ├── index.html
│   │       ├── MAD.svg
│   │       ├── mean.svg
│   │       ├── median.svg
│   │       ├── pdf_small.svg
│   │       ├── pdf.svg
│   │       ├── regression_small.svg
│   │       ├── regression.svg
│   │       ├── relative_pdf_small.svg
│   │       ├── relative_regression_small.svg
│   │       ├── SD.svg
│   │       ├── slope.svg
│   │       └── typical.svg
│   ├── non-reentrant-before-others
│   │   ├── base
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   ├── change
│   │   │   └── estimates.json
│   │   ├── new
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   └── report
│   │       ├── both
│   │       │   ├── pdf.svg
│   │       │   └── regression.svg
│   │       ├── change
│   │       │   ├── mean.svg
│   │       │   ├── median.svg
│   │       │   └── t-test.svg
│   │       ├── index.html
│   │       ├── MAD.svg
│   │       ├── mean.svg
│   │       ├── median.svg
│   │       ├── pdf_small.svg
│   │       ├── pdf.svg
│   │       ├── regression_small.svg
│   │       ├── regression.svg
│   │       ├── relative_pdf_small.svg
│   │       ├── relative_regression_small.svg
│   │       ├── SD.svg
│   │       ├── slope.svg
│   │       └── typical.svg
│   ├── push-zero-opcode
│   │   ├── base
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   ├── change
│   │   │   └── estimates.json
│   │   ├── new
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   └── report
│   │       ├── both
│   │       │   ├── pdf.svg
│   │       │   └── regression.svg
│   │       ├── change
│   │       │   ├── mean.svg
│   │       │   ├── median.svg
│   │       │   └── t-test.svg
│   │       ├── index.html
│   │       ├── MAD.svg
│   │       ├── mean.svg
│   │       ├── median.svg
│   │       ├── pdf_small.svg
│   │       ├── pdf.svg
│   │       ├── regression_small.svg
│   │       ├── regression.svg
│   │       ├── relative_pdf_small.svg
│   │       ├── relative_regression_small.svg
│   │       ├── SD.svg
│   │       ├── slope.svg
│   │       └── typical.svg
│   ├── report
│   │   └── index.html
│   ├── require-with-string
│   │   ├── base
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   ├── change
│   │   │   └── estimates.json
│   │   ├── new
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   └── report
│   │       ├── both
│   │       │   ├── pdf.svg
│   │       │   └── regression.svg
│   │       ├── change
│   │       │   ├── mean.svg
│   │       │   ├── median.svg
│   │       │   └── t-test.svg
│   │       ├── index.html
│   │       ├── MAD.svg
│   │       ├── mean.svg
│   │       ├── median.svg
│   │       ├── pdf_small.svg
│   │       ├── pdf.svg
│   │       ├── regression_small.svg
│   │       ├── regression.svg
│   │       ├── relative_pdf_small.svg
│   │       ├── relative_regression_small.svg
│   │       ├── SD.svg
│   │       ├── slope.svg
│   │       └── typical.svg
│   ├── solmate-safe-transfer-lib
│   │   ├── base
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   ├── change
│   │   │   └── estimates.json
│   │   ├── new
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   └── report
│   │       ├── both
│   │       │   ├── pdf.svg
│   │       │   └── regression.svg
│   │       ├── change
│   │       │   ├── mean.svg
│   │       │   ├── median.svg
│   │       │   └── t-test.svg
│   │       ├── index.html
│   │       ├── MAD.svg
│   │       ├── mean.svg
│   │       ├── median.svg
│   │       ├── pdf_small.svg
│   │       ├── pdf.svg
│   │       ├── regression_small.svg
│   │       ├── regression.svg
│   │       ├── relative_pdf_small.svg
│   │       ├── relative_regression_small.svg
│   │       ├── SD.svg
│   │       ├── slope.svg
│   │       └── typical.svg
│   ├── unindexed-events
│   │   ├── base
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   ├── change
│   │   │   └── estimates.json
│   │   ├── new
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   └── report
│   │       ├── both
│   │       │   ├── pdf.svg
│   │       │   └── regression.svg
│   │       ├── change
│   │       │   ├── mean.svg
│   │       │   ├── median.svg
│   │       │   └── t-test.svg
│   │       ├── index.html
│   │       ├── MAD.svg
│   │       ├── mean.svg
│   │       ├── median.svg
│   │       ├── pdf_small.svg
│   │       ├── pdf.svg
│   │       ├── regression_small.svg
│   │       ├── regression.svg
│   │       ├── relative_pdf_small.svg
│   │       ├── relative_regression_small.svg
│   │       ├── SD.svg
│   │       ├── slope.svg
│   │       └── typical.svg
│   ├── unprotected-initializer
│   │   ├── base
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   ├── change
│   │   │   └── estimates.json
│   │   ├── new
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   └── report
│   │       ├── both
│   │       │   ├── pdf.svg
│   │       │   └── regression.svg
│   │       ├── change
│   │       │   ├── mean.svg
│   │       │   ├── median.svg
│   │       │   └── t-test.svg
│   │       ├── index.html
│   │       ├── MAD.svg
│   │       ├── mean.svg
│   │       ├── median.svg
│   │       ├── pdf_small.svg
│   │       ├── pdf.svg
│   │       ├── regression_small.svg
│   │       ├── regression.svg
│   │       ├── relative_pdf_small.svg
│   │       ├── relative_regression_small.svg
│   │       ├── SD.svg
│   │       ├── slope.svg
│   │       └── typical.svg
│   ├── unsafe-erc20-functions
│   │   ├── base
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   ├── change
│   │   │   └── estimates.json
│   │   ├── new
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   └── report
│   │       ├── both
│   │       │   ├── pdf.svg
│   │       │   └── regression.svg
│   │       ├── change
│   │       │   ├── mean.svg
│   │       │   ├── median.svg
│   │       │   └── t-test.svg
│   │       ├── index.html
│   │       ├── MAD.svg
│   │       ├── mean.svg
│   │       ├── median.svg
│   │       ├── pdf_small.svg
│   │       ├── pdf.svg
│   │       ├── regression_small.svg
│   │       ├── regression.svg
│   │       ├── relative_pdf_small.svg
│   │       ├── relative_regression_small.svg
│   │       ├── SD.svg
│   │       ├── slope.svg
│   │       └── typical.svg
│   ├── unsafe-oz-erc721-mint
│   │   ├── base
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   ├── change
│   │   │   └── estimates.json
│   │   ├── new
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   └── report
│   │       ├── both
│   │       │   ├── pdf.svg
│   │       │   └── regression.svg
│   │       ├── change
│   │       │   ├── mean.svg
│   │       │   ├── median.svg
│   │       │   └── t-test.svg
│   │       ├── index.html
│   │       ├── MAD.svg
│   │       ├── mean.svg
│   │       ├── median.svg
│   │       ├── pdf_small.svg
│   │       ├── pdf.svg
│   │       ├── regression_small.svg
│   │       ├── regression.svg
│   │       ├── relative_pdf_small.svg
│   │       ├── relative_regression_small.svg
│   │       ├── SD.svg
│   │       ├── slope.svg
│   │       └── typical.svg
│   ├── unspecific-solidity-pragma
│   │   ├── base
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   ├── change
│   │   │   └── estimates.json
│   │   ├── new
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   └── report
│   │       ├── both
│   │       │   ├── pdf.svg
│   │       │   └── regression.svg
│   │       ├── change
│   │       │   ├── mean.svg
│   │       │   ├── median.svg
│   │       │   └── t-test.svg
│   │       ├── index.html
│   │       ├── MAD.svg
│   │       ├── mean.svg
│   │       ├── median.svg
│   │       ├── pdf_small.svg
│   │       ├── pdf.svg
│   │       ├── regression_small.svg
│   │       ├── regression.svg
│   │       ├── relative_pdf_small.svg
│   │       ├── relative_regression_small.svg
│   │       ├── SD.svg
│   │       ├── slope.svg
│   │       └── typical.svg
│   ├── useless-internal-function
│   │   ├── base
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   ├── change
│   │   │   └── estimates.json
│   │   ├── new
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   └── report
│   │       ├── both
│   │       │   ├── pdf.svg
│   │       │   └── regression.svg
│   │       ├── change
│   │       │   ├── mean.svg
│   │       │   ├── median.svg
│   │       │   └── t-test.svg
│   │       ├── index.html
│   │       ├── MAD.svg
│   │       ├── mean.svg
│   │       ├── median.svg
│   │       ├── pdf_small.svg
│   │       ├── pdf.svg
│   │       ├── regression_small.svg
│   │       ├── regression.svg
│   │       ├── relative_pdf_small.svg
│   │       ├── relative_regression_small.svg
│   │       ├── SD.svg
│   │       ├── slope.svg
│   │       └── typical.svg
│   ├── useless-modifier
│   │   ├── base
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   ├── change
│   │   │   └── estimates.json
│   │   ├── new
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   └── report
│   │       ├── both
│   │       │   ├── pdf.svg
│   │       │   └── regression.svg
│   │       ├── change
│   │       │   ├── mean.svg
│   │       │   ├── median.svg
│   │       │   └── t-test.svg
│   │       ├── index.html
│   │       ├── MAD.svg
│   │       ├── mean.svg
│   │       ├── median.svg
│   │       ├── pdf_small.svg
│   │       ├── pdf.svg
│   │       ├── regression_small.svg
│   │       ├── regression.svg
│   │       ├── relative_pdf_small.svg
│   │       ├── relative_regression_small.svg
│   │       ├── SD.svg
│   │       ├── slope.svg
│   │       └── typical.svg
│   ├── useless-public-function
│   │   ├── base
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   ├── change
│   │   │   └── estimates.json
│   │   ├── new
│   │   │   ├── benchmark.json
│   │   │   ├── estimates.json
│   │   │   ├── sample.json
│   │   │   └── tukey.json
│   │   └── report
│   │       ├── both
│   │       │   ├── pdf.svg
│   │       │   └── regression.svg
│   │       ├── change
│   │       │   ├── mean.svg
│   │       │   ├── median.svg
│   │       │   └── t-test.svg
│   │       ├── index.html
│   │       ├── MAD.svg
│   │       ├── mean.svg
│   │       ├── median.svg
│   │       ├── pdf_small.svg
│   │       ├── pdf.svg
│   │       ├── regression_small.svg
│   │       ├── regression.svg
│   │       ├── relative_pdf_small.svg
│   │       ├── relative_regression_small.svg
│   │       ├── SD.svg
│   │       ├── slope.svg
│   │       └── typical.svg
│   └── zero-address-check
│       ├── base
│       │   ├── benchmark.json
│       │   ├── estimates.json
│       │   ├── sample.json
│       │   └── tukey.json
│       ├── change
│       │   └── estimates.json
│       ├── new
│       │   ├── benchmark.json
│       │   ├── estimates.json
│       │   ├── sample.json
│       │   └── tukey.json
│       └── report
│           ├── both
│           │   ├── pdf.svg
│           │   └── regression.svg
│           ├── change
│           │   ├── mean.svg
│           │   ├── median.svg
│           │   └── t-test.svg
│           ├── index.html
│           ├── MAD.svg
│           ├── mean.svg
│           ├── median.svg
│           ├── pdf_small.svg
│           ├── pdf.svg
│           ├── regression_small.svg
│           ├── regression.svg
│           ├── relative_pdf_small.svg
│           ├── relative_regression_small.svg
│           ├── SD.svg
│           ├── slope.svg
│           └── typical.svg
├── Cargo.lock
├── Cargo.toml
├── cli
│   ├── benchmarks.sh
│   └── reportgen.sh
├── CODEOWNERS
├── CONTRIBUTING.md
├── cyfrinup
│   ├── dynamic_script
│   └── why.md
├── deny.toml
├── dist-workspace.toml
├── funding.json
├── LICENSE
├── Makefile
├── package-lock.json
├── package.json
├── README.md
├── RELEASE_CHECKLIST.md
├── reports
│   ├── adhoc-sol-files-highs-only-report.json
│   ├── adhoc-sol-files-report.md
│   ├── ccip-functions-report.md
│   ├── empty_report.md
│   ├── hardhat-playground-report.md
│   ├── nft-report-icm.md
│   ├── nft-report.md
│   ├── prb-math-report.md
│   ├── report.json
│   ├── report.md
│   ├── report.sarif
│   ├── sablier-aderyn-toml-nested-root.md
│   ├── templegold-report.md
│   └── uniswap_profile.md
├── rust-toolchain.toml
├── rustfmt.toml
├── tests
│   ├── adhoc-sol-files
│   │   ├── aderyn.toml
│   │   ├── Counter.sol
│   │   ├── DemoASTNodes.sol
│   │   ├── Helper.sol
│   │   ├── InconsistentUints.sol
│   │   ├── inheritance
│   │   │   ├── ExtendedInheritance.sol
│   │   │   ├── IContractInheritance.sol
│   │   │   └── InheritanceBase.sol
│   │   ├── InternalFunctions.sol
│   │   ├── lib
│   │   │   └── ThisShouldBeExcluded.sol
│   │   ├── multiple-versions
│   │   │   ├── 0.4
│   │   │   │   ├── A.sol
│   │   │   │   └── B.sol
│   │   │   ├── 0.5
│   │   │   │   ├── A.sol
│   │   │   │   └── B.sol
│   │   │   ├── 0.6
│   │   │   │   ├── A.sol
│   │   │   │   └── B.sol
│   │   │   ├── 0.7
│   │   │   │   ├── A.sol
│   │   │   │   └── B.sol
│   │   │   └── 0.8
│   │   │       ├── A.sol
│   │   │       └── B.sol
│   │   ├── OnceModifierExample.sol
│   │   └── StateVariables.sol
│   ├── ast
│   │   ├── abstract_contract.json
│   │   ├── address_payable.json
│   │   ├── array_type_name.json
│   │   ├── ast-erc4626.json
│   │   ├── base_constructor_call.json
│   │   ├── bit_not.json
│   │   ├── call.json
│   │   ├── constructor.json
│   │   ├── contract_dep_order.json
│   │   ├── do_while.json
│   │   ├── documentation_1.json
│   │   ├── documentation_2.json
│   │   ├── documentation_3.json
│   │   ├── documentation_local_variable.json
│   │   ├── documentation_on_statements.json
│   │   ├── documentation_triple.json
│   │   ├── empty_block.json
│   │   ├── enum_value_declaration.json
│   │   ├── enum_value.json
│   │   ├── event_definition.json
│   │   ├── experimental_encoder_pragma.json
│   │   ├── fallback_and_reveice_ether.json
│   │   ├── fallback_payable.json
│   │   ├── fallback.json
│   │   ├── function_type.json
│   │   ├── function.json
│   │   ├── global_enum.json
│   │   ├── global_struct.json
│   │   ├── inheritance_specifier.json
│   │   ├── leave.json
│   │   ├── license.json
│   │   ├── long_type_name_binary_operation.json
│   │   ├── long_type_name_identifier.json
│   │   ├── loop.json
│   │   ├── mappings.json
│   │   ├── modifier_definition.json
│   │   ├── modifier_invocation.json
│   │   ├── mutability.json
│   │   ├── nested_functions.json
│   │   ├── non_utf8.json
│   │   ├── override.json
│   │   ├── placeholder_statement.json
│   │   ├── receive_ether.json
│   │   ├── short_type_name_ref.json
│   │   ├── short_type_name.json
│   │   ├── slot_offset.json
│   │   ├── smoke.json
│   │   ├── source_location.json
│   │   ├── string.json
│   │   ├── stringlit.json
│   │   ├── switch_default.json
│   │   ├── switch.json
│   │   ├── try_catch.json
│   │   ├── two_base_functions.json
│   │   ├── unicode.json
│   │   ├── used_errors.json
│   │   ├── userDefinedValueType.json
│   │   ├── using_for_directive.json
│   │   ├── var_access.json
│   │   └── yul_hex_literal.json
│   ├── contract-playground
│   │   ├── .github
│   │   │   └── workflows
│   │   │       └── test.yml
│   │   ├── .gitignore
│   │   ├── dot
│   │   │   └── .gitkeep
│   │   ├── foundry.toml
│   │   ├── README.md
│   │   ├── script
│   │   │   └── Counter.s.sol
│   │   ├── src
│   │   │   ├── AbstractContract.sol
│   │   │   ├── AderynIgnoreCustomDetectors.sol
│   │   │   ├── AdminContract.sol
│   │   │   ├── ArbitraryTransferFrom.sol
│   │   │   ├── AssemblyExample.sol
│   │   │   ├── AssertStateChange.sol
│   │   │   ├── auditor_mode
│   │   │   │   ├── ExternalCalls.sol
│   │   │   │   └── PublicFunctionsWithoutSenderCheck.sol
│   │   │   ├── BooleanEquality.sol
│   │   │   ├── BuiltinSymbolShadow.sol
│   │   │   ├── CacheArrayLength.sol
│   │   │   ├── CallGraphTests.sol
│   │   │   ├── Casting.sol
│   │   │   ├── cloc
│   │   │   │   ├── AnotherHeavilyCommentedContract.sol
│   │   │   │   ├── EmptyContractFile.sol
│   │   │   │   └── HeavilyCommentedContract.sol
│   │   │   ├── CompilerBugStorageSignedIntegerArray.sol
│   │   │   ├── ConstantFuncsAssembly.sol
│   │   │   ├── ConstantsLiterals.sol
│   │   │   ├── ConstFuncChangeState.sol
│   │   │   ├── ContractLocksEther.sol
│   │   │   ├── ContractWithTodo.sol
│   │   │   ├── control_flow
│   │   │   │   └── SimpleProgram.sol
│   │   │   ├── CostlyOperationsInsideLoops.sol
│   │   │   ├── Counter.sol
│   │   │   ├── CrazyPragma.sol
│   │   │   ├── DangerousStrictEquality1.sol
│   │   │   ├── DangerousStrictEquality2.sol
│   │   │   ├── DangerousUnaryOperator.sol
│   │   │   ├── DeadCode.sol
│   │   │   ├── DelegateCallWithoutAddressCheck.sol
│   │   │   ├── DeletionNestedMappingStructureContract.sol
│   │   │   ├── DeprecatedOZFunctions.sol
│   │   │   ├── DivisionBeforeMultiplication.sol
│   │   │   ├── DynamicArrayLengthAssignment.sol
│   │   │   ├── EmitAfterExternalCall.sol
│   │   │   ├── EmptyBlocks.sol
│   │   │   ├── EnumerableSetIteration.sol
│   │   │   ├── eth2
│   │   │   │   └── DepositContract.sol
│   │   │   ├── ExperimentalEncoder.sol
│   │   │   ├── ExternalCalls.sol
│   │   │   ├── FunctionInitializingState.sol
│   │   │   ├── FunctionPointers.sol
│   │   │   ├── FunctionSignatureCollision.sol
│   │   │   ├── HugeConstants.sol
│   │   │   ├── IgnoreEverything.sol
│   │   │   ├── InconsistentUints.sol
│   │   │   ├── IncorrectCaretOperator.sol
│   │   │   ├── IncorrectERC20.sol
│   │   │   ├── IncorrectERC721.sol
│   │   │   ├── IncorrectModifier.sol
│   │   │   ├── IncorrectShift.sol
│   │   │   ├── inheritance
│   │   │   │   ├── ExtendedInheritance.sol
│   │   │   │   ├── IContractInheritance.sol
│   │   │   │   └── InheritanceBase.sol
│   │   │   ├── InternalFunctions.sol
│   │   │   ├── KeccakContract.sol
│   │   │   ├── LocalVariableShadow.sol
│   │   │   ├── MissingInheritance.sol
│   │   │   ├── MisusedBoolean.sol
│   │   │   ├── MsgValueInLoop.sol
│   │   │   ├── MultipleConstructorSchemes.sol
│   │   │   ├── MultiplePlaceholders.sol
│   │   │   ├── nested
│   │   │   │   ├── 1
│   │   │   │   │   └── Nested.sol
│   │   │   │   └── 2
│   │   │   │       └── Nested.sol
│   │   │   ├── nested_mappings
│   │   │   │   ├── LaterVersion.sol
│   │   │   │   └── NestedMappings.sol
│   │   │   ├── OnceModifierExample.sol
│   │   │   ├── OnlyLibrary.sol
│   │   │   ├── OutOfOrderRetryable.sol
│   │   │   ├── parent_chain
│   │   │   │   └── ParentChainContract.sol
│   │   │   ├── PragmaRange.sol
│   │   │   ├── PreDeclaredVarUsage.sol
│   │   │   ├── PublicFunction.sol
│   │   │   ├── PublicVariableReadInExternalContext.sol
│   │   │   ├── RedundantStatements.sol
│   │   │   ├── ReturnBomb.sol
│   │   │   ├── reused_contract_name
│   │   │   │   ├── ContractA.sol
│   │   │   │   └── ContractB.sol
│   │   │   ├── RevertsAndRequriesInLoops.sol
│   │   │   ├── router
│   │   │   │   ├── ExternalCalls.sol
│   │   │   │   ├── FallbackAndReceiveOverrides.sol
│   │   │   │   ├── InternalCalls.sol
│   │   │   │   ├── ModifierCalls.sol
│   │   │   │   └── VarOverridesFunction.sol
│   │   │   ├── RTLO.sol
│   │   │   ├── SendEtherNoChecks.sol
│   │   │   ├── SendEtherNoChecksLibImport.sol
│   │   │   ├── StateChangeAfterExternalCall.sol
│   │   │   ├── StateShadowing.sol
│   │   │   ├── StateVariableCouldBeDeclaredConstant.sol
│   │   │   ├── StateVariableCouldBeDeclaredImmutable.sol
│   │   │   ├── StateVariables.sol
│   │   │   ├── StateVariablesChangesWithoutEvents.sol
│   │   │   ├── StateVariablesManipulation.sol
│   │   │   ├── StorageConditionals.sol
│   │   │   ├── StorageParameters.sol
│   │   │   ├── T11sTranferer.sol
│   │   │   ├── TautologicalCompare.sol
│   │   │   ├── TautologyOrContradiction.sol
│   │   │   ├── TestERC20.sol
│   │   │   ├── TransientKeyword.sol
│   │   │   ├── Trump.sol
│   │   │   ├── TxOriginUsedForAuth.sol
│   │   │   ├── U2.sol
│   │   │   ├── U3.sol
│   │   │   ├── U4.sol
│   │   │   ├── U5.sol
│   │   │   ├── UncheckedCalls.sol
│   │   │   ├── UncheckedReturn.sol
│   │   │   ├── UncheckedSend.sol
│   │   │   ├── UninitializedLocalVariables.sol
│   │   │   ├── UninitializedStateVariable.sol
│   │   │   ├── uniswap
│   │   │   │   ├── UniswapV2Swapper.sol
│   │   │   │   └── UniswapV3Swapper.sol
│   │   │   ├── UnprotectedInitialize.sol
│   │   │   ├── UnsafeERC721Mint.sol
│   │   │   ├── UnusedError.sol
│   │   │   ├── UnusedImport.sol
│   │   │   ├── UnusedStateVariables.sol
│   │   │   ├── UsingSelfdestruct.sol
│   │   │   ├── VoidConstructor.sol
│   │   │   ├── WeakRandomness.sol
│   │   │   ├── WrongOrderOfLayout.sol
│   │   │   ├── YulReturn.sol
│   │   │   └── ZeroAddressCheck.sol
│   │   └── test
│   │       └── Counter.t.sol
│   ├── foundry-nft-f23
│   │   ├── .github
│   │   │   └── workflows
│   │   │       └── test.yml
│   │   ├── .gitignore
│   │   ├── foundry.lock
│   │   ├── foundry.toml
│   │   ├── README.md
│   │   ├── remappings.txt
│   │   └── src
│   │       ├── BasicNft.sol
│   │       ├── F1.sol
│   │       ├── F2.sol
│   │       ├── Initializer.sol
│   │       └── inner-core-modules
│   │           └── ICM.sol
│   ├── foundry-nft-f23-icm
│   │   ├── .github
│   │   │   └── workflows
│   │   │       └── test.yml
│   │   ├── .gitignore
│   │   ├── aderyn.toml
│   │   ├── foundry.toml
│   │   ├── README.md
│   │   ├── remappings.txt
│   │   └── src
│   │       ├── BasicNft.sol
│   │       ├── F1.sol
│   │       ├── F2.sol
│   │       ├── Initializer.sol
│   │       └── inner-core-modules
│   │           └── ICM.sol
│   ├── hardhat-js-playground
│   │   ├── .gitignore
│   │   ├── artifacts
│   │   │   ├── build-info
│   │   │   │   └── cee6fe9a9a2f03f7ff10a27ab2746af6.json
│   │   │   └── contracts
│   │   │       ├── Counter.sol
│   │   │       │   ├── Counter.dbg.json
│   │   │       │   └── Counter.json
│   │   │       ├── ExtendedInheritance.sol
│   │   │       │   ├── ExtendedInheritance.dbg.json
│   │   │       │   └── ExtendedInheritance.json
│   │   │       ├── IContractInheritance.sol
│   │   │       │   ├── IContractInheritance.dbg.json
│   │   │       │   └── IContractInheritance.json
│   │   │       ├── InheritanceBase.sol
│   │   │       │   ├── InheritanceBase.dbg.json
│   │   │       │   └── InheritanceBase.json
│   │   │       ├── KeccakContract.sol
│   │   │       │   ├── KeccakContract.dbg.json
│   │   │       │   └── KeccakContract.json
│   │   │       ├── Lock.sol
│   │   │       │   ├── Lock.dbg.json
│   │   │       │   └── Lock.json
│   │   │       └── StateVariables.sol
│   │   │           ├── StateVariables.dbg.json
│   │   │           └── StateVariables.json
│   │   ├── contracts
│   │   │   ├── Counter.sol
│   │   │   ├── ExtendedInheritance.sol
│   │   │   ├── IContractInheritance.sol
│   │   │   ├── InheritanceBase.sol
│   │   │   ├── KeccakContract.sol
│   │   │   ├── Lock.sol
│   │   │   └── StateVariables.sol
│   │   ├── hardhat.config.js
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── scripts
│   │   │   └── deploy.js
│   │   ├── test
│   │   │   └── Lock.js
│   │   └── yarn.lock
│   ├── no-sol-files
│   │   ├── extra
│   │   │   └── HelloAgain.md
│   │   ├── Hello.txt
│   │   └── Hello.yul
│   └── toml
│       ├── nested_project1
│       │   ├── aderyn.toml
│       │   ├── folder1
│       │   │   └── hardhat.config.ts
│       │   ├── folder2
│       │   │   └── hardhat.config.ts
│       │   └── folder3
│       │       └── file.txt
│       └── nested_project2
│           ├── aderyn.toml
│           ├── folder1
│           │   └── foundry.toml
│           └── folder2
│               └── file1.txt
├── tools
│   └── xtask
│       ├── Cargo.toml
│       └── src
│           ├── blesspr.rs
│           ├── cut_release.rs
│           ├── flags.rs
│           ├── main.rs
│           ├── reportgen.rs
│           └── tomlgen.rs
└── typos.toml
```

# Files

--------------------------------------------------------------------------------
/benchmarks/solmate-safe-transfer-lib/base/sample.json:
--------------------------------------------------------------------------------

```json
1 | {"sampling_mode":"Linear","iters":[292.0,584.0,876.0,1168.0,1460.0,1752.0,2044.0,2336.0,2628.0,2920.0,3212.0,3504.0,3796.0,4088.0,4380.0,4672.0,4964.0,5256.0,5548.0,5840.0,6132.0,6424.0,6716.0,7008.0,7300.0,7592.0,7884.0,8176.0,8468.0,8760.0,9052.0,9344.0,9636.0,9928.0,10220.0,10512.0,10804.0,11096.0,11388.0,11680.0,11972.0,12264.0,12556.0,12848.0,13140.0,13432.0,13724.0,14016.0,14308.0,14600.0,14892.0,15184.0,15476.0,15768.0,16060.0,16352.0,16644.0,16936.0,17228.0,17520.0,17812.0,18104.0,18396.0,18688.0,18980.0,19272.0,19564.0,19856.0,20148.0,20440.0,20732.0,21024.0,21316.0,21608.0,21900.0,22192.0,22484.0,22776.0,23068.0,23360.0,23652.0,23944.0,24236.0,24528.0,24820.0,25112.0,25404.0,25696.0,25988.0,26280.0,26572.0,26864.0,27156.0,27448.0,27740.0,28032.0,28324.0,28616.0,28908.0,29200.0],"times":[997990.0,1965424.0,3467476.0,3914259.0,5013435.0,5849950.0,8941973.0,7953753.0,9139220.0,9267038.0,10351067.0,11506127.0,12466142.0,13432426.0,14554931.0,15615660.0,16465445.0,17574089.0,18281793.0,18806230.0,19954265.0,21117146.0,22342220.0,22412672.0,23543893.0,24830363.0,25502455.0,27406565.0,28531027.0,29834957.0,30803633.0,31911239.0,32681347.0,32736833.0,33084270.0,34494054.0,35838690.0,36034730.0,36615032.0,38544982.0,39650221.0,40810132.0,41741539.0,42672424.0,43744598.0,45042155.0,46377222.0,51629388.0,50213970.0,49856984.0,50843605.0,51223715.0,52119621.0,53104051.0,53377859.0,52798383.0,55488493.0,55455731.0,56405636.0,57280836.0,59130757.0,60302233.0,59718696.0,61358849.0,62098602.0,61635688.0,64719827.0,66091778.0,64895764.0,66002658.0,68735962.0,69681083.0,69527911.0,71146396.0,72526931.0,73547197.0,75907799.0,88131329.0,77797867.0,78074754.0,79322501.0,78949231.0,78396257.0,81027112.0,82590019.0,83499411.0,82420211.0,84005987.0,84576718.0,86282774.0,88489197.0,88551298.0,90946855.0,89759611.0,89851763.0,93681091.0,95236719.0,96721425.0,93288848.0,93752315.0]}
```

--------------------------------------------------------------------------------
/benchmarks/solmate-safe-transfer-lib/new/sample.json:
--------------------------------------------------------------------------------

```json
1 | {"sampling_mode":"Linear","iters":[292.0,584.0,876.0,1168.0,1460.0,1752.0,2044.0,2336.0,2628.0,2920.0,3212.0,3504.0,3796.0,4088.0,4380.0,4672.0,4964.0,5256.0,5548.0,5840.0,6132.0,6424.0,6716.0,7008.0,7300.0,7592.0,7884.0,8176.0,8468.0,8760.0,9052.0,9344.0,9636.0,9928.0,10220.0,10512.0,10804.0,11096.0,11388.0,11680.0,11972.0,12264.0,12556.0,12848.0,13140.0,13432.0,13724.0,14016.0,14308.0,14600.0,14892.0,15184.0,15476.0,15768.0,16060.0,16352.0,16644.0,16936.0,17228.0,17520.0,17812.0,18104.0,18396.0,18688.0,18980.0,19272.0,19564.0,19856.0,20148.0,20440.0,20732.0,21024.0,21316.0,21608.0,21900.0,22192.0,22484.0,22776.0,23068.0,23360.0,23652.0,23944.0,24236.0,24528.0,24820.0,25112.0,25404.0,25696.0,25988.0,26280.0,26572.0,26864.0,27156.0,27448.0,27740.0,28032.0,28324.0,28616.0,28908.0,29200.0],"times":[997990.0,1965424.0,3467476.0,3914259.0,5013435.0,5849950.0,8941973.0,7953753.0,9139220.0,9267038.0,10351067.0,11506127.0,12466142.0,13432426.0,14554931.0,15615660.0,16465445.0,17574089.0,18281793.0,18806230.0,19954265.0,21117146.0,22342220.0,22412672.0,23543893.0,24830363.0,25502455.0,27406565.0,28531027.0,29834957.0,30803633.0,31911239.0,32681347.0,32736833.0,33084270.0,34494054.0,35838690.0,36034730.0,36615032.0,38544982.0,39650221.0,40810132.0,41741539.0,42672424.0,43744598.0,45042155.0,46377222.0,51629388.0,50213970.0,49856984.0,50843605.0,51223715.0,52119621.0,53104051.0,53377859.0,52798383.0,55488493.0,55455731.0,56405636.0,57280836.0,59130757.0,60302233.0,59718696.0,61358849.0,62098602.0,61635688.0,64719827.0,66091778.0,64895764.0,66002658.0,68735962.0,69681083.0,69527911.0,71146396.0,72526931.0,73547197.0,75907799.0,88131329.0,77797867.0,78074754.0,79322501.0,78949231.0,78396257.0,81027112.0,82590019.0,83499411.0,82420211.0,84005987.0,84576718.0,86282774.0,88489197.0,88551298.0,90946855.0,89759611.0,89851763.0,93681091.0,95236719.0,96721425.0,93288848.0,93752315.0]}
```

--------------------------------------------------------------------------------
/aderyn_core/src/stats.rs:
--------------------------------------------------------------------------------

```rust
 1 | use crate::context::workspace::WorkspaceContext;
 2 | use cloc::count_code_lines;
 3 | use ignore::get_lines_to_ignore;
 4 | use rayon::prelude::*;
 5 | use std::{
 6 |     collections::HashMap,
 7 |     path::{Path, PathBuf},
 8 |     str::FromStr,
 9 | };
10 | use token::tokenize;
11 | 
12 | pub mod cloc;
13 | pub mod ignore;
14 | pub mod token;
15 | pub mod util;
16 | 
17 | #[derive(Debug)]
18 | pub struct Stats {
19 |     pub code: usize,
20 |     pub ignore_lines: Vec<IgnoreLine>,
21 | }
22 | 
23 | #[derive(Debug, Clone)]
24 | pub enum When {
25 |     Always,
26 |     ForDetectorsWithNames(Vec<String>),
27 | }
28 | 
29 | #[derive(Debug, Clone)]
30 | pub struct IgnoreLine {
31 |     /// When to consider this ignore
32 |     pub when: When,
33 | 
34 |     /// Which line number to ignore
35 |     pub which: usize,
36 | }
37 | 
38 | pub fn collect_stats(
39 |     root: &Path,
40 |     skip_cloc: bool,
41 |     context: &WorkspaceContext,
42 | ) -> HashMap<String, Stats> {
43 |     context
44 |         .source_units()
45 |         .par_iter()
46 |         .map(|source_unit| {
47 |             let path = source_unit.absolute_path.clone().expect("absolute path not inserted");
48 |             let path = path.replace("//", "/"); // Condense entries that look like `contracts/templegold//AuctionBase.sol`
49 |             if !context.included.contains(&PathBuf::from_str(&path).unwrap()) {
50 |                 return None;
51 |             }
52 |             let content = source_unit.source.as_ref().expect("source not filled");
53 |             let stats = get_stats(content, skip_cloc);
54 |             let full_path = root.join(&path).to_string_lossy().to_string();
55 |             Some((full_path, stats))
56 |         })
57 |         .flatten()
58 |         .collect()
59 | }
60 | 
61 | pub fn get_stats(r_content: &str, skip_cloc: bool) -> Stats {
62 |     if r_content.is_empty() {
63 |         return Stats { code: 0, ignore_lines: vec![] };
64 |     }
65 | 
66 |     let token_descriptors = tokenize(r_content);
67 |     let code_lines = if skip_cloc { 0 } else { count_code_lines(&token_descriptors) };
68 |     let ignore_lines = get_lines_to_ignore(&token_descriptors);
69 | 
70 |     Stats { code: code_lines, ignore_lines }
71 | }
72 | 
```

--------------------------------------------------------------------------------
/benchmarks/hello_world/base/sample.json:
--------------------------------------------------------------------------------

```json
1 | {"sampling_mode":"Linear","iters":[486.0,972.0,1458.0,1944.0,2430.0,2916.0,3402.0,3888.0,4374.0,4860.0,5346.0,5832.0,6318.0,6804.0,7290.0,7776.0,8262.0,8748.0,9234.0,9720.0,10206.0,10692.0,11178.0,11664.0,12150.0,12636.0,13122.0,13608.0,14094.0,14580.0,15066.0,15552.0,16038.0,16524.0,17010.0,17496.0,17982.0,18468.0,18954.0,19440.0,19926.0,20412.0,20898.0,21384.0,21870.0,22356.0,22842.0,23328.0,23814.0,24300.0,24786.0,25272.0,25758.0,26244.0,26730.0,27216.0,27702.0,28188.0,28674.0,29160.0,29646.0,30132.0,30618.0,31104.0,31590.0,32076.0,32562.0,33048.0,33534.0,34020.0,34506.0,34992.0,35478.0,35964.0,36450.0,36936.0,37422.0,37908.0,38394.0,38880.0,39366.0,39852.0,40338.0,40824.0,41310.0,41796.0,42282.0,42768.0,43254.0,43740.0,44226.0,44712.0,45198.0,45684.0,46170.0,46656.0,47142.0,47628.0,48114.0,48600.0],"times":[788180.0,1691293.0,2999922.0,3158559.0,4751140.0,6364066.0,6025609.0,8795520.0,8531404.0,10440194.0,9299148.0,14278618.0,13037953.0,13186902.0,15164235.0,15837606.0,15758954.0,18526200.0,19907184.0,19464387.0,19517016.0,21309115.0,22391452.0,23778345.0,24497595.0,23118104.0,25348868.0,26683758.0,25608432.0,27254969.0,27123967.0,29825806.0,30221264.0,33536345.0,31892332.0,32469207.0,34945202.0,35775520.0,35629185.0,37370253.0,38136944.0,39305474.0,38830647.0,40012586.0,45815123.0,43455003.0,43518502.0,42622537.0,48902888.0,49138823.0,51249688.0,52570579.0,56016659.0,52727713.0,51796975.0,51692763.0,50992881.0,59851418.0,57665927.0,63542608.0,62652184.0,61793470.0,65560086.0,62260559.0,65534485.0,67709819.0,70808706.0,70004323.0,69616481.0,70749161.0,71658287.0,71946262.0,72391728.0,75792637.0,77826668.0,77204830.0,79340007.0,78435508.0,80847248.0,81817995.0,79781103.0,83751134.0,83998488.0,86061395.0,88695449.0,86021681.0,87807690.0,88040736.0,89118278.0,92632230.0,94122146.0,93160938.0,93297812.0,96588751.0,94820452.0,98630408.0,99426410.0,99895278.0,101846214.0,101516657.0]}
```

--------------------------------------------------------------------------------
/benchmarks/hello_world/new/sample.json:
--------------------------------------------------------------------------------

```json
1 | {"sampling_mode":"Linear","iters":[486.0,972.0,1458.0,1944.0,2430.0,2916.0,3402.0,3888.0,4374.0,4860.0,5346.0,5832.0,6318.0,6804.0,7290.0,7776.0,8262.0,8748.0,9234.0,9720.0,10206.0,10692.0,11178.0,11664.0,12150.0,12636.0,13122.0,13608.0,14094.0,14580.0,15066.0,15552.0,16038.0,16524.0,17010.0,17496.0,17982.0,18468.0,18954.0,19440.0,19926.0,20412.0,20898.0,21384.0,21870.0,22356.0,22842.0,23328.0,23814.0,24300.0,24786.0,25272.0,25758.0,26244.0,26730.0,27216.0,27702.0,28188.0,28674.0,29160.0,29646.0,30132.0,30618.0,31104.0,31590.0,32076.0,32562.0,33048.0,33534.0,34020.0,34506.0,34992.0,35478.0,35964.0,36450.0,36936.0,37422.0,37908.0,38394.0,38880.0,39366.0,39852.0,40338.0,40824.0,41310.0,41796.0,42282.0,42768.0,43254.0,43740.0,44226.0,44712.0,45198.0,45684.0,46170.0,46656.0,47142.0,47628.0,48114.0,48600.0],"times":[788180.0,1691293.0,2999922.0,3158559.0,4751140.0,6364066.0,6025609.0,8795520.0,8531404.0,10440194.0,9299148.0,14278618.0,13037953.0,13186902.0,15164235.0,15837606.0,15758954.0,18526200.0,19907184.0,19464387.0,19517016.0,21309115.0,22391452.0,23778345.0,24497595.0,23118104.0,25348868.0,26683758.0,25608432.0,27254969.0,27123967.0,29825806.0,30221264.0,33536345.0,31892332.0,32469207.0,34945202.0,35775520.0,35629185.0,37370253.0,38136944.0,39305474.0,38830647.0,40012586.0,45815123.0,43455003.0,43518502.0,42622537.0,48902888.0,49138823.0,51249688.0,52570579.0,56016659.0,52727713.0,51796975.0,51692763.0,50992881.0,59851418.0,57665927.0,63542608.0,62652184.0,61793470.0,65560086.0,62260559.0,65534485.0,67709819.0,70808706.0,70004323.0,69616481.0,70749161.0,71658287.0,71946262.0,72391728.0,75792637.0,77826668.0,77204830.0,79340007.0,78435508.0,80847248.0,81817995.0,79781103.0,83751134.0,83998488.0,86061395.0,88695449.0,86021681.0,87807690.0,88040736.0,89118278.0,92632230.0,94122146.0,93160938.0,93297812.0,96588751.0,94820452.0,98630408.0,99426410.0,99895278.0,101846214.0,101516657.0]}
```

--------------------------------------------------------------------------------
/tests/ast/call.json:
--------------------------------------------------------------------------------

```json
1 | {"absolutePath":"a","exportedSymbols":{"C":[6]},"id":7,"nodeType":"SourceUnit","nodes":[{"abstract":false,"baseContracts":[],"canonicalName":"C","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":6,"linearizedBaseContracts":[6],"name":"C","nameLocation":"9:1:1","nodeType":"ContractDefinition","nodes":[{"body":{"id":4,"nodeType":"Block","src":"37:59:1","statements":[{"AST":{"nodeType":"YulBlock","src":"56:34:1","statements":[{"expression":{"arguments":[{"arguments":[{"kind":"number","nodeType":"YulLiteral","src":"67:1:1","type":"","value":"0"},{"kind":"number","nodeType":"YulLiteral","src":"70:1:1","type":"","value":"1"},{"kind":"number","nodeType":"YulLiteral","src":"73:1:1","type":"","value":"2"},{"kind":"number","nodeType":"YulLiteral","src":"76:1:1","type":"","value":"3"},{"kind":"number","nodeType":"YulLiteral","src":"79:1:1","type":"","value":"4"},{"kind":"number","nodeType":"YulLiteral","src":"82:1:1","type":"","value":"5"},{"kind":"number","nodeType":"YulLiteral","src":"85:1:1","type":"","value":"6"}],"functionName":{"name":"call","nodeType":"YulIdentifier","src":"62:4:1"},"nodeType":"YulFunctionCall","src":"62:25:1"}],"functionName":{"name":"pop","nodeType":"YulIdentifier","src":"58:3:1"},"nodeType":"YulFunctionCall","src":"58:30:1"},"nodeType":"YulExpressionStatement","src":"58:30:1"}]},"evmVersion":"london","externalReferences":[],"id":3,"nodeType":"InlineAssembly","src":"47:43:1"}]},"functionSelector":"b582ec5f","id":5,"implemented":true,"kind":"function","modifiers":[],"name":"j","nameLocation":"26:1:1","nodeType":"FunctionDefinition","parameters":{"id":1,"nodeType":"ParameterList","parameters":[],"src":"27:2:1"},"returnParameters":{"id":2,"nodeType":"ParameterList","parameters":[],"src":"37:0:1"},"scope":6,"src":"17:79:1","stateMutability":"nonpayable","virtual":false,"visibility":"public"}],"scope":7,"src":"0:98:1","usedErrors":[]}],"src":"0:99:1"}
2 | 
```

--------------------------------------------------------------------------------
/aderyn_core/src/detect/high/selfdestruct.rs:
--------------------------------------------------------------------------------

```rust
 1 | use std::{collections::BTreeMap, error::Error};
 2 | 
 3 | use crate::ast::NodeID;
 4 | 
 5 | use crate::{
 6 |     capture,
 7 |     context::workspace::WorkspaceContext,
 8 |     detect::detector::{IssueDetector, IssueDetectorNamePool, IssueSeverity},
 9 | };
10 | use eyre::Result;
11 | 
12 | #[derive(Default)]
13 | pub struct SelfdestructDetector {
14 |     // Keys are: [0] source file name, [1] line number, [2] character location of node.
15 |     // Do not add items manually, use `capture!` to add nodes to this BTreeMap.
16 |     found_instances: BTreeMap<(String, usize, String), NodeID>,
17 | }
18 | 
19 | impl IssueDetector for SelfdestructDetector {
20 |     fn detect(&mut self, context: &WorkspaceContext) -> Result<bool, Box<dyn Error>> {
21 |         for identifier in context.identifiers() {
22 |             if identifier.name == "selfdestruct" {
23 |                 capture!(self, context, identifier);
24 |             }
25 |         }
26 |         Ok(!self.found_instances.is_empty())
27 |     }
28 | 
29 |     fn severity(&self) -> IssueSeverity {
30 |         IssueSeverity::High
31 |     }
32 | 
33 |     fn title(&self) -> String {
34 |         String::from("`selfdestruct` is Deprecated")
35 |     }
36 | 
37 |     fn description(&self) -> String {
38 |         String::from("Remove the `selfdestruct` instruction from the code.")
39 |     }
40 | 
41 |     fn instances(&self) -> BTreeMap<(String, usize, String), NodeID> {
42 |         self.found_instances.clone()
43 |     }
44 | 
45 |     fn name(&self) -> String {
46 |         IssueDetectorNamePool::Selfdestruct.to_string()
47 |     }
48 | }
49 | 
50 | #[cfg(test)]
51 | mod selfdestruct_identifier_tests {
52 | 
53 |     use crate::detect::{detector::IssueDetector, high::SelfdestructDetector};
54 | 
55 |     #[test]
56 | 
57 |     fn test_selfdestruct_identifier_tests() {
58 |         let context = crate::detect::test_utils::load_solidity_source_unit(
59 |             "../tests/contract-playground/src/UsingSelfdestruct.sol",
60 |         );
61 | 
62 |         let mut detector = SelfdestructDetector::default();
63 |         let found = detector.detect(&context).unwrap();
64 |         assert!(found);
65 |         assert_eq!(detector.instances().len(), 1);
66 |     }
67 | }
68 | 
```

--------------------------------------------------------------------------------
/aderyn_core/src/context/capturable.rs:
--------------------------------------------------------------------------------

```rust
 1 | use crate::ast::{ContractDefinition, *};
 2 | 
 3 | use super::{
 4 |     macros::generate_capturable_methods,
 5 |     workspace::{ASTNode, WorkspaceContext},
 6 | };
 7 | 
 8 | generate_capturable_methods! {
 9 |     Assignment,
10 |     BinaryOperation,
11 |     Block,
12 |     Conditional,
13 |     ContractDefinition,
14 |     ElementaryTypeNameExpression,
15 |     EnumDefinition,
16 |     EnumValue,
17 |     EventDefinition,
18 |     ExpressionStatement,
19 |     ErrorDefinition,
20 |     FunctionCall,
21 |     FunctionCallOptions,
22 |     FunctionDefinition,
23 |     ForStatement,
24 |     Identifier,
25 |     IdentifierPath,
26 |     IfStatement,
27 |     ImportDirective,
28 |     IndexAccess,
29 |     IndexRangeAccess,
30 |     InheritanceSpecifier,
31 |     InlineAssembly,
32 |     Literal,
33 |     MemberAccess,
34 |     NewExpression,
35 |     ModifierDefinition,
36 |     ModifierInvocation,
37 |     OverrideSpecifier,
38 |     ParameterList,
39 |     PragmaDirective,
40 |     Return,
41 |     SourceUnit,
42 |     StructDefinition,
43 |     StructuredDocumentation,
44 |     TupleExpression,
45 |     UnaryOperation,
46 |     UncheckedBlock,
47 |     UserDefinedValueTypeDefinition,
48 |     UsingForDirective,
49 |     VariableDeclaration,
50 |     VariableDeclarationStatement,
51 |     WhileStatement,
52 |     DoWhileStatement,
53 |     Break,
54 |     Continue,
55 |     PlaceholderStatement,
56 | }
57 | 
58 | impl From<&&ContractDefinition> for Capturable {
59 |     fn from(value: &&ContractDefinition) -> Self {
60 |         #[allow(suspicious_double_ref_op)]
61 |         Self::ContractDefinition(value.clone().clone())
62 |     }
63 | }
64 | 
65 | impl From<&&ModifierInvocation> for Capturable {
66 |     fn from(value: &&ModifierInvocation) -> Self {
67 |         #[allow(suspicious_double_ref_op)]
68 |         Self::ModifierInvocation(value.clone().clone())
69 |     }
70 | }
71 | 
72 | impl From<YulFunctionCall> for Capturable {
73 |     fn from(value: YulFunctionCall) -> Self {
74 |         Self::YulFunctionCall(value)
75 |     }
76 | }
77 | 
78 | impl From<&YulIdentifier> for Capturable {
79 |     fn from(value: &YulIdentifier) -> Self {
80 |         Self::YulIdentifier(value.clone())
81 |     }
82 | }
83 | 
84 | impl From<YulLiteral> for Capturable {
85 |     fn from(value: YulLiteral) -> Self {
86 |         Self::YulLiteral(value)
87 |     }
88 | }
89 | 
```

--------------------------------------------------------------------------------
/aderyn_driver/src/runner.rs:
--------------------------------------------------------------------------------

```rust
 1 | use aderyn_core::{context::workspace::WorkspaceContext, detect::detector::IssueDetector};
 2 | use std::error::Error;
 3 | 
 4 | use crate::{
 5 |     driver::CliArgsOutputConfig,
 6 |     interface::{OutputInterface, lsp::LspReport, output_interface_router, tables},
 7 |     process::WorkspaceContextWrapper,
 8 | };
 9 | use aderyn_core::report::*;
10 | 
11 | pub fn run_detector_mode(
12 |     cx_wrapper: &WorkspaceContextWrapper,
13 |     detectors: Vec<Box<dyn IssueDetector>>,
14 |     output_config: &CliArgsOutputConfig,
15 | ) -> Result<(), Box<dyn Error>> {
16 |     println!("Running {} detectors", detectors.len());
17 | 
18 |     let detectors_used =
19 |         &detectors.iter().map(|d| (d.name(), d.severity().to_string())).collect::<Vec<_>>();
20 | 
21 |     let report = detect_issues(&cx_wrapper.contexts, &cx_wrapper.root_path, detectors)?;
22 |     let output_file_path = output_config.output.clone();
23 | 
24 |     let output_interface = if output_file_path.ends_with(".json") {
25 |         OutputInterface::Json
26 |     } else if output_file_path.ends_with(".sarif") {
27 |         OutputInterface::Sarif
28 |     } else if output_file_path.ends_with(".md") {
29 |         OutputInterface::Markdown
30 |     } else {
31 |         println!("Warning: Output file extension is unrecognized. Reverting to markdown..");
32 |         OutputInterface::default()
33 |     };
34 | 
35 |     output_interface_router(output_interface, &report, cx_wrapper, detectors_used, output_config)?;
36 | 
37 |     Ok(())
38 | }
39 | 
40 | pub fn run_lsp_mode(
41 |     ctx_wrapper: &WorkspaceContextWrapper,
42 |     detectors: Vec<Box<dyn IssueDetector>>,
43 | ) -> Option<LspReport> {
44 |     let (root_rel_path, contexts) = (&ctx_wrapper.root_path, &ctx_wrapper.contexts);
45 |     match detect_issues(contexts, root_rel_path, detectors) {
46 |         Ok(report) => {
47 |             let (high_issues, low_issues) = report.detailed_issues(contexts);
48 |             Some(LspReport::from(low_issues, high_issues, root_rel_path))
49 |         }
50 |         Err(_) => None,
51 |     }
52 | }
53 | 
54 | pub fn run_auditor_mode(contexts: &[WorkspaceContext]) -> Result<(), Box<dyn Error>> {
55 |     tables::print_audit_info_tables(contexts)
56 | }
57 | 
```

--------------------------------------------------------------------------------
/aderyn_driver/src/interface/mod.rs:
--------------------------------------------------------------------------------

```rust
 1 | pub mod json;
 2 | pub mod lsp;
 3 | pub mod markdown;
 4 | pub mod sarif;
 5 | pub mod tables;
 6 | pub mod util;
 7 | 
 8 | use std::{
 9 |     fs::{File, remove_file},
10 |     io::{self, Result, Write},
11 |     path::Path,
12 | };
13 | 
14 | use aderyn_core::report::Report;
15 | 
16 | use crate::{driver::CliArgsOutputConfig, process::WorkspaceContextWrapper};
17 | 
18 | #[derive(Default)]
19 | pub enum OutputInterface {
20 |     Json,
21 |     #[default]
22 |     Markdown,
23 |     Sarif,
24 | }
25 | 
26 | pub fn output_interface_router(
27 |     output_interface: OutputInterface,
28 |     report: &Report,
29 |     cx_wrapper: &WorkspaceContextWrapper,
30 |     detectors_used: &[(String, String)],
31 |     output_config: &CliArgsOutputConfig,
32 | ) -> Result<()> {
33 |     let get_writer = |filename: &str| -> io::Result<File> {
34 |         let file_path = Path::new(filename);
35 |         if let Some(parent_dir) = file_path.parent() {
36 |             std::fs::create_dir_all(parent_dir)?;
37 |         }
38 |         if Path::new(filename).exists() {
39 |             remove_file(filename)?; // If file exists, delete it
40 |         }
41 |         File::create(filename)
42 |     };
43 | 
44 |     println!("Detectors run, printing report.");
45 | 
46 |     let mut b: Box<dyn Write> = if output_config.stdout {
47 |         Box::new(io::stdout())
48 |     } else {
49 |         Box::new(get_writer(&output_config.output)?)
50 |     };
51 | 
52 |     match output_interface {
53 |         OutputInterface::Json => {
54 |             json::print_report(
55 |                 &mut b,
56 |                 report,
57 |                 &cx_wrapper.contexts,
58 |                 output_config.stdout,
59 |                 detectors_used,
60 |             )?;
61 |         }
62 |         OutputInterface::Markdown => {
63 |             markdown::print_report(
64 |                 &mut b,
65 |                 report,
66 |                 cx_wrapper,
67 |                 output_config.output.clone(),
68 |                 output_config.no_snippets,
69 |             )?;
70 |         }
71 |         OutputInterface::Sarif => {
72 |             sarif::print_report(&mut b, report, output_config.stdout)?;
73 |         }
74 |     }
75 | 
76 |     if !output_config.stdout {
77 |         println!("Report printed to {}", output_config.output);
78 |     }
79 | 
80 |     Ok(())
81 | }
82 | 
```

--------------------------------------------------------------------------------
/aderyn_core/src/context/browser/peek_over.rs:
--------------------------------------------------------------------------------

```rust
 1 | use crate::{
 2 |     ast::NodeID,
 3 |     context::{browser::GetPreviousSibling, workspace::WorkspaceContext},
 4 |     visitor::ast_visitor::{ASTConstVisitor, Node},
 5 | };
 6 | 
 7 | pub trait PeekOver {
 8 |     /// Peek for text outside the node and just above until previous sibling is reached
 9 |     fn peek_over(&self, context: &WorkspaceContext) -> Option<String>;
10 | }
11 | 
12 | #[derive(Default)]
13 | struct NodeIDReceiver {
14 |     id: Option<NodeID>,
15 | }
16 | 
17 | impl ASTConstVisitor for NodeIDReceiver {
18 |     fn visit_node_id(&mut self, node_id: Option<NodeID>) -> eyre::Result<()> {
19 |         self.id = node_id;
20 |         Ok(())
21 |     }
22 | }
23 | 
24 | impl<T: Node + ?Sized> PeekOver for T {
25 |     fn peek_over(&self, context: &WorkspaceContext) -> Option<String> {
26 |         // Setup a Node ID receiver
27 |         let mut node_id_receiver = NodeIDReceiver::default();
28 | 
29 |         // Find the ID of the node this method is called upon
30 |         self.accept_id(&mut node_id_receiver).ok()?;
31 |         let current_node_id = node_id_receiver.id?;
32 | 
33 |         let source_unit =
34 |             context.get_source_unit_from_child_node(context.nodes.get(&current_node_id)?)?;
35 | 
36 |         let content = source_unit.source.as_ref()?;
37 |         let (curr_offset, _) = context.get_offset_and_length_of_node(current_node_id)?;
38 | 
39 |         if let Some(previous_sibling) = self.previous_sibling(context) {
40 |             let (prev_offset, prev_len) =
41 |                 context.get_offset_and_length_of_node(previous_sibling.id()?)?;
42 |             if prev_offset + prev_len < curr_offset && curr_offset < content.len() {
43 |                 let required_content = &content[prev_offset + prev_len..curr_offset];
44 |                 return Some(required_content.to_string());
45 |             } else {
46 |                 return None;
47 |             }
48 |         }
49 | 
50 |         // If there is no previous sibling we must return content from the top of the file
51 | 
52 |         if curr_offset < content.len() {
53 |             let required_content = &content[0..curr_offset];
54 |             return Some(required_content.to_string());
55 |         }
56 | 
57 |         None
58 |     }
59 | }
60 | 
```

--------------------------------------------------------------------------------
/tests/ast/enum_value_declaration.json:
--------------------------------------------------------------------------------

```json
1 | {"absolutePath":"a","exportedSymbols":{"A":[3],"f":[13]},"id":14,"nodeType":"SourceUnit","nodes":[{"canonicalName":"A","id":3,"members":[{"id":1,"name":"X","nameLocation":"9:1:1","nodeType":"EnumValue","src":"9:1:1"},{"id":2,"name":"Y","nameLocation":"12:1:1","nodeType":"EnumValue","src":"12:1:1"}],"name":"A","nameLocation":"5:1:1","nodeType":"EnumDefinition","src":"0:15:1"},{"body":{"id":12,"nodeType":"Block","src":"46:15:1","statements":[{"expression":{"expression":{"id":9,"name":"A","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":3,"src":"55:1:1","typeDescriptions":{"typeIdentifier":"t_type$_t_enum$_A_$3_$","typeString":"type(enum A)"}},"id":10,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberLocation":"57:1:1","memberName":"X","nodeType":"MemberAccess","referencedDeclaration":1,"src":"55:3:1","typeDescriptions":{"typeIdentifier":"t_enum$_A_$3","typeString":"enum A"}},"functionReturnParameters":8,"id":11,"nodeType":"Return","src":"48:10:1"}]},"id":13,"implemented":true,"kind":"freeFunction","modifiers":[],"name":"f","nameLocation":"25:1:1","nodeType":"FunctionDefinition","parameters":{"id":4,"nodeType":"ParameterList","parameters":[],"src":"26:2:1"},"returnParameters":{"id":8,"nodeType":"ParameterList","parameters":[{"constant":false,"id":7,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":13,"src":"43:1:1","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_enum$_A_$3","typeString":"enum A"},"typeName":{"id":6,"nodeType":"UserDefinedTypeName","pathNode":{"id":5,"name":"A","nameLocations":["43:1:1"],"nodeType":"IdentifierPath","referencedDeclaration":3,"src":"43:1:1"},"referencedDeclaration":3,"src":"43:1:1","typeDescriptions":{"typeIdentifier":"t_enum$_A_$3","typeString":"enum A"}},"visibility":"internal"}],"src":"42:3:1"},"scope":14,"src":"16:45:1","stateMutability":"pure","virtual":false,"visibility":"internal"}],"src":"0:62:1"}
2 | 
```

--------------------------------------------------------------------------------
/aderyn_core/src/ast/impls/node/using_for_directives.rs:
--------------------------------------------------------------------------------

```rust
 1 | use crate::{ast::*, visitor::ast_visitor::*};
 2 | use eyre::Result;
 3 | 
 4 | impl Node for UsingForDirective {
 5 |     fn accept(&self, visitor: &mut impl ASTConstVisitor) -> Result<()> {
 6 |         if visitor.visit_using_for_directive(self)? {
 7 |             // TODO there is a deviation. Missing FunctionsOrLibrary
 8 |             if self.library_name.is_some() {
 9 |                 match self.library_name.as_ref().unwrap() {
10 |                     UserDefinedTypeNameOrIdentifierPath::UserDefinedTypeName(_) => {}
11 |                     UserDefinedTypeNameOrIdentifierPath::IdentifierPath(identifier_path) => {
12 |                         identifier_path.accept(visitor)?;
13 |                     }
14 |                 };
15 |             }
16 |             if self.type_name.is_some() {
17 |                 self.type_name.as_ref().unwrap().accept(visitor)?;
18 |             }
19 |             if let Some(function_list) = &self.function_list {
20 |                 for func_item in function_list {
21 |                     match func_item {
22 |                         UsingForFunctionItem::Function(function) => {
23 |                             function.function.accept(visitor)?;
24 |                         }
25 |                         UsingForFunctionItem::OverloadedOperator(overloaded_operator) => {
26 |                             overloaded_operator.definition.accept(visitor)?;
27 |                         }
28 |                     }
29 |                 }
30 |             }
31 |             self.accept_metadata(visitor)?;
32 |         }
33 |         visitor.end_visit_using_for_directive(self)
34 |     }
35 |     fn accept_metadata(&self, visitor: &mut impl ASTConstVisitor) -> Result<()> {
36 |         if self.library_name.is_some() {
37 |             match self.library_name.as_ref().unwrap() {
38 |                 UserDefinedTypeNameOrIdentifierPath::UserDefinedTypeName(_) => {}
39 |                 UserDefinedTypeNameOrIdentifierPath::IdentifierPath(identifier_path) => {
40 |                     visitor.visit_immediate_children(self.id, vec![identifier_path.id])?;
41 |                 }
42 |             };
43 |         }
44 |         Ok(())
45 |     }
46 |     macros::accept_id!();
47 | }
48 | 
```

--------------------------------------------------------------------------------
/tests/ast/nested_functions.json:
--------------------------------------------------------------------------------

```json
1 | {"absolutePath":"a","exportedSymbols":{"C":[8]},"id":9,"nodeType":"SourceUnit","nodes":[{"abstract":false,"baseContracts":[],"canonicalName":"C","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":8,"linearizedBaseContracts":[8],"name":"C","nameLocation":"9:1:1","nodeType":"ContractDefinition","nodes":[{"body":{"id":6,"nodeType":"Block","src":"57:95:1","statements":[{"AST":{"nodeType":"YulBlock","src":"72:76:1","statements":[{"body":{"nodeType":"YulBlock","src":"94:35:1","statements":[{"body":{"nodeType":"YulBlock","src":"118:3:1","statements":[]},"name":"f2","nodeType":"YulFunctionDefinition","src":"104:17:1"}]},"name":"f1","nodeType":"YulFunctionDefinition","src":"80:49:1"},{"nodeType":"YulAssignment","src":"136:6:1","value":{"kind":"number","nodeType":"YulLiteral","src":"141:1:1","type":"","value":"2"},"variableNames":[{"name":"x","nodeType":"YulIdentifier","src":"136:1:1"}]}]},"evmVersion":"london","externalReferences":[{"declaration":3,"isOffset":false,"isSlot":false,"src":"136:1:1","valueSize":1}],"id":5,"nodeType":"InlineAssembly","src":"63:85:1"}]},"functionSelector":"26121ff0","id":7,"implemented":true,"kind":"function","modifiers":[],"name":"f","nameLocation":"24:1:1","nodeType":"FunctionDefinition","parameters":{"id":1,"nodeType":"ParameterList","parameters":[],"src":"25:2:1"},"returnParameters":{"id":4,"nodeType":"ParameterList","parameters":[{"constant":false,"id":3,"mutability":"mutable","name":"x","nameLocation":"54:1:1","nodeType":"VariableDeclaration","scope":7,"src":"49:6:1","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":2,"name":"uint","nodeType":"ElementaryTypeName","src":"49:4:1","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"src":"48:8:1"},"scope":8,"src":"15:137:1","stateMutability":"pure","virtual":false,"visibility":"public"}],"scope":9,"src":"0:154:1","usedErrors":[]}],"src":"0:155:1"}
2 | 
```

--------------------------------------------------------------------------------
/aderyn_core/src/detect/high/yul_return.rs:
--------------------------------------------------------------------------------

```rust
 1 | use std::{collections::BTreeMap, error::Error};
 2 | 
 3 | use crate::ast::NodeID;
 4 | 
 5 | use crate::{
 6 |     capture,
 7 |     context::workspace::WorkspaceContext,
 8 |     detect::detector::{IssueDetector, IssueDetectorNamePool, IssueSeverity},
 9 | };
10 | use eyre::Result;
11 | 
12 | #[derive(Default)]
13 | pub struct YulReturnDetector {
14 |     // Keys are: [0] source file name, [1] line number, [2] character location of node.
15 |     // Do not add items manually, use `capture!` to add nodes to this BTreeMap.
16 |     found_instances: BTreeMap<(String, usize, String), NodeID>,
17 | }
18 | 
19 | impl IssueDetector for YulReturnDetector {
20 |     fn detect(&mut self, context: &WorkspaceContext) -> Result<bool, Box<dyn Error>> {
21 |         for function_call in context.yul_function_calls() {
22 |             if function_call.function_name.name == "return" {
23 |                 capture!(self, context, function_call);
24 |             }
25 |         }
26 | 
27 |         Ok(!self.found_instances.is_empty())
28 |     }
29 | 
30 |     fn severity(&self) -> IssueSeverity {
31 |         IssueSeverity::High
32 |     }
33 | 
34 |     fn title(&self) -> String {
35 |         String::from("Yul block contains `return`")
36 |     }
37 | 
38 |     fn description(&self) -> String {
39 |         String::from(
40 |             "This causes the transaction execution to halt, and nothing after that call will execute including code following the assembly block.",
41 |         )
42 |     }
43 | 
44 |     fn instances(&self) -> BTreeMap<(String, usize, String), NodeID> {
45 |         self.found_instances.clone()
46 |     }
47 | 
48 |     fn name(&self) -> String {
49 |         IssueDetectorNamePool::YulReturn.to_string()
50 |     }
51 | }
52 | 
53 | #[cfg(test)]
54 | mod yul_return_detector_tests {
55 | 
56 |     use crate::detect::{detector::IssueDetector, high::yul_return::YulReturnDetector};
57 | 
58 |     #[test]
59 | 
60 |     fn test_yul_return() {
61 |         let context = crate::detect::test_utils::load_solidity_source_unit(
62 |             "../tests/contract-playground/src/YulReturn.sol",
63 |         );
64 | 
65 |         let mut detector = YulReturnDetector::default();
66 |         let found = detector.detect(&context).unwrap();
67 |         assert!(found);
68 | 
69 |         assert_eq!(detector.instances().len(), 1);
70 |     }
71 | }
72 | 
```

--------------------------------------------------------------------------------
/bacon.toml:
--------------------------------------------------------------------------------

```toml
 1 | # This is a configuration file for the bacon tool
 2 | #
 3 | # Complete help on configuration: https://dystroy.org/bacon/config/
 4 | #
 5 | # You may check the current default at
 6 | #   https://github.com/Canop/bacon/blob/main/defaults/default-bacon.toml
 7 | 
 8 | default_job = "clippy-display-warnings"
 9 | env.CARGO_TERM_COLOR = "always"
10 | 
11 | # Background jobs
12 | 
13 | # Lints
14 | 
15 | [jobs.clippy-display-warnings]
16 | command = ["cargo", "clippy"]
17 | need_stdout = false
18 | 
19 | [jobs.fmt-display-warnings]
20 | command = ["cargo", "fmt", "--all", "--check"]
21 | need_stdout = false
22 | 
23 | # Test
24 | 
25 | [job.test]
26 | command = ["cargo", "test"]
27 | need_stdout = false
28 | 
29 | # ===
30 | 
31 | # Non background jobs / ACTIONS
32 | 
33 | # Run aderyn on all integration tests
34 | [jobs.generate-all-reports]
35 | command = [
36 |     "cargo", "prep", "--all", "--parallel"
37 | ]
38 | need_stdout = true
39 | need_stderr = true
40 | allow_warnings = true
41 | background = false
42 | on_change_strategy = "kill_then_restart"
43 | 
44 | # Bless PR
45 | [jobs.blesspr]
46 | command = [
47 |     "cargo", "blesspr"
48 | ]
49 | need_stdout = true
50 | need_stderr = true
51 | allow_warnings = true
52 | background = false
53 | 
54 | ## Run aderyn on Contract playground
55 | 
56 | [jobs.contract-playground]
57 | command = [
58 |     "cargo", "prep", "--cpg"
59 |     # put launch parameters for your program behind a `--` separator
60 | ]
61 | need_stdout = true
62 | need_stderr = true
63 | allow_warnings = true
64 | background = false
65 | on_change_strategy = "kill_then_restart"
66 | 
67 | ## Run Tests and report time
68 | 
69 | [jobs.test-report-time]
70 | command = ["cargo", "test", "--", "-Zunstable-options", "--report-time"]
71 | need_stdout = true
72 | background = false
73 | 
74 | [jobs.nextest]
75 | command = [
76 |     "cargo", "nextest", "run",
77 |     "--hide-progress-bar", "--failure-output", "final"
78 | ]
79 | need_stdout = true
80 | analyzer = "nextest"
81 | background = false
82 | 
83 | ## Compile Docs and open
84 | [jobs.doc-open]
85 | command = ["cargo", "doc", "--no-deps", "--open"]
86 | need_stdout = false
87 | background = false
88 | on_success = "back" # so that we don't open the browser at each change
89 | 
90 | [keybindings]
91 | c = "job:clippy-display-warnings"
92 | f = "job:fmt-display-warnings"
93 | r = "job:contract-playground"
94 | alt-t = "job:test-report-time"
95 | t = "job:test"
96 | d = "job:doc-open"
97 | a = "job:generate-all-reports"
98 | alt-b = "job:blesspr"
99 | 
```

--------------------------------------------------------------------------------
/aderyn_core/src/test_utils.rs:
--------------------------------------------------------------------------------

```rust
 1 | mod load_source_unit;
 2 | 
 3 | use crate::{
 4 |     ast::{ContractDefinition, FunctionDefinition, FunctionKind, ModifierDefinition, NodeID},
 5 |     context::{browser::ExtractVariableDeclarations, workspace::WorkspaceContext},
 6 | };
 7 | 
 8 | // Using `solc` to read AST given a source unit (i.e Solidity file)
 9 | pub use load_source_unit::{
10 |     load_multiple_solidity_source_units_into_single_context, load_playground_solidity_source_units,
11 |     load_solidity_source_unit,
12 | };
13 | 
14 | impl WorkspaceContext {
15 |     pub fn find_contract_by_name(&self, name: &str) -> &ContractDefinition {
16 |         self.contract_definitions().into_iter().find(|c| c.name.as_str() == name).unwrap()
17 |     }
18 |     pub fn find_free_function_by_name(&self, name: &str) -> &FunctionDefinition {
19 |         self.function_definitions()
20 |             .iter()
21 |             .filter(|func| *func.kind() == FunctionKind::FreeFunction)
22 |             .find(|func| func.name == name)
23 |             .unwrap()
24 |     }
25 | }
26 | 
27 | impl ContractDefinition {
28 |     pub fn find_function_by_name(&self, name: &str) -> &FunctionDefinition {
29 |         self.function_definitions().iter().find(|func| func.name == name).unwrap()
30 |     }
31 | 
32 |     pub fn find_receive_function(&self) -> &FunctionDefinition {
33 |         self.function_definitions()
34 |             .iter()
35 |             .find(|func| *func.kind() == FunctionKind::Receive)
36 |             .unwrap()
37 |     }
38 | 
39 |     pub fn find_fallback_function(&self) -> &FunctionDefinition {
40 |         self.function_definitions()
41 |             .iter()
42 |             .find(|func| *func.kind() == FunctionKind::Fallback)
43 |             .unwrap()
44 |     }
45 | 
46 |     pub fn find_modifier_by_name(&self, name: &str) -> &ModifierDefinition {
47 |         self.modifier_definitions().iter().find(|modifier| modifier.name == name).unwrap()
48 |     }
49 | 
50 |     pub fn find_state_variable_node_id_by_name(&self, name: &str) -> NodeID {
51 |         let variable_declarations = ExtractVariableDeclarations::from(self).extracted;
52 |         let variable = variable_declarations
53 |             .into_iter()
54 |             .filter(|v| v.state_variable && v.name == name)
55 |             .collect::<Vec<_>>();
56 |         variable.first().unwrap().id
57 |     }
58 | }
59 | 
```

--------------------------------------------------------------------------------
/.github/workflows/toml.yml:
--------------------------------------------------------------------------------

```yaml
 1 | on: [push, pull_request, workflow_dispatch]
 2 | 
 3 | name: Aderyn toml creation
 4 | 
 5 | concurrency:
 6 |   group: ci-${{ github.ref }}-toml
 7 |   cancel-in-progress: true
 8 | 
 9 | jobs:
10 |   reports-setup:
11 |     name:  Check toml 
12 |     runs-on: ubuntu-latest
13 |     outputs:
14 |       rust-nightly: nightly-2025-09-20
15 |     
16 |     strategy:
17 |       fail-fast: false
18 |       matrix:
19 |         task:
20 |           - nested_folder1
21 |           - nested_folder2
22 | 
23 |     steps:
24 |       - name: Checkout Sources
25 |         uses: actions/checkout@v4
26 | 
27 |       - name: Checkout repository with submodules
28 |         uses: actions/checkout@v4
29 |         with:
30 |           submodules: recursive
31 | 
32 |       - name: Cache submodules
33 |         id: cache-submodules
34 |         uses: actions/cache@v3
35 |         with:
36 |           path: .git/modules
37 |           key: submodules-${{ runner.os }}-${{ hashFiles('.gitmodules') }}
38 |           restore-keys: |
39 |             submodules-${{ runner.os }}-${{ hashFiles('.gitmodules') }}
40 | 
41 |       - name: Install Rust Nightly (2025-01-01)
42 |         uses: actions-rs/toolchain@v1
43 |         with:
44 |           profile: minimal
45 |           toolchain: nightly-2025-09-20
46 |           override: true
47 | 
48 |       - name: Restore Rust Cache
49 |         uses: Swatinem/rust-cache@v2
50 | 
51 |       - name: Prebuild (${{ matrix.task }})
52 |         run: |
53 |           cargo build
54 | 
55 |       - name: Generate aderyn.toml (${{ matrix.task }})
56 |         run: |
57 |           case "${{ matrix.task }}" in
58 |             nested-folder1)
59 |               mv ./tests/toml/nested_project1/aderyn.toml expected1.toml
60 | 
61 |               rm -rf ./tests/toml/nested_project1/aderyn.toml
62 |               cargo run -- init ./tests/toml/nested_project1
63 | 
64 |               mv ./tests/toml/nested_project1/aderyn.toml actual1.toml
65 |               diff expected1.toml actual1.toml
66 |               ;;
67 |              nested-folder2)
68 |               mv ./tests/toml/nested_project2/aderyn.toml expected2.toml
69 | 
70 |               rm -rf ./tests/toml/nested_project2/aderyn.toml
71 |               cargo run -- init ./tests/toml/nested_project2
72 | 
73 |               mv ./tests/toml/nested_project2/aderyn.toml actual2.toml
74 |               diff expected2.toml actual2.toml
75 |               ;;
76 |           esac
77 | 
```

--------------------------------------------------------------------------------
/aderyn_core/src/ast/impls/own/hashing.rs:
--------------------------------------------------------------------------------

```rust
 1 | use crate::ast::*;
 2 | use std::hash::{Hash, Hasher};
 3 | 
 4 | // Identifier
 5 | impl PartialEq for Identifier {
 6 |     fn eq(&self, other: &Self) -> bool {
 7 |         self.argument_types.eq(&other.argument_types)
 8 |             && self.name.eq(&other.name)
 9 |             && self.overloaded_declarations.eq(&other.overloaded_declarations)
10 |             && self.referenced_declaration.eq(&other.referenced_declaration)
11 |             && self.type_descriptions.eq(&other.type_descriptions)
12 |     }
13 | }
14 | 
15 | impl Hash for Identifier {
16 |     fn hash<H: Hasher>(&self, state: &mut H) {
17 |         self.argument_types.hash(state);
18 |         self.name.hash(state);
19 |         self.overloaded_declarations.hash(state);
20 |         self.referenced_declaration.hash(state);
21 |         self.type_descriptions.hash(state);
22 |         self.src.hash(state);
23 |         self.id.hash(state);
24 |     }
25 | }
26 | 
27 | // Identifier Path
28 | impl PartialEq for IdentifierPath {
29 |     fn eq(&self, other: &Self) -> bool {
30 |         self.name.eq(&other.name) && self.referenced_declaration.eq(&other.referenced_declaration)
31 |     }
32 | }
33 | 
34 | impl Hash for IdentifierPath {
35 |     fn hash<H: Hasher>(&self, state: &mut H) {
36 |         self.name.hash(state);
37 |         self.referenced_declaration.hash(state);
38 |         self.src.hash(state);
39 |         self.id.hash(state);
40 |     }
41 | }
42 | 
43 | // ElementaryTypeName
44 | impl PartialEq for ElementaryTypeName {
45 |     fn eq(&self, other: &Self) -> bool {
46 |         self.state_mutability.eq(&other.state_mutability)
47 |             && self.type_descriptions.eq(&other.type_descriptions)
48 |     }
49 | }
50 | 
51 | impl Hash for ElementaryTypeName {
52 |     fn hash<H: Hasher>(&self, state: &mut H) {
53 |         self.state_mutability.hash(state);
54 |         self.name.hash(state);
55 |         self.type_descriptions.hash(state);
56 |     }
57 | }
58 | 
59 | // UserDefinedTypeName
60 | impl PartialEq for UserDefinedTypeName {
61 |     fn eq(&self, other: &Self) -> bool {
62 |         self.referenced_declaration.eq(&other.referenced_declaration)
63 |     }
64 | }
65 | 
66 | impl Hash for UserDefinedTypeName {
67 |     fn hash<H: Hasher>(&self, state: &mut H) {
68 |         self.path_node.hash(state);
69 |         self.referenced_declaration.hash(state);
70 |         self.name.hash(state);
71 |         self.type_descriptions.hash(state);
72 |     }
73 | }
74 | 
```

--------------------------------------------------------------------------------
/tests/ast/modifier_invocation.json:
--------------------------------------------------------------------------------

```json
1 | {"absolutePath":"a","exportedSymbols":{"C":[14]},"id":15,"nodeType":"SourceUnit","nodes":[{"abstract":false,"baseContracts":[],"canonicalName":"C","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":14,"linearizedBaseContracts":[14],"name":"C","nameLocation":"9:1:1","nodeType":"ContractDefinition","nodes":[{"body":{"id":5,"nodeType":"Block","src":"32:6:1","statements":[{"id":4,"nodeType":"PlaceholderStatement","src":"34:1:1"}]},"id":6,"name":"M","nameLocation":"22:1:1","nodeType":"ModifierDefinition","parameters":{"id":3,"nodeType":"ParameterList","parameters":[{"constant":false,"id":2,"mutability":"mutable","name":"i","nameLocation":"29:1:1","nodeType":"VariableDeclaration","scope":6,"src":"24:6:1","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":1,"name":"uint","nodeType":"ElementaryTypeName","src":"24:4:1","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"src":"23:8:1"},"src":"13:25:1","virtual":false,"visibility":"internal"},{"body":{"id":12,"nodeType":"Block","src":"64:2:1","statements":[]},"functionSelector":"28811f59","id":13,"implemented":true,"kind":"function","modifiers":[{"arguments":[{"hexValue":"31","id":9,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"54:1:1","typeDescriptions":{"typeIdentifier":"t_rational_1_by_1","typeString":"int_const 1"},"value":"1"}],"id":10,"kind":"modifierInvocation","modifierName":{"id":8,"name":"M","nameLocations":["52:1:1"],"nodeType":"IdentifierPath","referencedDeclaration":6,"src":"52:1:1"},"nodeType":"ModifierInvocation","src":"52:4:1"}],"name":"F","nameLocation":"48:1:1","nodeType":"FunctionDefinition","parameters":{"id":7,"nodeType":"ParameterList","parameters":[],"src":"49:2:1"},"returnParameters":{"id":11,"nodeType":"ParameterList","parameters":[],"src":"64:0:1"},"scope":14,"src":"39:27:1","stateMutability":"nonpayable","virtual":false,"visibility":"public"}],"scope":15,"src":"0:68:1","usedErrors":[]}],"src":"0:69:1"}
2 | 
```

--------------------------------------------------------------------------------
/tests/hardhat-js-playground/artifacts/contracts/InheritanceBase.sol/InheritanceBase.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "_format": "hh-sol-artifact-1",
 3 |   "contractName": "InheritanceBase",
 4 |   "sourceName": "contracts/InheritanceBase.sol",
 5 |   "abi": [
 6 |     {
 7 |       "anonymous": false,
 8 |       "inputs": [
 9 |         {
10 |           "indexed": false,
11 |           "internalType": "uint256",
12 |           "name": "something",
13 |           "type": "uint256"
14 |         }
15 |       ],
16 |       "name": "Do",
17 |       "type": "event"
18 |     },
19 |     {
20 |       "inputs": [
21 |         {
22 |           "internalType": "uint256",
23 |           "name": "something",
24 |           "type": "uint256"
25 |         }
26 |       ],
27 |       "name": "doSomething",
28 |       "outputs": [],
29 |       "stateMutability": "nonpayable",
30 |       "type": "function"
31 |     }
32 |   ],
33 |   "bytecode": "0x608060405234801561001057600080fd5b5061014e806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063a6b206bf14610030575b600080fd5b61004a600480360381019061004591906100c1565b61004c565b005b7f2ad1127294a42a5200f9832aacf01f051e55151abd09c0d2a055e56b214ebd4c8160405161007b91906100fd565b60405180910390a150565b600080fd5b6000819050919050565b61009e8161008b565b81146100a957600080fd5b50565b6000813590506100bb81610095565b92915050565b6000602082840312156100d7576100d6610086565b5b60006100e5848285016100ac565b91505092915050565b6100f78161008b565b82525050565b600060208201905061011260008301846100ee565b9291505056fea2646970667358221220bf22606c5b554878a183eb94c6d8d4f82fce03670d1285d5b85d2cc78ad83f2164736f6c63430008140033",
34 |   "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063a6b206bf14610030575b600080fd5b61004a600480360381019061004591906100c1565b61004c565b005b7f2ad1127294a42a5200f9832aacf01f051e55151abd09c0d2a055e56b214ebd4c8160405161007b91906100fd565b60405180910390a150565b600080fd5b6000819050919050565b61009e8161008b565b81146100a957600080fd5b50565b6000813590506100bb81610095565b92915050565b6000602082840312156100d7576100d6610086565b5b60006100e5848285016100ac565b91505092915050565b6100f78161008b565b82525050565b600060208201905061011260008301846100ee565b9291505056fea2646970667358221220bf22606c5b554878a183eb94c6d8d4f82fce03670d1285d5b85d2cc78ad83f2164736f6c63430008140033",
35 |   "linkReferences": {},
36 |   "deployedLinkReferences": {}
37 | }
38 | 
```

--------------------------------------------------------------------------------
/tests/ast/using_for_directive.json:
--------------------------------------------------------------------------------

```json
1 | {"absolutePath":"a","exportedSymbols":{"C":[13],"L":[4],"f":[10]},"id":14,"nodeType":"SourceUnit","nodes":[{"functionList":[{"function":{"id":1,"name":"f","nameLocations":["7:1:1"],"nodeType":"IdentifierPath","referencedDeclaration":10,"src":"7:1:1"}}],"global":false,"id":3,"nodeType":"UsingForDirective","src":"0:19:1","typeName":{"id":2,"name":"uint","nodeType":"ElementaryTypeName","src":"14:4:1","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}},{"abstract":false,"baseContracts":[],"canonicalName":"L","contractDependencies":[],"contractKind":"library","fullyImplemented":true,"id":4,"linearizedBaseContracts":[4],"name":"L","nameLocation":"28:1:1","nodeType":"ContractDefinition","nodes":[],"scope":14,"src":"20:12:1","usedErrors":[]},{"body":{"id":9,"nodeType":"Block","src":"50:2:1","statements":[]},"id":10,"implemented":true,"kind":"freeFunction","modifiers":[],"name":"f","nameLocation":"42:1:1","nodeType":"FunctionDefinition","parameters":{"id":7,"nodeType":"ParameterList","parameters":[{"constant":false,"id":6,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":10,"src":"44:4:1","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":5,"name":"uint","nodeType":"ElementaryTypeName","src":"44:4:1","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"src":"43:6:1"},"returnParameters":{"id":8,"nodeType":"ParameterList","parameters":[],"src":"50:0:1"},"scope":14,"src":"33:19:1","stateMutability":"nonpayable","virtual":false,"visibility":"internal"},{"abstract":false,"baseContracts":[],"canonicalName":"C","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":13,"linearizedBaseContracts":[13],"name":"C","nameLocation":"62:1:1","nodeType":"ContractDefinition","nodes":[{"global":false,"id":12,"libraryName":{"id":11,"name":"L","nameLocations":["72:1:1"],"nodeType":"IdentifierPath","referencedDeclaration":4,"src":"72:1:1"},"nodeType":"UsingForDirective","src":"66:14:1"}],"scope":14,"src":"53:29:1","usedErrors":[]}],"src":"0:83:1"}
2 | 
```

--------------------------------------------------------------------------------
/tests/ast/switch.json:
--------------------------------------------------------------------------------

```json
1 | {"absolutePath":"a","exportedSymbols":{"C":[6]},"id":7,"nodeType":"SourceUnit","nodes":[{"abstract":false,"baseContracts":[],"canonicalName":"C","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":6,"linearizedBaseContracts":[6],"name":"C","nameLocation":"9:1:1","nodeType":"ContractDefinition","nodes":[{"body":{"id":4,"nodeType":"Block","src":"42:154:1","statements":[{"AST":{"nodeType":"YulBlock","src":"61:129:1","statements":[{"nodeType":"YulVariableDeclaration","src":"75:10:1","value":{"kind":"number","nodeType":"YulLiteral","src":"84:1:1","type":"","value":"0"},"variables":[{"name":"v","nodeType":"YulTypedName","src":"79:1:1","type":""}]},{"cases":[{"body":{"nodeType":"YulBlock","src":"139:10:1","statements":[{"nodeType":"YulAssignment","src":"141:6:1","value":{"kind":"number","nodeType":"YulLiteral","src":"146:1:1","type":"","value":"1"},"variableNames":[{"name":"v","nodeType":"YulIdentifier","src":"141:1:1"}]}]},"nodeType":"YulCase","src":"132:17:1","value":{"kind":"number","nodeType":"YulLiteral","src":"137:1:1","type":"","value":"0"}},{"body":{"nodeType":"YulBlock","src":"170:10:1","statements":[{"nodeType":"YulAssignment","src":"172:6:1","value":{"kind":"number","nodeType":"YulLiteral","src":"177:1:1","type":"","value":"2"},"variableNames":[{"name":"v","nodeType":"YulIdentifier","src":"172:1:1"}]}]},"nodeType":"YulCase","src":"162:18:1","value":"default"}],"expression":{"arguments":[],"functionName":{"name":"calldatasize","nodeType":"YulIdentifier","src":"105:12:1"},"nodeType":"YulFunctionCall","src":"105:14:1"},"nodeType":"YulSwitch","src":"98:82:1"}]},"evmVersion":"london","externalReferences":[],"id":3,"nodeType":"InlineAssembly","src":"52:138:1"}]},"functionSelector":"26121ff0","id":5,"implemented":true,"kind":"function","modifiers":[],"name":"f","nameLocation":"26:1:1","nodeType":"FunctionDefinition","parameters":{"id":1,"nodeType":"ParameterList","parameters":[],"src":"27:2:1"},"returnParameters":{"id":2,"nodeType":"ParameterList","parameters":[],"src":"42:0:1"},"scope":6,"src":"17:179:1","stateMutability":"pure","virtual":false,"visibility":"public"}],"scope":7,"src":"0:198:1","usedErrors":[]}],"src":"0:199:1"}
2 | 
```

--------------------------------------------------------------------------------
/tests/ast/source_location.json:
--------------------------------------------------------------------------------

```json
1 | {"absolutePath":"a","exportedSymbols":{"C":[12]},"id":13,"nodeType":"SourceUnit","nodes":[{"abstract":false,"baseContracts":[],"canonicalName":"C","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":12,"linearizedBaseContracts":[12],"name":"C","nameLocation":"9:1:1","nodeType":"ContractDefinition","nodes":[{"body":{"id":10,"nodeType":"Block","src":"33:20:1","statements":[{"assignments":[4],"declarations":[{"constant":false,"id":4,"mutability":"mutable","name":"x","nameLocation":"40:1:1","nodeType":"VariableDeclaration","scope":10,"src":"35:6:1","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":3,"name":"uint","nodeType":"ElementaryTypeName","src":"35:4:1","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"id":6,"initialValue":{"hexValue":"32","id":5,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"44:1:1","typeDescriptions":{"typeIdentifier":"t_rational_2_by_1","typeString":"int_const 2"},"value":"2"},"nodeType":"VariableDeclarationStatement","src":"35:10:1"},{"expression":{"id":8,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"47:3:1","subExpression":{"id":7,"name":"x","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":4,"src":"47:1:1","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":9,"nodeType":"ExpressionStatement","src":"47:3:1"}]},"functionSelector":"26121ff0","id":11,"implemented":true,"kind":"function","modifiers":[],"name":"f","nameLocation":"22:1:1","nodeType":"FunctionDefinition","parameters":{"id":1,"nodeType":"ParameterList","parameters":[],"src":"23:2:1"},"returnParameters":{"id":2,"nodeType":"ParameterList","parameters":[],"src":"33:0:1"},"scope":12,"src":"13:40:1","stateMutability":"nonpayable","virtual":false,"visibility":"public"}],"scope":13,"src":"0:55:1","usedErrors":[]}],"src":"0:56:1"}
2 | 
```

--------------------------------------------------------------------------------
/aderyn_core/tests/common/closest_ancestor.rs:
--------------------------------------------------------------------------------

```rust
 1 | #![allow(clippy::collapsible_match)]
 2 | use std::{collections::BTreeMap, error::Error};
 3 | 
 4 | use aderyn_core::{
 5 |     ast::{NodeID, NodeType},
 6 |     capture,
 7 |     context::{
 8 |         browser::GetClosestAncestorOfTypeX,
 9 |         workspace::{ASTNode, WorkspaceContext},
10 |     },
11 |     detect::detector::{IssueDetector, IssueDetectorNamePool, IssueSeverity},
12 | };
13 | use eyre::Result;
14 | 
15 | #[derive(Default)]
16 | pub struct ClosestAncestorDemonstrator {
17 |     // Keys are: [0] source file name, [1] line number, [2] character location of node.
18 |     // Do not add items manually, use `capture!` to add nodes to this BTreeMap.
19 |     found_instances: BTreeMap<(String, usize, String), NodeID>,
20 | }
21 | 
22 | /*
23 | 
24 | In ParentChainContract.sol, there is only 1 assignment done. The goal is to capture it first, second and third parent
25 | */
26 | 
27 | impl IssueDetector for ClosestAncestorDemonstrator {
28 |     fn detect(&mut self, context: &WorkspaceContext) -> Result<bool, Box<dyn Error>> {
29 |         for assignment in context.assignments() {
30 |             capture!(self, context, assignment);
31 | 
32 |             if let Some(ASTNode::Block(block)) =
33 |                 assignment.closest_ancestor_of_type(context, NodeType::Block)
34 |             {
35 |                 capture!(self, context, block);
36 |             }
37 | 
38 |             if let Some(for_statement) =
39 |                 assignment.closest_ancestor_of_type(context, NodeType::ForStatement)
40 |             {
41 |                 capture!(self, context, for_statement);
42 | 
43 |                 if let Some(ASTNode::Block(block)) =
44 |                     for_statement.closest_ancestor_of_type(context, NodeType::Block)
45 |                 {
46 |                     capture!(self, context, block);
47 |                 }
48 |             }
49 |         }
50 | 
51 |         Ok(!self.found_instances.is_empty())
52 |     }
53 | 
54 |     fn severity(&self) -> IssueSeverity {
55 |         IssueSeverity::High
56 |     }
57 | 
58 |     fn title(&self) -> String {
59 |         String::from("Closest Parent Demonstrator")
60 |     }
61 | 
62 |     fn description(&self) -> String {
63 |         String::from("Closest Parent Demonstrator")
64 |     }
65 | 
66 |     fn instances(&self) -> BTreeMap<(String, usize, String), NodeID> {
67 |         self.found_instances.clone()
68 |     }
69 | 
70 |     fn name(&self) -> String {
71 |         format!("{}", IssueDetectorNamePool::CentralizationRisk)
72 |     }
73 | }
74 | 
```

--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------

```toml
 1 | [workspace]
 2 | resolver="2"
 3 | 
 4 | members = [
 5 |     "aderyn",
 6 |     "aderyn_core",
 7 |     "aderyn_driver",
 8 |     "tools/*",
 9 | ]
10 | 
11 | [workspace.package]
12 | edition = "2024"
13 | authors = ["Cyfrin <[email protected]>"]
14 | description = "Rust based Solidity AST analyzer backend"
15 | license = "MIT"
16 | repository = "https://github.com/cyfrin/aderyn"
17 | homepage = "https://github.com/cyfrin/aderyn"
18 | 
19 | [workspace.lints.clippy]
20 | large_enum_variant = "allow"
21 | result_large_err = "allow"
22 | 
23 | [workspace.dependencies]
24 | aderyn_core = { version = "0.6.5", path = "aderyn_core" }
25 | aderyn_driver = { version = "0.6.5", path = "aderyn_driver" }
26 | indoc = "2"
27 | clap = "4.4.6"
28 | criterion = "0.5.1"
29 | derive_more = "2"
30 | eyre = "0.6.12"
31 | field_access = "0.1.8"
32 | ignore = "0.4.21"
33 | lazy-regex = "3.2.0"
34 | log = "0.4.22"
35 | notify-debouncer-full = "0.3.1"
36 | num-bigint = "0.4"
37 | num-traits = "0.2"
38 | once_cell = "1.19.0"
39 | phf = "0.11.2"
40 | prettytable = "0.10.0"
41 | rayon = "1.8.0"
42 | reqwest = { version = "0.12.2", default-features = false }
43 | semver = "1.0.26"
44 | serde = "1.0.160"
45 | serde-sarif = "0.4.2"
46 | serde_json = "1.0.96"
47 | serde_repr = "0.1.12"
48 | serial_test = "3.0.0"
49 | strum = "0.26"
50 | termcolor = "1.4.1"
51 | tokio = "1.40.0"
52 | toml = "0.8.13"
53 | tower-lsp = "0.20.0"
54 | dunce = "=1.0.5"
55 | petgraph = "0"
56 | crossbeam-channel = "0.5.15"
57 | webbrowser = "1.0.4"
58 | urlencoding = "2.1.3"
59 | derive_builder = "0.20.2"
60 | rmcp = { version = "0.6", features = ["transport-streamable-http-server"] }
61 | axum = { version = "0.8", features = ["macros"] }
62 | askama = { version = "0.14.0", features = ["full"] }
63 | clap_complete = "4.4"
64 | regex = "1.12.2"
65 | 
66 | # Uncomment in Production (just before merging to dev)
67 | # Cyfrin managed github repository
68 | solidity_ast = { git = "https://github.com/Cyfrin/solidity-ast-rs", tag = "v0.0.1-alpha.beta.5", package = "solidity-ast" }
69 | 
70 | # Uncomment when debugging in branch (PR)
71 | # solidity_ast = { git = "https://github.com/Cyfrin/solidity-ast-rs", branch = "main", package = "solidity-ast" }
72 | 
73 | # Uncomment when debuggin locally
74 | # solidity_ast = { path = "../solidity-ast-rs", package = "solidity-ast"}
75 | 
76 | [profile.release]
77 | codegen-units = 1
78 | lto = true
79 | 
80 | [profile.lspdev]
81 | inherits = "dist"
82 | 
83 | [profile.lspdev.package."*"]
84 | inherits = "dist"
85 | 
86 | # The profile that 'dist' will build with
87 | [profile.dist]
88 | inherits = "release"
89 | lto = "thin"
90 | 
```

--------------------------------------------------------------------------------
/aderyn_core/src/detect/high/rtlo.rs:
--------------------------------------------------------------------------------

```rust
 1 | use std::{collections::BTreeMap, error::Error};
 2 | 
 3 | use crate::ast::NodeID;
 4 | 
 5 | use crate::{
 6 |     capture,
 7 |     context::workspace::WorkspaceContext,
 8 |     detect::detector::{IssueDetector, IssueDetectorNamePool, IssueSeverity},
 9 | };
10 | use eyre::Result;
11 | 
12 | #[derive(Default)]
13 | pub struct RTLODetector {
14 |     // Keys are: [0] source file name, [1] line number, [2] character location of node.
15 |     // Do not add items manually, use `capture!` to add nodes to this BTreeMap.
16 |     found_instances: BTreeMap<(String, usize, String), NodeID>,
17 | }
18 | 
19 | impl IssueDetector for RTLODetector {
20 |     fn detect(&mut self, context: &WorkspaceContext) -> Result<bool, Box<dyn Error>> {
21 |         // When you have found an instance of the issue,
22 |         // use the following macro to add it to `found_instances`:
23 |         //
24 |         // capture!(self, context, item);
25 | 
26 |         for source_unit in context.source_units() {
27 |             if let Some(content) = &source_unit.source
28 |                 && content.contains('\u{202e}')
29 |             {
30 |                 capture!(self, context, source_unit);
31 |             }
32 |         }
33 | 
34 |         Ok(!self.found_instances.is_empty())
35 |     }
36 | 
37 |     fn severity(&self) -> IssueSeverity {
38 |         IssueSeverity::High
39 |     }
40 | 
41 |     fn title(&self) -> String {
42 |         String::from("RTLO character detected in file: \\u{202e}")
43 |     }
44 | 
45 |     fn description(&self) -> String {
46 |         String::from(
47 |             "The right to left override character may be misleading and cause potential attacks by visually misordering method arguments.",
48 |         )
49 |     }
50 | 
51 |     fn instances(&self) -> BTreeMap<(String, usize, String), NodeID> {
52 |         self.found_instances.clone()
53 |     }
54 | 
55 |     fn name(&self) -> String {
56 |         IssueDetectorNamePool::RTLO.to_string()
57 |     }
58 | }
59 | 
60 | #[cfg(test)]
61 | mod rtlo_detector_tests {
62 | 
63 |     use crate::detect::{detector::IssueDetector, high::rtlo::RTLODetector};
64 | 
65 |     #[test]
66 | 
67 |     fn test_rtlo_detector() {
68 |         let context = crate::detect::test_utils::load_solidity_source_unit(
69 |             "../tests/contract-playground/src/RTLO.sol",
70 |         );
71 | 
72 |         let mut detector = RTLODetector::default();
73 |         let found = detector.detect(&context).unwrap();
74 |         assert!(found);
75 |         assert_eq!(detector.instances().len(), 1);
76 |     }
77 | }
78 | 
```

--------------------------------------------------------------------------------
/aderyn_core/src/context/mcp.rs:
--------------------------------------------------------------------------------

```rust
 1 | // Imports
 2 | use crate::context::{macros::make_route, workspace::WorkspaceContext};
 3 | use rmcp::{
 4 |     ErrorData as McpError,
 5 |     handler::server::{tool::ToolRoute, wrapper::Parameters},
 6 |     model::*,
 7 |     schemars::JsonSchema,
 8 | };
 9 | use solidity_ast::ProjectConfigInput;
10 | use std::{any::Any, path::PathBuf, sync::Arc};
11 | use strum::{Display, EnumString};
12 | 
13 | // Tools
14 | pub mod callgraph;
15 | pub mod contract_surface;
16 | pub mod list_contracts;
17 | pub mod node_finder;
18 | pub mod node_summarizer;
19 | pub mod project_overview;
20 | pub mod tool_guide;
21 | 
22 | pub use callgraph::CallgraphTool;
23 | pub use contract_surface::ContractSurfaceTool;
24 | pub use list_contracts::ListContractsTool;
25 | pub use node_finder::NodeFinderTool;
26 | pub use node_summarizer::NodeSummarizerTool;
27 | pub use project_overview::ProjectOverviewTool;
28 | pub use tool_guide::ToolGuide;
29 | 
30 | pub struct ModelContextProtocolState {
31 |     pub contexts: Vec<WorkspaceContext>,
32 |     pub root_path: PathBuf,
33 |     pub project_config: ProjectConfigInput,
34 | }
35 | 
36 | pub trait ModelContextProtocolTool: Send + Sync + Clone {
37 |     type Input: JsonSchema + Any + Send;
38 | 
39 |     fn new(state: Arc<ModelContextProtocolState>) -> Self;
40 | 
41 |     // Appears to the MCP client
42 |     fn name(&self) -> String;
43 | 
44 |     // LLM uses this information to decide if this tool should be called
45 |     fn description(&self) -> String;
46 | 
47 |     // Tool execution logic
48 |     fn execute(&self, input: Parameters<Self::Input>) -> Result<CallToolResult, McpError>;
49 | }
50 | 
51 | pub fn get_all_mcp_tools<T>(state: Arc<ModelContextProtocolState>) -> Vec<ToolRoute<T>>
52 | where
53 |     T: Send + Sync + 'static,
54 | {
55 |     vec![
56 |         // register MCP tools here
57 |         make_route!(ToolGuide, state),
58 |         make_route!(ProjectOverviewTool, state),
59 |         make_route!(ListContractsTool, state),
60 |         make_route!(ContractSurfaceTool, state),
61 |         make_route!(CallgraphTool, state),
62 |         make_route!(NodeSummarizerTool, state),
63 |         make_route!(NodeFinderTool, state),
64 |     ]
65 | }
66 | 
67 | #[derive(Debug, PartialEq, EnumString, Display)]
68 | #[strum(serialize_all = "snake_case")]
69 | pub enum MCPToolNamePool {
70 |     AderynGetToolGuide,
71 |     AderynGetProjectOverview,
72 |     AderynListContracts,
73 |     AderynContractSurfaceInspector,
74 |     AderynExploreCallgraphFromEntrypoint,
75 |     AderynNodeSummarizer,
76 |     AderynNodeFinder,
77 | }
78 | 
```

--------------------------------------------------------------------------------
/aderyn_core/tests/common/immediate_children.rs:
--------------------------------------------------------------------------------

```rust
 1 | #![allow(clippy::collapsible_match)]
 2 | use std::{collections::BTreeMap, error::Error};
 3 | 
 4 | use aderyn_core::{
 5 |     ast::{NodeID, NodeType},
 6 |     capture,
 7 |     context::{browser::GetImmediateChildren, workspace::WorkspaceContext},
 8 |     detect::detector::{IssueDetector, IssueDetectorNamePool, IssueSeverity},
 9 | };
10 | use eyre::Result;
11 | 
12 | #[derive(Default)]
13 | pub struct ImmediateChildrenDemonstrator {
14 |     // Keys are: [0] source file name, [1] line number, [2] character location of node.
15 |     // Do not add items manually, use `capture!` to add nodes to this BTreeMap.
16 |     found_instances: BTreeMap<(String, usize, String), NodeID>,
17 | }
18 | 
19 | impl IssueDetector for ImmediateChildrenDemonstrator {
20 |     fn detect(&mut self, context: &WorkspaceContext) -> Result<bool, Box<dyn Error>> {
21 |         // Step 1: Find the ParentChain contract
22 | 
23 |         let parent_chain_contract = context
24 |             .contract_definitions()
25 |             .into_iter()
26 |             .filter(|x| x.name.contains("ParentChain"))
27 |             .take(1)
28 |             .next()
29 |             .unwrap();
30 | 
31 |         // Step 2: Find the `increment` function
32 | 
33 |         let inc = parent_chain_contract
34 |             .function_definitions()
35 |             .into_iter()
36 |             .filter(|x| x.name.contains("increment"))
37 |             .take(1)
38 |             .next()
39 |             .unwrap();
40 | 
41 |         if let Some(children) = inc.body.as_ref().unwrap().children(context) {
42 |             for child in children {
43 |                 assert!(
44 |                     child.node_type() == NodeType::IfStatement,
45 |                     "Only if statement should be caught in function body's immediate children!"
46 |                 );
47 |                 capture!(self, context, child);
48 |             }
49 |         }
50 | 
51 |         Ok(!self.found_instances.is_empty())
52 |     }
53 | 
54 |     fn severity(&self) -> IssueSeverity {
55 |         IssueSeverity::High
56 |     }
57 | 
58 |     fn title(&self) -> String {
59 |         String::from("ImmediateChildrenDemonstrator")
60 |     }
61 | 
62 |     fn description(&self) -> String {
63 |         String::from("ImmediateChildrenDemonstrator")
64 |     }
65 | 
66 |     fn instances(&self) -> BTreeMap<(String, usize, String), NodeID> {
67 |         self.found_instances.clone()
68 |     }
69 | 
70 |     fn name(&self) -> String {
71 |         format!("{}", IssueDetectorNamePool::CentralizationRisk)
72 |     }
73 | }
74 | 
```

--------------------------------------------------------------------------------
/RELEASE_CHECKLIST.md:
--------------------------------------------------------------------------------

```markdown
 1 | # Release checklist
 2 | 
 3 | This checklist is meant to be used as a guide for the `aderyn` release process.
 4 | 
 5 | Releases are always made in lockstep, meaning that all crates in the repository
 6 | are released with the same version number, regardless of whether they have
 7 | changed or not.
 8 | 
 9 | ## Requirements
10 | 
11 | - [cargo-release](https://github.com/crate-ci/cargo-release): `cargo install cargo-release`
12 | - [gh](https://cli.github.com/): `brew install gh`
13 | 
14 | Stay logged in with `gh auth login`
15 | 
16 | ## Pre-requisites
17 | 
18 | - Code in the `dev` branch must be in good shape for release.
19 | - If there are breaking changes, a newer version of VSCode extension is ready to be released in it's `main` branch.
20 | 
21 | ## Steps
22 | 
23 | - [ ] Cut a release.
24 |     - [ ] Switch to dev branch and pull latest changes.
25 |     - [ ] Run `cargo patch`. Wait until the command is fully done.
26 |     - [ ] Generate Release Notes in the Github's Release page
27 | 
28 | - **NOTE: Expect the following in CI**:
29 |   * Sarif report tests fail because of version mismatch.
30 |   * After the building of global artifacts, `aderyn_driver` and `aderyn_core` crates fail to publish.
31 |   * Binary crate `aderyn` is successfully published.
32 | 
33 | - [ ] Create a checkpoint on `master`.
34 |     - [ ] Run `git checkout master && git pull`
35 |     - [ ] Run `git checkout -b master-merge-<version-to-be-released>`.
36 |     - [ ] Merge `dev` into it and preserve all changes in `dev`. `git merge --squash -X theirs dev`.
37 |     - [ ] Sometimes if conflicts are not auto-resolved, pick to keep all the changes from `dev`
38 |     - [ ] Merge it back to master by creating a PR (Verify CI tests)
39 | 
40 | - [ ] Switch back to `dev` branch with `git checkout dev`.
41 | 
42 | > NOTE: Replace `patch` with `minor` based on the needs.
43 | 
44 | ## Breaking change
45 | 
46 | If at least one of the following is observed, it's considered a breaking change. In that case, the minor version must be bumped at a minimum. This ensures the VS Code extension remains compatible, as users will be prompted to install the updated version.
47 | 
48 | - [ ] Changes in CLI flags - `--lsp`, `--json`, `--stdout`
49 | - [ ] Changes in the JSON output format.
50 | - [ ] Arbitrary Changes to LSP server.
51 | - [ ] Changes to asset names or URLs in Github Releases.
52 | - [ ] Changes to `aderyn.toml` template.
53 | 
54 | Above is a non-exhaustive list There can be more.
55 | 
```

--------------------------------------------------------------------------------
/aderyn_core/src/detect/low/division_before_multiplication.rs:
--------------------------------------------------------------------------------

```rust
 1 | use std::{collections::BTreeMap, error::Error};
 2 | 
 3 | use crate::ast::NodeID;
 4 | 
 5 | use crate::{
 6 |     ast::Expression,
 7 |     capture,
 8 |     context::workspace::WorkspaceContext,
 9 |     detect::detector::{IssueDetector, IssueDetectorNamePool, IssueSeverity},
10 | };
11 | use eyre::Result;
12 | 
13 | #[derive(Default)]
14 | pub struct DivisionBeforeMultiplicationDetector {
15 |     // Keys are source file name, line number, and description
16 |     found_instances: BTreeMap<(String, usize, String), NodeID>,
17 | }
18 | 
19 | impl IssueDetector for DivisionBeforeMultiplicationDetector {
20 |     fn detect(&mut self, context: &WorkspaceContext) -> Result<bool, Box<dyn Error>> {
21 |         for op in context.binary_operations().iter().filter(|op| op.operator == "*") {
22 |             if let Expression::BinaryOperation(left_op) = op.left_expression.as_ref()
23 |                 && left_op.operator == "/"
24 |             {
25 |                 capture!(self, context, left_op)
26 |             }
27 |         }
28 | 
29 |         Ok(!self.found_instances.is_empty())
30 |     }
31 | 
32 |     fn severity(&self) -> IssueSeverity {
33 |         IssueSeverity::Low
34 |     }
35 | 
36 |     fn title(&self) -> String {
37 |         String::from("Incorrect Order of Division and Multiplication")
38 |     }
39 | 
40 |     fn description(&self) -> String {
41 |         String::from("Division operations followed directly by multiplication operations can lead to precision loss due to the way integer arithmetic is handled in Solidity./
42 |         Consider Multiplication before Division.")
43 |     }
44 | 
45 |     fn instances(&self) -> BTreeMap<(String, usize, String), NodeID> {
46 |         self.found_instances.clone()
47 |     }
48 | 
49 |     fn name(&self) -> String {
50 |         format!("{}", IssueDetectorNamePool::DivisionBeforeMultiplication)
51 |     }
52 | }
53 | 
54 | #[cfg(test)]
55 | mod division_before_multiplication_detector_tests {
56 | 
57 |     use super::DivisionBeforeMultiplicationDetector;
58 |     use crate::detect::detector::IssueDetector;
59 | 
60 |     #[test]
61 | 
62 |     fn test_template_detector() {
63 |         let context = crate::detect::test_utils::load_solidity_source_unit(
64 |             "../tests/contract-playground/src/DivisionBeforeMultiplication.sol",
65 |         );
66 | 
67 |         let mut detector = DivisionBeforeMultiplicationDetector::default();
68 |         let found = detector.detect(&context).unwrap();
69 |         assert!(found);
70 |         assert_eq!(detector.instances().len(), 4);
71 |     }
72 | }
73 | 
```

--------------------------------------------------------------------------------
/aderyn_core/src/ast/impls/node/source_units.rs:
--------------------------------------------------------------------------------

```rust
 1 | use crate::{ast::*, visitor::ast_visitor::*};
 2 | use eyre::Result;
 3 | 
 4 | impl Node for SourceUnitNode {
 5 |     fn accept(&self, visitor: &mut impl ASTConstVisitor) -> Result<()> {
 6 |         match self {
 7 |             SourceUnitNode::PragmaDirective(pragma_directive) => pragma_directive.accept(visitor),
 8 |             SourceUnitNode::ImportDirective(import_directive) => import_directive.accept(visitor),
 9 |             SourceUnitNode::ContractDefinition(contract_definition) => {
10 |                 contract_definition.accept(visitor)
11 |             }
12 |             SourceUnitNode::StructDefinition(struct_definition) => {
13 |                 struct_definition.accept(visitor)
14 |             }
15 |             SourceUnitNode::EnumDefinition(enum_definition) => enum_definition.accept(visitor),
16 |             SourceUnitNode::ErrorDefinition(error_definition) => error_definition.accept(visitor),
17 |             SourceUnitNode::VariableDeclaration(variable_declaration) => {
18 |                 variable_declaration.accept(visitor)
19 |             }
20 |             SourceUnitNode::UserDefinedValueTypeDefinition(user_defined_value_type_definition) => {
21 |                 user_defined_value_type_definition.accept(visitor)
22 |             }
23 |             SourceUnitNode::FunctionDefinition(function_defn) => function_defn.accept(visitor),
24 |             SourceUnitNode::UsingForDirective(using_for_directive) => {
25 |                 using_for_directive.accept(visitor)
26 |             }
27 |             SourceUnitNode::EventDefinition(event_definition) => event_definition.accept(visitor),
28 |         }
29 |     }
30 |     fn accept_id(&self, visitor: &mut impl ASTConstVisitor) -> Result<()> {
31 |         visitor.visit_node_id(self.get_node_id())?;
32 |         Ok(())
33 |     }
34 | }
35 | 
36 | impl Node for SourceUnit {
37 |     fn accept(&self, visitor: &mut impl ASTConstVisitor) -> Result<()> {
38 |         if visitor.visit_source_unit(self)? {
39 |             list_accept(&self.nodes, visitor)?;
40 |         }
41 |         self.accept_metadata(visitor)?;
42 |         visitor.end_visit_source_unit(self)
43 |     }
44 |     fn accept_metadata(&self, visitor: &mut impl ASTConstVisitor) -> Result<()> {
45 |         let node_ids = &self.nodes.iter().flat_map(|x| x.get_node_id()).collect::<Vec<_>>();
46 |         visitor.visit_immediate_children(self.id, node_ids.clone())?;
47 |         Ok(())
48 |     }
49 |     macros::accept_id!();
50 | }
51 | 
```

--------------------------------------------------------------------------------
/tests/ast/long_type_name_binary_operation.json:
--------------------------------------------------------------------------------

```json
1 | {"absolutePath":"a","exportedSymbols":{"c":[11]},"id":12,"nodeType":"SourceUnit","nodes":[{"abstract":false,"baseContracts":[],"canonicalName":"c","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":11,"linearizedBaseContracts":[11],"name":"c","nameLocation":"9:1:1","nodeType":"ContractDefinition","nodes":[{"body":{"id":9,"nodeType":"Block","src":"33:19:1","statements":[{"assignments":[4],"declarations":[{"constant":false,"id":4,"mutability":"mutable","name":"a","nameLocation":"40:1:1","nodeType":"VariableDeclaration","scope":9,"src":"35:6:1","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":3,"name":"uint","nodeType":"ElementaryTypeName","src":"35:4:1","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"id":8,"initialValue":{"commonType":{"typeIdentifier":"t_rational_5_by_1","typeString":"int_const 5"},"id":7,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"leftExpression":{"hexValue":"32","id":5,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"44:1:1","typeDescriptions":{"typeIdentifier":"t_rational_2_by_1","typeString":"int_const 2"},"value":"2"},"nodeType":"BinaryOperation","operator":"+","rightExpression":{"hexValue":"33","id":6,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"48:1:1","typeDescriptions":{"typeIdentifier":"t_rational_3_by_1","typeString":"int_const 3"},"value":"3"},"src":"44:5:1","typeDescriptions":{"typeIdentifier":"t_rational_5_by_1","typeString":"int_const 5"}},"nodeType":"VariableDeclarationStatement","src":"35:14:1"}]},"functionSelector":"26121ff0","id":10,"implemented":true,"kind":"function","modifiers":[],"name":"f","nameLocation":"22:1:1","nodeType":"FunctionDefinition","parameters":{"id":1,"nodeType":"ParameterList","parameters":[],"src":"23:2:1"},"returnParameters":{"id":2,"nodeType":"ParameterList","parameters":[],"src":"33:0:1"},"scope":11,"src":"13:39:1","stateMutability":"nonpayable","virtual":false,"visibility":"public"}],"scope":12,"src":"0:54:1","usedErrors":[]}],"src":"0:55:1"}
2 | 
```

--------------------------------------------------------------------------------
/aderyn_core/src/detect/high/dangerous_unary_operator.rs:
--------------------------------------------------------------------------------

```rust
 1 | use std::{collections::BTreeMap, error::Error};
 2 | 
 3 | use crate::ast::NodeID;
 4 | 
 5 | use crate::{
 6 |     capture,
 7 |     context::{browser::Peek, workspace::WorkspaceContext},
 8 |     detect::detector::{IssueDetector, IssueDetectorNamePool, IssueSeverity},
 9 | };
10 | use eyre::Result;
11 | 
12 | #[derive(Default)]
13 | pub struct DangerousUnaryOperatorDetector {
14 |     // Keys are: [0] source file name, [1] line number, [2] character location of node.
15 |     // Do not add items manually, use `capture!` to add nodes to this BTreeMap.
16 |     found_instances: BTreeMap<(String, usize, String), NodeID>,
17 | }
18 | 
19 | impl IssueDetector for DangerousUnaryOperatorDetector {
20 |     fn detect(&mut self, context: &WorkspaceContext) -> Result<bool, Box<dyn Error>> {
21 |         for assignment in context.assignments() {
22 |             if let Some(content) = assignment.peek(context)
23 |                 && (content.contains("=-") || content.contains("=+"))
24 |             {
25 |                 capture!(self, context, assignment);
26 |             }
27 |         }
28 | 
29 |         Ok(!self.found_instances.is_empty())
30 |     }
31 | 
32 |     fn severity(&self) -> IssueSeverity {
33 |         IssueSeverity::High
34 |     }
35 | 
36 |     fn title(&self) -> String {
37 |         String::from("Dangerous unary operator")
38 |     }
39 | 
40 |     fn description(&self) -> String {
41 |         String::from(
42 |             "Potentially mistaken `=+` for `+=` or `=-` for `-=`. This acts as an assignment instead of an increment or decrement.\
43 |         Use the correct operator to increment or decrement a variable.",
44 |         )
45 |     }
46 | 
47 |     fn instances(&self) -> BTreeMap<(String, usize, String), NodeID> {
48 |         self.found_instances.clone()
49 |     }
50 | 
51 |     fn name(&self) -> String {
52 |         IssueDetectorNamePool::DangerousUnaryOperator.to_string()
53 |     }
54 | }
55 | 
56 | #[cfg(test)]
57 | mod dangerous_unary_expression_tests {
58 | 
59 |     use crate::detect::{
60 |         detector::IssueDetector, high::dangerous_unary_operator::DangerousUnaryOperatorDetector,
61 |     };
62 | 
63 |     #[test]
64 |     fn test_dangerous_unary_operator() {
65 |         let context = crate::detect::test_utils::load_solidity_source_unit(
66 |             "../tests/contract-playground/src/DangerousUnaryOperator.sol",
67 |         );
68 | 
69 |         let mut detector = DangerousUnaryOperatorDetector::default();
70 |         let found = detector.detect(&context).unwrap();
71 | 
72 |         assert!(found);
73 |         assert_eq!(detector.instances().len(), 2);
74 |     }
75 | }
76 | 
```

--------------------------------------------------------------------------------
/aderyn_core/src/context/browser/location.rs:
--------------------------------------------------------------------------------

```rust
 1 | use std::cmp::Ordering;
 2 | 
 3 | use crate::{
 4 |     ast::NodeID,
 5 |     context::workspace::WorkspaceContext,
 6 |     visitor::ast_visitor::{ASTConstVisitor, Node},
 7 | };
 8 | 
 9 | pub trait AppearsAfterNodeLocation<T: Node + ?Sized> {
10 |     fn appears_after(&self, context: &WorkspaceContext, other: &T) -> Option<bool>;
11 | }
12 | 
13 | pub trait AppearsBeforeNodeLocation<T: Node + ?Sized> {
14 |     fn appears_before(&self, context: &WorkspaceContext, other: &T) -> Option<bool>;
15 | }
16 | 
17 | #[derive(Default)]
18 | struct NodeIDReceiver {
19 |     id: Option<NodeID>,
20 | }
21 | 
22 | impl ASTConstVisitor for NodeIDReceiver {
23 |     fn visit_node_id(&mut self, node_id: Option<NodeID>) -> eyre::Result<()> {
24 |         self.id = node_id;
25 |         Ok(())
26 |     }
27 | }
28 | 
29 | impl<T: Node + ?Sized, U: Node + ?Sized> AppearsBeforeNodeLocation<U> for T {
30 |     fn appears_before(&self, context: &WorkspaceContext, other: &U) -> Option<bool> {
31 |         // Setup a Node ID receiver
32 |         let mut node_id_receiver = NodeIDReceiver::default();
33 | 
34 |         // Find the ID of the node this method is called upon
35 |         self.accept_id(&mut node_id_receiver).ok()?;
36 |         let current_node_id = node_id_receiver.id?;
37 | 
38 |         // FInd the ID of the target node
39 |         other.accept_id(&mut node_id_receiver).ok()?;
40 |         let target_node_id = node_id_receiver.id?;
41 | 
42 |         match context.get_relative_location_of_nodes(current_node_id, target_node_id)? {
43 |             Ordering::Less => Some(true),
44 |             Ordering::Greater => Some(false),
45 |             Ordering::Equal => Some(false),
46 |         }
47 |     }
48 | }
49 | 
50 | impl<T: Node + ?Sized, U: Node + ?Sized> AppearsAfterNodeLocation<U> for T {
51 |     fn appears_after(&self, context: &WorkspaceContext, other: &U) -> Option<bool> {
52 |         // Setup a Node ID receiver
53 |         let mut node_id_receiver = NodeIDReceiver::default();
54 | 
55 |         // Find the ID of the node this method is called upon
56 |         self.accept_id(&mut node_id_receiver).ok()?;
57 |         let current_node_id = node_id_receiver.id?;
58 | 
59 |         // FInd the ID of the target node
60 |         other.accept_id(&mut node_id_receiver).ok()?;
61 |         let target_node_id = node_id_receiver.id?;
62 | 
63 |         match context.get_relative_location_of_nodes(current_node_id, target_node_id)? {
64 |             Ordering::Less => Some(false),
65 |             Ordering::Greater => Some(true),
66 |             Ordering::Equal => Some(false),
67 |         }
68 |     }
69 | }
70 | 
```

--------------------------------------------------------------------------------
/aderyn_core/src/detect/high/experimental_encoder.rs:
--------------------------------------------------------------------------------

```rust
 1 | use std::{collections::BTreeMap, error::Error};
 2 | 
 3 | use crate::ast::NodeID;
 4 | 
 5 | use crate::{
 6 |     capture,
 7 |     context::workspace::WorkspaceContext,
 8 |     detect::detector::{IssueDetector, IssueDetectorNamePool, IssueSeverity},
 9 | };
10 | use eyre::Result;
11 | 
12 | #[derive(Default)]
13 | pub struct ExperimentalEncoderDetector {
14 |     // Keys are: [0] source file name, [1] line number, [2] character location of node.
15 |     // Do not add items manually, use `capture!` to add nodes to this BTreeMap.
16 |     found_instances: BTreeMap<(String, usize, String), NodeID>,
17 | }
18 | 
19 | impl IssueDetector for ExperimentalEncoderDetector {
20 |     fn detect(&mut self, context: &WorkspaceContext) -> Result<bool, Box<dyn Error>> {
21 |         for pragma_directive in context.pragma_directives() {
22 |             for literal in &pragma_directive.literals {
23 |                 if literal == "experimental" {
24 |                     capture!(self, context, pragma_directive);
25 |                 }
26 |             }
27 |         }
28 | 
29 |         Ok(!self.found_instances.is_empty())
30 |     }
31 | 
32 |     fn severity(&self) -> IssueSeverity {
33 |         IssueSeverity::High
34 |     }
35 | 
36 |     fn title(&self) -> String {
37 |         String::from("Experimental ABI Encoder")
38 |     }
39 | 
40 |     fn description(&self) -> String {
41 |         String::from(
42 |             "Experimental encoders should not be used in production. There are multiple known compiler bugs that are caused by the experimental encoder. Upgrade your solidity version to remove the need for experimental features.",
43 |         )
44 |     }
45 | 
46 |     fn instances(&self) -> BTreeMap<(String, usize, String), NodeID> {
47 |         self.found_instances.clone()
48 |     }
49 | 
50 |     fn name(&self) -> String {
51 |         IssueDetectorNamePool::ExperimentalEncoder.to_string()
52 |     }
53 | }
54 | 
55 | #[cfg(test)]
56 | mod storage_array_encode_compiler_bug_detector_tests {
57 | 
58 |     use crate::detect::{
59 |         detector::IssueDetector, high::experimental_encoder::ExperimentalEncoderDetector,
60 |     };
61 | 
62 |     #[test]
63 | 
64 |     fn test_storage_array_encode_compiler_bug_detector() {
65 |         let context = crate::detect::test_utils::load_solidity_source_unit(
66 |             "../tests/contract-playground/src/ExperimentalEncoder.sol",
67 |         );
68 | 
69 |         let mut detector = ExperimentalEncoderDetector::default();
70 |         let found = detector.detect(&context).unwrap();
71 |         assert!(found);
72 |         assert_eq!(detector.instances().len(), 1);
73 |     }
74 | }
75 | 
```

--------------------------------------------------------------------------------
/aderyn_core/src/ast/impls/disp/functions.rs:
--------------------------------------------------------------------------------

```rust
 1 | use crate::ast::*;
 2 | use std::fmt::Display;
 3 | 
 4 | impl Display for FunctionKind {
 5 |     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 6 |         f.write_fmt(format_args!("{}", format!("{self:?}").to_lowercase()))
 7 |     }
 8 | }
 9 | 
10 | impl Display for ParameterList {
11 |     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
12 |         f.write_str("(")?;
13 | 
14 |         for (i, parameter) in self.parameters.iter().enumerate() {
15 |             if i > 0 {
16 |                 f.write_str(", ")?;
17 |             }
18 | 
19 |             f.write_fmt(format_args!("{parameter}"))?;
20 |         }
21 | 
22 |         f.write_str(")")
23 |     }
24 | }
25 | 
26 | impl Display for OverrideSpecifier {
27 |     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28 |         f.write_str("override")?;
29 | 
30 |         if !self.overrides.is_empty() {
31 |             f.write_str("(")?;
32 | 
33 |             for (i, identifier_path) in self.overrides.iter().enumerate() {
34 |                 if i > 0 {
35 |                     f.write_str(", ")?;
36 |                 }
37 | 
38 |                 f.write_fmt(format_args!("{:?}", identifier_path))?;
39 |             }
40 | 
41 |             f.write_str(")")?;
42 |         }
43 | 
44 |         Ok(())
45 |     }
46 | }
47 | 
48 | impl Display for FunctionDefinition {
49 |     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50 |         f.write_fmt(format_args!("{}", self.kind()))?;
51 | 
52 |         if !self.name.is_empty() {
53 |             f.write_fmt(format_args!(" {}", self.name))?;
54 |         }
55 | 
56 |         f.write_fmt(format_args!("{} {}", self.parameters, self.visibility))?;
57 | 
58 |         if let Some(state_mutability) = &self.state_mutability
59 |             && *state_mutability != StateMutability::NonPayable
60 |         {
61 |             f.write_fmt(format_args!(" {}", state_mutability))?;
62 |         }
63 | 
64 |         if self.is_virtual {
65 |             f.write_str(" virtual")?;
66 |         }
67 | 
68 |         if let Some(overrides) = self.overrides.as_ref() {
69 |             f.write_fmt(format_args!(" {overrides}"))?;
70 |         }
71 | 
72 |         for modifier in self.modifiers.iter() {
73 |             f.write_fmt(format_args!(" {modifier}"))?;
74 |         }
75 | 
76 |         if !self.return_parameters.parameters.is_empty() {
77 |             f.write_fmt(format_args!(" returns {}", self.return_parameters))?;
78 |         }
79 | 
80 |         match self.body.as_ref() {
81 |             Some(body) => f.write_fmt(format_args!(" {body}")),
82 |             None => f.write_str(";"),
83 |         }
84 |     }
85 | }
86 | 
```

--------------------------------------------------------------------------------
/aderyn_core/templates/mcp-tool-response/callgraph.md:
--------------------------------------------------------------------------------

```markdown
 1 | ## Callgraph for {{ contract.name }} contract when traversed from {{ entrypoint_function.name }}
 2 | 
 3 | *Compilation Unit index:* {{ compilation_unit_index }}
 4 | 
 5 | *Contract:* {{ contract.name }} | Node ID: {{ contract.node_id }}
 6 | 
 7 | *Entrypoint function:* {{ entrypoint_function.name }} | Node ID: {{ entrypoint_function.node_id }}
 8 | 
 9 | Below is a adjacency list representation of the subgraph of {{ contract.name }}'s callgraph. It covers all function or modifiers nodes reachable when we start traversal from the single entrypoint function `{{ entrypoint_function.name }}`   with Node ID: {{ entrypoint_function.node_id }}
10 | 
11 | **Note:** This represents only the portion of {{ contract.name }}'s complete callgraph that is reachable from this specific entrypoint. Other public/external functions in the contract and their call chains are not included unless they are called by `{{ entrypoint_function.name }}`.
12 | 
13 | Every number in the adjacency list is a Node ID of a function or a modifier node.
14 | For example, if there is an edge from `A->B` (i.e A calls B) and `A->C` (A calls C), it would be represented as *A -> B, C*
15 | 
16 | ### Adjacency List Graph of NodeIDs
17 | 
18 | {% for (from, to_list) in &graph %}
19 | {% if to_list.len() > 0 %}
20 | - {{ from }} -> {% for (i, v) in to_list.iter().enumerate() %} {{ v }}{% if i != to_list.len() %},{% endif %} {% endfor %}
21 | {% else %}
22 | - {{ from }} -> *empty*
23 | {% endif %}
24 | {% endfor %}
25 | 
26 | ### Reverse Post Order of nodes in the above graph and their corresponding Node IDs
27 | 
28 | {% for node in post_order_nodes.iter().rev() %}
29 | **{{ node.name }} ({{ node.node_id }})** calls:
30 | {% if node.called_nodes.len() == 0 %}
31 |   - No subsequent calls found
32 | {% else %}
33 | {% for called_node in node.called_nodes %}
34 |   - {{ called_node.name }} ({{ called_node.node_id }})
35 | {% endfor %}
36 | {% endif %}
37 | {% endfor %}
38 | 
39 | The above order provides an approximation of the actual flow of data when a transaction reaches {{ entrypoint_function.name }} The infamouse LLVM project uses this technique to perform analysis so it is a very useful piece of information.
40 | 
41 | ### Next steps:
42 | It is maybe helpful to now run the node summarizer tool on function nodes and modifier nodes in the above output. That gives access to the source code and some potentially interesting metadata concerning those functions. To invoke the tool you have to pass the compilation unit index and the node ID mentioned above.
43 | 
```

--------------------------------------------------------------------------------
/aderyn_core/src/context/browser/siblings.rs:
--------------------------------------------------------------------------------

```rust
 1 | use crate::{
 2 |     ast::*,
 3 |     context::workspace::{ASTNode, WorkspaceContext},
 4 |     visitor::ast_visitor::{ASTConstVisitor, Node},
 5 | };
 6 | 
 7 | use super::{GetImmediateChildren, SortNodeReferencesToSequence};
 8 | 
 9 | pub trait GetNextSibling {
10 |     /// Get the next sibling an ASTNode
11 |     fn next_sibling<'a>(&self, context: &'a WorkspaceContext) -> Option<&'a ASTNode>;
12 | }
13 | 
14 | pub trait GetPreviousSibling {
15 |     /// Get the previous sibling an ASTNode
16 |     fn previous_sibling<'a>(&self, context: &'a WorkspaceContext) -> Option<&'a ASTNode>;
17 | }
18 | 
19 | #[derive(Default)]
20 | struct NodeIDReceiver {
21 |     id: Option<NodeID>,
22 | }
23 | 
24 | impl ASTConstVisitor for NodeIDReceiver {
25 |     fn visit_node_id(&mut self, node_id: Option<NodeID>) -> eyre::Result<()> {
26 |         self.id = node_id;
27 |         Ok(())
28 |     }
29 | }
30 | 
31 | impl<T: Node + ?Sized> GetNextSibling for T {
32 |     fn next_sibling<'a>(&self, context: &'a WorkspaceContext) -> Option<&'a ASTNode> {
33 |         // Setup a Node ID receiver
34 |         let mut node_id_receiver = NodeIDReceiver::default();
35 | 
36 |         // Find the ID of the node this method is called upon
37 |         self.accept_id(&mut node_id_receiver).ok()?;
38 |         let current_node_id = node_id_receiver.id?;
39 | 
40 |         let parent = context.get_parent(current_node_id)?;
41 |         let children = parent.children(context)?;
42 |         let sorted_children = children.sort_by_src_position(context)?;
43 | 
44 |         for i in 0..sorted_children.len() - 1 {
45 |             if sorted_children[i].id()? == current_node_id {
46 |                 return Some(sorted_children[i + 1]);
47 |             }
48 |         }
49 | 
50 |         None
51 |     }
52 | }
53 | 
54 | impl<T: Node + ?Sized> GetPreviousSibling for T {
55 |     fn previous_sibling<'a>(&self, context: &'a WorkspaceContext) -> Option<&'a ASTNode> {
56 |         // Setup a Node ID receiver
57 |         let mut node_id_receiver = NodeIDReceiver::default();
58 | 
59 |         // Find the ID of the node this method is called upon
60 |         self.accept_id(&mut node_id_receiver).ok()?;
61 |         let current_node_id = node_id_receiver.id?;
62 | 
63 |         let parent = context.get_parent(current_node_id)?;
64 |         let children = parent.children(context)?;
65 |         let sorted_children = children.sort_by_src_position(context)?;
66 | 
67 |         for i in (1..sorted_children.len()).rev() {
68 |             if sorted_children[i].id()? == current_node_id {
69 |                 return Some(sorted_children[i - 1]);
70 |             }
71 |         }
72 | 
73 |         None
74 |     }
75 | }
76 | 
```

--------------------------------------------------------------------------------
/aderyn_core/src/context/graph/callgraph/legacy.rs:
--------------------------------------------------------------------------------

```rust
 1 | use crate::{
 2 |     ast::{NodeID, NodeType},
 3 |     context::{
 4 |         browser::{ExtractReferencedDeclarations, GetClosestAncestorOfTypeX},
 5 |         workspace::{ASTNode, WorkspaceContext},
 6 |     },
 7 | };
 8 | 
 9 | pub(super) fn derive_outward_surface_points(
10 |     context: &WorkspaceContext,
11 |     nodes: &[&ASTNode],
12 | ) -> Vec<NodeID> {
13 |     let mut outward_surface_points = vec![];
14 |     for &node in nodes {
15 |         if node.node_type() == NodeType::FunctionDefinition
16 |             || node.node_type() == NodeType::ModifierDefinition
17 |         {
18 |             if let Some(id) = node.id() {
19 |                 outward_surface_points.push(id);
20 |             }
21 |         } else {
22 |             let parent_surface_point = node
23 |                 .closest_ancestor_of_type(context, NodeType::FunctionDefinition)
24 |                 .or_else(|| node.closest_ancestor_of_type(context, NodeType::ModifierDefinition));
25 |             if let Some(parent_surface_point) = parent_surface_point
26 |                 && let Some(parent_surface_point_id) = parent_surface_point.id()
27 |             {
28 |                 outward_surface_points.push(parent_surface_point_id);
29 |             }
30 |         }
31 |     }
32 |     outward_surface_points
33 | }
34 | 
35 | pub(super) fn derive_entry_points(nodes: &[&ASTNode]) -> super::Result<Vec<NodeID>> {
36 |     let mut entry_points = vec![];
37 |     for &node in nodes {
38 |         let node_id =
39 |             node.id().ok_or_else(|| super::Error::UnidentifiedEntryPointNode(node.clone()))?;
40 |         entry_points.push(node_id);
41 |     }
42 |     Ok(entry_points)
43 | }
44 | 
45 | pub(super) fn derive_inward_surface_points_legacy(
46 |     context: &WorkspaceContext,
47 |     nodes: &[&ASTNode],
48 | ) -> Vec<NodeID> {
49 |     let mut inward_surface_points = vec![];
50 | 
51 |     // Construct inward surface points
52 |     for &node in nodes {
53 |         let referenced_declarations = ExtractReferencedDeclarations::from(node).extracted;
54 | 
55 |         for declared_id in referenced_declarations {
56 |             if let Some(node) = context.nodes.get(&declared_id) {
57 |                 if node.node_type() == NodeType::ModifierDefinition {
58 |                     inward_surface_points.push(declared_id);
59 |                 } else if let ASTNode::FunctionDefinition(function_definition) = node
60 |                     && function_definition.implemented
61 |                 {
62 |                     inward_surface_points.push(declared_id);
63 |                 }
64 |             }
65 |         }
66 |     }
67 | 
68 |     inward_surface_points
69 | }
70 | 
```

--------------------------------------------------------------------------------
/tests/ast/contract_dep_order.json:
--------------------------------------------------------------------------------

```json
1 | {"absolutePath":"a","exportedSymbols":{"A":[1],"B":[4],"C":[7],"D":[10],"E":[13]},"id":14,"nodeType":"SourceUnit","nodes":[{"abstract":false,"baseContracts":[],"canonicalName":"A","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":1,"linearizedBaseContracts":[1],"name":"A","nameLocation":"9:1:1","nodeType":"ContractDefinition","nodes":[],"scope":14,"src":"0:14:1","usedErrors":[]},{"abstract":false,"baseContracts":[{"baseName":{"id":2,"name":"A","nameLocations":["29:1:1"],"nodeType":"IdentifierPath","referencedDeclaration":1,"src":"29:1:1"},"id":3,"nodeType":"InheritanceSpecifier","src":"29:1:1"}],"canonicalName":"B","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":4,"linearizedBaseContracts":[4,1],"name":"B","nameLocation":"24:1:1","nodeType":"ContractDefinition","nodes":[],"scope":14,"src":"15:19:1","usedErrors":[]},{"abstract":false,"baseContracts":[{"baseName":{"id":5,"name":"B","nameLocations":["49:1:1"],"nodeType":"IdentifierPath","referencedDeclaration":4,"src":"49:1:1"},"id":6,"nodeType":"InheritanceSpecifier","src":"49:1:1"}],"canonicalName":"C","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":7,"linearizedBaseContracts":[7,4,1],"name":"C","nameLocation":"44:1:1","nodeType":"ContractDefinition","nodes":[],"scope":14,"src":"35:19:1","usedErrors":[]},{"abstract":false,"baseContracts":[{"baseName":{"id":8,"name":"C","nameLocations":["69:1:1"],"nodeType":"IdentifierPath","referencedDeclaration":7,"src":"69:1:1"},"id":9,"nodeType":"InheritanceSpecifier","src":"69:1:1"}],"canonicalName":"D","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":10,"linearizedBaseContracts":[10,7,4,1],"name":"D","nameLocation":"64:1:1","nodeType":"ContractDefinition","nodes":[],"scope":14,"src":"55:19:1","usedErrors":[]},{"abstract":false,"baseContracts":[{"baseName":{"id":11,"name":"D","nameLocations":["89:1:1"],"nodeType":"IdentifierPath","referencedDeclaration":10,"src":"89:1:1"},"id":12,"nodeType":"InheritanceSpecifier","src":"89:1:1"}],"canonicalName":"E","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":13,"linearizedBaseContracts":[13,10,7,4,1],"name":"E","nameLocation":"84:1:1","nodeType":"ContractDefinition","nodes":[],"scope":14,"src":"75:19:1","usedErrors":[]}],"src":"0:95:1"}
2 | 
```

--------------------------------------------------------------------------------
/tools/xtask/src/flags.rs:
--------------------------------------------------------------------------------

```rust
  1 | xflags::xflags! {
  2 |     src "./src/flags.rs"
  3 | 
  4 |     cmd xtask {
  5 |         cmd cut-release {
  6 |             /// Cut a patch release
  7 |             optional -p, --patch
  8 | 
  9 |             /// Cut a minor release
 10 |             optional -m, --minor
 11 |         }
 12 |         cmd blesspr {}
 13 |         cmd reportgen {
 14 |             /// Run all integration tests
 15 |             optional -a, --all
 16 | 
 17 |             /// Parallel
 18 |             optional --parallel
 19 | 
 20 |             /// Sablier
 21 |             optional -s, --sablier
 22 | 
 23 |             /// Templegold
 24 |             optional -t, --tg
 25 | 
 26 |             /// AdHoc Sol files
 27 |             optional -h, --adhoc
 28 | 
 29 |             /// CCIP
 30 |             optional -c, --ccip
 31 | 
 32 |             /// Contract Playground
 33 |             optional -p, --cpg
 34 | 
 35 |             /// Foundry NFT
 36 |             optional -n, --fnft
 37 | 
 38 |             /// Foundry NFT ICM
 39 |             optional -i, --fnft-icm
 40 | 
 41 |             /// Contract Playrground Uniswap
 42 |             optional -u, --cpgu
 43 | 
 44 |             /// Hardhat Js Playground
 45 |             optional -b, --hhpg
 46 | 
 47 |             /// PRB Math
 48 |             optional -y, --prb-math
 49 | 
 50 |             /// Run in release mode
 51 |             optional --release
 52 |         }
 53 |         cmd tomlgen{}
 54 |     }
 55 | }
 56 | 
 57 | // generated start
 58 | // The following code is generated by `xflags` macro.
 59 | // Run `env UPDATE_XFLAGS=1 cargo build` to regenerate.
 60 | #[derive(Debug)]
 61 | pub struct Xtask {
 62 |     pub subcommand: XtaskCmd,
 63 | }
 64 | 
 65 | #[derive(Debug)]
 66 | pub enum XtaskCmd {
 67 |     CutRelease(CutRelease),
 68 |     Blesspr(Blesspr),
 69 |     Reportgen(Reportgen),
 70 |     Tomlgen(Tomlgen),
 71 | }
 72 | 
 73 | #[derive(Debug)]
 74 | pub struct CutRelease {
 75 |     pub patch: bool,
 76 |     pub minor: bool,
 77 | }
 78 | 
 79 | #[derive(Debug)]
 80 | pub struct Blesspr;
 81 | 
 82 | #[derive(Debug)]
 83 | pub struct Reportgen {
 84 |     pub all: bool,
 85 |     pub parallel: bool,
 86 |     pub sablier: bool,
 87 |     pub tg: bool,
 88 |     pub adhoc: bool,
 89 |     pub ccip: bool,
 90 |     pub cpg: bool,
 91 |     pub fnft: bool,
 92 |     pub fnft_icm: bool,
 93 |     pub cpgu: bool,
 94 |     pub hhpg: bool,
 95 |     pub prb_math: bool,
 96 |     pub release: bool,
 97 | }
 98 | 
 99 | #[derive(Debug)]
100 | pub struct Tomlgen;
101 | 
102 | impl Xtask {
103 |     #[allow(dead_code)]
104 |     pub fn from_env_or_exit() -> Self {
105 |         Self::from_env_or_exit_()
106 |     }
107 | 
108 |     #[allow(dead_code)]
109 |     pub fn from_env() -> xflags::Result<Self> {
110 |         Self::from_env_()
111 |     }
112 | 
113 |     #[allow(dead_code)]
114 |     pub fn from_vec(args: Vec<std::ffi::OsString>) -> xflags::Result<Self> {
115 |         Self::from_vec_(args)
116 |     }
117 | }
118 | // generated end
119 | 
```

--------------------------------------------------------------------------------
/aderyn_core/src/detect/low/ecrecover.rs:
--------------------------------------------------------------------------------

```rust
 1 | use std::{collections::BTreeMap, error::Error};
 2 | 
 3 | use crate::{
 4 |     ast::NodeID,
 5 |     capture,
 6 |     context::workspace::WorkspaceContext,
 7 |     detect::detector::{IssueDetector, IssueDetectorNamePool, IssueSeverity},
 8 | };
 9 | use eyre::Result;
10 | 
11 | #[derive(Default)]
12 | pub struct EcrecoverDetector {
13 |     // Keys are: [0] source file name, [1] line number, [2] character location of node.
14 |     // Do not add items manually, use `capture!` to add nodes to this BTreeMap.
15 |     found_instances: BTreeMap<(String, usize, String), NodeID>,
16 | }
17 | 
18 | impl IssueDetector for EcrecoverDetector {
19 |     fn detect(&mut self, context: &WorkspaceContext) -> Result<bool, Box<dyn Error>> {
20 |         for identifier in context.identifiers() {
21 |             if identifier.name == "ecrecover" {
22 |                 capture!(self, context, identifier);
23 |             }
24 |         }
25 |         Ok(!self.found_instances.is_empty())
26 |     }
27 | 
28 |     fn title(&self) -> String {
29 |         String::from("`ecrecover` Signature Malleability")
30 |     }
31 | 
32 |     fn description(&self) -> String {
33 |         String::from(
34 |             "The `ecrecover` function is susceptible to signature malleability. \
35 |             This means that the same message can be signed in multiple ways, \
36 |             allowing an attacker to change the message signature without invalidating it. \
37 |             This can lead to unexpected behavior in smart contracts, \
38 |             such as the loss of funds or the ability to bypass access control. \
39 |             Consider using OpenZeppelin's ECDSA library instead of the built-in function.",
40 |         )
41 |     }
42 | 
43 |     fn severity(&self) -> IssueSeverity {
44 |         IssueSeverity::Low
45 |     }
46 | 
47 |     fn instances(&self) -> BTreeMap<(String, usize, String), NodeID> {
48 |         self.found_instances.clone()
49 |     }
50 | 
51 |     fn name(&self) -> String {
52 |         format!("{}", IssueDetectorNamePool::Ecrecover)
53 |     }
54 | }
55 | 
56 | #[cfg(test)]
57 | mod ecrecover_tests {
58 | 
59 |     use crate::detect::detector::IssueDetector;
60 | 
61 |     use super::EcrecoverDetector;
62 | 
63 |     #[test]
64 | 
65 |     fn test_ecrecover_detector_by_loading_contract_directly() {
66 |         let context = crate::detect::test_utils::load_solidity_source_unit(
67 |             "../tests/contract-playground/src/inheritance/ExtendedInheritance.sol",
68 |         );
69 | 
70 |         let mut detector = EcrecoverDetector::default();
71 |         let found = detector.detect(&context).unwrap();
72 |         assert!(found);
73 |         assert_eq!(detector.instances().len(), 1);
74 |     }
75 | }
76 | 
```

--------------------------------------------------------------------------------
/aderyn/src/panic.rs:
--------------------------------------------------------------------------------

```rust
 1 | #![allow(clippy::unwrap_used)]
 2 | use std::{io::Write, panic::PanicHookInfo};
 3 | use termcolor::{Color, ColorSpec, WriteColor};
 4 | 
 5 | use std::io::IsTerminal;
 6 | 
 7 | use termcolor::{BufferWriter, ColorChoice};
 8 | 
 9 | pub fn stderr_buffer_writer() -> BufferWriter {
10 |     // Prefer to add colors to the output only if it is forced via an environment variable or
11 |     // because it's a terminal
12 | 
13 |     let color_choice = {
14 |         if std::env::var("FORCE_COLOR").is_ok_and(|e| !e.is_empty()) {
15 |             ColorChoice::Always
16 |         } else if std::io::stderr().is_terminal() {
17 |             ColorChoice::Auto
18 |         } else {
19 |             ColorChoice::Never
20 |         }
21 |     };
22 | 
23 |     BufferWriter::stderr(color_choice)
24 | }
25 | 
26 | pub fn add_handler() {
27 |     std::panic::set_hook(Box::new(move |info: &PanicHookInfo<'_>| {
28 |         print_compiler_bug_message(info)
29 |     }));
30 | }
31 | 
32 | fn print_compiler_bug_message(info: &PanicHookInfo<'_>) {
33 |     let message =
34 |         match (info.payload().downcast_ref::<&str>(), info.payload().downcast_ref::<String>()) {
35 |             (Some(s), _) => (*s).to_string(),
36 |             (_, Some(s)) => s.to_string(),
37 |             (None, None) => "unknown error".into(),
38 |         };
39 | 
40 |     let location = match info.location() {
41 |         None => "".into(),
42 |         Some(location) => format!("{}:{}\n\t", location.file(), location.line()),
43 |     };
44 | 
45 |     let buffer_writer = stderr_buffer_writer();
46 |     let mut buffer = buffer_writer.buffer();
47 |     buffer.set_color(ColorSpec::new().set_bold(true).set_fg(Some(Color::Red))).unwrap();
48 |     write!(buffer, "error").unwrap();
49 |     buffer.set_color(ColorSpec::new().set_bold(true)).unwrap();
50 |     write!(buffer, ": Fatal compiler bug!\n\n").unwrap();
51 |     buffer.set_color(&ColorSpec::new()).unwrap();
52 |     writeln!(
53 |         buffer,
54 |         "This is a fatal bug in Aderyn, sorry!
55 | 
56 | Please report this crash to https://github.com/cyfrin/aderyn/issues/new and include this error message with your report.
57 | 
58 | Panic: {location}{message}
59 | Aderyn version: {version}
60 | Operating system: {os}
61 | 
62 | If you can also share your code and say what file you were editing or any
63 | steps to reproduce the crash that would be a great help.
64 | 
65 | You may also want to try again with the `ADERYN_LOG=trace` environment
66 | variable set.
67 | ",
68 |         location = location,
69 |         message = message,
70 |         version = env!("CARGO_PKG_VERSION"),
71 |         os = std::env::consts::OS,
72 |     )
73 |     .unwrap();
74 |     buffer_writer.print(&buffer).unwrap();
75 | }
76 | 
```

--------------------------------------------------------------------------------
/aderyn_core/src/detect/high/incorrect_shift_order.rs:
--------------------------------------------------------------------------------

```rust
 1 | use std::{collections::BTreeMap, error::Error};
 2 | 
 3 | use crate::ast::{NodeID, YulExpression};
 4 | 
 5 | use crate::{
 6 |     capture,
 7 |     context::workspace::WorkspaceContext,
 8 |     detect::detector::{IssueDetector, IssueDetectorNamePool, IssueSeverity},
 9 | };
10 | use eyre::Result;
11 | 
12 | #[derive(Default)]
13 | pub struct IncorrectShiftOrderDetector {
14 |     // Keys are: [0] source file name, [1] line number, [2] character location of node.
15 |     // Do not add items manually, use `capture!` to add nodes to this BTreeMap.
16 |     found_instances: BTreeMap<(String, usize, String), NodeID>,
17 | }
18 | 
19 | impl IssueDetector for IncorrectShiftOrderDetector {
20 |     fn detect(&mut self, context: &WorkspaceContext) -> Result<bool, Box<dyn Error>> {
21 |         let yul_function_calls = context.yul_function_calls();
22 |         for yul_function_call in yul_function_calls {
23 |             if (yul_function_call.function_name.name == "shl"
24 |                 || yul_function_call.function_name.name == "shr")
25 |                 && yul_function_call
26 |                     .arguments
27 |                     .get(1)
28 |                     .is_some_and(|n| matches!(n, YulExpression::YulLiteral(_)))
29 |             {
30 |                 capture!(self, context, yul_function_call);
31 |             }
32 |         }
33 | 
34 |         Ok(!self.found_instances.is_empty())
35 |     }
36 | 
37 |     fn severity(&self) -> IssueSeverity {
38 |         IssueSeverity::High
39 |     }
40 | 
41 |     fn title(&self) -> String {
42 |         String::from("Incorrect Assembly Shift Parameter Order")
43 |     }
44 | 
45 |     fn description(&self) -> String {
46 |         String::from(
47 |             "Example: `shl(shifted, 4)` will shift the right constant `4` by `a` bits. The correct order is `shl(4, shifted)`.",
48 |         )
49 |     }
50 | 
51 |     fn instances(&self) -> BTreeMap<(String, usize, String), NodeID> {
52 |         self.found_instances.clone()
53 |     }
54 | 
55 |     fn name(&self) -> String {
56 |         IssueDetectorNamePool::IncorrectShiftOrder.to_string()
57 |     }
58 | }
59 | 
60 | #[cfg(test)]
61 | mod incorrect_shift_order_detector_tests {
62 | 
63 |     use crate::detect::{detector::IssueDetector, high::IncorrectShiftOrderDetector};
64 | 
65 |     #[test]
66 | 
67 |     fn test_incorrect_shift_order_detector() {
68 |         let context = crate::detect::test_utils::load_solidity_source_unit(
69 |             "../tests/contract-playground/src/IncorrectShift.sol",
70 |         );
71 | 
72 |         let mut detector = IncorrectShiftOrderDetector::default();
73 |         let found = detector.detect(&context).unwrap();
74 |         assert!(found);
75 |         assert_eq!(detector.instances().len(), 2);
76 |     }
77 | }
78 | 
```
Page 5/103FirstPrevNextLast