#
tokens: 49079/50000 19/1140 files (page 9/94)
lines: off (toggle) GitHub
raw markdown copy
This is page 9 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/both/regression.svg:
--------------------------------------------------------------------------------

```
<svg width="960" height="540" viewBox="0 0 960 540" xmlns="http://www.w3.org/2000/svg">
<text x="480" y="32" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="16.129032258064516" opacity="1" fill="#000000">
push-zero-opcode
</text>
<text x="27" y="263" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000" transform="rotate(270, 27, 263)">
Total sample time (ms)
</text>
<text x="510" y="513" 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="87" y1="472" x2="87" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="279" y1="472" x2="279" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="471" y1="472" x2="471" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="663" y1="472" x2="663" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="855" y1="472" x2="855" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="472" x2="932" y2="472"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="397" x2="932" y2="397"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="321" x2="932" y2="321"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="245" x2="932" y2="245"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="169" x2="932" y2="169"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="93" x2="932" y2="93"/>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="86,53 86,472 "/>
<text x="77" y="472" 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="81,472 86,472 "/>
<text x="77" y="397" 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="81,397 86,397 "/>
<text x="77" y="321" 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="81,321 86,321 "/>
<text x="77" y="245" 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="81,245 86,245 "/>
<text x="77" y="169" 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="81,169 86,169 "/>
<text x="77" y="93" 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="81,93 86,93 "/>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="87,473 932,473 "/>
<text x="87" y="483" 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="87,473 87,478 "/>
<text x="279" y="483" 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="279,473 279,478 "/>
<text x="471" y="483" 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="471,473 471,478 "/>
<text x="663" y="483" 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="663,473 663,478 "/>
<text x="855" y="483" 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="855,473 855,478 "/>
<polyline fill="none" opacity="1" stroke="#E31A1C" stroke-width="1" points="87,472 932,53 "/>
<polygon opacity="0.25" fill="#E31A1C" points="87,472 932,68 932,53 "/>
<polyline fill="none" opacity="1" stroke="#1F78B4" stroke-width="1" points="87,472 932,119 "/>
<polygon opacity="0.25" fill="#1F78B4" points="87,472 932,128 932,108 "/>
<text x="132" y="68" dy="0.76em" text-anchor="start" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
Base Sample
</text>
<text x="132" y="83" dy="0.76em" text-anchor="start" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
New Sample
</text>
<polyline fill="none" opacity="1" stroke="#E31A1C" stroke-width="2" points="102,73 122,73 "/>
<polyline fill="none" opacity="1" stroke="#1F78B4" stroke-width="2" points="102,88 122,88 "/>
</svg>

```

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

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

use crate::ast::{NodeID, StateMutability};

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

#[derive(Default)]
pub struct ConstantFunctionChangesStateDetector {
    // 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 ConstantFunctionChangesStateDetector {
    fn detect(&mut self, context: &WorkspaceContext) -> Result<bool, Box<dyn Error>> {
        for func in helpers::get_implemented_external_and_public_functions(context) {
            // Rule applies to only view functions, so ignore the rest
            if func.state_mutability() != &StateMutability::View {
                continue;
            }
            // Check if this func is compilable for solc < 0.5.0. If not, move on to the next
            if !func.compiles_for_solc_below_0_5_0(context) {
                continue;
            }
            // Now, investigate the function to see if there is scope for any state variable changes
            let mut tracker = StateVariableChangeTracker { state_var_has_changed: false, context };

            // Keep legacy for this because it is for solc version below 0.5.0 and the function
            // selectors don't exist
            let callgraph = CallGraphConsumer::get_legacy(
                context,
                &[&(func.into())],
                CallGraphDirection::Inward,
            )?;
            callgraph.accept(context, &mut tracker)?;

            if tracker.state_var_has_changed {
                capture!(self, context, func);
            }
        }

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

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

    fn title(&self) -> String {
        String::from("Constant functions changes state")
    }

    fn description(&self) -> String {
        String::from(
            "Function is declared constant/view but it changes state. Ensure that the attributes of contract compiled prior to 0.5 are correct.",
        )
    }

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

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

struct StateVariableChangeTracker<'a> {
    state_var_has_changed: bool,
    context: &'a WorkspaceContext,
}

impl CallGraphVisitor for StateVariableChangeTracker<'_> {
    fn visit_any(&mut self, node: &crate::ast::ASTNode) -> eyre::Result<()> {
        if self.state_var_has_changed {
            return Ok(());
        }
        // Check for state variable changes
        let finder = ApproximateStorageChangeFinder::from(self.context, node);
        if finder.state_variables_have_been_manipulated() {
            self.state_var_has_changed = true;
        }
        Ok(())
    }
}

mod func_compilation_solc_pragma_helper {
    use std::str::FromStr;

    use semver::{Version, VersionReq};

    use crate::{
        ast::{FunctionDefinition, NodeType},
        context::{
            browser::{ExtractPragmaDirectives, GetClosestAncestorOfTypeX},
            workspace::WorkspaceContext,
        },
        detect::helpers,
    };

    impl FunctionDefinition {
        pub fn compiles_for_solc_below_0_5_0(&self, context: &WorkspaceContext) -> bool {
            if let Some(source_unit) = self.closest_ancestor_of_type(context, NodeType::SourceUnit)
            {
                let pragma_directives = ExtractPragmaDirectives::from(source_unit).extracted;

                if let Some(pragma_directive) = pragma_directives.first()
                    && let Ok(pragma_semver) = helpers::pragma_directive_to_semver(pragma_directive)
                    && version_req_allows_below_0_5_0(&pragma_semver)
                {
                    return true;
                }
            }
            false
        }
    }

    fn version_req_allows_below_0_5_0(version_req: &VersionReq) -> bool {
        // If it matches any 0.4.0 to 0.4.26, return true
        for i in 0..=26 {
            let version = Version::from_str(&format!("0.4.{}", i)).unwrap();
            if version_req.matches(&version) {
                return true;
            }
        }

        // Else, return false
        false
    }
}

#[cfg(test)]
mod constant_func_changing_state {

    use crate::detect::{
        detector::IssueDetector,
        high::const_func_changes_state::ConstantFunctionChangesStateDetector,
    };

    #[test]

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

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

```

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

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

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

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

#[derive(Default)]
pub struct TxOriginUsedForAuthDetector {
    // 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 TxOriginUsedForAuthDetector {
    fn detect(&mut self, context: &WorkspaceContext) -> Result<bool, Box<dyn Error>> {
        for if_statement in context.if_statements() {
            // Check within the condition block only
            let ast_node: ASTNode = if_statement.condition.clone().into();
            self.check_eligibility_and_capture(context, &[&ast_node], &(if_statement.into()))?;
        }

        for function_call in context.function_calls() {
            if let Expression::Identifier(Identifier { name, .. }) =
                function_call.expression.as_ref()
            {
                if name != "require" {
                    continue;
                }

                // Now, check for arguments of the `require(..., "message")` function call
                let arguments = function_call
                    .arguments
                    .clone()
                    .into_iter()
                    .map(|n| n.into())
                    .collect::<Vec<ASTNode>>();

                let ast_nodes: &[&ASTNode] = &(arguments.iter().collect::<Vec<_>>());
                self.check_eligibility_and_capture(context, ast_nodes, &(function_call.into()))?;
            }
        }

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

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

    fn title(&self) -> String {
        String::from("Use of `tx.origin` for authentication")
    }

    fn description(&self) -> String {
        String::from(
            "Using `tx.origin` may lead to problems when users are interacting via smart contract with your \
            protocol. It is recommended to use `msg.sender` for authentication.",
        )
    }

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

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

impl TxOriginUsedForAuthDetector {
    fn check_eligibility_and_capture(
        &mut self,
        context: &WorkspaceContext,
        check_nodes: &[&ASTNode],
        capture_node: &ASTNode,
    ) -> Result<(), Box<dyn Error>> {
        // Boilerplate
        let callgraphs = CallGraphConsumer::get(context, check_nodes, CallGraphDirection::Inward)?;
        for callgraph in callgraphs {
            let mut tracker = MsgSenderAndTxOriginTracker::default();
            callgraph.accept(context, &mut tracker)?;

            if tracker.satisfied() {
                capture!(self, context, capture_node);
            }
        }
        Ok(())
    }
}

#[derive(Default)]
struct MsgSenderAndTxOriginTracker {
    reads_msg_sender: bool,
    reads_tx_origin: bool,
}

impl MsgSenderAndTxOriginTracker {
    /// To avoid FP (msg.sender == tx.origin) we require that tx.origin is present and msg.sender is
    /// absent for it to be considered satisfied
    fn satisfied(&self) -> bool {
        self.reads_tx_origin && !self.reads_msg_sender
    }
}

impl CallGraphVisitor for MsgSenderAndTxOriginTracker {
    fn visit_any(&mut self, node: &crate::ast::ASTNode) -> eyre::Result<()> {
        let member_accesses = ExtractMemberAccesses::from(node).extracted;

        let has_msg_sender = member_accesses.iter().any(|member_access| {
            member_access.member_name == "sender"
                && if let Expression::Identifier(identifier) = member_access.expression.as_ref() {
                    identifier.name == "msg"
                } else {
                    false
                }
        });
        self.reads_msg_sender = self.reads_msg_sender || has_msg_sender;

        let has_tx_origin = member_accesses.iter().any(|member_access| {
            member_access.member_name == "origin"
                && if let Expression::Identifier(identifier) = member_access.expression.as_ref() {
                    identifier.name == "tx"
                } else {
                    false
                }
        });
        self.reads_tx_origin = self.reads_tx_origin || has_tx_origin;

        Ok(())
    }
}

#[cfg(test)]
mod tx_origin_used_for_auth_detector {

    use crate::detect::{
        detector::IssueDetector, high::tx_origin_used_for_auth::TxOriginUsedForAuthDetector,
    };

    #[test]

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

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

```

--------------------------------------------------------------------------------
/.github/workflows/reports.yml:
--------------------------------------------------------------------------------

```yaml
on: [push, pull_request, workflow_dispatch]

name: Reports Workflow

concurrency:
  group: ci-${{ github.ref }}-reports
  cancel-in-progress: true

jobs:
  reports-setup:
    name:  Check Reports 
    runs-on: ubuntu-latest
    outputs:
      rust-nightly: nightly-2025-09-20
    
    strategy:
      fail-fast: false
      matrix:
        task:
          - report-workflow
          - uniswap_profile-workflow
          - sablier
          - adhoc-sol-files-workflow
          - nft-workflow
          - nft-workflow-env
          - ccip-functions-report
          - hardhat-playground-report
          - prb-math-report
          - report-json
          - adhoc-sol-files-highs-only-json
          - sarif-report
          - empty-report

    steps:
      - name: Checkout Sources
        uses: actions/checkout@v4

      - name: Checkout repository with submodules
        uses: actions/checkout@v4
        with:
          submodules: recursive

      - name: Cache submodules
        id: cache-submodules
        uses: actions/cache@v3
        with:
          path: .git/modules
          key: submodules-${{ runner.os }}-${{ hashFiles('.gitmodules') }}
          restore-keys: |
            submodules-${{ runner.os }}-${{ hashFiles('.gitmodules') }}

      - name: Install Rust Nightly (2025-01-01)
        uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          toolchain: nightly-2025-09-20
          override: true

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'

      - name: Install pnpm
        uses: pnpm/action-setup@v4
        with:
          version: 8

      - name: Restore Rust Cache
        uses: Swatinem/rust-cache@v2

      - name: Prebuild (${{ matrix.task }})
        run: |
          cargo build

      - name: Generate Report (${{ matrix.task }})
        run: |
          case "${{ matrix.task }}" in
            report-workflow)
              cargo run -- -o ./reports/report-workflow.md  --src src/ ./tests/contract-playground/ --skip-update-check
              diff ./reports/report.md ./reports/report-workflow.md
              ;;
            uniswap_profile-workflow)
              FOUNDRY_PROFILE=uniswap cargo run -- -o ./reports/uniswap_profile-workflow.md ./tests/contract-playground/ --skip-update-check
              diff reports/uniswap_profile.md reports/uniswap_profile-workflow.md
              ;;
            sablier)
              pnpm install --prefix tests/2024-05-Sablier/v2-core
              FOUNDRY_PROFILE=uniswap cargo run -- -o ./reports/sablier.md ./tests/2024-05-Sablier --skip-update-check
              diff reports/sablier-aderyn-toml-nested-root.md reports/sablier.md
              ;;
            adhoc-sol-files-workflow)
              cargo run -- -o ./reports/adhoc-sol-files-report-workflow.md ./tests/adhoc-sol-files --skip-update-check
              diff ./reports/adhoc-sol-files-report.md ./reports/adhoc-sol-files-report-workflow.md
              ;;
            nft-workflow)
              cargo run -- -o ./reports/nft-workflow-report.md --src src/ ./tests/foundry-nft-f23 --skip-update-check
              diff ./reports/nft-report.md ./reports/nft-workflow-report.md
              ;;
            nft-workflow-env)
              cargo run -- -o ./reports/nft-workflow-report-icm.md ./tests/foundry-nft-f23-icm --skip-update-check
              diff ./reports/nft-report-icm.md ./reports/nft-workflow-report-icm.md
              ;;
            ccip-functions-report)
              cargo run -- -o reports/ccip-functions-report-workflow.md tests/ccip-contracts/contracts --src src/v0.8/functions/ -x "tests/,test/,mocks/"  --skip-update-check
              diff ./reports/ccip-functions-report.md ./reports/ccip-functions-report-workflow.md
              ;;
            hardhat-playground-report)
              cargo run -- tests/hardhat-js-playground -o reports/hardhat-playground-report-workflow.md --skip-update-check
              diff ./reports/hardhat-playground-report.md ./reports/hardhat-playground-report-workflow.md
              ;;
            prb-math-report)
              pnpm install --prefix tests/prb-math/
              cargo run -- ./tests/prb-math -o ./reports/prb-math-report-workflow.md --skip-update-check
              diff ./reports/prb-math-report.md ./reports/prb-math-report-workflow.md
              ;;
            report-json)
              cargo run -- -o ./reports/report-workflow.json -i src/ -x lib/ ./tests/contract-playground/ --skip-update-check
              diff ./reports/report.json ./reports/report-workflow.json
              ;;
            adhoc-sol-files-highs-only-json)
              cargo run -- -o ./reports/adhoc-sol-files-highs-only-report-workflow.json ./tests/adhoc-sol-files --skip-update-check --highs-only
              diff ./reports/adhoc-sol-files-highs-only-report.json ./reports/adhoc-sol-files-highs-only-report-workflow.json
              ;;
            sarif-report)
              cargo run -- -o ./reports/ci-report.sarif ./tests/contract-playground/ --skip-update-check
              diff ./reports/report.sarif ./reports/ci-report.sarif
              ;;
            empty-report)
              cargo run -- tests/contract-playground -o reports/empty_report_workflow.md -i IgnoreEverything.sol
              diff ./reports/empty_report.md ./reports/empty_report_workflow.md
              ;;
          esac

```

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

```rust
use crate::ast::*;
use std::fmt::{Display, Write};

impl Display for Expression {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Expression::Literal(expr) => expr.fmt(f)?,
            Expression::Identifier(expr) => expr.fmt(f)?,
            Expression::UnaryOperation(expr) => expr.fmt(f)?,
            Expression::BinaryOperation(expr) => expr.fmt(f)?,
            Expression::Conditional(expr) => expr.fmt(f)?,
            Expression::Assignment(expr) => expr.fmt(f)?,
            Expression::FunctionCall(expr) => expr.fmt(f)?,
            Expression::FunctionCallOptions(expr) => expr.fmt(f)?,
            Expression::IndexAccess(expr) => expr.fmt(f)?,
            Expression::IndexRangeAccess(expr) => expr.fmt(f)?,
            Expression::MemberAccess(expr) => expr.fmt(f)?,
            Expression::ElementaryTypeNameExpression(expr) => expr.fmt(f)?,
            Expression::TupleExpression(expr) => expr.fmt(f)?,
            Expression::NewExpression(expr) => expr.fmt(f)?,
        }

        Ok(())
    }
}

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

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

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

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

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

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

            f.write_fmt(format_args!("{argument}"))?;
        }

        f.write_str(")")
    }
}

impl Display for FunctionCallOptions {
    #[allow(clippy::print_in_format_impl)]
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let option_count = self.options.len();

        if self.names.len() != option_count {
            eprintln!("ERROR: invalid FunctionCallOptions: {:?}, {:?}", self.names, self.options);

            return Err(std::fmt::Error);
        }

        f.write_fmt(format_args!("{}", self.expression))?;

        f.write_char('{')?;

        for i in 0..option_count {
            if i > 0 {
                f.write_str(", ")?;
            }

            f.write_fmt(format_args!("{}: {}", self.names[i], self.options[i]))?;
        }

        f.write_char('}')?;

        if let Some(arguments) = self.arguments.as_ref() {
            f.write_char('(')?;

            for (i, argument) in arguments.iter().enumerate() {
                if i > 0 {
                    f.write_str(", ")?;
                }

                f.write_fmt(format_args!("{argument}"))?;
            }

            f.write_char(')')?;
        }

        Ok(())
    }
}

impl Display for IndexAccess {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        if let Some(index_expression) = &self.index_expression {
            f.write_fmt(format_args!("{}[{}]", self.base_expression, index_expression))
        } else {
            f.write_fmt(format_args!("{}[]", self.base_expression))
        }
    }
}

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

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

        f.write_str(":")?;

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

        f.write_str("]")
    }
}

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

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

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

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

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

        f.write_str(")")
    }
}

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

```

--------------------------------------------------------------------------------
/aderyn/src/lib.rs:
--------------------------------------------------------------------------------

```rust
use aderyn_driver::detector::{IssueSeverity, get_all_detectors_names, get_issue_detector_by_name};
use semver::Version;
use serde_json::Value;
use std::{cmp::Ordering, fs::File, io::Write, path::PathBuf, str::FromStr};
use strum::IntoEnumIterator;

pub mod birdsong;
pub mod completions;
pub mod lsp;
pub mod mcp;

mod panic;

pub fn create_aderyn_toml_file_at(directory: String) {
    let solidity_dir = find_solidity_dir(&directory);
    let aderyn_toml_path = PathBuf::from_str(&directory).unwrap().join("aderyn.toml");
    let mut file = File::create_new(aderyn_toml_path.clone()).expect("File already exists!");
    file.write_fmt(format_args!(
        include_str!("../templates/aderyn.toml"),
        format!("\"{}\"", &solidity_dir)
    ))
    .expect("unable to write to aderyn.toml");
    println!("Created aderyn.toml at {}", aderyn_toml_path.display());
}

pub fn find_solidity_dir(root: &str) -> String {
    let path = PathBuf::from_str(root).expect("invalid path root");
    let indicators = ["hardhat.config.ts", "hardhat.config.js", "foundry.toml", "soldeer.toml"];

    // Check for indicators in the same directory level
    for indicator in indicators {
        let target = path.join(indicator);
        if target.is_file() {
            return path.to_string_lossy().to_string();
        }
    }

    // Check for indicators one level below
    for indicator in indicators {
        let mut nodes = std::fs::read_dir(path.clone())
            .expect("reading path failed")
            .flatten()
            .collect::<Vec<_>>();
        nodes.sort_by(|a, _| {
            if a.file_name().to_string_lossy().contains("contract") {
                Ordering::Less
            } else {
                Ordering::Greater
            }
        });
        for node in nodes {
            if !node.path().is_dir() {
                continue;
            }
            let target = node.path().join(indicator);
            if target.is_file() {
                let location = node.path();
                let toml_entry = location.strip_prefix(path).expect("stripping failed");
                return toml_entry.to_string_lossy().to_string();
            }
        }
    }

    root.to_string()
}

pub fn initialize_niceties() {
    // Crash with a nice message on panic
    panic::add_handler();

    // Logger
    #[cfg(debug_assertions)]
    {
        simplelog::WriteLogger::init(
            simplelog::LevelFilter::Info,
            simplelog::Config::default(),
            File::create(concat!(env!("CARGO_MANIFEST_DIR"), "/../app.log")).unwrap(),
        )
        .unwrap();
    }
}

pub fn print_detail_view(detector_name: &str) {
    let all_detector_names = get_all_detectors_names();
    if !all_detector_names.contains(&detector_name.to_string()) {
        println!("Couldn't recognize detector with name {}", detector_name);
        return;
    }
    let detector = get_issue_detector_by_name(detector_name);
    println!("\nDetector {}", detector_name);
    println!();
    println!("Title");
    println!("{}", detector.title());
    println!();
    println!("Severity");
    println!("{}", detector.severity());
    println!();
    println!("Description");
    println!("{}", detector.description());
    println!();
}

pub fn print_all_detectors_view() {
    let all_detector_names = get_all_detectors_names();
    println!("\nDetector Registry");
    println!();
    println!("{}   Title (Rating)", right_pad("Name", 30));
    println!();
    for severity in IssueSeverity::iter() {
        print_detectors_view_with_severity(severity, &all_detector_names);
        println!();
    }
    println!();
}

pub fn print_detectors_view_with_severity(severity: IssueSeverity, detectors_names: &[String]) {
    let concerned_detectors = detectors_names
        .iter()
        .filter(|name| {
            let detector = get_issue_detector_by_name(name);
            detector.severity() == severity
        })
        .collect::<Vec<_>>();

    if concerned_detectors.is_empty() {
        return;
    }

    println!("{}\n", severity);
    for name in concerned_detectors {
        let detector = get_issue_detector_by_name(name);
        println!("{} - {}", right_pad(name, 30), detector.title(),);
    }
    println!();
}

fn right_pad(s: &str, by: usize) -> String {
    if s.len() > by {
        return s.to_string();
    }
    let extra_spaces = by - s.len();
    let spaces = " ".repeat(extra_spaces);
    let mut new_string = s.to_string();
    new_string.push_str(&spaces);
    new_string
}

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

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

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

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

    Some(current >= newest)
}

#[cfg(test)]
mod latest_version_checker_tests {
    use super::*;

    #[test]
    #[ignore = "fails when frequently run as github will rate limit"]
    fn can_get_latest_version_from_github_releases() {
        assert!(aderyn_is_currently_running_newest_version().is_some())
    }
}

```

--------------------------------------------------------------------------------
/benchmarks/non-reentrant-before-others/report/both/regression.svg:
--------------------------------------------------------------------------------

```
<svg width="960" height="540" viewBox="0 0 960 540" xmlns="http://www.w3.org/2000/svg">
<text x="480" y="32" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="16.129032258064516" opacity="1" fill="#000000">
non-reentrant-before-others
</text>
<text x="27" y="263" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000" transform="rotate(270, 27, 263)">
Total sample time (ms)
</text>
<text x="510" y="513" 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="87" y1="472" x2="87" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="237" y1="472" x2="237" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="388" y1="472" x2="388" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="539" y1="472" x2="539" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="690" y1="472" x2="690" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="841" y1="472" x2="841" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="472" x2="932" y2="472"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="399" x2="932" y2="399"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="326" x2="932" y2="326"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="253" x2="932" y2="253"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="180" x2="932" y2="180"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="107" x2="932" y2="107"/>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="86,53 86,472 "/>
<text x="77" y="472" 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="81,472 86,472 "/>
<text x="77" y="399" 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="81,399 86,399 "/>
<text x="77" y="326" 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="81,326 86,326 "/>
<text x="77" y="253" 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="81,253 86,253 "/>
<text x="77" y="180" 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="81,180 86,180 "/>
<text x="77" y="107" 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="81,107 86,107 "/>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="87,473 932,473 "/>
<text x="87" y="483" 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="87,473 87,478 "/>
<text x="237" y="483" 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="237,473 237,478 "/>
<text x="388" y="483" 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="388,473 388,478 "/>
<text x="539" y="483" 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="539,473 539,478 "/>
<text x="690" y="483" 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="690,473 690,478 "/>
<text x="841" y="483" 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="841,473 841,478 "/>
<polyline fill="none" opacity="1" stroke="#E31A1C" stroke-width="1" points="87,472 932,53 "/>
<polygon opacity="0.25" fill="#E31A1C" points="87,472 932,63 932,53 "/>
<polyline fill="none" opacity="1" stroke="#1F78B4" stroke-width="1" points="87,472 932,140 "/>
<polygon opacity="0.25" fill="#1F78B4" points="87,472 932,142 932,136 "/>
<text x="132" y="68" dy="0.76em" text-anchor="start" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
Base Sample
</text>
<text x="132" y="83" dy="0.76em" text-anchor="start" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
New Sample
</text>
<polyline fill="none" opacity="1" stroke="#E31A1C" stroke-width="2" points="102,73 122,73 "/>
<polyline fill="none" opacity="1" stroke="#1F78B4" stroke-width="2" points="102,88 122,88 "/>
</svg>

```

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

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

use crate::{
    ast::{Literal, LiteralKind, NodeID},
    capture,
    context::{
        browser::{
            ExtractFunctionDefinitions, ExtractLiterals, ExtractModifierDefinitions,
            GetImmediateParent,
        },
        workspace::{ASTNode, WorkspaceContext},
    },
    detect::detector::{IssueDetector, IssueDetectorNamePool, IssueSeverity},
};
use eyre::Result;

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

impl IssueDetector for LiteralsInsteadOfConstantsDetector {
    fn detect(&mut self, context: &WorkspaceContext) -> Result<bool, Box<dyn Error>> {
        // Get all contracts
        // For each contract
        //      Get all Function definitions (and to the same for modifiers)
        //          Get all literals
        //          For each literal
        //              if literal.value is not 0 or 1
        //                  if the literal.value appears more than once, then capture all instances

        for contract in context.contract_definitions() {
            let mut literal_values_found: HashMap<String, Vec<Literal>> = HashMap::new();

            for function in ExtractFunctionDefinitions::from(contract).extracted.into_iter() {
                for literal in ExtractLiterals::from(&function).extracted.into_iter() {
                    if (literal.kind == LiteralKind::Number
                        && literal.value != Some(String::from("0"))
                        && literal.value != Some(String::from("1")))
                        && literal.value != Some(String::from("2"))
                        || literal.kind == LiteralKind::HexString
                        || literal.kind == LiteralKind::Address
                    {
                        // If the literal is used as an index access in a variable, don't capture it
                        if let Some(ASTNode::IndexAccess(_)) = literal.parent(context) {
                            continue;
                        }

                        if let Some(literal_value) = literal.value.as_ref() {
                            if literal_values_found.contains_key(literal_value) {
                                literal_values_found.get_mut(literal_value).unwrap().push(literal);
                            } else {
                                literal_values_found.insert(literal_value.clone(), vec![literal]);
                            }
                        }
                    }
                }
            }

            for modifier in ExtractModifierDefinitions::from(contract).extracted.into_iter() {
                for literal in ExtractLiterals::from(&modifier).extracted.into_iter() {
                    if (literal.kind == LiteralKind::Number
                        && literal.value != Some(String::from("0"))
                        && literal.value != Some(String::from("1")))
                        && literal.value != Some(String::from("2"))
                        || literal.kind == LiteralKind::HexString
                        || literal.kind == LiteralKind::Address
                    {
                        // If the literal is used as an index access in a variable, don't capture it
                        if let Some(ASTNode::IndexAccess(_)) = context.get_parent(literal.id) {
                            continue;
                        }

                        if let Some(literal_value) = literal.value.as_ref() {
                            if literal_values_found.contains_key(literal_value) {
                                literal_values_found.get_mut(literal_value).unwrap().push(literal);
                            } else {
                                literal_values_found.insert(literal_value.clone(), vec![literal]);
                            }
                        }
                    }
                }
            }

            for (_, literals) in literal_values_found.iter() {
                if literals.len() > 1 {
                    for literal in literals {
                        capture!(self, context, literal);
                    }
                }
            }
        }

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

    fn title(&self) -> String {
        String::from("Literal Instead of Constant")
    }

    fn description(&self) -> String {
        String::from(
            "Define and use `constant` variables instead of using literals. If the same constant literal value is used multiple times, create a constant state variable and reference it throughout the contract.",
        )
    }

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

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

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

#[cfg(test)]
mod constants_instead_of_literals_tests {

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

    #[test]

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

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

```

--------------------------------------------------------------------------------
/aderyn_core/src/context/router/external_calls.rs:
--------------------------------------------------------------------------------

```rust
use super::{ECDest, Router};
use crate::{
    ast::{
        ASTNode, ContractDefinition, FunctionCall, FunctionDefinition, FunctionKind, Visibility,
    },
    context::workspace::WorkspaceContext,
};
use std::collections::{HashMap, hash_map::Entry};

impl Router {
    /// Given a function call, resolve the function definition with it's selector.
    ///
    /// If no function is found with the said selector, it tries to retrieve a fallback function.
    /// Since function selector is data that's being passed it cannot point to receive function.
    ///
    /// Suspect here could be a variable as well
    pub(super) fn _resolve_external_call<'a>(
        &self,
        context: &'a WorkspaceContext,
        base_contract: &'a ContractDefinition,
        func_call: &'a FunctionCall,
    ) -> Option<ECDest> {
        // do not resolve if it's internal function call
        if func_call.is_internal_call() == Some(true) {
            return None;
        }

        // works for both public variables and functions
        let selector = func_call.suspected_function_selector(context)?;
        self._resolve_function_selector(base_contract, selector)
    }

    pub(super) fn _resolve_fallback_function<'a>(
        &self,
        context: &'a WorkspaceContext,
        base_contract: &'a ContractDefinition,
    ) -> Option<&'a FunctionDefinition> {
        // check if it's illegal base contract type
        if !base_contract.is_deployable_contract() {
            return None;
        }
        let lookup_index = self.external_calls.get(&base_contract.id)?;
        if let Some(ECDest::Fallback(func_id)) = lookup_index.routes.get("FALLBACK")
            && let Some(ASTNode::FunctionDefinition(fallback)) = context.nodes.get(func_id)
        {
            return Some(fallback);
        }
        None
    }

    pub(super) fn _resolve_receive_function<'a>(
        &self,
        context: &'a WorkspaceContext,
        base_contract: &'a ContractDefinition,
    ) -> Option<&'a FunctionDefinition> {
        // check if it's illegal base contract type
        if !base_contract.is_deployable_contract() {
            return None;
        }
        let lookup_index = self.external_calls.get(&base_contract.id)?;
        if let Some(ECDest::Receive(func_id)) = lookup_index.routes.get("RECEIVE")
            && let Some(ASTNode::FunctionDefinition(fallback)) = context.nodes.get(func_id)
        {
            return Some(fallback);
        }
        None
    }

    pub(super) fn _resolve_function_selector(
        &self,
        base_contract: &ContractDefinition,
        selector: impl AsRef<str>,
    ) -> Option<ECDest> {
        // check if it's illegal base contract type
        if !base_contract.is_deployable_contract() {
            return None;
        }

        let lookup_index = self.external_calls.get(&base_contract.id)?;

        match lookup_index.routes.get(selector.as_ref()) {
            Some(resolved) => Some(resolved.clone()),
            None => lookup_index.routes.get("FALLBACK").cloned(),
        }
    }
}

/// If function selector field isn't present, this algorithm cannot work.
/// Therefore, if for some reason it's not found, we return an empty hashmap
pub(super) fn build_ec_router_for_contract(
    context: &WorkspaceContext,
    base_contract: &ContractDefinition,
) -> HashMap<String, ECDest> {
    let c3 = base_contract.c3(context).collect::<Vec<_>>();
    let mut routes = HashMap::new();
    for contract in c3.iter() {
        // Loop through public state variables
        for var in contract.top_level_variables() {
            if var.visibility == Visibility::Public {
                let Some(func_selector) = var.function_selector.as_ref() else {
                    return HashMap::new();
                };
                if let Entry::Vacant(e) = routes.entry(func_selector.to_string()) {
                    e.insert(ECDest::PseudoExtFn(var.id));
                }
            }
        }
        // Loop through externally available functions
        for func in contract.function_definitions() {
            match *func.kind() {
                FunctionKind::Function => {
                    match func.visibility {
                        Visibility::Public => {
                            let Some(func_selector) = func.function_selector.as_ref() else {
                                return HashMap::new();
                            };
                            if let Entry::Vacant(e) = routes.entry(func_selector.to_string()) {
                                e.insert(ECDest::PublicFn(func.id));
                            }
                        }
                        Visibility::External => {
                            let Some(func_selector) = func.function_selector.as_ref() else {
                                return HashMap::new();
                            };
                            if let Entry::Vacant(e) = routes.entry(func_selector.to_string()) {
                                e.insert(ECDest::RealExtFn(func.id));
                            }
                        }
                        _ => {}
                    };
                }
                FunctionKind::Receive => {
                    if let Entry::Vacant(e) = routes.entry("RECEIVE".to_string()) {
                        e.insert(ECDest::Receive(func.id));
                    }
                }
                FunctionKind::Fallback => {
                    if let Entry::Vacant(e) = routes.entry("FALLBACK".to_string()) {
                        e.insert(ECDest::Fallback(func.id));
                    }
                }
                FunctionKind::FreeFunction => unreachable!(), // can't be inside a contract.
                FunctionKind::Constructor => {}
            };
        }
    }
    routes
}

```

--------------------------------------------------------------------------------
/aderyn_driver/src/config.rs:
--------------------------------------------------------------------------------

```rust
use std::{
    collections::HashMap,
    env, fs,
    path::{Path, PathBuf},
};

use serde::Deserialize;

use crate::process::PreprocessedConfig;

/// `aderyn.toml` file structure
#[derive(Deserialize, Clone)]
pub struct AderynConfig {
    pub version: usize,
    pub root: Option<String>,
    pub src: Option<String>,
    pub exclude: Option<Vec<String>>,
    pub include: Option<Vec<String>>,
    pub env: Option<HashMap<String, String>>,
}

pub fn supplement_values_from_aderyn_toml(
    current: PreprocessedConfig,
) -> Result<PreprocessedConfig, Box<dyn std::error::Error + Send + Sync>> {
    let root_path = current.root_path.clone();
    Ok(supplement(current, aderyn_toml_config(&root_path)?))
}

/// Load the aderyn.toml file and deserialize it to AderynConfig
fn aderyn_toml_config(root: &Path) -> Result<AderynConfig, String> {
    let config_path = root.join("aderyn.toml");
    // Read the file
    let content = fs::read_to_string(config_path)
        .map_err(|err| format!("Error reading config file: {}", err))?;

    // Deserialize the TOML string to AderynConfig
    let mut config: AderynConfig =
        toml::from_str(&content).map_err(|err| format!("Error parsing config file: {}", err))?;

    if config.version != 1 {
        return Err("aderyn.toml version not supported".to_owned());
    }

    // Clear empty vectors
    clear_empty_vectors(&mut config.exclude);
    clear_empty_vectors(&mut config.include);

    Ok(config)
}

fn supplement(current: PreprocessedConfig, config: AderynConfig) -> PreprocessedConfig {
    // Load env variables
    if let Some(map) = config.env.clone() {
        map.iter().for_each(|(k, v)| {
            unsafe { env::set_var(k, v) };
        })
    }

    let mut local_root: PathBuf = current.root_path;
    if let Some(config_root) = &config.root {
        // append the config_root to the local_root
        local_root.push(config_root);
    }

    // If config.src is some, command line arg src overrides config.src
    let mut local_src: Option<String> = current.src.clone();
    if let Some(config_src) = &config.src
        && local_src.is_none()
    {
        local_src = Some(config_src.clone());
    }

    // If config.exclude is some, append each value to exclude if it is not already present
    let mut local_exclude = current.exclude.clone();
    if let Some(config_exclude) = &config.exclude {
        if let Some(local_exclude) = &mut local_exclude {
            for item in config_exclude {
                if !local_exclude.contains(item) {
                    local_exclude.push(item.clone());
                }
            }
        } else {
            local_exclude = Some(config_exclude.clone());
        }
    }

    // If config.include is some, append each value to include if it is not already present
    let mut local_include = current.include.clone();
    if let Some(config_scope) = &config.include {
        if let Some(local_include) = &mut local_include {
            for item in config_scope {
                if !local_include.contains(item) {
                    local_include.push(item.clone());
                }
            }
        } else {
            local_include = Some(config_scope.clone());
        }
    }

    PreprocessedConfig {
        root_path: local_root,
        src: local_src,
        exclude: local_exclude,
        include: local_include,
    }
}

fn clear_empty_vectors<T>(vec: &mut Option<Vec<T>>) {
    if let Some(v) = vec
        && v.is_empty()
    {
        *vec = None;
    }
}

#[cfg(test)]
mod tests {
    use std::{collections::HashMap, env};

    use crate::process::PreprocessedConfig;

    #[test]
    fn test_interpret_aderyn_config_correctly_appends_and_replaces() {
        // Act
        let current = {
            let root = std::path::Path::new("ARG_ROOT");
            let src = Some("ARG_SRC".to_string());
            let exclude = Some(vec!["ARG_EXCLUDE_1".to_string(), "ARG_EXCLUDE_2".to_string()]);
            let include = Some(vec!["ARG_SCOPE_1".to_string(), "ARG_SCOPE_2".to_string()]);
            PreprocessedConfig { root_path: root.to_path_buf(), src, include, exclude }
        };
        let result = {
            let env = HashMap::from_iter(vec![(
                "FOUNDRY_PROFILE".to_string(),
                "ENV_VAR_VALUE".to_string(),
            )]);
            let config = super::AderynConfig {
                version: 1,
                root: Some("CONFIG_ROOT".to_string()),
                src: Some("CONFIG_SRC".to_string()),
                exclude: Some(vec!["CONFIG_EXCLUDE".to_string()]),
                include: Some(vec!["CONFIG_SCOPE".to_string()]),
                env: Some(env),
            };
            super::supplement(current, config)
        };

        // Assert
        assert_eq!(env::var("FOUNDRY_PROFILE").unwrap(), "ENV_VAR_VALUE");
        assert_eq!(result.root_path, std::path::Path::new("ARG_ROOT/CONFIG_ROOT"));
        assert_eq!(result.src, Some("ARG_SRC".to_string()));
        assert_eq!(
            result.exclude,
            Some(vec![
                "ARG_EXCLUDE_1".to_string(),
                "ARG_EXCLUDE_2".to_string(),
                "CONFIG_EXCLUDE".to_string()
            ])
        );
        assert_eq!(
            result.include,
            Some(vec![
                "ARG_SCOPE_1".to_string(),
                "ARG_SCOPE_2".to_string(),
                "CONFIG_SCOPE".to_string()
            ])
        );
    }

    #[test]
    fn test_clear_empty_vectors() {
        let mut vec_1 = Some(vec!["a".to_string(), "b".to_string()]);
        super::clear_empty_vectors(&mut vec_1);
        assert_eq!(vec_1, Some(vec!["a".to_string(), "b".to_string()]));

        let mut vec_2: Option<Vec<String>> = Some(vec![]);
        super::clear_empty_vectors(&mut vec_2);
        assert_eq!(vec_2, None);
    }
}

```

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

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

use crate::ast::{ASTNode, NodeID, NodeType, StateMutability};

use crate::{
    capture,
    context::browser::{
        ExtractInlineAssemblies, ExtractPragmaDirectives, GetClosestAncestorOfTypeX,
    },
};

use crate::{
    context::{
        graph::{CallGraphConsumer, CallGraphDirection, CallGraphVisitor},
        workspace::WorkspaceContext,
    },
    detect::{
        detector::{IssueDetector, IssueDetectorNamePool, IssueSeverity},
        helpers::{self, pragma_directive_to_semver},
    },
};
use eyre::Result;
use semver::{Version, VersionReq};

#[derive(Default)]
pub struct ConstantFunctionContainsAssemblyDetector {
    // 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 ConstantFunctionContainsAssemblyDetector {
    fn detect(&mut self, context: &WorkspaceContext) -> Result<bool, Box<dyn Error>> {
        for function in helpers::get_implemented_external_and_public_functions(context) {
            // First, check the eligibility for this function by checking
            if let Some(ASTNode::SourceUnit(source_unit)) =
                function.closest_ancestor_of_type(context, NodeType::SourceUnit)
            {
                // Store the extracted directives in a variable to extend its lifetime
                let extracted_directives = ExtractPragmaDirectives::from(source_unit).extracted;
                let pragma_directive = extracted_directives.first();

                if let Some(pragma_directive) = pragma_directive {
                    let version_req = pragma_directive_to_semver(pragma_directive);
                    if let Ok(version_req) = version_req
                        && version_req_allows_below_0_5_0(&version_req)
                    {
                        // Only run the logic if pragma is allowed to run on solc <0.5.0

                        if function.state_mutability() == &StateMutability::View
                            || function.state_mutability() == &StateMutability::Pure
                        {
                            let mut tracker = AssemblyTracker { has_assembly: false };
                            // keep legacy because < 0.5.0
                            let callgraph = CallGraphConsumer::get_legacy(
                                context,
                                &[&(function.into())],
                                CallGraphDirection::Inward,
                            )?;
                            callgraph.accept(context, &mut tracker)?;

                            if tracker.has_assembly {
                                capture!(self, context, function);
                            }
                        }
                    }
                }
            }
        }

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

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

    fn title(&self) -> String {
        String::from("Constant Function Contains Assembly")
    }

    fn description(&self) -> String {
        String::from(
            "constant/pure/view was not enforced prior to Solidity 0.5. Starting from Solidity 0.5, a call to a constant/pure/view function uses the STATICCALL opcode, \
        which reverts in case of state modification. As a result, a call to an incorrectly labeled function may trap a contract compiled with Solidity 0.5. \
        https://docs.soliditylang.org/en/develop/050-breaking-changes.html#interoperability-with-older-contracts",
        )
    }

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

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

fn version_req_allows_below_0_5_0(version_req: &VersionReq) -> bool {
    // If it matches any 0.4.0 to 0.4.26, return true
    for i in 0..=26 {
        let version: semver::Version = Version::from_str(&format!("0.4.{}", i)).unwrap();
        if version_req.matches(&version) {
            return true;
        }
    }

    // Else, return false
    false
}

struct AssemblyTracker {
    has_assembly: bool,
}

impl CallGraphVisitor for AssemblyTracker {
    fn visit_any(&mut self, node: &crate::ast::ASTNode) -> eyre::Result<()> {
        // If we are already satisfied, do not bother checking
        if self.has_assembly {
            return Ok(());
        }

        if let ASTNode::FunctionDefinition(function) = node {
            // Ignore checking functions that start with `_`
            // Example - templegold contains math functions like `_rpow()`, etc that are used by
            // view functions That should be okay .. I guess? (idk ... it's open for
            // discussion)
            if function.name.starts_with('_') {
                return Ok(());
            }
        }

        // Check if this node has assembly code
        let assemblies = ExtractInlineAssemblies::from(node).extracted;
        if !assemblies.is_empty() {
            self.has_assembly = true;
        }
        Ok(())
    }
}

#[cfg(test)]
mod constant_functions_assembly_detector {

    use crate::detect::{
        detector::IssueDetector,
        low::constant_function_contains_assembly::ConstantFunctionContainsAssemblyDetector,
    };

    #[test]

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

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

```

--------------------------------------------------------------------------------
/benchmarks/useless-public-function/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
</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="134" y1="244" x2="134" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="194" y1="244" x2="194" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="254" y1="244" x2="254" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="314" y1="244" x2="314" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="374" y1="244" x2="374" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="434" y1="244" x2="434" 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="212" x2="434" y2="212"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="180" x2="434" y2="180"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="147" x2="434" y2="147"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="115" x2="434" y2="115"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="83" x2="434" y2="83"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="50" x2="434" y2="50"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="18" x2="434" y2="18"/>
<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="212" 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,212 74,212 "/>
<text x="65" y="180" 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,180 74,180 "/>
<text x="65" y="147" 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,147 74,147 "/>
<text x="65" y="115" 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,115 74,115 "/>
<text x="65" y="83" 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,83 74,83 "/>
<text x="65" y="50" 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,50 74,50 "/>
<text x="65" y="18" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
140.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="69,18 74,18 "/>
<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="134" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
50
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="134,245 134,250 "/>
<text x="194" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
100
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="194,245 194,250 "/>
<text x="254" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
150
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="254,245 254,250 "/>
<text x="314" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
200
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="314,245 314,250 "/>
<text x="374" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
250
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="374,245 374,250 "/>
<text x="434" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
300
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="434,245 434,250 "/>
<polyline fill="none" opacity="1" stroke="#E31A1C" stroke-width="1" points="75,244 434,24 "/>
<polygon opacity="0.25" fill="#E31A1C" points="75,244 434,27 434,21 "/>
<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,20 434,15 "/>
</svg>

```

--------------------------------------------------------------------------------
/benchmarks/zero-address-check/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
</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="134" y1="244" x2="134" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="194" y1="244" x2="194" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="254" y1="244" x2="254" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="314" y1="244" x2="314" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="374" y1="244" x2="374" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="434" y1="244" x2="434" 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="215" x2="434" y2="215"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="185" x2="434" y2="185"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="155" x2="434" y2="155"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="125" x2="434" y2="125"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="95" x2="434" y2="95"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="65" x2="434" y2="65"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="35" x2="434" y2="35"/>
<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="215" 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,215 74,215 "/>
<text x="65" y="185" 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,185 74,185 "/>
<text x="65" y="155" 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,155 74,155 "/>
<text x="65" y="125" 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,125 74,125 "/>
<text x="65" y="95" 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,95 74,95 "/>
<text x="65" y="65" 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,65 74,65 "/>
<text x="65" y="35" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
140.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="69,35 74,35 "/>
<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="134" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
50
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="134,245 134,250 "/>
<text x="194" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
100
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="194,245 194,250 "/>
<text x="254" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
150
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="254,245 254,250 "/>
<text x="314" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
200
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="314,245 314,250 "/>
<text x="374" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
250
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="374,245 374,250 "/>
<text x="434" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
300
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="434,245 434,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,24 434,15 "/>
<polyline fill="none" opacity="1" stroke="#1F78B4" stroke-width="1" points="75,244 434,45 "/>
<polygon opacity="0.25" fill="#1F78B4" points="75,244 434,47 434,42 "/>
</svg>

```

--------------------------------------------------------------------------------
/benchmarks/useless-modifier/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="122" y1="244" x2="122" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="169" y1="244" x2="169" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="216" y1="244" x2="216" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="263" y1="244" x2="263" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="311" y1="244" x2="311" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="358" y1="244" x2="358" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="405" y1="244" x2="405" 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="207" x2="434" y2="207"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="169" x2="434" y2="169"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="131" x2="434" y2="131"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="93" x2="434" y2="93"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="55" x2="434" y2="55"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="18" x2="434" y2="18"/>
<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="207" 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,207 74,207 "/>
<text x="65" y="169" 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,169 74,169 "/>
<text x="65" y="131" 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,131 74,131 "/>
<text x="65" y="93" 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,93 74,93 "/>
<text x="65" y="55" 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,55 74,55 "/>
<text x="65" y="18" 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,18 74,18 "/>
<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="122" 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="122,245 122,250 "/>
<text x="169" 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="169,245 169,250 "/>
<text x="216" 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="216,245 216,250 "/>
<text x="263" 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="263,245 263,250 "/>
<text x="311" 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="311,245 311,250 "/>
<text x="358" 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="358,245 358,250 "/>
<text x="405" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
3.5
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="405,245 405,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,26 434,15 "/>
<polyline fill="none" opacity="1" stroke="#1F78B4" stroke-width="1" points="75,244 434,70 "/>
<polygon opacity="0.25" fill="#1F78B4" points="75,244 434,71 434,68 "/>
</svg>

```

--------------------------------------------------------------------------------
/benchmarks/block-timestamp-deadline/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
</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="119" y1="244" x2="119" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="164" y1="244" x2="164" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="209" y1="244" x2="209" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="254" y1="244" x2="254" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="299" y1="244" x2="299" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="344" y1="244" x2="344" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="389" y1="244" x2="389" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="434" y1="244" x2="434" 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="205" x2="434" y2="205"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="166" x2="434" y2="166"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="126" x2="434" y2="126"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="87" x2="434" y2="87"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="48" x2="434" y2="48"/>
<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="205" 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,205 74,205 "/>
<text x="65" y="166" 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,166 74,166 "/>
<text x="65" y="126" 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,126 74,126 "/>
<text x="65" y="87" 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,87 74,87 "/>
<text x="65" y="48" 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,48 74,48 "/>
<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="119" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
50
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="119,245 119,250 "/>
<text x="164" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
100
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="164,245 164,250 "/>
<text x="209" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
150
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="209,245 209,250 "/>
<text x="254" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
200
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="254,245 254,250 "/>
<text x="299" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
250
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="299,245 299,250 "/>
<text x="344" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
300
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="344,245 344,250 "/>
<text x="389" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
350
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="389,245 389,250 "/>
<text x="434" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
400
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="434,245 434,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,18 434,15 "/>
<polyline fill="none" opacity="1" stroke="#1F78B4" stroke-width="1" points="75,244 434,21 "/>
<polygon opacity="0.25" fill="#1F78B4" points="75,244 434,24 434,17 "/>
</svg>

```

--------------------------------------------------------------------------------
/benchmarks/unsafe-oz-erc721-mint/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
</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="119" y1="244" x2="119" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="164" y1="244" x2="164" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="209" y1="244" x2="209" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="254" y1="244" x2="254" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="299" y1="244" x2="299" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="344" y1="244" x2="344" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="389" y1="244" x2="389" y2="15"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="434" y1="244" x2="434" 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="163" x2="434" y2="163"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="122" x2="434" y2="122"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="81" x2="434" y2="81"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="75" y1="40" x2="434" y2="40"/>
<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="163" 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,163 74,163 "/>
<text x="65" y="122" 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,122 74,122 "/>
<text x="65" y="81" 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,81 74,81 "/>
<text x="65" y="40" 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,40 74,40 "/>
<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="119" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
50
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="119,245 119,250 "/>
<text x="164" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
100
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="164,245 164,250 "/>
<text x="209" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
150
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="209,245 209,250 "/>
<text x="254" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
200
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="254,245 254,250 "/>
<text x="299" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
250
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="299,245 299,250 "/>
<text x="344" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
300
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="344,245 344,250 "/>
<text x="389" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
350
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="389,245 389,250 "/>
<text x="434" y="255" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
400
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="434,245 434,250 "/>
<polyline fill="none" opacity="1" stroke="#E31A1C" stroke-width="1" points="75,244 434,46 "/>
<polygon opacity="0.25" fill="#E31A1C" points="75,244 434,48 434,45 "/>
<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,20 434,15 "/>
</svg>

```

--------------------------------------------------------------------------------
/benchmarks/unspecific-solidity-pragma/report/both/regression.svg:
--------------------------------------------------------------------------------

```
<svg width="960" height="540" viewBox="0 0 960 540" xmlns="http://www.w3.org/2000/svg">
<text x="480" y="32" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="16.129032258064516" opacity="1" fill="#000000">
unspecific-solidity-pragma
</text>
<text x="27" y="263" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000" transform="rotate(270, 27, 263)">
Total sample time (ms)
</text>
<text x="510" y="513" 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="87" y1="472" x2="87" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="225" y1="472" x2="225" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="364" y1="472" x2="364" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="502" y1="472" x2="502" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="641" y1="472" x2="641" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="779" y1="472" x2="779" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="918" y1="472" x2="918" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="472" x2="932" y2="472"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="397" x2="932" y2="397"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="321" x2="932" y2="321"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="245" x2="932" y2="245"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="169" x2="932" y2="169"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="93" x2="932" y2="93"/>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="86,53 86,472 "/>
<text x="77" y="472" 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="81,472 86,472 "/>
<text x="77" y="397" 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="81,397 86,397 "/>
<text x="77" y="321" 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="81,321 86,321 "/>
<text x="77" y="245" 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="81,245 86,245 "/>
<text x="77" y="169" 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="81,169 86,169 "/>
<text x="77" y="93" 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="81,93 86,93 "/>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="87,473 932,473 "/>
<text x="87" y="483" 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="87,473 87,478 "/>
<text x="225" y="483" 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="225,473 225,478 "/>
<text x="364" y="483" 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="364,473 364,478 "/>
<text x="502" y="483" 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="502,473 502,478 "/>
<text x="641" y="483" 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="641,473 641,478 "/>
<text x="779" y="483" 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="779,473 779,478 "/>
<text x="918" y="483" 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="918,473 918,478 "/>
<polyline fill="none" opacity="1" stroke="#E31A1C" stroke-width="1" points="87,472 932,53 "/>
<polygon opacity="0.25" fill="#E31A1C" points="87,472 932,64 932,53 "/>
<polyline fill="none" opacity="1" stroke="#1F78B4" stroke-width="1" points="87,472 932,98 "/>
<polygon opacity="0.25" fill="#1F78B4" points="87,472 932,100 932,96 "/>
<text x="132" y="68" dy="0.76em" text-anchor="start" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
Base Sample
</text>
<text x="132" y="83" dy="0.76em" text-anchor="start" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
New Sample
</text>
<polyline fill="none" opacity="1" stroke="#E31A1C" stroke-width="2" points="102,73 122,73 "/>
<polyline fill="none" opacity="1" stroke="#1F78B4" stroke-width="2" points="102,88 122,88 "/>
</svg>

```

--------------------------------------------------------------------------------
/benchmarks/unsafe-erc20-functions/report/both/regression.svg:
--------------------------------------------------------------------------------

```
<svg width="960" height="540" viewBox="0 0 960 540" xmlns="http://www.w3.org/2000/svg">
<text x="480" y="32" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="16.129032258064516" opacity="1" fill="#000000">
unsafe-erc20-functions
</text>
<text x="27" y="263" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000" transform="rotate(270, 27, 263)">
Total sample time (ms)
</text>
<text x="510" y="513" 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="87" y1="472" x2="87" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="237" y1="472" x2="237" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="388" y1="472" x2="388" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="539" y1="472" x2="539" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="690" y1="472" x2="690" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="841" y1="472" x2="841" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="472" x2="932" y2="472"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="405" x2="932" y2="405"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="338" x2="932" y2="338"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="271" x2="932" y2="271"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="203" x2="932" y2="203"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="136" x2="932" y2="136"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="69" x2="932" y2="69"/>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="86,53 86,472 "/>
<text x="77" y="472" 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="81,472 86,472 "/>
<text x="77" y="405" 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="81,405 86,405 "/>
<text x="77" y="338" 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="81,338 86,338 "/>
<text x="77" y="271" 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="81,271 86,271 "/>
<text x="77" y="203" 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="81,203 86,203 "/>
<text x="77" y="136" 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="81,136 86,136 "/>
<text x="77" y="69" 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="81,69 86,69 "/>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="87,473 932,473 "/>
<text x="87" y="483" 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="87,473 87,478 "/>
<text x="237" y="483" 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="237,473 237,478 "/>
<text x="388" y="483" 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="388,473 388,478 "/>
<text x="539" y="483" 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="539,473 539,478 "/>
<text x="690" y="483" 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="690,473 690,478 "/>
<text x="841" y="483" 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="841,473 841,478 "/>
<polyline fill="none" opacity="1" stroke="#E31A1C" stroke-width="1" points="87,472 932,135 "/>
<polygon opacity="0.25" fill="#E31A1C" points="87,472 932,135 932,134 "/>
<polyline fill="none" opacity="1" stroke="#1F78B4" stroke-width="1" points="87,472 932,53 "/>
<polygon opacity="0.25" fill="#1F78B4" points="87,472 932,60 932,53 "/>
<text x="132" y="68" dy="0.76em" text-anchor="start" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
Base Sample
</text>
<text x="132" y="83" dy="0.76em" text-anchor="start" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
New Sample
</text>
<polyline fill="none" opacity="1" stroke="#E31A1C" stroke-width="2" points="102,73 122,73 "/>
<polyline fill="none" opacity="1" stroke="#1F78B4" stroke-width="2" points="102,88 122,88 "/>
</svg>

```

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

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

use crate::ast::{
    ASTNode, Expression, Identifier, NodeID, TupleExpression, TypeDescriptions, UnaryOperation,
};

use crate::{
    capture,
    context::{
        browser::{ExtractPragmaDirectives, ExtractTupleExpressions, GetImmediateParent},
        workspace::WorkspaceContext,
    },
    detect::{
        detector::{IssueDetector, IssueDetectorNamePool, IssueSeverity},
        helpers,
    },
};
use eyre::Result;
use lazy_regex::regex;
use semver::{Version, VersionReq};

#[derive(Default)]
pub struct StorageSignedIntegerArrayDetector {
    // 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 StorageSignedIntegerArrayDetector {
    fn detect(&mut self, context: &WorkspaceContext) -> Result<bool, Box<dyn Error>> {
        for source_unit in context.source_units() {
            let tuple_expressions = ExtractTupleExpressions::from(source_unit).extracted;
            let pragma_directives = ExtractPragmaDirectives::from(source_unit).extracted;

            if let Some(pragma_directive) = pragma_directives.first()
                && let Ok(pragma_semver) = helpers::pragma_directive_to_semver(pragma_directive)
                && version_req_allows_below_0_5_10(&pragma_semver)
            {
                // Search for a literal array with one negative value in it
                for tuple_expression in tuple_expressions
                    .into_iter()
                    .filter(|tuple_expression| tuple_expression.is_inline_array)
                {
                    // First, make sure it's being assigned to an array pointer to storage
                    if !is_tuple_being_assigned_to_storage_array(&tuple_expression, context) {
                        continue;
                    }

                    // Now, make sure there is at least 1 negative value in the tuple array
                    let negative_component_present = tuple_expression.components.iter().any(|c| {
                        if let Some(Expression::UnaryOperation(UnaryOperation {
                            operator, ..
                        })) = c
                        {
                            return operator == "-";
                        }
                        false
                    });

                    if negative_component_present {
                        capture!(self, context, tuple_expression);
                    }
                }
            }
        }

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

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

    fn title(&self) -> String {
        String::from("Signed integer array in storage (solc `<0.5.10`)")
    }

    fn description(&self) -> String {
        String::from(
            "solc versions 0.4.7-0.5.9 contain a compiler bug leading to incorrect values in signed integer arrays.\
            Use solidity version 0.5.10 or above.",
        )
    }

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

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

fn version_req_allows_below_0_5_10(version_req: &VersionReq) -> bool {
    // If it matches any 0.4.0 to 0.4.26, return true
    for i in 0..=26 {
        let version = Version::from_str(&format!("0.4.{}", i)).unwrap();
        if version_req.matches(&version) {
            return true;
        }
    }

    // If it matches any 0.5.0 to 0.5.9 return true
    for i in 0..=9 {
        let version = Version::from_str(&format!("0.5.{}", i)).unwrap();
        if version_req.matches(&version) {
            return true;
        }
    }

    // Else, return false
    false
}

// Build a regular expression to catch type names that correspond to pointers to storage arrays
static SIGNED_STORAGE_ARRAY_POINTER: &lazy_regex::Lazy<lazy_regex::Regex> =
    regex!(r"^int[0-9]*\[[0-9]*] storage ref$");

fn is_tuple_being_assigned_to_storage_array(
    tuple_expression: &TupleExpression,
    context: &WorkspaceContext,
) -> bool {
    if let Some(ASTNode::Assignment(assignment)) = tuple_expression.parent(context)
        && let Expression::Identifier(Identifier {
            type_descriptions: TypeDescriptions { type_string: Some(type_string), .. },
            ..
        }) = assignment.left_hand_side.as_ref()
        && SIGNED_STORAGE_ARRAY_POINTER.is_match(type_string)
    {
        return true;
    }
    false
}

#[cfg(test)]
mod storage_signed_array_detector {

    use crate::detect::{
        detector::IssueDetector,
        high::signed_integer_storage_array::{
            SIGNED_STORAGE_ARRAY_POINTER, StorageSignedIntegerArrayDetector,
        },
    };

    #[test]

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

        let mut detector = StorageSignedIntegerArrayDetector::default();
        let found = detector.detect(&context).unwrap();

        assert!(found);
        assert_eq!(detector.instances().len(), 1);
    }

    #[test]
    fn test_regular_expression_works() {
        // TARGET signed storage array references

        assert!(SIGNED_STORAGE_ARRAY_POINTER.is_match("int256[3] storage ref"));
        assert!(SIGNED_STORAGE_ARRAY_POINTER.is_match("int[1300] storage ref"));
        assert!(SIGNED_STORAGE_ARRAY_POINTER.is_match("int8[] storage ref"));
        assert!(SIGNED_STORAGE_ARRAY_POINTER.is_match("int[] storage ref"));
        assert!(!SIGNED_STORAGE_ARRAY_POINTER.is_match("uint256[3] storage ref"));
        assert!(!SIGNED_STORAGE_ARRAY_POINTER.is_match("uint[1300] storage ref"));
        assert!(!SIGNED_STORAGE_ARRAY_POINTER.is_match("uint8[] storage ref"));
        assert!(!SIGNED_STORAGE_ARRAY_POINTER.is_match("uint[] storage ref"));
    }
}

```
Page 9/94FirstPrevNextLast