# Technical Documentation: crytic/slither

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/crytic/slither)

### Overview (`README.md`)

# [Slither, the smart contract static analyzer](https://crytic.github.io/slither/slither.html)

<img src="https://raw.githubusercontent.com/crytic/slither/master/logo.png" alt="Slither Static Analysis Framework Logo" width="500" />

[](https://github.com/crytic/slither/actions?query=workflow%3ACI)

[](https://crytic.github.io/slither/slither.html)
[](https://github.com/crytic/slither/wiki/SlithIR)

> Join the Empire Hacking Slack
>
> [](https://slack.empirehacking.nyc/)
> > _- Discussions and Support_

**Slither** is a Solidity & Vyper static analysis framework written in Python3. It runs a suite of vulnerability detectors, prints visual information about contract details, and provides an API to easily write custom analyses. Slither enables developers to find vulnerabilities, enhance their code comprehension, and quickly prototype custom analyses.

* [Features](#features)
* [Usage](#usage)
* [How to install](#how-to-install)
  * [Using uv (Recommended)](#using-uv-recommended)
  * [Using Pip](#using-pip)
  * [Using Git](#using-git-development)
  * [Using Docker](#using-docker)
  * [Integration](#integration)
* [Detectors](#detectors)
* [Printers](#printers)
  * [Quick Review Printers](#quick-review-printers)
  * [In-Depth Review Printers](#in-depth-review-printers)
* [Tools](#tools)
* [API Documentation](#api-documentation)
* [Getting Help](#getting-help)
* [FAQ](#faq)
* [License](#license)
* [Publications](#publications)
  * [Trail of Bits publication](#trail-of-bits-publication)
  * [External publications](#external-publications)

## Features

* Detects vulnerable Solidity code with low false positives (see the list of [trophies](./trophies.md))
* Identifies where the error condition occurs in the source code
* Easily integrates into continuous integration and Hardhat/Foundry builds
* Built-in 'printers' quickly report crucial contract information
* Detector API to write custom analyses in Python
* Ability to analyze contracts written with Solidity >= 0.4
* Intermediate representation ([SlithIR](https://github.com/crytic/slither/wiki/SlithIR)) enables simple, high-precision analyses
* Correctly parses 99.9% of all public Solidity code
* Average execution time of less than 1 second per contract
* Integrates with Github's code scanning in [CI](https://github.com/marketplace/actions/slither-action)
* Support for Vyper smart contracts

## Usage

Run Slither on a Hardhat/Foundry/Dapp/Brownie application:

```console
slither .
```

This is the preferred option if your project has dependencies as Slither relies on the underlying compilation framework to compile source code.

However, you can run Slither on a single file that does not import dependencies:

```console
slither tests/uninitialized.sol
```

## How to install

> **Note**
> Slither requires Python 3.10+.
If you're **not** going to use one of the [supported compilation frameworks](https://github.com/crytic/crytic-compile), you need [solc](https://github.com/ethereum/solidity/), the Solidity compiler; we recommend using [solc-select](https://github.com/crytic/solc-select) to conveniently switch between solc versions.

### Using uv (Recommended)

[uv](https://github.com/astral-sh/uv) is a fast Python package manager that's 10-100x faster than pip.

```console
# Install uv if you haven't already
curl -LsSf https://astral.sh/uv/install.sh | sh

# Install slither as a tool
uv tool install slither-analyzer

# Or run slither without installation
uvx --from slither-analyzer slither <target>
```

To upgrade:

```console
uv tool upgrade slither-analyzer
```

### Using Pip

```console
python3 -m pip install slither-analyzer
```

To upgrade:

```console
python3 -m pip install --upgrade slither-analyzer
```

### Using Brew

```console
brew install slither-analyzer
```

### Using Git (Development)

```bash
git clone https://github.com/crytic/slither.git && cd slither

# Install as editable for development
uv tool install -e .

# Or use uv run for testing without installation
uv run slither <target>
```

The `-e` flag installs in editable mode, meaning changes to the source code are immediately reflected without reinstalling.

### Using Docker

Use the [`eth-security-toolbox`](https://github.com/crytic/eth-security-toolbox/) docker image. It includes all of our security tools and every major version of Solidity in a single image. `/home/share` will be mounted to `/share` in the container.

```bash
docker pull trailofbits/eth-security-toolbox
```

To share a directory in the container:

```bash
docker run -it -v /home/share:/share trailofbits/eth-security-toolbox
```

### Integration

* For GitHub action integration, use [slither-action](https://github.com/marketplace/actions/slither-action).
* For pre-commit integration, use (replace `$GIT_TAG` with real tag)
  ```YAML
  - repo: https://github.com/crytic/slither
    rev: $GIT_TAG
    hooks:
      - id: slither
  ```
* To generate a Markdown report, use `slither [target] --checklist`.
* To generate a Markdown with GitHub source code highlighting, use `slither [target] --checklist --markdown-root https://github.com/ORG/REPO/blob/COMMIT/` (replace `ORG`, `REPO`, `COMMIT`)

## Detectors

Num | Detector | What it Detects | Impact | Confidence
--- | --- | --- | --- | ---
1 | `abiencoderv2-array` | [Storage abiencoderv2 array](https://github.com/crytic/slither/wiki/Detector-Documentation#storage-abiencoderv2-array) | High | High
2 | `arbitrary-send-erc20` | [transferFrom uses arbitrary `from`](https://github.com/crytic/slither/wiki/Detector-Documentation#arbitrary-from-in-transferfrom) | High | High
3 | `array-by-reference` | [Modifying storage array by value](https://github.com/crytic/slither/wiki/Detector-Documentation#modifying-storage-array-by-value) | High | High
4 | `encode-packed-collision` | [ABI encodePacked Collision](https://github.com/crytic/slither/wiki/Detector-Documentation#abi-encodePacked-collision) | High | High
5 | `incorrect-shift` | [The order of parameters in a shift instruction is incorrect.](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-shift-in-assembly) | High | High
6 | `multiple-constructors` | [Multiple constructor schemes](https://github.com/crytic/slither/wiki/Detector-Documentation#multiple-constructor-schemes) | High | High
7 | `name-reused` | [Contract's name reused](https://github.com/crytic/slither/wiki/Detector-Documentation#name-reused) | High | High
8 | `protected-vars` | [Detected unprotected variables](https://github.com/crytic/slither/wiki/Detector-Documentation#protected-variables) | High | High
9 | `public-mappings-nested` | [Public mappings with nested variables](https://github.com/crytic/slither/wiki/Detector-Documentation#public-mappings-with-nested-variables) | High | High
10 | `rtlo` | [Right-To-Left-Override control character is used](https://github.com/crytic/slither/wiki/Detector-Documentation#right-to-left-override-character) | High | High
11 | `shadowing-state` | [State variables shadowing](https://github.com/crytic/slither/wiki/Detector-Documentation#state-variable-shadowing) | High | High
12 | `suicidal` | [Functions allowing anyone to destruct the contract](https://github.com/crytic/slither/wiki/Detector-Documentation#suicidal) | High | High
13 | `uninitialized-state` | [Uninitialized state variables](https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-state-variables) | High | High
14 | `uninitialized-storage` | [Uninitialized storage variables](https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-storage-variables) | High | High
15 | `unprotected-upgrade` | [Unprotected upgradeable contract](https://github.com/crytic/slither/wiki/Detector-Documentation#unprotected-upgradeable-contract) | High | High
16 | `arbitrary-send-erc20-permit` | [transferFrom uses arbitrary from with permit](https://github.com/crytic/slither/wiki/Detector-Documentation#arbitrary-from-in-transferfrom-used-with-permit) | High | Medium
17 | `arbitrary-send-eth` | [Functions that send Ether to arbitrary destinations](https://github.com/crytic/slither/wiki/Detector-Documentation#functions-that-send-ether-to-arbitrary-destinations) | High | Medium
18 | `controlled-array-length` | [Tainted array length assignment](https://github.com/crytic/slither/wiki/Detector-Documentation#array-length-assignment) | High | Medium
19 | `controlled-delegatecall` | [Controlled delegatecall destination](https://github.com/crytic/slither/wiki/Detector-Documentation#controlled-delegatecall) | High | Medium
20 | `delegatecall-loop` | [Payable functions using `delegatecall` inside a loop](https://github.com/crytic/slither/wiki/Detector-Documentation/#payable-functions-using-delegatecall-inside-a-loop) | High | Medium
21 | `incorrect-exp` | [Incorrect exponentiation](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-exponentiation) | High | Medium
22 | `incorrect-return` | [If a `return` is incorrectly used in assembly mode.](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-return-in-assembly) | High | Medium
23 | `msg-value-loop` | [msg.value inside a loop](https://github.com/crytic/slither/wiki/Detector-Documentation/#msgvalue-inside-a-loop) | High | Medium
24 | `reentrancy-eth` | [Reentrancy vulnerabilities (theft of ethers)](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities) | High | Medium
25 | `reentrancy-balance` | [Reentrancy vulnerabilities leading to outdated balance checks](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-4) | High | Medium
26 | `return-leave` | [If a `return` is used instead of a `leave`.](https://github.com/crytic/slither/wiki/Detector-Documentation#return-instead-of-leave-in-assembly) | High | Medium
27 | `storage-array` | [Signed storage integer array compiler bug](https://github.com/crytic/slither/wiki/Detector-Documentation#storage-signed-integer-array) | High | Medium
28 | `unchecked-transfer` | [Unchecked tokens transfer](https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-transfer) | High | Medium
29 | `weak-prng` | [Weak PRNG](https://github.com/crytic/slither/wiki/Detector-Documentation#weak-PRNG) | High | Medium
30 | `domain-separator-collision` | [Detects ERC20 tokens that have a function whose signature collides with EIP-2612's DOMAIN_SEPARATOR()](https://github.com/crytic/slither/wiki/Detector-Documentation#domain-separator-collision) | Medium | High
31 | `enum-conversion` | [Detect dangerous enum conversion](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-enum-conversion) | Medium | High
32 | `erc20-interface` | [Incorrect ERC20 interfaces](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-erc20-interface) | Medium | High
33 | `erc721-interface` | [Incorrect ERC721 interfaces](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-erc721-interface) | Medium | High
34 | `incorrect-equality` | [Dangerous strict equalities](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-strict-equalities) | Medium | High
35 | `locked-ether` | [Contracts that lock ether](https://github.com/crytic/slither/wiki/Detector-Documentation#contracts-that-lock-ether) | Medium | High
36 | `mapping-deletion` | [Deletion on mapping containing a structure](https://github.com/crytic/slither/wiki/Detector-Documentation#deletion-on-mapping-containing-a-structure) | Medium | High
37 | `pyth-deprecated-functions` | [Detect Pyth deprecated functions](https://github.com/crytic/slither/wiki/Detector-Documentation#pyth-deprecated-functions) | Medium | High
38 | `pyth-unchecked-confidence` | [Detect when the confidence level of a Pyth price is not checked](https://github.com/crytic/slither/wiki/Detector-Documentation#pyth-unchecked-confidence-level) | Medium | High
39 | `pyth-unchecked-publishtime` | [Detect when the publishTime of a Pyth price is not checked](https://github.com/crytic/slither/wiki/Detector-Documentation#pyth-unchecked-publishtime) | Medium | High
40 | `shadowing-abstract` | [State variables shadowing from abstract contracts](https://github.com/crytic/slither/wiki/Detector-Documentation#state-variable-shadowing-from-abstract-contracts) | Medium | High
41 | `tautological-compare` | [Comparing a variable to itself always returns true or false, depending on comparison](https://github.com/crytic/slither/wiki/Detector-Documentation#tautological-compare) | Medium | High
42 | `tautology` | [Tautology or contradiction](https://github.com/crytic/slither/wiki/Detector-Documentation#tautology-or-contradiction) | Medium | High
43 | `write-after-write` | [Unused write](https://github.com/crytic/slither/wiki/Detector-Documentation#write-after-write) | Medium | High
44 | `boolean-cst` | [Misuse of Boolean constant](https://github.com/crytic/slither/wiki/Detector-Documentation#misuse-of-a-boolean-constant) | Medium | Medium
45 | `chronicle-unchecked-price` | [Detect when Chronicle price is not checked.](https://github.com/crytic/slither/wiki/Detector-Documentation#chronicle-unchecked-price) | Medium | Medium
46 | `constant-function-asm` | [Constant functions using assembly code](https://github.com/crytic/slither/wiki/Detector-Documentation#constant-functions-using-assembly-code) | Medium | Medium
47 | `constant-function-state` | [Constant functions changing the state](https://github.com/crytic/slither/wiki/Detector-Documentation#constant-functions-changing-the-state) | Medium | Medium
48 | `divide-before-multiply` | [Imprecise arithmetic operations order](https://github.com/crytic/slither/wiki/Detector-Documentation#divide-before-multiply) | Medium | Medium
49 | `gelato-unprotected-randomness` | [Call to `_requestRandomness` within an unprotected function](https://github.com/crytic/slither/wiki/Detector-Documentation#gelato-unprotected-randomness) | Medium | Medium
50 | `out-of-order-retryable` | [Out-of-order retryable transactions](https://github.com/crytic/slither/wiki/Detector-Documentation#out-of-order-retryable-transactions) | Medium | Medium
51 | `reentrancy-no-eth` | [Reentrancy vulnerabilities (no theft of ethers)](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-1) | Medium | Medium
52 | `reused-constructor` | [Reused base constructor](https://github.com/crytic/slither/wiki/Detector-Documentation#reused-base-constructors) | Medium | Medium
53 | `tx-origin` | [Dangerous usage of `tx.origin`](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-usage-of-txorigin) | Medium | Medium
54 | `unchecked-lowlevel` | [Unchecked low-level calls](https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-low-level-calls) | Medium | Medium
55 | `unchecked-send` | [Unchecked send](https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-send) | Medium | Medium
56 | `uninitialized-local` | [Uninitialized local variables](https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-local-variables) | Medium | Medium
57 | `unused-return` | [Unused return values](https://github.com/crytic/slither/wiki/Detector-Documentation#unused-return) | Medium | Medium
58 | `chainlink-feed-registry` | [Detect when chainlink feed registry is used](https://github.com/crytic/slither/wiki/Detector-Documentation#chainlink-feed-registry-usage) | Low | High
59 | `incorrect-modifier` | [Modifiers that can return the default value](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-modifier) | Low | High
60 | `optimism-deprecation` | [Detect when deprecated Optimism predeploy or function is used.](https://github.com/crytic/slither/wiki/Detector-Documentation#optimism-deprecated-predeploy-or-function) | Low | High
61 | `shadowing-builtin` | [Built-in symbol shadowing](https://github.com/crytic/slither/wiki/Detector-Documentation#builtin-symbol-shadowing) | Low | High
62 | `shadowing-local` | [Local variables shadowing](https://github.com/crytic/slither/wiki/Detector-Documentation#local-variable-shadowing) | Low | High
63 | `uninitialized-fptr-cst` | [Uninitialized function pointer calls in constructors](https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-function-pointers-in-constructors) | Low | High
64 | `variable-scope` | [Local variables used prior their declaration](https://github.com/crytic/slither/wiki/Detector-Documentation#pre-declaration-usage-of-local-variables) | Low | High
65 | `void-cst` | [Constructor called not implemented](https://github.com/crytic/slither/wiki/Detector-Documentation#void-constructor) | Low | High
66 | `calls-loop` | [Multiple calls in a loop](https://github.com/crytic/slither/wiki/Detector-Documentation/#calls-inside-a-loop) | Low | Medium
67 | `events-access` | [Missing Events Access Control](https://github.com/crytic/slither/wiki/Detector-Documentation#missing-events-access-control) | Low | Medium
68 | `events-maths` | [Missing Events Arithmetic](https://github.com/crytic/slither/wiki/Detector-Documentation#missing-events-arithmetic) | Low | Medium
69 | `incorrect-unary` | [Dangerous unary expressions](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-unary-expressions) | Low | Medium
70 | `missing-zero-check` | [Missing Zero Address Validation](https://github.com/crytic/slither/wiki/Detector-Documentation#missing-zero-address-validation) | Low | Medium
71 | `reentrancy-benign` | [Benign reentrancy vulnerabilities](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-2) | Low | Medium
72 | `reentrancy-events` | [Reentrancy vulnerabilities leading to out-of-order Events](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-3) | Low | Medium
73 | `return-bomb` | [A low level callee may consume all callers gas unexpectedly.](https://github.com/crytic/slither/wiki/Detector-Documentation#return-bomb) | Low | Medium
74 | `timestamp` | [Dangerous usage of `block.timestamp`](https://github.com/crytic/slither/wiki/Detector-Documentation#block-timestamp) | Low | Medium
75 | `assembly` | [Assembly usage](https://github.com/crytic/slither/wiki/Detector-Documentation#assembly-usage) | Informational | High
76 | `assert-state-change` | [Assert state change](https://github.com/crytic/slither/wiki/Detector-Documentation#assert-state-change) | Informational | High
77 | `boolean-equal` | [Comparison to boolean constant](https://github.com/crytic/slither/wiki/Detector-Documentation#boolean-equality) | Informational | High
78 | `cyclomatic-complexity` | [Detects functions with high (> 11) cyclomatic complexity](https://github.com/crytic/slither/wiki/Detector-Documentation#cyclomatic-complexity) | Informational | High
79 | `deprecated-standards` | [Deprecated Solidity Standards](https://github.com/crytic/slither/wiki/Detector-Documentation#deprecated-standards) | Informational | High
80 | `erc20-indexed` | [Un-indexed ERC20 event parameters](https://github.com/crytic/slither/wiki/Detector-Documentation#unindexed-erc20-event-parameters) | Informational | High
81 | `function-init-state` | [Function initializing state variables](https://github.com/crytic/slither/wiki/Detector-Documentation#function-initializing-state) | Informational | High
82 | `incorrect-using-for` | [Detects using-for statement usage when no function from a given library matches a given type](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-usage-of-using-for-statement) | Informational | High
83 | `low-level-calls` | [Low level calls](https://github.com/crytic/slither/wiki/Detector-Documentation#low-level-calls) | Informational | High
84 | `missing-inheritance` | [Missing inheritance](https://github.com/crytic/slither/wiki/Detector-Documentation#missing-inheritance) | Informational | High
85 | `naming-convention` | [Conformity to Solidity naming conventions](https://github.com/crytic/slither/wiki/Detector-Documentation#conformance-to-solidity-naming-conventions) | Informational | High
86 | `pragma` | [If different pragma directives are used](https://github.com/crytic/slither/wiki/Detector-Documentation#different-pragma-directives-are-used) | Informational | High
87 | `redundant-statements` | [Redundant statements](https://github.com/crytic/slither/wiki/Detector-Documentation#redundant-statements) | Informational | High
88 | `solc-version` | [Incorrect Solidity version](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-versions-of-solidity) | Informational | High
89 | `unimplemented-functions` | [Unimplemented functions](https://github.com/crytic/slither/wiki/Detector-Documentation#unimplemented-functions) | Informational | High
90 | `unindexed-event-address` | [Events with address parameters but no indexed parameters](https://github.com/crytic/slither/wiki/Detector-Documentation#unindexed-event-address-parameters) | Informational | High
91 | `unused-state` | [Unused state variables](https://github.com/crytic/slither/wiki/Detector-Documentation#unused-state-variable) | Informational | High
92 | `costly-loop` | [Costly operations in a loop](https://github.com/crytic/slither/wiki/Detector-Documentation#costly-operations-inside-a-loop) | Informational | Medium
93 | `dead-code` | [Functions that are not used](https://github.com/crytic/slither/wiki/Detector-Documentation#dead-code) | Informational | Medium
94 | `reentrancy-unlimited-gas` | [Reentrancy vulnerabilities through send and transfer](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-4) | Informational | Medium
95 | `too-many-digits` | [Conformance to numeric notation best practices](https://github.com/crytic/slither/wiki/Detector-Documentation#too-many-digits) | Informational | Medium
96 | `cache-array-length` | [Detects `for` loops that use `length` member of some storage array in their loop condition and don't modify it.](https://github.com/crytic/slither/wiki/Detector-Documentation#cache-array-length) | Optimization | High
97 | `constable-states` | [State variables that could be declared constant](https://github.com/crytic/slither/wiki/Detector-Documentation#state-variables-that-could-be-declared-constant) | Optimization | High
98 | `external-function` | [Public function that could be declared external](https://github.com/crytic/slither/wiki/Detector-Documentation#public-function-that-could-be-declared-external) | Optimization | High
99 | `immutable-states` | [State variables that could be declared immutable](https://github.com/crytic/slither/wiki/Detector-Documentation#state-variables-that-could-be-declared-immutable) | Optimization | High
100 | `var-read-using-this` | [Contract reads its own variable using `this`](https://github.com/crytic/slither/wiki/Detector-Documentation#public-variable-read-in-external-context) | Optimization | High

For more information, see

* The [Detector Documentation](https://github.com/crytic/slither/wiki/Detector-Documentation) for details on each detector
* The [Detection Selection](https://github.com/crytic/slither/wiki/Usage#detector-selection) to run only selected detectors. By default, all the detectors are run.
* The [Triage Mode](https://github.com/crytic/slither/wiki/Usage#triage-mode) to filter individual results

## Printers

### Quick Review Printers

* `human-summary`: [Print a human-readable summary of the contracts](https://github.com/trailofbits/slither/wiki/Printer-documentation#human-summary)
* `inheritance-graph`: [Export the inheritance graph of each contract to a dot file](https://github.com/trailofbits/slither/wiki/Printer-documentation#inheritance-graph)
* `contract-summary`: [Print a summary of the contracts](https://github.com/trailofbits/slither/wiki/Printer-documentation#contract-summary)
* `loc`: [Count the total number lines of code (LOC), source lines of code (SLOC), and comment lines of code (CLOC) found in source files (SRC), dependencies (DEP), and test files (TEST).](https://github.com/trailofbits/slither/wiki/Printer-documentation#loc)
* `entry-points`: [Print all the state-changing entry point functions and their variables of the contracts](https://github.com/trailofbits/slither/wiki/Printer-documentation#entry-points)

### In-Depth Review Printers

* `call-graph`: [Export the call-graph of the contracts to a dot file](https://github.com/crytic/slither/wiki/Printer-documentation#call-graph)
* `cfg`: [Export the CFG of each functions](https://github.com/crytic/slither/wiki/Printer-documentation#cfg)
* `function-summary`: [Print a summary of the functions](https://github.com/crytic/slither/wiki/Printer-documentation#function-summary)
* `vars-and-auth`: [Print the state variables written and the authorization of the functions](https://github.com/crytic/slither/wiki/Printer-documentation#variables-written-and-authorization)
* `not-pausable`: [Print functions that do not use `whenNotPaused` modifier](https://github.com/crytic/slither/wiki/Printer-documentation#when-not-paused).

To run a printer, use `--print` and a comma-separated list of printers.

See the [Printer documentation](https://github.com/crytic/slither/wiki/Printer-documentation) for the complete lists.

## Tools

* `slither-check-upgradeability`: [Review `delegatecall`-based upgradeability](./docs/src/tools/Upgradeability-Checks.md)
* `slither-prop`: [Automatic unit test and property generation](./docs/src/tools/Property-generation.md)
* `slither-flat`: [Flatten a codebase](./docs/src/tools/Contract-Flattening.md)
* `slither-check-erc`: [Check the ERC's conformance](./docs/src/tools/ERC-Conformance.md)
* `slither-read-storage`: [Read storage values from contracts](./docs/src/tools/ReadStorage.md)
* `slither-interface`: [Generate an interface for a contract](./docs/src/tools/Interface.md)

See the [Tool documentation](./docs/src/tools/README.md) for additional tools.

[Contact us](https://www.trailofbits.com/contact/) to get help on building custom tools.

## API Documentation

Documentation on Slither's internals is available [here](https://crytic.github.io/slither/slither.html).

## Getting Help

Feel free to stop by our [Slack channel](https://empireslacking.herokuapp.com) (#ethereum) for help using or extending Slither.

* The [Printer documentation](https://github.com/crytic/slither/wiki/Printer-documentation) describes the information Slither is capable of visualizing for each contract.

* The [Detector documentation](https://github.com/crytic/slither/wiki/Adding-a-new-detector) describes how to write a new vulnerability analyses.

* The [API documentation](https://github.com/crytic/slither/wiki/Python-API) describes the methods and objects available for custom analyses.

* The [SlithIR documentation](https://github.com/crytic/slither/wiki/SlithIR) describes the SlithIR intermediate representation.

## FAQ

How do I exclude mocks or tests?

* View our documentation on [path filtering](https://github.com/crytic/slither/wiki/Usage#path-filtering).

How do I fix "unknown file" or compilation issues?

* Because slither requires the solc AST, it must have all dependencies available.
If a contract has dependencies, `slither contract.sol` will fail.
Instead, use `slither .` in the parent directory of `contracts/` (you should see `contracts/` when you run `ls`).
If you have a `node_modules/` folder, it must be in the same directory as `contracts/`. To verify that this issue is related to slither,
run the compilation command for the framework you are using e.g `npx hardhat compile`. That must work successfully;
otherwise, slither's compilation engine, crytic-compile, cannot generate the AST.

## License

Slither is licensed and distributed under the AGPLv3 license. [Contact us](mailto:opensource@trailofbits.com) if you're looking for an exception to the terms.

## Publications

### Trail of Bits publication

* [Slither: A Static Analysis Framework For Smart Contracts](https://arxiv.org/abs/1908.09878), Josselin Feist, Gustavo Grieco, Alex Groce - WETSEB '19

### External publications

Title | Usage | Authors | Venue | Code
--- | --- | --- | --- | ---
[ReJection: A AST-Based Reentrancy Vulnerability Detection Method](https://www.researchgate.net/publication/339354823_ReJection_A_AST-Based_Reentrancy_Vulnerability_Detection_Method) | AST-based analysis built on top of Slither | Rui Ma, Zefeng Jian, Guangyuan Chen, Ke Ma, Yujia Chen | CTCIS 19 | -
[MPro: Combining Static and Symbolic Analysis for Scalable Testing of Smart Contract](https://arxiv.org/pdf/1911.00570.pdf) | Leverage data dependency through Slither | William Zhang, Sebastian Banescu, Leodardo Pasos, Steven Stewart, Vijay Ganesh | ISSRE 2019 | [MPro](https://github.com/QuanZhang-William/M-Pro)
[ETHPLOIT: From Fuzzing to Efficient Exploit Generation against Smart Contracts](https://wcventure.github.io/FuzzingPaper/Paper/SANER20_ETHPLOIT.pdf) | Leverage data dependency through Slither | Qingzhao Zhang, Yizhuo Wang, Juanru Li, Siqi Ma | SANER 20 | -
[Verification of Ethereum Smart Contracts: A Model Checking Approach](http://www.ijmlc.org/vol10/977-AM0059.pdf) | Symbolic execution built on top of Slither’s CFG | Tam Bang, Hoang H Nguyen, Dung Nguyen, Toan Trieu, Tho Quan | IJMLC 20 | -
[Smart Contract Repair](https://arxiv.org/pdf/1912.05823.pdf) | Rely on Slither’s vulnerabilities detectors | Xiao Liang Yu, Omar Al-Bataineh, David Lo, Abhik Roychoudhury | TOSEM 20 | [SCRepair](https://github.com/xiaoly8/SCRepair/)
[Demystifying Loops in Smart Contracts](https://www.microsoft.com/en-us/research/uploads/prod/2020/08/loops_solidity__camera_ready-5f3fec3f15c69.pdf) | Leverage data dependency through Slither | Ben Mariano, Yanju Chen, Yu Feng, Shuvendu Lahiri, Isil Dillig | ASE 20 | -
[Trace-Based Dynamic Gas Estimation of Loops in Smart Contracts](https://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=9268144) | Use Slither’s CFG to detect loops | Chunmiao Li, Shijie Nie, Yang Cao, Yijun Yu, Zhenjiang Hu | IEEE Open J. Comput. Soc. 1 (2020) | -
[SAILFISH: Vetting Smart Contract State-Inconsistency Bugs in Seconds](https://arxiv.org/pdf/2104.08638.pdf) | Rely on SlithIR to build a *storage dependency graph* | Priyanka Bose, Dipanjan Das, Yanju Chen, Yu Feng, Christopher Kruegel, and Giovanni Vigna | S&P 22 | [Sailfish](https://github.com/ucsb-seclab/sailfish)
[SolType: Refinement Types for Arithmetic Overflow in Solidity](https://arxiv.org/abs/2110.00677) | Use Slither as frontend to build refinement type system | Bryan Tan, Benjamin Mariano, Shuvendu K. Lahiri, Isil Dillig, Yu Feng | POPL 22 | -
[Do Not Rug on Me: Leveraging Machine Learning Techniques for Automated Scam Detection](https://www.mdpi.com/2227-7390/10/6/949) | Use Slither to extract tokens' features (mintable, pausable, ..) | Mazorra, Bruno, Victor Adan, and Vanesa Daza | Mathematics 10.6 (2022) | -
[MANDO: Multi-Level Heterogeneous Graph Embeddings for Fine-Grained Detection of Smart Contract Vulnerabilities](https://arxiv.org/abs/2208.13252) | Use Slither to extract the CFG and call graph | Hoang Nguyen, Nhat-Minh Nguyen, Chunyao Xie, Zahra Ahmadi, Daniel Kudendo, Thanh-Nam Doan and Lingxiao Jiang| IEEE 9th International Conference on Data Science and Advanced Analytics (DSAA, 2022) | [ge-sc](https://github.com/MANDO-Project/ge-sc)
[Automated Auditing of Price Gouging TOD Vulnerabilities in Smart Contracts](https://www.cs.toronto.edu/~fanl/papers/price-icbc22.pdf) | Use Slither to extract the CFG and data dependencies| Sidi Mohamed Beillahi, Eric Keilty, Keerthi Nelaturu, Andreas Veneris, and Fan Long | 2022 IEEE International Conference on Blockchain and Cryptocurrency (ICBC) | [Smart-Contract-Repair](https://github.com/Veneris-Group/TOD-Location-Rectification)
[Modeling and Enforcing Access Control Policies for Smart Contracts](https://publikationen.bibliothek.kit.edu/1000152805/151859658) | Extend Slither's data dependencies | Jan-Philipp Toberg, Jonas Schiffl, Frederik Reiche, Bernhard Beckert, Robert Heinrich, Ralf Reussner | IEEE International Conference on Decentralized Applications and Infrastructures (DAPPS), 2022  | [SolidityAccessControlEnforcement](https://github.com/KASTEL-CSSDA/SolidityAccessControlEnforcement)
[Smart Contract Vulnerability Detection Based on Deep Learning and Multimodal Decision Fusion](https://www.mdpi.com/1424-8220/23/16/7246) | Use Slither to extract the CFG | Weichu Deng, Huanchun Wei, Teng Huang, Cong Cao, Yun Peng, and Xuan Hu | Sensors 2023, 23, 7246 | -
[Semantic-enriched Code Knowledge Graph to Reveal Unknowns in Smart Contract Code Reuse](https://www.researchgate.net/profile/Qing-Huang-26/publication/370638129_Semantic-enriched_Code_Knowledge_Graph_to_Reveal_Unknowns_in_Smart_Contract_Code_Reuse/links/645b7b8639c408339b3a54da/Semantic-Enriched-Code-Knowledge-Graph-to-Reveal-Unknowns-in-Smart-Contract-Code-Reuse.pdf) | Use Slither to extract the code features (CFG, function, parameters types, ..) | Qing Huang, Dianshu Liao, Zhenchang Xing, Zhengkang Zuo, Changjing Wang, Xin Xia | ACM Transactions on Software Engineering and Methodology, 2023 | -
[Smart Contract Parallel Execution with Fine-Grained State Accesses](https://personal.ntu.edu.sg/yi_li/files/Qi2023SCP.pdf) | Use Slither to build state access graphs | Xiaodong Qi, Jiao Jiao, Yi Li | International Conference on Distributed Computing Systems (ICDCS), 2023 | -
[Bad Apples: Understanding the Centralized Security Risks in Decentralized Ecosystems](https://diaowenrui.github.io/paper/www23-yan.pdf) | Implement an internal analysis on top of Slither | Kailun Yan , Jilian Zhang , Xiangyu Liu , Wenrui Diao , Shanqing Guo | ACM Web Conference April 2023 | -
[Identifying Vulnerabilities in Smart Contracts using Interval Analysis](https://arxiv.org/pdf/2309.13805.pdf) | Create 4 detectors on top of Slither | Ştefan-Claudiu Susan, Andrei Arusoaie | FROM 2023 | -
Storage State Analysis and Extraction of Ethereum Blockchain Smart Contracts (no PDF in open access) | Rely on Slither's CFG and AST | Maha Ayub , Tania Saleem , Muhammad Janjua , Talha Ahmad | TOSEM 2023 | [SmartMuv](https://github.com/WaizKhan7/SmartMuv)

If you are using Slither on an academic work, consider applying to the [Crytic $10k Research Prize](https://blog.trailofbits.com/2019/11/13/announcing-the-crytic-10k-research-prize/).

---

### Overview (`plugin_example/README.md`)

# Slither, Plugin Example

This repository contains an example of plugin for Slither.

See the [detector documentation](https://github.com/trailofbits/slither/wiki/Adding-a-new-detector).

## Architecture

- `pyproject.toml`: Contains the plugin information and dependencies
- `slither_my_plugin/__init__.py`: Contains `make_plugin()`. The function must return the list of new detectors and printers
- `slither_my_plugin/detectors/example.py`: Detector plugin skeleton.

## Installation

Once these files are updated with your plugin, install it:

```bash
uv sync
uv run slither --help  # Verify plugin is loaded
```

---

### Overview (`docs/src/README.md`)

# [Slither, the smart contract static analyzer](https://crytic.github.io/slither/slither.html)

<img src="https://raw.githubusercontent.com/crytic/slither/master/logo.png" alt="Slither Static Analysis Framework Logo" width="500" />

[**Slither**](https://github.com/crytic/slither) is a Solidity & Vyper static analysis framework written in Python3. It runs a suite of vulnerability detectors, prints visual information about contract details, and provides an API to easily write custom analyses. Slither enables developers to find vulnerabilities, enhance their code comprehension, and quickly prototype custom analyses.

If you are looking to use Slither's cli:

- [Usage](./Usage.md) the most common flags

If you are looking to leverage Slither inbuilt features:

- [Detectors](./detectors/): Vulnerabilities detectors
- [Printers](./printers): Printers (code vizualiation)
- [Tools](./tools): Custom tools

If you are looking to learn how to extend Slither's capabilities:

- [API](./api): Introduction to static analysis & Slither's API
- [Tutorial](./tutorials/): Hands-on exercises

---

### Overview (`docs/src/api/README.md`)

# Slither API

Slither is fully customizable:

- [Static Analysis](./static_analysis.md): learn about the basics of static analysis
- [API](./api.md)
- [SlithIR](./SlithIR.md)
- [SSA](./SlithIR-SSA.md)
- [Data dependency](./Data-dependency.md)
- [JSON output](./JSON-output.md)

---

### Overview (`docs/src/tools/README.md`)

# Slither Inbuilt Tools

Slither comes with inbuilt tools

| Name                                                | Command-Line                   | What it Does                                                                                                                                                            |
| --------------------------------------------------- | ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Code Similarity](./Code-Similarity-Detector.md)    | `slither-simil`                | Detects similar Solidity functions/contracts using code similarity analysis. Useful for finding duplicated code, similar vulnerabilities, or analyzing large codebases. |
| [Contract Flattening](./Contract-Flattening.md)     | `slither-flat`                 | Flattens a Solidity codebase by inlining all imports into a single file. Useful for contract verification on Etherscan or debugging.                                    |
| [Documentation](./Documentation.md)                 | `slither-doc`                  | Automatically generates documentation for Solidity contracts, including inheritance information, functions, modifiers, and more.                                        |
| [Doctor](./Doctor.md)                               | `slither-doctor`               | Helps diagnose and fix common issues in your environment that might prevent Slither from working correctly.                                                             |
| [ERC Conformance](./ERC-Conformance.md)             | `slither-check-erc`            | Validates whether a contract correctly implements various ERC standards (ERC20, ERC721, etc.) by checking required functions and their signatures.                      |
| [Interface](./Interface.md)                         | `slither-interface`            | Generates Solidity interfaces from contract implementations, useful for creating minimal interfaces for contract interactions.                                          |
| [Mutator](./Mutator.md)                             | `slither-mutate`               | Performs mutation testing on Solidity contracts by automatically generating variants with small modifications to test suite effectiveness.                              |
| [Path Finding](./Path-Finding-Utility.md)           | `slither-prop`                 | Analyzes call paths between functions in smart contracts to understand control and data flow.                                                                           |
| [Property Generation](./Property-generation.md)     | `slither-prop`                 | Automatically generates security properties and unit tests for smart contracts based on their behavior.                                                                 |
| [Read Storage](./ReadStorage.md)                    | `slither-read-storage`         | Reads contract storage values directly from the blockchain, helping debug deployed contracts.                                                                           |
| [Format](./Slither-format.md)                       | `slither-format`               | Automatically patch bugs.                                                                                                                                               |
| [Upgradeability Checks](./Upgradeability-Checks.md) | `slither-check-upgradeability` | Analyzes upgradeable contracts for common issues and vulnerabilities in proxy patterns.                                                                                 |

---

### Overview (`docs/src/tutorials/README.md`)

# Slither

The objective of this tutorial is to demonstrate how to use Slither to automatically find bugs in smart contracts.

- [Installation](#installation)
- [Command-line usage](#command-line)
- [Introduction to static analysis](./static_analysis.md): A concise introduction to static analysis
- [API](../api/api.md): Python API description

Once you feel confident with the material in this README, proceed to the exercises:

- [Exercise 1](./exercise1.md): Function override protection
- [Exercise 2](./exercise2.md): Check for access controls
- [Exercise 3](./exercise3.md): Find variable used in conditional statements

Watch Slither's [code walkthrough](https://www.youtube.com/watch?v=EUl3UlYSluU), or [API walkthrough](https://www.youtube.com/watch?v=Ijf0pellvgw) to learn about its code structure.

## Installation

Slither requires Python >= 3.9. You can install it through pip or by using Docker.

Installing Slither through pip:

```bash
pip3 install --user slither-analyzer
```

### Docker

Installing Slither through Docker:

```bash
docker pull trailofbits/eth-security-toolbox
docker run -it -v "$PWD":/home/trufflecon trailofbits/eth-security-toolbox
```

_The last command runs the eth-security-toolbox in a Docker container that has access to your current directory. You can modify the files from your host, and run the tools on the files from the Docker container._

Inside the Docker container, run:

```bash
solc-select 0.5.11
cd /home/trufflecon/
```

## Command-line

**Command-line vs. user-defined scripts.** Slither comes with a set of predefined detectors that can identify many common bugs. Running Slither from the command-line will execute all the detectors without requiring detailed knowledge of static analysis:

```bash
slither project_paths
```

Besides detectors, Slither also offers code review capabilities through its [printers](https://github.com/crytic/slither#printers) and [tools](https://github.com/crytic/slither#tools).

---

### Overview (`slither/tools/demo/README.md`)

# Demo

This directory contains an example of Slither utility.

See the [utility documentation](https://github.com/crytic/slither/wiki/Adding-a-new-utility)

---

### Overview (`tests/e2e/compilation/test_data/test_change/README.md`)

# Foundry

To init this test case, run `forge install --no-commit --no-git foundry-rs/forge-std`

---

### Overview (`tests/e2e/compilation/test_data/test_source_unit/README.md`)

# README

Before using this project, run `forge init --no-git --no-commit --force` to initialize submodules

---

### Overview (`tests/e2e/printers/test_data/test_printer_cheatcode/README.md`)

# Counter

Init using :

```shell
forge install foundry-rs/forge-std
```

---

### Overview (`tests/tools/mutator/test_data/test_source_unit/README.md`)

# Counter

Init using :

```shell
forge install --no-commit --no-git .
```

---

### Src SUMMARY (`docs/src/SUMMARY.md`)

# Summary

- [Introduction](./README.md)
- [Usage](./Usage.md)
- [API](./api/README.md)
  - [Static Analysis](./api/static_analysis.md)
  - [API](./api/api.md)
  - [SlithIR](./api/SlithIR.md)
  - [SSA](./api/SlithIR-SSA.md)
  - [Data dependency](./api/Data-dependency.md)
  - [JSON output](./api/JSON-output.md)
- [Detectors](./detectors/Detector-Documentation.md)
  - [Detectors](./detectors/Detector-Documentation.md)
  - [Adding a detector](./detectors/Adding-a-new-detector.md)
- [Printers](./printers/Printer-documentation.md)
- [Tools](./tools/README.md)
  - [Adding a new tool](./tools/Adding-a-new-utility.md)
  - [Code Similarity](./tools/Code-Similarity-Detector.md)
  - [Contract Flattening](./tools/Contract-Flattening.md)
  - [Documentation](./tools/Documentation.md)
  - [Doctor](./tools/Doctor.md)
  - [ERC Conformance](./tools/ERC-Conformance.md)
  - [Interface](./tools/Interface.md)
  - [Mutator](./tools/Mutator.md)
  - [Path Finding Utility](./tools/Path-Finding-Utility.md)
  - [Property Generation](./tools/Property-generation.md)
  - [Read Storage](./tools/ReadStorage.md)
  - [Format](./tools/Slither-format.md)
  - [Upgradeability checks](./tools/Upgradeability-Checks.md)
- [Tutorials](./tutorials/README.md)
  - [Exercise 1](./tutorials/exercise1.md)
  - [Exercise 2](./tutorials/exercise2.md)
  - [Exercise 3](./tutorials/exercise3.md)

---

### Src Usage (`docs/src/Usage.md`)

# Usage

- [How to run Slither](#how-to-run-slither)
  - [Foundry/hardhat](#foundryhardhat)
  - [solc](#solc)
  - [Etherscan](#etherscan)
- [Detector selection](#detector-selection)
- [Printer selection](#printer-selection)
- [Path filtering](#path-filtering)
- [Suppressing findings](#suppressing-findings)
- [Triage mode](#triage-mode)
- [Configuration File](#configuration-file)

## How to run Slither

All the [`crytic-compile`](https://github.com/crytic/crytic-compile/wiki/Configuration) options are available through Slither.

### Foundry/hardhat

To run Slither on a Foundry/hardhat directory:

```sh
slither .
```

### solc

To run Slither from a Solidity file:

```sh
slither file.sol
```

### Etherscan

To run Slither from a contract hosted on Etherscan, run

```sh
slither 0x7F37f78cBD74481E593F9C737776F7113d76B315
```

We recommend installing [solc-select](https://github.com/crytic/solc-select/) so Slither can switch to the expected solc version automatically.

### Detector selection

Slither runs all its detectors by default.

To run only selected detectors, use `--detect detector1,detector2`. For example:

```sh
slither file.sol --detect arbitrary-send,pragma
```

To exclude detectors, use `--exclude detector1,detector2`. For example:

```sh
slither file.sol --exclude naming-convention,unused-state,suicidal
```

To exclude detectors with an informational or low severity, use `--exclude-informational` or `--exclude-low`.

`--list-detectors` lists [available detectors](https://github.com/crytic/slither/wiki/Detector-Documentation).

### Printer selection

By default, no printers are run.

To run selected printers, use `--print printer1,printer2`. For example:

```sh
slither file.sol --print inheritance-graph
```

`--list-printers` lists [available printers](https://github.com/crytic/slither/wiki/Printer-Documentation).

### Path filtering

`--filter-paths path1` will exclude all the results that are only related to `path1`. The path specified can be a path directory or a filename. Direct string comparison and [Python regular expression](https://docs.python.org/3/library/re.html) are used.

Examples:

```sh
slither . --filter-paths "openzepellin"
```

Filter all the results only related to openzepellin.

```bash
slither . --filter-paths "SafeMath.sol|ConvertLib.sol"
```

Filter all the results only related to the file `SafeMath.sol` or `ConvertLib.sol`.

### Suppressing findings

Slither offers several ways to suppress results:

- By adding `//slither-disable-next-line DETECTOR_NAME` before the issue
- By adding `// slither-disable-start [detector] ... // slither-disable-end [detector]` around the code to disable the detector on a large section
- By adding `@custom:security non-reentrant` before the variable declaration will indicate to Slither that the external calls from this variable are non-reentrant
- By running the triage mode (see below)

### Triage mode

`--triage-mode` runs Slither in its triage mode. For every finding, Slither will ask if the result should be shown for the next run. Results are saved in `slither.db.json`.

Examples:

```sh
slither . --triage-mode
[...]
0: C.destination (test.sol#3) is never initialized. It is used in:
 - f (test.sol#5-7)
Reference: https://github.com/trailofbits/slither/wiki/Vulnerabilities-Description#uninitialized-state-variables
Results to hide during next runs: "0,1,..." or "All" (enter to not hide results):  0
[...]
```

The second run of Slither will hide the above result.

To show the hidden results again, delete `slither.db.json`.

### Configuration File

Some options can be set through a json configuration file. By default, `slither.config.json` is used if present, with `slither.conf.json` accepted as an alternative (it can be changed through `--config-file file.config.json`).

Options passed via the CLI have priority over options set in the configuration file.

The following flags are supported:

```sh
{
    "detectors_to_run": "all",
    "printers_to_run": None,
    "detectors_to_exclude": None,
    "detectors_to_include": None,
    "exclude_dependencies": False,
    "exclude_informational": False,
    "exclude_optimization": False,
    "exclude_low": False,
    "exclude_medium": False,
    "exclude_high": False,
    "fail_on": FailOnLevel.PEDANTIC,
    "json": None,
    "sarif": None,
    "disable_color": False,
    "filter_paths": None,
    "include_paths": None,
    "generate_patches": False,
    "skip_assembly": False,
    "legacy_ast": False,
    "zip": None,
    "zip_type": "lzma",
    "show_ignored_findings": False,
    "sarif_input": "export.sarif",
    "sarif_triage": "export.sarif.sarifexplorer",
    "triage_database": "slither.db.json",
}
```

For flags related to the compilation, see the [`crytic-compile` configuration](https://github.com/crytic/crytic-compile/blob/master/crytic_compile/cryticparser/defaults.py)

---

### Src Api Data Dependency (`docs/src/api/Data-dependency.md`)

# Data dependency

Data dependency allows knowing if the value of a given variable is influenced by another variable's value.

Because smart contracts have a state machine based architecture, the results of the data dependency depend on the context (function/contract) of the analysis. Consider the following example:

```solidity
contract MyContract{
    uint a = 0;
    uint b = 0;

    function setA(uint input_a) public{
        a = input_a;
    }

    function setB() public{
        b = a;
    }

}
```

In this example, if we consider only `setA`, we have the following dependency:

- `a` is dependent on `input_a`

If we consider only `setB`, we have:

- `b` is dependent on `a`

If we consider the contract entirely (with all the functions), we have:

- `a` is dependent on `input_a`
- `b` is dependent on `a` and `input_a` (by transitivity)

`slither.analyses.is_dependent(variable, variable_source, context)` allows to know if `variable` is dependent on `variable_source` on the given context.

As a result, in our previous example, `is_dependent(b, a, funcA)` will return `False`, while `is_dependent(b, a, myContract)` will return `True`:

```python
from slither import Slither
from slither.analyses import is_dependent

slither = Slither('data_dependency_simple_example.sol')

myContract = slither.get_contract_from_name('MyContract')
funcA = myContract.get_function_from_signature('setA(uint256)')
input_a = funcA.parameters[0]

a = myContract.get_state_variable_from_name('a')
b = myContract.get_state_variable_from_name('b')

print(f'{b.name} is dependant from {input_a.name}?: {is_dependent(b, a, funcA)}')
print(f'{b.name} is dependant from {input_a.name}?: {is_dependent(b, a, myContract)}')
```

---

### Src Api JSON Output (`docs/src/api/JSON-output.md`)

# JSON Output

- [Top-level Command Output](https://github.com/crytic/slither/wiki/JSON-output#top-level-command-output): Standard top-level (for detectors, printers and tools)
- [Detectors output](https://github.com/crytic/slither/wiki/JSON-output#detector-results)
- [Upgradeability output](https://github.com/crytic/slither/wiki/JSON-output#slither-check-upgradeability)

## Top-level Command Output

At the top level, the JSON output provided by slither will appear in the following format:

```json
{
  "success": true,
  "error": null,
  "results": {}
}
```

- `success` (boolean): `true` if `results` were output successfully, `false` if an `error` occurred.
- `error` (string | null): If `success` is `false`, this will be a string with relevant error information. Otherwise, it will be `null`.
- `results` (command-results, see below): If `success` is `true`, this will be an object populated with different types of results, depending on the JSON arguments specified.

## Command Results

The underlying `results` item above will appear in the following format:

```json
{
  "detectors": [],
  "upgradeability-check": {}
}
```

- `detectors` (OPTIONAL, vulnerability-results, see below): The results of any detector analysis.
- `upgradeability-check` (OPTIONAL, upgradeability-results, see below): The results of `slither-check-upgradeability`.

## Detector Results

A detector result found in the `detectors` array above will be of the following format:

```json
{
 "check": "...",
 "impact": "...",
 "confidence": "...",
 "description": "...",
 "elements": []
}
```

- `check` (string): The detector identifier (see the [list of detectors](https://github.com/trailofbits/slither#detectors))
- `impact` (string): representation of the impact (`High`/ `Medium`/ `Low`/ `Informational`)
- `confidence` (string): representation of the confidence (`High`/ `Medium`/ `Low`)
- `description` (string): output of the slither
- `elements`: (element array, see below): an array of relevant items for this finding which map to some source code.
  - NOTE: When writing a detector, the first element should be carefully chosen to represent the most significant portion of mapped code for the finding (the area of source on which external tooling should primarily focus for the issue).
- `additional_fields`: (OPTIONAL, any): Offers additional detector-specific information, does not always exist.

## Detector Result Elements

Each element found in `elements` above is of the form:

```json
{
  "type": "...",
  "name": "...",
  "source_mapping": {},
  "type_specific_fields": {},
  "additional_fields": {}
}
```

- `type` (string): Refers to the type of element, this can be either: (`contract`, `function`, `variable`, `node`, `pragma`, `enum`, `struct`, `event`).
- `name` (string): Refers to the name of the element.
  - For `contract`/`function`/`variable`/`enum`/`struct`/`event` types, this refers to the definition name.
  - For `node` types, this refers to a string representation of any underlying expression. A blank string is used if there is no underlying expression.
  - For `pragma` types, this refers to a string representation of the `version` portion of the pragma (ie: `^0.5.0`).
- `source_mapping` (source mapping, see below): Refers to a source mapping object which defines the source range which represents this element.
- `type_specific_fields` (OPTIONAL, any):
  - For `function`/`event` type elements:
    - `parent` (result-element): Refers to the parent contract of this definition.
    - `signature` (string): Refers to the full signature of this function
  - For `enum`/`struct` type elements:
    - `parent` (result-element): Refers to the parent contract of this definition.
  - For `variable` type elements:
    - `parent` (result-element): Refers to the parent contract if this variable is a state variable. Refers to the parent function if this variable is a local variable.
  - For `node` type elements:
    - `parent` (result-element): Refers to the parent function of this node.
  - For `pragma` type elements:
    - `directive` (string array): Fully serialized pragma directive (ie: `["solidity", "^", "0.4", ".9"]`)
- `additional_fields` (OPTIONAL, any): Offers additional detector-specific element information, does not always exist.

## Source Mapping

Each `source_mapping` object is used to map an element to some portion of source. It is of the form:

```json
"source_mapping": {
 "start": 45
 "length": 58,
 "filename_relative": "contracts/tests/constant.sol",
 "filename_absolute": "/tmp/contracts/tests/constant.sol",
 "filename_short": "tests/constant.sol",
 "filename_used": "contracts/tests/constant.sol",
 "lines": [
  5,
  6,
  7
  ],
  "starting_column": 1,
  "ending_column": 24,
}
```

- `start` (integer): Refers to the starting byte position of the mapped source.
- `length` (integer): Refers to the byte-length of the mapped source.
- `filename_relative` (string): A relative file path from the analysis directory.
- `filename_absolute` (string): An absolute file path to the file.
- `filename_short` (string): A short version of the filename used for display purposes. Hides platform-specific directories (ex: `node_modules`).
- `filename_used` (string): The path used by the platform for analysis (non-standard).
- `lines` (integer array): An array of line numbers which the mapped source spans. Line numbers begin from 1.
- `starting_column` (integer): The starting column/character position for the first mapped source line. Begins from 1.
- `ending_column` (integer): The ending column/character position for the last mapped source line. Begins from 1.

## Detector-specific additional fields

Some detectors have custom elements output via the `additional_fields` field of their result, or result elements. Annotations here will specify _result_ or _result-element_ to specify the location of the additional fields.

- `constant-function`:
  - `contain_assembly` (result, boolean): Specifies if the result is due to the function containing assembly.
- `naming-convention`:

  - `convention` (result-element, string): Used to denote the convention used to find the result element/issue. Valid conventions are:
    - `CapWords`
    - `mixedCase`
    - `l_O_I_should_not_be_used`
    - `UPPER_CASE_WITH_UNDERSCORES`
  - `target` (result-element, string): Used to denote the type of finding (constant, parameter, etc). Valid targets are:
    - `contract`
    - `structure`
    - `event`
    - `function`
    - `variable`
    - `variable_constant`
    - `parameter`
    - `enum`
    - `modifier`

- `reentrancy` (all variants):
  - `underlying_type` (result-element, string): Specifies the type of result element. Is one of `external_calls`, `external_calls_sending_eth`, or `variables_written`.

## Slither Check Upgradeability

The `slither-check-upgradeability` tool also produces JSON output (with the use of the `--json` option). At the top level, this JSON output will appear in the format similar to that of Slither above:

```json
{
  "success": true,
  "error": null,
  "results": {
    "upgradeability-check": {}
  }
}
```

- `success` (boolean): `true` if `results` were output successfully, `false` if an `error` occurred.
- `error` (string | null): If `success` is `false`, this will be a string with relevant error information. Otherwise, it will be `null`.
- `results` (upgradeability-check-results, see below): If `success` is `true`, this will contain an `upgradeability-check` object populated with the different upgradeability checks. If `success` is `false`, `upgradeability-check` object will be empty.

## Upgradeability Check Results

The underlying `upgradeability-check` item above will appear in the following format:

```json
{
  "check-initialization": {},
  "check-initialization-v2": {},
  "compare-function-ids": {},
  "compare-variables-order-proxy": {},
  "compare-variables-order-implementation": {}
}
```

---

### Src Api SlithIR SSA (`docs/src/api/SlithIR-SSA.md`)

# SSA

Slither possess a Static Single Assignment (SSA) form representation of SlithIR. SSA is a commonly used representation in compilation and static analysis in general. It requires that each variable is assigned at least one time. SSA is a key component for building an efficient data-dependency analysis.

The [SSA printer](../printers/Printer-documentation.md#slithir-ssa) allows to visualize this representation.

---

### Src Api SlithIR (`docs/src/api/SlithIR.md`)

# SlithIR

Slither translates Solidity an intermediate representation, SlithIR, to enable high-precision analysis via a simple API. It supports taint and value tracking to enable detection of complex patterns.

SlithIR is a work in progress, although it is usable today. New developments in SlithIR are driven by needs identified by new detector modules. Please help us bugtest and enhance SlithIR!

## What is an IR?

In language design, compilers often operate on an “intermediate representation” (IR) of a language that carries extra details about the program as it is parsed. For example, a compiler creates a parse tree of a program that represents a program as written. However, the compiler can continue to enrich this tree with information, such as taint information, source location, and other items that could have impacted an item from control flow. Additionally, languages such as Solidity have inheritance, meaning that functions and methods may be defined outside the scope of a given contract. An IR could linearize these methods, allowing additional transformations and processing of the contract’s source code.

A demonstrative example would be LLVM’s IR vs C or x86 code. While C will clearly demonstrate a function call, it may be missing details about the underlying system, the path to a location, and so on. Likewise, while an analog to the same call would be clear in x86, this would lose all transient details of which variables and which path an application had taken to arrive at a specific call. LLVM’s IR solves this by abstracting away the specific details of a call instruction, while still capturing the variables, environmental state, and other values that lead to this position. In this way, LLVM can perform additional introspection of the resulting code, and use these analyses to drive other optimizations or information to other passes of the compiler.

## Why does Slither translate to an IR?

Solidity is a quirky language with a number of edge cases, both in terms of syntax and semantics. By translating to an IR, Slither normalizes many of these quirks to better analyze the contract. For example, Solidity’s grammar defines an array push as a function call to the array. A straightforward representation of this semantic would be indistinguishable from a normal function call. Slither, in contrast, treats array pushes as a specific operation, allowing further analysis of the accesses to arrays and their impact to the security of a program. Moreover, the operators in SlithIR have a hierarchy, so, for example in a few lines of code you can track all the operators that write to a variable, which makes it trivial to write precise taint analysis.

Additionally, Slither can include non-trivial variable tracking by default by translating to an IR. This can build richer representations of contracts and allow for deeper analysis of potential vulnerabilities. For example, answering the question “can a user control a variable” is central to uncovering more complex vulnerabilities from a static position. Slither will propagate information from function parameters to program state in an iterative fashion, which captures the control flow of information across potentially multiple transactions. In this way, Slither can enrich information and statically provide a large amount of assurance to contracts that standard vulnerabilities exist and are reachable under certain conditions.

## Example

`$ slither file.sol --print slithir` will output the IR for every function.

```sh
$ slither examples/printers/slihtir.sol --printers slithir
Contract UnsafeMath
 Function add(uint256,uint256)
  Expression: a + b
  IRs:
   TMP_0(uint256) = a + b
   RETURN TMP_0
 Function min(uint256,uint256)
  Expression: a - b
  IRs:
   TMP_0(uint256) = a - b
   RETURN TMP_0
Contract MyContract
 Function transfer(address,uint256)
  Expression: balances[msg.sender] = balances[msg.sender].min(val)
  IRs:
   REF_3(uint256) -> balances[msg.sender]
   REF_1(uint256) -> balances[msg.sender]
   TMP_1(uint256) = LIBRARY_CALL, dest:UnsafeMath, function:min, arguments:['REF_1', 'val']
   REF_3 := TMP_1
  Expression: balances[to] = balances[to].add(val)
  IRs:
   REF_3(uint256) -> balances[to]
   REF_1(uint256) -> balances[to]
   TMP_1(uint256) = LIBRARY_CALL, dest:UnsafeMath, function:add, arguments:['REF_1', 'val']
   REF_3 := TMP_1
```

## SlithIR Specification

### Variables

- `StateVariable`
- `LocalVariable`
- `Constant` (`string` or `int`)
- `SolidityVariable`
- `TupleVariable`
- `TemporaryVariable` (variables added by SlithIR)
- `ReferenceVariable` (variables added by SlithIR, for mapping/index accesses)

In the following we use:

- `LVALUE` can be: `StateVariable`, `LocalVariable`, `TemporaryVariable`, `ReferenceVariable` or `TupleVariable`
- `RVALUE` can be: `StateVariable`, `LocalVariable`, `Constant`, `SolidityVariable`, `TemporaryVariable` or `ReferenceVariable`

### Operators

- All the operators inherit from `Operation` and have a `read` attribute returning the list of variables read (see [slither/slithir/operations/operation.py](https://github.com/crytic/slither/blob/master/slither/slithir/operations/operation.py)).
- All the operators writing to a `LVALUE` inherit from `OperationWithLValue` and have the `lvalue` attribute (see [slither/slithir/operations/lvalue.py](https://github.com/crytic/slither/blob/master/slither/slithir/operations/lvalue.py)).

#### Assignment

- `LVALUE := RVALUE`
- `LVALUE := Tuple`
- `LVALUE := Function` (for dynamic function)

#### Binary Operation

- `LVALUE = RVALUE ** RVALUE`
- `LVALUE = RVALUE * RVALUE`
- `LVALUE = RVALUE / RVALUE`
- `LVALUE = RVALUE % RVALUE`
- `LVALUE = RVALUE + RVALUE`
- `LVALUE = RVALUE - RVALUE`
- `LVALUE = RVALUE << RVALUE`
- `LVALUE = RVALUE >> RVALUE`
- `LVALUE = RVALUE & RVALUE`
- `LVALUE = RVALUE ^ RVALUE`
- `LVALUE = RVALUE | RVALUE`
- `LVALUE = RVALUE < RVALUE`
- `LVALUE = RVALUE > RVALUE`
- `LVALUE = RVALUE <= RVALUE`
- `LVALUE = RVALUE >= RVALUE`
- `LVALUE = RVALUE == RVALUE`
- `LVALUE = RVALUE != RVALUE`
- `LVALUE = RVALUE && RVALUE`
- `LVALUE = RVALUE -- RVALUE`

#### Unary Operation

- `LVALUE = ! RVALUE`
- `LVALUE = ~ RVALUE`

#### Index

- `REFERENCE -> LVALUE [ RVALUE ]`

Note: The reference points to the memory location

#### Member

- `REFERENCE -> LVALUE . RVALUE`
- `REFERENCE -> CONTRACT . RVALUE`
- `REFERENCE -> ENUM . RVALUE`

Note: The reference points to the memory location

#### New Operators

- `LVALUE = NEW_ARRAY ARRAY_TYPE DEPTH(:int)`

`ARRAY_TYPE` is a [solidity_types](https://github.com/crytic/slither/tree/master/slither/core/solidity_types)

`DEPTH` is used for arrays of multiple dimensions.

- `LVALUE = NEW_CONTRACT CONSTANT`
- `LVALUE = NEW_STRUCTURE STRUCTURE`
- `LVALUE = NEW_ELEMENTARY_TYPE ELEMENTARY_TYPE`

`ELEMENTARY_TYPE` is defined in [slither/core/solidity_types/elementary_type.py](https://github.com/crytic/slither/blob/master/slither/core/solidity_types/elementary_type.py)

#### Push Operator

- `PUSH LVALUE RVALUE`
- `PUSH LVALUE Function` (for dynamic function)

#### Delete Operator

- `DELETE LVALUE`

#### Conversion

- `CONVERT LVALUE RVALUE TYPE`

TYPE is a [solidity_types](https://github.com/crytic/slither/tree/master/slither/core/solidity_types)

#### Unpack

- `LVALUE = UNPACK TUPLEVARIABLE INDEX(:int)`

#### Array Initialization

- `LVALUE = INIT_VALUES`

`INIT_VALUES` is a list of `RVALUE`, or a list of lists in case of a multidimensional array.

#### Calls Operators

In the following, `ARG` is a variable as defined in [SlithIR#variables](https://github.com/crytic/slither/wiki/SlithIR#variables)

- `LVALUE = HIGH_LEVEL_CALL DESTINATION FUNCTION [ARG, ..]`
- `LVALUE = LOW_LEVEL_CALL DESTINATION FUNCTION_NAME [ARG, ..]`

`FUNCTION_NAME` can only be `call`/`delegatecall`/`codecall`

- `LVALUE = SOLIDITY_CALL SOLIDITY_FUNCTION [ARG, ..]`

`SOLIDITY_FUNCTION` is defined in [slither/core/declarations/solidity_variables.py](https://github.com/crytic/slither/blob/master/slither/core/declarations/solidity_variables.py)

- `LVALUE = INTERNAL_CALL FUNCTION [ARG, ..]`
- `LVALUE = INTERNAL_DYNAMIC_CALL FUNCTION_TYPE [ARG, ..]`

`INTERNAL_DYNAMIC_CALL` represents the pointer of function.

`FUNCTION_TYPE` is defined in [slither/core/solidity_types/function_type.py](https://github.com/crytic/slither/blob/master/slither/core/solidity_types/function_type.py)

- `LVALUE = LIBRARY_CALL DESTINATION FUNCTION_NAME [ARG, ..]`
- `LVALUE = EVENT_CALL EVENT_NAME [ARG, ..]`
- `LVALUE = SEND DESTINATION VALUE`
- `TRANSFER DESTINATION VALUE`

Optional arguments:

- `GAS` and `VALUE` for `HIGH_LEVEL_CALL` / `LOW_LEVEL_CALL`.

#### Return

- `RETURN RVALUE`
- `RETURN TUPLE`
- `RETURN None`

`Return None` represents an empty return statement.

#### Condition

- `CONDITION RVALUE`

`CONDITION` holds the condition in a conditional node.

---

### Src Api Api (`docs/src/api/api.md`)

# API Basics

Slither has an API that allows you to explore basic attributes of contracts and their functions.

On a high level there are 6 layers:

- `Slither` - main slither object
- `SlitherCompilationUnit` - group of files used by one call to solc
- `Contract` - contract level
- `Function` - function level
- `Node` - control flow graph
- `SlithrIR` - intermediate representation

Watch our [API walkthrough](https://www.youtube.com/watch?v=Ijf0pellvgw) for more details

## Slither object

To load a codebase:

```python
from slither import Slither
slither = Slither('/path/to/project')
```

To load a contract deployed:

```python
from slither import Slither
slither = Slither('0x..') # assuming the code is verified on etherscan
```

Use `etherscan_api_key` to provide an [Etherscan API KEY](https://docs.etherscan.io/getting-started/viewing-api-usage-statistics)

```python
slither = Slither('0x..', etherscan_api_key='..')
```

You can retrieve the list of compilation units with:

- `sl.compilation_units # array of SlitherCompilationUnit`

## SlitherCompilationUnit object

- ~ group of files used by one call to solc
- Most targets have 1 compilation, but not always true
  - Partial compilation for optimization
  - Multiple solc version used
  - Etc..
- Why compilation unit matters?
  - Some APIs might be not intuitive
  - Ex: looking for a contract based on the name?
    - Can have multiple contracts
- For hacking you can (probably) use the first compilation unit
  - `compilation_unit = sl.compilation_units[0]`

A [`SlitherCompilationUnit`](https://github.com/crytic/slither/blob/master/slither/core/compilation_unit.py) has:

- `contracts (list(Contract))`: A list of contracts
- `contracts_derived (list(Contract))`: A list of contracts that are not inherited by another contract (a subset of contracts)
- `get_contract_from_name (str)`: Returns a list of contracts matching the name
- `[structures | enums | events | variables | functions]_top_level`: Top level object

Example

```python
from slither import Slither
sl = Slither("0xdac17f958d2ee523a2206206994597c13d831ec7")
compilation_unit = sl.compilation_units[0]

# Print all the contracts from the USDT address
print([str(c) for c in compilation_unit.contracts])

# Print the most derived contracts from the USDT address
print([str(c) for c in compilation_unit.contracts_derived])
```

```bash
% python test.py
['SafeMath', 'Ownable', 'ERC20Basic', 'ERC20', 'BasicToken', 'StandardToken', 'Pausable', 'BlackList', 'UpgradedStandardToken', 'TetherToken']

['SafeMath', 'UpgradedStandardToken', 'TetherToken']
```

## Contract Object

A [`Contract`](https://github.com/crytic/slither/blob/master/slither/core/declarations/contract.py) object has:

- `name: str`: The name of the contract
- `functions: list[Function]`: A list of functions
- `modifiers: list[Modifier]`: A list of modifiers
- `all_functions_called: list[Function/Modifier]`: A list of all internal functions reachable by the contract
- `inheritance: list[Contract]`: A list of inherited contracts (c3 linearization order)
- `derived_contracts: list[Contract]`: contracts derived from it
- `get_function_from_signature(str): Function`: Returns a Function from its signature
- `get_modifier_from_signature(str): Modifier`: Returns a Modifier from its signature
- `get_state_variable_from_name(str): StateVariable`: Returns a StateVariable from its name
- `state_variables: List[StateVariable]`: list of accessible variables
- `state_variables_ordered: List[StateVariable]`: all variable ordered by declaration

Example

```python
from slither import Slither
sl = Slither("0xdac17f958d2ee523a2206206994597c13d831ec7")
compilation_unit = sl.compilation_units[0]

# Print all the state variables of the USDT token
contract = compilation_unit.get_contract_from_name("TetherToken")[0]
print([str(v) for v in contract.state_variables])
```

```bash
% python test.py
['owner', 'paused', '_totalSupply', 'balances', 'basisPointsRate', 'maximumFee', 'allowed', 'MAX_UINT', 'isBlackListed', 'name', 'symbol', 'decimals', 'upgradedAddress', 'deprecated']
```

## Function object

A [`Function`](https://github.com/crytic/slither/blob/master/slither/core/declarations/function.py) or a `Modifier` object has:

- `name: str`: The name of the function
- `contract: Contract`: The contract where the function is declared
- `nodes: list[Node]`: A list of nodes composing the CFG of the function/modifier
- `entry_point: Node`: The entry point of the CFG
- `[state |local]_variable_[read |write]: list[StateVariable]`: A list of local/state variables read/write
  - All can be prefixed by “all\_” for recursive lookup
  - Ex: `all_state_variable_read`: return all the state variables read in internal calls
- `slithir_operations: List[Operation]`: list of IR operations

```python
from slither import Slither
sl = Slither("0xdac17f958d2ee523a2206206994597c13d831ec7")
compilation_unit = sl.compilation_units[0]
contract = compilation_unit.get_contract_from_name("TetherToken")[0]

transfer = contract.get_function_from_signature("transfer(address,uint256)")

# Print all the state variables read by the transfer function
print([str(v) for v in transfer.state_variables_read])
# Print all the state variables read by the transfer function and its internal calls
print([str(v) for v in transfer.all_state_variables_read])
```

```bash
% python test.py
['deprecated', 'isBlackListed', 'upgradedAddress']
['owner', 'basisPointsRate', 'deprecated', 'paused', 'isBlackListed', 'maximumFee', 'upgradedAddress', 'balances']
```

## Node object

[Node](https://github.com/crytic/slither/blob/master/slither/core/cfg/node.py)

To explore the nodes:

- If order does not matter
  - `for node in function.nodes`
- If order matters, walk through the nodes

```python
def visit_node(node: Node, visited: List[Node]):

    if node in visited:
        return
    visited += [node]

    # custom action
    for son in node.sons:
        visit_node(son, visited)
```

- If need to iterate more than once (advanced usages)
- Bound the iteration X times
- Create a fix-point - abstract interpretation style analysis

## SlithIR

- [slither/slithir](https://github.com/crytic/slither/tree/master/slither/slithir)
- Every IR operation has its own methods
- Check if an operation is of a type:
  - `isinstance(ir, TYPE)`
  - Ex: `isinstance(ir, Call)`
- Check if the operation is an addition
- `isinstance(ir, Binary) & ir.type == BinaryType.ADDITION`
- Check if the operation is a call to MyContract
- `isinstance(ir, HighLevelCall) & ir.destination == MyContract`

```python
from slither import Slither
sl = Slither("0xdac17f958d2ee523a2206206994597c13d831ec7")
compilation_unit = sl.compilation_units[0]
contract = compilation_unit.get_contract_from_name("TetherToken")[0]
totalSupply = contract.get_function_from_signature("totalSupply()")

# Print the external call made in the totalSupply function
for ir in totalSupply.slithir_operations:
    if isinstance(ir, HighLevelCall):
        print(f"External call found {ir} ({ir.node.source_mapping})")
```

```bash
% python test.py
External call found HIGH_LEVEL_CALL, […]   (...TetherToken.sol#339)
```

### Example: Print Basic Information

[print_basic_information.py](./examples/print_basic_information.py) demonstrates how to print basic information about a project.

---

### Src Api Static Analysis (`docs/src/api/static_analysis.md`)

# Static analysis

The capabilities and design of the Slither static analysis framework have been described in blog posts ([1](https://blog.trailofbits.com/2018/10/19/slither-a-solidity-static-analysis-framework/), [2](https://blog.trailofbits.com/2019/05/27/slither-the-leading-static-analyzer-for-smart-contracts/)) and an [academic paper](https://github.com/trailofbits/publications/blob/master/papers/wetseb19.pdf).

Static analysis comes in different flavors. You may already know that compilers like [clang](https://clang-analyzer.llvm.org/) and [gcc](https://lwn.net/Articles/806099/) rely on these research techniques, as do tools like [Infer](https://fbinfer.com/), [CodeClimate](https://codeclimate.com/), [FindBugs](http://findbugs.sourceforge.net/), and tools based on formal methods like [Frama-C](https://frama-c.com/) and [Polyspace](https://www.mathworks.com/products/polyspace.html).

In this article, we will not provide an exhaustive review of static analysis techniques and research. Instead, we'll focus on what you need to understand about how Slither works, so you can more effectively use it to find bugs and understand code.

- [Code representation](#code-representation)
- [Code analysis](#analysis)
- [Intermediate representation](#intermediate-representation)

## Code representation

Unlike dynamic analysis, which reasons about a single execution path, static analysis reasons about all paths at once. To do so, it relies on a different code representation. The two most common ones are the abstract syntax tree (AST) and the control flow graph (CFG).

### Abstract Syntax Trees (AST)

ASTs are used every time a compiler parses code. They are arguably the most basic structure upon which static analysis can be performed.

In a nutshell, an AST is a structured tree where, usually, each leaf contains a variable or a constant, and internal nodes are operands or control flow operations. Consider the following code:

```solidity
function safeAdd(uint256 a, uint256 b) internal pure returns (uint256) {
    if (a + b <= a) {
        revert();
    }
    return a + b;
}
```

The corresponding AST is shown in the following illustration:



Slither uses the AST exported by solc.

While simple to build, the AST is a nested structure that's not always straightforward to analyze. For example, to identify the operations used by the expression `a + b <= a`, you must first analyze `<=` and then `+`. A common approach is to use the so-called visitor pattern, which navigates through the tree recursively. Slither contains a generic visitor in [`ExpressionVisitor`](https://github.com/crytic/slither/blob/master/slither/visitors/expression/expression.py).

The following code uses `ExpressionVisitor` to detect if an expression contains an addition:

```python
from slither.visitors.expression.expression import ExpressionVisitor
from slither.core.expressions.binary_operation import BinaryOperationType

class HasAddition(ExpressionVisitor):

    def result(self):
        return self._result

    def _post_binary_operation(self, expression):
        if expression.type == BinaryOperationType.ADDITION:
            self._result = True

visitor = HasAddition(expression) # expression is the expression to be tested
print(f'The expression {expression} has an addition: {visitor.result()}')
```

### Control Flow Graph (CFG)

The second most common code representation is the control flow graph (CFG). As its name suggests, it is a graph-based representation that reveals all the execution paths. Each node contains one or multiple instructions, and edges in the graph represent control flow operations (if/then/else, loop, etc). The CFG of our previous example is as follows:



Most analyses are built on top of the CFG representation.

There are many other code representations, each with its advantages and drawbacks depending on the desired analysis.

### Analysis

The simplest types of analyses that can be performed with Slither are syntactic analyses.

### Syntax analysis

Slither can navigate through the different components of the code and their representation to find inconsistencies and flaws using a pattern matching-like approach.

For example, the following detectors look for syntax-related issues:

- [State variable shadowing](../detectors/Detector-Documentation.md#state-variable-shadowing): iterates over all state variables and checks if any shadow a variable from an inherited contract ([state.py#L51-L62](https://github.com/crytic/slither/blob/0441338e055ab7151b30ca69258561a5a793f8ba/slither/detectors/shadowing/state.py#L51-L62))

- [Incorrect ERC20 interface](./detectors/Detector-Documentation.md#incorrect-erc20-interface): searches for incorrect ERC20 function signatures ([incorrect_erc20_interface.py#L34-L55](https://github.com/crytic/slither/blob/0441338e055ab7151b30ca69258561a5a793f8ba/slither/detectors/erc/incorrect_erc20_interface.py#L34-L55))

### Semantic analysis

In contrast to syntax analysis, semantic analysis delves deeper and analyzes the "meaning" of the code. This category includes a broad range of analyses that yield more powerful and useful results but are more complex to write.

Semantic analyses are used for advanced vulnerability detection.

#### Data dependency analysis

A variable `variable_a` is said to be data-dependent on `variable_b` if there is a path for which the value of `variable_a` is influenced by `variable_b`.

In the following code, `variable_a` is dependent on `variable_b`:

```solidity
// ...
variable_a = variable_b + 1;
```

Slither comes with built-in [data dependency](./Data-dependency.md) capabilities, thanks to its intermediate representation (discussed later).

An example of data dependency usage can be found in the [dangerous strict equality detector](./detectors/Detector-Documentation.md#dangerous-strict-equalities). Slither looks for strict equality comparisons to dangerous values ([incorrect_strict_equality.py#L86-L87](https://github.com/crytic/slither/blob/6d86220a53603476f9567c3358524ea4db07fb25/slither/detectors/statements/incorrect_strict_equality.py#L86-L87)) and informs the user that they should use `>=` or `<=` instead of `==` to prevent attackers from trapping the contract. Among other things, the detector considers the return value of a call to `balanceOf(address)` to be dangerous ([incorrect_strict_equality.py#L63-L64](https://github.com/crytic/slither/blob/6d86220a53603476f9567c3358524ea4db07fb25/slither/detectors/statements/incorrect_strict_equality.py#L63-L64)) and uses the data dependency engine to track its usage.

#### Fixed-point computation

If your analysis navigates through the CFG and follows the edges, you're likely to encounter already visited nodes. For example, if a loop is presented as shown below:

```solidity
for(uint256 i; i < range; ++) {
    variable_a += 1;
}
```

Your analysis will need to know when to stop. There are two main strategies: (1) iterate on each node a finite number of times, (2) compute a so-called _fixpoint_. A fixpoint essentially means that analyzing the node doesn't provide any meaningful information.

An example of a fixpoint used can be found in the reentrancy detectors: Slither explores the nodes and looks for external calls, reads, and writes to storage. Once it has reached a fixpoint ([reentrancy.py#L125-L131](https://github.com/crytic/slither/blob/master/slither/detectors/reentrancy/reentrancy.py#L125-L131)), it stops the exploration and analyzes the results to see if a reentrancy is present, through different reentrancy patterns ([reentrancy_benign.py](https://github.com/crytic/slither/blob/b275bcc824b1b932310cf03b6bfb1a1fef0ebae1/slither/detectors/reentrancy/reentrancy_benign.py), [reentrancy_read_before_write.py](https://github.com/crytic/slither/blob/b275bcc824b1b932310cf03b6bfb1a1fef0ebae1/slither/detectors/reentrancy/reentrancy_read_before_write.py), [reentrancy_eth.py](https://github.com/crytic/slither/blob/b275bcc824b1b932310cf03b6bfb1a1fef0ebae1/slither/detectors/reentrancy/reentrancy_eth.py)).

Writing analyses using efficient fixed-point computation requires a good understanding of how the analysis propagates its information.

### Intermediate representation

An intermediate representation (IR) is a language designed to be more amenable to static analysis than the original one. Slither translates Solidity to its own IR: [SlithIR](./SlithIR.md).

Understanding SlithIR is not necessary if you only want to write basic checks. However, it becomes essential if you plan to write advanced semantic analyses. The [SlithIR](../printers/Printer-documentation.md#slithir) and [SSA](../printers/Printer-documentation.md#slithir-ssa) printers can help you understand how the code is translated.

---

### Src Detectors Adding A New Detector (`docs/src/detectors/Adding-a-new-detector.md`)

# Adding New Detectors

Slither's plugin architecture lets you integrate new detectors that run from the command-line.

## Detector Skeleton

The skeleton for a detector is:

```python
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification


class Skeleton(AbstractDetector):
    """
    Documentation
    """

    ARGUMENT = 'mydetector' # slither will launch the detector with slither.py --detect mydetector
    HELP = 'Help printed by slither'
    IMPACT = DetectorClassification.HIGH
    CONFIDENCE = DetectorClassification.HIGH

    WIKI = ''

    WIKI_TITLE = ''
    WIKI_DESCRIPTION = ''
    WIKI_EXPLOIT_SCENARIO = ''
    WIKI_RECOMMENDATION = ''

    def _detect(self):
        info = ['This is an example']
        res = self.generate_result(info)

        return [res]
```

- `ARGUMENT` lets you run the detector from the command-line
- `HELP` is the information printed from the command-line
- `IMPACT` indicates the impact of the issue. Allowed values are:
  - `DetectorClassification.OPTIMIZATION`: printed in green
  - `DetectorClassification.INFORMATIONAL`: printed in green
  - `DetectorClassification.LOW`: printed in green
  - `DetectorClassification.MEDIUM`: printed in yellow
  - `DetectorClassification.HIGH`: printed in red
- `CONFIDENCE` indicates your confidence in the analysis. Allowed values are:
  - `DetectorClassification.LOW`
  - `DetectorClassification.MEDIUM`
  - `DetectorClassification.HIGH`
- `WIKI` constants are used to generate automatically the documentation.

`_detect()` needs to return a list of findings. A finding is an element generated with `self.generate_result(info)`, where `info` is a list of text or contract's object (contract, function, node, ...)

An `AbstractDetector` object has the `slither` attribute, which returns the current `Slither` object.

## Integration

You can integrate your detector into Slither by:

- Adding it in [slither/detectors/all_detectors.py](https://github.com/trailofbits/slither/blob/ae7c410938b616d993e6c27678f6e48d9a4d7dd6/slither/detectors/all_detectors.py)
- or, by creating a plugin package (see the [skeleton example](https://github.com/trailofbits/slither/tree/ae7c410938b616d993e6c27678f6e48d9a4d7dd6/plugin_example)).

### Test the detector

See [CONTRIBUTING.md#development-environment](https://github.com/crytic/slither/blob/master/CONTRIBUTING.md#development-environment)

## Example

[backdoor.py](https://github.com/crytic/slither/blob/ae7c410938b616d993e6c27678f6e48d9a4d7dd6/slither/detectors/examples/backdoor.py) will detect any function with `backdoor` in its name.

---

### Src Detectors Detector Documentation (`docs/src/detectors/Detector-Documentation.md`)

# Public Detectors

List of public detectors

## Storage ABIEncoderV2 Array

### Configuration

* Check: `abiencoderv2-array`
* Severity: `High`
* Confidence: `High`

### Description

`solc` versions `0.4.7`-`0.5.9` contain a [compiler bug](https://blog.ethereum.org/2019/06/25/solidity-storage-array-bugs) leading to incorrect ABI encoder usage.

### Exploit Scenario

```solidity
contract A {
    uint[2][3] bad_arr = [[1, 2], [3, 4], [5, 6]];

    /* Array of arrays passed to abi.encode is vulnerable */
    function bad() public {
        bytes memory b = abi.encode(bad_arr);
    }
}
```

`abi.encode(bad_arr)` in a call to `bad()` will incorrectly encode the array as `[[1, 2], [2, 3], [3, 4]]` and lead to unintended behavior.

### Recommendation

Use a compiler >= `0.5.10`.

## Arbitrary `from` in transferFrom

### Configuration

* Check: `arbitrary-send-erc20`
* Severity: `High`
* Confidence: `High`

### Description

Detect when `msg.sender` is not used as `from` in transferFrom.

### Exploit Scenario

```solidity
    function a(address from, address to, uint256 amount) public {
        erc20.transferFrom(from, to, am);
    }
```

Alice approves this contract to spend her ERC20 tokens. Bob can call `a` and specify Alice's address as the `from` parameter in `transferFrom`, allowing him to transfer Alice's tokens to himself.

### Recommendation

Use `msg.sender` as `from` in transferFrom.

## Modifying storage array by value

### Configuration

* Check: `array-by-reference`
* Severity: `High`
* Confidence: `High`

### Description

Detect arrays passed to a function that expects reference to a storage array

### Exploit Scenario

```solidity
contract Memory {
    uint[1] public x; // storage

    function f() public {
        f1(x); // update x
        f2(x); // do not update x
    }

    function f1(uint[1] storage arr) internal { // by reference
        arr[0] = 1;
    }

    function f2(uint[1] arr) internal { // by value
        arr[0] = 2;
    }
}
```

Bob calls `f()`. Bob assumes that at the end of the call `x[0]` is 2, but it is 1.
As a result, Bob's usage of the contract is incorrect.

### Recommendation

Ensure the correct usage of `memory` and `storage` in the function parameters. Make all the locations explicit.

## ABI encodePacked Collision

### Configuration

* Check: `encode-packed-collision`
* Severity: `High`
* Confidence: `High`

### Description

Detect collision due to dynamic type usages in `abi.encodePacked`

### Exploit Scenario

```solidity
contract Sign {
    function get_hash_for_signature(string name, string doc) external returns(bytes32) {
        return keccak256(abi.encodePacked(name, doc));
    }
}
```

Bob calls `get_hash_for_signature` with (`bob`, `This is the content`). The hash returned is used as an ID.
Eve creates a collision with the ID using (`bo`, `bThis is the content`) and compromises the system.

### Recommendation

Do not use more than one dynamic type in `abi.encodePacked()`
(see the [Solidity documentation](https://solidity.readthedocs.io/en/v0.5.10/abi-spec.html?highlight=abi.encodePacked#non-standard-packed-modeDynamic)).
Use `abi.encode()`, preferably.

## Incorrect shift in assembly

### Configuration

* Check: `incorrect-shift`
* Severity: `High`
* Confidence: `High`

### Description

Detect if the values in a shift operation are reversed

### Exploit Scenario

```solidity
contract C {
    function f() internal returns (uint a) {
        assembly {
            a := shr(a, 8)
        }
    }
}
```

The shift statement will right-shift the constant 8 by `a` bits

### Recommendation

Swap the order of parameters.

## Multiple constructor schemes

### Configuration

* Check: `multiple-constructors`
* Severity: `High`
* Confidence: `High`

### Description

Detect multiple constructor definitions in the same contract (using new and old schemes).

### Exploit Scenario

```solidity
contract A {
    uint x;
    constructor() public {
        x = 0;
    }
    function A() public {
        x = 1;
    }

    function test() public returns(uint) {
        return x;
    }
}
```

In Solidity [0.4.22](https://github.com/ethereum/solidity/releases/tag/v0.4.23), a contract with both constructor schemes will compile. The first constructor will take precedence over the second, which may be unintended.

### Recommendation

Only declare one constructor, preferably using the new scheme `constructor(...)` instead of `function <contractName>(...)`.

## Name reused

### Configuration

* Check: `name-reused`
* Severity: `High`
* Confidence: `High`

### Description

If a codebase has two contracts the similar names, the compilation artifacts
will not contain one of the contracts with the duplicate name.

### Exploit Scenario

Bob's `truffle` codebase has two contracts named `ERC20`.
When `truffle compile` runs, only one of the two contracts will generate artifacts in `build/contracts`.
As a result, the second contract cannot be analyzed.

### Recommendation

Rename the contract.

## Protected Variables

### Configuration

* Check: `protected-vars`
* Severity: `High`
* Confidence: `High`

### Description

Detect unprotected variable that are marked protected

### Exploit Scenario

```solidity
contract Buggy{

    /// @custom:security write-protection="onlyOwner()"
    address owner;

    function set_protected() public onlyOwner(){
        owner = msg.sender;
    }

    function set_not_protected() public{
        owner = msg.sender;
    }
}
```

`owner` must be always written by function using `onlyOwner` (`write-protection="onlyOwner()"`), however anyone can call `set_not_protected`.

### Recommendation

Add access controls to the vulnerable function

## Public mappings with nested variables

### Configuration

* Check: `public-mappings-nested`
* Severity: `High`
* Confidence: `High`

### Description

Prior to Solidity 0.5, a public mapping with nested structures returned [incorrect values](https://github.com/ethereum/solidity/issues/5520).

### Exploit Scenario

Bob interacts with a contract that has a public mapping with nested structures. The values returned by the mapping are incorrect, breaking Bob's usage

### Recommendation

Do not use public mapping with nested structures.

## Right-to-Left-Override character

### Configuration

* Check: `rtlo`
* Severity: `High`
* Confidence: `High`

### Description

An attacker can manipulate the logic of the contract by using a right-to-left-override character (`U+202E)`.

### Exploit Scenario

```solidity
contract Token
{

    address payable o; // owner
    mapping(address => uint) tokens;

    function withdraw() external returns(uint)
    {
        uint amount = tokens[msg.sender];
        address payable d = msg.sender;
        tokens[msg.sender] = 0;
        _withdraw(/*owner‮/*noitanitsed*/ d, o/*‭
          /*value */, amount);
    }

    function _withdraw(address payable fee_receiver, address payable destination, uint value) internal
    {
  fee_receiver.transfer(1);
  destination.transfer(value);
    }
}
```

`Token` uses the right-to-left-override character when calling `_withdraw`. As a result, the fee is incorrectly sent to `msg.sender`, and the token balance is sent to the owner.

### Recommendation

Special control characters must not be allowed.

## State variable shadowing

### Configuration

* Check: `shadowing-state`
* Severity: `High`
* Confidence: `High`

### Description

Detection of state variables shadowed.

### Exploit Scenario

```solidity
contract BaseContract{
    address owner;

    modifier isOwner(){
        require(owner == msg.sender);
        _;
    }

}

contract DerivedContract is BaseContract{
    address owner;

    constructor(){
        owner = msg.sender;
    }

    function withdraw() isOwner() external{
        msg.sender.transfer(this.balance);
    }
}
```

`owner` of `BaseContract` is never assigned and the modifier `isOwner` does not work.

### Recommendation

Remove the state variable shadowing.

## Suicidal

### Configuration

* Check: `suicidal`
* Severity: `High`
* Confidence: `High`

### Description

Unprotected call to a function executing `selfdestruct`/`suicide`.

### Exploit Scenario

```solidity
contract Suicidal{
    function kill() public{
        selfdestruct(msg.sender);
    }
}
```

Bob calls `kill` and destructs the contract.

### Recommendation

Protect access to all sensitive functions.

## Uninitialized state variables

### Configuration

* Check: `uninitialized-state`
* Severity: `High`
* Confidence: `High`

### Description

Uninitialized state variables.

### Exploit Scenario

```solidity
contract Uninitialized{
    address destination;

    function transfer() payable public{
        destination.transfer(msg.value);
    }
}
```

Bob calls `transfer`. As a result, the Ether are sent to the address `0x0` and are lost.

### Recommendation

Initialize all the variables. If a variable is meant to be initialized to zero, explicitly set it to zero to improve code readability.

## Uninitialized storage variables

### Configuration

* Check: `uninitialized-storage`
* Severity: `High`
* Confidence: `High`

### Description

An uninitialized storage variable will act as a reference to the first state variable, and can override a critical variable.

### Exploit Scenario

```solidity
contract Uninitialized{
    address owner = msg.sender;

    struct St{
        uint a;
    }

    function func() {
        St st;
        st.a = 0x0;
    }
}
```

Bob calls `func`. As a result, `owner` is overridden to `0`.

### Recommendation

Initialize all storage variables.

## Unprotected upgradeable contract

### Configuration

* Check: `unprotected-upgrade`
* Severity: `High`
* Confidence: `High`

### Description

Detects logic contract that can be destructed.

### Exploit Scenario

```solidity
contract Buggy is Initializable{
    address payable owner;

    function initialize() external initializer{
        require(owner == address(0));
        owner = msg.sender;
    }
    function kill() external{
        require(msg.sender == owner);
        selfdestruct(owner);
    }
}
```

Buggy is an upgradeable contract. Anyone can call initialize on the logic contract, and destruct the contract.

### Recommendation

Add a constructor to ensure `initialize` cannot be called on the logic contract.

## Arbitrary `from` in transferFrom used with permit

### Configuration

* Check: `arbitrary-send-erc20-permit`
* Severity: `High`
* Confidence: `Medium`

### Description

Detect when `msg.sender` is not used as `from` in transferFrom and permit is used.

### Exploit Scenario

```solidity
    function bad(address from, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s, address to) public {
        erc20.permit(from, address(this), value, deadline, v, r, s);
        erc20.transferFrom(from, to, value);
    }
```

If an ERC20 token does not implement permit and has a fallback function e.g. WETH, transferFrom allows an attacker to transfer all tokens approved for this contract.

### Recommendation

Ensure that the underlying ERC20 token correctly implements a permit function.

## Functions that send Ether to arbitrary destinations

### Configuration

* Check: `arbitrary-send-eth`
* Severity: `High`
* Confidence: `Medium`

### Description

Unprotected call to a function sending Ether to an arbitrary address.

### Exploit Scenario

```solidity
contract ArbitrarySendEth{
    address destination;
    function setDestination(){
        destination = msg.sender;
    }

    function withdraw() public{
        destination.transfer(this.balance);
    }
}
```

Bob calls `setDestination` and `withdraw`. As a result he withdraws the contract's balance.

### Recommendation

Ensure that an arbitrary user cannot withdraw unauthorized funds.

## Array Length Assignment

### Configuration

* Check: `controlled-array-length`
* Severity: `High`
* Confidence: `Medium`

### Description

Detects the direct assignment of an array's length.

### Exploit Scenario

```solidity
contract A {
 uint[] testArray; // dynamic size array

 function f(uint usersCount) public {
  // ...
  testArray.length = usersCount;
  // ...
 }

 function g(uint userIndex, uint val) public {
  // ...
  testArray[userIndex] = val;
  // ...
 }
}
```

Contract storage/state-variables are indexed by a 256-bit integer.
The user can set the array length to `2**256-1` in order to index all storage slots.
In the example above, one could call the function `f` to set the array length, then call the function `g` to control any storage slot desired.
Note that storage slots here are indexed via a hash of the indexers; nonetheless, all storage will still be accessible and could be controlled by the attacker.

### Recommendation

Do not allow array lengths to be set directly set; instead, opt to add values as needed.
Otherwise, thoroughly review the contract to ensure a user-controlled variable cannot reach an array length assignment.

## Controlled Delegatecall

### Configuration

* Check: `controlled-delegatecall`
* Severity: `High`
* Confidence: `Medium`

### Description

`Delegatecall` or `callcode` to an address controlled by the user.

### Exploit Scenario

```solidity
contract Delegatecall{
    function delegate(address to, bytes data){
        to.delegatecall(data);
    }
}
```

Bob calls `delegate` and delegates the execution to his malicious contract. As a result, Bob withdraws the funds of the contract and destructs it.

### Recommendation

Avoid using `delegatecall`. Use only trusted destinations.

## Payable functions using `delegatecall` inside a loop

### Configuration

* Check: `delegatecall-loop`
* Severity: `High`
* Confidence: `Medium`

### Description

Detect the use of `delegatecall` inside a loop in a payable function.

### Exploit Scenario

```solidity
contract DelegatecallInLoop{

    mapping (address => uint256) balances;

    function bad(address[] memory receivers) public payable {
        for (uint256 i = 0; i < receivers.length; i++) {
            address(this).delegatecall(abi.encodeWithSignature("addBalance(address)", receivers[i]));
        }
    }

    function addBalance(address a) public payable {
        balances[a] += msg.value;
    }

}
```

When calling `bad` the same `msg.value` amount will be accredited multiple times.

### Recommendation

Carefully check that the function called by `delegatecall` is not payable/doesn't use `msg.value`.

## Incorrect exponentiation

### Configuration

* Check: `incorrect-exp`
* Severity: `High`
* Confidence: `Medium`

### Description

Detect use of bitwise `xor ^` instead of exponential `**`

### Exploit Scenario

```solidity
contract Bug{
    uint UINT_MAX = 2^256 - 1;
    ...
}
```

Alice deploys a contract in which `UINT_MAX` incorrectly uses `^` operator instead of `**` for exponentiation

### Recommendation

Use the correct operator `**` for exponentiation.

## Incorrect return in assembly

### Configuration

* Check: `incorrect-return`
* Severity: `High`
* Confidence: `Medium`

### Description

Detect if `return` in an assembly block halts unexpectedly the execution.

### Exploit Scenario

```solidity
contract C {
    function f() internal returns (uint a, uint b) {
        assembly {
            return (5, 6)
        }
    }

    function g() returns (bool){
        f();
        return true;
    }
}
```

The return statement in `f` will cause execution in `g` to halt.
The function will return 6 bytes starting from offset 5, instead of returning a boolean.

### Recommendation

Use the `leave` statement.

## `msg.value` inside a loop

### Configuration

* Check: `msg-value-loop`
* Severity: `High`
* Confidence: `Medium`

### Description

Detect the use of `msg.value` inside a loop.

### Exploit Scenario

```solidity
contract MsgValueInLoop{

    mapping (address => uint256) balances;

    function bad(address[] memory receivers) public payable {
        for (uint256 i=0; i < receivers.length; i++) {
            balances[receivers[i]] += msg.value;
        }
    }

}
```

### Recommendation

Provide an explicit array of amounts alongside the receivers array, and check that the sum of all amounts matches `msg.value`.

## Reentrancy vulnerabilities

### Configuration

* Check: `reentrancy-balance`
* Severity: `High`
* Confidence: `Medium`

### Description

Detects reentrancy vulnerabilities where a balance is saved (e.g., `balanceOf`) before an external call,
and the same balance is checked again after the call. An attacker could manipulate the balance during the reentrant call,
causing the post-call check to use an outdated value.

### Exploit Scenario

```solidity
interface IERC20 {
   function balanceOf(address account) external view returns (uint256);
}

interface I {
  function pay(uint256 amount) external;
}

function mint(IERC20 tk) public {
    uint amount_to_pay = 100;
    uint balance_before = tk.balanceOf(address(this));
    I(msg.sender).pay(amount_to_pay);
    require(tk.balanceOf(address(this)) - balance_before >= amount_to_pay);
    // Mint liquidity
}
```

The `balanceBefore` variable could be outdated if the external call reenter the `mint` function N times, allowing to pay the funds only once.

### Recommendation

Use `transferFrom` to transfer funds of a standard ERC20 token, or use reentrancy guards to prevent reentering the function.

## Reentrancy vulnerabilities

### Configuration

* Check: `reentrancy-eth`
* Severity: `High`
* Confidence: `Medium`

### Description

Detection of the [reentrancy bug](https://github.com/trailofbits/not-so-smart-contracts/tree/master/reentrancy).
Do not report reentrancies that don't involve Ether (see `reentrancy-no-eth`)

### Exploit Scenario

```solidity
    function withdrawBalance(){
        // send userBalance[msg.sender] Ether to msg.sender
        // if msg.sender is a contract, it will call its fallback function
        if( ! (msg.sender.call.value(userBalance[msg.sender])() ) ){
            throw;
        }
        userBalance[msg.sender] = 0;
    }
```

Bob uses the re-entrancy bug to call `withdrawBalance` two times, and withdraw more than its initial deposit to the contract.

### Recommendation

Apply the [`check-effects-interactions pattern`](http://solidity.readthedocs.io/en/v0.4.21/security-considerations.html#re-entrancy).

## Return instead of leave in assembly

### Configuration

* Check: `return-leave`
* Severity: `High`
* Confidence: `Medium`

### Description

Detect if a `return` is used where a `leave` should be used.

### Exploit Scenario

```solidity
contract C {
    function f() internal returns (uint a, uint b) {
        assembly {
            return (5, 6)
        }
    }

}
```

The function will halt the execution, instead of returning a two uint.

### Recommendation

Use the `leave` statement.

## Storage Signed Integer Array

### Configuration

* Check: `storage-array`
* Severity: `High`
* Confidence: `Medium`

### Description

`solc` versions `0.4.7`-`0.5.9` contain [a compiler bug](https://blog.ethereum.org/2019/06/25/solidity-storage-array-bugs)
leading to incorrect values in signed integer arrays.

### Exploit Scenario

```solidity
contract A {
 int[3] ether_balances; // storage signed integer array
 function bad0() private {
  // ...
  ether_balances = [-1, -1, -1];
  // ...
 }
}
```

`bad0()` uses a (storage-allocated) signed integer array state variable to store the ether balances of three accounts.
`-1` is supposed to indicate uninitialized values but the Solidity bug makes these as `1`, which could be exploited by the accounts.

### Recommendation

Use a compiler version >= `0.5.10`.

## Unchecked transfer

### Configuration

* Check: `unchecked-transfer`
* Severity: `High`
* Confidence: `Medium`

### Description

The return value of an external transfer/transferFrom call is not checked

### Exploit Scenario

```solidity
contract Token {
    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);
}
contract MyBank{
    mapping(address => uint) balances;
    Token token;
    function deposit(uint amount) public{
        token.transferFrom(msg.sender, address(this), amount);
        balances[msg.sender] += amount;
    }
}
```

Several tokens do not revert in case of failure and return false. If one of these tokens is used in `MyBank`, `deposit` will not revert if the transfer fails, and an attacker can call `deposit` for free..

### Recommendation

Use `SafeERC20`, or ensure that the transfer/transferFrom return value is checked.

## Weak PRNG

### Configuration

* Check: `weak-prng`
* Severity: `High`
* Confidence: `Medium`

### Description

Weak PRNG due to a modulo on `block.timestamp`, `now` or `blockhash`. These can be influenced by miners to some extent so they should be avoided.

### Exploit Scenario

```solidity
contract Game {

    uint reward_determining_number;

    function guessing() external{
      reward_determining_number = uint256(block.blockhash(10000)) % 10;
    }
}
```

Eve is a miner. Eve calls `guessing` and re-orders the block containing the transaction.
As a result, Eve wins the game.

### Recommendation

Do not use `block.timestamp`, `now` or `blockhash` as a source of randomness

## Domain separator collision

### Configuration

* Check: `domain-separator-collision`
* Severity: `Medium`
* Confidence: `High`

### Description

An ERC20 token has a function whose signature collides with EIP-2612's DOMAIN_SEPARATOR(), causing unanticipated behavior for contracts using `permit` functionality.

### Exploit Scenario

```solidity
contract Contract{
    function some_collisions() external() {}
}
```

`some_collision` clashes with EIP-2612's DOMAIN_SEPARATOR() and will interfere with contract's using `permit`.

### Recommendation

Remove or rename the function that collides with DOMAIN_SEPARATOR().

## Dangerous enum conversion

### Configuration

* Check: `enum-conversion`
* Severity: `Medium`
* Confidence: `High`

### Description

Detect out-of-range `enum` conversion (`solc` < `0.4.5`).

### Exploit Scenario

```solidity
    pragma solidity 0.4.2;
    contract Test{

    enum E{a}

    function bug(uint a) public returns(E){
        return E(a);
    }
}
```

Attackers can trigger unexpected behaviour by calling `bug(1)`.

### Recommendation

Use a recent compiler version. If `solc` <`0.4.5` is required, check the `enum` conversion range.

## Incorrect erc20 interface

### Configuration

* Check: `erc20-interface`
* Severity: `Medium`
* Confidence: `High`

### Description

Incorrect return values for `ERC20` functions. A contract compiled with Solidity > 0.4.22 interacting with these functions will fail to execute them, as the return value is missing.

### Exploit Scenario

```solidity
contract Token{
    function transfer(address to, uint value) external;
    //...
}
```

`Token.transfer` does not return a boolean. Bob deploys the token. Alice creates a contract that interacts with it but assumes a correct `ERC20` interface implementation. Alice's contract is unable to interact with Bob's contract.

### Recommendation

Set the appropriate return values and types for the defined `ERC20` functions.

## Incorrect erc721 interface

### Configuration

* Check: `erc721-interface`
* Severity: `Medium`
* Confidence: `High`

### Description

Incorrect return values for `ERC721` functions. A contract compiled with solidity > 0.4.22 interacting with these functions will fail to execute them, as the return value is missing.

### Exploit Scenario

```solidity
contract Token{
    function ownerOf(uint256 _tokenId) external view returns (bool);
    //...
}
```

`Token.ownerOf` does not return an address like `ERC721` expects. Bob deploys the token. Alice creates a contract that interacts with it but assumes a correct `ERC721` interface implementation. Alice's contract is unable to interact with Bob's contract.

### Recommendation

Set the appropriate return values and vtypes for the defined `ERC721` functions.

## Dangerous strict equalities

### Configuration

* Check: `incorrect-equality`
* Severity: `Medium`
* Confidence: `High`

### Description

Use of strict equalities that can be easily manipulated by an attacker.

### Exploit Scenario

```solidity
contract Crowdsale{
    function fund_reached() public returns(bool){
        return this.balance == 100 ether;
    }
```

`Crowdsale` relies on `fund_reached` to know when to stop the sale of tokens.
`Crowdsale` reaches 100 Ether. Bob sends 0.1 Ether. As a result, `fund_reached` is always false and the `crowdsale` never ends.

### Recommendation

Don't use strict equality to determine if an account has enough Ether or tokens.

## Contracts that lock Ether

### Configuration

* Check: `locked-ether`
* Severity: `Medium`
* Confidence: `High`

### Description

Contract with a `payable` function, but without a withdrawal capacity.

### Exploit Scenario

```solidity
pragma solidity 0.4.24;
contract Locked{
    function receive() payable public{
    }
}
```

Every Ether sent to `Locked` will be lost.

### Recommendation

Remove the payable attribute or add a withdraw function.

## Deletion on mapping containing a structure

### Configuration

* Check: `mapping-deletion`
* Severity: `Medium`
* Confidence: `High`

### Description

A deletion in a structure containing a mapping will not delete the mapping (see the [Solidity documentation](https://solidity.readthedocs.io/en/latest/types.html##delete)). The remaining data may be used to compromise the contract.

### Exploit Scenario

```solidity
    struct BalancesStruct{
        address owner;
        mapping(address => uint) balances;
    }
    mapping(address => BalancesStruct) public stackBalance;

    function remove() internal{
         delete stackBalance[msg.sender];
    }
```

`remove` deletes an item of `stackBalance`.
The mapping `balances` is never deleted, so `remove` does not work as intended.

### Recommendation

Use a lock mechanism instead of a deletion to disable structure containing a mapping.

## Pyth deprecated functions

### Configuration

* Check: `pyth-deprecated-functions`
* Severity: `Medium`
* Confidence: `High`

### Description

Detect when a Pyth deprecated function is used

### Exploit Scenario

```solidity
import "@pythnetwork/pyth-sdk-solidity/IPyth.sol";
import "@pythnetwork/pyth-sdk-solidity/PythStructs.sol";

contract C {

    IPyth pyth;

    constructor(IPyth _pyth) {
        pyth = _pyth;
    }

    function A(bytes32 priceId) public {
        PythStructs.Price memory price = pyth.getPrice(priceId);
        ...
    }
}
```

The function `A` uses the deprecated `getPrice` Pyth function.

### Recommendation

Do not use deprecated Pyth functions. Visit <https://api-reference.pyth.network/>.

## Pyth unchecked confidence level

### Configuration

* Check: `pyth-unchecked-confidence`
* Severity: `Medium`
* Confidence: `High`

### Description

Detect when the confidence level of a Pyth price is not checked

### Exploit Scenario

```solidity
import "@pythnetwork/pyth-sdk-solidity/IPyth.sol";
import "@pythnetwork/pyth-sdk-solidity/PythStructs.sol";

contract C {
    IPyth pyth;

    constructor(IPyth _pyth) {
        pyth = _pyth;
    }

    function bad(bytes32 id, uint256 age) public {
        PythStructs.Price memory price = pyth.getEmaPriceNoOlderThan(id, age);
        // Use price
    }
}
```

The function `A` uses the price without checking its confidence level.

### Recommendation

Check the confidence level of a Pyth price. Visit <https://docs.pyth.network/price-feeds/best-practices#confidence-intervals> for more information.

## Pyth unchecked publishTime

### Configuration

* Check: `pyth-unchecked-publishtime`
* Severity: `Medium`
* Confidence: `High`

### Description

Detect when the publishTime of a Pyth price is not checked

### Exploit Scenario

```solidity
import "@pythnetwork/pyth-sdk-solidity/IPyth.sol";
import "@pythnetwork/pyth-sdk-solidity/PythStructs.sol";

contract C {
    IPyth pyth;

    constructor(IPyth _pyth) {
        pyth = _pyth;
    }

    function bad(bytes32 id) public {
        PythStructs.Price memory price = pyth.getEmaPriceUnsafe(id);
        // Use price
    }
}
```

The function `A` uses the price without checking its `publishTime` coming from the `getEmaPriceUnsafe` function.

### Recommendation

Check the publishTime of a Pyth price.

## State variable shadowing from abstract contracts

### Configuration

* Check: `shadowing-abstract`
* Severity: `Medium`
* Confidence: `High`

### Description

Detection of state variables shadowed from abstract contracts.

### Exploit Scenario

```solidity
contract BaseContract{
    address owner;
}

contract DerivedContract is BaseContract{
    address owner;
}
```

`owner` of `BaseContract` is shadowed in `DerivedContract`.

### Recommendation

Remove the state variable shadowing.

## Tautological compare

### Configuration

* Check: `tautological-compare`
* Severity: `Medium`
* Confidence: `High`

### Description

A variable compared to itself is probably an error as it will always return `true` for `==`, `>=`, `<=` and always `false` for `<`, `>` and `!=`.

### Exploit Scenario

```solidity
    function check(uint a) external returns(bool){
        return (a >= a);
    }
```

`check` always return true.

### Recommendation

Remove comparison or compare to different value.

## Tautology or contradiction

### Configuration

* Check: `tautology`
* Severity: `Medium`
* Confidence: `High`

### Description

Detects expressions that are tautologies or contradictions.

### Exploit Scenario

```solidity
contract A {
 function f(uint x) public {
  // ...
        if (x >= 0) { // bad -- always true
           // ...
        }
  // ...
 }

 function g(uint8 y) public returns (bool) {
  // ...
        return (y < 512); // bad!
  // ...
 }
}
```

`x` is a `uint256`, so `x >= 0` will be always true.
`y` is a `uint8`, so `y <512` will be always true.

### Recommendation

Fix the incorrect comparison by changing the value type or the comparison.

## Write after write

### Configuration

* Check: `write-after-write`
* Severity: `Medium`
* Confidence: `High`

### Description

Detects variables that are written but never read and written again.

### Exploit Scenario

    ```solidity
    contract Buggy{
        function my_func() external initializer{
            // ...
            a = b;
            a = c;
            // ..
        }
    }
    ```
    `a` is first assigned to `b`, and then to `c`. As a result the first write does nothing.

### Recommendation

Fix or remove the writes.

## Misuse of a Boolean constant

### Configuration

* Check: `boolean-cst`
* Severity: `Medium`
* Confidence: `Medium`

### Description

Detects the misuse of a Boolean constant.

### Exploit Scenario

```solidity
contract A {
 function f(uint x) public {
  // ...
        if (false) { // bad!
           // ...
        }
  // ...
 }

 function g(bool b) public returns (bool) {
  // ...
        return (b || true); // bad!
  // ...
 }
}
```

Boolean constants in code have only a few legitimate uses.
Other uses (in complex expressions, as conditionals) indicate either an error or, most likely, the persistence of faulty code.

### Recommendation

Verify and simplify the condition.

## Chronicle unchecked price

### Configuration

* Check: `chronicle-unchecked-price`
* Severity: `Medium`
* Confidence: `Medium`

### Description

Chronicle oracle is used and the price returned is not checked to be valid. For more information <https://docs.chroniclelabs.org/Resources/FAQ/Oracles#how-do-i-check-if-an-oracle-becomes-inactive-gets-deprecated>.

### Exploit Scenario

```solidity
contract C {
    IChronicle chronicle;

    constructor(address a) {
        chronicle = IChronicle(a);
    }

    function bad() public {
        uint256 price = chronicle.read();
    }
```

The `bad` function gets the price from Chronicle by calling the read function however it does not check if the price is valid.

### Recommendation

Validate that the price returned by the oracle is valid.

## Constant functions using assembly code

### Configuration

* Check: `constant-function-asm`
* Severity: `Medium`
* Confidence: `Medium`

### Description

Functions declared as `constant`/`pure`/`view` using assembly code.

`constant`/`pure`/`view` was not enforced prior to Solidity 0.5.
Starting from Solidity 0.5, a call to a `constant`/`pure`/`view` function uses the `STATICCALL` opcode, which reverts in case of state modification.

As a result, a call to an [incorrectly labeled function may trap a contract compiled with Solidity 0.5](https://solidity.readthedocs.io/en/develop/050-breaking-changes.html#interoperability-with-older-contracts).

### Exploit Scenario

```solidity
contract Constant{
    uint counter;
    function get() public view returns(uint){
       counter = counter +1;
       return counter
    }
}
```

`Constant` was deployed with Solidity 0.4.25. Bob writes a smart contract that interacts with `Constant` in Solidity 0.5.0.
All the calls to `get` revert, breaking Bob's smart contract execution.

### Recommendation

Ensure the attributes of contracts compiled prior to Solidity 0.5.0 are correct.

## Constant functions changing the state

### Configuration

* Check: `constant-function-state`
* Severity: `Medium`
* Confidence: `Medium`

### Description

Functions declared as `constant`/`pure`/`view` change the state.

`constant`/`pure`/`view` was not enforced prior to Solidity 0.5.
Starting from Solidity 0.5, a call to a `constant`/`pure`/`view` function uses the `STATICCALL` opcode, which reverts in case of state modification.

As a result, a call to an [incorrectly labeled function may trap a contract compiled with Solidity 0.5](https://solidity.readthedocs.io/en/develop/050-breaking-changes.html#interoperability-with-older-contracts).

### Exploit Scenario

```solidity
contract Constant{
    uint counter;
    function get() public view returns(uint){
       counter = counter +1;
       return counter
    }
}
```

`Constant` was deployed with Solidity 0.4.25. Bob writes a smart contract that interacts with `Constant` in Solidity 0.5.0.
All the calls to `get` revert, breaking Bob's smart contract execution.

### Recommendation

Ensure that attributes of contracts compiled prior to Solidity 0.5.0 are correct.

## Divide before multiply

### Configuration

* Check: `divide-before-multiply`
* Severity: `Medium`
* Confidence: `Medium`

### Description

Solidity's integer division truncates. Thus, performing division before multiplication can lead to precision loss.

### Exploit Scenario

```solidity
contract A {
 function f(uint n) public {
        coins = (oldSupply / n) * interest;
    }
}
```

If `n` is greater than `oldSupply`, `coins` will be zero. For example, with `oldSupply = 5; n = 10, interest = 2`, coins will be zero.
If `(oldSupply * interest / n)` was used, `coins` would have been `1`.
In general, it's usually a good idea to re-arrange arithmetic to perform multiplication before division, unless the limit of a smaller type makes this dangerous.

### Recommendation

Consider ordering multiplication before division.

## Gelato unprotected randomness

### Configuration

* Check: `gelato-unprotected-randomness`
* Severity: `Medium`
* Confidence: `Medium`

### Description

Detect calls to `_requestRandomness` within an unprotected function.

### Exploit Scenario

```solidity
contract C is GelatoVRFConsumerBase {
    function _fulfillRandomness(
        uint256 randomness,
        uint256,
        bytes memory extraData
    ) internal override {
        // Do something with the random number
    }

    function bad() public {
        _requestRandomness(abi.encode(msg.sender));
    }
}
```

The function `bad` is uprotected and requests randomness.

### Recommendation

Function that request randomness should be allowed only to authorized users.

## Out-of-order retryable transactions

### Configuration

* Check: `out-of-order-retryable`
* Severity: `Medium`
* Confidence: `Medium`

### Description

Out-of-order retryable transactions

### Exploit Scenario

```solidity
contract L1 {
    function doStuffOnL2() external {
        // Retryable A
        IInbox(inbox).createRetryableTicket({
            to: l2contract,
            l2CallValue: 0,
            maxSubmissionCost: maxSubmissionCost,
            excessFeeRefundAddress: msg.sender,
            callValueRefundAddress: msg.sender,
            gasLimit: gasLimit,
            maxFeePerGas: maxFeePerGas,
            data: abi.encodeCall(l2contract.claim_rewards, ())
        });
        // Retryable B
        IInbox(inbox).createRetryableTicket({
            to: l2contract,
            l2CallValue: 0,
            maxSubmissionCost: maxSubmissionCost,
            excessFeeRefundAddress: msg.sender,
            callValueRefundAddress: msg.sender,
            gasLimit: gas,
            maxFeePerGas: maxFeePerGas,
            data: abi.encodeCall(l2contract.unstake, ())
        });
    }
}

contract L2 {
    function claim_rewards() public {
        // rewards is computed based on balance and staking period
        uint unclaimed_rewards = _compute_and_update_rewards();
        token.safeTransfer(msg.sender, unclaimed_rewards);
    }

    // Call claim_rewards before unstaking, otherwise you lose your rewards
    function unstake() public {
        _free_rewards(); // clean up rewards related variables
        balance = balance[msg.sender];
        balance[msg.sender] = 0;
        staked_token.safeTransfer(msg.sender, balance);
    }
}
```

Bob calls `doStuffOnL2` but the first retryable ticket calling `claim_rewards` fails. The second retryable ticket calling `unstake` is executed successfully. As a result, Bob loses his rewards.

### Recommendation

Do not rely on the order or successful execution of retryable tickets.

## Reentrancy vulnerabilities

### Configuration

* Check: `reentrancy-no-eth`
* Severity: `Medium`
* Confidence: `Medium`

### Description

Detection of the [reentrancy bug](https://github.com/trailofbits/not-so-smart-contracts/tree/master/reentrancy).
Do not report reentrancies that involve Ether (see `reentrancy-eth`).

### Exploit Scenario

```solidity
    function bug(){
        require(not_called);
        if( ! (msg.sender.call() ) ){
            throw;
        }
        not_called = False;
    }
```

### Recommendation

Apply the [`check-effects-interactions` pattern](http://solidity.readthedocs.io/en/v0.4.21/security-considerations.html#re-entrancy).

## Reused base constructors

### Configuration

* Check: `reused-constructor`
* Severity: `Medium`
* Confidence: `Medium`

### Description

Detects if the same base constructor is called with arguments from two different locations in the same inheritance hierarchy.

### Exploit Scenario

```solidity
pragma solidity ^0.4.0;

contract A{
    uint num = 5;
    constructor(uint x) public{
        num += x;
    }
}

contract B is A{
    constructor() A(2) public { /* ... */ }
}

contract C is A {
    constructor() A(3) public { /* ... */ }
}

contract D is B, C {
    constructor() public { /* ... */ }
}

contract E is B {
    constructor() A(1) public { /* ... */ }
}
```

The constructor of `A` is called multiple times in `D` and `E`:

* `D` inherits from `B` and `C`, both of which construct `A`.
* `E` only inherits from `B`, but `B` and `E` construct `A`.
.

### Recommendation

Remove the duplicate constructor call.

## Dangerous usage of `tx.origin`

### Configuration

* Check: `tx-origin`
* Severity: `Medium`
* Confidence: `Medium`

### Description

`tx.origin`-based protection can be abused by a malicious contract if a legitimate user interacts with the malicious contract.

### Exploit Scenario

```solidity
contract TxOrigin {
    address owner = msg.sender;

    function bug() {
        require(tx.origin == owner);
    }
```

Bob is the owner of `TxOrigin`. Bob calls Eve's contract. Eve's contract calls `TxOrigin` and bypasses the `tx.origin` protection.

### Recommendation

Do not use `tx.origin` for authorization.

## Unchecked low-level calls

### Configuration

* Check: `unchecked-lowlevel`
* Severity: `Medium`
* Confidence: `Medium`

### Description

The return value of a low-level call is not checked.

### Exploit Scenario

```solidity
contract MyConc{
    function my_func(address payable dst) public payable{
        dst.call.value(msg.value)("");
    }
}
```

The return value of the low-level call is not checked, so if the call fails, the Ether will be locked in the contract.
If the low level is used to prevent blocking operations, consider logging failed calls.

### Recommendation

Ensure that the return value of a low-level call is checked or logged.

## Unchecked Send

### Configuration

* Check: `unchecked-send`
* Severity: `Medium`
* Confidence: `Medium`

### Description

The return value of a `send` is not checked.

### Exploit Scenario

```solidity
contract MyConc{
    function my_func(address payable dst) public payable{
        dst.send(msg.value);
    }
}
```

The return value of `send` is not checked, so if the send fails, the Ether will be locked in the contract.
If `send` is used to prevent blocking operations, consider logging the failed `send`.

### Recommendation

Ensure that the return value of `send` is checked or logged.

## Uninitialized local variables

### Configuration

* Check: `uninitialized-local`
* Severity: `Medium`
* Confidence: `Medium`

### Description

Uninitialized local variables.

### Exploit Scenario

```solidity
contract Uninitialized is Owner{
    function withdraw() payable public onlyOwner{
        address to;
        to.transfer(this.balance)
    }
}
```

Bob calls `transfer`. As a result, all Ether is sent to the address `0x0` and is lost.

### Recommendation

Initialize all the variables. If a variable is meant to be initialized to zero, explicitly set it to zero to improve code readability.

## Unused return

### Configuration

* Check: `unused-return`
* Severity: `Medium`
* Confidence: `Medium`

### Description

The return value of an external call is not stored in a local or state variable.

### Exploit Scenario

```solidity
contract MyConc{
    using SafeMath for uint;
    function my_func(uint a, uint b) public{
        a.add(b);
    }
}
```

`MyConc` calls `add` of `SafeMath`, but does not store the result in `a`. As a result, the computation has no effect.

### Recommendation

Ensure that all the return values of the function calls are used.

## Chainlink Feed Registry usage

### Configuration

* Check: `chainlink-feed-registry`
* Severity: `Low`
* Confidence: `High`

### Description

Detect when Chainlink Feed Registry is used. At the moment is only available on Ethereum Mainnet.

### Exploit Scenario

```solidity
import "chainlink/contracts/src/v0.8/interfaces/FeedRegistryInteface.sol"

contract A {
    FeedRegistryInterface public immutable registry;

    constructor(address _registry) {
        registry = _registry;
    }

    function getPrice(address base, address quote) public return(uint256) {
        (, int256 price,,,) = registry.latestRoundData(base, quote);
        // Do price validation
        return uint256(price);
    }
}
```

If the contract is deployed on a different chain than Ethereum Mainnet the `getPrice` function will revert.

### Recommendation

Do not use Chainlink Feed Registry outside of Ethereum Mainnet.

## Incorrect modifier

### Configuration

* Check: `incorrect-modifier`
* Severity: `Low`
* Confidence: `High`

### Description

If a modifier does not execute `_` or revert, the execution of the function will return the default value, which can be misleading for the caller.

### Exploit Scenario

```solidity
    modifier myModif(){
        if(..){
           _;
        }
    }
    function get() myModif returns(uint){

    }
```

If the condition in `myModif` is false, the execution of `get()` will return 0.

### Recommendation

All the paths in a modifier must execute `_` or revert.

## Optimism deprecated predeploy or function

### Configuration

* Check: `optimism-deprecation`
* Severity: `Low`
* Confidence: `High`

### Description

Detect when deprecated Optimism predeploy or function is used.

### Exploit Scenario

```solidity
interface GasPriceOracle {
    function scalar() external view returns (uint256);
}

contract Test {
    GasPriceOracle constant OPT_GAS = GasPriceOracle(0x420000000000000000000000000000000000000F);

    function a() public {
        OPT_GAS.scalar();
    }
}
```

The call to the `scalar` function of the Optimism GasPriceOracle predeploy always revert.

### Recommendation

Do not use the deprecated components.

## Built-in Symbol Shadowing

### Configuration

* Check: `shadowing-builtin`
* Severity: `Low`
* Confidence: `High`

### Description

Detection of shadowing built-in symbols using local variables, state variables, functions, modifiers, or events.

### Exploit Scenario

```solidity
pragma solidity ^0.4.24;

contract Bug {
    uint now; // Overshadows current time stamp.

    function assert(bool condition) public {
        // Overshadows built-in symbol for providing assertions.
    }

    function get_next_expiration(uint earlier_time) private returns (uint) {
        return now + 259200; // References overshadowed timestamp.
    }
}
```

`now` is defined as a state variable, and shadows with the built-in symbol `now`. The function `assert` overshadows the built-in `assert` function. Any use of either of these built-in symbols may lead to unexpected results.

### Recommendation

Rename the local variables, state variables, functions, modifiers, and events that shadow a built-in symbol.

## Local variable shadowing

### Configuration

* Check: `shadowing-local`
* Severity: `Low`
* Confidence: `High`

### Description

Detection of shadowing using local variables.

### Exploit Scenario

```solidity
pragma solidity ^0.4.24;

contract Bug {
    uint owner;

    function sensitive_function(address owner) public {
        // ...
        require(owner == msg.sender);
    }

    function alternate_sensitive_function() public {
        address owner = msg.sender;
        // ...
        require(owner == msg.sender);
    }
}
```

`sensitive_function.owner` shadows `Bug.owner`. As a result, the use of `owner` in `sensitive_function` might be incorrect.

### Recommendation

Rename the local variables that shadow another component.

## Uninitialized function pointers in constructors

### Configuration

* Check: `uninitialized-fptr-cst`
* Severity: `Low`
* Confidence: `High`

### Description

solc versions `0.4.5`-`0.4.26` and `0.5.0`-`0.5.8` contain a compiler bug leading to unexpected behavior when calling uninitialized function pointers in constructors.

### Exploit Scenario

```solidity
contract bad0 {

  constructor() public {
    /* Uninitialized function pointer */
    function(uint256) internal returns(uint256) a;
    a(10);
  }

}
```

The call to `a(10)` will lead to unexpected behavior because function pointer `a` is not initialized in the constructor.

### Recommendation

Initialize function pointers before calling. Avoid function pointers if possible.

## Pre-declaration usage of local variables

### Configuration

* Check: `variable-scope`
* Severity: `Low`
* Confidence: `High`

### Description

Detects the possible usage of a variable before the declaration is stepped over (either because it is later declared, or declared in another scope).

### Exploit Scenario

```solidity
contract C {
    function f(uint z) public returns (uint) {
        uint y = x + 9 + z; // 'x' is used pre-declaration
        uint x = 7;

        if (z % 2 == 0) {
            uint max = 5;
            // ...
        }

        // 'max' was intended to be 5, but it was mistakenly declared in a scope and not assigned (so it is zero).
        for (uint i = 0; i < max; i++) {
            x += 1;
        }

        return x;
    }
}
```

In the case above, the variable `x` is used before its declaration, which may result in unintended consequences.
Additionally, the for-loop uses the variable `max`, which is declared in a previous scope that may not always be reached. This could lead to unintended consequences if the user mistakenly uses a variable prior to any intended declaration assignment. It also may indicate that the user intended to reference a different variable.

### Recommendation

Move all variable declarations prior to any usage of the variable, and ensure that reaching a variable declaration does not depend on some conditional if it is used unconditionally.

## Void constructor

### Configuration

* Check: `void-cst`
* Severity: `Low`
* Confidence: `High`

### Description

Detect the call to a constructor that is not implemented

### Exploit Scenario

```solidity
contract A{}
contract B is A{
    constructor() public A(){}
}
```

When reading `B`'s constructor definition, we might assume that `A()` initiates the contract, but no code is executed.

### Recommendation

Remove the constructor call.

## Calls inside a loop

### Configuration

* Check: `calls-loop`
* Severity: `Low`
* Confidence: `Medium`

### Description

Calls inside a loop might lead to a denial-of-service attack.

### Exploit Scenario

```solidity
contract CallsInLoop{

    address[] destinations;

    constructor(address[] newDestinations) public{
        destinations = newDestinations;
    }

    function bad() external{
        for (uint i=0; i < destinations.length; i++){
            destinations[i].transfer(i);
        }
    }

}
```

If one of the destinations has a fallback function that reverts, `bad` will always revert.

### Recommendation

Favor [pull over push](https://github.com/ethereum/wiki/wiki/Safety#favor-pull-over-push-for-external-calls) strategy for external calls.

## Missing events access control

### Configuration

* Check: `events-access`
* Severity: `Low`
* Confidence: `Medium`

### Description

Detect missing events for critical access control parameters

### Exploit Scenario

```solidity
contract C {

  modifier onlyAdmin {
    if (msg.sender != owner) throw;
    _;
  }

  function updateOwner(address newOwner) onlyAdmin external {
    owner = newOwner;
  }
}
```

`updateOwner()` has no event, so it is difficult to track off-chain owner changes.

### Recommendation

Emit an event for critical parameter changes.

## Missing events arithmetic

### Configuration

* Check: `events-maths`
* Severity: `Low`
* Confidence: `Medium`

### Description

Detect missing events for critical arithmetic parameters.

### Exploit Scenario

```solidity
contract C {

    modifier onlyOwner {
        if (msg.sender != owner) throw;
        _;
    }

    function setBuyPrice(uint256 newBuyPrice) onlyOwner public {
        buyPrice = newBuyPrice;
    }

    function buy() external {
     ... // buyPrice is used to determine the number of tokens purchased
    }
}
```

`setBuyPrice()` does not emit an event, so it is difficult to track changes in the value of `buyPrice` off-chain.

### Recommendation

Emit an event for critical parameter changes.

## Dangerous unary expressions

### Configuration

* Check: `incorrect-unary`
* Severity: `Low`
* Confidence: `Medium`

### Description

Unary expressions such as `x=+1` probably typos.

### Exploit Scenario

```Solidity
contract Bug{
    uint public counter;

    function increase() public returns(uint){
        counter=+1;
        return counter;
    }
}
```

`increase()` uses `=+` instead of `+=`, so `counter` will never exceed 1.

### Recommendation

Remove the unary expression.

## Missing zero address validation

### Configuration

* Check: `missing-zero-check`
* Severity: `Low`
* Confidence: `Medium`

### Description

Detect missing zero address validation.

### Exploit Scenario

```solidity
contract C {

  modifier onlyAdmin {
    if (msg.sender != owner) throw;
    _;
  }

  function updateOwner(address newOwner) onlyAdmin external {
    owner = newOwner;
  }
}
```

Bob calls `updateOwner` without specifying the `newOwner`, so Bob loses ownership of the contract.

### Recommendation

Check that the address is not zero.

## Reentrancy vulnerabilities

### Configuration

* Check: `reentrancy-benign`
* Severity: `Low`
* Confidence: `Medium`

### Description

Detection of the [reentrancy bug](https://github.com/trailofbits/not-so-smart-contracts/tree/master/reentrancy).
Only report reentrancy that acts as a double call (see `reentrancy-eth`, `reentrancy-no-eth`).

### Exploit Scenario

```solidity
    function callme(){
        if( ! (msg.sender.call()() ) ){
            throw;
        }
        counter += 1
    }
```

`callme` contains a reentrancy. The reentrancy is benign because it's exploitation would have the same effect as two consecutive calls.

### Recommendation

Apply the [`check-effects-interactions` pattern](http://solidity.readthedocs.io/en/v0.4.21/security-considerations.html#re-entrancy).

## Reentrancy vulnerabilities

### Configuration

* Check: `reentrancy-events`
* Severity: `Low`
* Confidence: `Medium`

### Description

Detects [reentrancies](https://github.com/trailofbits/not-so-smart-contracts/tree/master/reentrancy) that allow manipulation of the order or value of events.

### Exploit Scenario

```solidity
contract ReentrantContract {
 function f() external {
  if (BugReentrancyEvents(msg.sender).counter() == 1) {
   BugReentrancyEvents(msg.sender).count(this);
  }
 }
}
contract Counter {
 uint public counter;
 event Counter(uint);

}
contract BugReentrancyEvents is Counter {
    function count(ReentrantContract d) external {
        counter += 1;
        d.f();
        emit Counter(counter);
    }
}
contract NoReentrancyEvents is Counter {
 function count(ReentrantContract d) external {
        counter += 1;
        emit Counter(counter);
        d.f();
    }
}
```

If the external call `d.f()` re-enters `BugReentrancyEvents`, the `Counter` events will be incorrect (`Counter(2)`, `Counter(2)`) whereas `NoReentrancyEvents` will correctly emit
(`Counter(1)`, `Counter(2)`). This may cause issues for offchain components that rely on the values of events e.g. checking for the amount deposited to a bridge.

### Recommendation

Apply the [`check-effects-interactions` pattern](https://docs.soliditylang.org/en/latest/security-considerations.html#re-entrancy).

## Return Bomb

### Configuration

* Check: `return-bomb`
* Severity: `Low`
* Confidence: `Medium`

### Description

A low level callee may consume all callers gas unexpectedly.

### Exploit Scenario

```solidity
//Modified from https://github.com/nomad-xyz/ExcessivelySafeCall
contract BadGuy {
    function youveActivateMyTrapCard() external pure returns (bytes memory) {
        assembly{
            revert(0, 1000000)
        }
    }
}

contract Mark {
    function oops(address badGuy) public{
        bool success;
        bytes memory ret;

        // Mark pays a lot of gas for this copy
        //(success, ret) = badGuy.call{gas:10000}(
        (success, ret) = badGuy.call(
            abi.encodeWithSelector(
                BadGuy.youveActivateMyTrapCard.selector
            )
        );

        // Mark may OOG here, preventing local state changes
        //importantCleanup();
    }
}

```

After Mark calls BadGuy bytes are copied from returndata to memory, the memory expansion cost is paid. This means that when using a standard solidity call, the callee can "returnbomb" the caller, imposing an arbitrary gas cost.
Callee unexpectedly makes the caller OOG.

### Recommendation

Avoid unlimited implicit decoding of returndata.

## Block timestamp

### Configuration

* Check: `timestamp`
* Severity: `Low`
* Confidence: `Medium`

### Description

Dangerous usage of `block.timestamp`. `block.timestamp` can be manipulated by miners.

### Exploit Scenario

"Bob's contract relies on `block.timestamp` for its randomness. Eve is a miner and manipulates `block.timestamp` to exploit Bob's contract.

### Recommendation

Avoid relying on `block.timestamp`.

## Assembly usage

### Configuration

* Check: `assembly`
* Severity: `Informational`
* Confidence: `High`

### Description

The use of assembly is error-prone and should be avoided.

### Recommendation

Do not use `evm` assembly.

## Assert state change

### Configuration

* Check: `assert-state-change`
* Severity: `Informational`
* Confidence: `High`

### Description

Incorrect use of `assert()`. See Solidity best [practices](https://solidity.readthedocs.io/en/latest/control-structures.html#id4).

### Exploit Scenario

```solidity
contract A {

  uint s_a;

  function bad() public {
    assert((s_a += 1) > 10);
  }
}
```

The assert in `bad()` increments the state variable `s_a` while checking for the condition.

### Recommendation

Use `require` for invariants modifying the state.

## Boolean equality

### Configuration

* Check: `boolean-equal`
* Severity: `Informational`
* Confidence: `High`

### Description

Detects the comparison to boolean constants.

### Exploit Scenario

```solidity
contract A {
 function f(bool x) public {
  // ...
        if (x == true) { // bad!
           // ...
        }
  // ...
 }
}
```

Boolean constants can be used directly and do not need to be compare to `true` or `false`.

### Recommendation

Remove the equality to the boolean constant.

## Cyclomatic complexity

### Configuration

* Check: `cyclomatic-complexity`
* Severity: `Informational`
* Confidence: `High`

### Description

Detects functions with high (> 11) cyclomatic complexity.

### Recommendation

Reduce cyclomatic complexity by splitting the function into several smaller subroutines.

## Deprecated standards

### Configuration

* Check: `deprecated-standards`
* Severity: `Informational`
* Confidence: `High`

### Description

Detect the usage of deprecated standards.

### Exploit Scenario

```solidity
contract ContractWithDeprecatedReferences {
    // Deprecated: Change block.blockhash() -> blockhash()
    bytes32 globalBlockHash = block.blockhash(0);

    // Deprecated: Change constant -> view
    function functionWithDeprecatedThrow() public constant {
        // Deprecated: Change msg.gas -> gasleft()
        if(msg.gas == msg.value) {
            // Deprecated: Change throw -> revert()
            throw;
        }
    }

    // Deprecated: Change constant -> view
    function functionWithDeprecatedReferences() public constant {
        // Deprecated: Change sha3() -> keccak256()
        bytes32 sha3Result = sha3("test deprecated sha3 usage");

        // Deprecated: Change callcode() -> delegatecall()
        address(this).callcode();

        // Deprecated: Change suicide() -> selfdestruct()
        suicide(address(0));
    }
}
```

### Recommendation

Replace all uses of deprecated symbols.

## Unindexed ERC20 event parameters

### Configuration

* Check: `erc20-indexed`
* Severity: `Informational`
* Confidence: `High`

### Description

Detects whether events defined by the `ERC20` specification that should have some parameters as `indexed` are missing the `indexed` keyword.

### Exploit Scenario

```solidity
contract ERC20Bad {
    // ...
    event Transfer(address from, address to, uint value);
    event Approval(address owner, address spender, uint value);

    // ...
}
```

`Transfer` and `Approval` events should have the 'indexed' keyword on their two first parameters, as defined by the `ERC20` specification.
Failure to include these keywords will exclude the parameter data in the transaction/block's bloom filter, so external tooling searching for these parameters may overlook them and fail to index logs from this token contract.

### Recommendation

Add the `indexed` keyword to event parameters that should include it, according to the `ERC20` specification.

## Function Initializing State

### Configuration

* Check: `function-init-state`
* Severity: `Informational`
* Confidence: `High`

### Description

Detects the immediate initialization of state variables through function calls that are not pure/constant, or that use non-constant state variable.

### Exploit Scenario

```solidity
contract StateVarInitFromFunction {

    uint public v = set(); // Initialize from function (sets to 77)
    uint public w = 5;
    uint public x = set(); // Initialize from function (sets to 88)
    address public shouldntBeReported = address(8);

    constructor(){
        // The constructor is run after all state variables are initialized.
    }

    function set() public  returns(uint)  {
        // If this function is being used to initialize a state variable declared
        // before w, w will be zero. If it is declared after w, w will be set.
        if(w == 0) {
            return 77;
        }

        return 88;
    }
}
```

In this case, users might intend a function to return a value a state variable can initialize with, without realizing the context for the contract is not fully initialized.
In the example above, the same function sets two different values for state variables because it checks a state variable that is not yet initialized in one case, and is initialized in the other.
Special care must be taken when initializing state variables from an immediate function call so as not to incorrectly assume the state is initialized.

### Recommendation

Remove any initialization of state variables via non-constant state variables or function calls. If variables must be set upon contract deployment, locate initialization in the constructor instead.

## Incorrect usage of using-for statement

### Configuration

* Check: `incorrect-using-for`
* Severity: `Informational`
* Confidence: `High`

### Description

In Solidity, it is possible to use libraries for certain types, by the `using-for` statement (`using <library> for <type>`). However, the Solidity compiler doesn't check whether a given library has at least one function matching a given type. If it doesn't, such a statement has no effect and may be confusing.

### Exploit Scenario

    ```solidity
    library L {
        function f(bool) public pure {}
    }

    using L for uint;
    ```
    Such a code will compile despite the fact that `L` has no function with `uint` as its first argument.

### Recommendation

Make sure that the libraries used in `using-for` statements have at least one function matching a type used in these statements.

## Low-level calls

### Configuration

* Check: `low-level-calls`
* Severity: `Informational`
* Confidence: `High`

### Description

The use of low-level calls is error-prone. Low-level calls do not check for [code existence](https://solidity.readthedocs.io/en/v0.4.25/control-structures.html#error-handling-assert-require-revert-and-exceptions) or call success.

### Recommendation

Avoid low-level calls. Check the call success. If the call is meant for a contract, check for code existence.

## Missing inheritance

### Configuration

* Check: `missing-inheritance`
* Severity: `Informational`
* Confidence: `High`

### Description

Detect missing inheritance.

### Exploit Scenario

```solidity
interface ISomething {
    function f1() external returns(uint);
}

contract Something {
    function f1() external returns(uint){
        return 42;
    }
}
```

`Something` should inherit from `ISomething`.

### Recommendation

Inherit from the missing interface or contract.

## Conformance to Solidity naming conventions

### Configuration

* Check: `naming-convention`
* Severity: `Informational`
* Confidence: `High`

### Description

Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.25/style-guide.html#naming-conventions) that should be followed.

#### Rule exceptions

* Allow constant variable name/symbol/decimals to be lowercase (`ERC20`).
* Allow `_` at the beginning of the `mixed_case` match for private variables and unused parameters.

### Recommendation

Follow the Solidity [naming convention](https://solidity.readthedocs.io/en/v0.4.25/style-guide.html#naming-conventions).

## Different pragma directives are used

### Configuration

* Check: `pragma`
* Severity: `Informational`
* Confidence: `High`

### Description

Detect whether different Solidity versions are used.

### Recommendation

Use one Solidity version.

## Redundant Statements

### Configuration

* Check: `redundant-statements`
* Severity: `Informational`
* Confidence: `High`

### Description

Detect the usage of redundant statements that have no effect.

### Exploit Scenario

```solidity
contract RedundantStatementsContract {

    constructor() public {
        uint; // Elementary Type Name
        bool; // Elementary Type Name
        RedundantStatementsContract; // Identifier
    }

    function test() public returns (uint) {
        uint; // Elementary Type Name
        assert; // Identifier
        test; // Identifier
        return 777;
    }
}
```

Each commented line references types/identifiers, but performs no action with them, so no code will be generated for such statements and they can be removed.

### Recommendation

Remove redundant statements if they congest code but offer no value.

## Incorrect versions of Solidity

### Configuration

* Check: `solc-version`
* Severity: `Informational`
* Confidence: `High`

### Description

`solc` frequently releases new compiler versions. Using an old version prevents access to new Solidity security checks.
We also recommend avoiding complex `pragma` statement.

### Recommendation

Deploy with a recent version of Solidity (at least 0.8.0) with no known severe issues.

Use a simple pragma version that allows any of these versions.
Consider using the latest version of Solidity for testing.

## Unimplemented functions

### Configuration

* Check: `unimplemented-functions`
* Severity: `Informational`
* Confidence: `High`

### Description

Detect functions that are not implemented on derived-most contracts.

### Exploit Scenario

```solidity
interface BaseInterface {
    function f1() external returns(uint);
    function f2() external returns(uint);
}

interface BaseInterface2 {
    function f3() external returns(uint);
}

contract DerivedContract is BaseInterface, BaseInterface2 {
    function f1() external returns(uint){
        return 42;
    }
}
```

`DerivedContract` does not implement `BaseInterface.f2` or `BaseInterface2.f3`.
As a result, the contract will not properly compile.
All unimplemented functions must be implemented on a contract that is meant to be used.

### Recommendation

Implement all unimplemented functions in any contract you intend to use directly (not simply inherit from).

## Unindexed event address parameters

### Configuration

* Check: `unindexed-event-address`
* Severity: `Informational`
* Confidence: `High`

### Description

Detects events that have address-type parameters but no indexed parameters. Indexing event parameters enables efficient off-chain filtering.

### Exploit Scenario

```solidity
contract Token {
    event Transfer(address from, address to, uint256 value);

    function transfer(address to, uint256 value) external {
        // ...
        emit Transfer(msg.sender, to, value);
    }
}
```

The `Transfer` event has address parameters but none are indexed.
Off-chain tools cannot efficiently filter transfers by sender or recipient address.

### Recommendation

Add the `indexed` keyword to address parameters in events to enable efficient off-chain filtering.

## Unused state variable

### Configuration

* Check: `unused-state`
* Severity: `Informational`
* Confidence: `High`

### Description

Unused state variable.

### Recommendation

Remove unused state variables.

## Costly operations inside a loop

### Configuration

* Check: `costly-loop`
* Severity: `Informational`
* Confidence: `Medium`

### Description

Costly operations inside a loop might waste gas, so optimizations are justified.

### Exploit Scenario

```solidity
contract CostlyOperationsInLoop{

    uint loop_count = 100;
    uint state_variable=0;

    function bad() external{
        for (uint i=0; i < loop_count; i++){
            state_variable++;
        }
    }

    function good() external{
      uint local_variable = state_variable;
      for (uint i=0; i < loop_count; i++){
        local_variable++;
      }
      state_variable = local_variable;
    }
}
```

Incrementing `state_variable` in a loop incurs a lot of gas because of expensive `SSTOREs`, which might lead to an `out-of-gas`.

### Recommendation

Use a local variable to hold the loop computation result.

## Dead-code

### Configuration

* Check: `dead-code`
* Severity: `Informational`
* Confidence: `Medium`

### Description

Functions that are not used.

### Exploit Scenario

```solidity
contract Contract{
    function dead_code() internal() {}
}
```

`dead_code` is not used in the contract, and make the code's review more difficult.

### Recommendation

Remove unused functions.

## Reentrancy vulnerabilities

### Configuration

* Check: `reentrancy-unlimited-gas`
* Severity: `Informational`
* Confidence: `Medium`

### Description

Detection of the [reentrancy bug](https://github.com/trailofbits/not-so-smart-contracts/tree/master/reentrancy).
Only report reentrancy that is based on `transfer` or `send`.

### Exploit Scenario

```solidity
    function callme(){
        msg.sender.transfer(balances[msg.sender]):
        balances[msg.sender] = 0;
    }
```

`send` and `transfer` do not protect from reentrancies in case of gas price changes.

### Recommendation

Apply the [`check-effects-interactions` pattern](http://solidity.readthedocs.io/en/v0.4.21/security-considerations.html#re-entrancy).

## Too many digits

### Configuration

* Check: `too-many-digits`
* Severity: `Informational`
* Confidence: `Medium`

### Description

Literals with many digits are difficult to read and review. Use scientific notation or suffixes to make the code more readable.

### Exploit Scenario

```solidity
contract MyContract{
    uint 1_ether = 10000000000000000000;
}
```

While `1_ether` looks like `1 ether`, it is `10 ether`. As a result, it's likely to be used incorrectly.

### Recommendation

Use:

* [Ether suffix](https://solidity.readthedocs.io/en/latest/units-and-global-variables.html#ether-units),
* [Time suffix](https://solidity.readthedocs.io/en/latest/units-and-global-variables.html#time-units), or
* [The scientific notation](https://solidity.readthedocs.io/en/latest/types.html#rational-and-integer-literals)

## Cache array length

### Configuration

* Check: `cache-array-length`
* Severity: `Optimization`
* Confidence: `High`

### Description

Detects `for` loops that use `length` member of some storage array in their loop condition and don't modify it.

### Exploit Scenario

```solidity
contract C
{
    uint[] array;

    function f() public
    {
        for (uint i = 0; i < array.length; i++)
        {
            // code that does not modify length of `array`
        }
    }
}
```

Since the `for` loop in `f` doesn't modify `array.length`, it is more gas efficient to cache it in some local variable and use that variable instead, like in the following example:

```solidity
contract C
{
    uint[] array;

    function f() public
    {
        uint array_length = array.length;
        for (uint i = 0; i < array_length; i++)
        {
            // code that does not modify length of `array`
        }
    }
}
```

### Recommendation

Cache the lengths of storage arrays if they are used and not modified in `for` loops.

## State variables that could be declared constant

### Configuration

* Check: `constable-states`
* Severity: `Optimization`
* Confidence: `High`

### Description

State variables that are not updated following deployment should be declared constant to save gas.

### Recommendation

Add the `constant` attribute to state variables that never change.

## Public function that could be declared external

### Configuration

* Check: `external-function`
* Severity: `Optimization`
* Confidence: `High`

### Description

`public` functions that are never called by the contract should be declared `external`, and its immutable parameters should be located in `calldata` to save gas.

### Recommendation

Use the `external` attribute for functions never called from the contract, and change the location of immutable parameters to `calldata` to save gas.

## State variables that could be declared immutable

### Configuration

* Check: `immutable-states`
* Severity: `Optimization`
* Confidence: `High`

### Description

State variables that are not updated following deployment should be declared immutable to save gas.

### Recommendation

Add the `immutable` attribute to state variables that never change or are set only in the constructor.

## Public variable read in external context

### Configuration

* Check: `var-read-using-this`
* Severity: `Optimization`
* Confidence: `High`

### Description

The contract reads its own variable using `this`, adding overhead of an unnecessary STATICCALL.

### Exploit Scenario

```solidity
contract C {
    mapping(uint => address) public myMap;
    function test(uint x) external returns(address) {
        return this.myMap(x);
    }
}
```

### Recommendation

Read the variable directly from storage instead of calling the contract.

---

### Src Printers Printer Documentation (`docs/src/printers/Printer-documentation.md`)

Slither allows printing contracts information through its printers.

| Num | Printer             | Description                                                                                                      |
| --- | ------------------- | ---------------------------------------------------------------------------------------------------------------- |
| 1   | `call-graph`        | [Export the call-graph of the contracts to a dot file](#call-graph)                                              |
| 2   | `cfg`               | [Export the CFG of each functions](#cfg)                                                                         |
| 3   | `cheatcode`         | Print the usage of (Foundry) cheatcodes in the code.                                                             |
| 4   | `ck`                | Chidamber and Kemerer (CK) complexity metrics and related function attributes                                    |
| 5   | `constructor-calls` | [Print the constructors executed](#constructor-calls)                                                            |
| 6   | `contract-summary`  | [Print a summary of the contracts](#contract-summary)                                                            |
| 7   | `data-dependency`   | [Print the data dependencies of the variables](#data-dependencies)                                               |
| 8   | `declaration`       | Prototype showing the source code declaration, implementation and references of the contracts objects            |
| 9   | `dominator`         | Export the dominator tree of each functions                                                                      |
| 10  | `echidna`           | Export Echidna guiding information                                                                               |
| 11  | `entry-points`      | Print all the state-changing entry point functions of the contracts                                              |
| 12  | `evm`               | [Print the evm instructions of nodes in functions](#evm)                                                         |
| 13  | `function-id`       | [Print the keccak256 signature of the functions](#function-id)                                                   |
| 14  | `function-summary`  | [Print a summary of the functions](#function-summary)                                                            |
| 15  | `halstead`          | Computes the Halstead complexity metrics for each contract                                                       |
| 16  | `human-summary`     | [Print a human-readable summary of the contracts](#human-summary)                                                |
| 17  | `inheritance`       | [Print the inheritance relations between contracts](#inheritance)                                                |
| 18  | `inheritance-graph` | [Export the inheritance graph of each contract to a dot file](#inheritance-graph)                                |
| 19  | `loc`               | Count the total number lines of code (LOC), source lines of code (SLOC)                                          |
| 20  | `martin`            | Martin agile software metrics (Ca, Ce, I, A, D)                                                                  |
| 21  | `modifiers`         | Print the modifiers called by each function                                                                      |
| 22  | `not-pausable`      | Print functions that do not use whenNotPaused                                                                    |
| 23  | `require`           | [Print the require and assert calls of each function](#require)                                                  |
| 24  | `slithir`           | [Print the slithIR representation of the functions](#slithir)                                                    |
| 25  | `slithir-ssa`       | [Print the slithIR representation of the functions](#slithir-ssa)                                                |
| 26  | `variable-order`    | [Print the storage order of the state variables](#variable-order)                                                |
| 27  | `vars-and-auth`     | [Print the state variables written and the authorization of the functions](#variables-written-and-authorization) |

Several printers require xdot installed for visualization:

```
sudo apt install xdot
```

## Call Graph

`slither file.sol --print call-graph`

Export the call-graph of the contracts to a dot file

### Example

```
slither examples/printers/call_graph.sol --print call-graph
```

<img src="https://raw.githubusercontent.com/crytic/slither/master/examples/printers/call_graph.sol.dot.png">

The output format is [dot](https://www.graphviz.org/).
To visualize the graph:

```
xdot examples/printers/call_graph.sol.dot
```

To convert the file to svg:

```
dot examples/printers/call_graph.sol.dot -Tpng -o examples/printers/call_graph.sol.png
```

## CFG

Export the control flow graph of each function

`slither file.sol --print cfg`

### Example

The output format is [dot](https://www.graphviz.org/).
To visualize the graph:

```
xdot function.sol.dot
```

To convert the file to svg:

```
dot function.dot -Tsvg -o function.sol.png
```

## Contract Summary

Output a quick summary of the contract.

`slither file.sol --print contract-summary`

### Example

```
slither examples/printers/quick_summary.sol --print contract-summary
```

<img src="https://raw.githubusercontent.com/crytic/slither/master/examples/printers/quick_summary.sol.png">

## Data Dependencies

Print the data dependencies of the variables
`slither file.sol --print data-dependency`

### Example

```
slither examples/printers/data_dependencies.sol --print data-dependency
```

```
Contract MyContract
+----------+----------------------+
| Variable |     Dependencies     |
+----------+----------------------+
|    a     |     ['input_a']      |
|    b     | ['input_b', 'input'] |
|    c     |          []          |
+----------+----------------------+

Function setA(uint256,uint256)
+--------------+--------------+
|   Variable   | Dependencies |
+--------------+--------------+
|   input_a    |      []      |
|   input_b    |      []      |
| MyContract:a | ['input_a']  |
| MyContract:b |      []      |
| MyContract:c |      []      |
+--------------+--------------+
Function setB(uint256)
+--------------+----------------------+
|   Variable   |     Dependencies     |
+--------------+----------------------+
|    input     |     ['input_b']      |
| MyContract:a |          []          |
| MyContract:b | ['input_b', 'input'] |
| MyContract:c |          []          |
+--------------+----------------------+
```

## Constructor Calls

`slither file.sol --print constructor-calls`

Print the calling sequence of constructors based on C3 linearization.

### Example

```
...
$ slither examples/printers/constructors.sol --print constructor-calls
[..]

Contact Name: test2
        Constructor Call Sequence:   test--> test2
 Constructor Definitions:

  contract name : test2
     constructor()public{
        a=10;
    }

  contract name : test
     constructor()public{
        a =5;
    }


Contact Name: test3
        Constructor Call Sequence:   test--> test2--> test3
 Constructor Definitions:

  contract name : test3
     constructor(bytes32 _name)public{
        owner = msg.sender;
        name = _name;
        a=20;
    }

  contract name : test2
     constructor()public{
        a=10;
    }

  contract name : test
     constructor()public{
        a =5;
    }
```

## Echidna

This printer is meant to improve [Echidna](https://github.com/crytic/echidna) code coverage. The printer is a WIP and is not yet used by Echidna.

## EVM

`slither file.sol --print evm`

Print the EVM representation of the functions

> **Note:** Requires `evm-cfg-builder` to be installed:
>
> ```
> pip install evm-cfg-builder
> ```

### Example

```
$ slither examples/printers/evm.sol --print evm

INFO:Printers:Contract Test
 Function Test.foo()
  Node: ENTRY_POINT None
  Source line 5:   function foo() public returns (address) {
  EVM Instructions:
   0x44: JUMPDEST
   0x45: CALLVALUE
   0x50: POP
   0x51: PUSH1 0x56
   0x53: PUSH1 0x98
   0x55: JUMP
   0x56: JUMPDEST
   0x57: PUSH1 0x40
   0x59: MLOAD
   0x5a: DUP1
   0x5b: DUP3
   0x5c: PUSH20 0xffffffffffffffffffffffffffffffffffffffff
   0x71: AND
   0x72: PUSH20 0xffffffffffffffffffffffffffffffffffffffff
   0x87: AND
   0x88: DUP2
   0x89: MSTORE
   0x8a: PUSH1 0x20
   0x8c: ADD
   0x8d: SWAP2
   0x8e: POP
   0x8f: POP
   0x90: PUSH1 0x40
   0x92: MLOAD
   0x93: DUP1
   0x94: SWAP2
   0x95: SUB
   0x96: SWAP1
   0x97: RETURN
   0x98: JUMPDEST
   0x99: PUSH1 0x0
   0xa2: POP
   0xa3: SWAP1
                        0xa4: JUMP
                Node: NEW VARIABLE from = msg.sender
                Source line 6:     address from = msg.sender;
                EVM Instructions:
                        0x9b: DUP1
                        0x9c: CALLER
                        0x9d: SWAP1
                        0x9e: POP
                Node: RETURN (from)
                Source line 7:     return(from);
                EVM Instructions:
                        0x9f: DUP1
                        0xa0: SWAP2
                        0xa1: POP
```

## Function ID

`slither file.sol --print function-id`
Print the keccack256 signature of the functions

### Examples

```
$ slither examples/printers/authorization.sol --print function-id
INFO:Printers:
MyContract:
+---------------+------------+
|      Name     |     ID     |
+---------------+------------+
| constructor() | 0x90fa17bb |
| mint(uint256) | 0xa0712d68 |
+---------------+------------+
```

## Function Summary

`slither file.sol --print function-summary`

Output a summary of the contract showing for each function:

- What are the visibility and the modifiers
- What are the state variables read or written
- What are the calls

### Example

```
slither tests/backdoor.sol --print function-summary
```

```
[...]

Contract C
Contract vars: []
Inheritances:: []

+-----------------+------------+-----------+----------------+-------+---------------------------+----------------+
|     Function    | Visibility | Modifiers |      Read      | Write |       Internal Calls      | External Calls |
+-----------------+------------+-----------+----------------+-------+---------------------------+----------------+
| i_am_a_backdoor |   public   |     []    | ['msg.sender'] |   []  | ['selfdestruct(address)'] |       []       |
+-----------------+------------+-----------+----------------+-------+---------------------------+----------------+

+-----------+------------+------+-------+----------------+----------------+
| Modifiers | Visibility | Read | Write | Internal Calls | External Calls |
+-----------+------------+------+-------+----------------+----------------+
+-----------+------------+------+-------+----------------+----------------+
```

## Human Summary

`slither file.sol --print human-summary`

Print a human-readable summary of the contracts

### Example

```
slither examples/printers/human_printer.sol --print human-summary
```

<img src="https://raw.githubusercontent.com/crytic/slither/master/examples/printers/human_printer.sol.png">

## Inheritance

`slither file.sol --print inheritance`
Print the inheritance relations between contracts

### Example

```
slither examples/printers/inheritances.sol --print inheritance
```

<img src="https://raw.githubusercontent.com/crytic/slither/master/examples/printers/inheritances.sol.png">

## Inheritance Graph

`slither file.sol --print inheritance-graph`

Output a graph showing the inheritance interaction between the contracts.

### Example

```
$ slither examples/printers/inheritances.sol --print inheritance-graph
[...]
INFO:PrinterInheritance:Inheritance Graph: examples/DAO.sol.dot
```

The output format is [dot](https://www.graphviz.org/).
To visualize the graph:

```
xdot examples/printers/inheritances.sol.dot
```

To convert the file to svg:

```
dot examples/printers/inheritances.sol.dot -Tsvg -o examples/printers/inheritances.sol.png
```

<img src="https://raw.githubusercontent.com/crytic/slither/master/examples/printers/inheritances_graph.sol.png">

Indicators:

- If a contract has multiple inheritance, the connecting edges will be labelled in order of declaration.
- Functions highlighted orange override a parent's function.
- Functions which do not override each other directly (but collide due to multiple inheritance) will be emphasized at the bottom of the affected contract node in grey font.
- Variables highlighted red overshadow a parent's variable declaration.
- Variables of type `contract` specify the contract name in parentheses in a blue font.

## Modifiers

`slither file.sol --print modifiers`

Print the modifiers called by each function.

### Example

```
$ slither examples/printers/modifier.sol --print modifiers
INFO:Printers:
Contract C
+-------------+-------------+
|   Function  |  Modifiers  |
+-------------+-------------+
| constructor |      []     |
|     set     | ['isOwner'] |
+-------------+-------------+
```

## Require

`slither file.sol --print require`

Print the require and assert calls of each function.

### Example

```
$ slither examples/printers/require.sol --print require
INFO:Printers:
Contract Lib
+----------+--------------------------------------+
| Function |          require or assert           |
+----------+--------------------------------------+
|   set    | require(bool)(msg.sender == s.owner) |
+----------+--------------------------------------+
INFO:Printers:
Contract C
+-------------+--------------------------------------+
|   Function  |          require or assert           |
+-------------+--------------------------------------+
| constructor |                                      |
|     set     | require(bool)(msg.sender == s.owner) |
+-------------+--------------------------------------+
```

## SlithIR

`slither file.sol --print slithir`

Print the slithIR representation of the functions

### Example

```
$ slither examples/printers/slihtir.sol --print slithir
Contract UnsafeMath
 Function add(uint256,uint256)
  Expression: a + b
  IRs:
   TMP_0(uint256) = a + b
   RETURN TMP_0
 Function min(uint256,uint256)
  Expression: a - b
  IRs:
   TMP_0(uint256) = a - b
   RETURN TMP_0
Contract MyContract
 Function transfer(address,uint256)
  Expression: balances[msg.sender] = balances[msg.sender].min(val)
  IRs:
   REF_3(uint256) -> balances[msg.sender]
   REF_1(uint256) -> balances[msg.sender]
   TMP_1(uint256) = LIBRARY_CALL, dest:UnsafeMath, function:min, arguments:['REF_1', 'val']
   REF_3 := TMP_1
  Expression: balances[to] = balances[to].add(val)
  IRs:
   REF_3(uint256) -> balances[to]
   REF_1(uint256) -> balances[to]
   TMP_1(uint256) = LIBRARY_CALL, dest:UnsafeMath, function:add, arguments:['REF_1', 'val']
   REF_3 := TMP_1
```

## SlithIR-SSA

`slither file.sol --print slithir-ssa`

Print the slithIR representation of the functions (SSA version)

## Variable order

`slither file.sol --print variable-order`

Print the storage order of the state variables

### Example

```
$ slither tests/check-upgradability/contractV2_bug.sol --print variable-order
INFO:Printers:
ContractV2:
+-------------+---------+
|     Name    |   Type  |
+-------------+---------+
| destination | uint256 |
|    myFunc   | uint256 |
+-------------+---------+

```

## Variables written and authorization

`slither file.sol --print vars-and-auth`

Print the variables written and the check on `msg.sender` of each function.

### Example

```
...
$ slither examples/printers/authorization.sol --print vars-and-auth
[..]
INFO:Printers:
Contract MyContract
+-------------+-------------------------+----------------------------------------+
|   Function  | State variables written |        Conditions on msg.sender        |
+-------------+-------------------------+----------------------------------------+
| constructor |        ['owner']        |                   []                   |
|     mint    |       ['balances']      | ['require(bool)(msg.sender == owner)'] |
+-------------+-------------------------+----------------------------------------+
```

---

### Src Tools Adding A New Utility (`docs/src/tools/Adding-a-new-utility.md`)

# Adding New Utility

Slither can be used as a library to create new utilities.
Official utils are present in [tools](https://github.com/crytic/slither/tree/master/slither/tools)

## Skeleton

The skeleton util is present in [tools/demo](https://github.com/crytic/slither/tree/master/slither/tools/demo)

## Integration

To enable an util from the command-line, update `project.scripts` in [pyproject.toml](https://github.com/crytic/slither/blob/master/pyproject.toml).
Installing Slither will then install the util.

## Guidelines

- Favor the `logging` module rather than `print`
- Favor raising an exception rather than `sys.exit`
- Add unit-tests (ex: [scripts/travis_test_find_paths.sh](https://github.com/crytic/slither/blob/master/scripts/ci_test_find_paths.sh))

## Getting Help

Join our [slack channel](https://empireslacking.herokuapp.com/) to get any help (#ethereum).

---

### Src Tools Code Similarity Detector (`docs/src/tools/Code-Similarity-Detector.md`)

`slither-simil` uses state-of-the-art machine learning to detect similar (vulnerable) Solidity functions. We have provided a pretrained model from [etherscan_verified_contracts](https://github.com/thec00n/etherscan_verified_contracts) with 60,000 contracts and more than 850,000 functions to get you started quickly. We included the capability to easily train new models if you have access to larger or different datasets.

`slither-simil` uses [FastText](https://github.com/facebookresearch/fastText), a vector embedding technique, to generate compact numerical representations of every function. We used FastText because it:

- implements several state-of-the-art techniques such as nbow and skipgrams,
- has high performance (it is C++ code with Python bindings),
- has MIT license, and
- is well maintained (by Facebook).

## Requirements

Install the required packages before using `slither-simil`:

```
pip3 install pybind11 --user
pip3 install https://github.com/facebookresearch/fastText/archive/0.2.0.zip --user
pip3 install sklearn matplotlib --user # for plot mode
```

Make sure that you are using `pip3.6` or later. If you are running from inside a [virtualenv](https://virtualenv.pypa.io/en/latest/), remove the `--user` parameter.

## Usage

Note that these examples will use the following files:

- [etherscan_verified_contracts.bin](https://drive.google.com/file/d/1oEhbIL4V9582Y5VKp4iiOURGq8qa4cBN/view?usp=sharing)
- [cache.npz](https://drive.google.com/file/d/1vpwusbyzLn1JqqAvlFivHXtLvsEp0VqX/view?usp=sharing)
- [MetaCoin.sol](https://github.com/crytic/slither/wiki/MetacoinExample)

`slither-simil` has three modes:

- `test` - finds similar functions to your own in a dataset of contracts
- `plot` - provide a visual representation of similarity of multiple sampled functions
- `train` - builds new models of large datasets of contracts
- `info` - inspects the internal information of the pre-trained model or the assessed code

### Test mode

This mode transforms a function into a vector and uses it to find similar functions.

Test mode requires the following parameters:

1. A pre-trained model: this file will be used to transform every function into a vector, you can [train your own](#train-mode) or [use our pre-trained one (etherscan_verified_contracts.bin)](#usage).
2. A contract filename: this file will contain the code that you want to compare,
3. A function name (e.g. `SafeMath.add` or `add`),
4. An input directory or file: this can be either a directory with contracts or a [cache file with a pre-computed list of vectors for every contract (cache.npz)](#usage).

Use the cache to avoid long processing times to compile and vectorize the input contracts.

Here's an example that finds functions similar to `sendCoin` in `MetaCoin` (compiled with `solc-0.4.25`). Searching for similar functions among more than 800,000 functions takes only 20 seconds.

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Train mode

Train mode trains new models used to vectorize functions. You will need a large amount of contracts/functions if you plan to train a new model.

```
$ slither-simil train model.bin --input contracts
INFO:Slither-simil:Saving extracted data into last_data_train.txt
INFO:Slither-simil:Starting training
Read 0M words
Number of words:  348
Number of labels: 0
Progress: 100.0% words/sec/thread:   53124 lr:  0.000000 loss:  2.066949 ETA:   0h 0m
INFO:Slither-simil:Training complete
INFO:Slither-simil:Saving model
INFO:Slither-simil:Saving cache in cache.npz
INFO:Slither-simil:Done!
```

After it runs, the `slither-simil` will output the trained model in `model.bin`, a cache of every function for use in test mode in `cache.npz`, and the SlithIR of every function for debugging in `last_data_train.txt`.

### Plot mode

Plot mode plots sets of functions to visually detect clusters of similar ones.

Here's an example to plot all the functions named `add` from contracts named `SafeMath` sampling from 500 random contracts:

```
$ slither-simil plot etherscan_verified_contracts.bin --fname SafeMath.add --input cache.npz --nsamples 500
INFO:Slither-simil:Loading data..
INFO:Slither-simil:Processing data..
INFO:Slither-simil:Plotting data..
INFO:Slither-simil:Saving figure to plot.png..
```



This mode performs dimensionality reduction using PCA, so the axes you see here [are **not** associated with any particular unit](https://stats.stackexchange.com/questions/137813/the-meaning-of-units-on-the-axes-of-a-pca-plot).

It can also be used to plot sets of functions using only a name from any contract (e.g. `burn`) .

### Info mode

This mode has two features. You can inspect the internal information about a pre-trained model. Info mode is typically used for debugging.

```
$ slither-simil info etherscan_verified_contracts.bin
INFO:Slither-simil:etherscan_verified_contracts.bin uses the following words:
INFO:Slither-simil:</s>
INFO:Slither-simil:index(uint256)
INFO:Slither-simil:return
INFO:Slither-simil:condition(temporary_variable)
INFO:Slither-simil:member
INFO:Slither-simil:solidity_call(require(bool))
INFO:Slither-simil:library_call
INFO:Slither-simil:binary(+)
INFO:Slither-simil:event
INFO:Slither-simil:(local_solc_variable(default)):=(temporary_variable)
...
```

... or examine the internal representation of function:

```
$ slither-simil info etherscan_verified_contracts.bin --filename MetaCoin.sol --fname MetaCoin.sendCoin --solc solc-0.4.25
INFO:Slither-simil:Function sendCoin in contract MetaCoin is encoded as:
INFO:Slither-simil:index(uint256) binary(<) condition(temporary_variable) return index(uint256) binary(-) index(uint256) binary(+) event return
INFO:Slither-simil:[ 0.00689753 -0.05349572 -0.06854086 -0.01667773  0.1259813  -0.05974023
  0.06719872 -0.04520541  0.13745852  0.14690697 -0.03721125  0.00579037
  0.06865194 -0.03804035  0.01224702 -0.1014601  -0.02655532 -0.15334933
...
```

---

### Src Tools Contract Flattening (`docs/src/tools/Contract-Flattening.md`)

# slither-flat

`slither-flat` produces a flattened version of the codebase.

## Features

- Code flattening
- Support multiple [strategies](#strategies)
- Support circular dependency
- Support all the compilation platforms (Truffle, embark, buidler, etherlime, ...).

## Usage

`slither-flat target`

- `--contract ContractName`: flatten only one contract (standalone file)

### Strategies

`slither-flat` contains three strategies that can be specified with the `--strategy` flag:

- `MostDerived`: Export all the most derived contracts (every file is standalone)
- `OneFile`: Export all the contracts in one standalone file
- `LocalImport`: Export every contract in one separate file, and include import ".." in their preludes

Default: `MostDerived`

### Patching

`slither-flat` can transform the codebase to help some usage (eg. [Echidna](https://github.com/crytic/echidna))

- `--convert-external`: convert `external` function to `public`. This is meant to facilitate [Echidna](https://github.com/crytic/echidna) usage.
- `--contract name`: To flatten only a target contract
- `--remove-assert`: Remove call to assert().

### Export option

- `--dir DirName`: output directory
- `--json file.json`: export the results to a json file (`--json -` output to the standard output
- `--zip file.zip`: export to a ZIP file
- `--zip-type type`: ZIP compression type (default lzma))

---

### Src Tools Doctor (`docs/src/tools/Doctor.md`)

# Slither doctor

Slither doctor is a tool designed to troubleshoot running Slither on a project.

---

### Src Tools Documentation (`docs/src/tools/Documentation.md`)

# slither-documentation

`slither-documentation` uses [codex](https://platform.openai.com) to generate natspec documentation.

This tool is experimental. See [solmate documentation](https://github.com/montyly/solmate/pull/1) for an example of usage.

---

### Src Tools ERC Conformance (`docs/src/tools/ERC-Conformance.md`)

# slither-check-erc

`slither-check-erc` checks for ERC's conformance.

## Features

`slither-check-erc` will check that:

- All the functions are present
- All the events are present
- Functions return the correct type
- Functions that must be view are view
- Events' parameters are correctly indexed
- The functions emit the events
- Derived contracts do not break the conformance

## Supported ERCs

- [ERC20](https://eips.ethereum.org/EIPS/eip-20): Token standard
- [ERC223](https://github.com/ethereum/eips/issues/223): Token standard
- [ERC777](https://eips.ethereum.org/EIPS/eip-777): Token standard
- [ERC721](https://eips.ethereum.org/EIPS/eip-721): Non-fungible token standard
- [ERC165](https://eips.ethereum.org/EIPS/eip-165): Standard interface detection
- [ERC1155](https://eips.ethereum.org/EIPS/eip-1155): Multi Token Standard
- [ERC1820](https://eips.ethereum.org/EIPS/eip-1820): Pseudo-introspection registry contract
- [ERC4524](https://eips.ethereum.org/EIPS/eip-4524): Safer ERC-20
- [ERC1363](https://eips.ethereum.org/EIPS/eip-1363): Payable Token
- [ERC2612](https://eips.ethereum.org/EIPS/eip-2612): Permit Extension for EIP-20 Signed Approvals
- [ERC4626](https://eips.ethereum.org/EIPS/eip-4626): Tokenized Vaults

## Usage

```sh
slither-check-erc contract.sol ContractName
```

For example, on

```solidity
contract ERC20{

    event Transfer(address indexed,address,uint256);

    function transfer(address, uint256) public{

        emit Transfer(msg.sender,msg.sender,0);
    }

}
```

The tool will report:

```text
# Check ERC20

## Check functions
[ ] totalSupply() is missing
[ ] balanceOf(address) is missing
[✓] transfer(address,uint256) is present
 [ ] transfer(address,uint256) -> () should return bool
 [✓] Transfer(address,address,uint256) is emitted
[ ] transferFrom(address,address,uint256) is missing
[ ] approve(address,uint256) is missing
[ ] allowance(address,address) is missing
[ ] name() is missing (optional)
[ ] symbol() is missing (optional)
[ ] decimals() is missing (optional)

## Check events
[✓] Transfer(address,address,uint256) is present
 [✓] parameter 0 is indexed
 [ ] parameter 1 should be indexed
[ ] Approval(address,address,uint256) is missing
```

---

### Src Tools Interface (`docs/src/tools/Interface.md`)

# Slither-interface

Generates code for a Solidity interface from contract

## Usage

Run `slither-interface <ContractName> <source file or deployment address>`.

## CLI Interface

```shell
positional arguments:
  contract_source       The name of the contract (case sensitive) followed by the deployed contract address if verified on etherscan or project directory/filename for local contracts.

optional arguments:
  -h, --help            show this help message and exit
  --unroll-structs      Whether to use structures' underlying types instead of the user-defined type
  --exclude-events      Excludes event signatures in the interface
  --exclude-errors      Excludes custom error signatures in the interface
  --exclude-enums       Excludes enum definitions in the interface
  --exclude-structs     Exclude struct definitions in the interface
```

---

### Src Tools Mutator (`docs/src/tools/Mutator.md`)

# Slither-mutate

`slither-mutate` is a mutation testing tool for solidity based smart contracts.

## Quick Start

In a foundry project with **passing** tests that are run with `forge test`, you can mutate all solidity files in the `src` folder by running the following:

`slither-mutate src --test-cmd='forge test'`

You can provide flags to `forge` as part of the `--test-cmd` parameter or target a single file path instead of the whole `src` directory, for example:

`slither-mutate src/core/MyContract.sol --test-cmd='forge test --match-contract="MyContract"'`

If a `timout` flag is not provided, slither-mutate will default to using a value that's double the runtime of it's initial test cmd execution. Make sure you run `forge clean` or similar beforehand to ensure cache usage doesn't cause a timeout that's too short to be used; this could lead to false-negatives.

### CLI Interface

```shell
$ slither-mutate --help
usage: slither-mutate <codebase> --test-cmd <test command> <options>

Experimental smart contract mutator. Based on https://arxiv.org/abs/2006.11597

positional arguments:
  codebase              Codebase to analyze (.sol file, project directory, ...)

options:
  -h, --help            show this help message and exit
  --list-mutators       List available detectors
  --test-cmd TEST_CMD   Command to run the tests for your project
  --test-dir TEST_DIR   Tests directory
  --ignore-dirs IGNORE_DIRS
                        Directories to ignore
  --timeout TIMEOUT     Set timeout for test command (by default 2x the initial test runtime)
  --output-dir OUTPUT_DIR
                        Name of output directory (by default 'mutation_campaign')
  -v, --verbose         log mutants that are caught, uncaught, and fail to compile
  --mutators-to-run MUTATORS_TO_RUN
                        mutant generators to run
  --contract-names CONTRACT_NAMES
                        list of contract names you want to mutate
  --target-functions TARGET_FUNCTIONS
                        Comma-separated list of function selectors (hex like
                        0xa9059cbb or signature like transfer(address,uint256))
  --comprehensive       continue testing minor mutations if severe mutants are uncaught
```

---

### Src Tools Path Finding Utility (`docs/src/tools/Path-Finding-Utility.md`)

# slither-find-paths

`slither-find-paths` finds all the paths that reach a given target.

## Usage

```sh
slither-find-paths file.sol [contract.function targets]
```

- `[contract.function targets]` is either one target, or a list of target

## Example

Tested on [tests/e2e/printers/possible_paths/paths.sol](https://github.com/crytic/slither/blob/master/tests/e2e/printers/possible_paths/paths.sol)

```sh
$ slither-find-paths paths.sol A.destination
Target functions:
- A.destination()


The following functions reach the specified targets:
- A.call()
- B.call2(A)


The following paths reach the specified targets:
A.call() -> A.destination()

B.call2(A) -> A.call() -> A.destination()
```

---

### Src Tools Property Generation (`docs/src/tools/Property-generation.md`)

`slither-prop` generates code properties (e.g., invariants) that can be tested with unit tests or [Echidna](https://github.com/crytic/echidna/), entirely automatically. Once you have these properties in hand, use [Crytic](https://crytic.io/) to continuously test them with every commit.

Note: `slither-prop` only supports Truffle for now. We'll be adding support for other frameworks soon!

## How to Use Slither's Property Generator

There are four steps:

1. [Generate the tests](#step-1-generate-the-tests)
1. [Customize the constructor](#step-2-customize-the-constructor)
1. [Run the unit tests](#step-3-run-the-unit-tests-with-truffle)
1. [Run the Echidna tests](#step-4-run-the-property-tests-with-echidna)

### Step 1. Generate the tests

```
slither-prop . --contract ContractName
```

`slither-prop` will generate:

- Solidity files containing the properties
- `echidna_config.yaml` to configure Echidna
- One Truffle migration file
- Two Truffle unit-test files

For example on [examples/slither-prop](https://github.com/crytic/slither/tree/9623a2781faa4e7759f06d2e8c4adcd45078af69/examples/slither-prop).

```
Write contracts/crytic/interfaces.sol
Write contracts/crytic/PropertiesERC20BuggyTransferable.sol
Write contracts/crytic/TestERC20BuggyTransferable.sol
Write echidna_config.yaml
Write migrations/1_TestERC20BuggyTransferable.js
Write test/crytic/InitializationTestERC20BuggyTransferable.js
Write test/crytic/TestERC20BuggyTransferable.js
################################################
Update the constructor in contracts/crytic/TestERC20BuggyTransferable.sol

To run the unit tests:
 truffle test test/crytic/InitializationTestERC20BuggyTransferable.js
 truffle test test/crytic/TestERC20BuggyTransferable.js

To run Echidna:
  echidna-test . --contract TestERC20BuggyTransferable --config echidna_config.yaml
```

### Step 2. Customize the constructor

Next, update the constructor in `contracts/crytic/TestX.sol`:

On [examples/slither-prop/contracts](https://github.com/crytic/slither/tree/9623a2781faa4e7759f06d2e8c4adcd45078af69/examples/slither-prop), update the constructor as follow:

```solidity
 constructor() public{

  _balanceOf[crytic_user] = 1 ether;
  _balanceOf[crytic_owner] = 1 ether;
  _balanceOf[crytic_attacker] = 1 ether;
  _totalSupply = 3 ether;

  //
  //
  // Update the following if totalSupply and balanceOf are external functions or state variables:

  initialTotalSupply = totalSupply();
  initialBalance_owner = balanceOf(crytic_owner);
  initialBalance_user = balanceOf(crytic_user);
  initialBalance_attacker = balanceOf(crytic_attacker);
 }
```

### Step 3. Run the unit tests with Truffle

The first unit test file, named `InitializationX.js` will check that the constructor has been correctly initialized:

```
$ truffle test test/crytic/InitializationTestERC20BuggyTransferable.js
[..]
  Contract: TestERC20BuggyTransferable
    ✓ The total supply is correctly initialized. (47ms)
    ✓ Owner's balance is correctly initialized.
    ✓ User's balance is correctly initialized.
    ✓ Attacker's balance is correctly initialized.
    ✓ All the users have a positive balance. (69ms)
    ✓ The total supply is the user and owner balance. (38ms)

```

If all the unit tests passed, run the property tests:

```
$ truffle test test/crytic/InitializationTestERC20BuggyTransferable.js
  Contract: TestERC20BuggyTransferable
    ✓ The address 0x0 should not receive tokens.
    ✓ Allowance can be changed. (108ms)
    ✓ Balance of one user must be less or equal to the total supply. (70ms)
    ✓ Balance of the crytic users must be less or equal to the total supply.
    1) No one should be able to send tokens to the address 0x0 (transfer).
    > No events were emitted
    2) No one should be able to send tokens to the address 0x0 (transferFrom).
    > No events were emitted
    ✓ Self transferFrom works. (115ms)
    ✓ transferFrom works. (108ms)
    ✓ Self transfer works. (89ms)
    ✓ transfer works. (97ms)
    3) Cannot transfer more than the balance.
    > No events were emitted

```

As you can see, the unit tests detect some of the bugs.

### Step 4. Run the property tests with Echidna

```
echidna-test . --contract TestERC20BuggyTransferable --config echidna_config.yaml
```

## Scenarios

`slither-prop` contains different scenarios that can be specified with the `--scenario NAME` flag.

Here are the available scenarios:

```
#################### ERC20 ####################
Transferable - Test the correct tokens transfer
Pausable - Test the pausable functionality
NotMintable - Test that no one can mint tokens
NotMintableNotBurnable - Test that no one can mint or burn tokens
NotBurnable - Test that no one can burn tokens
Burnable - Test the burn of tokens. Require the "burn(address) returns()" function
```

## All properties

```
/* Detailed source-code truncated for AI context efficiency. */
```

---

### Src Tools ReadStorage (`docs/src/tools/ReadStorage.md`)

# Slither-read-storage

Slither-read-storage is a tool to retrieve the storage slots and values of entire contracts or single variables.

## Usage

### CLI Interface

```shell
positional arguments:
  contract_source       The deployed contract address if verified on etherscan. Prepend project directory for unverified contracts.

optional arguments:
  -h, --help            show this help message and exit
  --variable-name VARIABLE_NAME
                        The name of the variable whose value will be returned.
  --rpc-url RPC_URL     An endpoint for web3 requests.
  --key KEY             The key/ index whose value will be returned from a mapping or array.
  --deep-key DEEP_KEY   The key/ index whose value will be returned from a deep mapping or multidimensional array.
  --struct-var STRUCT_VAR
                        The name of the variable whose value will be returned from a struct.
  --storage-address STORAGE_ADDRESS
                        The address of the storage contract (if a proxy pattern is used).
  --contract-name CONTRACT_NAME
                        The name of the logic contract.
  --json JSON           Save the result in a JSON file.
  --value               Toggle used to include values in output.
  --table               Print table view of storage layout
  --silent              Silence log outputs
  --max-depth MAX_DEPTH
                        Max depth to search in data structure.
  --block BLOCK         The block number to read storage from. Requires an archive node to be provided as the RPC url.
  --unstructured        Include unstructured storage slots
```

### Examples

Retrieve the storage slots of a local contract:

```shell
slither-read-storage file.sol 0x8ad599c3a0ff1de082011efddc58f1908eb6e6d8 --json storage_layout.json
```

Retrieve the storage slots of a contract verified on an Etherscan-like platform:

```shell
slither-read-storage 0x8ad599c3a0ff1de082011efddc58f1908eb6e6d8 --json storage_layout.json
```

To retrieve the values as well, pass `--value` and `--rpc-url $RPC_URL`:

```shell
slither-read-storage 0x8ad599c3a0ff1de082011efddc58f1908eb6e6d8 --json storage_layout.json --rpc-url $RPC_URL --value
```

To view only the slot of the `slot0` structure variable, pass `--variable-name slot0`:

```shell
slither-read-storage 0x8ad599c3a0ff1de082011efddc58f1908eb6e6d8 --variable-name slot0 --rpc-url $RPC_URL --value
```

To view a member of the `slot0` struct, pass `--struct-var tick`

```shell
slither-read-storage 0x8ad599c3a0ff1de082011efddc58f1908eb6e6d8 --variable-name slot0 --rpc-url $RPC_URL --value --struct-var tick
```

Retrieve the ERC20 balance slot of an account:

```shell
slither-read-storage 0xa2327a938Febf5FEC13baCFb16Ae10EcBc4cbDCF --variable-name balances --key 0xab5801a7d398351b8be11c439e05c5b3259aec9b
```

To retrieve the actual balance, pass `--variable-name balances` and `--key 0xab5801a7d398351b8be11c439e05c5b3259aec9b`. (`balances` is a `mapping(address => uint)`)
Since this contract uses the delegatecall-proxy pattern, the proxy address must be passed as the `--storage-address`. Otherwise, it is not required.

```shell
slither-read-storage 0xa2327a938Febf5FEC13baCFb16Ae10EcBc4cbDCF --variable-name balances --key 0xab5801a7d398351b8be11c439e05c5b3259aec9b --storage-address 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48 --rpc-url $RPC_URL --value
```

## Troubleshooting/FAQ

- If the storage slots or values of a contract verified Etherscan are wrong, try passing `--contract $CONTRACT_NAME` explicitly. Otherwise, the storage may be retrieved from storage slots based off an unrelated contract (Etherscan includes these). (Also, make sure that the RPC is for the correct network.)

- If Etherscan fails to return a source code, try passing `--etherscan-apikey $API_KEY` to avoid hitting a rate-limit.

- How do I use this tool on other chains?
  If an EVM chain has an Etherscan-like platform the crytic-compile supports, this tool supports it by making the following modifications.
  Take Avalanche, for instance:

  ```shell
  slither-read-storage avax:0x0000000000000000000000000000000000000000 --json storage_layout.json --value --rpc-url $AVAX_RPC_URL
  ```

## Limitations

- Requires source code.
- Only works on Solidity contracts.
- Cannot find variables with unstructured storage.
- Does not support all data types (please open an issue or PR).
- Mappings cannot be completely enumerated since all keys used historically are not immediately available.

---

### Src Tools Slither Format (`docs/src/tools/Slither-format.md`)

# slither-format

`slither-format` generates automatically patches. The patches are compatible with `git`.

Carefully review each patch before applying it.

## Usage

`slither-format target`.

The patches will be generated in `crytic-export/patches`

## Detectors supported

- `unused-state`
- `solc-version`
- `pragma`
- `naming-convention`
- `external-function`
- `constable-states`
- `constant-function`

---

### Src Tools Upgradeability Checks (`docs/src/tools/Upgradeability-Checks.md`)

# Upgradeability Checks

`slither-check-upgradeability` helps review contracts that use the [delegatecall proxy pattern](https://blog.trailofbits.com/2018/09/05/contract-upgrade-anti-patterns/).

## Checks

| Num | Check                   | What it Detects                                                                         | Impact        | Proxy | Contract V2 |
| --- | ----------------------- | --------------------------------------------------------------------------------------- | ------------- | ----- | ----------- |
| 1   | `became-constant`       | [Variables that should not be constant](#variables-that-should-not-be-constant)         | High          |       | X           |
| 2   | `function-id-collision` | [Functions IDs collision](#functions-ids-collisions)                                    | High          | X     |
| 3   | `function-shadowing`    | [Functions shadowing](#functions-shadowing)                                             | High          | X     |
| 4   | `missing-calls`         | [Missing calls to init functions](#initialize-functions-are-not-called)                 | High          |       |
| 5   | `missing-init-modifier` | [initializer() is not called](#initializer-is-not-called)                               | High          |       |
| 6   | `multiple-calls`        | [Init functions called multiple times](#initialize-functions-are-called-multiple-times) | High          |       |
| 7   | `order-vars-contracts`  | [Incorrect vars order with the v2](#incorrect-variables-with-the-v2)                    | High          |       | X           |
| 8   | `order-vars-proxy`      | [Incorrect vars order with the proxy](#incorrect-variables-with-the-proxy)              | High          | X     |
| 9   | `variables-initialized` | [State variables with an initial value](#state-variable-initialized)                    | High          |       |
| 10  | `were-constant`         | [Variables that should be constant](#variables-that-should-be-constant)                 | High          |       | X           |
| 11  | `extra-vars-proxy`      | [Extra vars in the proxy](#extra-variables-in-the-proxy)                                | Medium        | X     |
| 12  | `missing-variables`     | [Variable missing in the v2](#missing-variables)                                        | Medium        |       | X           |
| 13  | `extra-vars-v2`         | [Extra vars in the v2](#extra-variables-in-the-v2)                                      | Informational |       | X           |
| 14  | `init-inherited`        | [Initializable is not inherited](#initializable-is-not-inherited)                       | Informational |       |
| 15  | `init-missing`          | [Initializable is missing](#initializable-is-missing)                                   | Informational |       |
| 16  | `initialize-target`     | [Initialize function that must be called](#initialize-function)                         | Informational |       |
| 17  | `initializer-missing`   | [initializer() is missing](#initializer-is-missing)                                     | Informational |       |

## Usage

```
slither-check-upgradeability project ContractName
```

- `project` can be a Solidity file, or a platform (truffle/embark/..) directory

### Contract V2

If you want to check the contract and its update, use:

- `--new-contract-name ContractName`
- `--new-contract-filename contract_project`

`--new-contract-filename` is not needed if the new contract is in the same codebase than the original one.

### Proxy

If you want to check also the proxy, use:

- `--proxy-name ProxyName`
- `--proxy-filename proxy_project`

`--proxy-filename` is not needed if the proxy is in the same codebase than the targeted contract.

#### ZOS

If you use zos, you will have the proxy and the contract in different directories.

Likely, you will use one of the proxy from <https://github.com/zeppelinos/zos>. Clone the `zos`, and install the dependencies:

```
git clone https://github.com/zeppelinos/zos
cd zos/packages/lib
npm install
rm contracts/mocks/WithConstructorImplementation.sol
```

Note: `contracts/mocks/WithConstructorImplementation.sol` must be removed as it contains a [name clash collision](https://github.com/crytic/slither/wiki#keyerror-or-nonetype-error) with `contracts/mocks/Invalid.sol`

Then from your project directory:

```
slither-check-upgradeability . ContractName --proxy-filename /path/to/zos/packages/lib/ --proxy-name UpgradeabilityProxy
```

According to your setup, you might choose another proxy name than `UpgradeabilityProxy`.

## Checks Description

## Variables that should not be constant

### Configuration

- Check: `became-constant`
- Severity: `High`

### Description

Detect state variables that should not be `constant̀`.

### Exploit Scenario

```solidity
contract Contract{
    uint variable1;
    uint variable2;
    uint variable3;
}

contract ContractV2{
    uint variable1;
    uint constant variable2;
    uint variable3;
}
```

Because `variable2` is now a `constant`, the storage location of `variable3` will be different.
As a result, `ContractV2` will have a corrupted storage layout.

### Recommendation

Do not make an existing state variable `constant`.

## Functions IDs collisions

### Configuration

- Check: `function-id-collision`
- Severity: `High`

### Description

Detect function ID collision between the contract and the proxy.

### Exploit Scenario

```solidity
contract Contract{
    function gsf() public {
        // ...
    }
}

contract Proxy{
    function tgeo() public {
        // ...
    }
}
```

`Proxy.tgeo()` and `Contract.gsf()` have the same function ID (0x67e43e43).
As a result, `Proxy.tgeo()` will shadow Contract.gsf()`.

### Recommendation

Rename the function. Avoid public functions in the proxy.

## Functions shadowing

### Configuration

- Check: `function-shadowing`
- Severity: `High`

### Description

Detect function shadowing between the contract and the proxy.

### Exploit Scenario

```solidity
contract Contract{
    function get() public {
        // ...
    }
}

contract Proxy{
    function get() public {
        // ...
    }
}
```

`Proxy.get` will shadow any call to `get()`. As a result `get()` is never executed in the logic contract and cannot be updated.

### Recommendation

Rename the function. Avoid public functions in the proxy.

## Initialize functions are not called

### Configuration

- Check: `missing-calls`
- Severity: `High`

### Description

Detect missing calls to initialize functions.

### Exploit Scenario

```solidity
contract Base{
    function initialize() public{
        ///
    }
}
contract Derived is Base{
    function initialize() public{
        ///
    }
}

```

`Derived.initialize` does not call `Base.initialize` leading the contract to not be correctly initialized.

### Recommendation

Ensure all the initialize functions are reached by the most derived initialize function.

## initializer() is not called

### Configuration

- Check: `missing-init-modifier`
- Severity: `High`

### Description

Detect if `Initializable.initializer()` is called.

### Exploit Scenario

```solidity
contract Contract{
    function initialize() public{
        ///
    }
}

```

`initialize` should have the `initializer` modifier to prevent someone from initializing the contract multiple times.

### Recommendation

Use `Initializable.initializer()`.

## Initialize functions are called multiple times

### Configuration

- Check: `multiple-calls`
- Severity: `High`

### Description

Detect multiple calls to a initialize function.

### Exploit Scenario

```solidity
contract Base{
    function initialize(uint) public{
        ///
    }
}
contract Derived is Base{
    function initialize(uint a, uint b) public{
        initialize(a);
    }
}

contract DerivedDerived is Derived{
    function initialize() public{
        initialize(0);
        initialize(0, 1 );
    }
}

```

`Base.initialize(uint)` is called two times in `DerivedDerived.initialize` execution, leading to a potential corruption.

### Recommendation

Call only one time every initialize function.

## Incorrect variables with the v2

### Configuration

- Check: `order-vars-contracts`
- Severity: `High`

### Description

Detect variables that are different between the original contract and the updated one.

### Exploit Scenario

```solidity
contract Contract{
    uint variable1;
}

contract ContractV2{
    address variable1;
}
```

`Contract` and `ContractV2` do not have the same storage layout. As a result the storage of both contracts can be corrupted.

### Recommendation

Respect the variable order of the original contract in the updated contract.

## Incorrect variables with the proxy

### Configuration

- Check: `order-vars-proxy`
- Severity: `High`

### Description

Detect variables that are different between the contract and the proxy.

### Exploit Scenario

```solidity
contract Contract{
    uint variable1;
}

contract Proxy{
    address variable1;
}
```

`Contract` and `Proxy` do not have the same storage layout. As a result the storage of both contracts can be corrupted.

### Recommendation

Avoid variables in the proxy. If a variable is in the proxy, ensure it has the same layout than in the contract.

## State variable initialized

### Configuration

- Check: `variables-initialized`
- Severity: `High`

### Description

Detect state variables that are initialized.

### Exploit Scenario

```solidity
contract Contract{
    uint variable = 10;
}
```

Using `Contract` will the delegatecall proxy pattern will lead `variable` to be 0 when called through the proxy.

### Recommendation

Using initialize functions to write initial values in state variables.

## Variables that should be constant

### Configuration

- Check: `were-constant`
- Severity: `High`

### Description

Detect state variables that should be `constant̀`.

### Exploit Scenario

```solidity
contract Contract{
    uint variable1;
    uint constant variable2;
    uint variable3;
}

contract ContractV2{
    uint variable1;
    uint variable2;
    uint variable3;
}
```

Because `variable2` is not anymore a `constant`, the storage location of `variable3` will be different.
As a result, `ContractV2` will have a corrupted storage layout.

### Recommendation

Do not remove `constant` from a state variables during an update.

## Extra variables in the proxy

### Configuration

- Check: `extra-vars-proxy`
- Severity: `Medium`

### Description

Detect variables that are in the proxy and not in the contract.

### Exploit Scenario

```solidity
contract Contract{
    uint variable1;
}

contract Proxy{
    uint variable1;
    uint variable2;
}
```

`Proxy` contains additional variables. A future update of `Contract` is likely to corrupt the proxy.

### Recommendation

Avoid variables in the proxy. If a variable is in the proxy, ensure it has the same layout than in the contract.

## Missing variables

### Configuration

- Check: `missing-variables`
- Severity: `Medium`

### Description

Detect variables that were present in the original contracts but are not in the updated one.

### Exploit Scenario

```solidity
contract V1{
    uint variable1;
    uint variable2;
}

contract V2{
    uint variable1;
}
```

The new version, `V2` does not contain `variable1`.
If a new variable is added in an update of `V2`, this variable will hold the latest value of `variable2` and
will be corrupted.

### Recommendation

Do not change the order of the state variables in the updated contract.

## Extra variables in the v2

### Configuration

- Check: `extra-vars-v2`
- Severity: `Informational`

### Description

Show new variables in the updated contract.

This finding does not have an immediate security impact and is informative.

### Exploit Scenario

```solidity
contract Contract{
    uint variable1;
}

contract Proxy{
    uint variable1;
    uint variable2;
}
```

`Proxy` contains additional variables. A future update of `Contract` is likely to corrupt the proxy.

### Recommendation

Ensure that all the new variables are expected.

## Initializable is not inherited

### Configuration

- Check: `init-inherited`
- Severity: `Informational`

### Description

Detect if `Initializable` is inherited.

### Recommendation

Review manually the contract's initialization. Consider inheriting `Initializable`.

## Initializable is missing

### Configuration

- Check: `init-missing`
- Severity: `Informational`

### Description

Detect if a contract `Initializable` is present.

### Recommendation

Review manually the contract's initialization..
Consider using a `Initializable` contract to follow [standard practice](https://docs.openzeppelin.com/upgrades/2.7/writing-upgradeable).

## Initialize function

### Configuration

- Check: `initialize-target`
- Severity: `Informational`

### Description

Show the function that must be called at deployment.

This finding does not have an immediate security impact and is informative.

### Recommendation

Ensure that the function is called at deployment.

## initializer() is missing

### Configuration

- Check: `initializer-missing`
- Severity: `Informational`

### Description

Detect the lack of `Initializable.initializer()` modifier.

### Recommendation

Review manually the contract's initialization. Consider inheriting a `Initializable.initializer()` modifier.

---

### Src Tutorials Exercise1 (`docs/src/tutorials/exercise1.md`)

# Exercise 1: Function Overridden Protection

The goal is to create a script that performs a feature that was not present in previous version of Solidity: function overriding protection.

[exercises/exercise1/coin.sol](./exercises/exercise1/coin.sol) contains a function that must never be overridden:

```solidity
_mint(address dst, uint256 val)
```

Use Slither to ensure that no contract inheriting Coin overrides this function.

Use `solc-select install 0.5.0 && solc-select use 0.5.0` to switch to solc 0.5.0

## Proposed Algorithm

```text
Get the Coin contract
    For each contract in the project:
        If Coin is in the list of inherited contracts:
            Get the _mint function
            If the contract declaring the _mint function is not Coin:
                A bug is found.
```

## Tips

- To get a specific contract, use `slither.get_contract_from_name` (note: it returns a list)
- To get a specific function, use `contract.get_function_from_signature`

## Solution

See [exercises/exercise1/solution.py](./exercises/exercise1/solution.py).

---

### Src Tutorials Exercise2 (`docs/src/tutorials/exercise2.md`)

# Exercise 2: Access Control

The [exercises/exercise2/coin.sol](./exercises/exercise2/coin.sol) file contains an access control implementation with the `onlyOwner` modifier. A common mistake is forgetting to add the modifier to a crucial function. In this exercise, we will use Slither to implement a conservative access control approach.

Our goal is to create a script that ensures all public and external functions call `onlyOwner`, except for the functions on the whitelist.

## Proposed Algorithm

```text
Create a whitelist of signatures
Explore all the functions
    If the function is in the whitelist of signatures:
        Skip
    If the function is public or external:
        If onlyOwner is not in the modifiers:
            A bug is found
```

## Solution

Refer to [exercises/exercise2/solution.py](./exercises/exercise2/solution.py) for the solution.

---

### Src Tutorials Exercise3 (`docs/src/tutorials/exercise3.md`)

# Exercise 3: Find function that use a given variable in a condition

The [exercises/exercise3/find.sol](./exercises/exercise3/find.sol) file contains a contract that use `my_variable` variable in multiple locations.

Our goal is to create a script that list all the functions that use `my_variable` in a conditional or require statement.

## Proposed Approach

Explore all the helpers provided by [`Function`](https://github.com/crytic/slither/blob/master/slither/core/declarations/function.py) object to find an easy way to reach the goal

## Solution

Refer to [exercises/exercise3/solution.py](./exercises/exercise3/solution.py) for the solution.

---

### Src Api Examples Expected Results Print Basic Information (`docs/src/api/examples/expected_results_print_basic_information.txt`)

Contract: Coin
	Inherit from[]
	_mint(address,uint256):
		Visibility: internal
		Contract: Coin
		Modifier: []
		Is constructor? False
	mint(address,uint256):
		Visibility: public
		Contract: Coin
		Modifier: []
		Is constructor? False
	slitherConstructorVariables():
		Visibility: internal
		Contract: Coin
		Modifier: []
		Is constructor? False
Contract: MyCoin
	Inherit from['Coin']
	_mint(address,uint256):
		Visibility: internal
		Contract: MyCoin
		Modifier: []
		Is constructor? False
	mint(address,uint256):
		Visibility: public
		Contract: MyCoin
		Modifier: []
		Is constructor? False
	_mint(address,uint256):
		Visibility: internal
		Contract: MyCoin
		Modifier: []
		Is constructor? False
	slitherConstructorVariables():
		Visibility: internal
		Contract: MyCoin
		Modifier: []
		Is constructor? False

---

### Src Tutorials Exercises Exercise3 Expected Results (`docs/src/tutorials/exercises/exercise3/expected_results.txt`)

The function using "a" in condition are ['condition', 'call_require']

---

--- METRICS ---
- Files Extracted: 40
- Estimated Token Budget: ~54869 tokens
- Canonical Reference: https://codewiki.google/github.com/crytic/slither
