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

# Directory Structure

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

# Files

--------------------------------------------------------------------------------
/benchmarks/aderyn/report/both/iteration_times.svg:
--------------------------------------------------------------------------------

```
  1 | <svg width="960" height="540" viewBox="0 0 960 540" xmlns="http://www.w3.org/2000/svg">
  2 | <text x="480" y="32" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="16.129032258064516" opacity="1" fill="#000000">
  3 | aderyn
  4 | </text>
  5 | <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)">
  6 | Average Iteration Time (ms)
  7 | </text>
  8 | <line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="472" x2="87" y2="53"/>
  9 | <line opacity="0.2" stroke="#000000" stroke-width="1" x1="171" y1="472" x2="171" y2="53"/>
 10 | <line opacity="0.2" stroke="#000000" stroke-width="1" x1="256" y1="472" x2="256" y2="53"/>
 11 | <line opacity="0.2" stroke="#000000" stroke-width="1" x1="340" y1="472" x2="340" y2="53"/>
 12 | <line opacity="0.2" stroke="#000000" stroke-width="1" x1="425" y1="472" x2="425" y2="53"/>
 13 | <line opacity="0.2" stroke="#000000" stroke-width="1" x1="509" y1="472" x2="509" y2="53"/>
 14 | <line opacity="0.2" stroke="#000000" stroke-width="1" x1="594" y1="472" x2="594" y2="53"/>
 15 | <line opacity="0.2" stroke="#000000" stroke-width="1" x1="678" y1="472" x2="678" y2="53"/>
 16 | <line opacity="0.2" stroke="#000000" stroke-width="1" x1="763" y1="472" x2="763" y2="53"/>
 17 | <line opacity="0.2" stroke="#000000" stroke-width="1" x1="847" y1="472" x2="847" y2="53"/>
 18 | <line opacity="0.2" stroke="#000000" stroke-width="1" x1="932" y1="472" x2="932" y2="53"/>
 19 | <line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="443" x2="932" y2="443"/>
 20 | <line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="388" x2="932" y2="388"/>
 21 | <line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="333" x2="932" y2="333"/>
 22 | <line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="277" x2="932" y2="277"/>
 23 | <line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="222" x2="932" y2="222"/>
 24 | <line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="167" x2="932" y2="167"/>
 25 | <line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="112" x2="932" y2="112"/>
 26 | <line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="56" x2="932" y2="56"/>
 27 | <polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="86,53 86,472 "/>
 28 | <text x="77" y="443" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
 29 | 100.0
 30 | </text>
 31 | <polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,443 86,443 "/>
 32 | <text x="77" y="388" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
 33 | 120.0
 34 | </text>
 35 | <polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,388 86,388 "/>
 36 | <text x="77" y="333" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
 37 | 140.0
 38 | </text>
 39 | <polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,333 86,333 "/>
 40 | <text x="77" y="277" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
 41 | 160.0
 42 | </text>
 43 | <polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,277 86,277 "/>
 44 | <text x="77" y="222" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
 45 | 180.0
 46 | </text>
 47 | <polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,222 86,222 "/>
 48 | <text x="77" y="167" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
 49 | 200.0
 50 | </text>
 51 | <polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,167 86,167 "/>
 52 | <text x="77" y="112" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
 53 | 220.0
 54 | </text>
 55 | <polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,112 86,112 "/>
 56 | <text x="77" y="56" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
 57 | 240.0
 58 | </text>
 59 | <polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,56 86,56 "/>
 60 | <polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="87,473 932,473 "/>
 61 | <text x="87" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
 62 | 0
 63 | </text>
 64 | <polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="87,473 87,478 "/>
 65 | <text x="171" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
 66 | 10
 67 | </text>
 68 | <polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="171,473 171,478 "/>
 69 | <text x="256" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
 70 | 20
 71 | </text>
 72 | <polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="256,473 256,478 "/>
 73 | <text x="340" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
 74 | 30
 75 | </text>
 76 | <polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="340,473 340,478 "/>
 77 | <text x="425" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
 78 | 40
 79 | </text>
 80 | <polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="425,473 425,478 "/>
 81 | <text x="509" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
 82 | 50
 83 | </text>
 84 | <polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="509,473 509,478 "/>
 85 | <text x="594" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
 86 | 60
 87 | </text>
 88 | <polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="594,473 594,478 "/>
 89 | <text x="678" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
 90 | 70
 91 | </text>
 92 | <polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="678,473 678,478 "/>
 93 | <text x="763" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
 94 | 80
 95 | </text>
 96 | <polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="763,473 763,478 "/>
 97 | <text x="847" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
 98 | 90
 99 | </text>
100 | <polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="847,473 847,478 "/>
101 | <text x="932" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
102 | 100
103 | </text>
104 | <polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="932,473 932,478 "/>
105 | <circle cx="95" cy="460" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
106 | <circle cx="103" cy="372" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
107 | <circle cx="112" cy="453" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
108 | <circle cx="120" cy="437" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
109 | <circle cx="129" cy="453" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
110 | <circle cx="137" cy="460" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
111 | <circle cx="146" cy="464" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
112 | <circle cx="154" cy="465" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
113 | <circle cx="163" cy="323" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
114 | <circle cx="171" cy="394" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
115 | <circle cx="179" cy="397" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
116 | <circle cx="188" cy="387" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
117 | <circle cx="196" cy="390" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
118 | <circle cx="205" cy="435" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
119 | <circle cx="213" cy="411" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
120 | <circle cx="222" cy="441" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
121 | <circle cx="230" cy="454" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
122 | <circle cx="239" cy="441" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
123 | <circle cx="247" cy="433" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
124 | <circle cx="256" cy="453" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
125 | <circle cx="264" cy="437" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
126 | <circle cx="272" cy="445" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
127 | <circle cx="281" cy="432" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
128 | <circle cx="289" cy="434" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
129 | <circle cx="298" cy="192" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
130 | <circle cx="306" cy="169" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
131 | <circle cx="315" cy="325" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
132 | <circle cx="323" cy="442" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
133 | <circle cx="332" cy="465" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
134 | <circle cx="340" cy="462" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
135 | <circle cx="348" cy="464" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
136 | <circle cx="357" cy="462" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
137 | <circle cx="365" cy="465" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
138 | <circle cx="374" cy="465" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
139 | <circle cx="382" cy="460" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
140 | <circle cx="391" cy="458" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
141 | <circle cx="399" cy="454" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
142 | <circle cx="408" cy="461" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
143 | <circle cx="416" cy="472" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
144 | <circle cx="425" cy="462" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
145 | <circle cx="433" cy="466" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
146 | <circle cx="441" cy="466" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
147 | <circle cx="450" cy="432" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
148 | <circle cx="458" cy="434" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
149 | <circle cx="467" cy="405" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
150 | <circle cx="475" cy="418" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
151 | <circle cx="484" cy="456" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
152 | <circle cx="492" cy="466" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
153 | <circle cx="501" cy="450" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
154 | <circle cx="509" cy="354" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
155 | <circle cx="517" cy="374" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
156 | <circle cx="526" cy="445" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
157 | <circle cx="534" cy="461" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
158 | <circle cx="543" cy="462" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
159 | <circle cx="551" cy="458" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
160 | <circle cx="560" cy="441" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
161 | <circle cx="568" cy="427" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
162 | <circle cx="577" cy="402" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
163 | <circle cx="585" cy="409" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
164 | <circle cx="594" cy="397" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
165 | <circle cx="602" cy="439" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
166 | <circle cx="610" cy="443" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
167 | <circle cx="619" cy="444" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
168 | <circle cx="627" cy="432" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
169 | <circle cx="636" cy="432" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
170 | <circle cx="644" cy="428" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
171 | <circle cx="653" cy="396" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
172 | <circle cx="661" cy="402" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
173 | <circle cx="670" cy="390" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
174 | <circle cx="678" cy="402" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
175 | <circle cx="686" cy="435" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
176 | <circle cx="695" cy="390" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
177 | <circle cx="703" cy="306" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
178 | <circle cx="712" cy="333" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
179 | <circle cx="720" cy="382" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
180 | <circle cx="729" cy="386" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
181 | <circle cx="737" cy="53" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
182 | <circle cx="746" cy="288" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
183 | <circle cx="754" cy="277" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
184 | <circle cx="763" cy="340" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
185 | <circle cx="771" cy="338" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
186 | <circle cx="779" cy="334" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
187 | <circle cx="788" cy="315" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
188 | <circle cx="796" cy="368" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
189 | <circle cx="805" cy="416" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
190 | <circle cx="813" cy="400" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
191 | <circle cx="822" cy="404" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
192 | <circle cx="830" cy="401" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
193 | <circle cx="839" cy="370" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
194 | <circle cx="847" cy="279" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
195 | <circle cx="855" cy="377" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
196 | <circle cx="864" cy="394" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
197 | <circle cx="872" cy="398" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
198 | <circle cx="881" cy="387" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
199 | <circle cx="889" cy="399" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
200 | <circle cx="898" cy="268" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
201 | <circle cx="906" cy="404" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
202 | <circle cx="915" cy="244" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
203 | <circle cx="923" cy="412" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
204 | <circle cx="932" cy="384" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
205 | <circle cx="95" cy="469" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
206 | <circle cx="103" cy="466" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
207 | <circle cx="112" cy="464" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
208 | <circle cx="120" cy="463" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
209 | <circle cx="129" cy="464" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
210 | <circle cx="137" cy="466" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
211 | <circle cx="146" cy="464" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
212 | <circle cx="154" cy="463" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
213 | <circle cx="163" cy="462" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
214 | <circle cx="171" cy="465" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
215 | <circle cx="179" cy="470" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
216 | <circle cx="188" cy="465" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
217 | <circle cx="196" cy="466" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
218 | <circle cx="205" cy="471" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
219 | <circle cx="213" cy="466" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
220 | <circle cx="222" cy="461" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
221 | <circle cx="230" cy="466" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
222 | <circle cx="239" cy="468" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
223 | <circle cx="247" cy="465" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
224 | <circle cx="256" cy="461" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
225 | <circle cx="264" cy="457" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
226 | <circle cx="272" cy="468" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
227 | <circle cx="281" cy="471" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
228 | <circle cx="289" cy="470" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
229 | <circle cx="298" cy="462" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
230 | <circle cx="306" cy="370" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
231 | <circle cx="315" cy="435" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
232 | <circle cx="323" cy="458" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
233 | <circle cx="332" cy="465" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
234 | <circle cx="340" cy="464" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
235 | <circle cx="348" cy="468" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
236 | <circle cx="357" cy="468" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
237 | <circle cx="365" cy="464" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
238 | <circle cx="374" cy="471" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
239 | <circle cx="382" cy="465" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
240 | <circle cx="391" cy="472" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
241 | <circle cx="399" cy="457" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
242 | <circle cx="408" cy="467" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
243 | <circle cx="416" cy="468" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
244 | <circle cx="425" cy="466" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
245 | <circle cx="433" cy="464" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
246 | <circle cx="441" cy="470" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
247 | <circle cx="450" cy="463" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
248 | <circle cx="458" cy="469" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
249 | <circle cx="467" cy="464" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
250 | <circle cx="475" cy="472" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
251 | <circle cx="484" cy="467" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
252 | <circle cx="492" cy="462" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
253 | <circle cx="501" cy="439" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
254 | <circle cx="509" cy="466" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
255 | <circle cx="517" cy="470" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
256 | <circle cx="526" cy="471" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
257 | <circle cx="534" cy="467" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
258 | <circle cx="543" cy="467" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
259 | <circle cx="551" cy="462" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
260 | <circle cx="560" cy="461" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
261 | <circle cx="568" cy="469" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
262 | <circle cx="577" cy="470" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
263 | <circle cx="585" cy="464" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
264 | <circle cx="594" cy="470" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
265 | <circle cx="602" cy="468" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
266 | <circle cx="610" cy="470" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
267 | <circle cx="619" cy="466" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
268 | <circle cx="627" cy="468" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
269 | <circle cx="636" cy="471" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
270 | <circle cx="644" cy="468" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
271 | <circle cx="653" cy="467" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
272 | <circle cx="661" cy="466" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
273 | <circle cx="670" cy="466" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
274 | <circle cx="678" cy="467" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
275 | <circle cx="686" cy="463" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
276 | <circle cx="695" cy="464" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
277 | <circle cx="703" cy="466" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
278 | <circle cx="712" cy="464" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
279 | <circle cx="720" cy="463" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
280 | <circle cx="729" cy="467" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
281 | <circle cx="737" cy="468" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
282 | <circle cx="746" cy="465" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
283 | <circle cx="754" cy="468" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
284 | <circle cx="763" cy="466" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
285 | <circle cx="771" cy="466" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
286 | <circle cx="779" cy="466" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
287 | <circle cx="788" cy="467" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
288 | <circle cx="796" cy="465" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
289 | <circle cx="805" cy="467" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
290 | <circle cx="813" cy="353" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
291 | <circle cx="822" cy="462" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
292 | <circle cx="830" cy="462" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
293 | <circle cx="839" cy="465" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
294 | <circle cx="847" cy="466" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
295 | <circle cx="855" cy="468" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
296 | <circle cx="864" cy="468" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
297 | <circle cx="872" cy="462" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
298 | <circle cx="881" cy="467" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
299 | <circle cx="889" cy="465" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
300 | <circle cx="898" cy="467" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
301 | <circle cx="906" cy="464" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
302 | <circle cx="915" cy="466" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
303 | <circle cx="923" cy="467" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
304 | <circle cx="932" cy="463" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
305 | <text x="132" y="68" dy="0.76em" text-anchor="start" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
306 | Current
307 | </text>
308 | <text x="132" y="83" dy="0.76em" text-anchor="start" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
309 | Base
310 | </text>
311 | <circle cx="112" cy="73" r="3" opacity="1" fill="#1F78B4" stroke="none" stroke-width="1"/>
312 | <circle cx="112" cy="88" r="3" opacity="1" fill="#E31A1C" stroke="none" stroke-width="1"/>
313 | </svg>
314 | 
```

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

```rust
   1 | use crate::{
   2 |     ast::*,
   3 |     context::workspace::WorkspaceContext,
   4 |     visitor::ast_visitor::{ASTConstVisitor, Node},
   5 | };
   6 | use eyre::*;
   7 | use std::{
   8 |     collections::{BTreeMap, BTreeSet},
   9 |     fmt::Debug,
  10 |     iter::zip,
  11 |     ops::Add,
  12 | };
  13 | 
  14 | /// Given an AST Block, it tries to detect any state variable inside it that may have been
  15 | /// manipulated. Now it's important to know that manipulations can occur either directly by
  16 | /// assigning to a state variable or, it may occur by assigning to a storage pointer that points to
  17 | /// some state variable. This light weight state variable manipulation finder captures both of the
  18 | /// above kinds of assignments. However, it's not smart enough to use a data dependency graph to
  19 | /// determine the exact state variables these storage pointers would be pointing to, in the context
  20 | /// of the block-flow.
  21 | ///
  22 | /// NOTE - Assignment is not the only avenue for manipulating state variables, but also operations
  23 | /// like `push()` and `pop()` on arrays, `M[i] = x` on mappings, `delete X` imply the same.
  24 | ///
  25 | /// Here, the term manipulation covers all kinds of changes discussed above.
  26 | ///
  27 | /// IMPORTANT: DO NOT MAKE THESE MEMBERS PUBLIC. Use the public methods implemented on this
  28 | /// structure only.
  29 | pub struct ApproximateStorageChangeFinder<'a> {
  30 |     directly_manipulated_state_variables: BTreeSet<NodeID>,
  31 |     manipulated_storage_pointers: BTreeSet<NodeID>,
  32 |     /// Key => State Variable ID, Value => Storage Pointer ID (Heuristics based, this map is NOT
  33 |     /// exhaustive) It leaves out a lot of links especially in cases where storage pointers are
  34 |     /// passed to and fro internal functions. But on average, for most cases the way code is
  35 |     /// generally written, this should contain a decent chunk of links to lookup.
  36 |     state_variables_to_storage_pointers: BTreeMap<NodeID, BTreeSet<NodeID>>,
  37 |     context: &'a WorkspaceContext,
  38 | }
  39 | 
  40 | /// This trait implementation will be useful when we run it through our callgraph and try to
  41 | /// aggregate state variable changes.
  42 | impl<'a> Add<ApproximateStorageChangeFinder<'_>> for ApproximateStorageChangeFinder<'a> {
  43 |     type Output = ApproximateStorageChangeFinder<'a>;
  44 | 
  45 |     fn add(mut self, rhs: ApproximateStorageChangeFinder) -> Self::Output {
  46 |         self.directly_manipulated_state_variables
  47 |             .extend(rhs.directly_manipulated_state_variables.iter());
  48 |         self.manipulated_storage_pointers.extend(rhs.manipulated_storage_pointers.iter());
  49 |         // For state_variables_to_storage_pointers, we have to "add" the storage point entry vectors
  50 |         for (state_var_id, storage_pointer_ids) in &rhs.state_variables_to_storage_pointers {
  51 |             match self.state_variables_to_storage_pointers.entry(*state_var_id) {
  52 |                 std::collections::btree_map::Entry::Vacant(v) => {
  53 |                     v.insert(BTreeSet::from_iter(storage_pointer_ids.iter().copied()));
  54 |                 }
  55 |                 std::collections::btree_map::Entry::Occupied(mut o) => {
  56 |                     (*o.get_mut()).extend(storage_pointer_ids);
  57 |                 }
  58 |             };
  59 |         }
  60 |         self
  61 |     }
  62 | }
  63 | 
  64 | impl Debug for ApproximateStorageChangeFinder<'_> {
  65 |     // Do not print context. Hence, debug is custom derived for this struct
  66 |     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  67 |         writeln!(f, "Manipulated directly: {:?}", self.directly_manipulated_state_variables)?;
  68 | 
  69 |         if !self.directly_manipulated_state_variables.is_empty() {
  70 |             writeln!(f, "↓↓")?;
  71 |             for id in &self.directly_manipulated_state_variables {
  72 |                 if let Some(node) = self.context.nodes.get(id) {
  73 |                     let loc_info = self.context.get_node_sort_key(node);
  74 |                     writeln!(f, "Line {:?}", (loc_info.1, loc_info.2))?;
  75 |                 } else {
  76 |                     writeln!(f, "<unknown_node_id_{}>\n", id)?;
  77 |                 }
  78 |             }
  79 |             writeln!(f)?;
  80 |         }
  81 | 
  82 |         writeln!(
  83 |             f,
  84 |             "Manipulated through storage pointers: {:?}",
  85 |             self.manipulated_storage_pointers
  86 |         )?;
  87 | 
  88 |         if !self.manipulated_storage_pointers.is_empty() {
  89 |             writeln!(f, "↓↓")?;
  90 |             for id in &self.manipulated_storage_pointers {
  91 |                 if let Some(node) = self.context.nodes.get(id) {
  92 |                     let loc_info = self.context.get_node_sort_key(node);
  93 |                     writeln!(f, "Line {:?}", (loc_info.1, loc_info.2))?;
  94 |                 } else {
  95 |                     writeln!(f, "<unknown_node_id_{}>", id)?;
  96 |                 }
  97 |             }
  98 |             writeln!(f)?;
  99 |         }
 100 | 
 101 |         writeln!(f, "Links heuristics: {:?}", self.state_variables_to_storage_pointers)?;
 102 | 
 103 |         if !self.state_variables_to_storage_pointers.is_empty() {
 104 |             writeln!(f, "↓↓")?;
 105 |             for (state_variable_id, storage_pointer_references) in
 106 |                 &self.state_variables_to_storage_pointers
 107 |             {
 108 |                 if let Some(node) = self.context.nodes.get(state_variable_id) {
 109 |                     let loc_info = self.context.get_node_sort_key(node);
 110 |                     writeln!(f, "Links to {:?}", (loc_info.1, loc_info.2))?;
 111 |                     for node_id in storage_pointer_references {
 112 |                         if let Some(node) = self.context.nodes.get(node_id) {
 113 |                             let loc_info = self.context.get_node_sort_key(node);
 114 |                             writeln!(f, "\t <> {:?}", (loc_info.1, loc_info.2))?;
 115 |                         }
 116 |                     }
 117 |                 } else {
 118 |                     writeln!(f, "<unknown_node_id_{}>", state_variable_id)?;
 119 |                 }
 120 |             }
 121 |             writeln!(f)?;
 122 |         }
 123 | 
 124 |         std::fmt::Result::Ok(())
 125 |     }
 126 | }
 127 | 
 128 | /// Interface to be used by other modules defined here.
 129 | impl<'a> ApproximateStorageChangeFinder<'a> {
 130 |     /// Initialize
 131 |     pub fn from<T: Node + ?Sized>(context: &'a WorkspaceContext, node: &T) -> Self {
 132 |         let mut extractor = ApproximateStorageChangeFinder {
 133 |             directly_manipulated_state_variables: BTreeSet::new(),
 134 |             manipulated_storage_pointers: BTreeSet::new(),
 135 |             state_variables_to_storage_pointers: BTreeMap::new(),
 136 |             context,
 137 |         };
 138 |         node.accept(&mut extractor).unwrap_or_default();
 139 |         extractor
 140 |     }
 141 | 
 142 |     pub fn state_variables_have_been_manipulated(&self) -> bool {
 143 |         !self.directly_manipulated_state_variables.is_empty()
 144 |             || !self.manipulated_storage_pointers.is_empty()
 145 |     }
 146 | 
 147 |     pub fn no_state_variable_has_been_manipulated(&self) -> bool {
 148 |         self.directly_manipulated_state_variables.is_empty()
 149 |             && self.manipulated_storage_pointers.is_empty()
 150 |     }
 151 | 
 152 |     pub fn fetch_non_exhaustive_manipulated_state_variables(&self) -> Vec<&VariableDeclaration> {
 153 |         let mut manipulated_state_vars: BTreeSet<NodeID> = BTreeSet::new();
 154 |         manipulated_state_vars.extend(self.directly_manipulated_state_variables.iter());
 155 |         for (state_variable_id, storage_pointers) in self.state_variables_to_storage_pointers.iter()
 156 |         {
 157 |             if storage_pointers.iter().any(|ptr| self.manipulated_storage_pointers.contains(ptr)) {
 158 |                 manipulated_state_vars.insert(*state_variable_id);
 159 |             }
 160 |         }
 161 |         manipulated_state_vars
 162 |             .into_iter()
 163 |             .flat_map(|v| self.context.nodes.get(&v))
 164 |             .flat_map(|n| {
 165 |                 if let ASTNode::VariableDeclaration(variable_declaration) = n {
 166 |                     assert!(variable_declaration.state_variable);
 167 |                     return Some(variable_declaration);
 168 |                 }
 169 |                 None
 170 |             })
 171 |             .collect()
 172 |     }
 173 | 
 174 |     pub fn state_variable_has_been_manipulated(&self, var: &VariableDeclaration) -> Option<bool> {
 175 |         if self.directly_manipulated_state_variables.contains(&var.id) {
 176 |             return Some(true);
 177 |         }
 178 |         if self.manipulated_storage_pointers.is_empty() {
 179 |             return Some(false);
 180 |         }
 181 |         // Now use our heuristics
 182 |         if self.state_variables_to_storage_pointers.get(&var.id).is_some_and(|entry| {
 183 |             entry.iter().any(|e| self.manipulated_storage_pointers.contains(e))
 184 |         }) {
 185 |             return Some(true);
 186 |         }
 187 | 
 188 |         // At this point, we don't know if any of the storage pointers refer to [`var`], so we
 189 |         // cannot say for sure, if it has been manipulated or not.
 190 |         None
 191 |     }
 192 | 
 193 |     pub fn state_variable_has_not_been_manipulated(
 194 |         &self,
 195 |         var: &VariableDeclaration,
 196 |     ) -> Option<bool> {
 197 |         if self.directly_manipulated_state_variables.contains(&var.id) {
 198 |             return Some(false);
 199 |         }
 200 |         if self.manipulated_storage_pointers.is_empty() {
 201 |             return Some(true);
 202 |         }
 203 |         // Now use our heuristics
 204 |         if self.state_variables_to_storage_pointers.get(&var.id).is_some_and(|entry| {
 205 |             entry.iter().any(|e| self.manipulated_storage_pointers.contains(e))
 206 |         }) {
 207 |             return Some(false);
 208 |         }
 209 | 
 210 |         // At this point, we don't know if any of the storage pointers refer to [`var`], so we
 211 |         // cannot say for sure, if it has been manipulated or not.
 212 |         None
 213 |     }
 214 | }
 215 | 
 216 | impl ASTConstVisitor for ApproximateStorageChangeFinder<'_> {
 217 |     fn visit_unary_operation(&mut self, node: &UnaryOperation) -> Result<bool> {
 218 |         // WRITE HEURISTICS
 219 |         // Catch unary operations that manipulate variables
 220 |         if node.operator == "delete" || node.operator == "++" || node.operator == "--" {
 221 |             for id in find_base(node.sub_expression.as_ref()).0 {
 222 |                 match is_storage_variable_or_storage_pointer(self.context, id) {
 223 |                     Some(AssigneeType::StateVariable) => {
 224 |                         self.directly_manipulated_state_variables.insert(id);
 225 |                     }
 226 |                     Some(AssigneeType::StorageLocationVariable) => {
 227 |                         self.manipulated_storage_pointers.insert(id);
 228 |                     }
 229 |                     None => {}
 230 |                 };
 231 |             }
 232 |         }
 233 | 
 234 |         Ok(true)
 235 |     }
 236 | 
 237 |     fn visit_member_access(&mut self, member: &MemberAccess) -> Result<bool> {
 238 |         if !member.expression.type_descriptions().is_some_and(|type_desc| {
 239 |             type_desc.type_string.as_ref().is_some_and(|type_string| {
 240 |                 type_string.ends_with("[] storage ref")
 241 |                     || type_string.ends_with("[] storage pointer")
 242 |             })
 243 |         }) {
 244 |             return Ok(true);
 245 |         }
 246 | 
 247 |         let (base_variable_ids, _) = find_base(member.expression.as_ref());
 248 |         // assert!(base_variable_ids.len() == 1);
 249 | 
 250 |         // WRITE HEURISTICS
 251 |         if member.member_name == "push" || member.member_name == "pop" {
 252 |             for id in base_variable_ids.iter() {
 253 |                 match is_storage_variable_or_storage_pointer(self.context, *id) {
 254 |                     Some(AssigneeType::StateVariable) => {
 255 |                         self.directly_manipulated_state_variables.insert(*id);
 256 |                     }
 257 |                     Some(AssigneeType::StorageLocationVariable) => {
 258 |                         self.manipulated_storage_pointers.insert(*id);
 259 |                     }
 260 |                     None => {}
 261 |                 };
 262 |             }
 263 |         }
 264 | 
 265 |         Ok(true)
 266 |     }
 267 | 
 268 |     fn visit_assignment(&mut self, assignment: &Assignment) -> Result<bool> {
 269 |         let (base_variable_lhs_ids, type_strings) = find_base(assignment.left_hand_side.as_ref());
 270 |         let (base_variable_rhs_ids, _) = find_base(assignment.right_hand_side.as_ref());
 271 | 
 272 |         for (id, type_string) in zip(base_variable_lhs_ids.iter(), type_strings.iter()) {
 273 |             // When something is assigned to an expression of type "storage pointer", no state
 274 |             // variable's value changes. The only value changed is the thing which the
 275 |             // storage pointer points to. The value of a storage variable changes if the
 276 |             // expression's type string contains "storage ref" in case of structs, arrays, etc
 277 | 
 278 |             if type_string.ends_with("storage pointer") {
 279 |                 continue;
 280 |             }
 281 | 
 282 |             match is_storage_variable_or_storage_pointer(self.context, *id) {
 283 |                 Some(AssigneeType::StateVariable) => {
 284 |                     self.directly_manipulated_state_variables.insert(*id);
 285 |                 }
 286 |                 Some(AssigneeType::StorageLocationVariable) => {
 287 |                     self.manipulated_storage_pointers.insert(*id);
 288 |                 }
 289 |                 None => {}
 290 |             };
 291 |         }
 292 | 
 293 |         // Now, on a separate note, let's look for a heuristic to link up state variables with
 294 |         // storage pointers. But here, we only handle the cases when there are equal number
 295 |         // of elements on either side of `=` . This allows us to assume 1:1 relationship.
 296 |         if base_variable_lhs_ids.len() == base_variable_rhs_ids.len() {
 297 |             for (lhs_id, rhs_id) in zip(base_variable_lhs_ids, base_variable_rhs_ids) {
 298 |                 if let (
 299 |                     Some(AssigneeType::StorageLocationVariable),
 300 |                     Some(AssigneeType::StateVariable),
 301 |                 ) = (
 302 |                     is_storage_variable_or_storage_pointer(self.context, lhs_id),
 303 |                     is_storage_variable_or_storage_pointer(self.context, rhs_id),
 304 |                 ) {
 305 |                     match self.state_variables_to_storage_pointers.entry(rhs_id) {
 306 |                         std::collections::btree_map::Entry::Vacant(v) => {
 307 |                             v.insert(BTreeSet::from_iter([lhs_id]));
 308 |                         }
 309 |                         std::collections::btree_map::Entry::Occupied(mut o) => {
 310 |                             (*o.get_mut()).insert(lhs_id);
 311 |                         }
 312 |                     };
 313 |                 }
 314 |             }
 315 |         }
 316 | 
 317 |         // READ HEURISTICS
 318 |         // Pretty much the same logic as described in `visit_variable_declaration_statement`
 319 |         //
 320 | 
 321 |         // let (left_node_ids, _) = find_base(assignment.left_hand_side.as_ref());
 322 |         // let right_node_ids = flatten_expression(assignment.right_hand_side.as_ref());
 323 | 
 324 |         // See if it's a 1:1 relationship. Only then, proceed. Later, we can think of heuristics to
 325 |         // handle x:y (but likely we will have to rely on a dependency graph for that. Case:
 326 |         // `(x, y) = func()` is out of scope for this).
 327 |         //
 328 |         // When it comes to tracking WRITEs, it doesn't matter what's on RHS of `=`
 329 |         // When it comes to tracking READs, it does! If the LHS type is storage then you are simply
 330 |         // carrying a reference at compile time, you are not actually reading. Whereas, if
 331 |         // the LHS is memory, you are performing "sload"! But again, this logic changes
 332 |         // based on type of value in RHS. If it's a function call you should look at
 333 |         // return values and nature of the corresponding variable where that value will be stored.
 334 |         // Likewise, different for different nodes albeit identifier one is probably the
 335 |         // most straightforward if left_node_ids.len() == right_node_ids.len() {}
 336 | 
 337 |         Ok(true)
 338 |     }
 339 | 
 340 |     // For heurstics: Try to link up as much storage pointers and state variables as possible
 341 |     fn visit_variable_declaration_statement(
 342 |         &mut self,
 343 |         node: &VariableDeclarationStatement,
 344 |     ) -> Result<bool> {
 345 |         if let Some(initial_value) = node.initial_value.as_ref() {
 346 |             let corresponding_variable_declaration_ids = node
 347 |                 .declarations
 348 |                 .iter()
 349 |                 .map(|v| {
 350 |                     if let Some(variable_declaration) = v {
 351 |                         variable_declaration.id
 352 |                     } else {
 353 |                         i64::MIN
 354 |                     }
 355 |                 })
 356 |                 .collect::<Vec<_>>();
 357 |             let initial_value_node_ids = flatten_expression(initial_value); // For READ heuristics
 358 |             let (initial_value_bases, _) = find_base(initial_value); // For LINK heuristics
 359 | 
 360 |             // Let's first support 1:1 relationships only
 361 |             if corresponding_variable_declaration_ids.len() == initial_value_node_ids.len() {
 362 |                 let common_len = corresponding_variable_declaration_ids.len();
 363 | 
 364 |                 // This for loop takes care of recording instances in VDS (Var Decl Stmnt) where
 365 |                 // there is a read from the storage.
 366 |                 //
 367 |                 //  READ HEURISTICS
 368 |                 //
 369 |                 // TODO: Write tests for these
 370 |                 // Then creates `passes_read_check()` before matching the var id on extracting
 371 |                 // reference declarations Then replicate the logic for assignments
 372 |                 // use lvaluerequested = false and islvalue = true to check if it's being read
 373 |                 // in case of visiting indexaccess, memberaccess, etc (expr_node! variants)
 374 |                 // So that it can detect stuff outside of just assignments. Example -
 375 |                 // functionCall(a.b) where a is state var (Technically you are
 376 |                 // reading a.b's value to make that function call)
 377 |                 //
 378 |                 // for i in 0..common_len {
 379 |                 //     let variable_declaration_id = corresponding_variable_declaration_ids[i];
 380 |                 //     let corresponding_initial_value_id = initial_value_node_ids[i];
 381 | 
 382 |                 //     if is_storage_variable_or_storage_pointer(
 383 |                 //         &self.context,
 384 |                 //         variable_declaration_id,
 385 |                 //     )
 386 |                 //     .is_some()
 387 |                 //     {
 388 |                 //         // If we are not assigning something to a storage pointer or a storage
 389 |                 // reference, that means         // we're storing it in memory.
 390 |                 // Therefore, we can consider that the corresponding initialValue
 391 |                 //         // is being "read". Otherwise we are just creating pointers, not
 392 |                 // "sload"ing.         continue;
 393 |                 //     }
 394 | 
 395 |                 //     if let Some(node) = self.context.nodes.get(&corresponding_initial_value_id) {
 396 |                 //         // In case of internal function call, it's complex to analyze
 397 |                 //         if node.node_type() != NodeType::FunctionCall || it is{
 398 |                 //             let referenced_declarations =
 399 |                 //                 ExtractReferencedDeclarations::from(node).extracted;
 400 | 
 401 |                 //             for variable_id in referenced_declarations {
 402 |                 //                 match is_storage_variable_or_storage_pointer(
 403 |                 //                     self.context,
 404 |                 //                     variable_id,
 405 |                 //                 ) {
 406 |                 //                     // Assumption: At this point in code we know that it could be
 407 |                 // a storage pointer/variable that represents                     //
 408 |                 // uint, bool, array element, etc. so it's technically being read.
 409 |                 //                     Some(AssigneeType::StateVariable) => {
 410 |                 //                         self.directly_read_state_variables.insert(variable_id);
 411 |                 //                     }
 412 |                 //                     Some(AssigneeType::StorageLocationVariable) => {
 413 |                 //                         self.read_storage_pointers.insert(variable_id);
 414 |                 //                     }
 415 |                 //                     None => {}
 416 |                 //                 }
 417 |                 //             }
 418 |                 //         }
 419 |                 //     }
 420 |                 // }
 421 | 
 422 |                 assert!(initial_value_bases.len() == common_len);
 423 | 
 424 |                 // LINK heuristics
 425 |                 for i in 0..common_len {
 426 |                     let variable_declaration_id = corresponding_variable_declaration_ids[i];
 427 |                     let corresponding_initial_value_base_id = initial_value_bases[i];
 428 | 
 429 |                     if let (
 430 |                         Some(AssigneeType::StorageLocationVariable),
 431 |                         Some(AssigneeType::StateVariable),
 432 |                     ) = (
 433 |                         is_storage_variable_or_storage_pointer(
 434 |                             self.context,
 435 |                             variable_declaration_id,
 436 |                         ),
 437 |                         is_storage_variable_or_storage_pointer(
 438 |                             self.context,
 439 |                             corresponding_initial_value_base_id,
 440 |                         ),
 441 |                     ) {
 442 |                         match self
 443 |                             .state_variables_to_storage_pointers
 444 |                             .entry(corresponding_initial_value_base_id)
 445 |                         {
 446 |                             std::collections::btree_map::Entry::Vacant(v) => {
 447 |                                 v.insert(BTreeSet::from_iter([variable_declaration_id]));
 448 |                             }
 449 |                             std::collections::btree_map::Entry::Occupied(mut o) => {
 450 |                                 (*o.get_mut()).insert(variable_declaration_id);
 451 |                             }
 452 |                         };
 453 |                     }
 454 |                 }
 455 |             }
 456 |         }
 457 | 
 458 |         Ok(true)
 459 |     }
 460 | }
 461 | 
 462 | fn flatten_expression(expr: &Expression) -> Vec<NodeID> {
 463 |     let mut node_ids = vec![];
 464 |     match expr {
 465 |         Expression::TupleExpression(TupleExpression { components, .. }) => {
 466 |             for component in components.iter().flatten() {
 467 |                 let component_node_ids = flatten_expression(component);
 468 |                 node_ids.extend(component_node_ids);
 469 |             }
 470 |         }
 471 |         _ => {
 472 |             node_ids.push(expr.get_node_id().unwrap_or(i64::MIN));
 473 |         }
 474 |     }
 475 |     node_ids
 476 | }
 477 | 
 478 | fn find_base(expr: &Expression) -> (Vec<NodeID>, Vec<String>) {
 479 |     let mut node_ids = vec![];
 480 |     let mut type_strings = vec![];
 481 |     match expr {
 482 |         Expression::Identifier(Identifier {
 483 |             referenced_declaration: Some(id),
 484 |             type_descriptions: TypeDescriptions { type_string: Some(type_string), .. },
 485 |             ..
 486 |         }) => {
 487 |             node_ids.push(*id);
 488 |             type_strings.push(type_string.clone());
 489 |         }
 490 |         // Handle mappings assignment
 491 |         Expression::IndexAccess(IndexAccess {
 492 |             base_expression,
 493 |             type_descriptions: TypeDescriptions { type_string: Some(type_string), .. },
 494 |             ..
 495 |         }) => {
 496 |             node_ids.extend(find_base(base_expression.as_ref()).0);
 497 |             type_strings.push(type_string.clone());
 498 |         }
 499 |         // Handle struct member assignment
 500 |         Expression::MemberAccess(MemberAccess {
 501 |             expression,
 502 |             type_descriptions: TypeDescriptions { type_string: Some(type_string), .. },
 503 |             ..
 504 |         }) => {
 505 |             node_ids.extend(find_base(expression.as_ref()).0);
 506 |             type_strings.push(type_string.clone());
 507 |         }
 508 |         // Handle tuple form lhs while assigning
 509 |         Expression::TupleExpression(TupleExpression { components, .. }) => {
 510 |             for component in components.iter() {
 511 |                 if let Some(component) = component {
 512 |                     let (component_node_ids, component_type_strings) = find_base(component);
 513 |                     node_ids.extend(component_node_ids);
 514 |                     type_strings.extend(component_type_strings);
 515 |                 } else {
 516 |                     node_ids.push(i64::MIN);
 517 |                     type_strings.push(String::from("irrelevant"));
 518 |                 }
 519 |             }
 520 |         }
 521 |         // Handle assignment with values like ++i, --j, i++, etc
 522 |         Expression::UnaryOperation(UnaryOperation {
 523 |             sub_expression,
 524 |             type_descriptions: TypeDescriptions { type_string: Some(type_string), .. },
 525 |             ..
 526 |         }) => {
 527 |             node_ids.extend(find_base(sub_expression.as_ref()).0);
 528 |             type_strings.push(type_string.clone());
 529 |         }
 530 |         _ => {
 531 |             node_ids.push(i64::MIN);
 532 |             type_strings.push(String::from("irrelevant"));
 533 |         }
 534 |     };
 535 |     assert_eq!(node_ids.len(), type_strings.len());
 536 |     (node_ids, type_strings)
 537 | }
 538 | 
 539 | #[derive(PartialEq)]
 540 | enum AssigneeType {
 541 |     StateVariable,
 542 |     StorageLocationVariable,
 543 | }
 544 | 
 545 | fn is_storage_variable_or_storage_pointer(
 546 |     context: &WorkspaceContext,
 547 |     node_id: NodeID,
 548 | ) -> Option<AssigneeType> {
 549 |     let node = context.nodes.get(&node_id)?;
 550 |     if let ASTNode::VariableDeclaration(variable) = node {
 551 |         if variable.storage_location == StorageLocation::Transient {
 552 |             return None;
 553 |         }
 554 |         // Assumption
 555 |         // variable.state_variable is true when it's an actual state variable
 556 |         // variable.storage_location is StorageLocation::Storage when it's a storage reference
 557 |         // pointer
 558 |         if variable.state_variable {
 559 |             return Some(AssigneeType::StateVariable);
 560 |         } else if variable.storage_location == StorageLocation::Storage {
 561 |             return Some(AssigneeType::StorageLocationVariable);
 562 |         }
 563 |     }
 564 |     None
 565 | }
 566 | 
 567 | #[cfg(test)]
 568 | mod approximate_storage_change_finder_tests {
 569 |     use crate::detect::test_utils::load_solidity_source_unit;
 570 | 
 571 |     use super::ApproximateStorageChangeFinder;
 572 | 
 573 |     #[test]
 574 | 
 575 |     fn has_variable_declarations() {
 576 |         let context = load_solidity_source_unit(
 577 |             "../tests/contract-playground/src/StateVariablesManipulation.sol",
 578 |         );
 579 | 
 580 |         assert!(!context.variable_declarations().is_empty());
 581 |     }
 582 | 
 583 |     #[test]
 584 | 
 585 |     fn test_no_state_variable_manipulations_found() {
 586 |         let context = load_solidity_source_unit(
 587 |             "../tests/contract-playground/src/StateVariablesManipulation.sol",
 588 |         );
 589 | 
 590 |         let contract = context.find_contract_by_name("NoStateVarManipulationExample");
 591 |         let func = contract.find_function_by_name("dontManipulateStateVar");
 592 | 
 593 |         let finder = ApproximateStorageChangeFinder::from(&context, func);
 594 |         let no_changes_found = !finder.state_variables_have_been_manipulated();
 595 |         println!("NoStateVarManipulationExample::dontManipulateStateVar()\n{:?}", finder);
 596 |         println!("{:?}", finder);
 597 |         assert!(no_changes_found);
 598 |     }
 599 | 
 600 |     #[test]
 601 | 
 602 |     fn test_simple_state_variable_manipulations_found() {
 603 |         let context = load_solidity_source_unit(
 604 |             "../tests/contract-playground/src/StateVariablesManipulation.sol",
 605 |         );
 606 | 
 607 |         let contract = context.find_contract_by_name("SimpleStateVarManipulationExample");
 608 |         let func = contract.find_function_by_name("manipulateStateVarDirectly");
 609 |         let func2 = contract.find_function_by_name("readSimpleStateVars");
 610 | 
 611 |         let finder = ApproximateStorageChangeFinder::from(&context, func);
 612 |         let changes_found = finder.state_variables_have_been_manipulated();
 613 |         println!("SimpleStateVarManipulationExample::manipulateStateVarDirectly()\n{:?}", finder);
 614 |         assert!(changes_found);
 615 |         assert_eq!(finder.directly_manipulated_state_variables.len(), 5);
 616 |         assert!(finder.manipulated_storage_pointers.is_empty());
 617 | 
 618 |         let finder = ApproximateStorageChangeFinder::from(&context, func2);
 619 |         let changes_found = finder.state_variables_have_been_manipulated();
 620 |         println!("SimpleStateVarManipulationExample::readSimpleStateVars()\n{:?}", finder);
 621 |         assert!(!changes_found);
 622 |         assert!(finder.directly_manipulated_state_variables.is_empty());
 623 |         assert!(finder.manipulated_storage_pointers.is_empty());
 624 |     }
 625 | 
 626 |     #[test]
 627 | 
 628 |     fn test_fixed_size_array_assignments() {
 629 |         let context = load_solidity_source_unit(
 630 |             "../tests/contract-playground/src/StateVariablesManipulation.sol",
 631 |         );
 632 | 
 633 |         let contract = context.find_contract_by_name("FixedSizeArraysAssignmentExample");
 634 | 
 635 |         let func1 = contract.find_function_by_name("manipulateDirectly");
 636 |         let func2 = contract.find_function_by_name("manipulateViaIndexAccess");
 637 | 
 638 |         // Test manipulateDirectly() function
 639 | 
 640 |         let finder = ApproximateStorageChangeFinder::from(&context, func1);
 641 |         println!("FixedSizeArraysAssignmentExample::manipulateDirectly()\n{:?}", finder);
 642 | 
 643 |         let changes_found = finder.state_variables_have_been_manipulated();
 644 |         assert!(changes_found);
 645 |         assert_eq!(finder.directly_manipulated_state_variables.len(), 1);
 646 |         assert!(finder.manipulated_storage_pointers.is_empty());
 647 | 
 648 |         // Test manipulateViaIndexAccess() function
 649 | 
 650 |         let finder = ApproximateStorageChangeFinder::from(&context, func2);
 651 |         println!("FixedSizeArraysAssignmentExample::manipulateViaIndexAccess()\n{:?}", finder);
 652 | 
 653 |         let changes_found2 = finder.state_variables_have_been_manipulated();
 654 |         assert!(changes_found2);
 655 |         assert_eq!(finder.directly_manipulated_state_variables.len(), 2);
 656 |         assert!(finder.manipulated_storage_pointers.is_empty());
 657 |     }
 658 | 
 659 |     #[test]
 660 | 
 661 |     fn test_struct_plus_fixed_array_assignment_example() {
 662 |         let context = load_solidity_source_unit(
 663 |             "../tests/contract-playground/src/StateVariablesManipulation.sol",
 664 |         );
 665 | 
 666 |         let contract = context.find_contract_by_name("StructPlusFixedArrayAssignmentExample");
 667 | 
 668 |         let func = contract.find_function_by_name("manipulateStateVariables");
 669 |         let func2 = contract.find_function_by_name("manipulateStateVariables2");
 670 |         let func3 = contract.find_function_by_name("manipulateStateVariables3");
 671 |         let func4 = contract.find_function_by_name("manipulateStateVariables4");
 672 |         let func5 = contract.find_function_by_name("manipulateStateVariables5");
 673 |         let func6 = contract.find_function_by_name("manipulateStateVariables6");
 674 |         let func7 = contract.find_function_by_name("manipulateStateVariables7");
 675 |         let func8 = contract.find_function_by_name("manipulateStateVariables8");
 676 |         let func_helper = contract.find_function_by_name("manipulateHelper");
 677 | 
 678 |         // Test manipulateStateVariables
 679 |         let finder = ApproximateStorageChangeFinder::from(&context, func);
 680 |         println!("StructPlusFixedArrayAssignmentExample::manipulateStateVariables()\n{:?}", finder);
 681 |         let changes_found = finder.state_variables_have_been_manipulated();
 682 |         assert!(changes_found);
 683 |         assert_eq!(finder.directly_manipulated_state_variables.len(), 3);
 684 |         assert!(finder.manipulated_storage_pointers.is_empty());
 685 | 
 686 |         // Test manipulateStateVariables2
 687 |         let finder = ApproximateStorageChangeFinder::from(&context, func2);
 688 |         println!(
 689 |             "StructPlusFixedArrayAssignmentExample::manipulateStateVariables2()\n{:?}",
 690 |             finder
 691 |         );
 692 |         let changes_found = finder.state_variables_have_been_manipulated();
 693 |         assert!(changes_found);
 694 |         assert_eq!(finder.manipulated_storage_pointers.len(), 1);
 695 |         assert_eq!(
 696 |             finder
 697 |                 .state_variables_to_storage_pointers
 698 |                 .get(&contract.find_state_variable_node_id_by_name("person3"))
 699 |                 .unwrap()
 700 |                 .len(),
 701 |             1
 702 |         );
 703 |         assert_eq!(
 704 |             finder
 705 |                 .state_variables_to_storage_pointers
 706 |                 .get(&contract.find_state_variable_node_id_by_name("persons"))
 707 |                 .unwrap()
 708 |                 .len(),
 709 |             1
 710 |         );
 711 |         assert!(finder.directly_manipulated_state_variables.is_empty());
 712 | 
 713 |         // Test manipulateStateVariables3
 714 |         let finder = ApproximateStorageChangeFinder::from(&context, func3);
 715 |         println!(
 716 |             "StructPlusFixedArrayAssignmentExample::manipulateStateVariables3()\n{:?}",
 717 |             finder
 718 |         );
 719 |         let no_changes_found = !finder.state_variables_have_been_manipulated();
 720 |         assert!(no_changes_found);
 721 |         assert!(finder.manipulated_storage_pointers.is_empty());
 722 |         assert!(finder.directly_manipulated_state_variables.is_empty());
 723 |         assert_eq!(finder.state_variables_to_storage_pointers.len(), 1); // person3 links to ptr_person3
 724 |         assert_eq!(
 725 |             finder
 726 |                 .state_variables_to_storage_pointers
 727 |                 .get(&contract.find_state_variable_node_id_by_name("person3"))
 728 |                 .unwrap()
 729 |                 .len(),
 730 |             1
 731 |         );
 732 | 
 733 |         // Test manipulateStateVariables4
 734 |         let finder = ApproximateStorageChangeFinder::from(&context, func4);
 735 |         println!(
 736 |             "StructPlusFixedArrayAssignmentExample::manipulateStateVariables4()\n{:?}",
 737 |             finder
 738 |         );
 739 |         let no_changes_found = !finder.state_variables_have_been_manipulated();
 740 |         assert!(no_changes_found);
 741 |         assert!(finder.manipulated_storage_pointers.is_empty());
 742 |         assert!(finder.directly_manipulated_state_variables.is_empty());
 743 | 
 744 |         // Test manipulateStateVariables5
 745 |         let finder = ApproximateStorageChangeFinder::from(&context, func5);
 746 |         println!(
 747 |             "StructPlusFixedArrayAssignmentExample::manipulateStateVariables5()\n{:?}",
 748 |             finder
 749 |         );
 750 |         let no_changes_found = !finder.state_variables_have_been_manipulated();
 751 |         assert!(no_changes_found);
 752 |         assert!(finder.manipulated_storage_pointers.is_empty());
 753 |         assert!(finder.directly_manipulated_state_variables.is_empty());
 754 |         assert_eq!(finder.state_variables_to_storage_pointers.len(), 1);
 755 |         assert_eq!(
 756 |             finder
 757 |                 .state_variables_to_storage_pointers
 758 |                 .get(&contract.find_state_variable_node_id_by_name("person3"))
 759 |                 .unwrap()
 760 |                 .len(),
 761 |             1
 762 |         );
 763 | 
 764 |         // Test funcHelper
 765 |         let finder = ApproximateStorageChangeFinder::from(&context, func_helper);
 766 |         println!("StructPlusFixedArrayAssignmentExample::manipulateHelper()\n{:?}", finder);
 767 |         let changes_found = finder.state_variables_have_been_manipulated();
 768 |         assert!(changes_found);
 769 |         assert_eq!(finder.manipulated_storage_pointers.len(), 2);
 770 |         assert!(finder.directly_manipulated_state_variables.is_empty());
 771 |         assert_eq!(
 772 |             finder
 773 |                 .state_variables_to_storage_pointers
 774 |                 .get(&contract.find_state_variable_node_id_by_name("person3"))
 775 |                 .unwrap()
 776 |                 .len(),
 777 |             1
 778 |         );
 779 | 
 780 |         // Test manipulateStateVariables6
 781 |         let finder = ApproximateStorageChangeFinder::from(&context, func6);
 782 |         println!(
 783 |             "StructPlusFixedArrayAssignmentExample::manipulateStateVariables6()\n{:?}",
 784 |             finder
 785 |         );
 786 |         let changes_found = finder.state_variables_have_been_manipulated();
 787 |         assert!(changes_found);
 788 |         assert_eq!(finder.manipulated_storage_pointers.len(), 2);
 789 |         assert!(finder.directly_manipulated_state_variables.is_empty());
 790 |         assert_eq!(
 791 |             finder
 792 |                 .state_variables_to_storage_pointers
 793 |                 .get(&contract.find_state_variable_node_id_by_name("person3"))
 794 |                 .unwrap()
 795 |                 .len(),
 796 |             4
 797 |         );
 798 | 
 799 |         // Test manipulateStateVariables7
 800 |         let finder = ApproximateStorageChangeFinder::from(&context, func7);
 801 |         println!(
 802 |             "StructPlusFixedArrayAssignmentExample::manipulateStateVariables7()\n{:?}",
 803 |             finder
 804 |         );
 805 |         let changes_found = finder.state_variables_have_been_manipulated();
 806 |         assert!(changes_found);
 807 |         assert!(finder.manipulated_storage_pointers.is_empty());
 808 |         assert_eq!(finder.directly_manipulated_state_variables.len(), 3);
 809 | 
 810 |         // Test manipulateStateVariables8
 811 |         let finder = ApproximateStorageChangeFinder::from(&context, func8);
 812 |         println!(
 813 |             "StructPlusFixedArrayAssignmentExample::manipulateStateVariables8()\n{:?}",
 814 |             finder
 815 |         );
 816 |         let changes_found = finder.state_variables_have_been_manipulated();
 817 |         assert!(changes_found);
 818 |         assert!(finder.manipulated_storage_pointers.is_empty());
 819 |         assert_eq!(finder.directly_manipulated_state_variables.len(), 2);
 820 |     }
 821 | 
 822 |     #[test]
 823 | 
 824 |     fn test_sv_manipulation_library() {
 825 |         let context = load_solidity_source_unit(
 826 |             "../tests/contract-playground/src/StateVariablesManipulation.sol",
 827 |         );
 828 | 
 829 |         let contract = context.find_contract_by_name("SVManipulationLibrary");
 830 | 
 831 |         let func = contract.find_function_by_name("manipulateLib");
 832 |         let func2 = contract.find_function_by_name("manipulateLib2");
 833 |         let func3 = contract.find_function_by_name("manipulateLib3");
 834 | 
 835 |         // Test manipulateLib()
 836 |         let finder = ApproximateStorageChangeFinder::from(&context, func);
 837 |         println!("SVManipulationLibrary::manipulateLib()\n{:?}", finder);
 838 |         let changes_found = finder.state_variables_have_been_manipulated();
 839 |         assert!(changes_found);
 840 |         assert_eq!(finder.manipulated_storage_pointers.len(), 1);
 841 |         assert!(finder.directly_manipulated_state_variables.is_empty());
 842 | 
 843 |         // Test manipulateLib2()
 844 |         let finder = ApproximateStorageChangeFinder::from(&context, func2);
 845 |         println!("SVManipulationLibrary::manipulateLib2()\n{:?}", finder);
 846 |         let changes_found = finder.state_variables_have_been_manipulated();
 847 |         assert!(changes_found);
 848 |         assert_eq!(finder.manipulated_storage_pointers.len(), 1);
 849 |         assert!(finder.directly_manipulated_state_variables.is_empty());
 850 | 
 851 |         // Test manipulateLib3()
 852 |         let finder = ApproximateStorageChangeFinder::from(&context, func3);
 853 |         println!("SVManipulationLibrary::manipulateLib3()\n{:?}", finder);
 854 |         let changes_found = finder.state_variables_have_been_manipulated();
 855 |         assert!(changes_found);
 856 |         assert_eq!(finder.manipulated_storage_pointers.len(), 2);
 857 |         assert!(finder.directly_manipulated_state_variables.is_empty());
 858 |     }
 859 | 
 860 |     #[test]
 861 | 
 862 |     fn test_no_struct_plus_fixed_array_assignment_example() {
 863 |         let context = load_solidity_source_unit(
 864 |             "../tests/contract-playground/src/StateVariablesManipulation.sol",
 865 |         );
 866 | 
 867 |         let contract = context.find_contract_by_name("NoStructPlusFixedArrayAssignmentExample");
 868 | 
 869 |         let func = contract.find_function_by_name("dontManipulateStateVariables");
 870 |         let func2 = contract.find_function_by_name("dontManipulateStateVariablesPart2");
 871 |         let func3 = contract.find_function_by_name("dontManipulateStateVariablesPart3");
 872 |         let func4 = contract.find_function_by_name("dontManipulateStateVariablesPart4");
 873 |         let func5 = contract.find_function_by_name("dontManipulateStateVariablesPart5");
 874 | 
 875 |         // Test dontManipulateStateVariables()
 876 |         let finder = ApproximateStorageChangeFinder::from(&context, func);
 877 |         println!(
 878 |             "NoStructPlusFixedArrayAssignmentExample::dontManipulateStateVariables()\n{:?}",
 879 |             finder
 880 |         );
 881 |         let no_changes_found = !finder.state_variables_have_been_manipulated();
 882 |         assert!(no_changes_found);
 883 |         assert!(finder.manipulated_storage_pointers.is_empty());
 884 |         assert!(finder.directly_manipulated_state_variables.is_empty());
 885 | 
 886 |         // Test dontManipulateStateVariablesPart2()
 887 |         let finder = ApproximateStorageChangeFinder::from(&context, func2);
 888 |         println!(
 889 |             "NoStructPlusFixedArrayAssignmentExample::dontManipulateStateVariablesPart2()\n{:?}",
 890 |             finder
 891 |         );
 892 |         let no_changes_found = !finder.state_variables_have_been_manipulated();
 893 |         assert!(no_changes_found);
 894 |         assert!(finder.manipulated_storage_pointers.is_empty());
 895 |         assert!(finder.directly_manipulated_state_variables.is_empty());
 896 | 
 897 |         // Test dontManipulateStateVariablesPart3()
 898 |         let finder = ApproximateStorageChangeFinder::from(&context, func3);
 899 |         println!(
 900 |             "NoStructPlusFixedArrayAssignmentExample::dontManipulateStateVariablesPart3()\n{:?}",
 901 |             finder
 902 |         );
 903 |         let no_changes_found = !finder.state_variables_have_been_manipulated();
 904 |         assert!(no_changes_found);
 905 |         assert!(finder.manipulated_storage_pointers.is_empty());
 906 |         assert!(finder.directly_manipulated_state_variables.is_empty());
 907 | 
 908 |         // Test dontManipulateStateVariablesPart4()
 909 |         let finder = ApproximateStorageChangeFinder::from(&context, func4);
 910 |         println!(
 911 |             "NoStructPlusFixedArrayAssignmentExample::dontManipulateStateVariablesPart4()\n{:?}",
 912 |             finder
 913 |         );
 914 |         let no_changes_found = !finder.state_variables_have_been_manipulated();
 915 |         assert!(no_changes_found);
 916 |         assert!(finder.manipulated_storage_pointers.is_empty());
 917 |         assert!(finder.directly_manipulated_state_variables.is_empty());
 918 | 
 919 |         // Test dontManipulateStateVariablesPart4()
 920 |         let finder = ApproximateStorageChangeFinder::from(&context, func5);
 921 |         println!(
 922 |             "NoStructPlusFixedArrayAssignmentExample::dontManipulateStateVariablesPart5()\n{:?}",
 923 |             finder
 924 |         );
 925 |         let no_changes_found = !finder.state_variables_have_been_manipulated();
 926 |         assert!(no_changes_found);
 927 |         assert!(finder.manipulated_storage_pointers.is_empty());
 928 |         assert!(finder.directly_manipulated_state_variables.is_empty());
 929 |     }
 930 | 
 931 |     #[test]
 932 | 
 933 |     fn test_dynamic_array_push_changes() {
 934 |         let context = load_solidity_source_unit(
 935 |             "../tests/contract-playground/src/StateVariablesManipulation.sol",
 936 |         );
 937 | 
 938 |         let contract = context.find_contract_by_name("DynamicArraysPushExample");
 939 | 
 940 |         let func = contract.find_function_by_name("manipulateDirectly");
 941 |         let func2 = contract.find_function_by_name("manipulateViaIndexAccess");
 942 |         let func3 = contract.find_function_by_name("manipulateViaMemberAccess");
 943 |         let func4 = contract.find_function_by_name("manipulateViaMemberAccess2");
 944 | 
 945 |         // Test manipulateDirectly()
 946 |         let finder = ApproximateStorageChangeFinder::from(&context, func);
 947 |         println!("DynamicArraysPushExample::manipulateDirectly()\n{:?}", finder);
 948 |         let changes_found = finder.state_variables_have_been_manipulated();
 949 |         assert!(changes_found);
 950 |         assert!(finder.manipulated_storage_pointers.is_empty());
 951 |         assert_eq!(finder.directly_manipulated_state_variables.len(), 1);
 952 | 
 953 |         // Test manipulateViaIndexAccess()
 954 |         let finder = ApproximateStorageChangeFinder::from(&context, func2);
 955 |         println!("DynamicArraysPushExample::manipulateViaIndexAccess()\n{:?}", finder);
 956 |         let changes_found = finder.state_variables_have_been_manipulated();
 957 |         assert!(changes_found);
 958 |         assert!(finder.manipulated_storage_pointers.is_empty());
 959 |         assert_eq!(finder.directly_manipulated_state_variables.len(), 3);
 960 | 
 961 |         // Test manipulateViaMemberAccess()
 962 |         let finder = ApproximateStorageChangeFinder::from(&context, func3);
 963 |         println!("DynamicArraysPushExample::manipulateViaMemberAccess()\n{:?}", finder);
 964 |         let changes_found = finder.state_variables_have_been_manipulated();
 965 |         assert!(changes_found);
 966 |         assert!(finder.manipulated_storage_pointers.is_empty());
 967 |         assert_eq!(finder.directly_manipulated_state_variables.len(), 1);
 968 | 
 969 |         // Test manipulateViaMemberAccess2()
 970 |         let finder = ApproximateStorageChangeFinder::from(&context, func4);
 971 |         println!("DynamicArraysPushExample::manipulateViaMemberAccess2()\n{:?}", finder);
 972 |         let changes_found = finder.state_variables_have_been_manipulated();
 973 |         assert!(changes_found);
 974 |         assert_eq!(finder.manipulated_storage_pointers.len(), 1); // we only want to capture p1
 975 |         assert!(finder.directly_manipulated_state_variables.is_empty());
 976 |     }
 977 | 
 978 |     #[test]
 979 | 
 980 |     fn test_dynamic_mappings_array_push_changes() {
 981 |         let context = load_solidity_source_unit(
 982 |             "../tests/contract-playground/src/StateVariablesManipulation.sol",
 983 |         );
 984 | 
 985 |         let contract = context.find_contract_by_name("DynamicMappingsArrayPushExample");
 986 |         let func = contract.find_function_by_name("add");
 987 | 
 988 |         // Test add()
 989 |         let finder = ApproximateStorageChangeFinder::from(&context, func);
 990 |         println!("DynamicMappingsArrayPushExample::add()\n{:?}", finder);
 991 |         let changes_found = finder.state_variables_have_been_manipulated();
 992 |         assert!(changes_found);
 993 |         assert_eq!(finder.directly_manipulated_state_variables.len(), 1);
 994 |         assert!(finder.manipulated_storage_pointers.is_empty());
 995 |     }
 996 | 
 997 |     #[test]
 998 | 
 999 |     fn test_fixed_size_arrays_deletion_example() {
1000 |         let context = load_solidity_source_unit(
1001 |             "../tests/contract-playground/src/StateVariablesManipulation.sol",
1002 |         );
1003 | 
1004 |         let contract = context.find_contract_by_name("FixedSizeArraysDeletionExample");
1005 |         let func = contract.find_function_by_name("manipulateDirectly");
1006 |         let func2 = contract.find_function_by_name("manipulateViaIndexAccess");
1007 | 
1008 |         // Test func()
1009 |         let finder = ApproximateStorageChangeFinder::from(&context, func);
1010 |         println!("FixedSizeArraysDeletionExample::manipulateDirectly()\n{:?}", finder);
1011 |         let changes_found = finder.state_variables_have_been_manipulated();
1012 |         assert!(changes_found);
1013 |         assert_eq!(finder.directly_manipulated_state_variables.len(), 1);
1014 |         assert!(finder.manipulated_storage_pointers.is_empty());
1015 | 
1016 |         // Test func2()
1017 |         let finder = ApproximateStorageChangeFinder::from(&context, func2);
1018 |         println!("FixedSizeArraysDeletionExample::manipulateViaIndexAccess()\n{:?}", finder);
1019 |         let changes_found = finder.state_variables_have_been_manipulated();
1020 |         assert!(changes_found);
1021 |         assert_eq!(finder.directly_manipulated_state_variables.len(), 2);
1022 |         assert!(finder.manipulated_storage_pointers.is_empty());
1023 |     }
1024 | }
1025 | 
```
Page 98/103FirstPrevNextLast