#
tokens: 48352/50000 25/1140 files (page 8/94)
lines: off (toggle) GitHub
raw markdown copy
This is page 8 of 94. Use http://codebase.md/cyfrin/aderyn?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/push-zero-opcode/report/relative_regression_small.svg:
--------------------------------------------------------------------------------

```
<svg width="450" height="300" viewBox="0 0 450 300" xmlns="http://www.w3.org/2000/svg">
<text x="15" y="130" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000" transform="rotate(270, 15, 130)">
Total sample time (ms)
</text>
<text x="255" y="285" dy="-0.5ex" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
Iterations (x 10^3)
</text>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="244" x2="75" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="156" y1="244" x2="156" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="238" y1="244" x2="238" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="319" y1="244" x2="319" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="401" y1="244" x2="401" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="244" x2="434" y2="244"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="203" x2="434" y2="203"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="162" x2="434" y2="162"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="120" x2="434" y2="120"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="79" x2="434" y2="79"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="37" x2="434" y2="37"/>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="74,15 74,244 "/>
<text x="65" y="244" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="69,244 74,244 "/>
<text x="65" y="203" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
20.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="69,203 74,203 "/>
<text x="65" y="162" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
40.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="69,162 74,162 "/>
<text x="65" y="120" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
60.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="69,120 74,120 "/>
<text x="65" y="79" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
80.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="69,79 74,79 "/>
<text x="65" y="37" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
100.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="69,37 74,37 "/>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="75,245 434,245 "/>
<text x="75" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="75,245 75,250 "/>
<text x="156" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.5
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="156,245 156,250 "/>
<text x="238" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
1
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="238,245 238,250 "/>
<text x="319" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
1.5
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="319,245 319,250 "/>
<text x="401" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
2
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="401,245 401,250 "/>
<polyline fill="none" opacity="1" stroke="#E31A1C" stroke-width="1" points="75,244 434,15 "/>
<polygon opacity="0.25" fill="#E31A1C" points="75,244 434,23 434,15 "/>
<polyline fill="none" opacity="1" stroke="#1F78B4" stroke-width="1" points="75,244 434,51 "/>
<polygon opacity="0.25" fill="#1F78B4" points="75,244 434,56 434,45 "/>
</svg>

```

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

```rust
use super::render::*;
use crate::{
    ast::{ASTNode, ContractDefinition, FunctionDefinition, NodeID},
    context::{graph::RawCallGraph, workspace::WorkspaceContext},
};
use rmcp::ErrorData as McpError;
use std::collections::{HashSet, hash_map::Entry};

pub fn build_post_order_nodes(
    context: &WorkspaceContext,
    subgraph: &RawCallGraph,
    entrypoint: &FunctionDefinition,
) -> Result<Vec<NodeData>, McpError> {
    let mut visited: HashSet<NodeID> = Default::default();
    let mut post_order_nodes = vec![];

    fn post_order_traverse(
        context: &WorkspaceContext,
        node_id: NodeID,
        post_order_nodes: &mut Vec<NodeData>,
        visited: &mut HashSet<NodeID>,
        subgraph: &RawCallGraph,
    ) {
        if visited.contains(&node_id) {
            return;
        }
        visited.insert(node_id);

        if let Some(to_node_ids) = subgraph.get(&node_id) {
            for to_id in to_node_ids {
                post_order_traverse(context, *to_id, post_order_nodes, visited, subgraph);
            }
        }

        let name = match context.nodes.get(&node_id) {
            Some(ASTNode::FunctionDefinition(func)) => Some(func.name.clone()),
            Some(ASTNode::ModifierDefinition(modifier)) => Some(modifier.name.clone()),
            _ => None,
        };

        let Some(name) = name else {
            return;
        };

        let mut called_nodes = vec![];
        if let Some(called) = subgraph.get(&node_id) {
            for c in called {
                let c_name = match context.nodes.get(c) {
                    Some(ASTNode::FunctionDefinition(func)) => Some(func.name.clone()),
                    Some(ASTNode::ModifierDefinition(modifier)) => Some(modifier.name.clone()),
                    _ => None,
                };

                let Some(c_name) = c_name else {
                    continue;
                };

                if let Ok(c_data) = NodeDataBuilder::default()
                    .node_id(*c)
                    .name(c_name)
                    .called_nodes(vec![]) // When displaying we only show one level deep.
                    .build()
                {
                    called_nodes.push(c_data);
                }
            }
        }

        if let Ok(node_data) = NodeDataBuilder::default()
            .node_id(node_id)
            .name(name)
            .called_nodes(called_nodes)
            .build()
        {
            post_order_nodes.push(node_data);
        }
    }

    post_order_traverse(context, entrypoint.id, &mut post_order_nodes, &mut visited, subgraph);

    Ok(post_order_nodes)
}

pub fn build_raw_callgraph_for_entrypoint(
    context: &WorkspaceContext,
    contract: &ContractDefinition,
    entrypoint: &FunctionDefinition,
) -> Result<RawCallGraph, McpError> {
    let Some(callgraphs) = &context.callgraphs else {
        return Err(McpError::internal_error("callgraphs could not be formed", None));
    };
    let Some(callgraph) = callgraphs.inward_callgraphs.get(&contract.id) else {
        return Err(McpError::internal_error(
            format!("callgraph for {} doesn't exist.", contract.id),
            None,
        ));
    };

    let mut visited: HashSet<NodeID> = Default::default();
    let mut subgraph = RawCallGraph::default();

    let mut worklist = vec![entrypoint.id];

    while let Some(node_id) = worklist.pop() {
        if visited.contains(&node_id) {
            continue;
        }
        visited.insert(node_id);
        create_node_if_not_exists(node_id, &mut subgraph);

        if let Some(to_nodes) = callgraph.get(&node_id) {
            for to_id in to_nodes {
                create_node_if_not_exists(*to_id, &mut subgraph);
                create_connection_if_not_exists(node_id, *to_id, &mut subgraph);
                // Only explore further if it hasn't already been explored.
                if !visited.contains(to_id) {
                    worklist.push(*to_id);
                }
            }
        }
    }
    Ok(subgraph)
}

#[inline(always)]
fn create_node_if_not_exists(node_id: NodeID, raw_callgraph: &mut RawCallGraph) {
    if let Entry::Vacant(v) = raw_callgraph.entry(node_id) {
        v.insert(vec![]);
    }
}

#[inline]
fn create_connection_if_not_exists(
    from_id: NodeID,
    to_id: NodeID,
    raw_callgraph: &mut RawCallGraph,
) {
    match raw_callgraph.entry(from_id) {
        Entry::Occupied(mut o) => {
            if !o.get().contains(&to_id) {
                o.get_mut().push(to_id);
            }
        }
        Entry::Vacant(v) => {
            v.insert(vec![to_id]);
        }
    }
}

```

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

```json
{
  "_format": "hh-sol-artifact-1",
  "contractName": "Counter",
  "sourceName": "contracts/Counter.sol",
  "abi": [
    {
      "inputs": [],
      "name": "TWO",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "callIncrement",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "increment",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "incrementByTwoConstant",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "incrementByTwoMagic",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "number",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "newNumber",
          "type": "uint256"
        }
      ],
      "name": "setNumber",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    }
  ],
  "bytecode": "0x60806040526000805534801561001457600080fd5b506102e3806100246000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c8063452707c11161005b578063452707c1146100c65780637b74087e146100d05780638381f58a146100da578063d09de08a146100f85761007d565b806334945b3a1461008257806338cd26de146100a05780633fb5c1cb146100aa575b600080fd5b61008a610102565b6040516100979190610189565b60405180910390f35b6100a8610107565b005b6100c460048036038101906100bf91906101d5565b610111565b005b6100ce61011b565b005b6100d8610136565b005b6100e2610151565b6040516100ef9190610189565b60405180910390f35b610100610157565b005b600281565b61010f610157565b565b8060008190555050565b600260008082825461012d9190610231565b92505081905550565b60026000808282546101489190610231565b92505081905550565b60005481565b60008081548092919061016990610265565b9190505550565b6000819050919050565b61018381610170565b82525050565b600060208201905061019e600083018461017a565b92915050565b600080fd5b6101b281610170565b81146101bd57600080fd5b50565b6000813590506101cf816101a9565b92915050565b6000602082840312156101eb576101ea6101a4565b5b60006101f9848285016101c0565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061023c82610170565b915061024783610170565b925082820190508082111561025f5761025e610202565b5b92915050565b600061027082610170565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036102a2576102a1610202565b5b60018201905091905056fea26469706673582212209d9bfe8376073e0b0e1f0123ffbc5bae37ce516cbfbc41f9816933997a6d327f64736f6c63430008140033",
  "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061007d5760003560e01c8063452707c11161005b578063452707c1146100c65780637b74087e146100d05780638381f58a146100da578063d09de08a146100f85761007d565b806334945b3a1461008257806338cd26de146100a05780633fb5c1cb146100aa575b600080fd5b61008a610102565b6040516100979190610189565b60405180910390f35b6100a8610107565b005b6100c460048036038101906100bf91906101d5565b610111565b005b6100ce61011b565b005b6100d8610136565b005b6100e2610151565b6040516100ef9190610189565b60405180910390f35b610100610157565b005b600281565b61010f610157565b565b8060008190555050565b600260008082825461012d9190610231565b92505081905550565b60026000808282546101489190610231565b92505081905550565b60005481565b60008081548092919061016990610265565b9190505550565b6000819050919050565b61018381610170565b82525050565b600060208201905061019e600083018461017a565b92915050565b600080fd5b6101b281610170565b81146101bd57600080fd5b50565b6000813590506101cf816101a9565b92915050565b6000602082840312156101eb576101ea6101a4565b5b60006101f9848285016101c0565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061023c82610170565b915061024783610170565b925082820190508082111561025f5761025e610202565b5b92915050565b600061027082610170565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036102a2576102a1610202565b5b60018201905091905056fea26469706673582212209d9bfe8376073e0b0e1f0123ffbc5bae37ce516cbfbc41f9816933997a6d327f64736f6c63430008140033",
  "linkReferences": {},
  "deployedLinkReferences": {}
}

```

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

```rust
use std::{collections::BTreeMap, error::Error};

use crate::{
    ast::NodeID,
    capture,
    context::{
        browser::{ExtractIdentifiers, ExtractModifierInvocations, ExtractRevertStatements},
        graph::CallGraphVisitor,
        workspace::WorkspaceContext,
    },
    detect::detector::{IssueDetector, IssueDetectorNamePool, IssueSeverity},
};
use eyre::Result;

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

impl IssueDetector for UnprotectedInitializerDetector {
    fn detect(&mut self, context: &WorkspaceContext) -> Result<bool, Box<dyn Error>> {
        #[derive(Default, Debug)]
        struct UnprotectedInitializationTracker {
            has_require_or_revert: bool,
            has_initializer_modifier: bool, // devtooligan's suggestion
        }

        impl CallGraphVisitor for UnprotectedInitializationTracker {
            fn visit_any(&mut self, node: &crate::ast::ASTNode) -> eyre::Result<()> {
                // Check for revert(), require(), revert SomeError()
                let has_req_or_revert_calls = ExtractIdentifiers::from(node)
                    .extracted
                    .into_iter()
                    .any(|x| x.name == "require" || x.name == "revert");

                let has_revert_stmnts = !ExtractRevertStatements::from(node).extracted.is_empty();

                if has_req_or_revert_calls || has_revert_stmnts {
                    self.has_require_or_revert = true;
                }

                // Check if modifier name is "initializer" or "reinitializer" and assume it works
                // This is done because often times initialized comes from openzeppelin and it is
                // out of scope when running aderyn due to it being a library

                let modifier_invocations = ExtractModifierInvocations::from(node).extracted;

                for inv in modifier_invocations {
                    match inv.modifier_name {
                        crate::ast::IdentifierOrIdentifierPath::Identifier(n) => {
                            if n.name == "initializer" || n.name == "reinitializer" {
                                self.has_initializer_modifier = true;
                            }
                        }
                        crate::ast::IdentifierOrIdentifierPath::IdentifierPath(n) => {
                            if n.name == "initializer" || n.name == "reinitializer" {
                                self.has_initializer_modifier = true;
                            }
                        }
                    }
                }

                Ok(())
            }
        }

        for (func, callgraphs) in context.entrypoints_with_callgraphs() {
            for callgraph in callgraphs {
                let mut tracker = UnprotectedInitializationTracker::default();
                callgraph.accept(context, &mut tracker)?;

                if func.name.starts_with("_init") || func.name.starts_with("init") {
                    if tracker.has_initializer_modifier || tracker.has_require_or_revert {
                        continue;
                    }
                    capture!(self, context, func);
                }
            }
        }

        Ok(!self.found_instances.is_empty())
    }

    fn title(&self) -> String {
        String::from("Unprotected initializer")
    }

    fn description(&self) -> String {
        String::from("Consider protecting the initializer functions with modifiers.")
    }

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

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

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

#[cfg(test)]
mod unprotected_initializer_tests {

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

    use super::UnprotectedInitializerDetector;

    #[test]

    fn test_unprotected_initializer_by_loading_contract_directly() {
        let context = crate::detect::test_utils::load_solidity_source_unit(
            "../tests/contract-playground/src/UnprotectedInitialize.sol",
        );

        let mut detector = UnprotectedInitializerDetector::default();
        let found = detector.detect(&context).unwrap();
        assert!(found);
        assert_eq!(detector.instances().len(), 2); // Now there are two instances: one in
        // InitializedContract and one in
        // ReinitializerContract
    }
}

```

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

```rust
use std::{collections::BTreeMap, error::Error};

use crate::ast::{ASTNode, Expression, FunctionCall, Identifier, NodeID};

use crate::{
    capture,
    context::{
        browser::ExtractReferencedDeclarations,
        graph::{CallGraphConsumer, CallGraphDirection, CallGraphVisitor},
        workspace::WorkspaceContext,
    },
    detect::detector::{IssueDetector, IssueDetectorNamePool, IssueSeverity},
};
use eyre::Result;

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

impl IssueDetector for FunctionInitializingStateDetector {
    fn detect(&mut self, context: &WorkspaceContext) -> Result<bool, Box<dyn Error>> {
        // PLAN
        // Capture state variables that are initialized directly by calling a non constant function.
        // Go thorough state variable declarations with initial value (this will be true when value
        // is set outside constructor) See if the function references non-constant state
        // variables. If it does, then capture it

        for variable_declaration in
            context.variable_declarations().into_iter().filter(|v| v.state_variable)
        {
            if let Some(Expression::FunctionCall(FunctionCall { expression, .. })) =
                variable_declaration.value.as_ref()
                && let Expression::Identifier(Identifier {
                    referenced_declaration: Some(func_id),
                    ..
                }) = expression.as_ref()
                && let Some(ASTNode::FunctionDefinition(func)) = context.nodes.get(func_id)
            {
                let callgraphs =
                    CallGraphConsumer::get(context, &[&(func.into())], CallGraphDirection::Inward)?;

                for callgraph in callgraphs {
                    let mut tracker =
                        NonConstantStateVariableReferenceDeclarationTracker::new(context);

                    callgraph.accept(context, &mut tracker)?;

                    if tracker.makes_a_reference {
                        capture!(self, context, variable_declaration);
                    }
                }
            }
        }

        Ok(!self.found_instances.is_empty())
    }

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

    fn title(&self) -> String {
        String::from("Function Used to Initialize State Variable")
    }

    fn description(&self) -> String {
        String::from(
            "Instead of using a function to initialize a state variable in its declaration; declare the state variable and initialize it in the constructor.",
        )
    }

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

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

struct NonConstantStateVariableReferenceDeclarationTracker<'a> {
    makes_a_reference: bool,
    context: &'a WorkspaceContext,
}

impl<'a> NonConstantStateVariableReferenceDeclarationTracker<'a> {
    fn new(context: &'a WorkspaceContext) -> Self {
        Self { makes_a_reference: false, context }
    }
}

impl CallGraphVisitor for NonConstantStateVariableReferenceDeclarationTracker<'_> {
    fn visit_any(&mut self, node: &ASTNode) -> eyre::Result<()> {
        // We already know the condition is satisfied
        if self.makes_a_reference {
            return Ok(());
        }

        let references = ExtractReferencedDeclarations::from(node).extracted;

        for reference in references {
            if let Some(ASTNode::VariableDeclaration(variable_declaration)) =
                self.context.nodes.get(&reference)
                && variable_declaration.state_variable
                && !variable_declaration.constant
            {
                self.makes_a_reference = true;
            }
        }

        Ok(())
    }
}

#[cfg(test)]
mod function_initializing_state_tests {

    use crate::detect::{
        detector::IssueDetector,
        low::function_initializing_state::FunctionInitializingStateDetector,
    };

    #[test]

    fn test_function_initializing_state() {
        let context = crate::detect::test_utils::load_solidity_source_unit(
            "../tests/contract-playground/src/FunctionInitializingState.sol",
        );

        let mut detector = FunctionInitializingStateDetector::default();
        let found = detector.detect(&context).unwrap();
        assert!(found);
        assert_eq!(detector.instances().len(), 3);
    }
}

```

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

```rust
pub(crate) mod assert_state_change;
pub(crate) mod block_timestamp_deadline;
pub(crate) mod boolean_equality;
pub(crate) mod builtin_symbol_shadowing;
pub(crate) mod centralization_risk;
pub(crate) mod constant_function_contains_assembly;
pub(crate) mod costly_loop;
pub(crate) mod dead_code;
pub(crate) mod delegatecall_in_loop;
pub(crate) mod deprecated_oz_function;
pub(crate) mod division_before_multiplication;
pub(crate) mod ecrecover;
pub(crate) mod empty_block;
pub(crate) mod empty_require_revert;
pub(crate) mod function_initializing_state;
pub(crate) mod function_pointer_in_constructor;
pub(crate) mod inconsistent_type_names;
pub(crate) mod incorrect_modifier;
pub(crate) mod internal_function_used_once;
pub(crate) mod large_numeric_literal;
pub(crate) mod literal_instead_of_constant;
pub(crate) mod local_variable_shadowing;
pub(crate) mod missing_inheritance;
pub(crate) mod modifier_used_only_once;
pub(crate) mod multiple_placeholders;
pub(crate) mod non_reentrant_not_first;
pub(crate) mod push_0_opcode;
pub(crate) mod redundant_statement;
pub(crate) mod require_revert_in_loop;
pub(crate) mod return_bomb;
pub(crate) mod solmate_safe_transfer_lib;
pub(crate) mod state_change_without_event;
pub(crate) mod state_no_address_check;
pub(crate) mod state_variable_could_be_constant;
pub(crate) mod state_variable_could_be_immutable;
pub(crate) mod state_variable_read_external;
pub(crate) mod storage_array_length_not_cached;
pub(crate) mod todo;
pub(crate) mod unchecked_return;
pub(crate) mod uninitialized_local_variable;
pub(crate) mod unsafe_erc20_operation;
pub(crate) mod unsafe_oz_erc721_mint;
pub(crate) mod unspecific_solidity_pragma;
pub(crate) mod unused_error;
pub(crate) mod unused_import;
pub(crate) mod unused_public_function;
pub(crate) mod unused_state_variable;
pub(crate) mod void_constructor;

pub use assert_state_change::AssertStateChangeDetector;
pub use block_timestamp_deadline::BlockTimestampDeadlineDetector;
pub use boolean_equality::BooleanEqualityDetector;
pub use builtin_symbol_shadowing::BuiltinSymbolShadowingDetector;
pub use centralization_risk::CentralizationRiskDetector;
pub use constant_function_contains_assembly::ConstantFunctionContainsAssemblyDetector;
pub use costly_loop::CostlyLoopDetector;
pub use dead_code::DeadCodeDetector;
pub use delegatecall_in_loop::DelegatecallInLoopDetector;
pub use deprecated_oz_function::DeprecatedOZFunctionDetector;
pub use division_before_multiplication::DivisionBeforeMultiplicationDetector;
pub use ecrecover::EcrecoverDetector;
pub use empty_block::EmptyBlockDetector;
pub use empty_require_revert::EmptyRequireRevertDetector;
pub use function_initializing_state::FunctionInitializingStateDetector;
pub use function_pointer_in_constructor::FunctionPointerInConstructorDetector;
pub use inconsistent_type_names::InconsistentTypeNamesDetector;
pub use incorrect_modifier::IncorrectUseOfModifierDetector;
pub use internal_function_used_once::InternalFunctionUsedOnceDetector;
pub use large_numeric_literal::LargeLiteralValueDetector;
pub use literal_instead_of_constant::LiteralsInsteadOfConstantsDetector;
pub use local_variable_shadowing::LocalVariableShadowingDetector;
pub use missing_inheritance::MissingInheritanceDetector;
pub use modifier_used_only_once::ModifierUsedOnlyOnceDetector;
pub use multiple_placeholders::MultiplePlaceholdersDetector;
pub use non_reentrant_not_first::NonReentrantBeforeOthersDetector;
pub use push_0_opcode::PushZeroOpcodeDetector;
pub use redundant_statement::RedundantStatementDetector;
pub use require_revert_in_loop::RequireRevertInLoopDetector;
pub use return_bomb::ReturnBombDetector;
pub use solmate_safe_transfer_lib::SolmateSafeTransferLibDetector;
pub use state_change_without_event::StateVariableChangesWithoutEventDetector;
pub use state_no_address_check::StateNoAddressCheckDetector;
pub use state_variable_could_be_constant::StateVariableCouldBeConstantDetector;
pub use state_variable_could_be_immutable::StateVariableCouldBeImmutableDetector;
pub use state_variable_read_external::StateVariableReadExternalDetector;
pub use storage_array_length_not_cached::CacheArrayLengthDetector;
pub use todo::TodoDetector;
pub use unchecked_return::UncheckedReturnDetector;
pub use uninitialized_local_variable::UninitializedLocalVariableDetector;
pub use unsafe_erc20_operation::UnsafeERC20OperationDetector;
pub use unsafe_oz_erc721_mint::UnsafeERC721MintDetector;
pub use unspecific_solidity_pragma::UnspecificSolidityPragmaDetector;
pub use unused_error::UnusedErrorDetector;
pub use unused_import::UnusedImportDetector;
pub use unused_public_function::UnusedPublicFunctionDetector;
pub use unused_state_variable::UnusedStateVariablesDetector;
pub use void_constructor::VoidConstructorDetector;

```

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

```rust
macro_rules! generate_capturable_methods {
    ($( $name:ident ),* $(,)*) => {

        #[derive(Clone)]
        pub enum Capturable {
            $($name($name),)*
            YulFunctionCall(YulFunctionCall),
            YulIdentifier(YulIdentifier),
            YulLiteral(YulLiteral),
            ASTNode(ASTNode),
        }

        $(
            impl From<$name> for Capturable {
                fn from(value: $name) -> Self {
                    Self::$name(value)
                }
            }

            impl From<&$name> for Capturable {
                fn from(value: &$name) -> Self {
                    Self::$name(value.clone())
                }
            }
        )*

        impl From<ASTNode> for Capturable {
            fn from(value: ASTNode) -> Self {
                Self::ASTNode(value)
            }
        }

        impl From<&ASTNode> for Capturable {
            fn from(value: &ASTNode) -> Self {
                Self::ASTNode(value.clone())
            }
        }


        impl Capturable {
            pub fn make_key(&self, context: &WorkspaceContext) -> (String, usize, String) {
                match self {
                    Self::ASTNode(node) => context.get_node_sort_key(node),
                    Self::YulFunctionCall(n) => context.get_node_sort_key(&n.into()),
                    Self::YulIdentifier(n) => context.get_node_sort_key(&n.into()),
                    Self::YulLiteral(n) => context.get_node_sort_key(&n.into()),
                    $(Self::$name(n) => context.get_node_sort_key(&n.into()),)*
                }
            }
            pub fn id(&self) -> Option<NodeID> {
                match self {
                    Self::ASTNode(ast_node) => ast_node.id(),
                    Self::YulFunctionCall(_) => None,
                    Self::YulIdentifier(_) => None,
                    Self::YulLiteral(_) => None,
                    $(Self::$name(n) => Some(n.id),)*
                }
            }
        }


    };
}

macro_rules! generate_get_source_unit {

    ($( $name:ident => $storage_var:ident ),* $(,)*) => {

        impl WorkspaceContext {
            pub fn get_source_unit_from_child_node(&self, node: &ASTNode) -> Option<&SourceUnit> {
                let source_unit_id = match node {
                    ASTNode::SourceUnit(node) => Some(node.id),
                    $(
                        ASTNode::$name(node) => self
                            .$storage_var
                            .get(node)
                            .map(|context| context.source_unit_id),
                    )*
                };
                // iterate through self.source_units until the source unit with the id matching `source_unit_id` is found, then return its `absolute_path`
                source_unit_id.and_then(|id| {
                    self.source_units_context
                        .iter()
                        .find(|source_unit| source_unit.id == id)
                })
            }
        }

    };

}

macro_rules! make_route {
    ($tool:ty, $st:tt) => {{
        let t = <$tool>::new(std::sync::Arc::clone(&$st));
        rmcp::handler::server::tool::ToolRoute::new(
            rmcp::model::Tool::new(
                t.name().to_string(),
                t.description().to_string(),
                rmcp::handler::server::tool::cached_schema_for_type::<
                    <$tool as crate::context::mcp::ModelContextProtocolTool>::Input,
                >(),
            ),
            move |a| t.execute(a),
        )
    }};
}

macro_rules! mcp_success {
    ($resp:expr_2021) => {{
        use askama::Template;
        use serde::Serialize;

        let t = $resp;

        fn assert_traits<T: Serialize + Template + ?Sized>(_t: &T) {}

        // Enforce that $resp implements Serialize
        assert_traits(&t);

        // Serialize and render
        let json_value = serde_json::to_value(&t).expect("failed to serialize structured content");
        let text = t.render().expect("failed to render response");

        let call_tool_response = rmcp::model::CallToolResult {
            content: vec![rmcp::model::Content::text(&text)],
            structured_content: Some(json_value),
            is_error: Some(false),
            meta: None,
        };

        Ok(call_tool_response)
    }};
}

macro_rules! mcp_error {
    ($msg:expr_2021) => {
        Ok(rmcp::model::CallToolResult::error(vec![rmcp::model::Content::text($msg)]))
    };
    ($fmt:expr_2021, $($arg:tt)*) => {
        Ok(rmcp::model::CallToolResult::error(vec![rmcp::model::Content::text(format!($fmt, $($arg)*))]))
    };
}

pub(crate) use generate_capturable_methods;
pub(crate) use generate_get_source_unit;
pub(crate) use make_route;
pub(crate) use mcp_error;
pub(crate) use mcp_success;

```

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

```rust
use crate::{
    ast::{ASTNode, NodeID},
    context::{
        macros::{mcp_error, mcp_success},
        mcp::{
            MCPToolNamePool, ModelContextProtocolState, ModelContextProtocolTool,
            callgraph::{
                render::{
                    CallgraphToolResponseBuilder, ContractDataBuilder,
                    EntrypointFunctionDataBuilder,
                },
                utils::{build_post_order_nodes, build_raw_callgraph_for_entrypoint},
            },
        },
    },
};
use indoc::indoc;
use rmcp::{
    ErrorData as McpError, handler::server::wrapper::Parameters, model::CallToolResult, schemars,
};
use serde::Deserialize;
use std::sync::Arc;

#[derive(Clone)]
pub struct CallgraphTool {
    state: Arc<ModelContextProtocolState>,
}

#[derive(Deserialize, schemars::JsonSchema)]
pub struct CallgraphPayload {
    /// The index of the compilation unit to analyze. Must be a positive integer starting from 1.
    /// Use the project overview tool first to see all available compilation units and their
    /// indices.
    pub compilation_unit_index: usize,
    /// The Node ID of the main contract to analyze. Obtain this from the list contracts tool,
    /// which returns Node IDs for all deployable contracts in the compilation unit. Each contract
    /// has a unique Node ID within its compilation unit.
    pub deployable_contract_node_id: NodeID,
    /// The Node ID of the specific entrypoint function in the contract to start exploring the
    /// callgraph from. Obtain this from contract surface area tool.
    pub entrypoint_function_node_id: NodeID,
}

impl ModelContextProtocolTool for CallgraphTool {
    type Input = CallgraphPayload;

    fn new(state: Arc<ModelContextProtocolState>) -> Self {
        Self { state }
    }

    fn name(&self) -> String {
        MCPToolNamePool::AderynExploreCallgraphFromEntrypoint.to_string()
    }

    fn description(&self) -> String {
        indoc! {
            "The callgraph provider tool maps and analyzes function execution flows within Solidity smart contracts \
            by tracing all possible internal function calls and modifier executions triggered by the given entrypoint\
            function's Node ID. It provides inheritance-aware analysis across contract hierarchies and \
            imported libraries. It returns compilation unit index and NodeIDs of the various functions in the call chain."
        }
        .to_string()
    }

    fn execute(&self, input: Parameters<Self::Input>) -> Result<CallToolResult, McpError> {
        let payload = input.0;

        if payload.compilation_unit_index < 1
            || payload.compilation_unit_index > self.state.contexts.len()
        {
            return mcp_error!(
                "Invalid compilation unit index: {}. Must be in range [1, {}]",
                payload.compilation_unit_index,
                self.state.contexts.len()
            );
        }

        let context = self
            .state
            .contexts
            .get(payload.compilation_unit_index - 1)
            .expect("Compilation unit index bounds check failed");

        let Some(ASTNode::ContractDefinition(contract)) =
            context.nodes.get(&payload.deployable_contract_node_id)
        else {
            return mcp_error!(
                "Node ID {} does not correspond to a contract definition",
                payload.deployable_contract_node_id
            );
        };

        let Some(ASTNode::FunctionDefinition(entrypoint)) =
            context.nodes.get(&payload.entrypoint_function_node_id)
        else {
            return mcp_error!(
                "Node ID {} does not correspond to a function",
                payload.entrypoint_function_node_id
            );
        };

        let contract_data = ContractDataBuilder::default()
            .name(contract.name.clone())
            .node_id(contract.id)
            .build()
            .expect("failed to build contract data");

        let entrypoint_function_data = EntrypointFunctionDataBuilder::default()
            .name(entrypoint.name.clone())
            .node_id(entrypoint.id)
            .build()
            .expect("failed to build entrypoint function data");

        let subgraph = build_raw_callgraph_for_entrypoint(context, contract, entrypoint)?;
        let post_order_data = build_post_order_nodes(context, &subgraph, entrypoint)?;

        let cg_response = CallgraphToolResponseBuilder::default()
            .compilation_unit_index(payload.compilation_unit_index)
            .contract(contract_data)
            .entrypoint_function(entrypoint_function_data)
            .graph(subgraph)
            .post_order_nodes(post_order_data)
            .build()
            .expect("failed to build callgraph tool response");

        mcp_success!(cg_response)
    }
}

```

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

```rust
use std::{
    collections::{BTreeMap, HashSet},
    error::Error,
};

use crate::ast::{
    ASTNode, ContractDefinition, Expression, Identifier, MemberAccess, NodeID, Visibility,
};

use crate::{
    capture,
    context::{
        browser::{ExtractFunctionCalls, ExtractVariableDeclarations},
        workspace::WorkspaceContext,
    },
    detect::detector::{IssueDetector, IssueDetectorNamePool, IssueSeverity},
};
use eyre::Result;

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

impl IssueDetector for StateVariableReadExternalDetector {
    fn detect(&mut self, context: &WorkspaceContext) -> Result<bool, Box<dyn Error>> {
        for contract in context.contract_definitions() {
            // Public state variables including the base contracts
            if let Ok(public_state_variable_names) =
                find_all_public_state_variables_names_for_contract(context, contract)
            {
                // Find all the `X`s that appear with the pattern `this.X()`
                let this_member_accesses =
                    find_all_public_member_names_called_using_this_keyword_in_contract(
                        context, contract,
                    );

                for member_access in this_member_accesses {
                    if public_state_variable_names.contains(&member_access.member_name) {
                        capture!(self, context, member_access);
                    }
                }
            }
        }

        Ok(!self.found_instances.is_empty())
    }

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

    fn title(&self) -> String {
        String::from("State Variable is Read as External")
    }

    fn description(&self) -> String {
        String::from(
            "The contract reads it's own state variable using `this` which adds an unnecessary STATICCALL. Consider removing `this` to access the variable from storage.",
        )
    }

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

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

fn find_all_public_member_names_called_using_this_keyword_in_contract<'a>(
    context: &'a WorkspaceContext,
    contract: &ContractDefinition,
) -> Vec<&'a MemberAccess> {
    let mut member_names = vec![];

    let function_calls = ExtractFunctionCalls::from(contract).extracted;
    for function_call in function_calls {
        if let Expression::MemberAccess(MemberAccess { id, expression, .. }) =
            function_call.expression.as_ref()
            && let Expression::Identifier(Identifier { name, .. }) = expression.as_ref()
            && name == "this"
            && let Some(ASTNode::MemberAccess(member_access)) = context.nodes.get(id)
        {
            member_names.push(member_access)
        }
    }

    member_names
}

// Scans the linearized base contracts and returns a list of all the NodeIDs of public variable
// declarations
fn find_all_public_state_variables_names_for_contract(
    context: &WorkspaceContext,
    contract: &ContractDefinition,
) -> Result<HashSet<String>, Box<dyn Error>> {
    Ok(contract
        .linearized_base_contracts
        .iter()
        .flat_map(|ancestor_id| {
            if let Some(ancestor) = context.nodes.get(ancestor_id) {
                let public_variable_declarations =
                    ExtractVariableDeclarations::from(ancestor).extracted;
                return Some(
                    public_variable_declarations
                        .into_iter()
                        .filter(|declaration| {
                            declaration.state_variable
                                && declaration.visibility == Visibility::Public
                        })
                        .collect::<Vec<_>>(),
                );
            }
            None
        })
        .flatten()
        .map(|v| v.name.clone())
        .collect())
}

#[cfg(test)]
mod public_variable_read_in_external_context_detector_tests {

    use crate::detect::{
        detector::IssueDetector,
        low::state_variable_read_external::StateVariableReadExternalDetector,
    };

    #[test]

    fn test_public_variable_read_in_external_context() {
        let context = crate::detect::test_utils::load_solidity_source_unit(
            "../tests/contract-playground/src/PublicVariableReadInExternalContext.sol",
        );

        let mut detector = StateVariableReadExternalDetector::default();
        let found = detector.detect(&context).unwrap();
        assert!(found);
        assert_eq!(detector.instances().len(), 4);
    }
}

```

--------------------------------------------------------------------------------
/benchmarks/non-reentrant-before-others/report/relative_regression_small.svg:
--------------------------------------------------------------------------------

```
<svg width="450" height="300" viewBox="0 0 450 300" xmlns="http://www.w3.org/2000/svg">
<text x="15" y="130" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000" transform="rotate(270, 15, 130)">
Total sample time (ms)
</text>
<text x="255" y="285" dy="-0.5ex" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
Iterations (x 10^3)
</text>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="244" x2="75" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="139" y1="244" x2="139" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="203" y1="244" x2="203" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="267" y1="244" x2="267" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="331" y1="244" x2="331" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="395" y1="244" x2="395" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="244" x2="434" y2="244"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="204" x2="434" y2="204"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="164" x2="434" y2="164"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="124" x2="434" y2="124"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="84" x2="434" y2="84"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="44" x2="434" y2="44"/>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="74,15 74,244 "/>
<text x="65" y="244" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="69,244 74,244 "/>
<text x="65" y="204" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
20.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="69,204 74,204 "/>
<text x="65" y="164" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
40.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="69,164 74,164 "/>
<text x="65" y="124" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
60.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="69,124 74,124 "/>
<text x="65" y="84" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
80.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="69,84 74,84 "/>
<text x="65" y="44" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
100.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="69,44 74,44 "/>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="75,245 434,245 "/>
<text x="75" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="75,245 75,250 "/>
<text x="139" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
5
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="139,245 139,250 "/>
<text x="203" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
10
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="203,245 203,250 "/>
<text x="267" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
15
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="267,245 267,250 "/>
<text x="331" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
20
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="331,245 331,250 "/>
<text x="395" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
25
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="395,245 395,250 "/>
<polyline fill="none" opacity="1" stroke="#E31A1C" stroke-width="1" points="75,244 434,15 "/>
<polygon opacity="0.25" fill="#E31A1C" points="75,244 434,21 434,15 "/>
<polyline fill="none" opacity="1" stroke="#1F78B4" stroke-width="1" points="75,244 434,63 "/>
<polygon opacity="0.25" fill="#1F78B4" points="75,244 434,64 434,61 "/>
</svg>

```

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

```rust
use std::{collections::BTreeMap, error::Error};

use crate::{
    ast::{Expression, Identifier, NodeID},
    capture,
    context::{browser::ExtractFunctionCalls, workspace::WorkspaceContext},
    detect::{
        detector::{IssueDetector, IssueDetectorNamePool, IssueSeverity},
        helpers::{get_implemented_external_and_public_functions, has_msg_sender_binary_operation},
    },
};
use eyre::Result;

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

impl IssueDetector for ArbitraryTransferFromDetector {
    fn detect(&mut self, context: &WorkspaceContext) -> Result<bool, Box<dyn Error>> {
        // Applying devtooligan's suggestion
        // * Operate on public and external functions only
        // * See that msg.sender is not checked
        // * Check that the argument passed in is from the parameter list of the said function

        let suspected_functions =
            get_implemented_external_and_public_functions(context).filter(|function_definition| {
                !has_msg_sender_binary_operation(&((*function_definition).into()))
                    && function_definition.modifiers.is_empty() // If there are modifiers, assume
                // the function is safe because
                // sometime modifiers' definition
                // may not be in scope
            });

        for func in suspected_functions {
            let func_parameters_ids =
                &func.parameters.parameters.iter().map(|f| f.id).collect::<Vec<_>>();

            let transfer_func_calls = ExtractFunctionCalls::from(func)
                .extracted
                .into_iter()
                .filter(|function_call| {
                    // For each function call, check if the function call is a member access
                    // and if the member name is "transferFrom" or "safeTransferFrom", then check if
                    // the first argument is valid If the first argument is
                    // valid, add the function call to found_instances
                    if let Expression::MemberAccess(member_access) = &*function_call.expression
                        && (member_access.member_name == "transferFrom"
                            || member_access.member_name == "safeTransferFrom")
                    {
                        return true;
                    }
                    false
                })
                .collect::<Vec<_>>();

            for func in transfer_func_calls {
                // Check if the first argument of the function call is valid
                // In function calls with 3 args, the first arg [0] is the `from` address
                // In function calls with 4 args, the second arg [1] is the `from` address
                let arg_index = if func.arguments.len() == 3 {
                    0
                } else if func.arguments.len() == 4 {
                    1
                } else {
                    continue;
                };

                let arg = &func.arguments[arg_index];

                if let Expression::Identifier(Identifier {
                    referenced_declaration: Some(referenced_id),
                    ..
                }) = arg
                    && func_parameters_ids.iter().any(|r| r == referenced_id)
                {
                    capture!(self, context, func);
                }
            }
        }

        Ok(!self.found_instances.is_empty())
    }

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

    fn title(&self) -> String {
        String::from("Arbitrary `from` Passed to `transferFrom`")
    }

    fn description(&self) -> String {
        String::from(
            "Passing an arbitrary `from` address to `transferFrom` (or `safeTransferFrom`) can lead to loss of funds, because anyone can transfer tokens from the `from` address if an approval is made.",
        )
    }

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

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

#[cfg(test)]
mod arbitrary_transfer_from_tests {

    use crate::detect::{
        detector::IssueDetector, high::arbitrary_transfer_from::ArbitraryTransferFromDetector,
    };

    #[test]

    fn test_arbitrary_transfer_from_detector_by_loading_contract_directly() {
        let context = crate::detect::test_utils::load_solidity_source_unit(
            "../tests/contract-playground/src/ArbitraryTransferFrom.sol",
        );

        let mut detector = ArbitraryTransferFromDetector::default();
        let found = detector.detect(&context).unwrap();
        assert!(found);
        assert_eq!(detector.instances().len(), 2);
    }
}

```

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

```rust
use std::{
    collections::{BTreeMap, HashMap},
    error::Error,
};

use crate::ast::NodeID;

use crate::{
    capture,
    context::workspace::WorkspaceContext,
    detect::detector::{IssueDetector, IssueDetectorNamePool, IssueSeverity},
};
use eyre::Result;

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

impl IssueDetector for FunctionSelectorCollisionDetector {
    fn detect(&mut self, context: &WorkspaceContext) -> Result<bool, Box<dyn Error>> {
        // function_selector -> (function_name -> function_id)
        let mut selectors: HashMap<String, HashMap<String, Vec<NodeID>>> = HashMap::new();

        // PLAN
        // If we have > 1 function_name entries for any function_selector, then capture all the
        // corresponding NodeIDs

        for function in context.function_definitions() {
            if let Some(selector) = function.function_selector.as_ref() {
                let name = &function.name;
                match selectors.entry(selector.clone()) {
                    std::collections::hash_map::Entry::Occupied(mut o) => {
                        match o.get_mut().entry(name.clone()) {
                            std::collections::hash_map::Entry::Occupied(mut o) => {
                                o.get_mut().push(function.id);
                            }
                            std::collections::hash_map::Entry::Vacant(v) => {
                                v.insert(vec![function.id]);
                            }
                        };
                    }
                    std::collections::hash_map::Entry::Vacant(v) => {
                        let mut nested_entry = HashMap::new();
                        nested_entry.insert(name.clone(), vec![function.id]);
                        v.insert(nested_entry);
                    }
                }
            }
        }

        for function_entries in selectors.values() {
            if function_entries.len() >= 2 {
                // Now we know that there is a collision + at least 2 different function names found
                // for that selector.

                // Capture the relevant functions
                for (function_name, function_ids) in function_entries {
                    // Prepare data for the hint
                    let all_colliding_function_names = function_entries
                        .keys()
                        .filter(|&x| x != function_name)
                        .cloned()
                        .collect::<Vec<_>>();

                    for function_id in function_ids {
                        // Prepare the hint
                        let mut hint =
                            String::from("collides with the following function name(s) in scope: ");
                        hint.push_str(&all_colliding_function_names.join(", "));

                        // Capture the function
                        if let Some(node) = context.nodes.get(function_id) {
                            capture!(self, context, node, hint);
                        }
                    }
                }
            }
        }

        Ok(!self.found_instances.is_empty())
    }

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

    fn title(&self) -> String {
        String::from("Function Selector Collision")
    }

    fn description(&self) -> String {
        String::from(
            "Function selector collides with other functions. This may cause the solidity function dispatcher to invoke the wrong function if the functions happen to be included in the same contract through an inheritance hierarchy later down the line. It is recommended to rename this function or change its parameters.",
        )
    }

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

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

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

#[cfg(test)]
mod function_signature_collision {

    use crate::detect::{
        detector::IssueDetector,
        high::function_selector_collision::FunctionSelectorCollisionDetector,
    };

    #[test]

    fn test_function_signature_collision() {
        let context = crate::detect::test_utils::load_solidity_source_unit(
            "../tests/contract-playground/src/FunctionSignatureCollision.sol",
        );

        let mut detector = FunctionSelectorCollisionDetector::default();
        let found = detector.detect(&context).unwrap();
        assert!(found);
        assert_eq!(detector.instances().len(), 2);
    }
}

```

--------------------------------------------------------------------------------
/aderyn_driver/src/compile.rs:
--------------------------------------------------------------------------------

```rust
#![allow(unstable_name_collisions)]

use aderyn_core::{
    ast::SourceUnit, context::workspace::WorkspaceContext, visitor::ast_visitor::Node,
};
use rayon::iter::{IntoParallelIterator, ParallelIterator};
use solidity_ast::{
    AstSourceFile, ExcludeConfig, IncludeConfig, ProjectConfigInput, ProjectConfigInputBuilder,
    Source, SourcesConfig, derive_ast_and_evm_info,
};
use std::{path::PathBuf, str::FromStr};

use crate::{
    display::{display_configuration_info, display_header, display_ingesting_message},
    process::PreprocessedConfig,
};

pub fn compile_project(
    preprocessed_config: PreprocessedConfig,
    lsp_mode: bool,
    verbose: bool,
) -> Result<(Vec<WorkspaceContext>, ProjectConfigInput), Box<dyn std::error::Error + Sync + Send>> {
    // Decompose pre-processed config
    let PreprocessedConfig { root_path, src, include, exclude } = preprocessed_config;

    // Process the pre-processed config using Cyfrin/solidity-ast-rs to translate to runtime values
    let path_form_src = |src: &str| -> PathBuf { PathBuf::from_str(src).unwrap() };
    let processed_config = ProjectConfigInputBuilder::new(&root_path)
        .with_sources(src.map_or_default(|src| SourcesConfig::Specific(path_form_src(&src))))
        .with_exclude(exclude.map_or_default(|exclude| ExcludeConfig::Specific(exclude.to_vec())))
        .with_include(include.map_or_default(|include| IncludeConfig::Specific(include.to_vec())))
        .build()?;

    if verbose {
        display_configuration_info(&processed_config);
        display_header(&processed_config, "Compiling Abstract Syntax Trees");
    }

    // Derive the raw AST content from the source files as per the processed config
    let derived_ast_evm_info = match derive_ast_and_evm_info(&processed_config) {
        Ok(results) => results,
        Err(e) => {
            eprintln!("Failed to Derive AST & EVM Info: {}", e);
            return Err("Failed to Derive AST / EVM info".into());
        }
    };

    // Parse the AST content into WorkspaceContexts
    let contexts_results = derived_ast_evm_info
        .versioned_asts
        .into_par_iter() // TODO: Bench to see which is faster - iter() or par_iter()?
        .map(|ast_info| {
            let mut context = WorkspaceContext::default();

            let sources = ast_info.sources.0;
            let sources_ast = ast_info.compiler_output.sources;
            let included = ast_info.included_files;

            for cerror in ast_info.compiler_output.errors {
                if cerror.severity.is_error() {
                    eprintln!("Compilation Error: {}", cerror);
                    return None;
                }
            }

            if verbose {
                display_ingesting_message(&sources_ast, &included, &ast_info.version.to_string());
            }
            for (source_path, ast_source_file) in sources_ast {
                let content = sources.get(&source_path).expect("content not found");
                absorb_ast_content_into_context(ast_source_file, &mut context, content.clone());
                context.src_filepaths.push(source_path.display().to_string());
            }

            context.evm_version = derived_ast_evm_info.evm_version;
            context.included = included;

            Some(context)
        })
        .collect::<Vec<_>>();

    // Only when not in LSP mode, error out if some context had compilation errors
    if !lsp_mode && contexts_results.iter().any(|c| c.is_none()) {
        std::process::exit(1);
    }

    if verbose {
        display_header(&processed_config, "Scanning Contracts");
    }

    // Return the parsed ASTs as a vector of Workspace Contexts
    Ok((contexts_results.into_iter().flatten().collect(), processed_config))
}

fn absorb_ast_content_into_context(
    ast_source_file: AstSourceFile,
    context: &mut WorkspaceContext,
    content: Source,
) {
    let Some(ast_content) = ast_source_file.ast else {
        eprintln!("Warning: AST not found in output");
        return;
    };

    let Ok(mut source_unit) = serde_json::from_str::<SourceUnit>(&ast_content) else {
        eprintln!("Unable to serialize Source Unit from AST - \n{}\n", &ast_content);
        let error = serde_json::from_str::<SourceUnit>(&ast_content).unwrap_err();
        eprintln!("{:?}", error);
        std::process::exit(1);
    };

    // Set the source
    source_unit.source = Some(content.content.to_string());

    // Read the relative filepath
    let filepath = source_unit.absolute_path.as_ref().unwrap();

    // Reset absolute path.
    source_unit.absolute_path = Some(filepath.to_string());

    // TODO: Change absolute_path to type Path instead of String so we don't lose any unicode
    // characters (in the minority of cases)

    source_unit.accept(context).unwrap_or_else(|err| {
        // Exit with a non-zero exit code
        eprintln!("Error loading AST into WorkspaceContext");
        eprintln!("{:?}", err);
        std::process::exit(1);
    });
}

```

--------------------------------------------------------------------------------
/tests/ast/userDefinedValueType.json:
--------------------------------------------------------------------------------

```json
{"absolutePath":"a","exportedSymbols":{"C":[27],"MyAddress":[2],"MyUInt":[4],"f":[16]},"id":28,"nodeType":"SourceUnit","nodes":[{"canonicalName":"MyAddress","id":2,"name":"MyAddress","nameLocation":"5:9:1","nodeType":"UserDefinedValueTypeDefinition","src":"0:26:1","underlyingType":{"id":1,"name":"address","nodeType":"ElementaryTypeName","src":"18:7:1","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}},{"canonicalName":"MyUInt","id":4,"name":"MyUInt","nameLocation":"32:6:1","nodeType":"UserDefinedValueTypeDefinition","src":"27:20:1","underlyingType":{"id":3,"name":"uint","nodeType":"ElementaryTypeName","src":"42:4:1","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}},{"body":{"id":15,"nodeType":"Block","src":"61:34:1","statements":[{"assignments":[9],"declarations":[{"constant":false,"id":9,"mutability":"mutable","name":"a","nameLocation":"77:1:1","nodeType":"VariableDeclaration","scope":15,"src":"67:11:1","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_userDefinedValueType$_MyAddress_$2","typeString":"MyAddress"},"typeName":{"id":8,"nodeType":"UserDefinedTypeName","pathNode":{"id":7,"name":"MyAddress","nameLocations":["67:9:1"],"nodeType":"IdentifierPath","referencedDeclaration":2,"src":"67:9:1"},"referencedDeclaration":2,"src":"67:9:1","typeDescriptions":{"typeIdentifier":"t_userDefinedValueType$_MyAddress_$2","typeString":"MyAddress"}},"visibility":"internal"}],"id":10,"nodeType":"VariableDeclarationStatement","src":"67:11:1"},{"assignments":[13],"declarations":[{"constant":false,"id":13,"mutability":"mutable","name":"b","nameLocation":"91:1:1","nodeType":"VariableDeclaration","scope":15,"src":"84:8:1","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_userDefinedValueType$_MyUInt_$4","typeString":"MyUInt"},"typeName":{"id":12,"nodeType":"UserDefinedTypeName","pathNode":{"id":11,"name":"MyUInt","nameLocations":["84:6:1"],"nodeType":"IdentifierPath","referencedDeclaration":4,"src":"84:6:1"},"referencedDeclaration":4,"src":"84:6:1","typeDescriptions":{"typeIdentifier":"t_userDefinedValueType$_MyUInt_$4","typeString":"MyUInt"}},"visibility":"internal"}],"id":14,"nodeType":"VariableDeclarationStatement","src":"84:8:1"}]},"id":16,"implemented":true,"kind":"freeFunction","modifiers":[],"name":"f","nameLocation":"57:1:1","nodeType":"FunctionDefinition","parameters":{"id":5,"nodeType":"ParameterList","parameters":[],"src":"58:2:1"},"returnParameters":{"id":6,"nodeType":"ParameterList","parameters":[],"src":"61:0:1"},"scope":28,"src":"48:47:1","stateMutability":"nonpayable","virtual":false,"visibility":"internal"},{"abstract":false,"baseContracts":[],"canonicalName":"C","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":27,"linearizedBaseContracts":[27],"name":"C","nameLocation":"105:1:1","nodeType":"ContractDefinition","nodes":[{"canonicalName":"C.MyAddress","id":18,"name":"MyAddress","nameLocation":"118:9:1","nodeType":"UserDefinedValueTypeDefinition","src":"113:26:1","underlyingType":{"id":17,"name":"address","nodeType":"ElementaryTypeName","src":"131:7:1","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}},{"canonicalName":"C.MyUInt","id":20,"name":"MyUInt","nameLocation":"149:6:1","nodeType":"UserDefinedValueTypeDefinition","src":"144:20:1","underlyingType":{"id":19,"name":"uint","nodeType":"ElementaryTypeName","src":"159:4:1","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}},{"constant":false,"functionSelector":"97682884","id":26,"mutability":"mutable","name":"m","nameLocation":"205:1:1","nodeType":"VariableDeclaration","scope":27,"src":"169:37:1","stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_mapping$_t_userDefinedValueType$_MyAddress_$18_$_t_userDefinedValueType$_MyUInt_$20_$","typeString":"mapping(C.MyAddress => C.MyUInt)"},"typeName":{"id":25,"keyType":{"id":22,"nodeType":"UserDefinedTypeName","pathNode":{"id":21,"name":"MyAddress","nameLocations":["177:9:1"],"nodeType":"IdentifierPath","referencedDeclaration":18,"src":"177:9:1"},"referencedDeclaration":18,"src":"177:9:1","typeDescriptions":{"typeIdentifier":"t_userDefinedValueType$_MyAddress_$18","typeString":"C.MyAddress"}},"nodeType":"Mapping","src":"169:28:1","typeDescriptions":{"typeIdentifier":"t_mapping$_t_userDefinedValueType$_MyAddress_$18_$_t_userDefinedValueType$_MyUInt_$20_$","typeString":"mapping(C.MyAddress => C.MyUInt)"},"valueType":{"id":24,"nodeType":"UserDefinedTypeName","pathNode":{"id":23,"name":"MyUInt","nameLocations":["190:6:1"],"nodeType":"IdentifierPath","referencedDeclaration":20,"src":"190:6:1"},"referencedDeclaration":20,"src":"190:6:1","typeDescriptions":{"typeIdentifier":"t_userDefinedValueType$_MyUInt_$20","typeString":"C.MyUInt"}}},"visibility":"public"}],"scope":28,"src":"96:113:1","usedErrors":[]}],"src":"0:210:1"}

```

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

```rust
use crate::ast::*;
use std::fmt::Display;

impl Display for Statement {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Statement::VariableDeclarationStatement(stmt) => stmt.fmt(f),
            Statement::IfStatement(stmt) => stmt.fmt(f),
            Statement::ForStatement(stmt) => stmt.fmt(f),
            Statement::WhileStatement(stmt) => stmt.fmt(f),
            Statement::EmitStatement(stmt) => stmt.fmt(f),
            Statement::TryStatement(stmt) => stmt.fmt(f),
            Statement::RevertStatement(stmt) => stmt.fmt(f),
            Statement::UncheckedBlock(stmt) => stmt.fmt(f),
            Statement::Return(stmt) => stmt.fmt(f),
            Statement::ExpressionStatement(stmt) => stmt.fmt(f),
            Statement::InlineAssembly(..) => {
                f.write_str("assembly { /* WARNING: not implemented */ }")
            }
            _ => f.write_str("unrecognized!"),
        }
    }
}

impl Display for ExpressionStatement {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_fmt(format_args!("{}", self.expression))
    }
}

impl Display for VariableDeclarationStatement {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        if self.declarations.len() == 1 {
            if let Some(declaration) = self.declarations[0].as_ref() {
                f.write_fmt(format_args!("{declaration}"))?;
            } else {
                f.write_str("()")?;
            }
        } else {
            f.write_str("(")?;

            for (i, declaration) in self.declarations.iter().enumerate() {
                if i > 0 {
                    f.write_str(", ")?;
                }

                if let Some(declaration) = declaration {
                    f.write_fmt(format_args!("{declaration}"))?;
                }
            }

            f.write_str(")")?;
        }

        if let Some(initial_value) = self.initial_value.as_ref() {
            f.write_fmt(format_args!(" = {initial_value}"))?;
        }

        Ok(())
    }
}

impl Display for BlockOrStatement {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            BlockOrStatement::Block(block) => block.fmt(f),
            BlockOrStatement::Statement(statement) => statement.fmt(f),
        }
    }
}

impl Display for IfStatement {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_fmt(format_args!("if ({}) {}", self.condition, self.true_body))?;

        if let Some(false_body) = self.false_body.as_ref() {
            f.write_fmt(format_args!("\nelse {false_body}"))?;
        }

        Ok(())
    }
}

impl Display for ForStatement {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_str("for (")?;

        if let Some(initialization_expression) = self.initialization_expression.as_ref() {
            f.write_fmt(format_args!("{:?}", initialization_expression))?;
        }

        f.write_str("; ")?;

        if let Some(condition) = self.condition.as_ref() {
            f.write_fmt(format_args!("{condition}"))?;
        }

        f.write_str("; ")?;

        if let Some(loop_expression) = self.loop_expression.as_ref() {
            f.write_fmt(format_args!("{loop_expression}"))?;
        }

        f.write_fmt(format_args!(") {}", self.body))
    }
}

impl Display for WhileStatement {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_fmt(format_args!("while ({}) {}", self.condition, self.body))
    }
}

impl Display for DoWhileStatement {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_fmt(format_args!("do {} while({});", self.body, self.condition))
    }
}

impl Display for EmitStatement {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_fmt(format_args!("emit {}", self.event_call))
    }
}

impl Display for TryStatement {
    fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        unimplemented!()
    }
}

impl Display for RevertStatement {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_fmt(format_args!("revert {}", self.error_call))
    }
}

impl Display for TryCatchClause {
    fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        unimplemented!()
    }
}

impl Display for Return {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_str("return")?;

        if let Some(expression) = self.expression.as_ref() {
            f.write_fmt(format_args!(" {expression}"))?;
        }

        Ok(())
    }
}

impl Display for Break {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_str("break;")
    }
}

impl Display for Continue {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_str("continue;")
    }
}

```

--------------------------------------------------------------------------------
/aderyn_core/src/ast/impls/ctx/utils.rs:
--------------------------------------------------------------------------------

```rust
use crate::{ast::*, context::workspace::WorkspaceContext};

impl ContractDefinition {
    /// Returns sequence of all inherited contracts including itself in C3 linearized hierarchy
    #[inline]
    pub fn c3<'a>(
        &'a self,
        context: &'a WorkspaceContext,
    ) -> impl Iterator<Item = &'a ContractDefinition> {
        self.linearized_base_contracts.iter().flat_map(|c_id| context.nodes.get(c_id)).flat_map(
            |n| {
                if let ASTNode::ContractDefinition(c) = n {
                    return Some(c);
                }
                None
            },
        )
    }

    #[inline]
    pub fn next_in<'a>(
        &'a self,
        context: &'a WorkspaceContext,
        base_contract: &'a ContractDefinition,
    ) -> Option<&'a ContractDefinition> {
        let mut base_c3 = base_contract.c3(context);
        while let Some(c) = base_c3.next() {
            if c.id == self.id {
                return base_c3.next();
            }
        }
        None
    }

    #[inline]
    pub fn is_in<'a>(
        &'a self,
        context: &'a WorkspaceContext,
        base_contract: &'a ContractDefinition,
    ) -> bool {
        let base_c3 = base_contract.c3(context);
        for c in base_c3 {
            if c.id == self.id {
                return true;
            }
        }
        false
    }

    pub fn entrypoint_functions<'a>(
        &'a self,
        context: &'a WorkspaceContext,
    ) -> Option<Vec<&'a FunctionDefinition>> {
        context.entrypoint_functions(self)
    }
}

impl FunctionCall {
    /// Returns the function definition referenced by the function call. In practice, it's not
    /// always the case that the function call will resolve to the referenced declaration. However,
    /// the type identifier of the real function (possibly overriding function) would be
    /// conserved i.e the same as the suspected target function
    ///
    /// Also see [`FunctionCall::is_internal_call`]
    #[inline]
    pub fn suspected_target_function<'a>(
        &self,
        context: &'a WorkspaceContext,
    ) -> Option<&'a FunctionDefinition> {
        // The most common forms of expressions when making a function call is
        // 1) xyz()
        // 2) A.xyz() where A is super or any parent class or library name or a something on which
        //    library is being used for. (using lib for uint8) .... 6.xyz()
        match self.expression.as_ref() {
            Expression::Identifier(Identifier { referenced_declaration: Some(id), .. })
            | Expression::MemberAccess(MemberAccess { referenced_declaration: Some(id), .. }) => {
                if let Some(ASTNode::FunctionDefinition(func)) = context.nodes.get(id) {
                    Some(func)
                } else {
                    None
                }
            }
            // TODO: Improve this function heuristics by exhausting enum possibilities for
            // expression
            _ => None,
        }
    }
    /// Returns the function definition or variable declaration referenced by the function call.
    /// Also see [`FunctionCall::suspected_target_function`]
    #[inline]
    pub fn suspected_function_selector(&self, context: &WorkspaceContext) -> Option<String> {
        match self.expression.as_ref() {
            Expression::Identifier(Identifier { referenced_declaration: Some(id), .. }) => {
                if let Some(ASTNode::FunctionDefinition(func)) = context.nodes.get(id) {
                    func.function_selector.clone()
                } else {
                    None
                }
            }
            Expression::MemberAccess(MemberAccess { referenced_declaration: Some(id), .. }) => {
                let suspect = context.nodes.get(id)?;
                match suspect {
                    ASTNode::FunctionDefinition(func) => func.function_selector.clone(),
                    // could be referencing a public state variable (pseudo getter method)
                    ASTNode::VariableDeclaration(var) => var.function_selector.clone(),
                    _ => None,
                }
            }
            // TODO: Improve this function heuristics by exhausting enum possibilities for
            // expression.
            _ => None,
        }
    }
}

impl ModifierInvocation {
    /// Returns the modifier definition referenced by the modifier invocation. In practice, it's not
    /// always the case that the function call will resolve to the referenced declaration. However,
    /// the type identifier of the real modifier (possibly overriding modifier) would be
    /// conserved i.e the same as the suspected target modifier
    #[inline]
    pub fn suspected_target_modifier<'a>(
        &self,
        context: &'a WorkspaceContext,
    ) -> Option<&'a ModifierDefinition> {
        let target_id = self.modifier_name.referenced_declaration()?;
        if let Some(ASTNode::ModifierDefinition(modifier)) = context.nodes.get(&target_id) {
            return Some(modifier);
        }
        None
    }
}

```

--------------------------------------------------------------------------------
/tests/ast/documentation_on_statements.json:
--------------------------------------------------------------------------------

```json
{"absolutePath":"a","exportedSymbols":{"C":[27]},"id":28,"nodeType":"SourceUnit","nodes":[{"abstract":false,"baseContracts":[],"canonicalName":"C","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":27,"linearizedBaseContracts":[27],"name":"C","nameLocation":"9:1:1","nodeType":"ContractDefinition","nodes":[{"constant":false,"id":2,"mutability":"mutable","name":"a","nameLocation":"50:1:1","nodeType":"VariableDeclaration","scope":27,"src":"45:6:1","stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":1,"name":"uint","nodeType":"ElementaryTypeName","src":"45:4:1","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"},{"body":{"id":25,"nodeType":"Block","src":"99:229:1","statements":[{"body":{"id":21,"nodeType":"Block","src":"156:66:1","statements":[{"expression":{"id":19,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftHandSide":{"id":17,"name":"x","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":5,"src":"205:1:1","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"Assignment","operator":"*=","rightHandSide":{"hexValue":"32","id":18,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"210:1:1","typeDescriptions":{"typeIdentifier":"t_rational_2_by_1","typeString":"int_const 2"},"value":"2"},"src":"205:6:1","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":20,"nodeType":"ExpressionStatement","src":"205:6:1"}]},"condition":{"commonType":{"typeIdentifier":"t_uint256","typeString":"uint256"},"id":13,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftExpression":{"id":11,"name":"i","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":8,"src":"143:1:1","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"BinaryOperation","operator":"<","rightExpression":{"hexValue":"3230","id":12,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"147:2:1","typeDescriptions":{"typeIdentifier":"t_rational_20_by_1","typeString":"int_const 20"},"value":"20"},"src":"143:6:1","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"id":22,"initializationExpression":{"assignments":[8],"declarations":[{"constant":false,"id":8,"mutability":"mutable","name":"i","nameLocation":"136:1:1","nodeType":"VariableDeclaration","scope":22,"src":"131:6:1","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":7,"name":"uint","nodeType":"ElementaryTypeName","src":"131:4:1","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"id":10,"initialValue":{"hexValue":"30","id":9,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"140:1:1","typeDescriptions":{"typeIdentifier":"t_rational_0_by_1","typeString":"int_const 0"},"value":"0"},"nodeType":"VariableDeclarationStatement","src":"131:10:1"},"loopExpression":{"expression":{"id":15,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"151:3:1","subExpression":{"id":14,"name":"i","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":8,"src":"151:1:1","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":16,"nodeType":"ExpressionStatement","src":"151:3:1"},"nodeType":"ForStatement","src":"126:96:1"},{"expression":{"id":23,"name":"x","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":5,"src":"320:1:1","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"functionReturnParameters":6,"id":24,"nodeType":"Return","src":"313:8:1"}]},"functionSelector":"26121ff0","id":26,"implemented":true,"kind":"function","modifiers":[],"name":"f","nameLocation":"66:1:1","nodeType":"FunctionDefinition","parameters":{"id":3,"nodeType":"ParameterList","parameters":[],"src":"67:2:1"},"returnParameters":{"id":6,"nodeType":"ParameterList","parameters":[{"constant":false,"id":5,"mutability":"mutable","name":"x","nameLocation":"96:1:1","nodeType":"VariableDeclaration","scope":26,"src":"91:6:1","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":4,"name":"uint","nodeType":"ElementaryTypeName","src":"91:4:1","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"src":"90:8:1"},"scope":27,"src":"57:271:1","stateMutability":"pure","virtual":false,"visibility":"public"}],"scope":28,"src":"0:330:1","usedErrors":[]}],"src":"0:331:1"}

```

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

```rust
use std::collections::{HashMap, HashSet, hash_map};

use crate::{
    ast::{Expression, IdentifierOrIdentifierPath, NodeID, NodeType},
    context::{
        browser::{ExtractFunctionCalls, ExtractModifierInvocations},
        workspace::WorkspaceContext,
    },
};

use crate::context::graph::{
    Error, LegacyWorkspaceCallGraph, RawCallGraph, Result, traits::Transpose,
};

impl LegacyWorkspaceCallGraph {
    /// Formula to create [`WorkspaceCallGraph`] for global preprocessing .
    pub fn from_context(context: &WorkspaceContext) -> Result<LegacyWorkspaceCallGraph> {
        let mut raw_callgraph: RawCallGraph = HashMap::new();
        let mut visited: HashSet<NodeID> = HashSet::new();

        let funcs = context
            .function_definitions()
            .into_iter()
            .filter(|func| func.implemented)
            .collect::<Vec<_>>();

        let modifier_definitions = context.modifier_definitions();

        for func in funcs {
            dfs_to_create_graph(func.id, &mut raw_callgraph, &mut visited, context)
                .map_err(|_| Error::WorkspaceCallGraphDFSError)?;
        }

        for modifier in modifier_definitions {
            dfs_to_create_graph(modifier.id, &mut raw_callgraph, &mut visited, context)
                .map_err(|_| Error::WorkspaceCallGraphDFSError)?;
        }

        Ok(LegacyWorkspaceCallGraph { raw_callgraph })
    }
}

/// Make connections from each of the nodes of [`crate::ast::FunctionDefinition`] and
/// [`crate::ast::ModifierDefinition`] with their connected counterparts.
fn dfs_to_create_graph(
    id: NodeID,
    raw_callgraph: &mut RawCallGraph,
    visited: &mut HashSet<NodeID>,
    context: &WorkspaceContext,
) -> Result<()> {
    if visited.contains(&id) {
        return Ok(());
    }

    visited.insert(id);

    // Only deal with `id`s that are in scope right now
    if let Some(from_node) = context.nodes.get(&id) {
        // referenced_declarations from previous calls in the recursion stack need to be vetted
        if from_node.node_type() != NodeType::FunctionDefinition
            && from_node.node_type() != NodeType::ModifierDefinition
        {
            return Ok(());
        }

        // connections to FunctionDefinition
        let function_calls = ExtractFunctionCalls::from(from_node).extracted;
        for function_call in function_calls {
            if let Expression::Identifier(identifier) = function_call.expression.as_ref()
                && let Some(referenced_function_id) = identifier.referenced_declaration
            {
                create_connection_if_not_exists(id, referenced_function_id, raw_callgraph);
                dfs_to_create_graph(referenced_function_id, raw_callgraph, visited, context)?;
            }
        }

        // connections to ModifierDefinition
        let modifier_invocations = ExtractModifierInvocations::from(from_node).extracted;
        for modifier_invocation in &modifier_invocations {
            match &modifier_invocation.modifier_name {
                IdentifierOrIdentifierPath::Identifier(identifier) => {
                    if let Some(reference_modifier_id) = identifier.referenced_declaration {
                        create_connection_if_not_exists(id, reference_modifier_id, raw_callgraph);
                        dfs_to_create_graph(
                            reference_modifier_id,
                            raw_callgraph,
                            visited,
                            context,
                        )?;
                    }
                }
                IdentifierOrIdentifierPath::IdentifierPath(identifier_path) => {
                    let referenced_modifier_id = identifier_path.referenced_declaration;
                    create_connection_if_not_exists(id, referenced_modifier_id, raw_callgraph);
                    dfs_to_create_graph(referenced_modifier_id, raw_callgraph, visited, context)?;
                }
            }
        }
    }

    // Change the default return to error later in "strict mode" maybe, because if we
    // can't find the node that means, the file was not in scope and hence it is not
    // available in the context although references to it exist.
    Ok(())
}

fn create_connection_if_not_exists(
    from_id: NodeID,
    to_id: NodeID,
    raw_callgraph: &mut RawCallGraph,
) {
    match raw_callgraph.entry(from_id) {
        hash_map::Entry::Occupied(mut o) => {
            // Performance Tip: Maybe later use binary search (it requires keeping ascending order
            // while inserting tho)
            if !o.get().contains(&to_id) {
                o.get_mut().push(to_id);
            }
        }
        hash_map::Entry::Vacant(v) => {
            v.insert(vec![to_id]);
        }
    }
}

impl Transpose for RawCallGraph {
    fn reverse(&self) -> Self {
        let mut reversed_callgraph = RawCallGraph::default();
        for (from_id, tos) in self {
            for to_id in tos {
                create_connection_if_not_exists(*to_id, *from_id, &mut reversed_callgraph);
            }
        }
        reversed_callgraph
    }
}

```

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

```rust
use std::{
    collections::{BTreeMap, HashSet},
    error::Error,
};

use crate::{
    ast::{NodeID, NodeType},
    capture,
    context::{
        flow::{Cfg, CfgNodeId},
        workspace::WorkspaceContext,
    },
    detect::detector::{IssueDetector, IssueDetectorNamePool, IssueSeverity},
};
use eyre::Result;

// HOW TO USE THIS TEMPLATE:
// 1. Copy this file and rename it to the snake_case version of the issue you are detecting.
// 2. Rename the TemplateDetector struct and impl to your new issue name.
// 3. Add this file and detector struct to the mod.rs file in the same directory.
// 4. Implement the detect function to find instances of the issue.

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

impl IssueDetector for MultiplePlaceholdersDetector {
    fn detect(&mut self, context: &WorkspaceContext) -> Result<bool, Box<dyn Error>> {
        let multiple_placeholders = |cfg: &Cfg, start: CfgNodeId| -> bool {
            // collect starting points
            let placeholders: HashSet<CfgNodeId> = {
                let mut set: HashSet<CfgNodeId> = Default::default();
                fn collect_cfg_nodes(
                    cfg: &Cfg,
                    visited: &mut HashSet<CfgNodeId>,
                    curr_node: CfgNodeId,
                ) {
                    if visited.contains(&curr_node) {
                        return;
                    }
                    visited.insert(curr_node);

                    for child in curr_node.children(cfg) {
                        collect_cfg_nodes(cfg, visited, child);
                    }
                }
                collect_cfg_nodes(cfg, &mut set, start);
                set.into_iter()
                    .filter(|n| {
                        cfg.nodes.get(n).is_some_and(|c| {
                            c.reflect(context)
                                .is_some_and(|d| d.node_type() == NodeType::PlaceholderStatement)
                        })
                    })
                    .collect()
            };

            fn dfs(
                context: &WorkspaceContext,
                cfg: &Cfg,
                visited: &mut HashSet<CfgNodeId>,
                curr_node: CfgNodeId,
                count: &mut usize,
            ) {
                if visited.contains(&curr_node) {
                    return;
                }
                visited.insert(curr_node);

                if cfg.nodes.get(&curr_node).is_some_and(|c| {
                    c.reflect(context)
                        .is_some_and(|d| d.node_type() == NodeType::PlaceholderStatement)
                }) {
                    *count += 1
                }

                for child in curr_node.children(cfg) {
                    dfs(context, cfg, visited, child, count);
                }
            }

            for starting_point in placeholders {
                let mut visited: HashSet<CfgNodeId> = Default::default();
                let mut count = 0;
                dfs(context, cfg, &mut visited, starting_point, &mut count);
                if count > 1 {
                    return true;
                }
            }
            false
        };

        for modifier in context.modifier_definitions() {
            let Some((cfg, start, _)) = Cfg::from_modifier_body(context, modifier) else {
                continue;
            };
            if multiple_placeholders(&cfg, start) {
                capture!(self, context, modifier);
            }
        }
        Ok(!self.found_instances.is_empty())
    }

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

    fn title(&self) -> String {
        String::from("Multiple Placeholders in Modifier")
    }

    fn description(&self) -> String {
        String::from(
            "Design the modifier to only contain 1 placeholder statement. If that is not possible, split the logic into multiple modifiers.",
        )
    }

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

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

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

#[cfg(test)]
mod multiple_placeholder_tests {

    use crate::detect::{
        detector::IssueDetector, low::multiple_placeholders::MultiplePlaceholdersDetector,
        test_utils,
    };

    #[test]
    fn test_multiple_placeholders() {
        let context = test_utils::load_solidity_source_unit(
            "../tests/contract-playground/src/MultiplePlaceholders.sol",
        );

        let mut detector = MultiplePlaceholdersDetector::default();
        let found = detector.detect(&context).unwrap();
        assert!(found);
        assert_eq!(detector.instances().len(), 3);
    }
}

```

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

```rust
use regex::Regex;

use crate::{
    ast::{ASTNode, FunctionKind, NodeID, NodeType},
    context::{
        mcp::node_finder::render::{NodeInfo, NodeInfoBuilder},
        workspace::WorkspaceContext,
    },
};

// Matches functions, modifiers and contracts by their exact names.

#[inline]
pub fn get_matching_functions(idx: usize, context: &WorkspaceContext, name: &str) -> Vec<NodeInfo> {
    get_nodes_by_exact_name_match(idx, context, Some(name), NodeType::FunctionDefinition)
}

#[inline]
pub fn get_matching_modifiers(idx: usize, context: &WorkspaceContext, name: &str) -> Vec<NodeInfo> {
    get_nodes_by_exact_name_match(idx, context, Some(name), NodeType::ModifierDefinition)
}

#[inline]
pub fn get_matching_contracts(idx: usize, context: &WorkspaceContext, name: &str) -> Vec<NodeInfo> {
    get_nodes_by_exact_name_match(idx, context, Some(name), NodeType::ContractDefinition)
}

// Matches all events and errors.

#[inline]
pub fn get_all_events(idx: usize, context: &WorkspaceContext) -> Vec<NodeInfo> {
    get_nodes_by_exact_name_match(idx, context, None, NodeType::EventDefinition)
}

#[inline]
pub fn get_all_errors(idx: usize, context: &WorkspaceContext) -> Vec<NodeInfo> {
    get_nodes_by_exact_name_match(idx, context, None, NodeType::ErrorDefinition)
}

// Matches functions, modifiers and state variables whose code snippets match a given regex

#[inline]
pub fn grep_functions(idx: usize, context: &WorkspaceContext, term: &str) -> Vec<NodeInfo> {
    let regex = Regex::new(term).expect("invalid regex was passed");
    context
        .function_definitions()
        .into_iter()
        .filter(|&f| {
            let f: ASTNode = f.into();
            let code_snippet = context.get_code_snippet(&f);
            regex.is_match(&code_snippet)
        })
        .map(|func| {
            let func_kind = func.kind();
            let mut name = func.name.to_owned();

            if func_kind != &FunctionKind::Function {
                if name.is_empty() {
                    name = func_kind.to_string();
                } else {
                    name.push_str(&format!("( {} )", func_kind));
                }
            }

            NodeInfoBuilder::default()
                .name(name)
                .node_id(func.id)
                .compilation_unit_index(idx)
                .build()
                .expect("failed to build node info")
        })
        .collect()
}

#[inline]
pub fn grep_modifiers(idx: usize, context: &WorkspaceContext, term: &str) -> Vec<NodeInfo> {
    let regex = Regex::new(term).expect("invalid regex was passed");
    context
        .modifier_definitions()
        .into_iter()
        .filter(|&m| {
            let m: ASTNode = m.into();
            let code_snippet = context.get_code_snippet(&m);
            regex.is_match(&code_snippet)
        })
        .map(|modifier| {
            NodeInfoBuilder::default()
                .name(modifier.name.to_owned())
                .node_id(modifier.id)
                .compilation_unit_index(idx)
                .build()
                .expect("failed to build node info")
        })
        .collect()
}

#[inline]
pub fn grep_state_variables(idx: usize, context: &WorkspaceContext, term: &str) -> Vec<NodeInfo> {
    let regex = Regex::new(term).expect("invalid regex was passed");
    context
        .contract_definitions()
        .into_iter()
        .flat_map(|c| c.top_level_variables())
        .filter(|v| regex.is_match(&v.name))
        .map(|v| {
            NodeInfoBuilder::default()
                .name(v.name.to_string())
                .node_id(v.id)
                .compilation_unit_index(idx)
                .build()
                .expect("failed to build node info")
        })
        .collect()
}

// Helper functions

fn get_nodes_by_exact_name_match(
    compilation_unit_index: usize,
    context: &WorkspaceContext,
    search_term: Option<&str>,
    node_ty: NodeType,
) -> Vec<NodeInfo> {
    let mut matching_nodes = vec![];

    let mut add_node = |name: &str, id: NodeID| {
        if let Ok(node_info) = NodeInfoBuilder::default()
            .name(name.to_string())
            .node_id(id)
            .compilation_unit_index(compilation_unit_index)
            .build()
        {
            matching_nodes.push(node_info);
        }
    };

    match node_ty {
        NodeType::ContractDefinition => {
            context
                .contract_definitions()
                .iter()
                .filter(|m| search_term.is_none_or(|t| t == m.name))
                .for_each(|m| add_node(&m.name, m.id));
        }
        NodeType::FunctionDefinition => {
            context
                .function_definitions()
                .iter()
                .filter(|m| search_term.is_none_or(|t| t == m.name))
                .for_each(|m| add_node(&m.name, m.id));
        }
        NodeType::ModifierDefinition => {
            context
                .modifier_definitions()
                .iter()
                .filter(|m| search_term.is_none_or(|t| t == m.name))
                .for_each(|m| add_node(&m.name, m.id));
        }
        _ => {}
    };
    matching_nodes
}

```

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

```rust
use std::{collections::BTreeMap, error::Error};

use crate::ast::{NodeID, NodeType, TypeName};

use crate::{
    capture,
    context::{
        browser::ExtractPragmaDirectives,
        workspace::{ASTNode, WorkspaceContext},
    },
    detect::{
        detector::{IssueDetector, IssueDetectorNamePool, IssueSeverity},
        helpers::pragma_directive_to_semver,
    },
};
use eyre::Result;
use semver::VersionReq;

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

fn version_req_allows_below_0_5_0(version_req: &VersionReq) -> bool {
    if version_req.comparators.is_empty() {
        return false; // Return false or handle as needed if there are no comparators
    }

    let comparator = &version_req.comparators[0];
    comparator.major == 0 && comparator.minor.is_some_and(|m| m < 5)
}

impl IssueDetector for NestedStructInMappingDetector {
    fn detect(&mut self, context: &WorkspaceContext) -> Result<bool, Box<dyn Error>> {
        // When you have found an instance of the issue,
        // use the following macro to add it to `found_instances`:
        //
        // capture!(self, context, item);

        let mappings = context.variable_declarations().into_iter().filter(|vd| {
            if let Some(type_name) = &vd.type_name {
                if let TypeName::Mapping(_) = type_name {
                    return true;
                }
                return false;
            }
            false
        });

        for mapping in mappings {
            if let Some(TypeName::Mapping(mapping_type)) = &mapping.type_name
                && let TypeName::UserDefinedTypeName(user_defined_type) = &*mapping_type.value_type
            {
                let struct_definition_ast_node =
                    context.nodes.get(&user_defined_type.referenced_declaration);
                if let Some(ASTNode::StructDefinition(struct_definition)) =
                    struct_definition_ast_node
                {
                    for member in struct_definition.members.iter() {
                        if let Some(member_type_string) = &member.type_descriptions.type_string
                            && member_type_string.contains("struct")
                        {
                            // Check if the contract that this is in allows for solidity
                            // pragma below 0.5.0
                            let source_unit_ast_node =
                                context.get_closest_ancestor(mapping.id, NodeType::SourceUnit);
                            if let Some(source_unit_ast_node) = source_unit_ast_node {
                                let pragma_directives =
                                    ExtractPragmaDirectives::from(source_unit_ast_node).extracted;
                                let version_req =
                                    pragma_directive_to_semver(pragma_directives.first().unwrap())?;
                                if version_req_allows_below_0_5_0(&version_req) {
                                    capture!(self, context, mapping);
                                }
                            }
                        }
                    }
                }
            }
        }

        Ok(!self.found_instances.is_empty())
    }

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

    fn title(&self) -> String {
        String::from("Nested Structs in Mappings pre-0.5.0")
    }

    fn description(&self) -> String {
        String::from(
            "Prior to updates in Solidity 0.5.0, public mappings with nested structs compiled, but produced incorrect values. Refrain from using these, or update to a more recent version of Solidity.",
        )
    }

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

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

#[cfg(test)]
mod nested_struct_in_mapping_detector_tests {

    use crate::detect::{detector::IssueDetector, high::NestedStructInMappingDetector};

    #[test]

    fn test_nested_struct_in_mapping_detector() {
        let context = crate::detect::test_utils::load_solidity_source_unit(
            "../tests/contract-playground/src/nested_mappings/NestedMappings.sol",
        );

        let mut detector = NestedStructInMappingDetector::default();
        let found = detector.detect(&context).unwrap();
        assert!(found);
        assert_eq!(detector.instances().len(), 1);
    }

    #[test]

    fn test_nested_struct_in_mapping_detector_no_issue() {
        let context = crate::detect::test_utils::load_solidity_source_unit(
            "../tests/contract-playground/src/nested_mappings/LaterVersion.sol",
        );

        let mut detector = NestedStructInMappingDetector::default();
        let found = detector.detect(&context).unwrap();
        assert!(!found);
        assert_eq!(detector.instances().len(), 0);
    }
}

```

--------------------------------------------------------------------------------
/tests/ast/documentation_triple.json:
--------------------------------------------------------------------------------

```json
{"absolutePath":"a","exportedSymbols":{"C":[28]},"id":29,"nodeType":"SourceUnit","nodes":[{"abstract":false,"baseContracts":[],"canonicalName":"C","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":28,"linearizedBaseContracts":[28],"name":"C","nameLocation":"9:1:1","nodeType":"ContractDefinition","nodes":[{"constant":false,"documentation":{"id":1,"nodeType":"StructuredDocumentation","src":"17:8:1","text":"test"},"id":3,"mutability":"mutable","name":"a","nameLocation":"35:1:1","nodeType":"VariableDeclaration","scope":28,"src":"30:6:1","stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":2,"name":"uint","nodeType":"ElementaryTypeName","src":"30:4:1","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"},{"body":{"id":26,"nodeType":"Block","src":"84:181:1","statements":[{"body":{"id":22,"nodeType":"Block","src":"142:75:1","statements":[{"documentation":"tee\n s \"t\" 3","expression":{"id":20,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftHandSide":{"id":18,"name":"x","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":6,"src":"200:1:1","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"Assignment","operator":"*=","rightHandSide":{"hexValue":"32","id":19,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"205:1:1","typeDescriptions":{"typeIdentifier":"t_rational_2_by_1","typeString":"int_const 2"},"value":"2"},"src":"200:6:1","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":21,"nodeType":"ExpressionStatement","src":"200:6:1"}]},"condition":{"commonType":{"typeIdentifier":"t_uint256","typeString":"uint256"},"id":14,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftExpression":{"id":12,"name":"i","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":9,"src":"129:1:1","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"BinaryOperation","operator":"<","rightExpression":{"hexValue":"3230","id":13,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"133:2:1","typeDescriptions":{"typeIdentifier":"t_rational_20_by_1","typeString":"int_const 20"},"value":"20"},"src":"129:6:1","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"documentation":"test2","id":23,"initializationExpression":{"assignments":[9],"declarations":[{"constant":false,"id":9,"mutability":"mutable","name":"i","nameLocation":"122:1:1","nodeType":"VariableDeclaration","scope":23,"src":"117:6:1","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":8,"name":"uint","nodeType":"ElementaryTypeName","src":"117:4:1","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"id":11,"initialValue":{"hexValue":"30","id":10,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"126:1:1","typeDescriptions":{"typeIdentifier":"t_rational_0_by_1","typeString":"int_const 0"},"value":"0"},"nodeType":"VariableDeclarationStatement","src":"117:10:1"},"loopExpression":{"expression":{"id":16,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"137:3:1","subExpression":{"id":15,"name":"i","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":9,"src":"137:1:1","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":17,"nodeType":"ExpressionStatement","src":"137:3:1"},"nodeType":"ForStatement","src":"112:105:1"},{"documentation":"tes \"t4\" ","expression":{"id":24,"name":"x","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":6,"src":"257:1:1","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"functionReturnParameters":7,"id":25,"nodeType":"Return","src":"250:8:1"}]},"functionSelector":"26121ff0","id":27,"implemented":true,"kind":"function","modifiers":[],"name":"f","nameLocation":"51:1:1","nodeType":"FunctionDefinition","parameters":{"id":4,"nodeType":"ParameterList","parameters":[],"src":"52:2:1"},"returnParameters":{"id":7,"nodeType":"ParameterList","parameters":[{"constant":false,"id":6,"mutability":"mutable","name":"x","nameLocation":"81:1:1","nodeType":"VariableDeclaration","scope":27,"src":"76:6:1","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":5,"name":"uint","nodeType":"ElementaryTypeName","src":"76:4:1","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"src":"75:8:1"},"scope":28,"src":"42:223:1","stateMutability":"pure","virtual":false,"visibility":"public"}],"scope":29,"src":"0:267:1","usedErrors":[]}],"src":"0:268:1"}

```

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

```rust
use crate::{
    ast::{ASTNode, NodeID, NodeType},
    context::{
        graph::RawCallGraph,
        mcp::node_summarizer::render::{
            EntrypointCallgraphInfo, EntrypointCallgraphInfoBuilder, NodeInfo, NodeInfoBuilder,
        },
        workspace::WorkspaceContext,
    },
};
use std::collections::{HashMap, HashSet, hash_map::Entry};

pub fn get_containing_contract(context: &WorkspaceContext, node: &ASTNode) -> Option<NodeInfo> {
    if let ASTNode::ContractDefinition(_) = node {
        return None;
    }
    let Some(ASTNode::ContractDefinition(parent_contract)) = context.get_closest_ancestor(
        node.id().expect("node found without an ID"),
        NodeType::ContractDefinition,
    ) else {
        return None;
    };
    Some((parent_contract.id, parent_contract.name.clone()).into())
}

pub fn get_containing_modifier(context: &WorkspaceContext, node: &ASTNode) -> Option<NodeInfo> {
    if let ASTNode::ModifierDefinition(_) = node {
        return None;
    }
    let Some(ASTNode::ModifierDefinition(parent_modifier)) = context.get_closest_ancestor(
        node.id().expect("node found without an ID"),
        NodeType::ModifierDefinition,
    ) else {
        return None;
    };
    Some((parent_modifier.id, parent_modifier.name.clone()).into())
}

pub fn get_containing_function(context: &WorkspaceContext, node: &ASTNode) -> Option<NodeInfo> {
    if let ASTNode::FunctionDefinition(_) = node {
        return None;
    }
    let Some(ASTNode::FunctionDefinition(parent_function)) = context.get_closest_ancestor(
        node.id().expect("node found without an ID"),
        NodeType::FunctionDefinition,
    ) else {
        return None;
    };
    Some((parent_function.id, parent_function.name.clone()).into())
}

impl From<(NodeID, String)> for NodeInfo {
    fn from(value: (NodeID, String)) -> Self {
        NodeInfoBuilder::default()
            .name(value.1)
            .node_id(value.0)
            .build()
            .expect("failed to build node info")
    }
}

pub fn get_containing_callgraphs(
    context: &WorkspaceContext,
    node: &ASTNode,
) -> Vec<EntrypointCallgraphInfo> {
    // Given node, we want to locate it in the callgraph
    let node_id = node.id().expect("node found without an ID");

    let parent_graph_node = match (
        context.get_closest_ancestor_including_self(node_id, NodeType::FunctionDefinition),
        context.get_closest_ancestor_including_self(node_id, NodeType::ModifierDefinition),
    ) {
        (Some(ASTNode::FunctionDefinition(func)), _) => Some(func.id),
        (_, Some(ASTNode::ModifierDefinition(modifier))) => Some(modifier.id),
        (_, _) => None,
    };

    let Some(parent_graph_node) = parent_graph_node else {
        return vec![];
    };

    // Keys => (deployabele contract id, contract name), Values => entrypoint function ids
    let mut entrypoint_info: HashMap<(NodeID, String), Vec<NodeID>> = HashMap::new();

    for contract in context.deployable_contracts() {
        let Some(contract_callgraph) =
            context.callgraphs.as_ref().and_then(|c| c.outward_callgraphs.get(&contract.id))
        else {
            continue;
        };
        let Some(entrypoint_ids) = contract
            .entrypoint_functions(context)
            .map(|funcs| funcs.into_iter().map(|f| f.id).collect::<HashSet<_>>())
        else {
            continue;
        };
        let reachable_entrypoints = traverse_cg_and_get_reachable_entrypoints(
            parent_graph_node,
            contract_callgraph,
            &entrypoint_ids,
        );

        for entrypoint_id in reachable_entrypoints {
            match entrypoint_info.entry((contract.id, contract.name.to_owned())) {
                Entry::Occupied(mut o) => {
                    o.get_mut().push(entrypoint_id);
                }
                Entry::Vacant(v) => {
                    v.insert(vec![entrypoint_id]);
                }
            }
        }
    }

    entrypoint_info
        .into_iter()
        .map(|((contract_id, contract_name), entrypoints)| {
            EntrypointCallgraphInfoBuilder::default()
                .deployable_contract_id(contract_id)
                .deployable_contract_name(contract_name)
                .entrypoint_ids(entrypoints)
                .build()
                .expect("failed to build entrypoint callgraph info")
        })
        .collect()
}

fn traverse_cg_and_get_reachable_entrypoints(
    node_id: NodeID,
    outward_cg: &RawCallGraph,
    entrypoint_ids: &HashSet<NodeID>,
) -> HashSet<NodeID> {
    // Visit all possible nodes starting from node_id in the outward callgraph. Then collect all the
    // nodes which can be potential starting points that lead to node_id in the (real) inward
    // callgraph.
    let mut worklist = vec![node_id];
    let mut visited: HashSet<NodeID> = Default::default();

    while let Some(node) = worklist.pop() {
        if visited.contains(&node) {
            continue;
        }
        visited.insert(node);

        if let Some(connections) = outward_cg.get(&node) {
            for conn in connections {
                worklist.push(*conn);
            }
        }
    }

    visited.into_iter().filter(|f| entrypoint_ids.contains(f)).collect()
}

```

--------------------------------------------------------------------------------
/benchmarks/unsafe-erc20-functions/report/relative_regression_small.svg:
--------------------------------------------------------------------------------

```
<svg width="450" height="300" viewBox="0 0 450 300" xmlns="http://www.w3.org/2000/svg">
<text x="15" y="130" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000" transform="rotate(270, 15, 130)">
Total sample time (ms)
</text>
<text x="255" y="285" dy="-0.5ex" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
Iterations (x 10^3)
</text>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="244" x2="75" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="139" y1="244" x2="139" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="203" y1="244" x2="203" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="267" y1="244" x2="267" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="331" y1="244" x2="331" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="395" y1="244" x2="395" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="244" x2="434" y2="244"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="208" x2="434" y2="208"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="171" x2="434" y2="171"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="134" x2="434" y2="134"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="97" x2="434" y2="97"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="61" x2="434" y2="61"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="24" x2="434" y2="24"/>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="74,15 74,244 "/>
<text x="65" y="244" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="69,244 74,244 "/>
<text x="65" y="208" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
20.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="69,208 74,208 "/>
<text x="65" y="171" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
40.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="69,171 74,171 "/>
<text x="65" y="134" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
60.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="69,134 74,134 "/>
<text x="65" y="97" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
80.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="69,97 74,97 "/>
<text x="65" y="61" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
100.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="69,61 74,61 "/>
<text x="65" y="24" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
120.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="69,24 74,24 "/>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="75,245 434,245 "/>
<text x="75" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="75,245 75,250 "/>
<text x="139" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.5
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="139,245 139,250 "/>
<text x="203" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
1
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="203,245 203,250 "/>
<text x="267" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
1.5
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="267,245 267,250 "/>
<text x="331" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
2
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="331,245 331,250 "/>
<text x="395" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
2.5
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="395,245 395,250 "/>
<polyline fill="none" opacity="1" stroke="#E31A1C" stroke-width="1" points="75,244 434,60 "/>
<polygon opacity="0.25" fill="#E31A1C" points="75,244 434,60 434,60 "/>
<polyline fill="none" opacity="1" stroke="#1F78B4" stroke-width="1" points="75,244 434,15 "/>
<polygon opacity="0.25" fill="#1F78B4" points="75,244 434,19 434,15 "/>
</svg>

```

--------------------------------------------------------------------------------
/benchmarks/unspecific-solidity-pragma/report/relative_regression_small.svg:
--------------------------------------------------------------------------------

```
<svg width="450" height="300" viewBox="0 0 450 300" xmlns="http://www.w3.org/2000/svg">
<text x="15" y="130" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000" transform="rotate(270, 15, 130)">
Total sample time (ms)
</text>
<text x="255" y="285" dy="-0.5ex" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
Iterations (x 10^3)
</text>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="244" x2="75" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="133" y1="244" x2="133" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="192" y1="244" x2="192" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="251" y1="244" x2="251" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="310" y1="244" x2="310" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="369" y1="244" x2="369" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="428" y1="244" x2="428" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="244" x2="434" y2="244"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="203" x2="434" y2="203"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="162" x2="434" y2="162"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="120" x2="434" y2="120"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="79" x2="434" y2="79"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="37" x2="434" y2="37"/>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="74,15 74,244 "/>
<text x="65" y="244" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="69,244 74,244 "/>
<text x="65" y="203" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
20.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="69,203 74,203 "/>
<text x="65" y="162" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
40.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="69,162 74,162 "/>
<text x="65" y="120" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
60.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="69,120 74,120 "/>
<text x="65" y="79" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
80.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="69,79 74,79 "/>
<text x="65" y="37" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
100.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="69,37 74,37 "/>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="75,245 434,245 "/>
<text x="75" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="75,245 75,250 "/>
<text x="133" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
1
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="133,245 133,250 "/>
<text x="192" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
2
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="192,245 192,250 "/>
<text x="251" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
3
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="251,245 251,250 "/>
<text x="310" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
4
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="310,245 310,250 "/>
<text x="369" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
5
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="369,245 369,250 "/>
<text x="428" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
6
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="428,245 428,250 "/>
<polyline fill="none" opacity="1" stroke="#E31A1C" stroke-width="1" points="75,244 434,15 "/>
<polygon opacity="0.25" fill="#E31A1C" points="75,244 434,21 434,15 "/>
<polyline fill="none" opacity="1" stroke="#1F78B4" stroke-width="1" points="75,244 434,40 "/>
<polygon opacity="0.25" fill="#1F78B4" points="75,244 434,41 434,38 "/>
</svg>

```
Page 8/94FirstPrevNextLast