This is page 17 of 94. Use http://codebase.md/cyfrin/aderyn?lines=false&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
--------------------------------------------------------------------------------
/tests/hardhat-js-playground/artifacts/contracts/ExtendedInheritance.sol/ExtendedInheritance.json:
--------------------------------------------------------------------------------
```json
{
"_format": "hh-sol-artifact-1",
"contractName": "ExtendedInheritance",
"sourceName": "contracts/ExtendedInheritance.sol",
"abi": [
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint256",
"name": "something",
"type": "uint256"
}
],
"name": "Do",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint256",
"name": "somethingElse",
"type": "uint256"
}
],
"name": "DoSomethingElse",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "somethingElse",
"type": "uint256"
}
],
"name": "DoSomethingElseWithIndex",
"type": "event"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "somethingElse",
"type": "uint256"
}
],
"name": "doSomething",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "target",
"type": "address"
}
],
"name": "doSomethingElse",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint8",
"name": "v",
"type": "uint8"
},
{
"internalType": "bytes32",
"name": "r",
"type": "bytes32"
},
{
"internalType": "bytes32",
"name": "s",
"type": "bytes32"
},
{
"internalType": "bytes32",
"name": "theHash",
"type": "bytes32"
}
],
"name": "recoverThatThang",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "pure",
"type": "function"
}
],
"bytecode": "0x608060405234801561001057600080fd5b50610610806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80637277d9d214610046578063a5666fa214610062578063a6b206bf14610092575b600080fd5b610060600480360381019061005b91906102be565b6100ae565b005b61007c6004803603810190610077919061035a565b6101c6565b60405161008991906103d0565b60405180910390f35b6100ac60048036038101906100a79190610421565b610221565b005b60005b60038110156101c2578173ffffffffffffffffffffffffffffffffffffffff16816040516024016100e2919061045d565b6040516020818303038152906040527fa6b206bf000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161016c91906104e9565b600060405180830381855af49150503d80600081146101a7576040519150601f19603f3d011682016040523d82523d6000602084013e6101ac565b606091505b50505080806101ba9061052f565b9150506100b1565b5050565b6000600182868686604051600081526020016040526040516101eb9493929190610595565b6020604051602081039080840390855afa15801561020d573d6000803e3d6000fd5b505050602060405103519050949350505050565b7f33782d62d9804c35aa012275d93a348a1ce28d2558032fbf95b540356f7c900a81604051610250919061045d565b60405180910390a150565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061028b82610260565b9050919050565b61029b81610280565b81146102a657600080fd5b50565b6000813590506102b881610292565b92915050565b6000602082840312156102d4576102d361025b565b5b60006102e2848285016102a9565b91505092915050565b600060ff82169050919050565b610301816102eb565b811461030c57600080fd5b50565b60008135905061031e816102f8565b92915050565b6000819050919050565b61033781610324565b811461034257600080fd5b50565b6000813590506103548161032e565b92915050565b600080600080608085870312156103745761037361025b565b5b60006103828782880161030f565b945050602061039387828801610345565b93505060406103a487828801610345565b92505060606103b587828801610345565b91505092959194509250565b6103ca81610280565b82525050565b60006020820190506103e560008301846103c1565b92915050565b6000819050919050565b6103fe816103eb565b811461040957600080fd5b50565b60008135905061041b816103f5565b92915050565b6000602082840312156104375761043661025b565b5b60006104458482850161040c565b91505092915050565b610457816103eb565b82525050565b6000602082019050610472600083018461044e565b92915050565b600081519050919050565b600081905092915050565b60005b838110156104ac578082015181840152602081019050610491565b60008484015250505050565b60006104c382610478565b6104cd8185610483565b93506104dd81856020860161048e565b80840191505092915050565b60006104f582846104b8565b915081905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061053a826103eb565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361056c5761056b610500565b5b600182019050919050565b61058081610324565b82525050565b61058f816102eb565b82525050565b60006080820190506105aa6000830187610577565b6105b76020830186610586565b6105c46040830185610577565b6105d16060830184610577565b9594505050505056fea26469706673582212203fc91ff64ea071db5e7af5e9c193fde5f32a8464f9d926e3198d362290e18a9c64736f6c63430008140033",
"deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100415760003560e01c80637277d9d214610046578063a5666fa214610062578063a6b206bf14610092575b600080fd5b610060600480360381019061005b91906102be565b6100ae565b005b61007c6004803603810190610077919061035a565b6101c6565b60405161008991906103d0565b60405180910390f35b6100ac60048036038101906100a79190610421565b610221565b005b60005b60038110156101c2578173ffffffffffffffffffffffffffffffffffffffff16816040516024016100e2919061045d565b6040516020818303038152906040527fa6b206bf000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161016c91906104e9565b600060405180830381855af49150503d80600081146101a7576040519150601f19603f3d011682016040523d82523d6000602084013e6101ac565b606091505b50505080806101ba9061052f565b9150506100b1565b5050565b6000600182868686604051600081526020016040526040516101eb9493929190610595565b6020604051602081039080840390855afa15801561020d573d6000803e3d6000fd5b505050602060405103519050949350505050565b7f33782d62d9804c35aa012275d93a348a1ce28d2558032fbf95b540356f7c900a81604051610250919061045d565b60405180910390a150565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061028b82610260565b9050919050565b61029b81610280565b81146102a657600080fd5b50565b6000813590506102b881610292565b92915050565b6000602082840312156102d4576102d361025b565b5b60006102e2848285016102a9565b91505092915050565b600060ff82169050919050565b610301816102eb565b811461030c57600080fd5b50565b60008135905061031e816102f8565b92915050565b6000819050919050565b61033781610324565b811461034257600080fd5b50565b6000813590506103548161032e565b92915050565b600080600080608085870312156103745761037361025b565b5b60006103828782880161030f565b945050602061039387828801610345565b93505060406103a487828801610345565b92505060606103b587828801610345565b91505092959194509250565b6103ca81610280565b82525050565b60006020820190506103e560008301846103c1565b92915050565b6000819050919050565b6103fe816103eb565b811461040957600080fd5b50565b60008135905061041b816103f5565b92915050565b6000602082840312156104375761043661025b565b5b60006104458482850161040c565b91505092915050565b610457816103eb565b82525050565b6000602082019050610472600083018461044e565b92915050565b600081519050919050565b600081905092915050565b60005b838110156104ac578082015181840152602081019050610491565b60008484015250505050565b60006104c382610478565b6104cd8185610483565b93506104dd81856020860161048e565b80840191505092915050565b60006104f582846104b8565b915081905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061053a826103eb565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361056c5761056b610500565b5b600182019050919050565b61058081610324565b82525050565b61058f816102eb565b82525050565b60006080820190506105aa6000830187610577565b6105b76020830186610586565b6105c46040830185610577565b6105d16060830184610577565b9594505050505056fea26469706673582212203fc91ff64ea071db5e7af5e9c193fde5f32a8464f9d926e3198d362290e18a9c64736f6c63430008140033",
"linkReferences": {},
"deployedLinkReferences": {}
}
```
--------------------------------------------------------------------------------
/benchmarks/ecrecover/report/both/regression.svg:
--------------------------------------------------------------------------------
```
<svg width="960" height="540" viewBox="0 0 960 540" xmlns="http://www.w3.org/2000/svg">
<text x="480" y="32" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="16.129032258064516" opacity="1" fill="#000000">
ecrecover
</text>
<text x="27" y="263" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000" transform="rotate(270, 27, 263)">
Total sample time (ms)
</text>
<text x="510" y="513" dy="-0.5ex" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
Iterations (x 10^3)
</text>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="472" x2="87" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="173" y1="472" x2="173" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="259" y1="472" x2="259" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="345" y1="472" x2="345" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="431" y1="472" x2="431" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="518" y1="472" x2="518" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="604" y1="472" x2="604" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="690" y1="472" x2="690" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="776" y1="472" x2="776" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="863" y1="472" x2="863" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="472" x2="932" y2="472"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="433" x2="932" y2="433"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="393" x2="932" y2="393"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="353" x2="932" y2="353"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="314" x2="932" y2="314"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="274" x2="932" y2="274"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="234" x2="932" y2="234"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="195" x2="932" y2="195"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="155" x2="932" y2="155"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="115" x2="932" y2="115"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="76" x2="932" y2="76"/>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="86,53 86,472 "/>
<text x="77" y="472" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,472 86,472 "/>
<text x="77" y="433" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
10.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,433 86,433 "/>
<text x="77" y="393" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
20.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,393 86,393 "/>
<text x="77" y="353" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
30.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,353 86,353 "/>
<text x="77" y="314" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
40.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,314 86,314 "/>
<text x="77" y="274" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
50.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,274 86,274 "/>
<text x="77" y="234" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
60.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,234 86,234 "/>
<text x="77" y="195" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
70.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,195 86,195 "/>
<text x="77" y="155" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
80.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,155 86,155 "/>
<text x="77" y="115" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
90.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,115 86,115 "/>
<text x="77" y="76" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
100.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,76 86,76 "/>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="87,473 932,473 "/>
<text x="87" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="87,473 87,478 "/>
<text x="173" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
2
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="173,473 173,478 "/>
<text x="259" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
4
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="259,473 259,478 "/>
<text x="345" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
6
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="345,473 345,478 "/>
<text x="431" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
8
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="431,473 431,478 "/>
<text x="518" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
10
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="518,473 518,478 "/>
<text x="604" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
12
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="604,473 604,478 "/>
<text x="690" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
14
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="690,473 690,478 "/>
<text x="776" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
16
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="776,473 776,478 "/>
<text x="863" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
18
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="863,473 863,478 "/>
<polyline fill="none" opacity="1" stroke="#E31A1C" stroke-width="1" points="87,472 932,81 "/>
<polygon opacity="0.25" fill="#E31A1C" points="87,472 932,85 932,77 "/>
<polyline fill="none" opacity="1" stroke="#1F78B4" stroke-width="1" points="87,472 932,53 "/>
<polygon opacity="0.25" fill="#1F78B4" points="87,472 932,73 932,53 "/>
<text x="132" y="68" dy="0.76em" text-anchor="start" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
Base Sample
</text>
<text x="132" y="83" dy="0.76em" text-anchor="start" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
New Sample
</text>
<polyline fill="none" opacity="1" stroke="#E31A1C" stroke-width="2" points="102,73 122,73 "/>
<polyline fill="none" opacity="1" stroke="#1F78B4" stroke-width="2" points="102,88 122,88 "/>
</svg>
```
--------------------------------------------------------------------------------
/benchmarks/empty-block/report/both/regression.svg:
--------------------------------------------------------------------------------
```
<svg width="960" height="540" viewBox="0 0 960 540" xmlns="http://www.w3.org/2000/svg">
<text x="480" y="32" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="16.129032258064516" opacity="1" fill="#000000">
empty-block
</text>
<text x="27" y="263" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000" transform="rotate(270, 27, 263)">
Total sample time (ms)
</text>
<text x="510" y="513" dy="-0.5ex" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
Iterations (x 10^3)
</text>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="472" x2="87" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="175" y1="472" x2="175" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="264" y1="472" x2="264" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="353" y1="472" x2="353" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="442" y1="472" x2="442" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="531" y1="472" x2="531" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="620" y1="472" x2="620" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="709" y1="472" x2="709" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="798" y1="472" x2="798" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="887" y1="472" x2="887" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="472" x2="932" y2="472"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="433" x2="932" y2="433"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="394" x2="932" y2="394"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="354" x2="932" y2="354"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="315" x2="932" y2="315"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="276" x2="932" y2="276"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="236" x2="932" y2="236"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="197" x2="932" y2="197"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="158" x2="932" y2="158"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="118" x2="932" y2="118"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="79" x2="932" y2="79"/>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="86,53 86,472 "/>
<text x="77" y="472" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,472 86,472 "/>
<text x="77" y="433" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
10.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,433 86,433 "/>
<text x="77" y="394" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
20.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,394 86,394 "/>
<text x="77" y="354" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
30.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,354 86,354 "/>
<text x="77" y="315" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
40.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,315 86,315 "/>
<text x="77" y="276" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
50.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,276 86,276 "/>
<text x="77" y="236" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
60.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,236 86,236 "/>
<text x="77" y="197" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
70.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,197 86,197 "/>
<text x="77" y="158" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
80.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,158 86,158 "/>
<text x="77" y="118" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
90.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,118 86,118 "/>
<text x="77" y="79" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
100.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,79 86,79 "/>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="87,473 932,473 "/>
<text x="87" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="87,473 87,478 "/>
<text x="175" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.2
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="175,473 175,478 "/>
<text x="264" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.4
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="264,473 264,478 "/>
<text x="353" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.6
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="353,473 353,478 "/>
<text x="442" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.8
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="442,473 442,478 "/>
<text x="531" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
1
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="531,473 531,478 "/>
<text x="620" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
1.2
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="620,473 620,478 "/>
<text x="709" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
1.4
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="709,473 709,478 "/>
<text x="798" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
1.6
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="798,473 798,478 "/>
<text x="887" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
1.8
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="887,473 887,478 "/>
<polyline fill="none" opacity="1" stroke="#E31A1C" stroke-width="1" points="87,472 932,53 "/>
<polygon opacity="0.25" fill="#E31A1C" points="87,472 932,59 932,53 "/>
<polyline fill="none" opacity="1" stroke="#1F78B4" stroke-width="1" points="87,472 932,102 "/>
<polygon opacity="0.25" fill="#1F78B4" points="87,472 932,104 932,100 "/>
<text x="132" y="68" dy="0.76em" text-anchor="start" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
Base Sample
</text>
<text x="132" y="83" dy="0.76em" text-anchor="start" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
New Sample
</text>
<polyline fill="none" opacity="1" stroke="#E31A1C" stroke-width="2" points="102,73 122,73 "/>
<polyline fill="none" opacity="1" stroke="#1F78B4" stroke-width="2" points="102,88 122,88 "/>
</svg>
```
--------------------------------------------------------------------------------
/benchmarks/large-numeric-literal/report/both/regression.svg:
--------------------------------------------------------------------------------
```
<svg width="960" height="540" viewBox="0 0 960 540" xmlns="http://www.w3.org/2000/svg">
<text x="480" y="32" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="16.129032258064516" opacity="1" fill="#000000">
large-numeric-literal
</text>
<text x="27" y="263" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000" transform="rotate(270, 27, 263)">
Total sample time (ms)
</text>
<text x="510" y="513" dy="-0.5ex" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
Iterations (x 10^3)
</text>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="472" x2="87" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="180" y1="472" x2="180" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="274" y1="472" x2="274" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="368" y1="472" x2="368" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="462" y1="472" x2="462" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="556" y1="472" x2="556" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="650" y1="472" x2="650" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="744" y1="472" x2="744" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="838" y1="472" x2="838" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="932" y1="472" x2="932" y2="53"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="472" x2="932" y2="472"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="431" x2="932" y2="431"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="389" x2="932" y2="389"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="348" x2="932" y2="348"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="306" x2="932" y2="306"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="265" x2="932" y2="265"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="223" x2="932" y2="223"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="182" x2="932" y2="182"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="140" x2="932" y2="140"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="99" x2="932" y2="99"/>
<line opacity="0.2" stroke="#000000" stroke-width="1" x1="87" y1="57" x2="932" y2="57"/>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="86,53 86,472 "/>
<text x="77" y="472" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,472 86,472 "/>
<text x="77" y="431" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
10.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,431 86,431 "/>
<text x="77" y="389" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
20.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,389 86,389 "/>
<text x="77" y="348" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
30.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,348 86,348 "/>
<text x="77" y="306" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
40.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,306 86,306 "/>
<text x="77" y="265" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
50.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,265 86,265 "/>
<text x="77" y="223" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
60.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,223 86,223 "/>
<text x="77" y="182" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
70.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,182 86,182 "/>
<text x="77" y="140" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
80.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,140 86,140 "/>
<text x="77" y="99" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
90.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,99 86,99 "/>
<text x="77" y="57" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
100.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,57 86,57 "/>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="87,473 932,473 "/>
<text x="87" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="87,473 87,478 "/>
<text x="180" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.2
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="180,473 180,478 "/>
<text x="274" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.4
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="274,473 274,478 "/>
<text x="368" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.6
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="368,473 368,478 "/>
<text x="462" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.8
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="462,473 462,478 "/>
<text x="556" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
1
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="556,473 556,478 "/>
<text x="650" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
1.2
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="650,473 650,478 "/>
<text x="744" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
1.4
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="744,473 744,478 "/>
<text x="838" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
1.6
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="838,473 838,478 "/>
<text x="932" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
1.8
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="932,473 932,478 "/>
<polyline fill="none" opacity="1" stroke="#E31A1C" stroke-width="1" points="87,472 932,77 "/>
<polygon opacity="0.25" fill="#E31A1C" points="87,472 932,79 932,75 "/>
<polyline fill="none" opacity="1" stroke="#1F78B4" stroke-width="1" points="87,472 932,53 "/>
<polygon opacity="0.25" fill="#1F78B4" points="87,472 932,57 932,53 "/>
<text x="132" y="68" dy="0.76em" text-anchor="start" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
Base Sample
</text>
<text x="132" y="83" dy="0.76em" text-anchor="start" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
New Sample
</text>
<polyline fill="none" opacity="1" stroke="#E31A1C" stroke-width="2" points="102,73 122,73 "/>
<polyline fill="none" opacity="1" stroke="#1F78B4" stroke-width="2" points="102,88 122,88 "/>
</svg>
```
--------------------------------------------------------------------------------
/aderyn/src/lsp.rs:
--------------------------------------------------------------------------------
```rust
use log::{info, warn};
use notify_debouncer_full::notify::{Event, RecommendedWatcher, Result as NotifyResult};
use std::{collections::HashSet, path::PathBuf, sync::Arc, time::Duration};
use tokio::{
runtime::Builder,
sync::{Mutex, mpsc::Receiver},
};
use tower_lsp::{
Client, ClientSocket, LanguageServer, LspService, Server, jsonrpc::Result, lsp_types::*,
};
use aderyn_driver::driver::{self, Args};
use notify_debouncer_full::notify::{Config, RecursiveMode, Watcher};
#[derive(Debug)]
struct LanguageServerBackend {
client: Arc<Mutex<Client>>,
}
#[tower_lsp::async_trait]
impl LanguageServer for LanguageServerBackend {
async fn initialize(&self, params: InitializeParams) -> Result<InitializeResult> {
info!("TLSP initialize: {:?}", params.capabilities);
let code_editor = self.client.lock().await;
code_editor
.log_message(MessageType::INFO, "Aderyn LSP received an initialization request!")
.await;
Ok(InitializeResult {
capabilities: ServerCapabilities {
text_document_sync: Some(TextDocumentSyncCapability::Options(
TextDocumentSyncOptions {
open_close: Some(false),
change: None,
will_save: Some(false),
will_save_wait_until: Some(false),
save: None,
},
)),
..Default::default()
},
..Default::default()
})
}
async fn initialized(&self, params: InitializedParams) {
info!("TLSP initialized: {:?}", params);
let code_editor = self.client.lock().await;
code_editor
.log_message(
MessageType::INFO,
"Aderyn LSP has been notified that the edtior's LSP client is initialized.",
)
.await;
}
async fn shutdown(&self) -> Result<()> {
info!("TLSP shutdown");
let code_editor = self.client.lock().await;
code_editor.log_message(MessageType::INFO, "Aderyn LSP has been shutdown").await;
Ok(())
}
}
pub fn spin_up_language_server(args: Args) {
// Setup the logging file
// NOTE: Uncomment this for debugging purposes
//_ = log_to_file(
// "/Users/tilakmadichetti/Documents/OpenSource/my-first-vscode-lsp/lsp_server.log",
// LevelFilter::Info,
//);
// Create tokio runtime to run futures
let async_runtime = Builder::new_multi_thread()
.worker_threads(20)
.thread_name("aderyn-async-runtime")
.thread_stack_size(3 * 1024 * 1024)
.enable_all()
.build()
.expect("unable to start async runtime");
// Block on this function
async_runtime.block_on(async {
// Channel to communicate file system changes (triggered when files are added, removed, or
// changed)
let (tx_file_change_event, rx_file_change_event) = tokio::sync::mpsc::channel(10);
// Create the async watcher
let mut file_system_watcher = RecommendedWatcher::new(
move |res| {
tx_file_change_event
.blocking_send(res)
.expect("unable to notify file rx_file_change_event receiver");
},
Config::default()
.with_poll_interval(Duration::from_millis(20))
.with_compare_contents(false),
)
.expect("couldn't create file system watcher");
// Watch for file changes
file_system_watcher
.watch(
PathBuf::from(args.input_config.root.clone()).as_path(),
RecursiveMode::Recursive,
)
.expect("unable to watch for file changes");
// Most editor's LSP clients communicate through stdout/stdin channels. Theefore use
// a log file to send debugging statements. Please note EVERY BYTE FLOWING IN
// STDOUT/STDIN MUST FOLLOW THE LSP PROTOCOL.
let stdin = tokio::io::stdin();
let stdout = tokio::io::stdout();
let (service, socket) =
create_lsp_service_and_react_to_file_event(rx_file_change_event, args);
// This loop will run until the client issues a shutdown request to our LSP server
Server::new(stdin, stdout, socket).serve(service).await;
});
}
/// Perform 2 things in parallel
/// 1. React to file changes by regenerating diagnostics
/// 2. Talk to the LSP client and push only the required diagnostics
fn create_lsp_service_and_react_to_file_event(
rx_file_change_event: Receiver<NotifyResult<Event>>,
args: Args,
) -> (LspService<LanguageServerBackend>, ClientSocket) {
let (service, socket) = LspService::new(move |client| {
// Guard the receiver and the client so we can send them across threads
let guarded_client = Arc::new(Mutex::new(client));
let guarded_file_change_event_receiver = Arc::new(Mutex::new(rx_file_change_event));
// Clone the guarded client (but it doesn't actually clone, it just clones the reference).
// Do not use `.clone()` but rather `Arc::clone()` to make this clear.
let guarded_client_clone = Arc::clone(&guarded_client);
let guarded_file_change_event_receiver_clone =
Arc::clone(&guarded_file_change_event_receiver);
// Create a guard that keeps track of all the files to which diagnostics were sent in the
// last run. This is because LSP spec expects to manually push an empty vec![] to clean up
// stale diagnostics. So we every time, we generate a report, we should check to see if
// there has been a file left out that previously had errors, if so, then clean it.
let seen_file_uris: Arc<Mutex<HashSet<Url>>> = Arc::new(Mutex::new(HashSet::new()));
async fn generate_diagnostics_and_publish(
args: &Args,
guarded_client: Arc<Mutex<Client>>,
seen_file_uris: Arc<Mutex<HashSet<Url>>>,
) {
// Generate diagnostics due to this change
let guarded_report_results = driver::fetch_report_for_lsp(args.clone());
// Extract report from the mutex
let mut diagnostics_mutex = guarded_report_results.lock().await;
let Some(diagnostics_report) = &mut *diagnostics_mutex else {
warn!("no diagnostics report generated");
return;
};
info!("sending diagnostics to client {:?}", &diagnostics_report.diagnostics);
let client_mutex = guarded_client.lock().await;
for (file_uri, file_diagnostics) in &diagnostics_report.diagnostics {
client_mutex
.publish_diagnostics(file_uri.clone(), file_diagnostics.to_vec(), None)
.await;
}
// Clear out the diagnostics for file which had reported errors before
let current_run_file_uris =
diagnostics_report.diagnostics.keys().cloned().collect::<HashSet<_>>();
let mut seen_file_uris_mutex = seen_file_uris.lock().await;
let seen_file_uris = &mut *seen_file_uris_mutex;
for seen_file_uri in seen_file_uris.iter() {
if !¤t_run_file_uris.contains(seen_file_uri) {
// Clear the diagnostics for this seen file uri
// It had errors in the past, but not any more
client_mutex.publish_diagnostics(seen_file_uri.clone(), vec![], None).await;
}
}
// Now, update the seen_files with files reported in the current run
for current_run_file_uri in current_run_file_uris {
seen_file_uris.insert(current_run_file_uri);
}
}
tokio::spawn(async move {
// For the first time, run it automatically
let new_guarded_clone = Arc::clone(&guarded_client);
let seen_files_uris_clone = Arc::clone(&seen_file_uris);
generate_diagnostics_and_publish(&args, new_guarded_clone, seen_files_uris_clone).await;
// After that, run it only when you receive file change events from the system
let mut rxer = guarded_file_change_event_receiver_clone.lock().await;
while let Some(rxer_change) = rxer.recv().await {
if rxer_change.is_ok() {
info!("rxer change detected");
let new_guarded_clone = Arc::clone(&guarded_client);
let seen_files_uris_clone = Arc::clone(&seen_file_uris);
generate_diagnostics_and_publish(
&args,
new_guarded_clone,
seen_files_uris_clone,
)
.await;
} else {
warn!("rxer change errored!");
}
}
});
LanguageServerBackend { client: guarded_client_clone }
});
(service, socket)
}
```
--------------------------------------------------------------------------------
/aderyn_core/src/ast/impls/own/utils.rs:
--------------------------------------------------------------------------------
```rust
use crate::{ast::*, context::browser::is_extcallish};
impl FunctionDefinition {
/// The kind of function this node defines.
#[inline]
pub fn kind(&self) -> &FunctionKind {
if let Some(kind) = &self.kind {
kind
} else if self.is_constructor {
&FunctionKind::Constructor
} else {
&FunctionKind::Function
}
}
/// The state mutability of the function.
///
/// Note: Before Solidity 0.5.x, this is an approximation, as there was no distinction between
/// `view` and `pure`.
#[inline]
pub fn state_mutability(&self) -> &StateMutability {
if let Some(state_mutability) = &self.state_mutability {
state_mutability
} else if self.is_declared_const {
&StateMutability::View
} else if self.is_payable {
&StateMutability::Payable
} else {
&StateMutability::NonPayable
}
}
/// HACK
/// Internal functions don't have function selectors, because it can have parameters like
/// storage pointers. In order to identify internal functions that override other internal
/// functions we must be able to pick a combination of type strings and func names to do the
/// same.
///
/// TODO: Find a better way
pub fn selectorish(&self) -> String {
let func_name = self.name.to_string();
let mut t = String::new();
for param in self.parameters.parameters.iter() {
if let Some(ts) = param.type_descriptions.type_string.as_ref() {
t.push_str(ts);
}
t.push('!');
if let Some(ti) = param.type_descriptions.type_identifier.as_ref() {
t.push_str(ti);
}
t.push('@');
}
func_name + ":" + &t
}
}
impl ModifierDefinition {
/// HACK
/// Internal functions don't have function selectors, because it can have parameters like
/// storage pointers. In order to identify internal functions that override other internal
/// functions we must be able to pick a combination of type strings and func names to do the
/// same.
///
/// TODO: Find a better way
pub fn selectorish(&self) -> String {
let func_name = self.name.to_string();
let mut t = String::new();
for param in self.parameters.parameters.iter() {
if let Some(ts) = param.type_descriptions.type_string.as_ref() {
t.push_str(ts);
}
t.push('!');
if let Some(ti) = param.type_descriptions.type_identifier.as_ref() {
t.push_str(ti);
}
t.push('@');
}
func_name + ":" + &t
}
}
impl FunctionCall {
/// DO NOT USE
/// It doesn't work as expected. This was more so crafted for one specific detector and code
/// needs to be migrated.
pub fn is_extcallish(&self) -> bool {
is_extcallish(self.into())
}
/// Internal call made to -
/// * Internal Library function
/// * Public/Private/Internal contract function
///
/// Also see [`FunctionCall::suspected_target_function`]
#[inline]
pub fn is_internal_call(&self) -> Option<bool> {
if self.kind != FunctionCallKind::FunctionCall {
return Some(false);
}
// The most common forms of expressions when making a function call is
// 1) xyz()
// 2) A.xyz() where A is super or any parent class or library name or a something on which
// library is being used for. (using lib for uint8) .... 6.xyz()
match self.expression.as_ref() {
Expression::Identifier(Identifier {
type_descriptions: TypeDescriptions { type_identifier: Some(ty_ident), .. },
..
})
| Expression::MemberAccess(MemberAccess {
type_descriptions: TypeDescriptions { type_identifier: Some(ty_ident), .. },
..
}) => Some(ty_ident.starts_with("t_function_internal")),
_ => None, // TODO: Exhaust these enums
}
}
}
impl FunctionCallOptions {
pub fn is_extcallish(&self) -> bool {
is_extcallish(self.into())
}
}
impl VariableDeclaration {
/// Returns the mutability of the variable that was declared.
///
/// This is a helper to check variable mutability across Solidity versions.
#[inline]
pub fn mutability(&self) -> Option<&Mutability> {
if let Some(mutability) = &self.mutability {
Some(mutability)
} else if self.constant {
Some(&Mutability::Constant)
} else if self.state_variable {
Some(&Mutability::Mutable)
} else {
None
}
}
}
impl ContractDefinition {
#[inline]
pub fn function_definitions(&self) -> Vec<&FunctionDefinition> {
self.nodes
.iter()
.filter_map(|node| {
if let ContractDefinitionNode::FunctionDefinition(function_definition) = node {
Some(function_definition)
} else {
None
}
})
.collect()
}
#[inline]
pub fn modifier_definitions(&self) -> Vec<&ModifierDefinition> {
self.nodes
.iter()
.filter_map(|node| {
if let ContractDefinitionNode::ModifierDefinition(modifier_definition) = node {
Some(modifier_definition)
} else {
None
}
})
.collect()
}
pub fn top_level_variables(&self) -> Vec<&VariableDeclaration> {
self.nodes
.iter()
.filter_map(|node| {
if let ContractDefinitionNode::VariableDeclaration(modifier_definition) = node {
Some(modifier_definition)
} else {
None
}
})
.collect()
}
#[inline(always)]
pub fn is_deployable_contract(&self) -> bool {
self.kind == ContractKind::Contract && !self.is_abstract
}
}
impl IdentifierOrIdentifierPath {
#[inline]
pub fn name(&self) -> String {
match self {
IdentifierOrIdentifierPath::Identifier(identifier) => identifier.name.clone(),
IdentifierOrIdentifierPath::IdentifierPath(identifier_path) => {
identifier_path.name.clone()
}
}
}
#[inline]
pub fn referenced_declaration(&self) -> Option<NodeID> {
match self {
IdentifierOrIdentifierPath::Identifier(identifier) => identifier.referenced_declaration,
IdentifierOrIdentifierPath::IdentifierPath(identifier_path) => {
Some(identifier_path.referenced_declaration)
}
}
}
}
impl UserDefinedTypeNameOrIdentifierPath {
#[inline]
pub fn name(&self) -> Option<String> {
match self {
UserDefinedTypeNameOrIdentifierPath::UserDefinedTypeName(node) => node.name.clone(),
UserDefinedTypeNameOrIdentifierPath::IdentifierPath(node) => Some(node.name.clone()),
}
}
}
impl Expression {
#[inline]
pub fn type_descriptions(&self) -> Option<&TypeDescriptions> {
match self {
Expression::Literal(Literal { type_descriptions, .. }) => Some(type_descriptions),
Expression::Identifier(Identifier { type_descriptions, .. }) => Some(type_descriptions),
Expression::UnaryOperation(UnaryOperation { type_descriptions, .. }) => {
Some(type_descriptions)
}
Expression::BinaryOperation(BinaryOperation { type_descriptions, .. }) => {
Some(type_descriptions)
}
Expression::Conditional(Conditional { type_descriptions, .. }) => {
Some(type_descriptions)
}
Expression::Assignment(Assignment { type_descriptions, .. }) => Some(type_descriptions),
Expression::FunctionCall(FunctionCall { type_descriptions, .. }) => {
Some(type_descriptions)
}
Expression::FunctionCallOptions(FunctionCallOptions { type_descriptions, .. }) => {
Some(type_descriptions)
}
Expression::IndexAccess(IndexAccess { type_descriptions, .. }) => {
Some(type_descriptions)
}
Expression::IndexRangeAccess(IndexRangeAccess { type_descriptions, .. }) => {
Some(type_descriptions)
}
Expression::MemberAccess(MemberAccess { type_descriptions, .. }) => {
Some(type_descriptions)
}
Expression::ElementaryTypeNameExpression(ElementaryTypeNameExpression {
type_descriptions,
..
}) => Some(type_descriptions),
Expression::TupleExpression(TupleExpression { type_descriptions, .. }) => {
Some(type_descriptions)
}
Expression::NewExpression(NewExpression { type_descriptions, .. }) => {
Some(type_descriptions)
}
}
}
}
```
--------------------------------------------------------------------------------
/aderyn_core/src/visitor/workspace_visitor.rs:
--------------------------------------------------------------------------------
```rust
use super::{
ast_visitor::ASTConstVisitor,
macros::generate_visit_methods_for_workspace_context_with_insert_node,
};
use crate::{
ast::*,
context::workspace::{NodeContext, WorkspaceContext},
};
use eyre::Result;
impl ASTConstVisitor for WorkspaceContext {
fn visit_contract_definition(&mut self, node: &ContractDefinition) -> Result<bool> {
self.nodes.insert(node.id, ASTNode::ContractDefinition(node.clone()));
self.contract_definitions_context.insert(
node.clone(),
NodeContext {
source_unit_id: self.last_source_unit_id,
contract_definition_id: self.last_contract_definition_id,
function_definition_id: self.last_function_definition_id,
modifier_definition_id: self.last_modifier_definition_id,
},
);
self.last_contract_definition_id = Some(node.id);
Ok(true)
}
fn end_visit_contract_definition(&mut self, _: &ContractDefinition) -> Result<()> {
self.last_contract_definition_id = None;
Ok(())
}
fn visit_function_definition(&mut self, node: &FunctionDefinition) -> Result<bool> {
self.nodes.insert(node.id, ASTNode::FunctionDefinition(node.clone()));
self.function_definitions_context.insert(
node.clone(),
NodeContext {
source_unit_id: self.last_source_unit_id,
contract_definition_id: self.last_contract_definition_id,
function_definition_id: self.last_function_definition_id,
modifier_definition_id: self.last_modifier_definition_id,
},
);
self.last_function_definition_id = Some(node.id);
Ok(true)
}
fn end_visit_function_definition(&mut self, _: &FunctionDefinition) -> Result<()> {
self.last_function_definition_id = None;
Ok(())
}
fn visit_modifier_definition(&mut self, node: &ModifierDefinition) -> Result<bool> {
self.nodes.insert(node.id, ASTNode::ModifierDefinition(node.clone()));
self.modifier_definitions_context.insert(
node.clone(),
NodeContext {
source_unit_id: self.last_source_unit_id,
contract_definition_id: self.last_contract_definition_id,
function_definition_id: self.last_function_definition_id,
modifier_definition_id: self.last_modifier_definition_id,
},
);
self.last_modifier_definition_id = Some(node.id);
Ok(true)
}
fn end_visit_modifier_definition(&mut self, _: &ModifierDefinition) -> Result<()> {
self.last_modifier_definition_id = None;
Ok(())
}
fn visit_source_unit(&mut self, node: &SourceUnit) -> Result<bool> {
self.nodes.insert(node.id, ASTNode::SourceUnit(node.clone()));
self.source_units_context.push(node.clone());
self.last_source_unit_id = node.id;
Ok(true)
}
fn visit_yul_function_call(&mut self, node: &YulFunctionCall) -> Result<bool> {
self.yul_function_calls_context.insert(
node.clone(),
NodeContext {
source_unit_id: self.last_source_unit_id,
contract_definition_id: self.last_contract_definition_id,
function_definition_id: self.last_function_definition_id,
modifier_definition_id: self.last_modifier_definition_id,
},
);
Ok(true)
}
fn visit_yul_identifier(&mut self, node: &YulIdentifier) -> Result<bool> {
// No node ID in Yul
self.yul_identifiers_context.insert(
node.clone(),
NodeContext {
source_unit_id: self.last_source_unit_id,
contract_definition_id: self.last_contract_definition_id,
function_definition_id: self.last_function_definition_id,
modifier_definition_id: self.last_modifier_definition_id,
},
);
Ok(true)
}
fn visit_yul_assignment(&mut self, node: &YulAssignment) -> Result<bool> {
self.yul_assignments_context.insert(
node.clone(),
NodeContext {
source_unit_id: self.last_source_unit_id,
contract_definition_id: self.last_contract_definition_id,
function_definition_id: self.last_function_definition_id,
modifier_definition_id: self.last_modifier_definition_id,
},
);
Ok(true)
}
// Read the following like follows -
generate_visit_methods_for_workspace_context_with_insert_node! {
// Explanation for the 1st one : Create a method called `visit_assignment` that takes in `Assignment` as parameter and puts it inside `assignments_context`
visit_assignment | Assignment => assignments_context |,
visit_binary_operation | BinaryOperation => binary_operations_context |,
visit_block | Block => blocks_context |,
visit_conditional | Conditional => conditionals_context |,
visit_elementary_type_name_expression | ElementaryTypeNameExpression => elementary_type_name_expressions_context |,
visit_enum_definition | EnumDefinition => enum_definitions_context |,
visit_enum_value | EnumValue => enum_values_context |,
visit_event_definition | EventDefinition => event_definitions_context |,
visit_error_definition | ErrorDefinition => error_definitions_context |,
visit_function_call | FunctionCall => function_calls_context |,
visit_function_call_options | FunctionCallOptions => function_call_options_context |,
visit_for_statement | ForStatement => for_statements_context |,
visit_identifier | Identifier => identifiers_context |,
visit_identifier_path | IdentifierPath => identifier_paths_context |,
visit_if_statement | IfStatement => if_statements_context |,
visit_import_directive | ImportDirective => import_directives_context |,
visit_index_access | IndexAccess => index_accesses_context |,
visit_index_range_access | IndexRangeAccess => index_range_accesses_context |,
visit_inheritance_specifier | InheritanceSpecifier => inheritance_specifiers_context |,
visit_inline_assembly | InlineAssembly => inline_assemblies_context |,
visit_literal | Literal => literals_context |,
visit_member_access | MemberAccess => member_accesses_context |,
visit_new_expression | NewExpression => new_expressions_context |,
visit_modifier_invocation | ModifierInvocation => modifier_invocations_context |,
visit_override_specifier | OverrideSpecifier => override_specifiers_context |,
visit_parameter_list | ParameterList => parameter_lists_context |,
visit_pragma_directive | PragmaDirective => pragma_directives_context |,
visit_return | Return => returns_context |,
visit_struct_definition | StructDefinition => struct_definitions_context |,
visit_structured_documentation | StructuredDocumentation => structured_documentations_context |,
visit_tuple_expression | TupleExpression => tuple_expressions_context |,
visit_unary_operation | UnaryOperation => unary_operations_context |,
visit_unchecked_block | UncheckedBlock => unchecked_blocks_context |,
visit_user_defined_value_type_definition | UserDefinedValueTypeDefinition => user_defined_value_type_definitions_context |,
visit_using_for_directive | UsingForDirective => using_for_directives_context |,
visit_variable_declaration | VariableDeclaration => variable_declarations_context |,
visit_variable_declaration_statement | VariableDeclarationStatement => variable_declaration_statements_context |,
visit_while_statement | WhileStatement => while_statements_context |,
visit_do_while_statement | DoWhileStatement => do_while_statements_context |,
visit_break_statement | Break => break_statements_context |,
visit_continue_statement | Continue => continue_statements_context |,
visit_placeholder_statement | PlaceholderStatement => placeholder_statements_context |,
visit_array_type_name | ArrayTypeName => array_type_names_context |,
visit_mapping | Mapping => mappings_context |,
visit_try_statement | TryStatement => try_statements_context |,
visit_try_catch_clause | TryCatchClause => try_catch_clauses_context |,
visit_user_defined_type_name | UserDefinedTypeName => user_defined_type_names_context |,
visit_expression_statement | ExpressionStatement => expression_statements_context |,
visit_revert_statement | RevertStatement => revert_statements_context |,
visit_emit_statement | EmitStatement => emit_statements_context |,
visit_elementary_type_name | ElementaryTypeName => elementary_type_names_context |,
visit_function_type_name | FunctionTypeName => function_type_names_context |,
}
fn visit_immediate_children(
&mut self,
node_id: NodeID,
node_children_ids: Vec<NodeID>,
) -> Result<()> {
for id in node_children_ids {
self.parent_link.insert(id, node_id);
}
Ok(())
}
}
```
--------------------------------------------------------------------------------
/aderyn_core/src/detect/low/state_no_address_check.rs:
--------------------------------------------------------------------------------
```rust
use std::{
collections::{BTreeMap, HashMap, HashSet},
error::Error,
};
use crate::{
ast::{Assignment, BinaryOperation, Expression, Mutability, NodeID, VariableDeclaration},
capture,
context::{
browser::{ExtractAssignments, ExtractBinaryOperations, ExtractIdentifiers},
workspace::WorkspaceContext,
},
detect::detector::{IssueDetector, IssueDetectorNamePool, IssueSeverity},
};
use eyre::Result;
#[derive(Default)]
pub struct StateNoAddressCheckDetector {
// All the state variables, set at the beginning of the detect Function
mutable_address_state_variables: HashMap<i64, VariableDeclaration>,
// Keys are: [0] source file name, [1] line number, [2] character location of node.
// Do not add items manually, use `capture!` to add nodes to this BTreeMap.
found_instances: BTreeMap<(String, usize, String), NodeID>,
}
impl IssueDetector for StateNoAddressCheckDetector {
fn detect(&mut self, context: &WorkspaceContext) -> Result<bool, Box<dyn Error>> {
// Get all address state variables
self.mutable_address_state_variables = context
.variable_declarations()
.iter()
.filter_map(|&var_decl| {
if !var_decl.constant
&& matches!(var_decl.mutability(), Some(Mutability::Mutable))
&& var_decl.state_variable
&& (var_decl.type_descriptions.type_string.as_deref().unwrap_or("")
== "address"
|| var_decl
.type_descriptions
.type_string
.as_deref()
.unwrap_or("")
.contains("contract "))
{
Some((var_decl.id, (*var_decl).clone())) // Deref and clone the
// VariableDeclaration.
} else {
None
}
})
.collect();
// Get all Function definitions
for function_definition in context.function_definitions() {
// Get all the binary checks inside the Function
let binary_operations: Vec<BinaryOperation> =
ExtractBinaryOperations::from(function_definition)
.extracted
.into_iter()
.filter(|x| x.operator == "==" || x.operator == "!=")
.collect();
// Filter the binary checks and extract all node ids into a vector
let mut identifier_reference_declaration_ids_in_binary_checks = HashSet::new();
for x in binary_operations {
let l = x.left_expression.as_ref();
if let Expression::Identifier(left_identifier) = l {
if let Some(reference_id) = left_identifier.referenced_declaration {
identifier_reference_declaration_ids_in_binary_checks.insert(reference_id);
}
} else {
ExtractIdentifiers::from(l)
.extracted
.into_iter()
.filter_map(|f| f.referenced_declaration)
.for_each(|f| {
identifier_reference_declaration_ids_in_binary_checks.insert(f);
});
}
let r = x.right_expression.as_ref();
if let Expression::Identifier(right_identifier) = r {
if let Some(reference_id) = right_identifier.referenced_declaration {
identifier_reference_declaration_ids_in_binary_checks.insert(reference_id);
}
} else {
ExtractIdentifiers::from(r)
.extracted
.into_iter()
.filter_map(|f| f.referenced_declaration)
.for_each(|f| {
identifier_reference_declaration_ids_in_binary_checks.insert(f);
});
}
}
// Get all the assignments where the left hand side is a mutable address state variable
let assignments: Vec<Assignment> = ExtractAssignments::from(function_definition)
.extracted
.into_iter()
.filter(|x| {
let left_hand_side = x.left_hand_side.as_ref();
if let Expression::Identifier(left_identifier) = left_hand_side {
left_identifier.referenced_declaration.is_some_and(|reference_id| {
self.mutable_address_state_variables.contains_key(&reference_id)
})
} else {
let left_identifiers = ExtractIdentifiers::from(left_hand_side).extracted;
left_identifiers.into_iter().any(|identifier| {
identifier.referenced_declaration.is_some_and(|reference_id| {
self.mutable_address_state_variables.contains_key(&reference_id)
})
})
}
})
.collect();
// For each assignment, if the right hand side is in the
// identifier_reference_declaration_ids_in_binary_checks and is also in the
// Function.parameters, then add the assignment to the found_instances
for assignment in assignments {
if let Expression::Identifier(right_identifier) = &*assignment.right_hand_side {
if let Some(reference_id) = right_identifier.referenced_declaration
&& !identifier_reference_declaration_ids_in_binary_checks
.contains(&reference_id)
&& function_definition
.parameters
.parameters
.iter()
.any(|x| x.id == reference_id)
{
capture!(self, context, assignment);
}
} else {
let right_identifiers = ExtractIdentifiers::from(&*assignment.right_hand_side);
for right_identifier in right_identifiers.extracted {
if let Some(reference_id) = right_identifier.referenced_declaration
&& !identifier_reference_declaration_ids_in_binary_checks
.contains(&reference_id)
&& function_definition
.parameters
.parameters
.iter()
.any(|x| x.id == reference_id)
{
capture!(self, context, assignment);
}
}
}
}
}
Ok(!self.found_instances.is_empty())
}
fn title(&self) -> String {
String::from("Address State Variable Set Without Checks")
}
fn description(&self) -> String {
String::from("Check for `address(0)` when assigning values to address state variables.")
}
fn severity(&self) -> IssueSeverity {
IssueSeverity::Low
}
fn instances(&self) -> BTreeMap<(String, usize, String), NodeID> {
self.found_instances.clone()
}
fn name(&self) -> String {
format!("{}", IssueDetectorNamePool::StateNoAddressCheck)
}
}
#[cfg(test)]
mod zero_address_check_tests {
use crate::{
ast::NodeType,
context::{browser::GetClosestAncestorOfTypeX, workspace::ASTNode},
detect::{detector::IssueDetector, low::StateNoAddressCheckDetector},
};
#[test]
fn test_zero_address_check_using_mapping_with_address_in_it() {
let context = crate::detect::test_utils::load_solidity_source_unit(
"../tests/contract-playground/src/TestERC20.sol",
);
let mut detector = StateNoAddressCheckDetector::default();
let found = detector.detect(&context).unwrap();
// assert that nothing was found
assert!(!found);
}
#[test]
fn test_zero_address_check_detector_by_loading_contract_directly() {
let context = crate::detect::test_utils::load_solidity_source_unit(
"../tests/contract-playground/src/ZeroAddressCheck.sol",
);
let mut detector = StateNoAddressCheckDetector::default();
let found = detector.detect(&context).unwrap();
assert!(found);
assert_eq!(detector.instances().len(), 3);
for node_id in detector.instances().values() {
if let ASTNode::Assignment(assignment) = context.nodes.get(node_id).unwrap() {
if let ASTNode::FunctionDefinition(function) = assignment
.closest_ancestor_of_type(&context, NodeType::FunctionDefinition)
.unwrap()
{
assert!(function.name.contains("bad"));
} else {
panic!()
}
} else {
panic!()
}
}
}
}
```
--------------------------------------------------------------------------------
/aderyn_core/src/context/graph/callgraph/visit.rs:
--------------------------------------------------------------------------------
```rust
#![allow(clippy::large_enum_variant)]
#![allow(clippy::result_large_err)]
use std::collections::HashSet;
use crate::{
ast::{NodeID, NodeType},
context::{
graph::RawCallGraph,
workspace::{ASTNode, WorkspaceContext},
},
};
use super::*;
impl CallGraphConsumer {
/// Responsible for informing the trackers.
/// First, we visit the entry points. Then, we derive the subgraph from the
/// [`WorkspaceCallGraph`] which consists of all the nodes that can be reached by traversing
/// the edges starting from the surface points.
pub(super) fn _accept<T>(
&self,
context: &WorkspaceContext,
visitor: &mut T,
) -> super::Result<()>
where
T: CallGraphVisitor,
{
let callgraphs = context.callgraphs.as_ref().expect("callgraphs not attached to context");
let inward_callgraph = {
if self.is_legacy() {
context
.inward_callgraph
.as_ref()
.ok_or(super::Error::InwardCallgraphNotAvailable)?
.raw_callgraph
.clone()
} else {
callgraphs
.inward_callgraphs
.get(&self.base_contract.expect("base contract not set"))
.ok_or(super::Error::InwardCallgraphNotAvailable)?
.clone()
}
};
let outward_callgraph = {
if self.is_legacy() {
context
.outward_callgraph
.as_ref()
.ok_or(super::Error::OutwardCallgraphNotAvailable)?
.raw_callgraph
.clone()
} else {
callgraphs
.outward_callgraphs
.get(&self.base_contract.expect("base contract not set"))
.ok_or(super::Error::OutwardCallgraphNotAvailable)?
.clone()
}
};
// Visit entry point nodes (so that trackers can track the state across all code regions in
// 1 place)
for entry_point_id in &self.entry_points {
self.make_entry_point_visit_call(context, *entry_point_id, visitor)?;
}
// Keep track of visited node IDs during DFS from surface nodes
let mut visited_inward = HashSet::new();
let mut visited_outward = HashSet::new();
let mut visited_outward_side_effects = HashSet::new();
// Now decide, which points to visit outward or inward
if self.direction == CallGraphDirection::BothWays
|| self.direction == CallGraphDirection::Inward
{
// Visit the subgraph starting from surface points
for surface_point_id in &self.inward_surface_points {
self.dfs_and_visit_subgraph(
*surface_point_id,
&mut visited_inward,
context,
&inward_callgraph,
visitor,
CurrentDFSVector::Inward,
None,
)?;
}
}
if self.direction == CallGraphDirection::BothWays
|| self.direction == CallGraphDirection::Outward
{
// Visit the subgraph starting from surface points
for surface_point_id in &self.outward_surface_points {
self.dfs_and_visit_subgraph(
*surface_point_id,
&mut visited_outward,
context,
&outward_callgraph,
visitor,
CurrentDFSVector::Outward,
None,
)?;
}
}
// Collect already visited nodes so that we don't repeat visit calls on them
// while traversing through side effect nodes.
let mut blacklisted = HashSet::new();
blacklisted.extend(visited_inward.iter());
blacklisted.extend(visited_outward.iter());
blacklisted.extend(self.entry_points.iter());
if self.direction == CallGraphDirection::BothWays {
// Visit the subgraph from the outward points (go inward in inward graph)
// but do not re-visit the outward nodes or the inward nodes again
for surface_point_id in &visited_outward {
self.dfs_and_visit_subgraph(
*surface_point_id,
&mut visited_outward_side_effects,
context,
&inward_callgraph,
visitor,
CurrentDFSVector::OutwardSideEffect,
Some(&blacklisted),
)?;
}
}
Ok(())
}
#[allow(clippy::too_many_arguments)]
pub(super) fn dfs_and_visit_subgraph<T>(
&self,
node_id: NodeID,
visited: &mut HashSet<NodeID>,
context: &WorkspaceContext,
callgraph: &RawCallGraph,
visitor: &mut T,
current_investigation_direction: CurrentDFSVector,
blacklist: Option<&HashSet<NodeID>>,
) -> super::Result<()>
where
T: CallGraphVisitor,
{
if visited.contains(&node_id) {
return Ok(());
}
visited.insert(node_id);
if let Some(blacklist) = blacklist {
if !blacklist.contains(&node_id) {
self.make_relevant_visit_call(
context,
node_id,
visitor,
current_investigation_direction,
)?;
}
} else {
self.make_relevant_visit_call(
context,
node_id,
visitor,
current_investigation_direction,
)?;
}
if let Some(pointing_to) = callgraph.get(&node_id) {
for destination in pointing_to {
self.dfs_and_visit_subgraph(
*destination,
visited,
context,
callgraph,
visitor,
current_investigation_direction,
blacklist,
)?;
}
}
Ok(())
}
pub(super) fn make_relevant_visit_call<T>(
&self,
context: &WorkspaceContext,
node_id: NodeID,
visitor: &mut T,
current_investigation_direction: CurrentDFSVector,
) -> super::Result<()>
where
T: CallGraphVisitor,
{
if let Some(node) = context.nodes.get(&node_id) {
if node.node_type() != NodeType::FunctionDefinition
&& node.node_type() != NodeType::ModifierDefinition
{
return Ok(());
}
match current_investigation_direction {
CurrentDFSVector::Inward => {
if let ASTNode::FunctionDefinition(function) = node {
visitor
.visit_inward_function_definition(function)
.map_err(|_| super::Error::InwardFunctionDefinitionVisitError)?;
}
if let ASTNode::ModifierDefinition(modifier) = node {
visitor
.visit_inward_modifier_definition(modifier)
.map_err(|_| super::Error::InwardModifierDefinitionVisitError)?;
}
}
CurrentDFSVector::Outward => {
if let ASTNode::FunctionDefinition(function) = node {
visitor
.visit_outward_function_definition(function)
.map_err(|_| super::Error::OutwardFunctionDefinitionVisitError)?;
}
if let ASTNode::ModifierDefinition(modifier) = node {
visitor
.visit_outward_modifier_definition(modifier)
.map_err(|_| super::Error::OutwardModifierDefinitionVisitError)?;
}
}
CurrentDFSVector::OutwardSideEffect => {
if let ASTNode::FunctionDefinition(function) = node {
visitor.visit_outward_side_effect_function_definition(function).map_err(
|_| super::Error::OutwardSideEffectFunctionDefinitionVisitError,
)?;
}
if let ASTNode::ModifierDefinition(modifier) = node {
visitor.visit_outward_side_effect_modifier_definition(modifier).map_err(
|_| super::Error::OutwardSideEffectModifierDefinitionVisitError,
)?;
}
}
}
}
Ok(())
}
pub(super) fn make_entry_point_visit_call<T>(
&self,
context: &WorkspaceContext,
node_id: NodeID,
visitor: &mut T,
) -> super::Result<()>
where
T: CallGraphVisitor,
{
let node = context.nodes.get(&node_id).ok_or(super::Error::InvalidEntryPointId(node_id))?;
visitor.visit_entry_point(node).map_err(|_| super::Error::EntryPointVisitError)?;
Ok(())
}
}
```
--------------------------------------------------------------------------------
/aderyn_core/src/detect/low/unused_import.rs:
--------------------------------------------------------------------------------
```rust
use std::{collections::BTreeMap, error::Error};
use crate::ast::{ASTNode, NodeID, NodeType};
use crate::{
capture,
context::{
browser::{ExtractReferencedDeclarationsConditionally, GetClosestAncestorOfTypeX},
workspace::WorkspaceContext,
},
detect::detector::{IssueDetector, IssueDetectorNamePool, IssueSeverity},
};
use eyre::Result;
use self::source_unit_graph_analysis::Graph;
#[derive(Default)]
pub struct UnusedImportDetector {
// Keys are: [0] source file name, [1] line number, [2] character location of node.
// Do not add items manually, use `capture!` to add nodes to this BTreeMap.
found_instances: BTreeMap<(String, usize, String), NodeID>,
}
impl IssueDetector for UnusedImportDetector {
fn detect(&mut self, context: &WorkspaceContext) -> Result<bool, Box<dyn Error>> {
let mut graph = Graph::new();
for source_unit in context.source_units() {
for imported_source_unit in source_unit.import_directives() {
let imported_symbols = imported_source_unit
.symbol_aliases
.iter()
.flat_map(|s| s.foreign.referenced_declaration)
.collect::<Vec<_>>();
let imported_source_unit_id = imported_source_unit.source_unit;
if imported_symbols.is_empty() {
// This means it's not a named import, so technically we're importing
// everything that the source unit exports
if let Some(ASTNode::SourceUnit(i)) =
context.nodes.get(&imported_source_unit_id)
&& let Some(exported_symbols) = i.exported_symbols.as_ref()
{
let exported_symbols =
exported_symbols.values().flatten().collect::<Vec<_>>();
// Create a relationship from source_unit -> imported source unit FOR
// ALL exported_symbols
graph.create_relationship_for_symbols(
source_unit.id,
imported_source_unit_id,
imported_source_unit.id,
exported_symbols.into_iter().cloned().collect::<Vec<_>>(),
);
}
} else {
// This is a names import and we're only importing specific symbols
graph.create_relationship_for_symbols(
source_unit.id,
imported_source_unit_id,
imported_source_unit.id,
imported_symbols,
);
}
}
}
for source_unit in context.source_units() {
let referenced_declarations = ExtractReferencedDeclarationsConditionally::from(
source_unit,
context,
Box::new(|node_id, context| {
if let Some(node) = context.nodes.get(&node_id) {
return node
.closest_ancestor_of_type(context, NodeType::ImportDirective)
.is_none();
}
false
}),
)
.extracted;
for referenced_symbol in referenced_declarations {
graph.mark_used_pathways(source_unit.id, referenced_symbol);
if let Some(symbol_place) = context.nodes.get(&referenced_symbol)
&& let Some(ASTNode::ContractDefinition(contract)) =
symbol_place.closest_ancestor_of_type(context, NodeType::ContractDefinition)
{
graph.mark_used_pathways(source_unit.id, contract.id);
}
}
}
for unused_import_id in graph.collect_unused_imports() {
if let Some(node) = context.nodes.get(&unused_import_id) {
capture!(self, context, node);
}
}
Ok(!self.found_instances.is_empty())
}
fn severity(&self) -> IssueSeverity {
IssueSeverity::Low
}
fn title(&self) -> String {
String::from("Unused Import")
}
fn description(&self) -> String {
String::from("Redundant import statement. Consider removing it.")
}
fn instances(&self) -> BTreeMap<(String, usize, String), NodeID> {
self.found_instances.clone()
}
fn name(&self) -> String {
format!("{}", IssueDetectorNamePool::UnusedImport)
}
}
mod source_unit_graph_analysis {
//! Goal of this module is to create a graphical representation of all the source units
//! connected with import statements.
//!
//! Will be used to detect unused imports
use std::collections::{HashMap, HashSet};
use crate::ast::NodeID;
#[derive(Default, Debug)]
pub struct GNode {
#[allow(dead_code)]
source_unit: NodeID,
edges: Vec<GEdge>,
}
#[derive(Default, Debug)]
pub struct GEdge {
symbols: Vec<NodeID>,
to: NodeID,
import_statement: NodeID,
}
#[derive(Default, Debug)]
pub struct Graph {
/// Key source units: source unit ID
source_units: HashMap<NodeID, GNode>,
/// Key: Import Statement, Value: Symbol that is imported
useful_symbols: HashMap<NodeID, Vec<NodeID>>,
}
impl Graph {
pub fn new() -> Self {
Graph::default()
}
/// Each relationship edge corresponds to an import statement in `from` source unit that
/// imports symbols `symbols` from `to` source unit
pub fn create_relationship_for_symbols(
&mut self,
from_source_unit: NodeID,
to_source_unit: NodeID,
import_statement: NodeID,
symbols: Vec<NodeID>,
) {
// First we try to find the GNode with corresponding to the source unit. If we do we
// return it's index in the graph otherwise, we insert a GNode
let from_node = self
.source_units
.entry(from_source_unit)
.or_insert_with(|| GNode { source_unit: to_source_unit, edges: vec![] });
// Create the relationship edge
let relationship = GEdge { symbols, to: to_source_unit, import_statement };
from_node.edges.push(relationship);
// Make sure the `to` source unit node is present in the graph
_ = self
.source_units
.entry(to_source_unit)
.or_insert_with(|| GNode { source_unit: to_source_unit, edges: vec![] });
}
pub fn mark_used_pathways(
&mut self,
source_unit_id: NodeID,
symbol_id: NodeID,
) -> Option<()> {
let mut visited_source_unit_ids = HashSet::new();
self.dfs(source_unit_id, symbol_id, &mut visited_source_unit_ids)?;
Some(())
}
fn dfs(
&mut self,
source_unit: NodeID,
symbol_id: NodeID,
visited: &mut HashSet<NodeID>,
) -> Option<()> {
if visited.contains(&source_unit) {
return Some(());
}
visited.insert(source_unit);
let s = self.source_units.get(&source_unit)?;
let mut to_ids = vec![];
for relationship in &s.edges {
if relationship.symbols.contains(&symbol_id) {
self.useful_symbols
.entry(relationship.import_statement)
.or_default()
.push(symbol_id);
to_ids.push(relationship.to);
}
}
for to in to_ids {
self.dfs(to, symbol_id, visited)?;
}
Some(())
}
pub fn collect_unused_imports(&mut self) -> Vec<NodeID> {
let mut useless_imports: Vec<_> = vec![];
for node in self.source_units.values() {
for relationship in &node.edges {
if !self.useful_symbols.contains_key(&relationship.import_statement) {
useless_imports.push(relationship.import_statement);
}
}
}
useless_imports
}
}
}
#[cfg(test)]
mod unused_imports_tests {
use semver::Version;
use crate::detect::{detector::IssueDetector, low::unused_import::UnusedImportDetector};
#[test]
fn test_unused_imports() {
let context =
crate::detect::test_utils::load_multiple_solidity_source_units_into_single_context(
&[
"../tests/contract-playground/src/UnusedImport.sol",
"../tests/contract-playground/src/U2.sol",
"../tests/contract-playground/src/U3.sol",
"../tests/contract-playground/src/U4.sol",
"../tests/contract-playground/src/U5.sol",
],
Version::new(0, 8, 19),
);
let mut detector = UnusedImportDetector::default();
let found = detector.detect(&context).unwrap();
assert!(found);
assert_eq!(detector.instances().len(), 2);
}
}
```
--------------------------------------------------------------------------------
/benchmarks/ecrecover/report/change/t-test.svg:
--------------------------------------------------------------------------------
```
<svg width="960" height="540" viewBox="0 0 960 540" xmlns="http://www.w3.org/2000/svg">
<text x="480" y="32" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="16.129032258064516" opacity="1" fill="#000000">
ecrecover: Welch t test
</text>
<text x="27" y="263" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000" transform="rotate(270, 27, 263)">
Density
</text>
<text x="510" y="513" dy="-0.5ex" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
t score
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="86,53 86,472 "/>
<text x="77" y="472" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,472 86,472 "/>
<text x="77" y="420" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.05
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,420 86,420 "/>
<text x="77" y="368" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.1
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,368 86,368 "/>
<text x="77" y="316" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.15
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,316 86,316 "/>
<text x="77" y="263" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.2
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,263 86,263 "/>
<text x="77" y="211" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.25
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,211 86,211 "/>
<text x="77" y="159" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.3
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,159 86,159 "/>
<text x="77" y="107" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.35
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,107 86,107 "/>
<text x="77" y="54" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.4
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,54 86,54 "/>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="87,473 932,473 "/>
<text x="107" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
-4.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="107,473 107,478 "/>
<text x="210" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
-3.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="210,473 210,478 "/>
<text x="314" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
-2.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="314,473 314,478 "/>
<text x="417" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
-1.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="417,473 417,478 "/>
<text x="520" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="520,473 520,478 "/>
<text x="623" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
1.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="623,473 623,478 "/>
<text x="727" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
2.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="727,473 727,478 "/>
<text x="830" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
3.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="830,473 830,478 "/>
<polygon opacity="0.25" fill="#1F78B4" points="87,472 88,472 90,472 92,472 93,472 95,472 97,472 98,472 100,472 102,472 103,472 105,472 107,472 109,472 110,472 112,472 114,472 115,472 117,472 119,472 120,472 122,472 124,472 125,472 127,472 129,472 131,472 132,472 134,472 136,472 137,472 139,472 141,472 142,472 144,472 146,472 147,472 149,472 151,472 153,472 154,472 156,472 158,472 159,472 161,472 163,472 164,472 166,472 168,472 169,472 171,472 173,472 175,472 176,472 178,472 180,472 181,472 183,472 185,472 186,472 188,472 190,472 191,472 193,472 195,471 197,471 198,471 200,471 202,471 203,471 205,471 207,471 208,471 210,471 212,470 214,470 215,470 217,470 219,470 220,470 222,470 224,469 225,469 227,469 229,469 230,468 232,468 234,468 236,467 237,467 239,467 241,466 242,466 244,465 246,465 247,464 249,464 251,463 252,463 254,462 256,461 258,461 259,460 261,459 263,458 264,458 266,457 268,456 269,455 271,454 273,453 274,451 276,450 278,449 280,448 281,447 283,445 285,444 286,442 288,441 290,439 291,438 293,436 295,435 296,433 298,431 300,429 302,428 303,426 305,424 307,422 308,419 310,417 312,415 313,412 315,410 317,407 318,405 320,402 322,399 324,396 325,393 327,390 329,387 330,384 332,381 334,378 335,375 337,372 339,368 341,365 342,362 344,358 346,355 347,352 349,348 351,345 352,341 354,338 356,334 357,331 359,327 361,324 363,320 364,317 366,313 368,309 369,306 371,302 373,298 374,294 376,290 378,286 379,282 381,278 383,274 385,270 386,266 388,263 390,259 391,255 393,252 395,248 396,245 398,242 400,238 401,235 403,232 405,229 407,226 408,222 410,219 412,216 413,213 415,209 417,206 418,203 420,199 422,196 423,193 425,190 427,187 429,184 430,181 432,178 434,175 435,172 437,169 439,166 440,163 442,160 444,157 445,154 447,151 449,148 451,145 452,142 454,139 456,136 457,134 459,131 461,129 462,127 464,124 466,122 468,120 469,118 471,117 473,115 474,113 476,111 478,109 479,108 481,106 483,105 484,104 486,102 488,101 490,100 491,99 493,98 495,98 496,97 498,96 500,95 501,95 503,94 505,93 506,93 508,92 510,92 512,92 513,92 515,92 517,92 518,92 520,92 522,92 523,92 525,92 527,92 528,92 530,92 532,92 534,92 535,92 537,93 539,93 540,94 542,95 544,96 545,97 547,98 549,100 550,101 552,103 554,105 556,107 557,108 559,110 561,112 562,114 564,115 566,117 567,119 569,121 571,122 573,124 574,126 576,128 578,130 579,132 581,135 583,137 584,140 586,142 588,145 589,148 591,150 593,153 595,156 596,158 598,161 600,164 601,167 603,169 605,172 606,175 608,177 610,180 611,183 613,186 615,188 617,191 618,194 620,197 622,200 623,203 625,206 627,209 628,212 630,215 632,218 633,221 635,225 637,228 639,232 640,235 642,239 644,243 645,246 647,250 649,254 650,258 652,262 654,266 655,271 657,275 659,279 661,283 662,287 664,291 666,295 667,299 669,303 671,307 672,311 674,315 676,319 677,323 679,326 681,330 683,333 684,337 686,340 688,343 689,346 691,349 693,352 694,355 696,358 698,362 700,365 701,368 703,371 705,374 706,377 708,380 710,384 711,387 713,390 715,393 716,396 718,398 720,401 722,404 723,406 725,408 727,411 728,413 730,415 732,417 733,419 735,421 737,424 738,426 740,428 742,430 744,432 745,434 747,435 749,437 750,439 752,441 754,443 755,444 757,446 759,447 760,449 762,450 764,451 766,452 767,453 769,454 771,455 772,456 774,457 776,458 777,459 779,460 781,460 782,461 784,462 786,462 788,463 789,464 791,464 793,465 794,465 796,465 798,466 799,466 801,466 803,467 804,467 806,467 808,468 810,468 811,468 813,468 815,469 816,469 818,469 820,469 821,470 823,470 825,470 827,470 828,470 830,470 832,471 833,471 835,471 837,471 838,471 840,471 842,471 843,472 845,472 847,472 849,472 850,472 852,472 854,472 855,472 857,472 859,472 860,472 862,472 864,472 865,472 867,472 869,472 871,472 872,472 874,472 876,472 877,472 879,472 881,472 882,472 884,472 886,472 887,472 889,472 891,472 893,472 894,472 896,472 898,472 899,472 901,472 903,472 904,472 906,472 908,472 909,472 911,472 913,472 915,472 916,472 918,472 920,472 921,472 923,472 925,472 926,472 928,472 930,472 932,472 932,472 87,472 "/>
<polyline fill="none" opacity="1" stroke="#1F78B4" stroke-width="2" points="468,472 468,53 "/>
<text x="842" y="250" dy="0.76em" text-anchor="start" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
t distribution
</text>
<text x="842" y="265" dy="0.76em" text-anchor="start" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
t statistic
</text>
<rect x="812" y="250" width="20" height="10" opacity="0.25" fill="#1F78B4" stroke="none"/>
<polyline fill="none" opacity="1" stroke="#1F78B4" stroke-width="1" points="812,270 832,270 "/>
</svg>
```
--------------------------------------------------------------------------------
/benchmarks/arbitrary-transfer-from/report/change/t-test.svg:
--------------------------------------------------------------------------------
```
<svg width="960" height="540" viewBox="0 0 960 540" xmlns="http://www.w3.org/2000/svg">
<text x="480" y="32" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="16.129032258064516" opacity="1" fill="#000000">
arbitrary-transfer-from: Welch t test
</text>
<text x="27" y="263" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000" transform="rotate(270, 27, 263)">
Density
</text>
<text x="510" y="513" dy="-0.5ex" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
t score
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="86,53 86,472 "/>
<text x="77" y="472" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,472 86,472 "/>
<text x="77" y="421" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.05
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,421 86,421 "/>
<text x="77" y="370" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.1
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,370 86,370 "/>
<text x="77" y="319" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.15
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,319 86,319 "/>
<text x="77" y="268" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.2
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,268 86,268 "/>
<text x="77" y="217" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.25
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,217 86,217 "/>
<text x="77" y="166" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.3
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,166 86,166 "/>
<text x="77" y="114" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.35
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,114 86,114 "/>
<text x="77" y="63" dy="0.5ex" text-anchor="end" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.4
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="81,63 86,63 "/>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="87,473 932,473 "/>
<text x="90" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
-4.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="90,473 90,478 "/>
<text x="196" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
-3.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="196,473 196,478 "/>
<text x="301" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
-2.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="301,473 301,478 "/>
<text x="407" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
-1.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="407,473 407,478 "/>
<text x="512" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
0.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="512,473 512,478 "/>
<text x="618" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
1.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="618,473 618,478 "/>
<text x="723" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
2.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="723,473 723,478 "/>
<text x="829" y="483" dy="0.76em" text-anchor="middle" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
3.0
</text>
<polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="829,473 829,478 "/>
<polygon opacity="0.25" fill="#1F78B4" points="87,472 88,472 90,472 92,472 93,472 95,472 97,472 98,472 100,472 102,472 103,472 105,472 107,472 109,472 110,472 112,472 114,472 115,472 117,472 119,472 120,472 122,472 124,472 125,472 127,472 129,472 131,472 132,472 134,472 136,472 137,472 139,472 141,472 142,472 144,472 146,472 147,472 149,472 151,472 153,472 154,472 156,472 158,472 159,472 161,472 163,472 164,472 166,472 168,472 169,472 171,472 173,472 175,472 176,472 178,472 180,472 181,471 183,471 185,471 186,471 188,471 190,471 191,471 193,470 195,470 197,470 198,470 200,469 202,469 203,469 205,469 207,468 208,468 210,468 212,468 214,467 215,467 217,467 219,467 220,466 222,466 224,466 225,465 227,465 229,464 230,464 232,463 234,463 236,462 237,461 239,461 241,460 242,459 244,459 246,458 247,457 249,457 251,456 252,455 254,454 256,453 258,452 259,452 261,451 263,450 264,449 266,448 268,447 269,446 271,445 273,443 274,442 276,441 278,440 280,438 281,437 283,435 285,434 286,432 288,430 290,428 291,427 293,425 295,423 296,421 298,418 300,416 302,414 303,412 305,409 307,407 308,404 310,402 312,399 313,396 315,393 317,391 318,388 320,385 322,382 324,379 325,377 327,374 329,371 330,368 332,365 334,362 335,359 337,357 339,354 341,351 342,348 344,345 346,342 347,339 349,336 351,333 352,330 354,327 356,323 357,320 359,317 361,313 363,310 364,307 366,303 368,299 369,296 371,292 373,288 374,285 376,281 378,277 379,273 381,270 383,266 385,262 386,258 388,254 390,251 391,247 393,243 395,240 396,236 398,233 400,229 401,226 403,223 405,219 407,216 408,213 410,210 412,207 413,203 415,200 417,197 418,193 420,190 422,187 423,183 425,180 427,176 429,173 430,170 432,166 434,163 435,160 437,157 439,155 440,152 442,149 444,147 445,144 447,142 449,139 451,137 452,135 454,132 456,130 457,128 459,126 461,125 462,123 464,121 466,120 468,118 469,117 471,115 473,114 474,113 476,111 478,110 479,108 481,107 483,106 484,104 486,103 488,102 490,101 491,100 493,99 495,98 496,97 498,97 500,96 501,96 503,95 505,95 506,94 508,94 510,93 512,93 513,93 515,92 517,92 518,92 520,92 522,92 523,92 525,92 527,92 528,93 530,94 532,94 534,95 535,96 537,97 539,99 540,100 542,101 544,103 545,104 547,106 549,107 550,108 552,110 554,111 556,113 557,114 559,116 561,118 562,119 564,121 566,123 567,125 569,127 571,130 573,132 574,134 576,137 578,139 579,142 581,145 583,147 584,150 586,153 588,156 589,159 591,161 593,164 595,167 596,170 598,173 600,176 601,179 603,181 605,184 606,187 608,190 610,194 611,197 613,200 615,203 617,207 618,210 620,214 622,218 623,222 625,225 627,229 628,233 630,237 632,241 633,245 635,249 637,252 639,256 640,260 642,264 644,267 645,271 647,274 649,278 650,281 652,285 654,288 655,292 657,296 659,299 661,303 662,307 664,310 666,314 667,318 669,321 671,325 672,328 674,331 676,335 677,338 679,341 681,344 683,347 684,350 686,353 688,356 689,359 691,362 693,365 694,367 696,370 698,373 700,376 701,379 703,381 705,384 706,387 708,390 710,392 711,395 713,397 715,400 716,402 718,405 720,407 722,409 723,411 725,414 727,416 728,418 730,420 732,422 733,423 735,425 737,427 738,429 740,431 742,432 744,434 745,436 747,437 749,439 750,440 752,442 754,443 755,444 757,445 759,447 760,448 762,449 764,450 766,451 767,452 769,453 771,454 772,455 774,456 776,457 777,458 779,459 781,460 782,460 784,461 786,461 788,462 789,463 791,463 793,464 794,464 796,464 798,465 799,465 801,466 803,466 804,466 806,467 808,467 810,467 811,468 813,468 815,468 816,468 818,469 820,469 821,469 823,469 825,470 827,470 828,470 830,470 832,470 833,470 835,471 837,471 838,471 840,471 842,471 843,471 845,471 847,471 849,471 850,471 852,472 854,472 855,472 857,472 859,472 860,472 862,472 864,472 865,472 867,472 869,472 871,472 872,472 874,472 876,472 877,472 879,472 881,472 882,472 884,472 886,472 887,472 889,472 891,472 893,472 894,472 896,472 898,472 899,472 901,472 903,472 904,472 906,472 908,472 909,472 911,472 913,472 915,472 916,472 918,472 920,472 921,472 923,472 925,472 926,472 928,472 930,472 932,472 932,472 87,472 "/>
<polyline fill="none" opacity="1" stroke="#1F78B4" stroke-width="2" points="344,472 344,53 "/>
<text x="842" y="250" dy="0.76em" text-anchor="start" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
t distribution
</text>
<text x="842" y="265" dy="0.76em" text-anchor="start" font-family="sans-serif" font-size="9.67741935483871" opacity="1" fill="#000000">
t statistic
</text>
<rect x="812" y="250" width="20" height="10" opacity="0.25" fill="#1F78B4" stroke="none"/>
<polyline fill="none" opacity="1" stroke="#1F78B4" stroke-width="1" points="812,270 832,270 "/>
</svg>
```