mirror of https://github.com/crytic/slither
commit
6a10e0a1e1
@ -0,0 +1,88 @@ |
|||||||
|
SHELL := /bin/bash
|
||||||
|
|
||||||
|
PY_MODULE := slither
|
||||||
|
TEST_MODULE := tests
|
||||||
|
|
||||||
|
ALL_PY_SRCS := $(shell find $(PY_MODULE) -name '*.py') \
|
||||||
|
$(shell find test -name '*.py')
|
||||||
|
|
||||||
|
# Optionally overriden by the user, if they're using a virtual environment manager.
|
||||||
|
VENV ?= env
|
||||||
|
|
||||||
|
# On Windows, venv scripts/shims are under `Scripts` instead of `bin`.
|
||||||
|
VENV_BIN := $(VENV)/bin
|
||||||
|
ifeq ($(OS),Windows_NT) |
||||||
|
VENV_BIN := $(VENV)/Scripts
|
||||||
|
endif |
||||||
|
|
||||||
|
# Optionally overridden by the user in the `release` target.
|
||||||
|
BUMP_ARGS :=
|
||||||
|
|
||||||
|
# Optionally overridden by the user in the `test` target.
|
||||||
|
TESTS :=
|
||||||
|
|
||||||
|
# Optionally overridden by the user/CI, to limit the installation to a specific
|
||||||
|
# subset of development dependencies.
|
||||||
|
SLITHER_EXTRA := dev
|
||||||
|
|
||||||
|
# If the user selects a specific test pattern to run, set `pytest` to fail fast
|
||||||
|
# and only run tests that match the pattern.
|
||||||
|
# Otherwise, run all tests and enable coverage assertions, since we expect
|
||||||
|
# complete test coverage.
|
||||||
|
ifneq ($(TESTS),) |
||||||
|
TEST_ARGS := -x -k $(TESTS)
|
||||||
|
COV_ARGS :=
|
||||||
|
else |
||||||
|
TEST_ARGS := -n auto
|
||||||
|
COV_ARGS := # --fail-under 100
|
||||||
|
endif |
||||||
|
|
||||||
|
.PHONY: all |
||||||
|
all: |
||||||
|
@echo "Run my targets individually!"
|
||||||
|
|
||||||
|
.PHONY: dev |
||||||
|
dev: $(VENV)/pyvenv.cfg |
||||||
|
|
||||||
|
.PHONY: run |
||||||
|
run: $(VENV)/pyvenv.cfg |
||||||
|
@. $(VENV_BIN)/activate && slither $(ARGS)
|
||||||
|
|
||||||
|
$(VENV)/pyvenv.cfg: pyproject.toml |
||||||
|
# Create our Python 3 virtual environment
|
||||||
|
python3 -m venv env
|
||||||
|
$(VENV_BIN)/python -m pip install --upgrade pip
|
||||||
|
$(VENV_BIN)/python -m pip install -e .[$(SLITHER_EXTRA)]
|
||||||
|
|
||||||
|
.PHONY: lint |
||||||
|
lint: $(VENV)/pyvenv.cfg |
||||||
|
. $(VENV_BIN)/activate && \
|
||||||
|
black --check . && \
|
||||||
|
pylint $(PY_MODULE) $(TEST_MODULE)
|
||||||
|
# ruff $(ALL_PY_SRCS) && \
|
||||||
|
# mypy $(PY_MODULE) &&
|
||||||
|
|
||||||
|
.PHONY: reformat |
||||||
|
reformat: |
||||||
|
. $(VENV_BIN)/activate && \
|
||||||
|
black .
|
||||||
|
|
||||||
|
.PHONY: test tests |
||||||
|
test tests: $(VENV)/pyvenv.cfg |
||||||
|
. $(VENV_BIN)/activate && \
|
||||||
|
pytest --cov=$(PY_MODULE) $(T) $(TEST_ARGS) && \
|
||||||
|
python -m coverage report -m $(COV_ARGS)
|
||||||
|
|
||||||
|
.PHONY: doc |
||||||
|
doc: $(VENV)/pyvenv.cfg |
||||||
|
. $(VENV_BIN)/activate && \
|
||||||
|
PDOC_ALLOW_EXEC=1 pdoc -o html slither '!slither.tools'
|
||||||
|
|
||||||
|
.PHONY: package |
||||||
|
package: $(VENV)/pyvenv.cfg |
||||||
|
. $(VENV_BIN)/activate && \
|
||||||
|
python3 -m build
|
||||||
|
|
||||||
|
.PHONY: edit |
||||||
|
edit: |
||||||
|
$(EDITOR) $(ALL_PY_SRCS)
|
@ -1,3 +1,9 @@ |
|||||||
contract A{ |
pragma solidity 0.8.19; |
||||||
|
|
||||||
} |
error RevertIt(); |
||||||
|
|
||||||
|
contract Example { |
||||||
|
function reverts() external pure { |
||||||
|
revert RevertIt(); |
||||||
|
} |
||||||
|
} |
@ -1,5 +1,16 @@ |
|||||||
import "./a.sol"; |
import "./a.sol"; |
||||||
|
|
||||||
contract B is A{ |
pragma solidity 0.8.19; |
||||||
|
|
||||||
|
enum B { |
||||||
|
a, |
||||||
|
b |
||||||
} |
} |
||||||
|
|
||||||
|
contract T { |
||||||
|
Example e = new Example(); |
||||||
|
function b() public returns(uint) { |
||||||
|
B b = B.a; |
||||||
|
return 4; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,95 @@ |
|||||||
|
#!/usr/bin/env bash |
||||||
|
|
||||||
|
### Test slither-interface |
||||||
|
|
||||||
|
DIR_TESTS="tests/tools/interface" |
||||||
|
|
||||||
|
solc-select use 0.8.19 --always-install |
||||||
|
|
||||||
|
#Test 1 - Etherscan target |
||||||
|
slither-interface WETH9 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 |
||||||
|
DIFF=$(diff crytic-export/interfaces/IWETH9.sol "$DIR_TESTS/test_1.sol" --strip-trailing-cr) |
||||||
|
if [ "$DIFF" != "" ] |
||||||
|
then |
||||||
|
echo "slither-interface test 1 failed" |
||||||
|
cat "crytic-export/interfaces/IWETH9.sol" |
||||||
|
echo "" |
||||||
|
cat "$DIR_TESTS/test_1.sol" |
||||||
|
exit 255 |
||||||
|
fi |
||||||
|
|
||||||
|
|
||||||
|
#Test 2 - Local file target |
||||||
|
slither-interface Mock tests/tools/interface/ContractMock.sol |
||||||
|
DIFF=$(diff crytic-export/interfaces/IMock.sol "$DIR_TESTS/test_2.sol" --strip-trailing-cr) |
||||||
|
if [ "$DIFF" != "" ] |
||||||
|
then |
||||||
|
echo "slither-interface test 2 failed" |
||||||
|
cat "crytic-export/interfaces/IMock.sol" |
||||||
|
echo "" |
||||||
|
cat "$DIR_TESTS/test_2.sol" |
||||||
|
exit 255 |
||||||
|
fi |
||||||
|
|
||||||
|
|
||||||
|
#Test 3 - unroll structs |
||||||
|
slither-interface Mock tests/tools/interface/ContractMock.sol --unroll-structs |
||||||
|
DIFF=$(diff crytic-export/interfaces/IMock.sol "$DIR_TESTS/test_3.sol" --strip-trailing-cr) |
||||||
|
if [ "$DIFF" != "" ] |
||||||
|
then |
||||||
|
echo "slither-interface test 3 failed" |
||||||
|
cat "crytic-export/interfaces/IMock.sol" |
||||||
|
echo "" |
||||||
|
cat "$DIR_TESTS/test_3.sol" |
||||||
|
exit 255 |
||||||
|
fi |
||||||
|
|
||||||
|
#Test 4 - exclude structs |
||||||
|
slither-interface Mock tests/tools/interface/ContractMock.sol --exclude-structs |
||||||
|
DIFF=$(diff crytic-export/interfaces/IMock.sol "$DIR_TESTS/test_4.sol" --strip-trailing-cr) |
||||||
|
if [ "$DIFF" != "" ] |
||||||
|
then |
||||||
|
echo "slither-interface test 4 failed" |
||||||
|
cat "crytic-export/interfaces/IMock.sol" |
||||||
|
echo "" |
||||||
|
cat "$DIR_TESTS/test_4.sol" |
||||||
|
exit 255 |
||||||
|
fi |
||||||
|
|
||||||
|
#Test 5 - exclude errors |
||||||
|
slither-interface Mock tests/tools/interface/ContractMock.sol --exclude-errors |
||||||
|
DIFF=$(diff crytic-export/interfaces/IMock.sol "$DIR_TESTS/test_5.sol" --strip-trailing-cr) |
||||||
|
if [ "$DIFF" != "" ] |
||||||
|
then |
||||||
|
echo "slither-interface test 5 failed" |
||||||
|
cat "crytic-export/interfaces/IMock.sol" |
||||||
|
echo "" |
||||||
|
cat "$DIR_TESTS/test_5.sol" |
||||||
|
exit 255 |
||||||
|
fi |
||||||
|
|
||||||
|
#Test 6 - exclude enums |
||||||
|
slither-interface Mock tests/tools/interface/ContractMock.sol --exclude-enums |
||||||
|
DIFF=$(diff crytic-export/interfaces/IMock.sol "$DIR_TESTS/test_6.sol" --strip-trailing-cr) |
||||||
|
if [ "$DIFF" != "" ] |
||||||
|
then |
||||||
|
echo "slither-interface test 6 failed" |
||||||
|
cat "crytic-export/interfaces/IMock.sol" |
||||||
|
echo "" |
||||||
|
cat "$DIR_TESTS/test_6.sol" |
||||||
|
exit 255 |
||||||
|
fi |
||||||
|
|
||||||
|
#Test 7 - exclude events |
||||||
|
slither-interface Mock tests/tools/interface/ContractMock.sol --exclude-events |
||||||
|
DIFF=$(diff crytic-export/interfaces/IMock.sol "$DIR_TESTS/test_7.sol" --strip-trailing-cr) |
||||||
|
if [ "$DIFF" != "" ] |
||||||
|
then |
||||||
|
echo "slither-interface test 7 failed" |
||||||
|
cat "crytic-export/interfaces/IMock.sol" |
||||||
|
echo "" |
||||||
|
cat "$DIR_TESTS/test_7.sol" |
||||||
|
exit 255 |
||||||
|
fi |
||||||
|
|
||||||
|
rm -r crytic-export |
@ -1 +1,4 @@ |
|||||||
|
""" |
||||||
|
.. include:: ../README.md |
||||||
|
""" |
||||||
from .slither import Slither |
from .slither import Slither |
||||||
|
@ -0,0 +1,104 @@ |
|||||||
|
""" |
||||||
|
Module detecting usage of more than one dynamic type in abi.encodePacked() arguments which could lead to collision |
||||||
|
""" |
||||||
|
|
||||||
|
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification |
||||||
|
from slither.core.declarations.solidity_variables import SolidityFunction |
||||||
|
from slither.slithir.operations import SolidityCall |
||||||
|
from slither.analyses.data_dependency.data_dependency import is_tainted |
||||||
|
from slither.core.solidity_types import ElementaryType |
||||||
|
from slither.core.solidity_types import ArrayType |
||||||
|
|
||||||
|
|
||||||
|
def _is_dynamic_type(arg): |
||||||
|
""" |
||||||
|
Args: |
||||||
|
arg (function argument) |
||||||
|
Returns: |
||||||
|
Bool |
||||||
|
""" |
||||||
|
if isinstance(arg.type, ElementaryType) and (arg.type.name in ["string", "bytes"]): |
||||||
|
return True |
||||||
|
if isinstance(arg.type, ArrayType) and arg.type.length is None: |
||||||
|
return True |
||||||
|
|
||||||
|
return False |
||||||
|
|
||||||
|
|
||||||
|
def _detect_abi_encodePacked_collision(contract): |
||||||
|
""" |
||||||
|
Args: |
||||||
|
contract (Contract) |
||||||
|
Returns: |
||||||
|
list((Function), (list (Node))) |
||||||
|
""" |
||||||
|
ret = [] |
||||||
|
# pylint: disable=too-many-nested-blocks |
||||||
|
for f in contract.functions_and_modifiers_declared: |
||||||
|
for n in f.nodes: |
||||||
|
for ir in n.irs: |
||||||
|
if isinstance(ir, SolidityCall) and ir.function == SolidityFunction( |
||||||
|
"abi.encodePacked()" |
||||||
|
): |
||||||
|
dynamic_type_count = 0 |
||||||
|
for arg in ir.arguments: |
||||||
|
if is_tainted(arg, contract) and _is_dynamic_type(arg): |
||||||
|
dynamic_type_count += 1 |
||||||
|
elif dynamic_type_count > 1: |
||||||
|
ret.append((f, n)) |
||||||
|
dynamic_type_count = 0 |
||||||
|
else: |
||||||
|
dynamic_type_count = 0 |
||||||
|
if dynamic_type_count > 1: |
||||||
|
ret.append((f, n)) |
||||||
|
return ret |
||||||
|
|
||||||
|
|
||||||
|
class EncodePackedCollision(AbstractDetector): |
||||||
|
""" |
||||||
|
Detect usage of more than one dynamic type in abi.encodePacked() arguments which could to collision |
||||||
|
""" |
||||||
|
|
||||||
|
ARGUMENT = "encode-packed-collision" |
||||||
|
HELP = "ABI encodePacked Collision" |
||||||
|
IMPACT = DetectorClassification.HIGH |
||||||
|
CONFIDENCE = DetectorClassification.HIGH |
||||||
|
|
||||||
|
WIKI = ( |
||||||
|
"https://github.com/crytic/slither/wiki/Detector-Documentation#abi-encodePacked-collision" |
||||||
|
) |
||||||
|
|
||||||
|
WIKI_TITLE = "ABI encodePacked Collision" |
||||||
|
WIKI_DESCRIPTION = """Detect collision due to dynamic type usages in `abi.encodePacked`""" |
||||||
|
|
||||||
|
WIKI_EXPLOIT_SCENARIO = """ |
||||||
|
```solidity |
||||||
|
contract Sign { |
||||||
|
function get_hash_for_signature(string name, string doc) external returns(bytes32) { |
||||||
|
return keccak256(abi.encodePacked(name, doc)); |
||||||
|
} |
||||||
|
} |
||||||
|
``` |
||||||
|
Bob calls `get_hash_for_signature` with (`bob`, `This is the content`). The hash returned is used as an ID. |
||||||
|
Eve creates a collision with the ID using (`bo`, `bThis is the content`) and compromises the system. |
||||||
|
""" |
||||||
|
WIKI_RECOMMENDATION = """Do not use more than one dynamic type in `abi.encodePacked()` |
||||||
|
(see the [Solidity documentation](https://solidity.readthedocs.io/en/v0.5.10/abi-spec.html?highlight=abi.encodePacked#non-standard-packed-modeDynamic)). |
||||||
|
Use `abi.encode()`, preferably.""" |
||||||
|
|
||||||
|
def _detect(self): |
||||||
|
"""Detect usage of more than one dynamic type in abi.encodePacked(..) arguments which could lead to collision""" |
||||||
|
results = [] |
||||||
|
for c in self.compilation_unit.contracts: |
||||||
|
values = _detect_abi_encodePacked_collision(c) |
||||||
|
for func, node in values: |
||||||
|
info = [ |
||||||
|
func, |
||||||
|
" calls abi.encodePacked() with multiple dynamic arguments:\n\t- ", |
||||||
|
node, |
||||||
|
"\n", |
||||||
|
] |
||||||
|
json = self.generate_result(info) |
||||||
|
results.append(json) |
||||||
|
|
||||||
|
return results |
@ -0,0 +1,223 @@ |
|||||||
|
from typing import List |
||||||
|
|
||||||
|
from slither.core.declarations import Contract, Structure, Enum |
||||||
|
from slither.core.declarations.using_for_top_level import UsingForTopLevel |
||||||
|
from slither.core.solidity_types import ( |
||||||
|
UserDefinedType, |
||||||
|
Type, |
||||||
|
ElementaryType, |
||||||
|
TypeAlias, |
||||||
|
MappingType, |
||||||
|
ArrayType, |
||||||
|
) |
||||||
|
from slither.core.solidity_types.elementary_type import Uint, Int, Byte |
||||||
|
from slither.detectors.abstract_detector import ( |
||||||
|
AbstractDetector, |
||||||
|
DetectorClassification, |
||||||
|
DETECTOR_INFO, |
||||||
|
) |
||||||
|
from slither.utils.output import Output |
||||||
|
|
||||||
|
|
||||||
|
def _is_correctly_used(type_: Type, library: Contract) -> bool: |
||||||
|
""" |
||||||
|
Checks if a `using library for type_` statement is used correctly (that is, does library contain any function |
||||||
|
with type_ as the first argument). |
||||||
|
""" |
||||||
|
for f in library.functions: |
||||||
|
if len(f.parameters) == 0: |
||||||
|
continue |
||||||
|
if f.parameters[0].type and not _implicitly_convertible_to(type_, f.parameters[0].type): |
||||||
|
continue |
||||||
|
return True |
||||||
|
return False |
||||||
|
|
||||||
|
|
||||||
|
def _implicitly_convertible_to(type1: Type, type2: Type) -> bool: |
||||||
|
""" |
||||||
|
Returns True if type1 may be implicitly converted to type2. |
||||||
|
""" |
||||||
|
if isinstance(type1, TypeAlias) or isinstance(type2, TypeAlias): |
||||||
|
if isinstance(type1, TypeAlias) and isinstance(type2, TypeAlias): |
||||||
|
return type1.type == type2.type |
||||||
|
return False |
||||||
|
|
||||||
|
if isinstance(type1, UserDefinedType) and isinstance(type2, UserDefinedType): |
||||||
|
if isinstance(type1.type, Contract) and isinstance(type2.type, Contract): |
||||||
|
return _implicitly_convertible_to_for_contracts(type1.type, type2.type) |
||||||
|
|
||||||
|
if isinstance(type1.type, Structure) and isinstance(type2.type, Structure): |
||||||
|
return type1.type.canonical_name == type2.type.canonical_name |
||||||
|
|
||||||
|
if isinstance(type1.type, Enum) and isinstance(type2.type, Enum): |
||||||
|
return type1.type.canonical_name == type2.type.canonical_name |
||||||
|
|
||||||
|
if isinstance(type1, ElementaryType) and isinstance(type2, ElementaryType): |
||||||
|
return _implicitly_convertible_to_for_elementary_types(type1, type2) |
||||||
|
|
||||||
|
if isinstance(type1, MappingType) and isinstance(type2, MappingType): |
||||||
|
return _implicitly_convertible_to_for_mappings(type1, type2) |
||||||
|
|
||||||
|
if isinstance(type1, ArrayType) and isinstance(type2, ArrayType): |
||||||
|
return _implicitly_convertible_to_for_arrays(type1, type2) |
||||||
|
|
||||||
|
return False |
||||||
|
|
||||||
|
|
||||||
|
def _implicitly_convertible_to_for_arrays(type1: ArrayType, type2: ArrayType) -> bool: |
||||||
|
""" |
||||||
|
Returns True if type1 may be implicitly converted to type2. |
||||||
|
""" |
||||||
|
return _implicitly_convertible_to(type1.type, type2.type) |
||||||
|
|
||||||
|
|
||||||
|
def _implicitly_convertible_to_for_mappings(type1: MappingType, type2: MappingType) -> bool: |
||||||
|
""" |
||||||
|
Returns True if type1 may be implicitly converted to type2. |
||||||
|
""" |
||||||
|
return type1.type_from == type2.type_from and type1.type_to == type2.type_to |
||||||
|
|
||||||
|
|
||||||
|
def _implicitly_convertible_to_for_elementary_types( |
||||||
|
type1: ElementaryType, type2: ElementaryType |
||||||
|
) -> bool: |
||||||
|
""" |
||||||
|
Returns True if type1 may be implicitly converted to type2. |
||||||
|
""" |
||||||
|
if type1.type == "bool" and type2.type == "bool": |
||||||
|
return True |
||||||
|
if type1.type == "string" and type2.type == "string": |
||||||
|
return True |
||||||
|
if type1.type == "bytes" and type2.type == "bytes": |
||||||
|
return True |
||||||
|
if type1.type == "address" and type2.type == "address": |
||||||
|
return _implicitly_convertible_to_for_addresses(type1, type2) |
||||||
|
if type1.type in Uint and type2.type in Uint: |
||||||
|
return _implicitly_convertible_to_for_uints(type1, type2) |
||||||
|
if type1.type in Int and type2.type in Int: |
||||||
|
return _implicitly_convertible_to_for_ints(type1, type2) |
||||||
|
if ( |
||||||
|
type1.type != "bytes" |
||||||
|
and type2.type != "bytes" |
||||||
|
and type1.type in Byte |
||||||
|
and type2.type in Byte |
||||||
|
): |
||||||
|
return _implicitly_convertible_to_for_bytes(type1, type2) |
||||||
|
return False |
||||||
|
|
||||||
|
|
||||||
|
def _implicitly_convertible_to_for_bytes(type1: ElementaryType, type2: ElementaryType) -> bool: |
||||||
|
""" |
||||||
|
Returns True if type1 may be implicitly converted to type2 assuming they are both bytes. |
||||||
|
""" |
||||||
|
assert type1.type in Byte and type2.type in Byte |
||||||
|
assert type1.size is not None |
||||||
|
assert type2.size is not None |
||||||
|
|
||||||
|
return type1.size <= type2.size |
||||||
|
|
||||||
|
|
||||||
|
def _implicitly_convertible_to_for_addresses(type1: ElementaryType, type2: ElementaryType) -> bool: |
||||||
|
""" |
||||||
|
Returns True if type1 may be implicitly converted to type2 assuming they are both addresses. |
||||||
|
""" |
||||||
|
assert type1.type == "address" and type2.type == "address" |
||||||
|
# payable attribute to be implemented; for now, always return True |
||||||
|
return True |
||||||
|
|
||||||
|
|
||||||
|
def _implicitly_convertible_to_for_ints(type1: ElementaryType, type2: ElementaryType) -> bool: |
||||||
|
""" |
||||||
|
Returns True if type1 may be implicitly converted to type2 assuming they are both ints. |
||||||
|
""" |
||||||
|
assert type1.type in Int and type2.type in Int |
||||||
|
assert type1.size is not None |
||||||
|
assert type2.size is not None |
||||||
|
|
||||||
|
return type1.size <= type2.size |
||||||
|
|
||||||
|
|
||||||
|
def _implicitly_convertible_to_for_uints(type1: ElementaryType, type2: ElementaryType) -> bool: |
||||||
|
""" |
||||||
|
Returns True if type1 may be implicitly converted to type2 assuming they are both uints. |
||||||
|
""" |
||||||
|
assert type1.type in Uint and type2.type in Uint |
||||||
|
assert type1.size is not None |
||||||
|
assert type2.size is not None |
||||||
|
|
||||||
|
return type1.size <= type2.size |
||||||
|
|
||||||
|
|
||||||
|
def _implicitly_convertible_to_for_contracts(contract1: Contract, contract2: Contract) -> bool: |
||||||
|
""" |
||||||
|
Returns True if contract1 may be implicitly converted to contract2. |
||||||
|
""" |
||||||
|
return contract1 == contract2 or contract2 in contract1.inheritance |
||||||
|
|
||||||
|
|
||||||
|
class IncorrectUsingFor(AbstractDetector): |
||||||
|
""" |
||||||
|
Detector for incorrect using-for statement usage. |
||||||
|
""" |
||||||
|
|
||||||
|
ARGUMENT = "incorrect-using-for" |
||||||
|
HELP = "Detects using-for statement usage when no function from a given library matches a given type" |
||||||
|
IMPACT = DetectorClassification.INFORMATIONAL |
||||||
|
CONFIDENCE = DetectorClassification.HIGH |
||||||
|
|
||||||
|
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-using-for-usage" |
||||||
|
|
||||||
|
WIKI_TITLE = "Incorrect usage of using-for statement" |
||||||
|
WIKI_DESCRIPTION = ( |
||||||
|
"In Solidity, it is possible to use libraries for certain types, by the `using-for` statement " |
||||||
|
"(`using <library> for <type>`). However, the Solidity compiler doesn't check whether a given " |
||||||
|
"library has at least one function matching a given type. If it doesn't, such a statement has " |
||||||
|
"no effect and may be confusing. " |
||||||
|
) |
||||||
|
|
||||||
|
# region wiki_exploit_scenario |
||||||
|
WIKI_EXPLOIT_SCENARIO = """ |
||||||
|
```solidity |
||||||
|
library L { |
||||||
|
function f(bool) public pure {} |
||||||
|
} |
||||||
|
|
||||||
|
using L for uint; |
||||||
|
``` |
||||||
|
Such a code will compile despite the fact that `L` has no function with `uint` as its first argument.""" |
||||||
|
# endregion wiki_exploit_scenario |
||||||
|
WIKI_RECOMMENDATION = ( |
||||||
|
"Make sure that the libraries used in `using-for` statements have at least one function " |
||||||
|
"matching a type used in these statements. " |
||||||
|
) |
||||||
|
|
||||||
|
def _append_result( |
||||||
|
self, results: List[Output], uf: UsingForTopLevel, type_: Type, library: Contract |
||||||
|
) -> None: |
||||||
|
info: DETECTOR_INFO = [ |
||||||
|
f"using-for statement at {uf.source_mapping} is incorrect - no matching function for {type_} found in ", |
||||||
|
library, |
||||||
|
".\n", |
||||||
|
] |
||||||
|
res = self.generate_result(info) |
||||||
|
results.append(res) |
||||||
|
|
||||||
|
def _detect(self) -> List[Output]: |
||||||
|
results: List[Output] = [] |
||||||
|
|
||||||
|
for uf in self.compilation_unit.using_for_top_level: |
||||||
|
# UsingForTopLevel.using_for is a dict with a single entry, which is mapped to a list of functions/libraries |
||||||
|
# the following code extracts the type from using-for and skips using-for statements with functions |
||||||
|
type_ = list(uf.using_for.keys())[0] |
||||||
|
for lib_or_fcn in uf.using_for[type_]: |
||||||
|
# checking for using-for with functions is already performed by the compiler; we only consider libraries |
||||||
|
if isinstance(lib_or_fcn, UserDefinedType): |
||||||
|
lib_or_fcn_type = lib_or_fcn.type |
||||||
|
if ( |
||||||
|
isinstance(type_, Type) |
||||||
|
and isinstance(lib_or_fcn_type, Contract) |
||||||
|
and not _is_correctly_used(type_, lib_or_fcn_type) |
||||||
|
): |
||||||
|
self._append_result(results, uf, type_, lib_or_fcn_type) |
||||||
|
|
||||||
|
return results |
@ -0,0 +1,105 @@ |
|||||||
|
import argparse |
||||||
|
import logging |
||||||
|
from pathlib import Path |
||||||
|
|
||||||
|
from crytic_compile import cryticparser |
||||||
|
|
||||||
|
from slither import Slither |
||||||
|
from slither.utils.code_generation import generate_interface |
||||||
|
|
||||||
|
logging.basicConfig() |
||||||
|
logger = logging.getLogger("Slither-Interface") |
||||||
|
logger.setLevel(logging.INFO) |
||||||
|
|
||||||
|
|
||||||
|
def parse_args() -> argparse.Namespace: |
||||||
|
""" |
||||||
|
Parse the underlying arguments for the program. |
||||||
|
:return: Returns the arguments for the program. |
||||||
|
""" |
||||||
|
parser = argparse.ArgumentParser( |
||||||
|
description="Generates code for a Solidity interface from contract", |
||||||
|
usage=("slither-interface <ContractName> <source file or deployment address>"), |
||||||
|
) |
||||||
|
|
||||||
|
parser.add_argument( |
||||||
|
"contract_source", |
||||||
|
help="The name of the contract (case sensitive) followed by the deployed contract address if verified on etherscan or project directory/filename for local contracts.", |
||||||
|
nargs="+", |
||||||
|
) |
||||||
|
|
||||||
|
parser.add_argument( |
||||||
|
"--unroll-structs", |
||||||
|
help="Whether to use structures' underlying types instead of the user-defined type", |
||||||
|
default=False, |
||||||
|
action="store_true", |
||||||
|
) |
||||||
|
|
||||||
|
parser.add_argument( |
||||||
|
"--exclude-events", |
||||||
|
help="Excludes event signatures in the interface", |
||||||
|
default=False, |
||||||
|
action="store_true", |
||||||
|
) |
||||||
|
|
||||||
|
parser.add_argument( |
||||||
|
"--exclude-errors", |
||||||
|
help="Excludes custom error signatures in the interface", |
||||||
|
default=False, |
||||||
|
action="store_true", |
||||||
|
) |
||||||
|
|
||||||
|
parser.add_argument( |
||||||
|
"--exclude-enums", |
||||||
|
help="Excludes enum definitions in the interface", |
||||||
|
default=False, |
||||||
|
action="store_true", |
||||||
|
) |
||||||
|
|
||||||
|
parser.add_argument( |
||||||
|
"--exclude-structs", |
||||||
|
help="Exclude struct definitions in the interface", |
||||||
|
default=False, |
||||||
|
action="store_true", |
||||||
|
) |
||||||
|
|
||||||
|
cryticparser.init(parser) |
||||||
|
|
||||||
|
return parser.parse_args() |
||||||
|
|
||||||
|
|
||||||
|
def main() -> None: |
||||||
|
args = parse_args() |
||||||
|
|
||||||
|
contract_name, target = args.contract_source |
||||||
|
slither = Slither(target, **vars(args)) |
||||||
|
|
||||||
|
_contract = slither.get_contract_from_name(contract_name)[0] |
||||||
|
|
||||||
|
interface = generate_interface( |
||||||
|
contract=_contract, |
||||||
|
unroll_structs=args.unroll_structs, |
||||||
|
include_events=not args.exclude_events, |
||||||
|
include_errors=not args.exclude_errors, |
||||||
|
include_enums=not args.exclude_enums, |
||||||
|
include_structs=not args.exclude_structs, |
||||||
|
) |
||||||
|
|
||||||
|
# add version pragma |
||||||
|
interface = ( |
||||||
|
f"pragma solidity {_contract.compilation_unit.pragma_directives[0].version};\n\n" |
||||||
|
+ interface |
||||||
|
) |
||||||
|
|
||||||
|
# write interface to file |
||||||
|
export = Path("crytic-export", "interfaces") |
||||||
|
export.mkdir(parents=True, exist_ok=True) |
||||||
|
filename = f"I{contract_name}.sol" |
||||||
|
path = Path(export, filename) |
||||||
|
logger.info(f" Interface exported to {path}") |
||||||
|
with open(path, "w", encoding="utf8") as f: |
||||||
|
f.write(interface) |
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__": |
||||||
|
main() |
@ -0,0 +1,79 @@ |
|||||||
|
# pylint: disable=redefined-outer-name |
||||||
|
import os |
||||||
|
from pathlib import Path |
||||||
|
import tempfile |
||||||
|
import shutil |
||||||
|
from contextlib import contextmanager |
||||||
|
import pytest |
||||||
|
from filelock import FileLock |
||||||
|
from solc_select import solc_select |
||||||
|
from slither import Slither |
||||||
|
|
||||||
|
|
||||||
|
def pytest_configure(config): |
||||||
|
"""Create a temporary directory for the tests to use.""" |
||||||
|
if is_master(): |
||||||
|
config.stash["shared_directory"] = tempfile.mkdtemp() |
||||||
|
|
||||||
|
|
||||||
|
def pytest_unconfigure(config): |
||||||
|
"""Remove the temporary directory after the tests are done.""" |
||||||
|
if is_master(): |
||||||
|
shutil.rmtree(config.stash["shared_directory"]) |
||||||
|
|
||||||
|
|
||||||
|
def pytest_configure_node(node): |
||||||
|
"""Configure each worker node with the shared directory.""" |
||||||
|
node.workerinput["shared_directory"] = node.config.stash["shared_directory"] |
||||||
|
|
||||||
|
|
||||||
|
def is_master(): |
||||||
|
"""Returns True if the current process is the master process (which does not have a worker id).""" |
||||||
|
return os.environ.get("PYTEST_XDIST_WORKER") is None |
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture |
||||||
|
def shared_directory(request): |
||||||
|
"""Returns the shared directory for the current process.""" |
||||||
|
if is_master(): |
||||||
|
return request.config.stash["shared_directory"] |
||||||
|
return request.config.workerinput["shared_directory"] |
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture |
||||||
|
def solc_binary_path(shared_directory): |
||||||
|
""" |
||||||
|
Returns the path to the solc binary for the given version. |
||||||
|
If the binary is not installed, it will be installed. |
||||||
|
""" |
||||||
|
|
||||||
|
def inner(version): |
||||||
|
lock = FileLock(f"{shared_directory}/{version}.lock", timeout=60) |
||||||
|
with lock: |
||||||
|
if not solc_select.artifact_path(version).exists(): |
||||||
|
print("Installing solc version", version) |
||||||
|
solc_select.install_artifacts([version]) |
||||||
|
return solc_select.artifact_path(version).as_posix() |
||||||
|
|
||||||
|
return inner |
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture |
||||||
|
def slither_from_source(solc_binary_path): |
||||||
|
@contextmanager |
||||||
|
def inner(source_code: str, solc_version: str = "0.8.19"): |
||||||
|
"""Yields a Slither instance using source_code string and solc_version. |
||||||
|
Creates a temporary file and compiles with solc_version. |
||||||
|
""" |
||||||
|
|
||||||
|
fname = "" |
||||||
|
try: |
||||||
|
with tempfile.NamedTemporaryFile(mode="w", suffix=".sol", delete=False) as f: |
||||||
|
fname = f.name |
||||||
|
f.write(source_code) |
||||||
|
solc_path = solc_binary_path(solc_version) |
||||||
|
yield Slither(fname, solc=solc_path) |
||||||
|
finally: |
||||||
|
Path(fname).unlink() |
||||||
|
|
||||||
|
return inner |
@ -0,0 +1,18 @@ |
|||||||
|
Function A.bad3() (tests/e2e/detectors/test_data/abiencoderv2-array/0.4.25/storage_ABIEncoderV2_array.sol#39-41) trigger an abi encoding bug: |
||||||
|
- b = abi.encode(s) (tests/e2e/detectors/test_data/abiencoderv2-array/0.4.25/storage_ABIEncoderV2_array.sol#40) |
||||||
|
|
||||||
|
Function A.bad0() (tests/e2e/detectors/test_data/abiencoderv2-array/0.4.25/storage_ABIEncoderV2_array.sol#21-23) trigger an abi encoding bug: |
||||||
|
- this.bad0_external(bad_arr) (tests/e2e/detectors/test_data/abiencoderv2-array/0.4.25/storage_ABIEncoderV2_array.sol#22) |
||||||
|
|
||||||
|
Function A.bad4() (tests/e2e/detectors/test_data/abiencoderv2-array/0.4.25/storage_ABIEncoderV2_array.sol#44-46) trigger an abi encoding bug: |
||||||
|
- event1_bad(bad_arr) (tests/e2e/detectors/test_data/abiencoderv2-array/0.4.25/storage_ABIEncoderV2_array.sol#45) |
||||||
|
|
||||||
|
Function A.bad2() (tests/e2e/detectors/test_data/abiencoderv2-array/0.4.25/storage_ABIEncoderV2_array.sol#34-36) trigger an abi encoding bug: |
||||||
|
- b = abi.encode(bad_arr) (tests/e2e/detectors/test_data/abiencoderv2-array/0.4.25/storage_ABIEncoderV2_array.sol#35) |
||||||
|
|
||||||
|
Function A.bad1(A.S[3]) (tests/e2e/detectors/test_data/abiencoderv2-array/0.4.25/storage_ABIEncoderV2_array.sol#29-31) trigger an abi encoding bug: |
||||||
|
- this.bad1_external(s) (tests/e2e/detectors/test_data/abiencoderv2-array/0.4.25/storage_ABIEncoderV2_array.sol#30) |
||||||
|
|
||||||
|
Function A.bad5() (tests/e2e/detectors/test_data/abiencoderv2-array/0.4.25/storage_ABIEncoderV2_array.sol#49-51) trigger an abi encoding bug: |
||||||
|
- event2_bad(s) (tests/e2e/detectors/test_data/abiencoderv2-array/0.4.25/storage_ABIEncoderV2_array.sol#50) |
||||||
|
|
@ -0,0 +1,18 @@ |
|||||||
|
Function A.bad5() (tests/e2e/detectors/test_data/abiencoderv2-array/0.5.9/storage_ABIEncoderV2_array.sol#49-51) trigger an abi encoding bug: |
||||||
|
- event2_bad(s) (tests/e2e/detectors/test_data/abiencoderv2-array/0.5.9/storage_ABIEncoderV2_array.sol#50) |
||||||
|
|
||||||
|
Function A.bad0() (tests/e2e/detectors/test_data/abiencoderv2-array/0.5.9/storage_ABIEncoderV2_array.sol#21-23) trigger an abi encoding bug: |
||||||
|
- this.bad0_external(bad_arr) (tests/e2e/detectors/test_data/abiencoderv2-array/0.5.9/storage_ABIEncoderV2_array.sol#22) |
||||||
|
|
||||||
|
Function A.bad4() (tests/e2e/detectors/test_data/abiencoderv2-array/0.5.9/storage_ABIEncoderV2_array.sol#44-46) trigger an abi encoding bug: |
||||||
|
- event1_bad(bad_arr) (tests/e2e/detectors/test_data/abiencoderv2-array/0.5.9/storage_ABIEncoderV2_array.sol#45) |
||||||
|
|
||||||
|
Function A.bad2() (tests/e2e/detectors/test_data/abiencoderv2-array/0.5.9/storage_ABIEncoderV2_array.sol#34-36) trigger an abi encoding bug: |
||||||
|
- b = abi.encode(bad_arr) (tests/e2e/detectors/test_data/abiencoderv2-array/0.5.9/storage_ABIEncoderV2_array.sol#35) |
||||||
|
|
||||||
|
Function A.bad1(A.S[3]) (tests/e2e/detectors/test_data/abiencoderv2-array/0.5.9/storage_ABIEncoderV2_array.sol#29-31) trigger an abi encoding bug: |
||||||
|
- this.bad1_external(s) (tests/e2e/detectors/test_data/abiencoderv2-array/0.5.9/storage_ABIEncoderV2_array.sol#30) |
||||||
|
|
||||||
|
Function A.bad3() (tests/e2e/detectors/test_data/abiencoderv2-array/0.5.9/storage_ABIEncoderV2_array.sol#39-41) trigger an abi encoding bug: |
||||||
|
- b = abi.encode(s) (tests/e2e/detectors/test_data/abiencoderv2-array/0.5.9/storage_ABIEncoderV2_array.sol#40) |
||||||
|
|
@ -0,0 +1,6 @@ |
|||||||
|
C.bad4(address,address,uint256) (tests/e2e/detectors/test_data/arbitrary-send-erc20/0.4.25/arbitrary_send_erc20.sol#65-67) uses arbitrary from in transferFrom: SafeERC20.safeTransferFrom(erc20,from,to,amount) (tests/e2e/detectors/test_data/arbitrary-send-erc20/0.4.25/arbitrary_send_erc20.sol#66) |
||||||
|
|
||||||
|
C.bad1(address,uint256) (tests/e2e/detectors/test_data/arbitrary-send-erc20/0.4.25/arbitrary_send_erc20.sol#35-37) uses arbitrary from in transferFrom: erc20.transferFrom(notsend,to,am) (tests/e2e/detectors/test_data/arbitrary-send-erc20/0.4.25/arbitrary_send_erc20.sol#36) |
||||||
|
|
||||||
|
C.bad3(address,address,uint256) (tests/e2e/detectors/test_data/arbitrary-send-erc20/0.4.25/arbitrary_send_erc20.sol#57-59) uses arbitrary from in transferFrom: erc20.safeTransferFrom(from,to,amount) (tests/e2e/detectors/test_data/arbitrary-send-erc20/0.4.25/arbitrary_send_erc20.sol#58) |
||||||
|
|
@ -0,0 +1,6 @@ |
|||||||
|
C.bad4(address,address,uint256) (tests/e2e/detectors/test_data/arbitrary-send-erc20/0.5.16/arbitrary_send_erc20.sol#65-67) uses arbitrary from in transferFrom: SafeERC20.safeTransferFrom(erc20,from,to,amount) (tests/e2e/detectors/test_data/arbitrary-send-erc20/0.5.16/arbitrary_send_erc20.sol#66) |
||||||
|
|
||||||
|
C.bad3(address,address,uint256) (tests/e2e/detectors/test_data/arbitrary-send-erc20/0.5.16/arbitrary_send_erc20.sol#57-59) uses arbitrary from in transferFrom: erc20.safeTransferFrom(from,to,amount) (tests/e2e/detectors/test_data/arbitrary-send-erc20/0.5.16/arbitrary_send_erc20.sol#58) |
||||||
|
|
||||||
|
C.bad1(address,uint256) (tests/e2e/detectors/test_data/arbitrary-send-erc20/0.5.16/arbitrary_send_erc20.sol#35-37) uses arbitrary from in transferFrom: erc20.transferFrom(notsend,to,am) (tests/e2e/detectors/test_data/arbitrary-send-erc20/0.5.16/arbitrary_send_erc20.sol#36) |
||||||
|
|
@ -0,0 +1,6 @@ |
|||||||
|
C.bad1(address,uint256) (tests/e2e/detectors/test_data/arbitrary-send-erc20/0.6.11/arbitrary_send_erc20.sol#35-37) uses arbitrary from in transferFrom: erc20.transferFrom(notsend,to,am) (tests/e2e/detectors/test_data/arbitrary-send-erc20/0.6.11/arbitrary_send_erc20.sol#36) |
||||||
|
|
||||||
|
C.bad3(address,address,uint256) (tests/e2e/detectors/test_data/arbitrary-send-erc20/0.6.11/arbitrary_send_erc20.sol#57-59) uses arbitrary from in transferFrom: erc20.safeTransferFrom(from,to,amount) (tests/e2e/detectors/test_data/arbitrary-send-erc20/0.6.11/arbitrary_send_erc20.sol#58) |
||||||
|
|
||||||
|
C.bad4(address,address,uint256) (tests/e2e/detectors/test_data/arbitrary-send-erc20/0.6.11/arbitrary_send_erc20.sol#65-67) uses arbitrary from in transferFrom: SafeERC20.safeTransferFrom(erc20,from,to,amount) (tests/e2e/detectors/test_data/arbitrary-send-erc20/0.6.11/arbitrary_send_erc20.sol#66) |
||||||
|
|
@ -0,0 +1,6 @@ |
|||||||
|
C.bad4(address,address,uint256) (tests/e2e/detectors/test_data/arbitrary-send-erc20/0.7.6/arbitrary_send_erc20.sol#65-67) uses arbitrary from in transferFrom: SafeERC20.safeTransferFrom(erc20,from,to,amount) (tests/e2e/detectors/test_data/arbitrary-send-erc20/0.7.6/arbitrary_send_erc20.sol#66) |
||||||
|
|
||||||
|
C.bad3(address,address,uint256) (tests/e2e/detectors/test_data/arbitrary-send-erc20/0.7.6/arbitrary_send_erc20.sol#57-59) uses arbitrary from in transferFrom: erc20.safeTransferFrom(from,to,amount) (tests/e2e/detectors/test_data/arbitrary-send-erc20/0.7.6/arbitrary_send_erc20.sol#58) |
||||||
|
|
||||||
|
C.bad1(address,uint256) (tests/e2e/detectors/test_data/arbitrary-send-erc20/0.7.6/arbitrary_send_erc20.sol#35-37) uses arbitrary from in transferFrom: erc20.transferFrom(notsend,to,am) (tests/e2e/detectors/test_data/arbitrary-send-erc20/0.7.6/arbitrary_send_erc20.sol#36) |
||||||
|
|
@ -0,0 +1,2 @@ |
|||||||
|
T.bad(address) (tests/e2e/detectors/test_data/arbitrary-send-erc20/0.8.0/arbitrary_send_erc20_inheritance.sol#11-13) uses arbitrary from in transferFrom: erc20.safeTransferFrom(from,address(0x1),90) (tests/e2e/detectors/test_data/arbitrary-send-erc20/0.8.0/arbitrary_send_erc20_inheritance.sol#12) |
||||||
|
|
@ -0,0 +1,6 @@ |
|||||||
|
C.bad1(address,uint256) (tests/e2e/detectors/test_data/arbitrary-send-erc20/0.8.0/arbitrary_send_erc20.sol#35-37) uses arbitrary from in transferFrom: erc20.transferFrom(notsend,to,am) (tests/e2e/detectors/test_data/arbitrary-send-erc20/0.8.0/arbitrary_send_erc20.sol#36) |
||||||
|
|
||||||
|
C.bad3(address,address,uint256) (tests/e2e/detectors/test_data/arbitrary-send-erc20/0.8.0/arbitrary_send_erc20.sol#57-59) uses arbitrary from in transferFrom: erc20.safeTransferFrom(from,to,amount) (tests/e2e/detectors/test_data/arbitrary-send-erc20/0.8.0/arbitrary_send_erc20.sol#58) |
||||||
|
|
||||||
|
C.bad4(address,address,uint256) (tests/e2e/detectors/test_data/arbitrary-send-erc20/0.8.0/arbitrary_send_erc20.sol#65-67) uses arbitrary from in transferFrom: SafeERC20.safeTransferFrom(erc20,from,to,amount) (tests/e2e/detectors/test_data/arbitrary-send-erc20/0.8.0/arbitrary_send_erc20.sol#66) |
||||||
|
|
@ -0,0 +1,8 @@ |
|||||||
|
C.int_transferFrom(address,uint256,uint256,uint8,bytes32,bytes32,address) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.4.25/arbitrary_send_erc20_permit.sol#42-45) uses arbitrary from in transferFrom in combination with permit: erc20.transferFrom(from,to,value) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.4.25/arbitrary_send_erc20_permit.sol#44) |
||||||
|
|
||||||
|
C.bad3(address,uint256,uint256,uint8,bytes32,bytes32,address) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.4.25/arbitrary_send_erc20_permit.sol#47-50) uses arbitrary from in transferFrom in combination with permit: erc20.safeTransferFrom(from,to,value) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.4.25/arbitrary_send_erc20_permit.sol#49) |
||||||
|
|
||||||
|
C.bad4(address,uint256,uint256,uint8,bytes32,bytes32,address) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.4.25/arbitrary_send_erc20_permit.sol#52-55) uses arbitrary from in transferFrom in combination with permit: SafeERC20.safeTransferFrom(erc20,from,to,value) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.4.25/arbitrary_send_erc20_permit.sol#54) |
||||||
|
|
||||||
|
C.bad1(address,uint256,uint256,uint8,bytes32,bytes32,address) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.4.25/arbitrary_send_erc20_permit.sol#32-35) uses arbitrary from in transferFrom in combination with permit: erc20.transferFrom(from,to,value) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.4.25/arbitrary_send_erc20_permit.sol#34) |
||||||
|
|
@ -0,0 +1,8 @@ |
|||||||
|
C.int_transferFrom(address,uint256,uint256,uint8,bytes32,bytes32,address) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.5.16/arbitrary_send_erc20_permit.sol#42-45) uses arbitrary from in transferFrom in combination with permit: erc20.transferFrom(from,to,value) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.5.16/arbitrary_send_erc20_permit.sol#44) |
||||||
|
|
||||||
|
C.bad4(address,uint256,uint256,uint8,bytes32,bytes32,address) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.5.16/arbitrary_send_erc20_permit.sol#52-55) uses arbitrary from in transferFrom in combination with permit: SafeERC20.safeTransferFrom(erc20,from,to,value) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.5.16/arbitrary_send_erc20_permit.sol#54) |
||||||
|
|
||||||
|
C.bad3(address,uint256,uint256,uint8,bytes32,bytes32,address) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.5.16/arbitrary_send_erc20_permit.sol#47-50) uses arbitrary from in transferFrom in combination with permit: erc20.safeTransferFrom(from,to,value) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.5.16/arbitrary_send_erc20_permit.sol#49) |
||||||
|
|
||||||
|
C.bad1(address,uint256,uint256,uint8,bytes32,bytes32,address) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.5.16/arbitrary_send_erc20_permit.sol#32-35) uses arbitrary from in transferFrom in combination with permit: erc20.transferFrom(from,to,value) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.5.16/arbitrary_send_erc20_permit.sol#34) |
||||||
|
|
@ -0,0 +1,8 @@ |
|||||||
|
C.bad3(address,uint256,uint256,uint8,bytes32,bytes32,address) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.6.11/arbitrary_send_erc20_permit.sol#47-50) uses arbitrary from in transferFrom in combination with permit: erc20.safeTransferFrom(from,to,value) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.6.11/arbitrary_send_erc20_permit.sol#49) |
||||||
|
|
||||||
|
C.bad4(address,uint256,uint256,uint8,bytes32,bytes32,address) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.6.11/arbitrary_send_erc20_permit.sol#52-55) uses arbitrary from in transferFrom in combination with permit: SafeERC20.safeTransferFrom(erc20,from,to,value) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.6.11/arbitrary_send_erc20_permit.sol#54) |
||||||
|
|
||||||
|
C.int_transferFrom(address,uint256,uint256,uint8,bytes32,bytes32,address) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.6.11/arbitrary_send_erc20_permit.sol#42-45) uses arbitrary from in transferFrom in combination with permit: erc20.transferFrom(from,to,value) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.6.11/arbitrary_send_erc20_permit.sol#44) |
||||||
|
|
||||||
|
C.bad1(address,uint256,uint256,uint8,bytes32,bytes32,address) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.6.11/arbitrary_send_erc20_permit.sol#32-35) uses arbitrary from in transferFrom in combination with permit: erc20.transferFrom(from,to,value) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.6.11/arbitrary_send_erc20_permit.sol#34) |
||||||
|
|
@ -0,0 +1,8 @@ |
|||||||
|
C.int_transferFrom(address,uint256,uint256,uint8,bytes32,bytes32,address) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.7.6/arbitrary_send_erc20_permit.sol#42-45) uses arbitrary from in transferFrom in combination with permit: erc20.transferFrom(from,to,value) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.7.6/arbitrary_send_erc20_permit.sol#44) |
||||||
|
|
||||||
|
C.bad1(address,uint256,uint256,uint8,bytes32,bytes32,address) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.7.6/arbitrary_send_erc20_permit.sol#32-35) uses arbitrary from in transferFrom in combination with permit: erc20.transferFrom(from,to,value) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.7.6/arbitrary_send_erc20_permit.sol#34) |
||||||
|
|
||||||
|
C.bad4(address,uint256,uint256,uint8,bytes32,bytes32,address) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.7.6/arbitrary_send_erc20_permit.sol#52-55) uses arbitrary from in transferFrom in combination with permit: SafeERC20.safeTransferFrom(erc20,from,to,value) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.7.6/arbitrary_send_erc20_permit.sol#54) |
||||||
|
|
||||||
|
C.bad3(address,uint256,uint256,uint8,bytes32,bytes32,address) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.7.6/arbitrary_send_erc20_permit.sol#47-50) uses arbitrary from in transferFrom in combination with permit: erc20.safeTransferFrom(from,to,value) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.7.6/arbitrary_send_erc20_permit.sol#49) |
||||||
|
|
@ -0,0 +1,8 @@ |
|||||||
|
C.bad3(address,uint256,uint256,uint8,bytes32,bytes32,address) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.8.0/arbitrary_send_erc20_permit.sol#47-50) uses arbitrary from in transferFrom in combination with permit: erc20.safeTransferFrom(from,to,value) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.8.0/arbitrary_send_erc20_permit.sol#49) |
||||||
|
|
||||||
|
C.bad4(address,uint256,uint256,uint8,bytes32,bytes32,address) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.8.0/arbitrary_send_erc20_permit.sol#52-55) uses arbitrary from in transferFrom in combination with permit: SafeERC20.safeTransferFrom(erc20,from,to,value) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.8.0/arbitrary_send_erc20_permit.sol#54) |
||||||
|
|
||||||
|
C.int_transferFrom(address,uint256,uint256,uint8,bytes32,bytes32,address) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.8.0/arbitrary_send_erc20_permit.sol#42-45) uses arbitrary from in transferFrom in combination with permit: erc20.transferFrom(from,to,value) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.8.0/arbitrary_send_erc20_permit.sol#44) |
||||||
|
|
||||||
|
C.bad1(address,uint256,uint256,uint8,bytes32,bytes32,address) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.8.0/arbitrary_send_erc20_permit.sol#32-35) uses arbitrary from in transferFrom in combination with permit: erc20.transferFrom(from,to,value) (tests/e2e/detectors/test_data/arbitrary-send-erc20-permit/0.8.0/arbitrary_send_erc20_permit.sol#34) |
||||||
|
|
@ -0,0 +1,8 @@ |
|||||||
|
Test.indirect() (tests/e2e/detectors/test_data/arbitrary-send-eth/0.4.25/arbitrary_send_eth.sol#19-21) sends eth to arbitrary user |
||||||
|
Dangerous calls: |
||||||
|
- destination.send(address(this).balance) (tests/e2e/detectors/test_data/arbitrary-send-eth/0.4.25/arbitrary_send_eth.sol#20) |
||||||
|
|
||||||
|
Test.direct() (tests/e2e/detectors/test_data/arbitrary-send-eth/0.4.25/arbitrary_send_eth.sol#11-13) sends eth to arbitrary user |
||||||
|
Dangerous calls: |
||||||
|
- msg.sender.send(address(this).balance) (tests/e2e/detectors/test_data/arbitrary-send-eth/0.4.25/arbitrary_send_eth.sol#12) |
||||||
|
|
@ -0,0 +1,8 @@ |
|||||||
|
Test.direct() (tests/e2e/detectors/test_data/arbitrary-send-eth/0.5.16/arbitrary_send_eth.sol#11-13) sends eth to arbitrary user |
||||||
|
Dangerous calls: |
||||||
|
- msg.sender.send(address(this).balance) (tests/e2e/detectors/test_data/arbitrary-send-eth/0.5.16/arbitrary_send_eth.sol#12) |
||||||
|
|
||||||
|
Test.indirect() (tests/e2e/detectors/test_data/arbitrary-send-eth/0.5.16/arbitrary_send_eth.sol#19-21) sends eth to arbitrary user |
||||||
|
Dangerous calls: |
||||||
|
- destination.send(address(this).balance) (tests/e2e/detectors/test_data/arbitrary-send-eth/0.5.16/arbitrary_send_eth.sol#20) |
||||||
|
|
@ -0,0 +1,8 @@ |
|||||||
|
Test.indirect() (tests/e2e/detectors/test_data/arbitrary-send-eth/0.6.11/arbitrary_send_eth.sol#19-21) sends eth to arbitrary user |
||||||
|
Dangerous calls: |
||||||
|
- destination.send(address(this).balance) (tests/e2e/detectors/test_data/arbitrary-send-eth/0.6.11/arbitrary_send_eth.sol#20) |
||||||
|
|
||||||
|
Test.direct() (tests/e2e/detectors/test_data/arbitrary-send-eth/0.6.11/arbitrary_send_eth.sol#11-13) sends eth to arbitrary user |
||||||
|
Dangerous calls: |
||||||
|
- msg.sender.send(address(this).balance) (tests/e2e/detectors/test_data/arbitrary-send-eth/0.6.11/arbitrary_send_eth.sol#12) |
||||||
|
|
@ -0,0 +1,8 @@ |
|||||||
|
Test.direct() (tests/e2e/detectors/test_data/arbitrary-send-eth/0.7.6/arbitrary_send_eth.sol#11-13) sends eth to arbitrary user |
||||||
|
Dangerous calls: |
||||||
|
- msg.sender.send(address(this).balance) (tests/e2e/detectors/test_data/arbitrary-send-eth/0.7.6/arbitrary_send_eth.sol#12) |
||||||
|
|
||||||
|
Test.indirect() (tests/e2e/detectors/test_data/arbitrary-send-eth/0.7.6/arbitrary_send_eth.sol#19-21) sends eth to arbitrary user |
||||||
|
Dangerous calls: |
||||||
|
- destination.send(address(this).balance) (tests/e2e/detectors/test_data/arbitrary-send-eth/0.7.6/arbitrary_send_eth.sol#20) |
||||||
|
|
@ -0,0 +1,12 @@ |
|||||||
|
D.f() (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#39)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#25-28)which only takes arrays by value |
||||||
|
|
||||||
|
D.f() (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#39)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#21-23)which only takes arrays by value |
||||||
|
|
||||||
|
C.f() (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#2)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#21-23)which only takes arrays by value |
||||||
|
|
||||||
|
C.f() (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#2)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#25-28)which only takes arrays by value |
||||||
|
|
||||||
|
C.g() (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#11)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#25-28)which only takes arrays by value |
||||||
|
|
||||||
|
C.g() (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#11)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#21-23)which only takes arrays by value |
||||||
|
|
@ -0,0 +1,12 @@ |
|||||||
|
D.f() (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#39)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#25-28)which only takes arrays by value |
||||||
|
|
||||||
|
D.f() (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#39)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#21-23)which only takes arrays by value |
||||||
|
|
||||||
|
C.f() (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#2)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#21-23)which only takes arrays by value |
||||||
|
|
||||||
|
C.f() (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#2)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#25-28)which only takes arrays by value |
||||||
|
|
||||||
|
C.g() (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#11)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#25-28)which only takes arrays by value |
||||||
|
|
||||||
|
C.g() (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#11)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#21-23)which only takes arrays by value |
||||||
|
|
@ -0,0 +1,12 @@ |
|||||||
|
D.f() (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#39)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#25-28)which only takes arrays by value |
||||||
|
|
||||||
|
D.f() (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#39)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#21-23)which only takes arrays by value |
||||||
|
|
||||||
|
C.f() (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#2)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#21-23)which only takes arrays by value |
||||||
|
|
||||||
|
C.f() (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#2)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#25-28)which only takes arrays by value |
||||||
|
|
||||||
|
C.g() (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#11)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#25-28)which only takes arrays by value |
||||||
|
|
||||||
|
C.g() (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#11)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#21-23)which only takes arrays by value |
||||||
|
|
@ -0,0 +1,12 @@ |
|||||||
|
D.f() (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#39)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#25-28)which only takes arrays by value |
||||||
|
|
||||||
|
D.f() (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#39)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#21-23)which only takes arrays by value |
||||||
|
|
||||||
|
C.f() (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#2)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#21-23)which only takes arrays by value |
||||||
|
|
||||||
|
C.f() (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#2)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#25-28)which only takes arrays by value |
||||||
|
|
||||||
|
C.g() (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#11)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#25-28)which only takes arrays by value |
||||||
|
|
||||||
|
C.g() (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#11)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#21-23)which only takes arrays by value |
||||||
|
|
@ -0,0 +1,9 @@ |
|||||||
|
ArrayLengthAssignment (tests/e2e/detectors/test_data/controlled-array-length/0.4.25/array_length_assignment.sol#1-46) contract sets array length with a user-controlled value: |
||||||
|
- b.subStruct.x.length = param + 1 (tests/e2e/detectors/test_data/controlled-array-length/0.4.25/array_length_assignment.sol#41) |
||||||
|
|
||||||
|
ArrayLengthAssignment (tests/e2e/detectors/test_data/controlled-array-length/0.4.25/array_length_assignment.sol#1-46) contract sets array length with a user-controlled value: |
||||||
|
- a.x.length = param (tests/e2e/detectors/test_data/controlled-array-length/0.4.25/array_length_assignment.sol#36) |
||||||
|
|
||||||
|
ArrayLengthAssignment (tests/e2e/detectors/test_data/controlled-array-length/0.4.25/array_length_assignment.sol#1-46) contract sets array length with a user-controlled value: |
||||||
|
- arr.length = param (tests/e2e/detectors/test_data/controlled-array-length/0.4.25/array_length_assignment.sol#26) |
||||||
|
|
@ -0,0 +1,9 @@ |
|||||||
|
ArrayLengthAssignment (tests/e2e/detectors/test_data/controlled-array-length/0.5.16/array_length_assignment.sol#1-46) contract sets array length with a user-controlled value: |
||||||
|
- b.subStruct.x.length = param + 1 (tests/e2e/detectors/test_data/controlled-array-length/0.5.16/array_length_assignment.sol#41) |
||||||
|
|
||||||
|
ArrayLengthAssignment (tests/e2e/detectors/test_data/controlled-array-length/0.5.16/array_length_assignment.sol#1-46) contract sets array length with a user-controlled value: |
||||||
|
- a.x.length = param (tests/e2e/detectors/test_data/controlled-array-length/0.5.16/array_length_assignment.sol#36) |
||||||
|
|
||||||
|
ArrayLengthAssignment (tests/e2e/detectors/test_data/controlled-array-length/0.5.16/array_length_assignment.sol#1-46) contract sets array length with a user-controlled value: |
||||||
|
- arr.length = param (tests/e2e/detectors/test_data/controlled-array-length/0.5.16/array_length_assignment.sol#26) |
||||||
|
|
@ -0,0 +1,3 @@ |
|||||||
|
GetCode.at(address) (tests/e2e/detectors/test_data/assembly/0.4.25/inline_assembly_contract.sol#6-20) uses assembly |
||||||
|
- INLINE ASM (tests/e2e/detectors/test_data/assembly/0.4.25/inline_assembly_contract.sol#7-20) |
||||||
|
|
@ -0,0 +1,6 @@ |
|||||||
|
VectorSum.sumPureAsm(uint256[]) (tests/e2e/detectors/test_data/assembly/0.4.25/inline_assembly_library.sol#25-47) uses assembly |
||||||
|
- INLINE ASM (tests/e2e/detectors/test_data/assembly/0.4.25/inline_assembly_library.sol#26-47) |
||||||
|
|
||||||
|
VectorSum.sumAsm(uint256[]) (tests/e2e/detectors/test_data/assembly/0.4.25/inline_assembly_library.sol#16-22) uses assembly |
||||||
|
- INLINE ASM (tests/e2e/detectors/test_data/assembly/0.4.25/inline_assembly_library.sol#18-21) |
||||||
|
|
@ -0,0 +1,3 @@ |
|||||||
|
GetCode.at(address) (tests/e2e/detectors/test_data/assembly/0.5.16/inline_assembly_contract.sol#6-20) uses assembly |
||||||
|
- INLINE ASM (tests/e2e/detectors/test_data/assembly/0.5.16/inline_assembly_contract.sol#7-19) |
||||||
|
|
@ -0,0 +1,6 @@ |
|||||||
|
VectorSum.sumAsm(uint256[]) (tests/e2e/detectors/test_data/assembly/0.5.16/inline_assembly_library.sol#16-22) uses assembly |
||||||
|
- INLINE ASM (tests/e2e/detectors/test_data/assembly/0.5.16/inline_assembly_library.sol#18-20) |
||||||
|
|
||||||
|
VectorSum.sumPureAsm(uint256[]) (tests/e2e/detectors/test_data/assembly/0.5.16/inline_assembly_library.sol#25-47) uses assembly |
||||||
|
- INLINE ASM (tests/e2e/detectors/test_data/assembly/0.5.16/inline_assembly_library.sol#26-46) |
||||||
|
|
@ -0,0 +1,3 @@ |
|||||||
|
GetCode.at(address) (tests/e2e/detectors/test_data/assembly/0.6.11/inline_assembly_contract.sol#4-18) uses assembly |
||||||
|
- INLINE ASM (tests/e2e/detectors/test_data/assembly/0.6.11/inline_assembly_contract.sol#5-17) |
||||||
|
|
@ -0,0 +1,6 @@ |
|||||||
|
VectorSum.sumAsm(uint256[]) (tests/e2e/detectors/test_data/assembly/0.6.11/inline_assembly_library.sol#14-20) uses assembly |
||||||
|
- INLINE ASM (tests/e2e/detectors/test_data/assembly/0.6.11/inline_assembly_library.sol#16-18) |
||||||
|
|
||||||
|
VectorSum.sumPureAsm(uint256[]) (tests/e2e/detectors/test_data/assembly/0.6.11/inline_assembly_library.sol#23-45) uses assembly |
||||||
|
- INLINE ASM (tests/e2e/detectors/test_data/assembly/0.6.11/inline_assembly_library.sol#24-44) |
||||||
|
|
@ -0,0 +1,3 @@ |
|||||||
|
GetCode.at(address) (tests/e2e/detectors/test_data/assembly/0.7.6/inline_assembly_contract.sol#4-18) uses assembly |
||||||
|
- INLINE ASM (tests/e2e/detectors/test_data/assembly/0.7.6/inline_assembly_contract.sol#5-17) |
||||||
|
|
@ -0,0 +1,6 @@ |
|||||||
|
VectorSum.sumAsm(uint256[]) (tests/e2e/detectors/test_data/assembly/0.7.6/inline_assembly_library.sol#14-20) uses assembly |
||||||
|
- INLINE ASM (tests/e2e/detectors/test_data/assembly/0.7.6/inline_assembly_library.sol#16-18) |
||||||
|
|
||||||
|
VectorSum.sumPureAsm(uint256[]) (tests/e2e/detectors/test_data/assembly/0.7.6/inline_assembly_library.sol#23-45) uses assembly |
||||||
|
- INLINE ASM (tests/e2e/detectors/test_data/assembly/0.7.6/inline_assembly_library.sol#24-44) |
||||||
|
|
@ -0,0 +1,12 @@ |
|||||||
|
A.bad2() (tests/e2e/detectors/test_data/assert-state-change/0.4.25/assert_state_change.sol#19-21) has an assert() call which possibly changes state. |
||||||
|
-assert(bool)(bad2_callee()) (tests/e2e/detectors/test_data/assert-state-change/0.4.25/assert_state_change.sol#20) |
||||||
|
Consider using require() or change the invariant to not modify the state. |
||||||
|
|
||||||
|
A.bad0() (tests/e2e/detectors/test_data/assert-state-change/0.4.25/assert_state_change.sol#6-8) has an assert() call which possibly changes state. |
||||||
|
-assert(bool)((s_a += 1) > 10) (tests/e2e/detectors/test_data/assert-state-change/0.4.25/assert_state_change.sol#7) |
||||||
|
Consider using require() or change the invariant to not modify the state. |
||||||
|
|
||||||
|
A.bad1(uint256) (tests/e2e/detectors/test_data/assert-state-change/0.4.25/assert_state_change.sol#11-13) has an assert() call which possibly changes state. |
||||||
|
-assert(bool)((s_a += a) > 10) (tests/e2e/detectors/test_data/assert-state-change/0.4.25/assert_state_change.sol#12) |
||||||
|
Consider using require() or change the invariant to not modify the state. |
||||||
|
|
@ -0,0 +1,12 @@ |
|||||||
|
A.bad1(uint256) (tests/e2e/detectors/test_data/assert-state-change/0.5.16/assert_state_change.sol#11-13) has an assert() call which possibly changes state. |
||||||
|
-assert(bool)((s_a += a) > 10) (tests/e2e/detectors/test_data/assert-state-change/0.5.16/assert_state_change.sol#12) |
||||||
|
Consider using require() or change the invariant to not modify the state. |
||||||
|
|
||||||
|
A.bad2() (tests/e2e/detectors/test_data/assert-state-change/0.5.16/assert_state_change.sol#19-21) has an assert() call which possibly changes state. |
||||||
|
-assert(bool)(bad2_callee()) (tests/e2e/detectors/test_data/assert-state-change/0.5.16/assert_state_change.sol#20) |
||||||
|
Consider using require() or change the invariant to not modify the state. |
||||||
|
|
||||||
|
A.bad0() (tests/e2e/detectors/test_data/assert-state-change/0.5.16/assert_state_change.sol#6-8) has an assert() call which possibly changes state. |
||||||
|
-assert(bool)((s_a += 1) > 10) (tests/e2e/detectors/test_data/assert-state-change/0.5.16/assert_state_change.sol#7) |
||||||
|
Consider using require() or change the invariant to not modify the state. |
||||||
|
|
@ -0,0 +1,12 @@ |
|||||||
|
A.bad0() (tests/e2e/detectors/test_data/assert-state-change/0.6.11/assert_state_change.sol#6-8) has an assert() call which possibly changes state. |
||||||
|
-assert(bool)((s_a += 1) > 10) (tests/e2e/detectors/test_data/assert-state-change/0.6.11/assert_state_change.sol#7) |
||||||
|
Consider using require() or change the invariant to not modify the state. |
||||||
|
|
||||||
|
A.bad1(uint256) (tests/e2e/detectors/test_data/assert-state-change/0.6.11/assert_state_change.sol#11-13) has an assert() call which possibly changes state. |
||||||
|
-assert(bool)((s_a += a) > 10) (tests/e2e/detectors/test_data/assert-state-change/0.6.11/assert_state_change.sol#12) |
||||||
|
Consider using require() or change the invariant to not modify the state. |
||||||
|
|
||||||
|
A.bad2() (tests/e2e/detectors/test_data/assert-state-change/0.6.11/assert_state_change.sol#19-21) has an assert() call which possibly changes state. |
||||||
|
-assert(bool)(bad2_callee()) (tests/e2e/detectors/test_data/assert-state-change/0.6.11/assert_state_change.sol#20) |
||||||
|
Consider using require() or change the invariant to not modify the state. |
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue