Merge remote-tracking branch 'crytic/slither/dev' into dev-upgradeability-utils

pull/1757/head
webthethird 2 years ago
commit ccb98d883e
  1. 61
      .github/ISSUE_TEMPLATE/false_negative.yml
  2. 61
      .github/ISSUE_TEMPLATE/false_positive.yml
  3. 1
      .github/workflows/read_storage.yml
  4. 4
      setup.py
  5. 2
      slither/__main__.py
  6. 2
      slither/printers/summary/slithir.py
  7. 34
      slither/tools/read_storage/read_storage.py
  8. 6
      slither/tools/read_storage/utils/__init__.py
  9. 2
      slither/tools/read_storage/utils/utils.py
  10. 18
      tests/test_read_storage.py

@ -0,0 +1,61 @@
---
body:
-
attributes:
value: |
Please check the issues tab to avoid duplicates.
Thanks for helping make Slither the best it can be!
type: markdown
-
attributes:
label: "What bug did Slither miss and which detector did you anticipate would catch it?"
id: what-happened
type: textarea
validations:
required: true
-
attributes:
label: Frequency
description: How often do you run across this false negative?
options:
- Very Frequently
- Occasionally
- Rarely
- Not sure
id: frequency
type: dropdown
validations:
required: true
-
attributes:
description: "It can be a github repo, etherscan link, or code snippet."
label: "Code example to reproduce the issue:"
placeholder: "`contract A {}`\n"
id: reproduce
type: textarea
validations:
required: true
-
attributes:
description: |
What version of slither are you running?
Run `slither --version`
label: "Version:"
id: version
type: textarea
validations:
required: true
-
attributes:
description: |
Please copy and paste the result output. This
will be automatically formatted into code, so no need for backticks.
render: shell
label: "Relevant log output:"
id: logs
type: textarea
description: "Slither missed a bug it should find."
labels:
- false-negative
name: False Negative"
title: "[False Negative]: "

@ -0,0 +1,61 @@
---
body:
-
attributes:
value: |
Please check the issues tab to avoid duplicates.
Thanks for helping make Slither the best it can be!
type: markdown
-
attributes:
label: "Describe the false alarm that Slither raise and how you know it's inaccurate:"
id: what-happened
type: textarea
validations:
required: true
-
attributes:
label: Frequency
description: How often do you run across this false positive?
options:
- Very Frequently
- Occasionally
- Rarely
- Not sure
id: frequency
type: dropdown
validations:
required: true
-
attributes:
description: "It can be a github repo, etherscan link, or code snippet."
label: "Code example to reproduce the issue:"
placeholder: "`contract A {}`\n"
id: reproduce
type: textarea
validations:
required: true
-
attributes:
description: |
What version of slither are you running?
Run `slither --version`
label: "Version:"
id: version
type: textarea
validations:
required: true
-
attributes:
description: |
Please copy and paste the result output. This
will be automatically formatted into code, so no need for backticks.
render: shell
label: "Relevant log output:"
id: logs
type: textarea
description: "Slither warned of an issue that is not legitimate and does not need to be fixed."
labels:
- false-positive
name: "False Positive"
title: "[False-Positive]: "

@ -40,7 +40,6 @@ jobs:
- name: Install python dependencies - name: Install python dependencies
run: | run: |
pip install ".[dev]" pip install ".[dev]"
pip install web3
solc-select install 0.8.1 solc-select install 0.8.1
solc-select install 0.8.10 solc-select install 0.8.10
solc-select use 0.8.1 solc-select use 0.8.1

@ -27,10 +27,10 @@ setup(
"pytest-xdist", "pytest-xdist",
"deepdiff", "deepdiff",
"numpy", "numpy",
"solc-select>=v1.0.0b1",
"openai", "openai",
"pdoc", "pdoc",
] "web3>=6.0.0",
],
}, },
license="AGPL-3.0", license="AGPL-3.0",
long_description=long_description, long_description=long_description,

@ -514,7 +514,7 @@ def parse_args(
group_misc.add_argument( group_misc.add_argument(
"--filter-paths", "--filter-paths",
help="Comma-separated list of paths for which results will be excluded", help="Regex filter to exclude detector results matching file path e.g. (mocks/|test/)",
action="store", action="store",
dest="filter_paths", dest="filter_paths",
default=defaults_flag_in_config["filter_paths"], default=defaults_flag_in_config["filter_paths"],

@ -46,7 +46,7 @@ class PrinterSlithIR(AbstractPrinter):
txt += f"\tModifier {modifier.canonical_name}\n" txt += f"\tModifier {modifier.canonical_name}\n"
txt += _print_function(modifier) txt += _print_function(modifier)
if compilation_unit.functions_top_level: if compilation_unit.functions_top_level:
txt += "Top level functions" txt += "Top level functions\n"
for function in compilation_unit.functions_top_level: for function in compilation_unit.functions_top_level:
txt += f"\tFunction {function.canonical_name}\n" txt += f"\tFunction {function.canonical_name}\n"
txt += _print_function(function) txt += _print_function(function)

@ -1,30 +1,22 @@
import logging import logging
import sys
from math import floor from math import floor
from typing import Callable, Optional, Tuple, Union, List, Dict, Any from typing import Any, Callable, Dict, List, Optional, Tuple, Union
try: import dataclasses
from web3 import Web3
from eth_abi import decode, encode
from eth_typing.evm import ChecksumAddress from eth_typing.evm import ChecksumAddress
from eth_abi import decode_single, encode_abi
from eth_utils import keccak from eth_utils import keccak
from .utils import ( from web3 import Web3
get_offset_value,
get_storage_data,
coerce_type,
)
except ImportError:
print("ERROR: in order to use slither-read-storage, you need to install web3")
print("$ pip3 install web3 --user\n")
sys.exit(-1)
import dataclasses
from slither.utils.myprettytable import MyPrettyTable
from slither.core.solidity_types.type import Type
from slither.core.solidity_types import ArrayType, ElementaryType, UserDefinedType, MappingType
from slither.core.declarations import Contract, Structure from slither.core.declarations import Contract, Structure
from slither.core.solidity_types import ArrayType, ElementaryType, MappingType, UserDefinedType
from slither.core.solidity_types.type import Type
from slither.core.variables.state_variable import StateVariable from slither.core.variables.state_variable import StateVariable
from slither.core.variables.structure_variable import StructureVariable from slither.core.variables.structure_variable import StructureVariable
from slither.utils.myprettytable import MyPrettyTable
from .utils import coerce_type, get_offset_value, get_storage_data
logging.basicConfig() logging.basicConfig()
logger = logging.getLogger("Slither-read-storage") logger = logging.getLogger("Slither-read-storage")
@ -92,7 +84,7 @@ class SlitherReadStorage:
if not self.storage_address: if not self.storage_address:
raise ValueError raise ValueError
if not self._checksum_address: if not self._checksum_address:
self._checksum_address = self.web3.toChecksumAddress(self.storage_address) self._checksum_address = self.web3.to_checksum_address(self.storage_address)
return self._checksum_address return self._checksum_address
@property @property
@ -449,7 +441,7 @@ class SlitherReadStorage:
if "int" in key_type: # without this eth_utils encoding fails if "int" in key_type: # without this eth_utils encoding fails
key = int(key) key = int(key)
key = coerce_type(key_type, key) key = coerce_type(key_type, key)
slot = keccak(encode_abi([key_type, "uint256"], [key, decode_single("uint256", slot)])) slot = keccak(encode([key_type, "uint256"], [key, decode("uint256", slot)]))
if isinstance(target_variable_type.type_to, UserDefinedType) and isinstance( if isinstance(target_variable_type.type_to, UserDefinedType) and isinstance(
target_variable_type.type_to.type, Structure target_variable_type.type_to.type, Structure
@ -471,7 +463,7 @@ class SlitherReadStorage:
deep_key = int(deep_key) deep_key = int(deep_key)
# If deep map, will be keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot))))) # If deep map, will be keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))))
slot = keccak(encode_abi([key_type, "bytes32"], [deep_key, slot])) slot = keccak(encode([key_type, "bytes32"], [deep_key, slot]))
# mapping(elem => mapping(elem => elem)) # mapping(elem => mapping(elem => elem))
target_variable_type_type_to_type_to = target_variable_type.type_to.type_to target_variable_type_type_to_type_to = target_variable_type.type_to.type_to

@ -1,5 +1 @@
from .utils import ( from .utils import coerce_type, get_offset_value, get_storage_data
get_offset_value,
get_storage_data,
coerce_type,
)

@ -1,7 +1,7 @@
from typing import Union from typing import Union
from eth_typing.evm import ChecksumAddress from eth_typing.evm import ChecksumAddress
from eth_utils import to_int, to_text, to_checksum_address from eth_utils import to_checksum_address, to_int, to_text
def get_offset_value(hex_bytes: bytes, offset: int, size: int) -> bytes: def get_offset_value(hex_bytes: bytes, offset: int, size: int) -> bytes:

@ -1,7 +1,6 @@
import re
import os
import sys
import json import json
import os
import re
import shutil import shutil
import subprocess import subprocess
from time import sleep from time import sleep
@ -9,16 +8,11 @@ from typing import Generator
import pytest import pytest
from deepdiff import DeepDiff from deepdiff import DeepDiff
from slither import Slither
from slither.tools.read_storage import SlitherReadStorage
try:
from web3 import Web3 from web3 import Web3
from web3.contract import Contract from web3.contract import Contract
except ImportError:
print("ERROR: in order to use slither-read-storage, you need to install web3") from slither import Slither
print("$ pip3 install web3 --user\n") from slither.tools.read_storage import SlitherReadStorage
sys.exit(-1)
SLITHER_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) SLITHER_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
STORAGE_TEST_ROOT = os.path.join(SLITHER_ROOT, "tests", "storage-layout") STORAGE_TEST_ROOT = os.path.join(SLITHER_ROOT, "tests", "storage-layout")
@ -98,7 +92,7 @@ def deploy_contract(w3, ganache, contract_bin, contract_abi) -> Contract:
# pylint: disable=too-many-locals # pylint: disable=too-many-locals
@pytest.mark.usefixtures("web3", "ganache") @pytest.mark.usefixtures("web3", "ganache")
def test_read_storage(web3, ganache) -> None: def test_read_storage(web3, ganache) -> None:
assert web3.isConnected() assert web3.is_connected()
bin_path = os.path.join(STORAGE_TEST_ROOT, "StorageLayout.bin") bin_path = os.path.join(STORAGE_TEST_ROOT, "StorageLayout.bin")
abi_path = os.path.join(STORAGE_TEST_ROOT, "StorageLayout.abi") abi_path = os.path.join(STORAGE_TEST_ROOT, "StorageLayout.abi")
bytecode = get_source_file(bin_path) bytecode = get_source_file(bin_path)

Loading…
Cancel
Save