Merge pull request #613 from crytic/dev-0.7-sync-88954ac6

Synchronize 0.7
dev-0.7
Feist Josselin 4 years ago committed by GitHub
commit 8fba6ba0e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 40
      .github/workflows/ci.yml
  2. 21
      CONTRIBUTING.md
  3. 10
      Dockerfile
  4. 20
      README.md
  5. 3
      plugin_example/README.md
  6. 7
      pyproject.toml
  7. 21
      scripts/ci_generate_test_detectors_4.sh
  8. 28
      scripts/ci_generate_test_detectors_5.sh
  9. 11
      scripts/ci_generate_test_detectors_6.sh
  10. 11
      scripts/ci_generate_test_detectors_7.sh
  11. 86
      scripts/ci_test.sh
  12. 18
      scripts/ci_test_cli.sh
  13. 9
      scripts/ci_test_dapp.sh
  14. 9
      scripts/ci_test_data_dependency.sh
  15. 70
      scripts/ci_test_detectors_4.sh
  16. 51
      scripts/ci_test_detectors_5.sh
  17. 7
      scripts/ci_test_detectors_6.sh
  18. 7
      scripts/ci_test_detectors_7.sh
  19. 9
      scripts/ci_test_embark.sh
  20. 6
      scripts/ci_test_erc.sh
  21. 7
      scripts/ci_test_etherlime.sh
  22. 23
      scripts/ci_test_etherscan.sh
  23. 5
      scripts/ci_test_find_paths.sh
  24. 5
      scripts/ci_test_kspec.sh
  25. 8
      scripts/ci_test_printers.sh
  26. 2
      scripts/ci_test_prop.sh
  27. 6
      scripts/ci_test_simil.sh
  28. 9
      scripts/ci_test_slither_config.sh
  29. 7
      scripts/ci_test_truffle.sh
  30. 49
      scripts/ci_test_upgradability.sh
  31. 5
      scripts/fix_travis_relative_paths.sh
  32. 6
      scripts/json_diff.py
  33. 42
      scripts/tests_generate_expected_json_5.sh
  34. 119
      scripts/travis_test_5.sh
  35. 24
      scripts/travis_test_cli.sh
  36. 11
      scripts/travis_test_data_dependency.sh
  37. 26
      scripts/travis_test_etherscan.sh
  38. 11
      scripts/travis_test_slither_config.sh
  39. 9
      slither/__main__.py
  40. 10
      slither/core/cfg/node.py
  41. 4
      slither/core/declarations/contract.py
  42. 28
      slither/core/declarations/function.py
  43. 10
      slither/core/declarations/solidity_variables.py
  44. 29
      slither/core/expressions/binary_operation.py
  45. 8
      slither/core/expressions/call_expression.py
  46. 5
      slither/core/expressions/elementary_type_name_expression.py
  47. 75
      slither/core/slither_core.py
  48. 9
      slither/core/solidity_types/array_type.py
  49. 9
      slither/core/solidity_types/elementary_type.py
  50. 6
      slither/core/solidity_types/function_type.py
  51. 6
      slither/core/solidity_types/mapping_type.py
  52. 15
      slither/core/solidity_types/type.py
  53. 14
      slither/core/solidity_types/type_information.py
  54. 35
      slither/core/solidity_types/user_defined_type.py
  55. 2
      slither/detectors/abstract_detector.py
  56. 6
      slither/detectors/attributes/const_functions_asm.py
  57. 8
      slither/detectors/attributes/const_functions_state.py
  58. 2
      slither/detectors/attributes/constant_pragma.py
  59. 46
      slither/detectors/attributes/incorrect_solc.py
  60. 6
      slither/detectors/attributes/locked_ether.py
  61. 6
      slither/detectors/erc/incorrect_erc20_interface.py
  62. 6
      slither/detectors/erc/incorrect_erc721_interface.py
  63. 9
      slither/detectors/erc/unindexed_event_parameters.py
  64. 10
      slither/detectors/functions/arbitrary_send.py
  65. 6
      slither/detectors/functions/external_function.py
  66. 4
      slither/detectors/functions/suicidal.py
  67. 10
      slither/detectors/naming_convention/naming_convention.py
  68. 2
      slither/detectors/operations/low_level_calls.py
  69. 4
      slither/detectors/operations/unchecked_low_level_return_values.py
  70. 8
      slither/detectors/operations/unchecked_send_return_value.py
  71. 2
      slither/detectors/operations/unused_return_values.py
  72. 6
      slither/detectors/operations/void_constructor.py
  73. 4
      slither/detectors/reentrancy/reentrancy_benign.py
  74. 8
      slither/detectors/reentrancy/reentrancy_eth.py
  75. 10
      slither/detectors/reentrancy/reentrancy_events.py
  76. 8
      slither/detectors/reentrancy/reentrancy_no_gas.py
  77. 6
      slither/detectors/reentrancy/reentrancy_read_before_write.py
  78. 4
      slither/detectors/shadowing/builtin_symbols.py
  79. 6
      slither/detectors/shadowing/local.py
  80. 8
      slither/detectors/slither/name_reused.py
  81. 4
      slither/detectors/source/rtlo.py
  82. 2
      slither/detectors/statements/assembly.py
  83. 6
      slither/detectors/statements/boolean_constant_equality.py
  84. 3
      slither/detectors/statements/boolean_constant_misuse.py
  85. 4
      slither/detectors/statements/calls_in_loop.py
  86. 4
      slither/detectors/statements/controlled_delegatecall.py
  87. 4
      slither/detectors/statements/deprecated_calls.py
  88. 6
      slither/detectors/statements/divide_before_multiply.py
  89. 6
      slither/detectors/statements/incorrect_strict_equality.py
  90. 4
      slither/detectors/statements/too_many_digits.py
  91. 2
      slither/detectors/statements/tx_origin.py
  92. 6
      slither/detectors/statements/type_based_tautology.py
  93. 4
      slither/detectors/variables/possible_const_state_variables.py
  94. 2
      slither/detectors/variables/uninitialized_local_variables.py
  95. 2
      slither/detectors/variables/uninitialized_state_variables.py
  96. 6
      slither/detectors/variables/uninitialized_storage_variables.py
  97. 2
      slither/detectors/variables/unused_state_variables.py
  98. 2
      slither/printers/functions/authorization.py
  99. 2
      slither/printers/functions/cfg.py
  100. 1
      slither/printers/guidance/echidna.py
  101. Some files were not shown because too many files have changed in this diff Show More

@ -1,5 +1,10 @@
name: CI
defaults:
run:
# To load bashrc
shell: bash -ieo pipefail {0}
on:
push:
branches:
@ -15,7 +20,23 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
type: ["4", "5", "cli", "data_dependency", "embark", "erc", "etherlime", "find_paths", "kspec", "printers", "simil", "slither_config", "truffle", "upgradability", "prop"]
type: ["detectors_4",
"detectors_5",
"detectors_6",
"detectors_7",
"cli",
"data_dependency",
"embark",
"erc",
"etherlime",
"find_paths",
"kspec",
"printers",
"simil",
"slither_config",
"truffle",
"upgradability",
"prop"]
steps:
- uses: actions/checkout@v1
- name: Set up Python 3.6
@ -25,19 +46,18 @@ jobs:
- name: Install dependencies
run: |
python setup.py install
# Used by travis_test.sh
# Used by ci_test.sh
pip install deepdiff
sudo wget -O /usr/bin/solc-0.4.25 https://github.com/ethereum/solidity/releases/download/v0.4.25/solc-static-linux
sudo chmod +x /usr/bin/solc-0.4.25
sudo wget -O /usr/bin/solc-0.5.1 https://github.com/ethereum/solidity/releases/download/v0.5.1/solc-static-linux
sudo chmod +x /usr/bin/solc-0.5.1
sudo wget -O /usr/bin/solc-0.5.0 https://github.com/ethereum/solidity/releases/download/v0.5.0/solc-static-linux
sudo chmod +x /usr/bin/solc-0.5.0
sudo cp /usr/bin/solc-0.5.1 /usr/bin/solc
git clone https://github.com/crytic/solc-select.git
./solc-select/scripts/install.sh
export PATH=/home/runner/.solc-select:$PATH
echo "export PATH=/home/runner/.solc-select:$PATH" >> ~/.bashrc
solc use 0.5.1
- name: Run Tests
env:
TEST_TYPE: ${{ matrix.type }}
GITHUB_ETHERSCAN: ${{ secrets.GITHUB_ETHERSCAN }}
run: |
bash scripts/travis_test_${TEST_TYPE}.sh
bash scripts/ci_test_${TEST_TYPE}.sh

@ -3,13 +3,13 @@ First, thanks for your interest in contributing to Slither! We welcome and appre
If you're unsure where to start, we recommend our [`good first issue`](https://github.com/crytic/slither/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) and [`help wanted`](https://github.com/crytic/slither/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) issue labels.
# Bug reports and feature suggestions
## Bug reports and feature suggestions
Bug reports and feature suggestions can be submitted to our issue tracker. For bug reports, attaching the contract that caused the bug will help us in debugging and resolving the issue quickly. If you find a security vulnerability, do not open an issue; email opensource@trailofbits.com instead.
# Questions
## Questions
Questions can be submitted to the issue tracker, but you may get a faster response if you ask in our [chat room](https://empireslacking.herokuapp.com/) (in the #ethereum channel).
# Code
## Code
Slither uses the pull request contribution model. Please make an account on Github, fork this repo, and submit code contributions via pull request. For more documentation, look [here](https://guides.github.com/activities/forking/).
Some pull request guidelines:
@ -20,5 +20,18 @@ Some pull request guidelines:
- Fill out the pull request description with a summary of what your patch does, key changes that have been made, and any further points of discussion, if applicable.
- Title your pull request with a brief description of what it's changing. "Fixes #123" is a good comment to add to the description, but makes for an unclear title on its own.
# Development Environment
## Development Environment
Instructions for installing a development version of Slither can be found in our [wiki](https://github.com/crytic/slither/wiki/Developer-installation).
## Detectors regression tests
For each new detector, at least one regression tests must be present.
To generate the following scripts, you must have [`solc-select`](https://github.com/crytic/solc-select) installed.
- Create a test in `tests`
- Update `script/ci_test_detectors_[solc_version].sh`, and add `generate_expected_json tests/YOUR_FILENAME.sol "DETECTOR_NAME"`. Be sure that all the other lines are commented (otherwise you will regenerate the tests for all the detectores)
- Run `./script/ci_test_detectors_[solc_version].sh`. This will generate the json artifacts in `tests/expected_json`. Add the generated files to git.
- Update `scripts/ci_test_detectors_[solc_version].sh` with your new tests.
- Run `scripts/ci_test_detectors_[solc_version].sh` and check that everything worked.

@ -1,10 +1,10 @@
FROM ubuntu:bionic
LABEL name slither
LABEL src "https://github.com/trailofbits/slither"
LABEL creator trailofbits
LABEL dockerfile_maintenance trailofbits
LABEL desc "Static Analyzer for Solidity"
LABEL name=slither
LABEL src="https://github.com/trailofbits/slither"
LABEL creator=trailofbits
LABEL dockerfile_maintenance=trailofbits
LABEL desc="Static Analyzer for Solidity"
RUN apt update \
&& apt upgrade -y \

@ -31,13 +31,13 @@ Slither is a Solidity static analysis framework written in Python 3. It runs a s
## Bugs and Optimizations Detection
Run Slither on a Truffle/Embark/Dapp/Etherlime application:
```
```bash
slither .
```
Run Slither on a single file:
```
$ slither tests/uninitialized.sol
```bash
slither tests/uninitialized.sol
```
For additional configuration, see the [usage](https://github.com/trailofbits/slither/wiki/Usage) documentation.
@ -123,7 +123,7 @@ See the [Printer documentation](https://github.com/crytic/slither/wiki/Printer-d
- `slither-check-upgradeability`: [Review `delegatecall`-based upgradeability](https://github.com/crytic/slither/wiki/Upgradeability-Checks)
- `slither-prop`: [Automatic unit tests and properties generation](https://github.com/crytic/slither/wiki/Properties-generation)
- `slither-flat`: [Flatten a codebase](https://github.com/crytic/slither/wiki/Contract-Flattening)
- `slither-erc`: [Check the ERC's conformance](https://github.com/crytic/slither/wiki/ERC-Conformance)
- `slither-check-erc`: [Check the ERC's conformance](https://github.com/crytic/slither/wiki/ERC-Conformance)
- `slither-format`: [Automatic patches generation](https://github.com/crytic/slither/wiki/Slither-format)
See the [Tool documentation](https://github.com/crytic/slither/wiki/Tool-Documentation) for additional tools.
@ -136,15 +136,15 @@ Slither requires Python 3.6+ and [solc](https://github.com/ethereum/solidity/),
### Using Pip
```
$ pip3 install slither-analyzer
```bash
pip3 install slither-analyzer
```
### Using Git
```bash
$ git clone https://github.com/crytic/slither.git && cd slither
$ python3 setup.py install
git clone https://github.com/crytic/slither.git && cd slither
python3 setup.py install
```
We recommend using an Python virtual environment, as detailed in the [Developer Installation Instructions](https://github.com/trailofbits/slither/wiki/Developer-installation), if you prefer to install Slither via git.
@ -153,13 +153,13 @@ We recommend using an Python virtual environment, as detailed in the [Developer
Use the [`eth-security-toolbox`](https://github.com/trailofbits/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
```

@ -11,9 +11,8 @@ See the [detector documentation](https://github.com/trailofbits/slither/wiki/Add
- `slither_my_plugin/detectors/example.py`: Detector plugin skeleton.
Once these files are updated with your plugin, you can install it:
```
```bash
python setup.py develop
```
We recommend to use a Python virtual environment (for example: [virtualenvwrapper](https://virtualenvwrapper.readthedocs.io/en/latest/)).

@ -0,0 +1,7 @@
[tool.black]
target-version = ["py36"]
line-length = 100
[tool.pylint.messages_control]
disable = """
C0116,C0114
"""

@ -1,24 +1,10 @@
#!/usr/bin/env bash
DIR="$(cd "$(dirname "$0")" && pwd)"
CURRENT_PATH=$(pwd)
TRAVIS_PATH='/home/travis/build/crytic/slither'
source "$(dirname "$0")""/ci_test.sh"
# generate_expected_json file.sol detectors
generate_expected_json(){
# generate output filename
# e.g. file: uninitialized.sol detector: uninitialized-state
# ---> uninitialized.uninitialized-state.json
output_filename="$DIR/../tests/expected_json/$(basename $1 .sol).$2.json"
output_filename_txt="$DIR/../tests/expected_json/$(basename $1 .sol).$2.txt"
solc use "0.4.25"
# run slither detector on input file and save output as json
slither "$1" --solc-disable-warnings --detect "$2" --json "$output_filename" --solc solc-0.4.25 > $output_filename_txt 2>&1
sed "s|$CURRENT_PATH|$TRAVIS_PATH|g" "$output_filename" -i
sed "s|$CURRENT_PATH|$TRAVIS_PATH|g" "$output_filename_txt" -i
}
# Be sure that only one of the following line is uncommented before running the script
generate_expected_json tests/deprecated_calls.sol "deprecated-standards"
@ -58,3 +44,4 @@ generate_expected_json tests/deprecated_calls.sol "deprecated-standards"
#generate_expected_json tests/solc_version_incorrect.sol "solc-version"
#generate_expected_json tests/right_to_left_override.sol "rtlo"
#generate_expected_json tests/unchecked_lowlevel.sol "unchecked-lowlevel"

@ -0,0 +1,28 @@
#!/usr/bin/env bash
source "$(dirname "$0")""/ci_test.sh"
solc use "0.5.1"
# Be sure that only one of the following line is uncommented before running the script
# generate_expected_json tests/void-cst.sol "void-cst"
# generate_expected_json tests/solc_version_incorrect_05.ast.json "solc-version"
# generate_expected_json tests/uninitialized-0.5.1.sol "uninitialized-state"
# generate_expected_json tests/backdoor.sol "backdoor"
# generate_expected_json tests/backdoor.sol "suicidal"
# generate_expected_json tests/old_solc.sol.json "solc-version"
# generate_expected_json tests/reentrancy-0.5.1.sol "reentrancy-eth"
# generate_expected_json tests/reentrancy-0.5.1-events.sol "reentrancy-events"
# generate_expected_json tests/tx_origin-0.5.1.sol "tx-origin"
# generate_expected_json tests/locked_ether-0.5.1.sol "locked-ether"
# generate_expected_json tests/arbitrary_send-0.5.1.sol "arbitrary-send"
# generate_expected_json tests/inline_assembly_contract-0.5.1.sol "assembly"
# generate_expected_json tests/inline_assembly_library-0.5.1.sol "assembly"
# generate_expected_json tests/constant-0.5.1.sol "constant-function-asm"
# generate_expected_json tests/constant-0.5.1.sol "constant-function-state"
# generate_expected_json tests/incorrect_equality.sol "incorrect-equality"
# generate_expected_json tests/too_many_digits.sol "too-many-digits"
# generate_expected_json tests/unchecked_lowlevel-0.5.1.sol "unchecked-lowlevel"
# generate_expected_json tests/unchecked_send-0.5.1.sol "unchecked-send"

@ -0,0 +1,11 @@
#!/usr/bin/env bash
source "$(dirname "$0")""/ci_test.sh"
solc use "0.6.11"
# Be sure that only one of the following line is uncommented before running the script
#generate_expected_json tests/filename.sol "detector_name"

@ -0,0 +1,11 @@
#!/usr/bin/env bash
source "$(dirname "$0")""/ci_test.sh"
solc use "0.7.0"
# Be sure that only one of the following line is uncommented before running the script
#generate_expected_json tests/filename.sol "detector_name"

@ -0,0 +1,86 @@
#!/usr/bin/env bash
### Test Detectors
DIR="$(cd "$(dirname "$0")" && pwd)"
CURRENT_PATH=$(pwd)
TRAVIS_PATH='/home/travis/build/crytic/slither'
# test_slither file.sol detectors
test_slither(){
expected="$DIR/../tests/expected_json/$(basename "$1" .sol).$2.json"
# run slither detector on input file and save output as json
slither "$1" --solc-disable-warnings --detect "$2" --json "$DIR/tmp-test.json"
if [ $? -eq 255 ]
then
echo "Slither crashed"
exit 255
fi
if [ ! -f "$DIR/tmp-test.json" ]; then
echo ""
echo "Missing generated file"
echo ""
exit 1
fi
sed "s|$CURRENT_PATH|$TRAVIS_PATH|g" "$DIR/tmp-test.json" -i
result=$(python "$DIR/json_diff.py" "$expected" "$DIR/tmp-test.json")
rm "$DIR/tmp-test.json"
if [ "$result" != "{}" ]; then
echo ""
echo "failed test of file: $1, detector: $2"
echo ""
echo "$result"
echo ""
exit 1
fi
# run slither detector on input file and save output as json
slither "$1" --solc-disable-warnings --detect "$2" --legacy-ast --json "$DIR/tmp-test.json"
if [ $? -eq 255 ]
then
echo "Slither crashed"
exit 255
fi
if [ ! -f "$DIR/tmp-test.json" ]; then
echo ""
echo "Missing generated file"
echo ""
exit 1
fi
sed "s|$CURRENT_PATH|$TRAVIS_PATH|g" "$DIR/tmp-test.json" -i
result=$(python "$DIR/json_diff.py" "$expected" "$DIR/tmp-test.json")
rm "$DIR/tmp-test.json"
if [ "$result" != "{}" ]; then
echo ""
echo "failed test of file: $1, detector: $2"
echo ""
echo "$result"
echo ""
exit 1
fi
}
# generate_expected_json file.sol detectors
generate_expected_json(){
# generate output filename
# e.g. file: uninitialized.sol detector: uninitialized-state
# ---> uninitialized.uninitialized-state.json
output_filename="$DIR/../tests/expected_json/$(basename "$1" .sol).$2.json"
output_filename_txt="$DIR/../tests/expected_json/$(basename "$1" .sol).$2.txt"
# run slither detector on input file and save output as json
slither "$1" --solc-disable-warnings --detect "$2" --json "$output_filename" > "$output_filename_txt" 2>&1
sed "s|$CURRENT_PATH|$TRAVIS_PATH|g" "$output_filename" -i
sed "s|$CURRENT_PATH|$TRAVIS_PATH|g" "$output_filename_txt" -i
}

@ -0,0 +1,18 @@
#!/usr/bin/env bash
### Test
if ! slither "tests/*.json" --solc-ast --ignore-return-value; then
echo "--solc-ast failed"
exit 1
fi
if ! slither "tests/*0.5*.sol" --solc-disable-warnings --ignore-return-value; then
echo "--solc-disable-warnings failed"
exit 1
fi
if ! slither "tests/*0.5*.sol" --disable-color --ignore-return-value; then
echo "--disable-color failed"
exit 1
fi

@ -3,18 +3,19 @@
### Test Dapp integration
mkdir test_dapp
cd test_dapp
cd test_dapp || exit 255
# The dapp init process makes a temporary local git repo and needs certain values to be set
git config --global user.email "ci@trailofbits.com"
git config --global user.name "CI User"
curl https://nixos.org/nix/install | sh
# shellcheck disable=SC1090
. "$HOME/.nix-profile/etc/profile.d/nix.sh"
nix-env -iA nixpkgs.cachix
cachix use dapp
git clone --recursive https://github.com/dapphub/dapptools $HOME/.dapp/dapptools
nix-env -f $HOME/.dapp/dapptools -iA dapp seth solc hevm ethsign
git clone --recursive https://github.com/dapphub/dapptools "$HOME/.dapp/dapptools"
nix-env -f "$HOME/.dapp/dapptools" -iA dapp seth solc hevm ethsign
dapp init
@ -26,4 +27,4 @@ then
fi
echo "Truffle test failed"
exit -1
exit 255

@ -0,0 +1,9 @@
#!/usr/bin/env bash
### Test data dependecy
if ! python ./examples/scripts/data_dependency.py ./examples/scripts/data_dependency.sol; then
echo "data dependency failed"
exit 1
fi
exit 0

@ -1,73 +1,8 @@
#!/usr/bin/env bash
### Test Detectors
DIR="$(cd "$(dirname "$0")" && pwd)"
CURRENT_PATH=$(pwd)
TRAVIS_PATH='/home/travis/build/crytic/slither'
# test_slither file.sol detectors
test_slither(){
expected="$DIR/../tests/expected_json/$(basename $1 .sol).$2.json"
# run slither detector on input file and save output as json
slither "$1" --solc-disable-warnings --detect "$2" --json "$DIR/tmp-test.json" --solc solc-0.4.25
if [ $? -eq 255 ]
then
echo "Slither crashed"
exit -1
fi
if [ ! -f "$DIR/tmp-test.json" ]; then
echo ""
echo "Missing generated file"
echo ""
exit 1
fi
sed "s|$CURRENT_PATH|$TRAVIS_PATH|g" "$DIR/tmp-test.json" -i
result=$(python "$DIR/json_diff.py" "$expected" "$DIR/tmp-test.json")
rm "$DIR/tmp-test.json"
if [ "$result" != "{}" ]; then
echo ""
echo "failed test of file: $1, detector: $2"
echo ""
echo "$result"
echo ""
exit 1
fi
# run slither detector on input file and save output as json
slither "$1" --solc-disable-warnings --detect "$2" --legacy-ast --json "$DIR/tmp-test.json" --solc solc-0.4.25
if [ $? -eq 255 ]
then
echo "Slither crashed"
exit -1
fi
if [ ! -f "$DIR/tmp-test.json" ]; then
echo ""
echo "Missing generated file"
echo ""
exit 1
fi
sed "s|$CURRENT_PATH|$TRAVIS_PATH|g" "$DIR/tmp-test.json" -i
result=$(python "$DIR/json_diff.py" "$expected" "$DIR/tmp-test.json")
rm "$DIR/tmp-test.json"
if [ "$result" != "{}" ]; then
echo ""
echo "failed test of file: $1, detector: $2"
echo ""
echo "$result"
echo ""
exit 1
fi
}
source "$(dirname "$0")""/ci_test.sh"
solc use "0.4.25"
test_slither tests/unchecked_lowlevel.sol "unchecked-lowlevel"
test_slither tests/deprecated_calls.sol "deprecated-standards"
@ -92,7 +27,6 @@ test_slither tests/const_state_variables.sol "constable-states"
test_slither tests/external_function.sol "external-function"
test_slither tests/external_function_2.sol "external-function"
test_slither tests/naming_convention.sol "naming-convention"
#test_slither tests/complex_func.sol "complex-function"
test_slither tests/controlled_delegatecall.sol "controlled-delegatecall"
test_slither tests/uninitialized_local_variable.sol "uninitialized-local"
test_slither tests/constant.sol "constant-function-asm"

@ -0,0 +1,51 @@
#!/usr/bin/env bash
source "$(dirname "$0")""/ci_test.sh"
solc use "0.5.1"
test_slither tests/void-cst.sol "void-cst"
test_slither tests/solc_version_incorrect_05.ast.json "solc-version"
test_slither tests/unchecked_lowlevel-0.5.1.sol "unchecked-lowlevel"
test_slither tests/unchecked_send-0.5.1.sol "unchecked-send"
test_slither tests/uninitialized-0.5.1.sol "uninitialized-state"
test_slither tests/backdoor.sol "backdoor"
test_slither tests/backdoor.sol "suicidal"
test_slither tests/old_solc.sol.json "solc-version"
test_slither tests/reentrancy-0.5.1.sol "reentrancy-eth"
test_slither tests/reentrancy-0.5.1-events.sol "reentrancy-events"
test_slither tests/tx_origin-0.5.1.sol "tx-origin"
test_slither tests/unused_state.sol "unused-state"
test_slither tests/locked_ether-0.5.1.sol "locked-ether"
test_slither tests/arbitrary_send-0.5.1.sol "arbitrary-send"
test_slither tests/inline_assembly_contract-0.5.1.sol "assembly"
test_slither tests/inline_assembly_library-0.5.1.sol "assembly"
test_slither tests/low_level_calls.sol "low-level-calls"
test_slither tests/const_state_variables.sol "constable-states"
test_slither tests/external_function.sol "external-function"
test_slither tests/external_function_2.sol "external-function"
test_slither tests/naming_convention.sol "naming-convention"
#test_slither tests/complex_func.sol "complex-function"
test_slither tests/controlled_delegatecall.sol "controlled-delegatecall"
test_slither tests/constant-0.5.1.sol "constant-function-asm"
test_slither tests/constant-0.5.1.sol "constant-function-state"
test_slither tests/unused_return.sol "unused-return"
test_slither tests/timestamp.sol "timestamp"
test_slither tests/incorrect_equality.sol "incorrect-equality"
test_slither tests/too_many_digits.sol "too-many-digits"
### Test scripts
if ! python examples/scripts/functions_called.py examples/scripts/functions_called.sol; then
exit 1
fi
if ! python examples/scripts/functions_writing.py examples/scripts/functions_writing.sol; then
exit 1
fi
if ! python examples/scripts/variable_in_condition.py examples/scripts/variable_in_condition.sol; then
exit 1
fi
exit 0

@ -0,0 +1,7 @@
#!/usr/bin/env bash
source "$(dirname "$0")""/ci_test.sh"
solc use "0.6.11"
# test_slither tests/filename.sol "detector_name"

@ -0,0 +1,7 @@
#!/usr/bin/env bash
source "$(dirname "$0")""/ci_test.sh"
solc use "0.7.0"
# test_slither tests/filename.sol "detector_name"

@ -3,24 +3,25 @@
### Test embark integration
mkdir test_embark
cd test_embark
cd test_embark || exit 255
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash
# shellcheck disable=SC1090
source ~/.nvm/nvm.sh
nvm install 10.17.0
nvm use 10.17.0
npm install -g embark@4.2.0
embark demo
cd embark_demo
cd embark_demo || exit 255
npm install
slither . --embark-overwrite-config
if [ $? -eq 3 ]
if [ $? -eq 4 ]
then
exit 0
fi
echo "Embark test failed"
exit -1
exit 255

@ -4,7 +4,8 @@
DIR_TESTS="tests/check-erc"
slither-check-erc "$DIR_TESTS/erc20.sol" ERC20 --solc solc-0.5.0 > test_1.txt 2>&1
solc use 0.5.0
slither-check-erc "$DIR_TESTS/erc20.sol" ERC20 > test_1.txt 2>&1
DIFF=$(diff test_1.txt "$DIR_TESTS/test_1.txt")
if [ "$DIFF" != "" ]
then
@ -12,9 +13,8 @@ then
cat test_1.txt
echo ""
cat "$DIR_TESTS/test_1.txt"
exit -1
exit 255
fi
rm test_1.txt

@ -3,9 +3,10 @@
### Test etherlime integration
mkdir test_etherlime
cd test_etherlime
cd test_etherlime || exit 255
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash
# shellcheck disable=SC1090
source ~/.nvm/nvm.sh
nvm install 10.17.0
nvm use 10.17.0
@ -14,10 +15,10 @@ npm i -g etherlime
etherlime init
slither .
if [ $? -eq 6 ]
if [ $? -eq 7 ]
then
exit 0
fi
echo "Etherlime test failed"
exit -1
exit 255

@ -0,0 +1,23 @@
#!/usr/bin/env bash
### Test etherscan integration
mkdir etherscan
cd etherscan || exit 255
slither 0x7F37f78cBD74481E593F9C737776F7113d76B315 --etherscan-apikey "$GITHUB_ETHERSCAN"
if [ $? -ne 5 ]
then
echo "Etherscan test failed"
exit 255
fi
slither rinkeby:0xFe05820C5A92D9bc906D4A46F662dbeba794d3b7 --etherscan-apikey "$GITHUB_ETHERSCAN"
if [ $? -ne 70 ]
then
echo "Etherscan test failed"
exit 255
fi

@ -4,13 +4,14 @@
DIR_TESTS="tests/possible_paths"
slither-find-paths "$DIR_TESTS/paths.sol" A.destination --solc solc-0.5.0 > test_possible_paths.txt 2>&1
solc use "0.5.0"
slither-find-paths "$DIR_TESTS/paths.sol" A.destination > test_possible_paths.txt 2>&1
DIFF=$(diff test_possible_paths.txt "$DIR_TESTS/paths.txt")
if [ "$DIFF" != "" ]
then
echo "slither-find-paths failed"
cat test_possible_paths.txt
cat "$DIR_TESTS/paths.txt"
exit -1
exit 255
fi
rm test_possible_paths.txt

@ -2,7 +2,8 @@
DIR_TESTS="tests/check-kspec"
slither-check-kspec "$DIR_TESTS/safeAdd/safeAdd.sol" "$DIR_TESTS/safeAdd/spec.md" --solc solc-0.5.0 > test_1.txt 2>&1
solc use "0.5.0"
slither-check-kspec "$DIR_TESTS/safeAdd/safeAdd.sol" "$DIR_TESTS/safeAdd/spec.md" > test_1.txt 2>&1
DIFF=$(diff test_1.txt "$DIR_TESTS/test_1.txt")
if [ "$DIFF" != "" ]
then
@ -10,7 +11,7 @@ then
cat test_1.txt
echo ""
cat "$DIR_TESTS/test_1.txt"
exit -1
exit 255
fi
rm test_1.txt

@ -5,11 +5,11 @@
# Needed for evm printer
pip install evm-cfg-builder
slither "tests/*.json" --print all --json -
if [ $? -ne 0 ]; then
if ! slither "tests/*.json" --print all --json -; then
echo "Printer tests failed"
exit 1
fi
slither examples/scripts/test_evm_api.sol --print evm --solc solc-0.5.1
solc use "0.5.1"
slither examples/scripts/test_evm_api.sol --print evm

@ -2,7 +2,7 @@
### Test slither-prop
cd examples/slither-prop
cd examples/slither-prop || exit 1
slither-prop . --contract ERC20Buggy
if [ ! -f contracts/crytic/TestERC20BuggyTransferable.sol ]; then
echo "slither-prop failed"

@ -7,15 +7,17 @@ pip3.6 install https://github.com/facebookresearch/fastText/archive/0.2.0.zip
### Test slither-simil
solc use "0.4.25"
DIR_TESTS="tests/simil"
slither-simil info "" --filename $DIR_TESTS/../complex_func.sol --fname Complex.complexExternalWrites --solc solc-0.4.25 > test_1.txt 2>&1
slither-simil info "" --filename $DIR_TESTS/../complex_func.sol --fname Complex.complexExternalWrites > test_1.txt 2>&1
DIFF=$(diff test_1.txt "$DIR_TESTS/test_1.txt")
if [ "$DIFF" != "" ]
then
echo "slither-simil failed"
cat test_1.txt
cat "$DIR_TESTS/test_1.txt"
exit -1
exit 255
fi
rm test_1.txt

@ -0,0 +1,9 @@
#!/usr/bin/env bash
### Test
if ! slither "tests/*.json" --config "tests/config/slither.config.json"; then
echo "Config failed"
exit 1
fi

@ -3,9 +3,10 @@
### Test truffle integration
mkdir test_truffle
cd test_truffle
cd test_truffle || exit 255
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash
# shellcheck disable=SC1090
source ~/.nvm/nvm.sh
nvm install --lts
nvm use --lts
@ -14,10 +15,10 @@ npm install -g truffle
truffle unbox metacoin
slither .
if [ $? -eq 5 ]
if [ $? -eq 8 ]
then
exit 0
fi
echo "Truffle test failed"
exit -1
exit 255

@ -3,8 +3,9 @@
### Test slither-check-upgradeability
DIR_TESTS="tests/check-upgradeability"
solc use "0.5.0"
slither-check-upgradeability "$DIR_TESTS/contractV1.sol" ContractV1 --proxy-filename "$DIR_TESTS/proxy.sol" --proxy-name Proxy --solc solc-0.5.0 > test_1.txt 2>&1
slither-check-upgradeability "$DIR_TESTS/contractV1.sol" ContractV1 --proxy-filename "$DIR_TESTS/proxy.sol" --proxy-name Proxy > test_1.txt 2>&1
DIFF=$(diff test_1.txt "$DIR_TESTS/test_1.txt")
if [ "$DIFF" != "" ]
then
@ -12,10 +13,10 @@ then
cat test_1.txt
echo ""
cat "$DIR_TESTS/test_1.txt"
exit -1
exit 255
fi
slither-check-upgradeability "$DIR_TESTS/contractV1.sol" ContractV1 --proxy-filename "$DIR_TESTS/proxy.sol" --proxy-name Proxy --solc solc-0.5.0 --new-contract-filename "$DIR_TESTS/contractV2.sol" --new-contract-name ContractV2 > test_2.txt 2>&1
slither-check-upgradeability "$DIR_TESTS/contractV1.sol" ContractV1 --proxy-filename "$DIR_TESTS/proxy.sol" --proxy-name Proxy --new-contract-filename "$DIR_TESTS/contractV2.sol" --new-contract-name ContractV2 > test_2.txt 2>&1
DIFF=$(diff test_2.txt "$DIR_TESTS/test_2.txt")
if [ "$DIFF" != "" ]
then
@ -23,10 +24,10 @@ then
cat test_2.txt
echo ""
cat "$DIR_TESTS/test_2.txt"
exit -1
exit 255
fi
slither-check-upgradeability "$DIR_TESTS/contractV1.sol" ContractV1 --proxy-filename "$DIR_TESTS/proxy.sol" --proxy-name Proxy --solc solc-0.5.0 --new-contract-filename "$DIR_TESTS/contractV2_bug.sol" --new-contract-name ContractV2 > test_3.txt 2>&1
slither-check-upgradeability "$DIR_TESTS/contractV1.sol" ContractV1 --proxy-filename "$DIR_TESTS/proxy.sol" --proxy-name Proxy --new-contract-filename "$DIR_TESTS/contractV2_bug.sol" --new-contract-name ContractV2 > test_3.txt 2>&1
DIFF=$(diff test_3.txt "$DIR_TESTS/test_3.txt")
if [ "$DIFF" != "" ]
then
@ -34,10 +35,10 @@ then
cat test_3.txt
echo ""
cat "$DIR_TESTS/test_3.txt"
exit -1
exit 255
fi
slither-check-upgradeability "$DIR_TESTS/contractV1.sol" ContractV1 --proxy-filename "$DIR_TESTS/proxy.sol" --proxy-name Proxy --solc solc-0.5.0 --new-contract-filename "$DIR_TESTS/contractV2_bug2.sol" --new-contract-name ContractV2 > test_4.txt 2>&1
slither-check-upgradeability "$DIR_TESTS/contractV1.sol" ContractV1 --proxy-filename "$DIR_TESTS/proxy.sol" --proxy-name Proxy --new-contract-filename "$DIR_TESTS/contractV2_bug2.sol" --new-contract-name ContractV2 > test_4.txt 2>&1
DIFF=$(diff test_4.txt "$DIR_TESTS/test_4.txt")
if [ "$DIFF" != "" ]
then
@ -45,10 +46,10 @@ then
cat test_4.txt
echo ""
cat "$DIR_TESTS/test_4.txt"
exit -1
exit 255
fi
slither-check-upgradeability "$DIR_TESTS/contract_initialization.sol" Contract_no_bug --proxy-filename "$DIR_TESTS/proxy.sol" --proxy-name Proxy --solc solc-0.5.0 > test_5.txt 2>&1
slither-check-upgradeability "$DIR_TESTS/contract_initialization.sol" Contract_no_bug --proxy-filename "$DIR_TESTS/proxy.sol" --proxy-name Proxy > test_5.txt 2>&1
DIFF=$(diff test_5.txt "$DIR_TESTS/test_5.txt")
if [ "$DIFF" != "" ]
then
@ -58,10 +59,10 @@ then
cat "$DIR_TESTS/test_5.txt"
echo ""
echo "$DIFF"
exit -1
exit 255
fi
slither-check-upgradeability "$DIR_TESTS/contract_initialization.sol" Contract_no_bug --proxy-filename "$DIR_TESTS/proxy.sol" --proxy-name Proxy --solc solc-0.5.0 > test_5.txt 2>&1
slither-check-upgradeability "$DIR_TESTS/contract_initialization.sol" Contract_no_bug --proxy-filename "$DIR_TESTS/proxy.sol" --proxy-name Proxy > test_5.txt 2>&1
DIFF=$(diff test_5.txt "$DIR_TESTS/test_5.txt")
if [ "$DIFF" != "" ]
then
@ -71,11 +72,11 @@ then
cat "$DIR_TESTS/test_5.txt"
echo ""
echo "$DIFF"
exit -1
exit 255
fi
slither-check-upgradeability "$DIR_TESTS/contract_initialization.sol" Contract_lack_to_call_modifier --proxy-filename "$DIR_TESTS/proxy.sol" --proxy-name Proxy --solc solc-0.5.0 > test_6.txt 2>&1
slither-check-upgradeability "$DIR_TESTS/contract_initialization.sol" Contract_lack_to_call_modifier --proxy-filename "$DIR_TESTS/proxy.sol" --proxy-name Proxy > test_6.txt 2>&1
DIFF=$(diff test_6.txt "$DIR_TESTS/test_6.txt")
if [ "$DIFF" != "" ]
then
@ -85,11 +86,11 @@ then
cat "$DIR_TESTS/test_6.txt"
echo ""
echo "$DIFF"
exit -1
exit 255
fi
slither-check-upgradeability "$DIR_TESTS/contract_initialization.sol" Contract_not_called_super_init --proxy-filename "$DIR_TESTS/proxy.sol" --proxy-name Proxy --solc solc-0.5.0 > test_7.txt 2>&1
slither-check-upgradeability "$DIR_TESTS/contract_initialization.sol" Contract_not_called_super_init --proxy-filename "$DIR_TESTS/proxy.sol" --proxy-name Proxy > test_7.txt 2>&1
DIFF=$(diff test_7.txt "$DIR_TESTS/test_7.txt")
if [ "$DIFF" != "" ]
then
@ -99,10 +100,10 @@ then
cat "$DIR_TESTS/test_7.txt"
echo ""
echo "$DIFF"
exit -1
exit 255
fi
slither-check-upgradeability "$DIR_TESTS/contract_initialization.sol" Contract_no_bug_inherits --proxy-filename "$DIR_TESTS/proxy.sol" --proxy-name Proxy --solc solc-0.5.0 > test_8.txt 2>&1
slither-check-upgradeability "$DIR_TESTS/contract_initialization.sol" Contract_no_bug_inherits --proxy-filename "$DIR_TESTS/proxy.sol" --proxy-name Proxy > test_8.txt 2>&1
DIFF=$(diff test_8.txt "$DIR_TESTS/test_8.txt")
if [ "$DIFF" != "" ]
then
@ -112,10 +113,10 @@ then
cat "$DIR_TESTS/test_8.txt"
echo ""
echo "$DIFF"
exit -1
exit 255
fi
slither-check-upgradeability "$DIR_TESTS/contract_initialization.sol" Contract_double_call --proxy-filename "$DIR_TESTS/proxy.sol" --proxy-name Proxy --solc solc-0.5.0 > test_9.txt 2>&1
slither-check-upgradeability "$DIR_TESTS/contract_initialization.sol" Contract_double_call --proxy-filename "$DIR_TESTS/proxy.sol" --proxy-name Proxy > test_9.txt 2>&1
DIFF=$(diff test_9.txt "$DIR_TESTS/test_9.txt")
if [ "$DIFF" != "" ]
then
@ -125,10 +126,10 @@ then
cat "$DIR_TESTS/test_9.txt"
echo ""
echo "$DIFF"
exit -1
exit 255
fi
slither-check-upgradeability "$DIR_TESTS/contractV1.sol" ContractV1 --solc solc-0.5.0 --new-contract-filename "$DIR_TESTS/contract_v2_constant.sol" --new-contract-name ContractV2 > test_10.txt 2>&1
slither-check-upgradeability "$DIR_TESTS/contractV1.sol" ContractV1 --new-contract-filename "$DIR_TESTS/contract_v2_constant.sol" --new-contract-name ContractV2 > test_10.txt 2>&1
DIFF=$(diff test_10.txt "$DIR_TESTS/test_10.txt")
if [ "$DIFF" != "" ]
then
@ -138,10 +139,10 @@ then
cat "$DIR_TESTS/test_10.txt"
echo ""
echo "$DIFF"
exit -1
exit 255
fi
slither-check-upgradeability "$DIR_TESTS/contract_v1_var_init.sol" ContractV1 --solc solc-0.5.0 > test_11.txt 2>&1
slither-check-upgradeability "$DIR_TESTS/contract_v1_var_init.sol" ContractV1 > test_11.txt 2>&1
DIFF=$(diff test_11.txt "$DIR_TESTS/test_11.txt")
if [ "$DIFF" != "" ]
then
@ -151,7 +152,7 @@ then
cat "$DIR_TESTS/test_11.txt"
echo ""
echo "$DIFF"
exit -1
exit 255
fi
rm test_1.txt

@ -1,5 +0,0 @@
CURRENT_PATH=$(pwd)
TRAVIS_PATH='/home/travis/build/crytic/slither'
for f in tests/expected_json/*json; do
sed "s|$CURRENT_PATH|$TRAVIS_PATH|g" "$f" -i
done

@ -22,6 +22,7 @@ for elem in d2:
if "description" in elem:
del elem["description"]
def removes_lines(d):
if isinstance(d, list):
for sub in d:
@ -29,11 +30,12 @@ def removes_lines(d):
return
if not isinstance(d, dict):
return
if 'lines' in d:
del d['lines']
if "lines" in d:
del d["lines"]
for key in d.keys():
removes_lines(d[key])
results = DeepDiff(d1, d2, ignore_order=True, verbose_level=2)
removes_lines(results)
pprint(results)

@ -1,42 +0,0 @@
#!/usr/bin/env bash
DIR="$(cd "$(dirname "$0")" && pwd)"
CURRENT_PATH=$(pwd)
TRAVIS_PATH='/home/travis/build/crytic/slither'
# generate_expected_json file.sol detectors
generate_expected_json(){
# generate output filename
# e.g. file: uninitialized.sol detector: uninitialized-state
# ---> uninitialized.uninitialized-state.json
output_filename="$DIR/../tests/expected_json/$(basename $1 .sol).$2.json"
output_filename_txt="$DIR/../tests/expected_json/$(basename $1 .sol).$2.txt"
# run slither detector on input file and save output as json
slither "$1" --solc-disable-warnings --detect "$2" --json "$output_filename" --solc solc-0.5.1 > $output_filename_txt 2>&1
sed "s|$CURRENT_PATH|$TRAVIS_PATH|g" "$output_filename" -i
sed "s|$CURRENT_PATH|$TRAVIS_PATH|g" "$output_filename_txt" -i
}
generate_expected_json tests/void-cst.sol "void-cst"
generate_expected_json tests/solc_version_incorrect_05.ast.json "solc-version"
generate_expected_json tests/uninitialized-0.5.1.sol "uninitialized-state"
generate_expected_json tests/backdoor.sol "backdoor"
generate_expected_json tests/backdoor.sol "suicidal"
generate_expected_json tests/old_solc.sol.json "solc-version"
generate_expected_json tests/reentrancy-0.5.1.sol "reentrancy-eth"
generate_expected_json tests/reentrancy-0.5.1-events.sol "reentrancy-events"
generate_expected_json tests/tx_origin-0.5.1.sol "tx-origin"
generate_expected_json tests/locked_ether-0.5.1.sol "locked-ether"
generate_expected_json tests/arbitrary_send-0.5.1.sol "arbitrary-send"
generate_expected_json tests/inline_assembly_contract-0.5.1.sol "assembly"
generate_expected_json tests/inline_assembly_library-0.5.1.sol "assembly"
generate_expected_json tests/constant-0.5.1.sol "constant-function-asm"
generate_expected_json tests/constant-0.5.1.sol "constant-function-state"
generate_expected_json tests/incorrect_equality.sol "incorrect-equality"
generate_expected_json tests/too_many_digits.sol "too-many-digits"
generate_expected_json tests/unchecked_lowlevel-0.5.1.sol "unchecked-lowlevel"
generate_expected_json tests/unchecked_send-0.5.1.sol "unchecked-send"

@ -1,119 +0,0 @@
#!/usr/bin/env bash
### Test Detectors
DIR="$(cd "$(dirname "$0")" && pwd)"
CURRENT_PATH=$(pwd)
TRAVIS_PATH='/home/travis/build/crytic/slither'
# test_slither file.sol detectors
test_slither(){
expected="$DIR/../tests/expected_json/$(basename $1 .sol).$2.json"
# run slither detector on input file and save output as json
slither "$1" --solc-disable-warnings --detect "$2" --json "$DIR/tmp-test.json" --solc solc-0.5.1
if [ $? -eq 255 ]
then
echo "Slither crashed"
exit -1
fi
if [ ! -f "$DIR/tmp-test.json" ]; then
echo ""
echo "Missing generated file"
echo ""
exit 1
fi
sed "s|$CURRENT_PATH|$TRAVIS_PATH|g" "$DIR/tmp-test.json" -i
result=$(python "$DIR/json_diff.py" "$expected" "$DIR/tmp-test.json")
rm "$DIR/tmp-test.json"
if [ "$result" != "{}" ]; then
echo ""
echo "failed test of file: $1, detector: $2"
echo ""
echo "$result"
echo ""
exit 1
fi
# run slither detector on input file and save output as json
slither "$1" --solc-disable-warnings --detect "$2" --legacy-ast --json "$DIR/tmp-test.json" --solc solc-0.5.1
if [ $? -eq 255 ]
then
echo "Slither crashed"
exit -1
fi
if [ ! -f "$DIR/tmp-test.json" ]; then
echo ""
echo "Missing generated file"
echo ""
exit 1
fi
sed "s|$CURRENT_PATH|$TRAVIS_PATH|g" "$DIR/tmp-test.json" -i
result=$(python "$DIR/json_diff.py" "$expected" "$DIR/tmp-test.json")
rm "$DIR/tmp-test.json"
if [ "$result" != "{}" ]; then
echo ""
echo "failed test of file: $1, detector: $2"
echo ""
echo "$result"
echo ""
exit 1
fi
}
test_slither tests/void-cst.sol "void-cst"
test_slither tests/solc_version_incorrect_05.ast.json "solc-version"
test_slither tests/unchecked_lowlevel-0.5.1.sol "unchecked-lowlevel"
test_slither tests/unchecked_send-0.5.1.sol "unchecked-send"
test_slither tests/uninitialized-0.5.1.sol "uninitialized-state"
test_slither tests/backdoor.sol "backdoor"
test_slither tests/backdoor.sol "suicidal"
test_slither tests/old_solc.sol.json "solc-version"
test_slither tests/reentrancy-0.5.1.sol "reentrancy-eth"
test_slither tests/reentrancy-0.5.1-events.sol "reentrancy-events"
test_slither tests/tx_origin-0.5.1.sol "tx-origin"
test_slither tests/unused_state.sol "unused-state"
test_slither tests/locked_ether-0.5.1.sol "locked-ether"
test_slither tests/arbitrary_send-0.5.1.sol "arbitrary-send"
test_slither tests/inline_assembly_contract-0.5.1.sol "assembly"
test_slither tests/inline_assembly_library-0.5.1.sol "assembly"
test_slither tests/low_level_calls.sol "low-level-calls"
test_slither tests/const_state_variables.sol "constable-states"
test_slither tests/external_function.sol "external-function"
test_slither tests/external_function_2.sol "external-function"
test_slither tests/naming_convention.sol "naming-convention"
#test_slither tests/complex_func.sol "complex-function"
test_slither tests/controlled_delegatecall.sol "controlled-delegatecall"
test_slither tests/constant-0.5.1.sol "constant-function-asm"
test_slither tests/constant-0.5.1.sol "constant-function-state"
test_slither tests/unused_return.sol "unused-return"
test_slither tests/timestamp.sol "timestamp"
test_slither tests/incorrect_equality.sol "incorrect-equality"
test_slither tests/too_many_digits.sol "too-many-digits"
### Test scripts
python examples/scripts/functions_called.py examples/scripts/functions_called.sol
if [ $? -ne 0 ]; then
exit 1
fi
python examples/scripts/functions_writing.py examples/scripts/functions_writing.sol
if [ $? -ne 0 ]; then
exit 1
fi
python examples/scripts/variable_in_condition.py examples/scripts/variable_in_condition.sol
if [ $? -ne 0 ]; then
exit 1
fi
exit 0

@ -1,24 +0,0 @@
#!/usr/bin/env bash
### Test
slither "tests/*.json" --solc-ast --ignore-return-value
if [ $? -ne 0 ]; then
echo "--solc-ast failed"
exit 1
fi
slither "tests/*0.5*.sol" --solc-disable-warnings --ignore-return-value
if [ $? -ne 0 ]; then
echo "--solc-disable-warnings failed"
exit 1
fi
slither "tests/*0.5*.sol" --disable-color --ignore-return-value
if [ $? -ne 0 ]; then
echo "--disable-color failed"
exit 1
fi

@ -1,11 +0,0 @@
#!/usr/bin/env bash
### Test data dependecy
python ./examples/scripts/data_dependency.py ./examples/scripts/data_dependency.sol
if [ $? -ne 0 ]; then
echo "data dependency failed"
exit 1
fi
exit 0

@ -1,26 +0,0 @@
#!/usr/bin/env bash
### Test etherscan integration
mkdir etherscan
cd etherscan
wget -O solc-0.4.25 https://github.com/ethereum/solidity/releases/download/v0.4.25/solc-static-linux
chmod +x solc-0.4.25
slither 0x7F37f78cBD74481E593F9C737776F7113d76B315 --solc "./solc-0.4.25" --etherscan-apikey $GITHUB_ETHERSCAN
if [ $? -ne 5 ]
then
echo "Etherscan test failed"
exit -1
fi
slither rinkeby:0xFe05820C5A92D9bc906D4A46F662dbeba794d3b7 --solc "./solc-0.4.25" --etherscan-apikey $GITHUB_ETHERSCAN
if [ $? -ne 70 ]
then
echo "Etherscan test failed"
exit -1
fi

@ -1,11 +0,0 @@
#!/usr/bin/env bash
### Test
slither "tests/*.json" --config "tests/config/slither.config.json"
if [ $? -ne 0 ]; then
echo "Config failed"
exit 1
fi

@ -473,6 +473,11 @@ def parse_args(detector_classes, printer_classes):
# if the json is splitted in different files
parser.add_argument("--splitted", help=argparse.SUPPRESS, action="store_true", default=False)
# Disable the throw/catch on partial analyses
parser.add_argument(
"--disallow-partial", help=argparse.SUPPRESS, action="store_true", default=False
)
if len(sys.argv) == 1:
parser.print_help(sys.stderr)
sys.exit(1)
@ -556,6 +561,9 @@ class FormatterCryticCompile(logging.Formatter):
def main():
# Codebase with complex domninators can lead to a lot of SSA recursive call
sys.setrecursionlimit(1500)
detectors, printers = get_detectors_and_printers()
main_impl(all_detector_classes=detectors, all_printer_classes=printers)
@ -733,7 +741,6 @@ def main_impl(all_detector_classes, all_printer_classes):
logging.error("Error in %s" % args.filename)
logging.error(output_error)
# If we are outputting JSON, capture the redirected output and disable the redirect to output the final JSON.
if outputting_json:
if "console" in args.json_types:

@ -651,13 +651,13 @@ class Node(SourceMapping, ChildFunction):
@property
def son_true(self) -> Optional["Node"]:
if self.type == NodeType.IF:
if self.type in [NodeType.IF, NodeType.IFLOOP]:
return self._sons[0]
return None
@property
def son_false(self) -> Optional["Node"]:
if self.type == NodeType.IF and len(self._sons) >= 1:
if self.type in [NodeType.IF, NodeType.IFLOOP] and len(self._sons) >= 1:
return self._sons[1]
return None
@ -984,11 +984,11 @@ class Node(SourceMapping, ChildFunction):
###################################################################################
def __str__(self):
additional_info = ''
additional_info = ""
if self.expression:
additional_info += ' ' + str(self.expression)
additional_info += " " + str(self.expression)
elif self.variable_declaration:
additional_info += ' ' + str(self.variable_declaration)
additional_info += " " + str(self.variable_declaration)
txt = str(self._node_type) + additional_info
return txt

@ -54,7 +54,7 @@ class Contract(ChildSlither, SourceMapping):
self._structures: Dict[str, "Structure"] = {}
self._events: Dict[str, "Event"] = {}
self._variables: Dict[str, "StateVariable"] = {}
self._variables_ordered: List["StateVariable"] = [] # contain also shadowed variables
self._variables_ordered: List["StateVariable"] = []
self._modifiers: Dict[str, "Modifier"] = {}
self._functions: Dict[str, "Function"] = {}
self._linearizedBaseContracts = List[int]
@ -255,7 +255,7 @@ class Contract(ChildSlither, SourceMapping):
@property
def state_variables_ordered(self) -> List["StateVariable"]:
"""
list(StateVariable): List of the state variables by order of declaration. Contains also shadowed variables
list(StateVariable): List of the state variables by order of declaration.
"""
return list(self._variables_ordered)

@ -89,6 +89,7 @@ class Function(ChildContract, ChildInheritance, SourceMapping):
def __init__(self):
super(Function, self).__init__()
self._scope: List[str] = []
self._name: Optional[str] = None
self._view: bool = False
self._pure: bool = False
@ -200,6 +201,20 @@ class Function(ChildContract, ChildInheritance, SourceMapping):
def name(self, new_name: str):
self._name = new_name
@property
def scope(self) -> List[str]:
"""
Return a list of name representing the scope of the function
This is used to model nested functions declared in YUL
:return:
"""
return self._scope
@scope.setter
def scope(self, new_scope: List[str]):
self._scope = new_scope
@property
def full_name(self) -> str:
"""
@ -207,7 +222,7 @@ class Function(ChildContract, ChildInheritance, SourceMapping):
Return the function signature without the return values
"""
name, parameters, _ = self.signature
return name + "(" + ",".join(parameters) + ")"
return ".".join(self._scope + [name]) + "(" + ",".join(parameters) + ")"
@property
def canonical_name(self) -> str:
@ -216,7 +231,12 @@ class Function(ChildContract, ChildInheritance, SourceMapping):
Return the function signature without the return values
"""
name, parameters, _ = self.signature
return self.contract_declarer.name + "." + name + "(" + ",".join(parameters) + ")"
return (
".".join([self.contract_declarer.name] + self._scope + [name])
+ "("
+ ",".join(parameters)
+ ")"
)
@property
def contains_assembly(self) -> bool:
@ -1282,7 +1302,7 @@ class Function(ChildContract, ChildInheritance, SourceMapping):
if node.irs:
label += "\nIRs:\n" + "\n".join([str(ir) for ir in node.irs])
content += '{}[label="{}"];\n'.format(node.node_id, label)
if node.type == NodeType.IF:
if node.type in [NodeType.IF, NodeType.IFLOOP]:
true_node = node.son_true
if true_node:
content += '{}->{}[label="True"];\n'.format(node.node_id, true_node.node_id)
@ -1538,7 +1558,7 @@ class Function(ChildContract, ChildInheritance, SourceMapping):
if self._entry_point is None:
return dict()
# node, values
to_explore: List[Tuple[Node, Dict]] = [(self._entry_point, dict())]
to_explore: List[Tuple["Node", Dict]] = [(self._entry_point, dict())]
# node -> values
explored: Dict = dict()
# name -> instances

@ -66,6 +66,7 @@ SOLIDITY_FUNCTIONS: Dict[str, List[str]] = {
# abi.decode returns an a list arbitrary types
"abi.decode()": [],
"type(address)": [],
"type()": [], # 0.6.8 changed type(address) to type()
}
@ -90,7 +91,14 @@ class SolidityVariable(Context):
# dev function, will be removed once the code is stable
def _check_name(self, name: str):
assert name in SOLIDITY_VARIABLES
assert name in SOLIDITY_VARIABLES or name.endswith("_slot") or name.endswith("_offset")
@property
def state_variable(self):
if self._name.endswith("_slot"):
return self._name[:-5]
if self._name.endswith("_offset"):
return self._name[:-7]
@property
def name(self) -> str:

@ -31,6 +31,15 @@ class BinaryOperationType(Enum):
ANDAND = 17 # &&
OROR = 18 # ||
# YUL specific operators
# TODO: investigate if we can remove these
# Find the types earlier on, and do the conversion
DIVISION_SIGNED = 19
MODULO_SIGNED = 20
LESS_SIGNED = 21
GREATER_SIGNED = 22
RIGHT_SHIFT_ARITHMETIC = 23
@staticmethod
def get_type(operation_type: "BinaryOperation"):
if operation_type == "**":
@ -71,6 +80,16 @@ class BinaryOperationType(Enum):
return BinaryOperationType.ANDAND
if operation_type == "||":
return BinaryOperationType.OROR
if operation_type == "/'":
return BinaryOperationType.DIVISION_SIGNED
if operation_type == "%'":
return BinaryOperationType.MODULO_SIGNED
if operation_type == "<'":
return BinaryOperationType.LESS_SIGNED
if operation_type == ">'":
return BinaryOperationType.GREATER_SIGNED
if operation_type == ">>'":
return BinaryOperationType.RIGHT_SHIFT_ARITHMETIC
raise SlitherCoreError("get_type: Unknown operation type {})".format(operation_type))
@ -113,6 +132,16 @@ class BinaryOperationType(Enum):
return "&&"
if self == BinaryOperationType.OROR:
return "||"
if self == BinaryOperationType.DIVISION_SIGNED:
return "/'"
if self == BinaryOperationType.MODULO_SIGNED:
return "%'"
if self == BinaryOperationType.LESS_SIGNED:
return "<'"
if self == BinaryOperationType.GREATER_SIGNED:
return ">'"
if self == BinaryOperationType.RIGHT_SHIFT_ARITHMETIC:
return ">>'"
raise SlitherCoreError("str: Unknown operation type {})".format(self))

@ -41,14 +41,6 @@ class CallExpression(Expression):
def call_salt(self, salt):
self._salt = salt
@property
def call_salt(self):
return self._salt
@call_salt.setter
def call_salt(self, salt):
self._salt = salt
@property
def called(self) -> Expression:
return self._called

@ -15,5 +15,10 @@ class ElementaryTypeNameExpression(Expression):
def type(self) -> Type:
return self._type
@type.setter
def type(self, new_type: Type):
assert isinstance(new_type, Type)
self._type = new_type
def __str__(self):
return str(self._type)

@ -5,13 +5,14 @@ import os
import logging
import json
import re
import math
from collections import defaultdict
from typing import Optional, Dict, List, Set, Union
from typing import Optional, Dict, List, Set, Union, Tuple
from crytic_compile import CryticCompile
from slither.core.context.context import Context
from slither.core.declarations import Contract, Pragma, Import, Function, Modifier
from slither.core.declarations import Contract, Pragma, Import, Function, Modifier, Structure, Enum
from slither.core.variables.state_variable import StateVariable
from slither.slithir.operations import InternalCall
from slither.slithir.variables import Constant
@ -56,6 +57,11 @@ class SlitherCore(Context):
self._contract_name_collisions = defaultdict(list)
self._contract_with_missing_inheritance = set()
self._storage_layouts: Dict[str, Dict[str, Tuple[int, int]]] = {}
# If set to true, slither will not catch errors during parsing
self._disallow_partial: bool = False
###################################################################################
###################################################################################
# region Source code
@ -136,7 +142,7 @@ class SlitherCore(Context):
"""list(Contract): List of contracts that are derived and not inherited."""
inheritance = (x.inheritance for x in self.contracts)
inheritance = [item for sublist in inheritance for item in sublist]
return [c for c in self._contracts.values() if c not in inheritance]
return [c for c in self._contracts.values() if c not in inheritance and not c.is_top_level]
@property
def contracts_as_dict(self) -> Dict[str, Contract]:
@ -200,6 +206,23 @@ class SlitherCore(Context):
self._all_state_variables = set(state_variables)
return list(self._all_state_variables)
# endregion
###################################################################################
###################################################################################
# region Top level
###################################################################################
###################################################################################
@property
def top_level_structures(self) -> List[Structure]:
top_level_structures = [c.structures for c in self.contracts if c.is_top_level]
return [st for sublist in top_level_structures for st in sublist]
@property
def top_level_enums(self) -> List[Enum]:
top_level_enums = [c.enums for c in self.contracts if c.is_top_level]
return [st for sublist in top_level_enums for st in sublist]
# endregion
###################################################################################
###################################################################################
@ -344,4 +367,50 @@ class SlitherCore(Context):
def contracts_with_missing_inheritance(self) -> Set:
return self._contract_with_missing_inheritance
@property
def disallow_partial(self) -> bool:
"""
Return true if partial analyses are disallowed
For example, codebase with duplicate names will lead to partial analyses
:return:
"""
return self._disallow_partial
# endregion
###################################################################################
###################################################################################
# region Storage Layouts
###################################################################################
###################################################################################
def compute_storage_layout(self):
for contract in self.contracts_derived:
self._storage_layouts[contract.name] = {}
slot = 0
offset = 0
for var in contract.state_variables_ordered:
if var.is_constant:
continue
size, new_slot = var.type.storage_size
if new_slot:
if offset > 0:
slot += 1
offset = 0
elif size + offset > 32:
slot += 1
offset = 0
self._storage_layouts[contract.name][var.canonical_name] = (slot, offset)
if new_slot:
slot += math.ceil(size / 32)
else:
offset += size
def storage_layout_of(self, contract, var) -> Tuple[int, int]:
return self._storage_layouts[contract.name][var.canonical_name]
# endregion

@ -1,4 +1,4 @@
from typing import Optional
from typing import Optional, Tuple
from slither.core.expressions import Literal
from slither.core.expressions.expression import Expression
@ -37,6 +37,13 @@ class ArrayType(Type):
def lenght_value(self) -> Optional[Literal]:
return self._length_value
@property
def storage_size(self) -> Tuple[int, bool]:
if self._length_value:
elem_size, _ = self._type.storage_size
return elem_size * int(self._length_value.value), True
return 32, True
def __str__(self):
if self._length:
return str(self._type) + "[{}]".format(str(self._length_value))

@ -1,5 +1,5 @@
import itertools
from typing import Optional
from typing import Optional, Tuple
from slither.core.solidity_types.type import Type
@ -172,6 +172,13 @@ class ElementaryType(Type):
return int(t[len("bytes") :])
return None
@property
def storage_size(self) -> Tuple[int, bool]:
if self._type == "string" or self._type == "bytes":
return 32, True
return int(self.size / 8), False
def __str__(self):
return self._type

@ -1,4 +1,4 @@
from typing import List
from typing import List, Tuple
from slither.core.solidity_types.type import Type
from slither.core.variables.function_type_variable import FunctionTypeVariable
@ -26,6 +26,10 @@ class FunctionType(Type):
def return_type(self) -> List[Type]:
return [x.type for x in self.return_values]
@property
def storage_size(self) -> Tuple[int, bool]:
return 24, False
def __str__(self):
# Use x.type
# x.name may be empty

@ -1,3 +1,5 @@
from typing import Tuple
from slither.core.solidity_types.type import Type
@ -17,6 +19,10 @@ class MappingType(Type):
def type_to(self) -> Type:
return self._to
@property
def storage_size(self) -> Tuple[int, bool]:
return 32, True
def __str__(self):
return "mapping({} => {})".format(str(self._from), str(self._to))

@ -1,5 +1,16 @@
import abc
from typing import Tuple
from slither.core.source_mapping.source_mapping import SourceMapping
class Type(SourceMapping):
pass
class Type(SourceMapping, metaclass=abc.ABCMeta):
@property
@abc.abstractmethod
def storage_size(self) -> Tuple[int, bool]:
"""
Computes and returns storage layout related metadata
:return: (int, bool) - the number of bytes this type will require, and whether it must start in
a new slot regardless of whether the current slot can still fit it
"""

@ -1,4 +1,4 @@
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, Tuple
from slither.core.solidity_types.type import Type
@ -20,6 +20,18 @@ class TypeInformation(Type):
def type(self) -> "Contract":
return self._type
@property
def storage_size(self) -> Tuple[int, bool]:
"""
32 is incorrect, as Type(x) return a kind of structure that can contain
an arbitrary number of value
As Type(x) cannot be directly stored, we are assuming that the correct storage size
will be handled by the fields access
:return:
"""
return 32, True
def __str__(self):
return f"type({self.type.name})"

@ -1,4 +1,5 @@
from typing import Union, TYPE_CHECKING
from typing import Union, TYPE_CHECKING, Tuple
import math
from slither.core.solidity_types.type import Type
@ -22,6 +23,38 @@ class UserDefinedType(Type):
def type(self) -> Union["Contract", "Enum", "Structure"]:
return self._type
@property
def storage_size(self) -> Tuple[int, bool]:
from slither.core.declarations.structure import Structure
from slither.core.declarations.enum import Enum
from slither.core.declarations.contract import Contract
if isinstance(self._type, Contract):
return 20, False
elif isinstance(self._type, Enum):
return int(math.ceil(math.log2(len(self._type.values)) / 8)), False
elif isinstance(self._type, Structure):
# todo there's some duplicate logic here and slither_core, can we refactor this?
slot = 0
offset = 0
for elem in self._type.elems_ordered:
size, new_slot = elem.type.storage_size
if new_slot:
if offset > 0:
slot += 1
offset = 0
elif size + offset > 32:
slot += 1
offset = 0
if new_slot:
slot += math.ceil(size / 32)
else:
offset += size
if offset > 0:
slot += 1
return slot * 32, True
def __str__(self):
from slither.core.declarations.structure import Structure
from slither.core.declarations.enum import Enum

@ -186,7 +186,7 @@ class AbstractDetector(metaclass=abc.ABCMeta):
if results and self.slither.triage_mode:
while True:
indexes = input(
'Results to hide during next runs: "0,1,..." or "All" (enter to not hide results): '.format(
'Results to hide during next runs: "0,1,...,{}" or "All" (enter to not hide results): '.format(
len(results)
)
)

@ -22,7 +22,7 @@ class ConstantFunctionsAsm(AbstractDetector):
WIKI_DESCRIPTION = """
Functions declared as `constant`/`pure`/`view` using assembly code.
`constant`/`pure`/`view` was not enforced prior Solidity 0.5.
`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)."""
@ -37,11 +37,11 @@ contract Constant{
}
}
```
`Constant` was deployed with Solidity 0.4.25. Bob writes a smart contract interacting with `Constant` in Solidity 0.5.0.
`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."""
WIKI_RECOMMENDATION = (
"Ensure that the attributes of contracts compiled prior to Solidity 0.5.0 are correct."
"Ensure the attributes of contracts compiled prior to Solidity 0.5.0 are correct."
)
def _detect(self):

@ -20,9 +20,9 @@ class ConstantFunctionsState(AbstractDetector):
WIKI_TITLE = "Constant functions changing the state"
WIKI_DESCRIPTION = """
Functions declared as `constant`/`pure`/`view` changing the state.
Functions declared as `constant`/`pure`/`view` change the state.
`constant`/`pure`/`view` was not enforced prior Solidity 0.5.
`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)."""
@ -37,11 +37,11 @@ contract Constant{
}
}
```
`Constant` was deployed with Solidity 0.4.25. Bob writes a smart contract interacting with `Constant` in Solidity 0.5.0.
`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."""
WIKI_RECOMMENDATION = (
"Ensure that the attributes of contracts compiled prior to Solidity 0.5.0 are correct."
"Ensure that attributes of contracts compiled prior to Solidity 0.5.0 are correct."
)
def _detect(self):

@ -19,7 +19,7 @@ class ConstantPragma(AbstractDetector):
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#different-pragma-directives-are-used"
WIKI_TITLE = "Different pragma directives are used"
WIKI_DESCRIPTION = "Detect if different Solidity versions are used."
WIKI_DESCRIPTION = "Detect whether different Solidity versions are used."
WIKI_RECOMMENDATION = "Use one Solidity version."
def _detect(self):

@ -30,24 +30,40 @@ class IncorrectSolc(AbstractDetector):
WIKI_TITLE = "Incorrect versions of Solidity"
WIKI_DESCRIPTION = """
Solc frequently releases new compiler versions. Using an old version prevents access to new Solidity security checks.
We recommend avoiding complex pragma statement."""
`solc` frequently releases new compiler versions. Using an old version prevents access to new Solidity security checks.
We also recommend avoiding complex `pragma` statement."""
WIKI_RECOMMENDATION = """
Use Solidity 0.4.25 or 0.5.11. Consider using the latest version of Solidity for testing the compilation, and a trusted version for deploying."""
Deploy with any of the following Solidity versions:
- 0.5.11 - 0.5.13,
- 0.5.15 - 0.5.17,
- 0.6.8,
- 0.6.10 - 0.6.11.
Use a simple pragma version that allows any of these versions.
Consider using the latest version of Solidity for testing."""
COMPLEX_PRAGMA_TXT = "is too complex"
OLD_VERSION_TXT = "allows old versions"
LESS_THAN_TXT = "uses lesser than"
TOO_RECENT_VERSION_TXT = (
"necessitates versions too recent to be trusted. Consider deploying with 0.5.11"
"necessitates a version too recent to be trusted. Consider deploying with 0.6.11"
)
BUGGY_VERSION_TXT = (
"is known to contain severe issue (https://solidity.readthedocs.io/en/v0.5.8/bugs.html)"
"is known to contain severe issues (https://solidity.readthedocs.io/en/latest/bugs.html)"
)
# Indicates the allowed versions. Must be formatted in increasing order.
ALLOWED_VERSIONS = ["0.4.25", "0.4.26", "0.5.11"]
ALLOWED_VERSIONS = [
"0.5.11",
"0.5.12",
"0.5.13",
"0.5.15",
"0.5.16",
"0.5.17",
"0.6.8",
"0.6.10",
"0.6.11",
]
# Indicates the versions that should not be used.
BUGGY_VERSIONS = [
@ -59,6 +75,8 @@ Use Solidity 0.4.25 or 0.5.11. Consider using the latest version of Solidity for
"^0.5.6",
"0.5.14",
"^0.5.14",
"0.6.9",
"^0.6.9",
]
def _check_version(self, version):
@ -124,6 +142,22 @@ Use Solidity 0.4.25 or 0.5.11. Consider using the latest version of Solidity for
results.append(json)
if self.slither.crytic_compile:
if self.slither.crytic_compile.compiler_version:
if (
self.slither.crytic_compile.compiler_version.version
not in self.ALLOWED_VERSIONS
):
info = [
"solc-",
self.slither.crytic_compile.compiler_version.version,
" is not recommended for deployement\n",
]
json = self.generate_result(info)
results.append(json)
return results
@staticmethod

@ -25,8 +25,8 @@ class LockedEther(AbstractDetector):
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#contracts-that-lock-ether"
WIKI_TITLE = "Contracts that lock ether"
WIKI_DESCRIPTION = "Contract with a `payable` function, but without a withdraw capacity."
WIKI_TITLE = "Contracts that lock Ether"
WIKI_DESCRIPTION = "Contract with a `payable` function, but without a withdrawal capacity."
WIKI_EXPLOIT_SCENARIO = """
```solidity
pragma solidity 0.4.24;
@ -35,7 +35,7 @@ contract Locked{
}
}
```
Every ether sent to `Locked` will be lost."""
Every Ether sent to `Locked` will be lost."""
WIKI_RECOMMENDATION = "Remove the payable attribute or add a withdraw function."

@ -18,7 +18,7 @@ class IncorrectERC20InterfaceDetection(AbstractDetector):
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-erc20-interface"
WIKI_TITLE = "Incorrect erc20 interface"
WIKI_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."
WIKI_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."
WIKI_EXPLOIT_SCENARIO = """
```solidity
contract Token{
@ -26,10 +26,10 @@ contract Token{
//...
}
```
`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."""
`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."""
WIKI_RECOMMENDATION = (
"Set the appropriate return values and value-types for the defined ERC20 functions."
"Set the appropriate return values and types for the defined `ERC20` functions."
)
@staticmethod

@ -19,7 +19,7 @@ class IncorrectERC721InterfaceDetection(AbstractDetector):
)
WIKI_TITLE = "Incorrect erc721 interface"
WIKI_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."
WIKI_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."
WIKI_EXPLOIT_SCENARIO = """
```solidity
contract Token{
@ -27,10 +27,10 @@ contract Token{
//...
}
```
`Token.ownerOf` does not return an address as 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."""
`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."""
WIKI_RECOMMENDATION = (
"Set the appropriate return values and value-types for the defined ERC721 functions."
"Set the appropriate return values and vtypes for the defined `ERC721` functions."
)
@staticmethod

@ -16,8 +16,8 @@ class UnindexedERC20EventParameters(AbstractDetector):
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#unindexed-erc20-event-parameters"
WIKI_TITLE = "Unindexed ERC20 Event Parameters"
WIKI_DESCRIPTION = "Detects that events defined by the ERC20 specification which are meant to have some parameters as `indexed`, are missing the `indexed` keyword."
WIKI_TITLE = "Unindexed ERC20 event oarameters"
WIKI_DESCRIPTION = "Detects whether events defined by the `ERC20` specification that should have some parameters as `indexed` are missing the `indexed` keyword."
WIKI_EXPLOIT_SCENARIO = """
```solidity
contract ERC20Bad {
@ -28,9 +28,10 @@ contract ERC20Bad {
// ...
}
```
In this case, 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 not include the parameter data in the transaction/block's bloom filter. This may cause external tooling searching for these parameters to overlook them, and fail to index logs from this token contract."""
`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."""
WIKI_RECOMMENDATION = "Add the `indexed` keyword to event parameters which should include it, according to the ERC20 specification."
WIKI_RECOMMENDATION = "Add the `indexed` keyword to event parameters that should include it, according to the `ERC20` specification."
STANDARD_JSON = False

@ -28,16 +28,14 @@ class ArbitrarySend(AbstractDetector):
"""
ARGUMENT = "arbitrary-send"
HELP = "Functions that send ether to arbitrary destinations"
HELP = "Functions that send Ether to arbitrary destinations"
IMPACT = DetectorClassification.HIGH
CONFIDENCE = DetectorClassification.MEDIUM
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#functions-that-send-ether-to-arbitrary-destinations"
WIKI_TITLE = "Functions that send ether to arbitrary destinations"
WIKI_DESCRIPTION = (
"Unprotected call to a function executing sending ethers to an arbitrary address."
)
WIKI_TITLE = "Functions that send Ether to arbitrary destinations"
WIKI_DESCRIPTION = "Unprotected call to a function sending Ether to an arbitrary address."
WIKI_EXPLOIT_SCENARIO = """
```solidity
contract ArbitrarySend{
@ -53,7 +51,7 @@ contract ArbitrarySend{
```
Bob calls `setDestination` and `withdraw`. As a result he withdraws the contract's balance."""
WIKI_RECOMMENDATION = "Ensure that an arbitrary user cannot withdraw unauthorize funds."
WIKI_RECOMMENDATION = "Ensure that an arbitrary user cannot withdraw unauthorized funds."
def arbitrary_send(self, func):
"""

@ -13,13 +13,13 @@ class ExternalFunction(AbstractDetector):
"""
ARGUMENT = "external-function"
HELP = "Public function that could be declared as external"
HELP = "Public function that could be declared external"
IMPACT = DetectorClassification.OPTIMIZATION
CONFIDENCE = DetectorClassification.HIGH
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#public-function-that-could-be-declared-as-external"
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#public-function-that-could-be-declared-external"
WIKI_TITLE = "Public function that could be declared as external"
WIKI_TITLE = "Public function that could be declared external"
WIKI_DESCRIPTION = "`public` functions that are never called by the contract should be declared `external` to save gas."
WIKI_RECOMMENDATION = (
"Use the `external` attribute for functions never called from the contract."

@ -45,7 +45,7 @@ Bob calls `kill` and destructs the contract."""
if func.is_constructor:
return False
if func.visibility != "public":
if func.visibility not in ["public", "external"]:
return False
calls = [c.name for c in func.internal_calls]
@ -59,7 +59,7 @@ Bob calls `kill` and destructs the contract."""
def detect_suicidal(self, contract):
ret = []
for f in [f for f in contract.functions if f.contract_declarer == contract]:
for f in contract.functions_declared:
if self.detect_suicidal_func(f):
ret.append(f)
return ret

@ -15,18 +15,18 @@ class NamingConvention(AbstractDetector):
"""
ARGUMENT = "naming-convention"
HELP = "Conformance to Solidity naming conventions"
HELP = "Conformity to Solidity naming conventions"
IMPACT = DetectorClassification.INFORMATIONAL
CONFIDENCE = DetectorClassification.HIGH
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#conformance-to-solidity-naming-conventions"
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#conformity-to-solidity-naming-conventions"
WIKI_TITLE = "Conformance to Solidity naming conventions"
WIKI_DESCRIPTION = """
Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.25/style-guide.html#naming-conventions) that should be followed.
#### Rules exceptions
- Allow constant variables name/symbol/decimals to be lowercase (ERC20)
- Allow `_` at the beginning of the mixed_case match for private variables and unused parameters."""
#### 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."""
WIKI_RECOMMENDATION = "Follow the Solidity [naming convention](https://solidity.readthedocs.io/en/v0.4.25/style-guide.html#naming-conventions)."

@ -18,7 +18,7 @@ class LowLevelCalls(AbstractDetector):
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#low-level-calls"
WIKI_TITLE = "Low level calls"
WIKI_TITLE = "Low-level calls"
WIKI_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."
WIKI_RECOMMENDATION = "Avoid low-level calls. Check the call success. If the call is meant for a contract, check for code existence."

@ -28,11 +28,11 @@ contract MyConc{
}
}
```
The return value of the low-level call is not checked. As a result if the callfailed, the ether will be locked in the contract.
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.
"""
WIKI_RECOMMENDATION = "Ensure that the return value of low-level call is checked or logged."
WIKI_RECOMMENDATION = "Ensure that the return value of a low-level call is checked or logged."
_txt_description = "low-level calls"

@ -20,7 +20,7 @@ class UncheckedSend(UnusedReturnValues):
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-send"
WIKI_TITLE = "Unchecked Send"
WIKI_DESCRIPTION = "The return value of a send is not checked."
WIKI_DESCRIPTION = "The return value of a `send` is not checked."
WIKI_EXPLOIT_SCENARIO = """
```solidity
contract MyConc{
@ -29,11 +29,11 @@ contract MyConc{
}
}
```
The return value of `send` is not checked. As a result if the send failed, the ether will be locked in the contract.
If `send` is used to prevent blocking operations, consider logging the failed sent.
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`.
"""
WIKI_RECOMMENDATION = "Ensure that the return value of send is checked or logged."
WIKI_RECOMMENDATION = "Ensure that the return value of `send` is checked or logged."
_txt_description = "send calls"

@ -32,7 +32,7 @@ contract MyConc{
}
}
```
`MyConc` calls `add` of SafeMath, but does not store the result in `a`. As a result, the computation has no effect."""
`MyConc` calls `add` of `SafeMath`, but does not store the result in `a`. As a result, the computation has no effect."""
WIKI_RECOMMENDATION = "Ensure that all the return values of the function calls are used."

@ -11,8 +11,8 @@ class VoidConstructor(AbstractDetector):
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#void-constructor"
WIKI_TITLE = "Void Constructor"
WIKI_DESCRIPTION = "Detect the call to a constructor not implemented"
WIKI_TITLE = "Void constructor"
WIKI_DESCRIPTION = "Detect the call to a constructor that is not implemented"
WIKI_RECOMMENDATION = "Remove the constructor call."
WIKI_EXPLOIT_SCENARIO = """
```solidity
@ -21,7 +21,7 @@ contract B is A{
constructor() public A(){}
}
```
By reading B's constructor definition, the reader might assume that `A()` initiate the contract, while no code is executed."""
When reading `B`'s constructor definition, we might assume that `A()` initiates the contract, but no code is executed."""
def _detect(self):
"""

@ -26,7 +26,7 @@ class ReentrancyBenign(Reentrancy):
WIKI_TITLE = "Reentrancy vulnerabilities"
WIKI_DESCRIPTION = """
Detection of the [re-entrancy bug](https://github.com/trailofbits/not-so-smart-contracts/tree/master/reentrancy).
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`)."""
WIKI_EXPLOIT_SCENARIO = """
```solidity
@ -40,7 +40,7 @@ Only report reentrancy that acts as a double call (see `reentrancy-eth`, `reentr
`callme` contains a reentrancy. The reentrancy is benign because it's exploitation would have the same effect as two consecutive calls."""
WIKI_RECOMMENDATION = "Apply the [check-effects-interactions pattern](http://solidity.readthedocs.io/en/v0.4.21/security-considerations.html#re-entrancy)."
WIKI_RECOMMENDATION = "Apply the [`check-effects-interactions` pattern](http://solidity.readthedocs.io/en/v0.4.21/security-considerations.html#re-entrancy)."
STANDARD_JSON = False

@ -26,12 +26,12 @@ class ReentrancyEth(Reentrancy):
WIKI_TITLE = "Reentrancy vulnerabilities"
WIKI_DESCRIPTION = """
Detection of the [re-entrancy bug](https://github.com/trailofbits/not-so-smart-contracts/tree/master/reentrancy).
Do not report reentrancies that don't involve ethers (see `reentrancy-no-eth`)"""
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`)"""
WIKI_EXPLOIT_SCENARIO = """
```solidity
function withdrawBalance(){
// send userBalance[msg.sender] ethers to msg.sender
// send userBalance[msg.sender] Ether to msg.sender
// if mgs.sender is a contract, it will call its fallback function
if( ! (msg.sender.call.value(userBalance[msg.sender])() ) ){
throw;
@ -42,7 +42,7 @@ Do not report reentrancies that don't involve ethers (see `reentrancy-no-eth`)""
Bob uses the re-entrancy bug to call `withdrawBalance` two times, and withdraw more than its initial deposit to the contract."""
WIKI_RECOMMENDATION = "Apply the [check-effects-interactions pattern](http://solidity.readthedocs.io/en/v0.4.21/security-considerations.html#re-entrancy)."
WIKI_RECOMMENDATION = "Apply the [`check-effects-interactions pattern`](http://solidity.readthedocs.io/en/v0.4.21/security-considerations.html#re-entrancy)."
STANDARD_JSON = False

@ -25,8 +25,8 @@ class ReentrancyEvent(Reentrancy):
WIKI_TITLE = "Reentrancy vulnerabilities"
WIKI_DESCRIPTION = """
Detection of the [re-entrancy bug](https://github.com/trailofbits/not-so-smart-contracts/tree/master/reentrancy).
Only report reentrancies leading to out-of-order Events"""
Detection of the [reentrancy bug](https://github.com/trailofbits/not-so-smart-contracts/tree/master/reentrancy).
Only report reentrancies leading to out-of-order events."""
WIKI_EXPLOIT_SCENARIO = """
```solidity
function bug(Called d){
@ -36,9 +36,9 @@ Only report reentrancies leading to out-of-order Events"""
}
```
If `d.()` reenters, the `Counter` events will be showed in an incorrect order, which might lead to issues for third-parties."""
If `d.()` re-enters, the `Counter` events will be shown in an incorrect order, which might lead to issues for third parties."""
WIKI_RECOMMENDATION = "Apply the [check-effects-interactions pattern](http://solidity.readthedocs.io/en/v0.4.21/security-considerations.html#re-entrancy)."
WIKI_RECOMMENDATION = "Apply the [`check-effects-interactions` pattern](http://solidity.readthedocs.io/en/v0.4.21/security-considerations.html#re-entrancy)."
STANDARD_JSON = False
@ -85,7 +85,7 @@ If `d.()` reenters, the `Counter` events will be showed in an incorrect order, w
for (func, calls, send_eth), events in result_sorted:
calls = sorted(list(set(calls)), key=lambda x: x[0].node_id)
send_eth = sorted(list(set(send_eth)), key=lambda x: x[0].node_id)
events = sorted(events, key=lambda x: (x.variable.name, x.node.node_id))
events = sorted(events, key=lambda x: (str(x.variable.name), x.node.node_id))
info = ["Reentrancy in ", func, ":\n"]
info += ["\tExternal calls:\n"]

@ -29,8 +29,8 @@ class ReentrancyNoGas(Reentrancy):
WIKI_TITLE = "Reentrancy vulnerabilities"
WIKI_DESCRIPTION = """
Detection of the [re-entrancy bug](https://github.com/trailofbits/not-so-smart-contracts/tree/master/reentrancy).
Only report reentrancy that are based on `transfer` or `send`."""
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`."""
WIKI_EXPLOIT_SCENARIO = """
```solidity
function callme(){
@ -39,9 +39,9 @@ Only report reentrancy that are based on `transfer` or `send`."""
}
```
`send` and `transfer` does not protect from reentrancies in case of gas-price change."""
`send` and `transfer` do not protect from reentrancies in case of gas price changes."""
WIKI_RECOMMENDATION = "Apply the [check-effects-interactions pattern](http://solidity.readthedocs.io/en/v0.4.21/security-considerations.html#re-entrancy)."
WIKI_RECOMMENDATION = "Apply the [`check-effects-interactions` pattern](http://solidity.readthedocs.io/en/v0.4.21/security-considerations.html#re-entrancy)."
@staticmethod
def can_callback(ir):

@ -25,8 +25,8 @@ class ReentrancyReadBeforeWritten(Reentrancy):
WIKI_TITLE = "Reentrancy vulnerabilities"
WIKI_DESCRIPTION = """
Detection of the [re-entrancy bug](https://github.com/trailofbits/not-so-smart-contracts/tree/master/reentrancy).
Do not report reentrancies that involve ethers (see `reentrancy-eth`)"""
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`)."""
WIKI_EXPLOIT_SCENARIO = """
```solidity
@ -39,7 +39,7 @@ Do not report reentrancies that involve ethers (see `reentrancy-eth`)"""
}
```
"""
WIKI_RECOMMENDATION = "Apply the [check-effects-interactions pattern](http://solidity.readthedocs.io/en/v0.4.21/security-considerations.html#re-entrancy)."
WIKI_RECOMMENDATION = "Apply the [`check-effects-interactions` pattern](http://solidity.readthedocs.io/en/v0.4.21/security-considerations.html#re-entrancy)."
STANDARD_JSON = False

@ -18,7 +18,7 @@ class BuiltinSymbolShadowing(AbstractDetector):
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#builtin-symbol-shadowing"
WIKI_TITLE = "Builtin Symbol Shadowing"
WIKI_DESCRIPTION = "Detection of shadowing built-in symbols using local variables/state variables/functions/modifiers/events."
WIKI_DESCRIPTION = "Detection of shadowing built-in symbols using local variables, state variables, functions, modifiers, or events."
WIKI_EXPLOIT_SCENARIO = """
```solidity
pragma solidity ^0.4.24;
@ -37,7 +37,7 @@ contract Bug {
```
`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."""
WIKI_RECOMMENDATION = "Rename the local variable/state variable/function/modifier/event, so as not to mistakenly overshadow any built-in symbol definitions."
WIKI_RECOMMENDATION = "Rename the local variables, state variables, functions, modifiers, and events that shadow a builtin symbol."
SHADOWING_FUNCTION = "function"
SHADOWING_MODIFIER = "modifier"

@ -17,7 +17,7 @@ class LocalShadowing(AbstractDetector):
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#local-variable-shadowing"
WIKI_TITLE = "Local Variable Shadowing"
WIKI_TITLE = "Local variable shadowing"
WIKI_DESCRIPTION = "Detection of shadowing using local variables."
WIKI_EXPLOIT_SCENARIO = """
```solidity
@ -38,9 +38,9 @@ contract Bug {
}
}
```
`sensitive_function.owner` shadows `Bug.owner`. As a result, the use of `owner` inside `sensitive_function` might be incorrect."""
`sensitive_function.owner` shadows `Bug.owner`. As a result, the use of `owner` in `sensitive_function` might be incorrect."""
WIKI_RECOMMENDATION = "Rename the local variable so as not to mistakenly overshadow any state variable/function/modifier/event definitions."
WIKI_RECOMMENDATION = "Rename the local variables that shadow another component."
OVERSHADOWED_FUNCTION = "function"
OVERSHADOWED_MODIFIER = "modifier"

@ -33,11 +33,11 @@ class NameReused(AbstractDetector):
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#name-reused"
WIKI_TITLE = "Name reused"
WIKI_DESCRIPTION = """If a codebase has two contracts with the similar name, the compilation artifacts
will not contain one of the contract with the dupplicate name."""
WIKI_DESCRIPTION = """If a codebase has two contracts the similar names, the compilation artifacts
will not contain one of the contracts with the duplicate name."""
WIKI_EXPLOIT_SCENARIO = """
Bob's truffle codebase has two contracts named `ERC20`.
When `truffle compile` runs, only one of the two contract will generate artifacts in `build/contracts`.
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.
"""
WIKI_RECOMMENDATION = "Rename the contract."

@ -13,8 +13,8 @@ class RightToLeftOverride(AbstractDetector):
CONFIDENCE = DetectorClassification.HIGH
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#right-to-left-override-character"
WIKI_TITLE = "Right-To-Left-Override character"
WIKI_DESCRIPTION = "An attacker can manipulate the logic of the contract by using a right-to-left-override character (U+202E)"
WIKI_TITLE = "Right-to-Left-Override character"
WIKI_DESCRIPTION = "An attacker can manipulate the logic of the contract by using a right-to-left-override character (`U+202E)`."
WIKI_EXPLOIT_SCENARIO = """
```solidity
contract Token

@ -20,7 +20,7 @@ class Assembly(AbstractDetector):
WIKI_TITLE = "Assembly usage"
WIKI_DESCRIPTION = "The use of assembly is error-prone and should be avoided."
WIKI_RECOMMENDATION = "Do not use evm assembly."
WIKI_RECOMMENDATION = "Do not use `evm` assembly."
@staticmethod
def _contains_inline_assembly_use(node):

@ -19,8 +19,8 @@ class BooleanEquality(AbstractDetector):
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#boolean-equality"
WIKI_TITLE = "Boolean Equality"
WIKI_DESCRIPTION = """Detects the comparison to boolean constant."""
WIKI_TITLE = "Boolean equality"
WIKI_DESCRIPTION = """Detects the comparison to boolean constants."""
WIKI_EXPLOIT_SCENARIO = """
```solidity
contract A {
@ -33,7 +33,7 @@ contract A {
}
}
```
Boolean can be used directly and do not need to be compare to `true` or `false`."""
Boolean constants can be used directly and do not need to be compare to `true` or `false`."""
WIKI_RECOMMENDATION = """Remove the equality to the boolean constant."""

@ -52,7 +52,8 @@ contract A {
}
}
```
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 debugging/development code that is likely faulty."""
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."""
WIKI_RECOMMENDATION = """Verify and simplify the condition."""

@ -17,7 +17,7 @@ class MultipleCallsInLoop(AbstractDetector):
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation/#calls-inside-a-loop"
WIKI_TITLE = "Calls inside a loop"
WIKI_DESCRIPTION = "Calls inside a loop might lead to denial of service attack."
WIKI_DESCRIPTION = "Calls inside a loop might lead to a denial-of-service attack."
WIKI_EXPLOIT_SCENARIO = """
```solidity
contract CallsInLoop{
@ -36,7 +36,7 @@ contract CallsInLoop{
}
```
If one of the destinations has a fallback function which reverts, `bad` will always revert."""
If one of the destinations has a fallback function that reverts, `bad` will always revert."""
WIKI_RECOMMENDATION = "Favor [pull over push](https://github.com/ethereum/wiki/wiki/Safety#favor-pull-over-push-for-external-calls) strategy for external calls."

@ -15,7 +15,7 @@ class ControlledDelegateCall(AbstractDetector):
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#controlled-delegatecall"
WIKI_TITLE = "Controlled Delegatecall"
WIKI_DESCRIPTION = "Delegatecall or callcode to an address controlled by the user."
WIKI_DESCRIPTION = "`Delegatecall` or `callcode` to an address controlled by the user."
WIKI_EXPLOIT_SCENARIO = """
```solidity
contract Delegatecall{
@ -24,7 +24,7 @@ contract Delegatecall{
}
}
```
Bob calls `delegate` and delegates the execution to its malicious contract. As a result, Bob withdraws the funds of the contract and destructs it."""
Bob calls `delegate` and delegates the execution to his malicious contract. As a result, Bob withdraws the funds of the contract and destructs it."""
WIKI_RECOMMENDATION = "Avoid using `delegatecall`. Use only trusted destinations."

@ -22,8 +22,8 @@ class DeprecatedStandards(AbstractDetector):
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#deprecated-standards"
WIKI_TITLE = "Deprecated Standards"
WIKI_DESCRIPTION = "Detect the usage of deprecated standards (as defined by SWC-111), excluding only `constant` keyword detection on functions."
WIKI_TITLE = "Deprecated standards"
WIKI_DESCRIPTION = "Detect the usage of deprecated standards."
WIKI_EXPLOIT_SCENARIO = """
```solidity
contract ContractWithDeprecatedReferences {

@ -64,7 +64,7 @@ class DivideBeforeMultiply(AbstractDetector):
WIKI_TITLE = "Divide before multiply"
WIKI_DESCRIPTION = """Solidity only supports integers, so division will often truncate; performing a multiply before a divison can sometimes avoid loss of precision."""
WIKI_DESCRIPTION = """Solidity integer division might truncate. As a result, performing a multiply before a divison might lead to loss of precision."""
WIKI_DESCRIPTION = """Solidity integer division might truncate. As a result, performing multiplication before divison might reduce precision."""
WIKI_EXPLOIT_SCENARIO = """
```solidity
contract A {
@ -75,9 +75,9 @@ contract A {
```
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 multiply before divide, unless the limit of a smaller type makes this dangerous."""
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."""
WIKI_RECOMMENDATION = """Consider ordering multiplication prior division."""
WIKI_RECOMMENDATION = """Consider ordering multiplication before division."""
def _explore(self, node, explored, f_results, divisions):
if node in explored:

@ -33,10 +33,11 @@ contract Crowdsale{
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."""
`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."""
WIKI_RECOMMENDATION = (
"""Don't use strict equality to determine if an account has enough ethers or tokens."""
"""Don't use strict equality to determine if an account has enough Ether or tokens."""
)
sources_taint = [
@ -68,6 +69,7 @@ contract Crowdsale{
# TODO: fix Balance support
taints.append(ir.lvalue)
if isinstance(ir, HighLevelCall):
# print(ir.function.full_name)
if (
isinstance(ir.function, Function)
and ir.function.full_name == "balanceOf(address)"

@ -28,11 +28,11 @@ contract MyContract{
}
```
While `1_ether` looks like `1 ether`, it is `10 ether`. As a result, its usage is likely to be incorrect.
While `1_ether` looks like `1 ether`, it is `10 ether`. As a result, it's likely to be used incorrectly.
"""
WIKI_RECOMMENDATION = """
Use:
- [Ether suffix](https://solidity.readthedocs.io/en/latest/units-and-global-variables.html#ether-units)
- [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)
"""

@ -20,7 +20,7 @@ class TxOrigin(AbstractDetector):
)
WIKI_TITLE = "Dangerous usage of `tx.origin`"
WIKI_DESCRIPTION = "`tx.origin`-based protection can be abused by malicious contract if a legitimate user interacts with the malicious contract."
WIKI_DESCRIPTION = "`tx.origin`-based protection can be abused by a malicious contract if a legitimate user interacts with the malicious contract."
WIKI_EXPLOIT_SCENARIO = """
```solidity
contract TxOrigin {

@ -42,12 +42,12 @@ contract A {
}
}
```
`x` is an `uint256`, as a result `x >= 0` will be always true.
`y` is an `uint8`, as a result `y <512` will be always true.
`x` is a `uint256`, so `x >= 0` will be always true.
`y` is a `uint8`, so `y <512` will be always true.
"""
WIKI_RECOMMENDATION = (
"""Fix the incorrect comparison by chaning the value type or the comparison."""
"""Fix the incorrect comparison by changing the value type or the comparison."""
)
def typeRange(self, t):

@ -26,8 +26,8 @@ class ConstCandidateStateVars(AbstractDetector):
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#state-variables-that-could-be-declared-constant"
WIKI_TITLE = "State variables that could be declared constant"
WIKI_DESCRIPTION = "Constant state variable should be declared constant to save gas."
WIKI_RECOMMENDATION = "Add the `constant` attributes to the state variables that never change."
WIKI_DESCRIPTION = "Constant state variables should be declared constant to save gas."
WIKI_RECOMMENDATION = "Add the `constant` attributes to state variables that never change."
@staticmethod
def _valid_candidate(v):

@ -30,7 +30,7 @@ contract Uninitialized is Owner{
}
}
```
Bob calls `transfer`. As a result, the ethers are sent to the address 0x0 and are lost."""
Bob calls `transfer`. As a result, all Ether is sent to the address `0x0` and is lost."""
WIKI_RECOMMENDATION = "Initialize all the variables. If a variable is meant to be initialized to zero, explicitly set it to zero."

@ -38,7 +38,7 @@ contract Uninitialized{
}
}
```
Bob calls `transfer`. As a result, the ethers are sent to the address 0x0 and are lost.
Bob calls `transfer`. As a result, the Ether are sent to the address `0x0` and are lost.
"""
WIKI_RECOMMENDATION = """
Initialize all the variables. If a variable is meant to be initialized to zero, explicitly set it to zero.

@ -20,7 +20,7 @@ class UninitializedStorageVars(AbstractDetector):
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-storage-variables"
WIKI_TITLE = "Uninitialized storage variables"
WIKI_DESCRIPTION = "An uinitialized storage variable will act as a reference to the first state variable, and can override a critical variable."
WIKI_DESCRIPTION = "An uninitialized storage variable will act as a reference to the first state variable, and can override a critical variable."
WIKI_EXPLOIT_SCENARIO = """
```solidity
contract Uninitialized{
@ -36,10 +36,10 @@ contract Uninitialized{
}
}
```
Bob calls `func`. As a result, `owner` is override to 0.
Bob calls `func`. As a result, `owner` is overridden to `0`.
"""
WIKI_RECOMMENDATION = "Initialize all the storage variables."
WIKI_RECOMMENDATION = "Initialize all storage variables."
# node.context[self.key] contains the uninitialized storage variables
key = "UNINITIALIZEDSTORAGE"

@ -21,7 +21,7 @@ class UnusedStateVars(AbstractDetector):
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#unused-state-variables"
WIKI_TITLE = "Unused state variables"
WIKI_TITLE = "Unused state variable"
WIKI_DESCRIPTION = "Unused state variable."
WIKI_EXPLOIT_SCENARIO = ""
WIKI_RECOMMENDATION = "Remove unused state variables."

@ -41,6 +41,8 @@ class PrinterWrittenVariablesAndAuthorization(AbstractPrinter):
txt = ""
all_tables = []
for contract in self.contracts:
if contract.is_top_level:
continue
txt += "\nContract %s\n" % contract.name
table = MyPrettyTable(
["Function", "State variables written", "Conditions on msg.sender"]

@ -21,6 +21,8 @@ class CFG(AbstractPrinter):
info = ""
all_files = []
for contract in self.contracts:
if contract.is_top_level:
continue
for function in contract.functions + contract.modifiers:
if original_filename:
filename = "{}-{}-{}.dot".format(

@ -18,6 +18,7 @@ from slither.core.slither_core import SlitherCore
from slither.core.variables.state_variable import StateVariable
from slither.core.variables.variable import Variable
from slither.printers.abstract_printer import AbstractPrinter
from slither.slithir.operations import (
AccessMember,
Operation,

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save