Merge pull request #732 from crytic/dev-19-new-detectors

Open source 19 new bug detectors
pull/733/head
Feist Josselin 4 years ago committed by GitHub
commit bb1c1fbbad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      scripts/ci_test_etherlime.sh
  2. 22
      slither/detectors/all_detectors.py
  3. 0
      slither/detectors/assembly/__init__.py
  4. 60
      slither/detectors/assembly/shift_parameter_mixup.py
  5. 138
      slither/detectors/attributes/unimplemented_interface.py
  6. 0
      slither/detectors/compiler_bugs/__init__.py
  7. 160
      slither/detectors/compiler_bugs/array_by_reference.py
  8. 84
      slither/detectors/compiler_bugs/enum_conversion.py
  9. 62
      slither/detectors/compiler_bugs/multiple_constructor_schemes.py
  10. 89
      slither/detectors/compiler_bugs/public_mapping_nested.py
  11. 157
      slither/detectors/compiler_bugs/reused_base_constructor.py
  12. 150
      slither/detectors/compiler_bugs/storage_ABIEncoderV2_array.py
  13. 147
      slither/detectors/compiler_bugs/storage_signed_integer_array.py
  14. 149
      slither/detectors/compiler_bugs/uninitialized_function_ptr_in_constructor.py
  15. 105
      slither/detectors/functions/unimplemented.py
  16. 122
      slither/detectors/operations/bad_prng.py
  17. 118
      slither/detectors/statements/array_length_assignment.py
  18. 83
      slither/detectors/statements/assert_state_change.py
  19. 94
      slither/detectors/statements/costly_operations_in_loop.py
  20. 82
      slither/detectors/statements/mapping_deletion.py
  21. 88
      slither/detectors/statements/redundant_statements.py
  22. 107
      slither/detectors/variables/function_init_state_variables.py
  23. 86
      slither/detectors/variables/similar_variables.py
  24. 99
      tests/detectors/abiencoderv2-array/storage_ABIEncoderV2_array.sol
  25. 1828
      tests/detectors/abiencoderv2-array/storage_ABIEncoderV2_array.sol.0.4.25.ABIEncoderV2Array.json
  26. 51
      tests/detectors/array-by-reference/array_by_reference.sol
  27. 1333
      tests/detectors/array-by-reference/array_by_reference.sol.0.4.25.ArrayByReference.json
  28. 39
      tests/detectors/assert-state-change/assert_state_change.sol
  29. 568
      tests/detectors/assert-state-change/assert_state_change.sol.0.5.12.AssertStateChange.json
  30. 568
      tests/detectors/assert-state-change/assert_state_change.sol.0.5.8.AssertStateChange.json
  31. 168
      tests/detectors/boolean-equality/boolean-equality.sol.0.5.1.BooleanEquality.json
  32. 46
      tests/detectors/controlled-array-length/array_length_assignment.sol
  33. 604
      tests/detectors/controlled-array-length/array_length_assignment.sol.0.4.25.ArrayLengthAssignment.json
  34. 35
      tests/detectors/costly-loop/multiple_costly_operations_in_loop.sol
  35. 184
      tests/detectors/costly-loop/multiple_costly_operations_in_loop.sol.0.4.25.CostlyOperationsInLoop.json
  36. 46
      tests/detectors/function-init-state/function_init_state_variables.sol
  37. 464
      tests/detectors/function-init-state/function_init_state_variables.sol.0.4.25.FunctionInitializedState.json
  38. 43
      tests/detectors/mapping-deletion/MappingDeletion.sol
  39. 425
      tests/detectors/mapping-deletion/MappingDeletion.sol.0.4.25.MappingDeletionDetection.json
  40. 72
      tests/detectors/missing-inheritance/unimplemented_interfaces.sol
  41. 3
      tests/detectors/missing-inheritance/unimplemented_interfaces.sol.0.5.12.UnimplementedFunctionDetection.json
  42. 785
      tests/detectors/multiple-constructors/multiple-constructors.sol.compact.json
  43. 29
      tests/detectors/public-mappings-nested/public_mappings_nested.sol
  44. 69
      tests/detectors/public-mappings-nested/public_mappings_nested.sol.0.4.25.PublicMappingNested.json
  45. 17
      tests/detectors/redundant-statements/redundant_statements.sol
  46. 733
      tests/detectors/redundant-statements/redundant_statements.sol.0.4.25.RedundantStatements.json
  47. 37
      tests/detectors/reused-constructor/reused_base_constructor.sol
  48. 1044
      tests/detectors/reused-constructor/reused_base_constructor.sol.0.4.25.ReusedBaseConstructor.json
  49. 45
      tests/detectors/storage-array/storage_signed_integer_array.sol
  50. 3
      tests/detectors/storage-array/storage_signed_integer_array.sol.0.5.12.StorageSignedIntegerArray.json
  51. 516
      tests/detectors/storage-array/storage_signed_integer_array.sol.0.5.8.StorageSignedIntegerArray.json
  52. 41
      tests/detectors/unimplemented-functions/unimplemented.sol
  53. 346
      tests/detectors/unimplemented-functions/unimplemented.sol.0.4.25.UnimplementedFunctionDetection.json
  54. 136
      tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol
  55. 325
      tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol.0.5.8.UninitializedFunctionPtrsConstructor.json
  56. 28
      tests/detectors/weak-prng/bad_prng.sol
  57. 660
      tests/detectors/weak-prng/bad_prng.sol.0.4.25.BadPRNG.json
  58. 360
      tests/test_detectors.py

@ -15,7 +15,7 @@ npm i -g etherlime
etherlime init
slither .
if [ $? -eq 7 ]
if [ $? -eq 8 ]
then
exit 0
fi

@ -49,5 +49,27 @@ from .statements.divide_before_multiply import DivideBeforeMultiply
from .statements.unprotected_upgradeable import UnprotectedUpgradeable
from .slither.name_reused import NameReused
from .functions.unimplemented import UnimplementedFunctionDetection
from .statements.mapping_deletion import MappingDeletionDetection
from .statements.array_length_assignment import ArrayLengthAssignment
from .variables.similar_variables import SimilarVarsDetection
from .variables.function_init_state_variables import FunctionInitializedState
from .statements.redundant_statements import RedundantStatements
from .operations.bad_prng import BadPRNG
from .statements.costly_operations_in_loop import CostlyOperationsInLoop
from .statements.assert_state_change import AssertStateChange
from .attributes.unimplemented_interface import MissingInheritance
from .assembly.shift_parameter_mixup import ShiftParameterMixup
from .compiler_bugs.storage_signed_integer_array import StorageSignedIntegerArray
from .compiler_bugs.uninitialized_function_ptr_in_constructor import (
UninitializedFunctionPtrsConstructor,
)
from .compiler_bugs.storage_ABIEncoderV2_array import ABIEncoderV2Array
from .compiler_bugs.array_by_reference import ArrayByReference
from .compiler_bugs.enum_conversion import EnumConversion
from .compiler_bugs.multiple_constructor_schemes import MultipleConstructorSchemes
from .compiler_bugs.public_mapping_nested import PublicMappingNested
from .compiler_bugs.reused_base_constructor import ReusedBaseConstructor
#
#

@ -0,0 +1,60 @@
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations import Binary, BinaryType
from slither.slithir.variables import Constant
class ShiftParameterMixup(AbstractDetector):
"""
Check for cases where a return(a,b) is used in an assembly function that also returns two variables
"""
ARGUMENT = "incorrect-shift"
HELP = "The order of parameters in a shift instruction is incorrect."
IMPACT = DetectorClassification.HIGH
CONFIDENCE = DetectorClassification.HIGH
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#shift-parameter-mixup"
WIKI_TITLE = "Incorrect shift in assembly."
WIKI_DESCRIPTION = "Detect if the values in a shift operation are reversed"
WIKI_EXPLOIT_SCENARIO = """
```solidity
contract C {
function f() internal returns (uint a) {
assembly {
a := shr(a, 8)
}
}
}
```
The shift statement will right-shift the constant 8 by `a` bits"""
WIKI_RECOMMENDATION = "Swap the order of parameters."
def _check_function(self, f):
results = []
for node in f.nodes:
for ir in node.irs:
if isinstance(ir, Binary) and ir.type in [
BinaryType.LEFT_SHIFT,
BinaryType.RIGHT_SHIFT,
]:
if isinstance(ir.variable_left, Constant):
info = [f, " contains an incorrect shift operation: ", node, "\n"]
json = self.generate_result(info)
results.append(json)
return results
def _detect(self):
results = []
for c in self.contracts:
for f in c.functions:
if f.contract_declarer != c:
continue
if f.contains_assembly:
results += self._check_function(f)
return results

@ -0,0 +1,138 @@
"""
Module detecting unimplemented interfaces
Collect all the interfaces
Check for contracts which implement all interface functions but do not explicitly derive from those interfaces.
"""
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
class MissingInheritance(AbstractDetector):
"""
Unimplemented interface detector
"""
ARGUMENT = "missing-inheritance"
HELP = "Missing inheritance"
IMPACT = DetectorClassification.INFORMATIONAL
CONFIDENCE = DetectorClassification.HIGH
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#missing-inheritance"
WIKI_TITLE = "Missing inheritance"
WIKI_DESCRIPTION = "Detect missing inheritance."
WIKI_EXPLOIT_SCENARIO = """
```solidity
interface ISomething {
function f1() external returns(uint);
}
contract Something {
function f1() external returns(uint){
return 42;
}
}
```
`Something` should inherit from `ISomething`.
"""
WIKI_RECOMMENDATION = "Inherit from the missing interface or contract."
@staticmethod
def detect_unimplemented_interface(contract, interfaces):
"""
Detects if contract intends to implement one of the interfaces but does not explicitly do so by deriving from it
:param contract: The contract to check
:param interfaces: List of all the interfaces
:return: Interfaces likely intended to implement by the contract
"""
intended_interfaces = []
sigs_contract = {f.full_name for f in contract.functions_entry_points}
if not sigs_contract:
return intended_interfaces
for interface in interfaces:
# If contract already inherits from interface, skip that interface
if interface in contract.inheritance:
continue
sigs_interface = {f.full_name for f in interface.functions_entry_points}
# Contract should implement all the functions of the intended interface
if not sigs_interface.issubset(sigs_contract):
continue
# A parent contract inherited should not implement a superset of intended interface
# This is because in the following:
# interface ERC20_interface:
# - balanceOf(uint) -> uint
# - transfer(address, address) -> bool
# contract ForeignToken:
# - balanceOf(uint) -> uint
# contract MyERC20Implementation is ERC20_interface
#
# We do not want MyERC20Implementation to be declared as missing ForeignToken interface
intended_interface_is_subset_parent = False
for parent in contract.inheritance:
sigs_parent = {f.full_name for f in parent.functions_entry_points}
if sigs_interface.issubset(sigs_parent):
intended_interface_is_subset_parent = True
break
if not intended_interface_is_subset_parent:
# Should not be a subset of an earlier determined intended_interface or derive from it
intended_interface_is_subset_intended = False
for intended_interface in intended_interfaces:
sigs_intended_interface = {
f.full_name for f in intended_interface.functions_entry_points
}
if (
sigs_interface.issubset(sigs_intended_interface)
or interface in intended_interface.inheritance
):
intended_interface_is_subset_intended = True
break
# If superset of an earlier determined intended_interface or derives from it,
# remove the intended_interface
if (
sigs_intended_interface.issubset(sigs_interface)
or intended_interface in interface.inheritance
):
intended_interfaces.remove(intended_interface)
if not intended_interface_is_subset_intended:
intended_interfaces.append(interface)
return intended_interfaces
def _detect(self):
"""Detect unimplemented interfaces
Returns:
list: {'contract'}
"""
# Collect all the interfaces
# Here interface can be "interface" from solidity, or contracts with only functions declaration
# Skip interfaces without functions
interfaces = [
contract
for contract in self.slither.contracts
if contract.is_signature_only()
and any(not f.is_constructor_variables for f in contract.functions)
]
# Check derived contracts for missing interface implementations
results = []
for contract in self.slither.contracts_derived:
# Skip interfaces
if contract in interfaces:
continue
intended_interfaces = self.detect_unimplemented_interface(contract, interfaces)
for interface in intended_interfaces:
info = [contract, " should inherit from ", interface, "\n"]
res = self.generate_result(info)
results.append(res)
return results

@ -0,0 +1,160 @@
"""
Detects the passing of arrays located in memory to functions which expect to modify arrays via storage reference.
"""
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.core.solidity_types.array_type import ArrayType
from slither.core.variables.state_variable import StateVariable
from slither.core.variables.local_variable import LocalVariable
from slither.slithir.operations.high_level_call import HighLevelCall
from slither.slithir.operations.internal_call import InternalCall
class ArrayByReference(AbstractDetector):
"""
Detects passing of arrays located in memory to functions which expect to modify arrays via storage reference.
"""
ARGUMENT = "array-by-reference"
HELP = "Modifying storage array by value"
IMPACT = DetectorClassification.HIGH
CONFIDENCE = DetectorClassification.HIGH
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#modifying-storage-array-by-value"
WIKI_TITLE = "Modifying storage array by value"
WIKI_DESCRIPTION = (
"Detect arrays passed to a function that expects reference to a storage array"
)
WIKI_EXPLOIT_SCENARIO = """
```solidity
contract Memory {
uint[1] public x; // storage
function f() public {
f1(x); // update x
f2(x); // do not update x
}
function f1(uint[1] storage arr) internal { // by reference
arr[0] = 1;
}
function f2(uint[1] arr) internal { // by value
arr[0] = 2;
}
}
```
Bob calls `f()`. Bob assumes that at the end of the call `x[0]` is 2, but it is 1.
As a result, Bob's usage of the contract is incorrect."""
WIKI_RECOMMENDATION = "Ensure the correct usage of `memory` and `storage` in the function parameters. Make all the locations explicit."
@staticmethod
def get_funcs_modifying_array_params(contracts):
"""
Obtains a set of functions which take arrays not located in storage as parameters, and writes to them.
:param contracts: The collection of contracts to check functions in.
:return: A set of functions which take an array not located in storage as a parameter and writes to it.
"""
# Initialize our resulting set of functions which modify non-reference array parameters
results = set()
# Loop through all functions in all contracts.
for contract in contracts:
for function in contract.functions_declared:
# Skip any constructor functions.
if function.is_constructor:
continue
# Determine if this function takes an array as a parameter and the location isn't storage.
# If it has been written to, we know this sets an non-storage-ref array.
for param in function.parameters:
if isinstance(param.type, ArrayType) and param.location != "storage":
if param in function.variables_written:
results.add(function)
break
return results
@staticmethod
def detect_calls_passing_ref_to_function(contracts, array_modifying_funcs):
"""
Obtains all calls passing storage arrays by value to a function which cannot write to them successfully.
:param contracts: The collection of contracts to check for problematic calls in.
:param array_modifying_funcs: The collection of functions which take non-storage arrays as input and writes to
them.
:return: A list of tuples (calling_node, affected_argument, invoked_function) which denote all problematic
nodes invoking a function with some storage array argument where the invoked function seemingly attempts to
write to the array unsuccessfully.
"""
# Define our resulting array.
results = []
# Verify we have functions in our list to check for.
if not array_modifying_funcs:
return results
# Loop for each node in each function/modifier in each contract
# pylint: disable=too-many-nested-blocks
for contract in contracts:
for function in contract.functions_and_modifiers_declared:
for node in function.nodes:
# If this node has no expression, skip it.
if not node.expression:
continue
for ir in node.irs:
# Verify this is a high level call.
if not isinstance(ir, (HighLevelCall, InternalCall)):
continue
# Verify this references a function in our array modifying functions collection.
if ir.function not in array_modifying_funcs:
continue
# Verify one of these parameters is an array in storage.
for arg in ir.arguments:
# Verify this argument is a variable that is an array type.
if not isinstance(arg, (StateVariable, LocalVariable)):
continue
if not isinstance(arg.type, ArrayType):
continue
# If it is a state variable OR a local variable referencing storage, we add it to the list.
if isinstance(arg, StateVariable) or (
isinstance(arg, LocalVariable) and arg.location == "storage"
):
results.append((node, arg, ir.function))
return results
def _detect(self):
"""
Detects passing of arrays located in memory to functions which expect to modify arrays via storage reference.
:return: The JSON results of the detector, which contains the calling_node, affected_argument_variable and
invoked_function for each result found.
"""
results = []
array_modifying_funcs = self.get_funcs_modifying_array_params(self.contracts)
problematic_calls = self.detect_calls_passing_ref_to_function(
self.contracts, array_modifying_funcs
)
if problematic_calls:
for calling_node, affected_argument, invoked_function in problematic_calls:
info = [
calling_node.function,
" passes array ",
affected_argument,
"by reference to ",
invoked_function,
"which only takes arrays by value\n",
]
res = self.generate_result(info)
results.append(res)
return results

@ -0,0 +1,84 @@
"""
Module detecting dangerous conversion to enum
"""
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations import TypeConversion
from slither.core.declarations.enum import Enum
def _uses_vulnerable_solc_version(version):
"""Detect if used compiler version is 0.4.[0|1|2|3|4]
Args:
version (solc version used)
Returns:
Bool
"""
if version in ["0.4.0", "0.4.1", "0.4.2", "0.4.3", "0.4.4"]:
return True
return False
def _detect_dangerous_enum_conversions(contract):
"""Detect dangerous conversion to enum by checking IR
Args:
contract (Contract)
Returns:
list[(node, variable)] (Nodes where a variable is being converted into enum)
"""
return [
(n, ir.variable)
for f in contract.functions_declared
for n in f.nodes
for ir in n.irs
if isinstance(ir, TypeConversion) and isinstance(ir.type.type, Enum)
]
class EnumConversion(AbstractDetector):
"""
Detect dangerous conversion to enum
"""
ARGUMENT = "enum-conversion"
HELP = "Detect dangerous enum conversion"
IMPACT = DetectorClassification.MEDIUM
CONFIDENCE = DetectorClassification.HIGH
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-enum-conversion"
WIKI_TITLE = "Dangerous enum conversion"
WIKI_DESCRIPTION = "Detect out-of-range `enum` conversion (`solc` < `0.4.5`)."
WIKI_EXPLOIT_SCENARIO = """
```solidity
pragma solidity 0.4.2;
contract Test{
enum E{a}
function bug(uint a) public returns(E){
return E(a);
}
}
```
Attackers can trigger unexpected behaviour by calling `bug(1)`."""
WIKI_RECOMMENDATION = "Use a recent compiler version. If `solc` <`0.4.5` is required, check the `enum` conversion range."
def _detect(self):
"""Detect dangerous conversion to enum"""
results = []
# If solc version >= 0.4.5 then return
if not _uses_vulnerable_solc_version(self.slither.solc_version):
return results
for c in self.slither.contracts:
ret = _detect_dangerous_enum_conversions(c)
for node, var in ret:
func_info = [node, " has a dangerous enum conversion\n"]
# Output each node with the function info header as a separate result.
variable_info = ["\t- Variable: ", var, f" of type: {str(var.type)}\n"]
node_info = ["\t- Enum conversion: ", node, "\n"]
json = self.generate_result(func_info + variable_info + node_info)
results.append(json)
return results

@ -0,0 +1,62 @@
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
class MultipleConstructorSchemes(AbstractDetector):
"""
Module detecting multiple constructors in the same contract.
(This was possible prior to Solidity 0.4.23, using old and new constructor schemes).
"""
ARGUMENT = "multiple-constructors"
HELP = "Multiple constructor schemes"
IMPACT = DetectorClassification.HIGH
CONFIDENCE = DetectorClassification.HIGH
WIKI = (
"https://github.com/crytic/slither/wiki/Detector-Documentation#multiple-constructor-schemes"
)
WIKI_TITLE = "Multiple constructor schemes"
WIKI_DESCRIPTION = (
"Detect multiple constructor definitions in the same contract (using new and old schemes)."
)
WIKI_EXPLOIT_SCENARIO = """
```solidity
contract A {
uint x;
constructor() public {
x = 0;
}
function A() public {
x = 1;
}
function test() public returns(uint) {
return x;
}
}
```
In Solidity [0.4.22](https://github.com/ethereum/solidity/releases/tag/v0.4.23), a contract with both constructor schemes will compile. The first constructor will take precedence over the second, which may be unintended."""
WIKI_RECOMMENDATION = "Only declare one constructor, preferably using the new scheme `constructor(...)` instead of `function <contractName>(...)`."
def _detect(self):
"""
Detect multiple constructor schemes in the same contract
:return: Returns a list of contract JSON result, where each result contains all constructor definitions.
"""
results = []
for contract in self.contracts:
# Obtain any constructors defined in this contract
constructors = [f for f in contract.constructors if f.contract_declarer == contract]
# If there is more than one, we encountered the described issue occurring.
if constructors and len(constructors) > 1:
info = [contract, " contains multiple constructors in the same contract:\n"]
for constructor in constructors:
info += ["\t- ", constructor, "\n"]
res = self.generate_result(info)
results.append(res)
return results

@ -0,0 +1,89 @@
"""
Module detecting public mappings with nested variables (returns incorrect values prior to 0.5.x)
"""
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.core.solidity_types.mapping_type import MappingType
from slither.core.solidity_types.user_defined_type import UserDefinedType
from slither.core.declarations.structure import Structure
def detect_public_nested_mappings(contract):
"""
Detect any state variables that are initialized from an immediate function call (prior to constructor run).
:param contract: The contract to detect state variable definitions for.
:return: A list of all state variables defined in the given contract that meet the specified criteria.
"""
results = []
for state_variable in contract.variables:
# Verify this variable is defined in this contract
if state_variable.contract != contract:
continue
# Verify this is a public mapping
if state_variable.visibility != "public" or not isinstance(
state_variable.type, MappingType
):
continue
# Verify the value type is a user defined type (struct)
if not isinstance(state_variable.type.type_to, UserDefinedType) or not isinstance(
state_variable.type.type_to.type, Structure
):
continue
# Obtain the struct
struct_type = state_variable.type.type_to.type
for struct_member in struct_type.elems.values():
if isinstance(struct_member.type, UserDefinedType) and isinstance(
struct_member.type.type, Structure
):
results.append(state_variable)
break
return results
class PublicMappingNested(AbstractDetector):
"""
Detects public mappings with nested variables (returns incorrect values prior to 0.5.x)
"""
ARGUMENT = "public-mappings-nested"
HELP = "Public mappings with nested variables"
IMPACT = DetectorClassification.HIGH
CONFIDENCE = DetectorClassification.HIGH
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#public-mappings-with-nested-variables"
WIKI_TITLE = "Public mappings with nested variables"
WIKI_DESCRIPTION = "Prior to Solidity 0.5, a public mapping with nested structures returned [incorrect values](https://github.com/ethereum/solidity/issues/5520)."
WIKI_EXPLOIT_SCENARIO = """Bob interacts with a contract that has a public mapping with nested structures. The values returned by the mapping are incorrect, breaking Bob's usage"""
WIKI_RECOMMENDATION = "Do not use public mapping with nested structures."
def _detect(self):
"""
Detect public mappings with nested variables (returns incorrect values prior to 0.5.x)
Returns:
list: {'vuln', 'filename,'contract','func', 'public_nested_mappings'}
"""
results = []
for p in self.slither.pragma_directives:
if "0.5.0" in p.version and not "<0.5.0" in p.version:
return []
if self.slither.solc_version and self.slither.solc_version.startswith("0.5."):
return []
for contract in self.contracts:
public_nested_mappings = detect_public_nested_mappings(contract)
if public_nested_mappings:
for public_nested_mapping in public_nested_mappings:
info = [public_nested_mapping, " is a public mapping with nested variables\n"]
json = self.generate_result(info)
results.append(json)
return results

@ -0,0 +1,157 @@
"""
Module detecting re-used base constructors in inheritance hierarchy.
"""
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
# Helper: adds explicitly called constructors with arguments to the results lookup.
def _add_constructors_with_args(
base_constructors, called_by_constructor, current_contract, results
):
for explicit_base_constructor in base_constructors:
if len(explicit_base_constructor.parameters) > 0:
if explicit_base_constructor not in results:
results[explicit_base_constructor] = []
results[explicit_base_constructor] += [(current_contract, called_by_constructor)]
class ReusedBaseConstructor(AbstractDetector):
"""
Re-used base constructors
"""
ARGUMENT = "reused-constructor"
HELP = "Reused base constructor"
IMPACT = DetectorClassification.MEDIUM
# The confidence is medium, because prior Solidity 0.4.22, we cant differentiate
# contract C is A() {
# to
# contract C is A {
CONFIDENCE = DetectorClassification.MEDIUM
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#reused-base-constructors"
WIKI_TITLE = "Reused base constructors"
WIKI_DESCRIPTION = "Detects if the same base constructor is called with arguments from two different locations in the same inheritance hierarchy."
WIKI_EXPLOIT_SCENARIO = """
```solidity
pragma solidity ^0.4.0;
contract A{
uint num = 5;
constructor(uint x) public{
num += x;
}
}
contract B is A{
constructor() A(2) public { /* ... */ }
}
contract C is A {
constructor() A(3) public { /* ... */ }
}
contract D is B, C {
constructor() public { /* ... */ }
}
contract E is B {
constructor() A(1) public { /* ... */ }
}
```
The constructor of `A` is called multiple times in `D` and `E`:
- `D` inherits from `B` and `C`, both of which construct `A`.
- `E` only inherits from `B`, but `B` and `E` construct `A`.
."""
WIKI_RECOMMENDATION = "Remove the duplicate constructor call."
def _detect_explicitly_called_base_constructors(self, contract):
"""
Detects explicitly calls to base constructors with arguments in the inheritance hierarchy.
:param contract: The contract to detect explicit calls to a base constructor with arguments to.
:return: Dictionary of function:list(tuple): { constructor : [(invoking_contract, called_by_constructor]}
"""
results = dict()
# Create a set to track all completed contracts
processed_contracts = set()
queued_contracts = [contract] + contract.inheritance
# Loop until there are no queued contracts left.
while len(queued_contracts) > 0:
# Pop a contract off the front of the queue, if it has already been processed, we stop.
current_contract = queued_contracts.pop(0)
if current_contract in processed_contracts:
continue
# Add this contract to the processed contracts
processed_contracts.add(current_contract)
# Prior Solidity 0.4.22, the constructor would appear two times
# Leading to several FPs
# As the result, we might miss some TPs if the reused is due to the constructor called
# In the contract definition
if self.slither.solc_version >= "0.4.22":
# Find all base constructors explicitly called from the contract definition with arguments.
_add_constructors_with_args(
current_contract.explicit_base_constructor_calls,
False,
current_contract,
results,
)
# Find all base constructors explicitly called from the constructor definition with arguments.
if current_contract.constructors_declared:
_add_constructors_with_args(
current_contract.constructors_declared.explicit_base_constructor_calls,
True,
current_contract,
results,
)
return results
def _detect(self):
"""
Detect reused base constructors.
:return: Returns a list of JSON results.
"""
results = []
# The bug is not possible with solc >= 0.5.0
if not self.slither.solc_version.startswith("0.4."):
return []
# Loop for each contract
for contract in self.contracts:
# Detect all locations which all underlying base constructors with arguments were called from.
called_base_constructors = self._detect_explicitly_called_base_constructors(contract)
for base_constructor, call_list in called_base_constructors.items():
# Only report if there are multiple calls to the same base constructor.
if len(call_list) <= 1:
continue
# Generate data to output.
info = [
contract,
" gives base constructor ",
base_constructor,
" arguments more than once in inheritance hierarchy:\n",
]
for (calling_contract, called_by_constructor) in call_list:
info += [
"\t- From ",
calling_contract,
f" {'constructor' if called_by_constructor else 'contract'} definition\n",
]
res = self.generate_result(info)
results.append(res)
return results

@ -0,0 +1,150 @@
"""
Module detecting ABIEncoderV2 array bug
"""
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.core.solidity_types import ArrayType
from slither.core.solidity_types import UserDefinedType
from slither.core.variables.local_variable import LocalVariable
from slither.core.variables.state_variable import StateVariable
from slither.slithir.operations import SolidityCall
from slither.core.declarations.solidity_variables import SolidityFunction
from slither.slithir.operations import EventCall
from slither.slithir.operations import HighLevelCall
from slither.utils.utils import unroll
vulnerable_solc_versions = [
"0.4.7",
"0.4.8",
"0.4.9",
"0.4.10",
"0.4.11",
"0.4.12",
"0.4.13",
"0.4.14",
"0.4.15",
"0.4.16",
"0.4.17",
"0.4.18",
"0.4.19",
"0.4.20",
"0.4.21",
"0.4.22",
"0.4.23",
"0.4.24",
"0.4.25",
"0.5.0",
"0.5.1",
"0.5.2",
"0.5.3",
"0.5.4",
"0.5.5",
"0.5.6",
"0.5.7",
"0.5.8",
"0.5.9",
"0.5.10",
]
class ABIEncoderV2Array(AbstractDetector):
"""
Detects Storage ABIEncoderV2 array bug
"""
ARGUMENT = "abiencoderv2-array"
HELP = "Storage abiencoderv2 array"
IMPACT = DetectorClassification.HIGH
CONFIDENCE = DetectorClassification.HIGH
WIKI = (
"https://github.com/crytic/slither/wiki/Detector-Documentation#storage-abiencoderv2-array"
)
WIKI_TITLE = "Storage ABIEncoderV2 Array"
WIKI_DESCRIPTION = """`solc` versions `0.4.7`-`0.5.10` contain a [compiler bug](https://blog.ethereum.org/2019/06/25/solidity-storage-array-bugs.) leading to incorrect ABI encoder usage."""
WIKI_EXPLOIT_SCENARIO = """
```solidity
contract A {
uint[2][3] bad_arr = [[1, 2], [3, 4], [5, 6]];
/* Array of arrays passed to abi.encode is vulnerable */
function bad() public {
bytes memory b = abi.encode(bad_arr);
}
}
```
`abi.encode(bad_arr)` in a call to `bad()` will incorrectly encode the array as `[[1, 2], [2, 3], [3, 4]]` and lead to unintended behavior.
"""
WIKI_RECOMMENDATION = "Use a compiler >= `0.5.10`."
@staticmethod
def _detect_storage_abiencoderv2_arrays(contract):
"""
Detects and returns all nodes with storage-allocated abiencoderv2 arrays of arrays/structs in abi.encode, events or external calls
:param contract: Contract to detect within
:return: A list of tuples with (function, node) where function node has storage-allocated abiencoderv2 arrays of arrays/structs
"""
# Create our result set.
results = set()
# Loop for each function and modifier.
# pylint: disable=too-many-nested-blocks
for function in contract.functions_and_modifiers_declared:
# Loop every node, looking for storage-allocated array of arrays/structs
# in arguments to abi.encode, events or external calls
for node in function.nodes:
for ir in node.irs:
# Call to abi.encode()
if (
isinstance(ir, SolidityCall)
and ir.function == SolidityFunction("abi.encode()")
or
# Call to emit event
# Call to external function
isinstance(ir, (EventCall, HighLevelCall))
):
for arg in unroll(ir.arguments):
# Check if arguments are storage allocated arrays of arrays/structs
if (
isinstance(arg.type, ArrayType)
# Storage allocated
and (
isinstance(arg, StateVariable)
or (isinstance(arg, LocalVariable) and arg.is_storage)
)
# Array of arrays or structs
and isinstance(arg.type.type, (ArrayType, UserDefinedType))
):
results.add((function, node))
break
# Return the resulting set of tuples
return results
def _detect(self):
"""
Detect ABIEncoderV2 array bug
"""
results = []
# Check if vulnerable solc versions are used
if self.slither.solc_version not in vulnerable_solc_versions:
return results
# Check if pragma experimental ABIEncoderV2 is used
if not any(
(p.directive[0] == "experimental" and p.directive[1] == "ABIEncoderV2")
for p in self.slither.pragma_directives
):
return results
# Check for storage-allocated abiencoderv2 arrays of arrays/structs
# in arguments of abi.encode, events or external calls
for contract in self.contracts:
storage_abiencoderv2_arrays = self._detect_storage_abiencoderv2_arrays(contract)
for function, node in storage_abiencoderv2_arrays:
info = ["Function ", function, " trigger an abi encoding bug:\n\t- ", node, "\n"]
res = self.generate_result(info)
results.append(res)
return results

@ -0,0 +1,147 @@
"""
Module detecting storage signed integer array bug
"""
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.core.cfg.node import NodeType
from slither.core.solidity_types import ArrayType
from slither.core.solidity_types.elementary_type import Int, ElementaryType
from slither.core.variables.local_variable import LocalVariable
from slither.core.variables.state_variable import StateVariable
from slither.slithir.operations.assignment import Assignment
from slither.slithir.operations.init_array import InitArray
vulnerable_solc_versions = [
"0.4.7",
"0.4.8",
"0.4.9",
"0.4.10",
"0.4.11",
"0.4.12",
"0.4.13",
"0.4.14",
"0.4.15",
"0.4.16",
"0.4.17",
"0.4.18",
"0.4.19",
"0.4.20",
"0.4.21",
"0.4.22",
"0.4.23",
"0.4.24",
"0.4.25",
"0.5.0",
"0.5.1",
"0.5.2",
"0.5.3",
"0.5.4",
"0.5.5",
"0.5.6",
"0.5.7",
"0.5.8",
"0.5.9",
"0.5.10",
]
class StorageSignedIntegerArray(AbstractDetector):
"""
Storage signed integer array
"""
ARGUMENT = "storage-array"
HELP = "Signed storage integer array compiler bug"
IMPACT = DetectorClassification.HIGH
CONFIDENCE = DetectorClassification.MEDIUM
WIKI = (
"https://github.com/crytic/slither/wiki/Detector-Documentation#storage-signed-integer-array"
)
WIKI_TITLE = "Storage Signed Integer Array"
WIKI_DESCRIPTION = """`solc` versions `0.4.7`-`0.5.10` contain [a compiler bug](https://blog.ethereum.org/2019/06/25/solidity-storage-array-bugs)
leading to incorrect values in signed integer arrays."""
WIKI_EXPLOIT_SCENARIO = """
```solidity
contract A {
int[3] ether_balances; // storage signed integer array
function bad0() private {
// ...
ether_balances = [-1, -1, -1];
// ...
}
}
```
`bad0()` uses a (storage-allocated) signed integer array state variable to store the ether balances of three accounts.
`-1` is supposed to indicate uninitialized values but the Solidity bug makes these as `1`, which could be exploited by the accounts.
"""
WIKI_RECOMMENDATION = "Use a compiler version >= `0.5.10`."
@staticmethod
def _is_vulnerable_type(ir):
"""
Detect if the IR lvalue is a vulnerable type
Must be a storage allocation, and an array of Int
Assume the IR is a InitArray, or an Assignement to an ArrayType
"""
# Storage allocation
# Base type is signed integer
return (
(
isinstance(ir.lvalue, StateVariable)
or (isinstance(ir.lvalue, LocalVariable) and ir.lvalue.is_storage)
)
and isinstance(ir.lvalue.type.type, ElementaryType)
and ir.lvalue.type.type.type in Int
)
def detect_storage_signed_integer_arrays(self, contract):
"""
Detects and returns all nodes with storage-allocated signed integer array init/assignment
:param contract: Contract to detect within
:return: A list of tuples with (function, node) where function node has storage-allocated signed integer array init/assignment
"""
# Create our result set.
results = set()
# Loop for each function and modifier.
for function in contract.functions_and_modifiers_declared:
# Loop for every node in this function, looking for storage-allocated
# signed integer array initializations/assignments
for node in function.nodes:
if node.type == NodeType.EXPRESSION:
for ir in node.irs:
# Storage-allocated signed integer array initialization expression
if isinstance(ir, InitArray) and self._is_vulnerable_type(ir):
results.add((function, node))
# Assignment expression with lvalue being a storage-allocated signed integer array and
# rvalue being a signed integer array of different base type than lvalue
if (
isinstance(ir, Assignment)
and isinstance(ir.lvalue.type, ArrayType)
and self._is_vulnerable_type(ir)
# Base type is signed integer and lvalue base type is different from rvalue base type
and ir.lvalue.type.type != ir.rvalue.type.type
):
results.add((function, node))
# Return the resulting set of tuples
return results
def _detect(self):
"""
Detect storage signed integer array init/assignment
"""
results = []
if self.slither.solc_version not in vulnerable_solc_versions:
return results
for contract in self.contracts:
storage_signed_integer_arrays = self.detect_storage_signed_integer_arrays(contract)
for function, node in storage_signed_integer_arrays:
contract_info = ["Contract ", contract, " \n"]
function_info = ["\t- Function ", function, "\n"]
node_info = ["\t\t- ", node, " has a storage signed integer array assignment\n"]
res = self.generate_result(contract_info + function_info + node_info)
results.append(res)
return results

@ -0,0 +1,149 @@
"""
Module detecting uninitialized function pointer calls in constructors
"""
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations import InternalDynamicCall, OperationWithLValue
from slither.slithir.variables import ReferenceVariable
from slither.slithir.variables.variable import SlithIRVariable
vulnerable_solc_versions = [
"0.4.5",
"0.4.6",
"0.4.7",
"0.4.8",
"0.4.9",
"0.4.10",
"0.4.11",
"0.4.12",
"0.4.13",
"0.4.14",
"0.4.15",
"0.4.16",
"0.4.17",
"0.4.18",
"0.4.19",
"0.4.20",
"0.4.21",
"0.4.22",
"0.4.23",
"0.4.24",
"0.4.25",
"0.5.0",
"0.5.1",
"0.5.2",
"0.5.3",
"0.5.4",
"0.5.5",
"0.5.6",
"0.5.7",
"0.5.8",
]
def _get_variables_entrance(function):
"""
Return the first SSA variables of the function
Catpure the phi operation at the entry point
"""
ret = []
if function.entry_point:
for ir_ssa in function.entry_point.irs_ssa:
if isinstance(ir_ssa, OperationWithLValue):
ret.append(ir_ssa.lvalue)
return ret
def _is_vulnerable(node, variables_entrance):
"""
Vulnerable if an IR ssa:
- It is an internal dynamic call
- The destination has not an index of 0
- The destination is not in the allowed variable
"""
for ir_ssa in node.irs_ssa:
if isinstance(ir_ssa, InternalDynamicCall):
destination = ir_ssa.function
# If it is a reference variable, destination should be the origin variable
# Note: this will create FN if one of the field of a structure is updated, while not begin
# the field of the function pointer. This should be fixed once we have the IR refactoring
if isinstance(destination, ReferenceVariable):
destination = destination.points_to_origin
if isinstance(destination, SlithIRVariable) and ir_ssa.function.index == 0:
return True
if destination in variables_entrance:
return True
return False
class UninitializedFunctionPtrsConstructor(AbstractDetector):
"""
Uninitialized function pointer calls in constructors
"""
ARGUMENT = "uninitialized-fptr-cst"
HELP = "Uninitialized function pointer calls in constructors"
IMPACT = DetectorClassification.LOW
CONFIDENCE = DetectorClassification.HIGH
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-function-pointers-in-constructors"
WIKI_TITLE = "Uninitialized function pointers in constructors"
WIKI_DESCRIPTION = "solc versions `0.4.5`-`0.4.26` and `0.5.0`-`0.5.8` contain a compiler bug leading to unexpected behavior when calling uninitialized function pointers in constructors."
WIKI_EXPLOIT_SCENARIO = """
```solidity
contract bad0 {
constructor() public {
/* Uninitialized function pointer */
function(uint256) internal returns(uint256) a;
a(10);
}
}
```
The call to `a(10)` will lead to unexpected behavior because function pointer `a` is not initialized in the constructor."""
WIKI_RECOMMENDATION = (
"Initialize function pointers before calling. Avoid function pointers if possible."
)
@staticmethod
def _detect_uninitialized_function_ptr_in_constructor(contract):
"""
Detect uninitialized function pointer calls in constructors
:param contract: The contract of interest for detection
:return: A list of nodes with uninitialized function pointer calls in the constructor of given contract
"""
results = []
constructor = contract.constructors_declared
if constructor:
variables_entrance = _get_variables_entrance(constructor)
results = [
node for node in constructor.nodes if _is_vulnerable(node, variables_entrance)
]
return results
def _detect(self):
"""
Detect uninitialized function pointer calls in constructors of contracts
Returns:
list: ['uninitialized function pointer calls in constructors']
"""
results = []
# Check if vulnerable solc versions are used
if self.slither.solc_version not in vulnerable_solc_versions:
return results
for contract in self.slither.contracts:
contract_info = ["Contract ", contract, " \n"]
nodes = self._detect_uninitialized_function_ptr_in_constructor(contract)
for node in nodes:
node_info = [
"\t ",
node,
" is an unintialized function pointer call in a constructor\n",
]
json = self.generate_result(contract_info + node_info)
results.append(json)
return results

@ -0,0 +1,105 @@
"""
Module detecting unimplemented functions
Recursively check the called functions
Collect all the implemented and unimplemented functions of all the contracts
Check for unimplemented functions that are never implemented
Consider public state variables as implemented functions
Do not consider fallback function or constructor
"""
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
# Since 0.5.1, Solidity allows creating state variable matching a function signature.
older_solc_versions = ["0.5.0"] + ["0.4." + str(x) for x in range(0, 27)]
class UnimplementedFunctionDetection(AbstractDetector):
"""
Unimplemented functions detector
"""
ARGUMENT = "unimplemented-functions"
HELP = "Unimplemented functions"
IMPACT = DetectorClassification.INFORMATIONAL
CONFIDENCE = DetectorClassification.HIGH
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#unimplemented-functions"
WIKI_TITLE = "Unimplemented functions"
WIKI_DESCRIPTION = "Detect functions that are not implemented on derived-most contracts."
WIKI_EXPLOIT_SCENARIO = """
```solidity
interface BaseInterface {
function f1() external returns(uint);
function f2() external returns(uint);
}
interface BaseInterface2 {
function f3() external returns(uint);
}
contract DerivedContract is BaseInterface, BaseInterface2 {
function f1() external returns(uint){
return 42;
}
}
```
`DerivedContract` does not implement `BaseInterface.f2` or `BaseInterface2.f3`.
As a result, the contract will not properly compile.
All unimplemented functions must be implemented on a contract that is meant to be used."""
WIKI_RECOMMENDATION = "Implement all unimplemented functions in any contract you intend to use directly (not simply inherit from)."
@staticmethod
def _match_state_variable(contract, f):
return any(s.full_name == f.full_name for s in contract.state_variables)
def _detect_unimplemented_function(self, contract):
"""
Detects any function definitions which are not implemented in the given contract.
:param contract: The contract to search unimplemented functions for.
:return: A list of functions which are not implemented.
"""
# If it's simply a contract signature, we have no functions.
if contract.is_signature_only():
return set()
# Populate our unimplemented functions set with any functions not implemented in this contract, excluding the
# fallback function and constructor.
unimplemented = set()
for f in contract.all_functions_called:
if (
not f.is_implemented
and not f.is_constructor
and not f.is_fallback
and not f.is_constructor_variables
):
if self.slither.solc_version not in older_solc_versions:
# Since 0.5.1, Solidity allows creating state variable matching a function signature
if not self._match_state_variable(contract, f):
unimplemented.add(f)
else:
unimplemented.add(f)
return unimplemented
def _detect(self):
"""Detect unimplemented functions
Recursively visit the calls
Returns:
list: {'vuln', 'filename,'contract','func'}
"""
results = []
for contract in self.slither.contracts_derived:
functions = self._detect_unimplemented_function(contract)
if functions:
info = [contract, " does not implement functions:\n"]
for function in sorted(functions, key=lambda x: x.full_name):
info += ["\t- ", function, "\n"]
res = self.generate_result(info)
results.append(res)
return results

@ -0,0 +1,122 @@
"""
Module detecting bad PRNG due to the use of block.timestamp, now or blockhash (block.blockhash) as a source of randomness
"""
from slither.analyses.data_dependency.data_dependency import is_dependent_ssa
from slither.core.declarations.solidity_variables import (
SolidityVariable,
SolidityFunction,
SolidityVariableComposed,
)
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations import BinaryType, Binary
from slither.slithir.operations import SolidityCall
def collect_return_values_of_bad_PRNG_functions(f):
"""
Return the return-values of calls to blockhash()
Args:
f (Function)
Returns:
list(values)
"""
values_returned = []
for n in f.nodes:
for ir in n.irs_ssa:
if (
isinstance(ir, SolidityCall)
and ir.function == SolidityFunction("blockhash(uint256)")
and ir.lvalue
):
values_returned.append(ir.lvalue)
return values_returned
def contains_bad_PRNG_sources(func, blockhash_ret_values):
"""
Check if any node in function has a modulus operator and the first operand is dependent on block.timestamp, now or blockhash()
Returns:
(nodes)
"""
ret = set()
# pylint: disable=too-many-nested-blocks
for node in func.nodes:
for ir in node.irs_ssa:
if isinstance(ir, Binary) and ir.type == BinaryType.MODULO:
if is_dependent_ssa(
ir.variable_left, SolidityVariableComposed("block.timestamp"), func.contract
) or is_dependent_ssa(ir.variable_left, SolidityVariable("now"), func.contract):
ret.add(node)
break
for ret_val in blockhash_ret_values:
if is_dependent_ssa(ir.variable_left, ret_val, func.contract):
ret.add(node)
break
return list(ret)
def detect_bad_PRNG(contract):
"""
Args:
contract (Contract)
Returns:
list((Function), (list (Node)))
"""
blockhash_ret_values = []
for f in contract.functions:
blockhash_ret_values += collect_return_values_of_bad_PRNG_functions(f)
ret = []
for f in contract.functions:
bad_prng_nodes = contains_bad_PRNG_sources(f, blockhash_ret_values)
if bad_prng_nodes:
ret.append((f, bad_prng_nodes))
return ret
class BadPRNG(AbstractDetector):
"""
Detect weak PRNG due to a modulo operation on block.timestamp, now or blockhash
"""
ARGUMENT = "weak-prng"
HELP = "Weak PRNG"
IMPACT = DetectorClassification.HIGH
CONFIDENCE = DetectorClassification.MEDIUM
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#weak-PRNG"
WIKI_TITLE = "Weak PRNG"
WIKI_DESCRIPTION = "Weak PRNG due to a modulo on `block.timestamp`, `now` or `blockhash`. These can be influenced by miners to some extent so they should be avoided."
WIKI_EXPLOIT_SCENARIO = """
```solidity
contract Game {
uint reward_determining_number;
function guessing() external{
reward_determining_number = uint256(block.blockhash(10000)) % 10;
}
}
```
Eve is a miner. Eve calls `guessing` and re-orders the block containing the transaction.
As a result, Eve wins the game."""
WIKI_RECOMMENDATION = (
"Do not use `block.timestamp`, `now` or `blockhash` as a source of randomness"
)
def _detect(self):
"""Detect bad PRNG due to the use of block.timestamp, now or blockhash (block.blockhash) as a source of randomness"""
results = []
for c in self.slither.contracts_derived:
values = detect_bad_PRNG(c)
for func, nodes in values:
for node in nodes:
info = [func, ' uses a weak PRNG: "', node, '" \n']
res = self.generate_result(info)
results.append(res)
return results

@ -0,0 +1,118 @@
"""
Module detecting assignment of array length
"""
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.core.cfg.node import NodeType
from slither.slithir.operations import Assignment, Length
from slither.slithir.variables.reference import ReferenceVariable
from slither.slithir.operations.binary import Binary
from slither.analyses.data_dependency.data_dependency import is_tainted
def detect_array_length_assignment(contract):
"""
Detects and returns all nodes which assign array length.
:param contract: Contract to detect assignment within.
:return: A list of tuples with (Variable, node) where Variable references an array whose length was set by node.
"""
# Create our result set.
results = set()
# Loop for each function and modifier.
# pylint: disable=too-many-nested-blocks
for function in contract.functions_and_modifiers_declared:
# Define a set of reference variables which refer to array length.
array_length_refs = set()
# Loop for every node in this function, looking for expressions where array length references are made,
# and subsequent expressions where array length references are assigned to.
for node in function.nodes:
if node.type == NodeType.EXPRESSION:
for ir in node.irs:
# First we look for the member access for 'length', for which a reference is created.
# We add the reference to our list of array length references.
if isinstance(ir, Length): # a
# if ir.variable_right == "length":
array_length_refs.add(ir.lvalue)
# If we have an assignment/binary operation, verify the left side refers to a reference variable
# which is in our list or array length references. (Array length is being assigned to).
elif isinstance(ir, (Assignment, Binary)):
if isinstance(ir.lvalue, ReferenceVariable):
if ir.lvalue in array_length_refs and any(
is_tainted(v, contract) for v in ir.read
):
# the taint is not precise enough yet
# as a result, REF_0 = REF_0 + 1
# where REF_0 points to a LENGTH operation
# is considered as tainted
if ir.lvalue in ir.read:
continue
results.add(node)
break
# Return the resulting set of nodes which set array length.
return results
class ArrayLengthAssignment(AbstractDetector):
"""
Array length assignment
"""
ARGUMENT = "controlled-array-length"
HELP = "Tainted array length assignment"
IMPACT = DetectorClassification.HIGH
CONFIDENCE = DetectorClassification.MEDIUM
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#array-length-assignment"
WIKI_TITLE = "Array Length Assignment"
WIKI_DESCRIPTION = """Detects the direct assignment of an array's length."""
WIKI_EXPLOIT_SCENARIO = """
```solidity
contract A {
uint[] testArray; // dynamic size array
function f(uint usersCount) public {
// ...
testArray.length = usersCount;
// ...
}
function g(uint userIndex, uint val) public {
// ...
testArray[userIndex] = val;
// ...
}
}
```
Contract storage/state-variables are indexed by a 256-bit integer.
The user can set the array length to `2**256-1` in order to index all storage slots.
In the example above, one could call the function `f` to set the array length, then call the function `g` to control any storage slot desired.
Note that storage slots here are indexed via a hash of the indexers; nonetheless, all storage will still be accessible and could be controlled by the attacker."""
WIKI_RECOMMENDATION = """Do not allow array lengths to be set directly set; instead, opt to add values as needed.
Otherwise, thoroughly review the contract to ensure a user-controlled variable cannot reach an array length assignment."""
def _detect(self):
"""
Detect array length assignments
"""
results = []
for contract in self.contracts:
array_length_assignments = detect_array_length_assignment(contract)
if array_length_assignments:
contract_info = [
contract,
" contract sets array length with a user-controlled value:\n",
]
for node in array_length_assignments:
node_info = contract_info + ["\t- ", node, "\n"]
res = self.generate_result(node_info)
results.append(res)
return results

@ -0,0 +1,83 @@
"""
Module detecting state changes in assert calls
"""
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations.internal_call import InternalCall
def detect_assert_state_change(contract):
"""
Detects and returns all nodes with assert calls that change contract state from within the invariant
:param contract: Contract to detect
:return: A list of nodes with assert calls that change contract state from within the invariant
"""
# Create our result set.
# List of tuples (function, node)
results = []
# Loop for each function and modifier.
for function in contract.functions_declared + contract.modifiers_declared:
for node in function.nodes:
# Detect assert() calls
if any(c.name == "assert(bool)" for c in node.internal_calls) and (
# Detect direct changes to state
node.state_variables_written
or
# Detect changes to state via function calls
any(
ir
for ir in node.irs
if isinstance(ir, InternalCall) and ir.function.state_variables_written
)
):
results.append((function, node))
# Return the resulting set of nodes
return results
class AssertStateChange(AbstractDetector):
"""
Assert state change
"""
ARGUMENT = "assert-state-change"
HELP = "Assert state change"
IMPACT = DetectorClassification.INFORMATIONAL
CONFIDENCE = DetectorClassification.INFORMATIONAL
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#assert-state-change"
WIKI_TITLE = "Assert state shange"
WIKI_DESCRIPTION = """Incorrect use of `assert()`. See Solidity best [practices](https://solidity.readthedocs.io/en/latest/control-structures.html#id4)."""
WIKI_EXPLOIT_SCENARIO = """
```solidity
contract A {
uint s_a;
function bad() public {
assert((s_a += 1) > 10);
}
}
```
The assert in `bad()` increments the state variable `s_a` while checking for the condition.
"""
WIKI_RECOMMENDATION = """Use `require` for invariants modifying the state."""
def _detect(self):
"""
Detect assert calls that change state from within the invariant
"""
results = []
for contract in self.contracts:
assert_state_change = detect_assert_state_change(contract)
for (func, node) in assert_state_change:
info = [func, " has an assert() call which possibly changes state.\n"]
info += ["\t-", node, "\n"]
info += [
"Consider using require() or change the invariant to not modify the state.\n"
]
res = self.generate_result(info)
results.append(res)
return results

@ -0,0 +1,94 @@
from slither.core.cfg.node import NodeType
from slither.core.solidity_types.array_type import ArrayType
from slither.core.solidity_types.mapping_type import MappingType
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
class CostlyOperationsInLoop(AbstractDetector):
ARGUMENT = "costly-loop"
HELP = "Costly operations in a loop"
IMPACT = DetectorClassification.INFORMATIONAL
# Overall the detector seems precise, but it does not take into account
# case where there are external calls or internal calls that might read the state
# variable changes. In these cases the optimization should not be applied
CONFIDENCE = DetectorClassification.MEDIUM
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#costly-operations-inside-a-loop"
WIKI_TITLE = "Costly operations inside a loop"
WIKI_DESCRIPTION = (
"Costly operations inside a loop might waste gas, so optimizations are justified."
)
WIKI_EXPLOIT_SCENARIO = """
```solidity
contract CostlyOperationsInLoop{
uint loop_count = 100;
uint state_variable=0;
function bad() external{
for (uint i=0; i < loop_count; i++){
state_variable++;
}
}
function good() external{
uint local_variable = state_variable;
for (uint i=0; i < loop_count; i++){
local_variable++;
}
state_variable = local_variable;
}
}
```
Incrementing `state_variable` in a loop incurs a lot of gas because of expensive `SSTOREs`, which might lead to an `out-of-gas`."""
WIKI_RECOMMENDATION = "Use a local variable to hold the loop computation result."
@staticmethod
def costly_operations_in_loop(node, in_loop, visited, ret):
if node in visited:
return
# shared visited
visited.append(node)
if node.type == NodeType.STARTLOOP:
in_loop = True
elif node.type == NodeType.ENDLOOP:
in_loop = False
if in_loop:
sv_written = node.state_variables_written
for sv in sv_written:
# Ignore Array/Mapping/Struct types for now
if isinstance(sv.type, (ArrayType, MappingType)):
continue
ret.append(node)
break
for son in node.sons:
CostlyOperationsInLoop.costly_operations_in_loop(son, in_loop, visited, ret)
@staticmethod
def detect_costly_operations_in_loop(contract):
ret = []
for f in contract.functions + contract.modifiers:
if f.contract_declarer == contract and f.is_implemented:
CostlyOperationsInLoop.costly_operations_in_loop(f.entry_point, False, [], ret)
return ret
def _detect(self):
""""""
results = []
for c in self.slither.contracts_derived:
values = self.detect_costly_operations_in_loop(c)
for node in values:
func = node.function
info = [func, " has costly operations inside a loop:\n"]
info += ["\t- ", node, "\n"]
res = self.generate_result(info)
results.append(res)
return results

@ -0,0 +1,82 @@
"""
Detect deletion on structure containing a mapping
"""
from slither.core.declarations import Structure
from slither.core.solidity_types import MappingType, UserDefinedType
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations import Delete
class MappingDeletionDetection(AbstractDetector):
"""
Mapping deletion detector
"""
ARGUMENT = "mapping-deletion"
HELP = "Deletion on mapping containing a structure"
IMPACT = DetectorClassification.MEDIUM
CONFIDENCE = DetectorClassification.HIGH
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#deletion-on-mapping-containing-a-structure"
WIKI_TITLE = "Deletion on mapping containing a structure"
WIKI_DESCRIPTION = "A deletion in a structure containing a mapping will not delete the mapping (see the [Solidity documentation](https://solidity.readthedocs.io/en/latest/types.html##delete)). The remaining data may be used to compromise the contract."
WIKI_EXPLOIT_SCENARIO = """
```solidity
struct BalancesStruct{
address owner;
mapping(address => uint) balances;
}
mapping(address => BalancesStruct) public stackBalance;
function remove() internal{
delete stackBalance[msg.sender];
}
```
`remove` deletes an item of `stackBalance`.
The mapping `balances` is never deleted, so `remove` does not work as intended."""
WIKI_RECOMMENDATION = (
"Use a lock mechanism instead of a deletion to disable structure containing a mapping."
)
@staticmethod
def detect_mapping_deletion(contract):
"""Detect deletion on structure containing a mapping
Returns:
list (function, structure, node)
"""
ret = []
# pylint: disable=too-many-nested-blocks
for f in contract.functions:
for node in f.nodes:
for ir in node.irs:
if isinstance(ir, Delete):
value = ir.variable
if isinstance(value.type, UserDefinedType) and isinstance(
value.type.type, Structure
):
st = value.type.type
if any(isinstance(e.type, MappingType) for e in st.elems.values()):
ret.append((f, st, node))
return ret
def _detect(self):
"""Detect mapping deletion
Returns:
list: {'vuln', 'filename,'contract','func','struct''}
"""
results = []
for c in self.contracts:
mapping = MappingDeletionDetection.detect_mapping_deletion(c)
for (func, struct, node) in mapping:
info = [func, " deletes ", struct, " which contains a mapping:\n"]
info += ["\t-", node, "\n"]
res = self.generate_result(info)
results.append(res)
return results

@ -0,0 +1,88 @@
"""
Module detecting redundant statements.
"""
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.core.cfg.node import NodeType
from slither.core.expressions.elementary_type_name_expression import ElementaryTypeNameExpression
from slither.core.expressions.identifier import Identifier
class RedundantStatements(AbstractDetector):
"""
Use of Redundant Statements
"""
ARGUMENT = "redundant-statements"
HELP = "Redundant statements"
IMPACT = DetectorClassification.INFORMATIONAL
CONFIDENCE = DetectorClassification.HIGH
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#redundant-statements"
WIKI_TITLE = "Redundant Statements"
WIKI_DESCRIPTION = "Detect the usage of redundant statements that have no effect."
WIKI_EXPLOIT_SCENARIO = """
```solidity
contract RedundantStatementsContract {
constructor() public {
uint; // Elementary Type Name
bool; // Elementary Type Name
RedundantStatementsContract; // Identifier
}
function test() public returns (uint) {
uint; // Elementary Type Name
assert; // Identifier
test; // Identifier
return 777;
}
}
```
Each commented line references types/identifiers, but performs no action with them, so no code will be generated for such statements and they can be removed."""
WIKI_RECOMMENDATION = "Remove redundant statements if they congest code but offer no value."
# This is a disallowed list of tuple (node.type, type(node.expression))
REDUNDANT_TOP_LEVEL_EXPRESSIONS = (ElementaryTypeNameExpression, Identifier)
def detect_redundant_statements_contract(self, contract):
"""Detects the usage of redundant statements in a contract.
Returns:
list: nodes"""
results = []
# Loop through all functions + modifiers defined explicitly in this contract.
for function in contract.functions_and_modifiers_declared:
# Loop through each node in this function.
for node in function.nodes:
if node.expression:
if node.type == NodeType.EXPRESSION and isinstance(
node.expression, self.REDUNDANT_TOP_LEVEL_EXPRESSIONS
):
results.append(node)
return results
def _detect(self):
"""Detect redundant statements
Recursively visit the calls
Returns:
list: {'vuln', 'filename,'contract','func', 'redundant_statements'}
"""
results = []
for contract in self.contracts:
redundant_statements = self.detect_redundant_statements_contract(contract)
if redundant_statements:
for redundant_statement in redundant_statements:
info = ['Redundant expression "', redundant_statement, '" in', contract, "\n"]
json = self.generate_result(info)
results.append(json)
return results

@ -0,0 +1,107 @@
"""
Module detecting state variables initializing from an immediate function call (prior to constructor run).
"""
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.visitors.expression.export_values import ExportValues
from slither.core.declarations.function import Function
from slither.core.variables.state_variable import StateVariable
def detect_function_init_state_vars(contract):
"""
Detect any state variables that are initialized from an immediate function call (prior to constructor run).
:param contract: The contract to detect state variable definitions for.
:return: A list of all state variables defined in the given contract that meet the specified criteria.
"""
results = []
# Loop for each state variable explicitly defined in this contract.
for state_variable in contract.variables:
# Skip this variable if it is inherited and not explicitly defined in this contract definition.
if state_variable.contract != contract:
continue
# If it has an expression, we try to break it down to identify if it contains a function call, or reference
# to a non-constant state variable.
if state_variable.expression:
exported_values = ExportValues(state_variable.expression).result()
for exported_value in exported_values:
if (
isinstance(exported_value, StateVariable) and not exported_value.is_constant
) or (isinstance(exported_value, Function) and not exported_value.pure):
results.append(state_variable)
break
return results
class FunctionInitializedState(AbstractDetector):
"""
State variables initializing from an immediate function call (prior to constructor run).
"""
ARGUMENT = "function-init-state"
HELP = "Function initializing state variables"
IMPACT = DetectorClassification.INFORMATIONAL
CONFIDENCE = DetectorClassification.HIGH
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#function-initializing-state-variables"
WIKI_TITLE = "Function Initializing State"
WIKI_DESCRIPTION = "Detects the immediate initialization of state variables through function calls that are not pure/constant, or that use non-constant state variable."
WIKI_EXPLOIT_SCENARIO = """
```solidity
contract StateVarInitFromFunction {
uint public v = set(); // Initialize from function (sets to 77)
uint public w = 5;
uint public x = set(); // Initialize from function (sets to 88)
address public shouldntBeReported = address(8);
constructor(){
// The constructor is run after all state variables are initialized.
}
function set() public returns(uint) {
// If this function is being used to initialize a state variable declared
// before w, w will be zero. If it is declared after w, w will be set.
if(w == 0) {
return 77;
}
return 88;
}
}
```
In this case, users might intend a function to return a value a state variable can initialize with, without realizing the context for the contract is not fully initialized.
In the example above, the same function sets two different values for state variables because it checks a state variable that is not yet initialized in one case, and is initialized in the other.
Special care must be taken when initializing state variables from an immediate function call so as not to incorrectly assume the state is initialized.
"""
WIKI_RECOMMENDATION = "Remove any initialization of state variables via non-constant state variables or function calls. If variables must be set upon contract deployment, locate initialization in the constructor instead."
def _detect(self):
"""
Detect state variables defined from an immediate function call (pre-contract deployment).
Recursively visit the calls
Returns:
list: {'vuln', 'filename,'contract','func', 'shadow'}
"""
results = []
for contract in self.contracts:
state_variables = detect_function_init_state_vars(contract)
if state_variables:
for state_variable in state_variables:
info = [
state_variable,
" is set pre-construction with a non-constant function or state variable:\n",
]
info += [f"\t- {state_variable.expression}\n"]
json = self.generate_result(info)
results.append(json)
return results

@ -0,0 +1,86 @@
"""
Check for state variables too similar
Do not check contract inheritance
"""
import difflib
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
class SimilarVarsDetection(AbstractDetector):
"""
Variable similar detector
"""
ARGUMENT = "similar-names"
HELP = "Variable names are too similar"
IMPACT = DetectorClassification.INFORMATIONAL
CONFIDENCE = DetectorClassification.MEDIUM
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#variable-names-are-too-similar"
WIKI_TITLE = "Variable names too similar"
WIKI_DESCRIPTION = "Detect variables with names that are too similar."
WIKI_EXPLOIT_SCENARIO = "Bob uses several variables with similar names. As a result, his code is difficult to review."
WIKI_RECOMMENDATION = "Prevent variables from having similar names."
@staticmethod
def similar(seq1, seq2):
"""Test the name similarity
Two name are similar if difflib.SequenceMatcher on the lowercase
version of the name is greater than 0.90
See: https://docs.python.org/2/library/difflib.html
Args:
seq1 (str): first name
seq2 (str): second name
Returns:
bool: true if names are similar
"""
if len(seq1) != len(seq2):
return False
val = difflib.SequenceMatcher(a=seq1.lower(), b=seq2.lower()).ratio()
ret = val > 0.90
return ret
@staticmethod
def detect_sim(contract):
"""Detect variables with similar name
Returns:
bool: true if variables have similar name
"""
all_var = [x.variables for x in contract.functions]
all_var = [x for l in all_var for x in l]
contract_var = contract.variables
all_var = set(all_var + contract_var)
ret = []
for v1 in all_var:
for v2 in all_var:
if v1.name.lower() != v2.name.lower():
if SimilarVarsDetection.similar(v1.name, v2.name):
if (v2, v1) not in ret:
ret.append((v1, v2))
return set(ret)
def _detect(self):
"""Detect similar variables name
Returns:
list: {'vuln', 'filename,'contract','vars'}
"""
results = []
for c in self.contracts:
allVars = self.detect_sim(c)
if allVars:
for (v1, v2) in sorted(allVars, key=lambda x: (x[0].name, x[1].name)):
v_left = v1 if v1.name < v2.name else v2
v_right = v2 if v_left == v1 else v1
info = ["Variable ", v_left, " is too similar to ", v_right, "\n"]
json = self.generate_result(info)
results.append(json)
return results

@ -0,0 +1,99 @@
pragma experimental ABIEncoderV2;
contract A {
struct S {
uint i;
}
uint[2][3] bad_arr = [[1, 2], [3, 4], [5, 6]];
uint[3] good_arr = [1, 2, 3];
S[3] s;
event event1_bad(uint[2][3] bad_arr);
event event1_good(uint[3] good_arr);
event event2_bad(S[3] s);
function bad0_external(uint [2][3] arr1) external {
}
/* Array of arrays passed to an external function is vulnerable */
function bad0() public {
this.bad0_external(bad_arr);
}
function bad1_external (S[3] s1) external {
}
/* Array of structs passed to an external function is vulnerable */
function bad1 (S[3] s1) public {
this.bad1_external(s);
}
/* Array of arrays passed to abi.encode is vulnerable */
function bad2() public {
bytes memory b = abi.encode(bad_arr);
}
/* Array of structs passed to abi.encode is vulnerable */
function bad3() public {
bytes memory b = abi.encode(s);
}
/* Array of arrays passed to an event emit is vulnerable */
function bad4() public {
emit event1_bad(bad_arr);
}
/* Array of structs passed to an event emit is vulnerable */
function bad5() public {
emit event2_bad(s);
}
function good0_public (uint[2][3] arr1) public {
}
/* Array of arrays passed to a public function is benign */
function good0() public {
good0_public(bad_arr);
}
function good1_public (S[3] s1) public {
}
/* Array of structs passed to a public function is benign */
function good1 (S[3] s1) {
good1_public(s);
}
/* Array of arrays in-memory passed to abi.encode is benign */
function good2() public {
uint8 [2][3] memory bad_arr_mem = [[1, 2], [3, 4], [5, 6]];
bytes memory b = abi.encode(bad_arr_mem);
}
/* Array of structs in-memory passed to abi.encode is benign */
function good3() public {
S[3] memory s_mem;
bytes memory b = abi.encode(s_mem);
}
function good4_external(uint[3] arr1) external {
}
/* Array of elementary types passed to external function is benign */
function good4() public {
this.good4_external(good_arr);
}
/* Array of elementary types passed to abi.encode is benign */
function good5() public {
bytes memory b = abi.encode(good_arr);
}
/* Array of elementary types passed to event emit is benign */
function good6() public {
emit event1_good(good_arr);
}
}

@ -0,0 +1,51 @@
contract C {
uint[1] public x;
function f() public {
setByRef(x); // can set x.
setByValue(x); // cannot set x.
uint test = 1 + setByValueAndReturn(x); // cannot set x.
}
function g() public {
uint[1] storage y = x;
setByRef(y); // can set y.
setByValue(y); // cannot set y.
uint test = 1 + setByValueAndReturn(y); // cannot set y.
}
function setByRef(uint[1] storage arr) internal {
arr[0] = 1;
}
function setByValue(uint[1] arr) public {
arr[0] = 2;
}
function setByValueAndReturn(uint[1] arr) public returns(uint) {
arr[0] = 2;
return arr[0];
}
}
contract D {
// Struct definition
struct TestStruct {
uint[1] x;
}
// State Variables
TestStruct ts;
uint[1] x;
// Functions
function f() public {
C c = new C();
c.setByValue(ts.x); // cannot set x.
uint test = 1 + c.setByValueAndReturn(ts.x); // cannot set x.
c.setByValue(x); // cannot set x.
test = 1 + c.setByValueAndReturn(x); // cannot set x.
}
}

@ -0,0 +1,39 @@
contract A {
uint s_a;
/* Direct state change in assert is NOT ok */
function bad0() public {
assert((s_a += 1) > 10);
}
/* Direct state change in assert is NOT ok */
function bad1(uint256 a) public {
assert((s_a += a) > 10);
}
/* State change via functions calls in assert is NOT ok */
function bad2_callee() public returns (bool) {
return (s_a += 1) > 10;
}
function bad2() public {
assert(bad2_callee());
}
/* Parameter use is ok */
function good0(uint256 a) public {
assert(a > 10);
}
/* Parameter change is ok */
function good1(uint256 a) public {
assert((a += 1) > 10);
}
/* State change in require is ok */
function good2(uint256 a) public {
require(a == (s_a += 1));
}
}

@ -0,0 +1,568 @@
[
[
{
"elements": [
{
"type": "function",
"name": "bad0",
"source_mapping": {
"start": 77,
"length": 57,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol",
"is_dependency": false,
"lines": [
6,
7,
8
],
"starting_column": 3,
"ending_column": 4
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "A",
"source_mapping": {
"start": 0,
"length": 759,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol",
"is_dependency": false,
"lines": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "bad0()"
}
},
{
"type": "node",
"name": "assert(bool)((s_a += 1) > 10)",
"source_mapping": {
"start": 106,
"length": 23,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol",
"is_dependency": false,
"lines": [
7
],
"starting_column": 5,
"ending_column": 28
},
"type_specific_fields": {
"parent": {
"type": "function",
"name": "bad0",
"source_mapping": {
"start": 77,
"length": 57,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol",
"is_dependency": false,
"lines": [
6,
7,
8
],
"starting_column": 3,
"ending_column": 4
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "A",
"source_mapping": {
"start": 0,
"length": 759,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol",
"is_dependency": false,
"lines": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "bad0()"
}
}
}
}
],
"description": "A.bad0() (tests/detectors/assert-state-change/assert_state_change.sol#6-8) has an assert() call which possibly changes state.\n\t-assert(bool)((s_a += 1) > 10) (tests/detectors/assert-state-change/assert_state_change.sol#7)\nConsider using require() or change the invariant to not modify the state.\n",
"markdown": "[A.bad0()](tests/detectors/assert-state-change/assert_state_change.sol#L6-L8) has an assert() call which possibly changes state.\n\t-[assert(bool)((s_a += 1) > 10)](tests/detectors/assert-state-change/assert_state_change.sol#L7)\nConsider using require() or change the invariant to not modify the state.\n",
"id": "a4f5ea904ad28f8c83aa1bab8284b485e1fe638545b500ca0c8a0fa8e442203e",
"check": "assert-state-change",
"impact": "Informational",
"confidence": "Informational"
},
{
"elements": [
{
"type": "function",
"name": "bad1",
"source_mapping": {
"start": 186,
"length": 66,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol",
"is_dependency": false,
"lines": [
11,
12,
13
],
"starting_column": 3,
"ending_column": 4
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "A",
"source_mapping": {
"start": 0,
"length": 759,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol",
"is_dependency": false,
"lines": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "bad1(uint256)"
}
},
{
"type": "node",
"name": "assert(bool)((s_a += a) > 10)",
"source_mapping": {
"start": 224,
"length": 23,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol",
"is_dependency": false,
"lines": [
12
],
"starting_column": 5,
"ending_column": 28
},
"type_specific_fields": {
"parent": {
"type": "function",
"name": "bad1",
"source_mapping": {
"start": 186,
"length": 66,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol",
"is_dependency": false,
"lines": [
11,
12,
13
],
"starting_column": 3,
"ending_column": 4
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "A",
"source_mapping": {
"start": 0,
"length": 759,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol",
"is_dependency": false,
"lines": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "bad1(uint256)"
}
}
}
}
],
"description": "A.bad1(uint256) (tests/detectors/assert-state-change/assert_state_change.sol#11-13) has an assert() call which possibly changes state.\n\t-assert(bool)((s_a += a) > 10) (tests/detectors/assert-state-change/assert_state_change.sol#12)\nConsider using require() or change the invariant to not modify the state.\n",
"markdown": "[A.bad1(uint256)](tests/detectors/assert-state-change/assert_state_change.sol#L11-L13) has an assert() call which possibly changes state.\n\t-[assert(bool)((s_a += a) > 10)](tests/detectors/assert-state-change/assert_state_change.sol#L12)\nConsider using require() or change the invariant to not modify the state.\n",
"id": "2b42e9f701ebd94656a026702bf90f31c62710a301600e0c05cfed04bfefabf9",
"check": "assert-state-change",
"impact": "Informational",
"confidence": "Informational"
},
{
"elements": [
{
"type": "function",
"name": "bad2",
"source_mapping": {
"start": 398,
"length": 55,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol",
"is_dependency": false,
"lines": [
19,
20,
21
],
"starting_column": 3,
"ending_column": 4
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "A",
"source_mapping": {
"start": 0,
"length": 759,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol",
"is_dependency": false,
"lines": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "bad2()"
}
},
{
"type": "node",
"name": "assert(bool)(bad2_callee())",
"source_mapping": {
"start": 427,
"length": 21,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol",
"is_dependency": false,
"lines": [
20
],
"starting_column": 5,
"ending_column": 26
},
"type_specific_fields": {
"parent": {
"type": "function",
"name": "bad2",
"source_mapping": {
"start": 398,
"length": 55,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol",
"is_dependency": false,
"lines": [
19,
20,
21
],
"starting_column": 3,
"ending_column": 4
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "A",
"source_mapping": {
"start": 0,
"length": 759,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol",
"is_dependency": false,
"lines": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "bad2()"
}
}
}
}
],
"description": "A.bad2() (tests/detectors/assert-state-change/assert_state_change.sol#19-21) has an assert() call which possibly changes state.\n\t-assert(bool)(bad2_callee()) (tests/detectors/assert-state-change/assert_state_change.sol#20)\nConsider using require() or change the invariant to not modify the state.\n",
"markdown": "[A.bad2()](tests/detectors/assert-state-change/assert_state_change.sol#L19-L21) has an assert() call which possibly changes state.\n\t-[assert(bool)(bad2_callee())](tests/detectors/assert-state-change/assert_state_change.sol#L20)\nConsider using require() or change the invariant to not modify the state.\n",
"id": "a72f3e7eef408be55123fbf5c290bfd20aed4f095d659f5df0857d64d61df011",
"check": "assert-state-change",
"impact": "Informational",
"confidence": "Informational"
}
]
]

@ -0,0 +1,568 @@
[
[
{
"elements": [
{
"type": "function",
"name": "bad0",
"source_mapping": {
"start": 77,
"length": 57,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol",
"is_dependency": false,
"lines": [
6,
7,
8
],
"starting_column": 3,
"ending_column": 4
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "A",
"source_mapping": {
"start": 0,
"length": 759,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol",
"is_dependency": false,
"lines": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "bad0()"
}
},
{
"type": "node",
"name": "assert(bool)((s_a += 1) > 10)",
"source_mapping": {
"start": 106,
"length": 23,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol",
"is_dependency": false,
"lines": [
7
],
"starting_column": 5,
"ending_column": 28
},
"type_specific_fields": {
"parent": {
"type": "function",
"name": "bad0",
"source_mapping": {
"start": 77,
"length": 57,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol",
"is_dependency": false,
"lines": [
6,
7,
8
],
"starting_column": 3,
"ending_column": 4
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "A",
"source_mapping": {
"start": 0,
"length": 759,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol",
"is_dependency": false,
"lines": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "bad0()"
}
}
}
}
],
"description": "A.bad0() (tests/detectors/assert-state-change/assert_state_change.sol#6-8) has an assert() call which possibly changes state.\n\t-assert(bool)((s_a += 1) > 10) (tests/detectors/assert-state-change/assert_state_change.sol#7)\nConsider using require() or change the invariant to not modify the state.\n",
"markdown": "[A.bad0()](tests/detectors/assert-state-change/assert_state_change.sol#L6-L8) has an assert() call which possibly changes state.\n\t-[assert(bool)((s_a += 1) > 10)](tests/detectors/assert-state-change/assert_state_change.sol#L7)\nConsider using require() or change the invariant to not modify the state.\n",
"id": "a4f5ea904ad28f8c83aa1bab8284b485e1fe638545b500ca0c8a0fa8e442203e",
"check": "assert-state-change",
"impact": "Informational",
"confidence": "Informational"
},
{
"elements": [
{
"type": "function",
"name": "bad1",
"source_mapping": {
"start": 186,
"length": 66,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol",
"is_dependency": false,
"lines": [
11,
12,
13
],
"starting_column": 3,
"ending_column": 4
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "A",
"source_mapping": {
"start": 0,
"length": 759,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol",
"is_dependency": false,
"lines": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "bad1(uint256)"
}
},
{
"type": "node",
"name": "assert(bool)((s_a += a) > 10)",
"source_mapping": {
"start": 224,
"length": 23,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol",
"is_dependency": false,
"lines": [
12
],
"starting_column": 5,
"ending_column": 28
},
"type_specific_fields": {
"parent": {
"type": "function",
"name": "bad1",
"source_mapping": {
"start": 186,
"length": 66,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol",
"is_dependency": false,
"lines": [
11,
12,
13
],
"starting_column": 3,
"ending_column": 4
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "A",
"source_mapping": {
"start": 0,
"length": 759,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol",
"is_dependency": false,
"lines": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "bad1(uint256)"
}
}
}
}
],
"description": "A.bad1(uint256) (tests/detectors/assert-state-change/assert_state_change.sol#11-13) has an assert() call which possibly changes state.\n\t-assert(bool)((s_a += a) > 10) (tests/detectors/assert-state-change/assert_state_change.sol#12)\nConsider using require() or change the invariant to not modify the state.\n",
"markdown": "[A.bad1(uint256)](tests/detectors/assert-state-change/assert_state_change.sol#L11-L13) has an assert() call which possibly changes state.\n\t-[assert(bool)((s_a += a) > 10)](tests/detectors/assert-state-change/assert_state_change.sol#L12)\nConsider using require() or change the invariant to not modify the state.\n",
"id": "2b42e9f701ebd94656a026702bf90f31c62710a301600e0c05cfed04bfefabf9",
"check": "assert-state-change",
"impact": "Informational",
"confidence": "Informational"
},
{
"elements": [
{
"type": "function",
"name": "bad2",
"source_mapping": {
"start": 398,
"length": 55,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol",
"is_dependency": false,
"lines": [
19,
20,
21
],
"starting_column": 3,
"ending_column": 4
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "A",
"source_mapping": {
"start": 0,
"length": 759,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol",
"is_dependency": false,
"lines": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "bad2()"
}
},
{
"type": "node",
"name": "assert(bool)(bad2_callee())",
"source_mapping": {
"start": 427,
"length": 21,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol",
"is_dependency": false,
"lines": [
20
],
"starting_column": 5,
"ending_column": 26
},
"type_specific_fields": {
"parent": {
"type": "function",
"name": "bad2",
"source_mapping": {
"start": 398,
"length": 55,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol",
"is_dependency": false,
"lines": [
19,
20,
21
],
"starting_column": 3,
"ending_column": 4
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "A",
"source_mapping": {
"start": 0,
"length": 759,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol",
"is_dependency": false,
"lines": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "bad2()"
}
}
}
}
],
"description": "A.bad2() (tests/detectors/assert-state-change/assert_state_change.sol#19-21) has an assert() call which possibly changes state.\n\t-assert(bool)(bad2_callee()) (tests/detectors/assert-state-change/assert_state_change.sol#20)\nConsider using require() or change the invariant to not modify the state.\n",
"markdown": "[A.bad2()](tests/detectors/assert-state-change/assert_state_change.sol#L19-L21) has an assert() call which possibly changes state.\n\t-[assert(bool)(bad2_callee())](tests/detectors/assert-state-change/assert_state_change.sol#L20)\nConsider using require() or change the invariant to not modify the state.\n",
"id": "a72f3e7eef408be55123fbf5c290bfd20aed4f095d659f5df0857d64d61df011",
"check": "assert-state-change",
"impact": "Informational",
"confidence": "Informational"
}
]
]

@ -0,0 +1,168 @@
[
[
{
"elements": [
{
"type": "function",
"name": "bad1",
"source_mapping": {
"start": 134,
"length": 84,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/boolean-equality/boolean-equality.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/boolean-equality/boolean-equality.sol",
"is_dependency": false,
"lines": [
8,
9,
10
],
"starting_column": 5,
"ending_column": 6
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "MyConc",
"source_mapping": {
"start": 0,
"length": 573,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/boolean-equality/boolean-equality.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/boolean-equality/boolean-equality.sol",
"is_dependency": false,
"lines": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "bad1(bool)"
}
},
{
"type": "node",
"name": "(b == true)",
"source_mapping": {
"start": 193,
"length": 18,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/boolean-equality/boolean-equality.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/boolean-equality/boolean-equality.sol",
"is_dependency": false,
"lines": [
9
],
"starting_column": 9,
"ending_column": 27
},
"type_specific_fields": {
"parent": {
"type": "function",
"name": "bad1",
"source_mapping": {
"start": 134,
"length": 84,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/boolean-equality/boolean-equality.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/boolean-equality/boolean-equality.sol",
"is_dependency": false,
"lines": [
8,
9,
10
],
"starting_column": 5,
"ending_column": 6
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "MyConc",
"source_mapping": {
"start": 0,
"length": 573,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/boolean-equality/boolean-equality.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/boolean-equality/boolean-equality.sol",
"is_dependency": false,
"lines": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "bad1(bool)"
}
}
}
}
],
"description": "MyConc.bad1(bool) (tests/detectors/boolean-equality/boolean-equality.sol#8-10) compares to a boolean constant:\n\t-(b == true) (tests/detectors/boolean-equality/boolean-equality.sol#9)\n",
"markdown": "[MyConc.bad1(bool)](tests/detectors/boolean-equality/boolean-equality.sol#L8-L10) compares to a boolean constant:\n\t-[(b == true)](tests/detectors/boolean-equality/boolean-equality.sol#L9)\n",
"id": "62abb2589dfdb591044c10941ebc076ca56579e64bb3076c82c3acc761805495",
"check": "boolean-equal",
"impact": "Informational",
"confidence": "High"
}
]
]

@ -0,0 +1,46 @@
contract ArrayLengthAssignment {
uint x;
uint120[] arr;
uint120[] arr2;
uint256[] arr3;
constructor() public {
x = 7;
}
struct TestStructWithArray {
uint[] x;
uint[][] y;
}
struct TestStructWithStructWithArray {
TestStructWithArray subStruct;
uint[] z;
}
TestStructWithArray a;
TestStructWithStructWithArray b;
function f(uint param, uint param2) public {
x += 1;
if(x > 3) {
arr.length = 7;
arr.length = param;
}
else{
// Array length that is incremented/decremented should not be found.
x = arr2.length++;
x = 7 + 3;
}
// Array length setting in structs should not be detected too.
a.x.length++;
a.x.length = param;
// Array length setting in embedded structs should not be detected too.
b.subStruct.x.length--;
b.subStruct.x.length = param + 1;
arr3[0] = param2;
arr3.length++;
}
}

@ -0,0 +1,604 @@
[
[
{
"elements": [
{
"type": "contract",
"name": "ArrayLengthAssignment",
"source_mapping": {
"start": 0,
"length": 1055,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/controlled-array-length/array_length_assignment.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/controlled-array-length/array_length_assignment.sol",
"is_dependency": false,
"lines": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46
],
"starting_column": 1,
"ending_column": 2
}
},
{
"type": "node",
"name": "b.subStruct.x.length = param + 1",
"source_mapping": {
"start": 964,
"length": 32,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/controlled-array-length/array_length_assignment.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/controlled-array-length/array_length_assignment.sol",
"is_dependency": false,
"lines": [
41
],
"starting_column": 9,
"ending_column": 41
},
"type_specific_fields": {
"parent": {
"type": "function",
"name": "f",
"source_mapping": {
"start": 406,
"length": 647,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/controlled-array-length/array_length_assignment.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/controlled-array-length/array_length_assignment.sol",
"is_dependency": false,
"lines": [
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45
],
"starting_column": 5,
"ending_column": 6
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "ArrayLengthAssignment",
"source_mapping": {
"start": 0,
"length": 1055,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/controlled-array-length/array_length_assignment.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/controlled-array-length/array_length_assignment.sol",
"is_dependency": false,
"lines": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "f(uint256,uint256)"
}
}
}
}
],
"description": "ArrayLengthAssignment (tests/detectors/controlled-array-length/array_length_assignment.sol#1-46) contract sets array length with a user-controlled value:\n\t- b.subStruct.x.length = param + 1 (tests/detectors/controlled-array-length/array_length_assignment.sol#41)\n",
"markdown": "[ArrayLengthAssignment](tests/detectors/controlled-array-length/array_length_assignment.sol#L1-L46) contract sets array length with a user-controlled value:\n\t- [b.subStruct.x.length = param + 1](tests/detectors/controlled-array-length/array_length_assignment.sol#L41)\n",
"id": "15164b2025ba6106829ae6e7baa9a73e931c0aa3e16a8d95ee30158667b4b7f5",
"check": "controlled-array-length",
"impact": "High",
"confidence": "Medium"
},
{
"elements": [
{
"type": "contract",
"name": "ArrayLengthAssignment",
"source_mapping": {
"start": 0,
"length": 1055,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/controlled-array-length/array_length_assignment.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/controlled-array-length/array_length_assignment.sol",
"is_dependency": false,
"lines": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46
],
"starting_column": 1,
"ending_column": 2
}
},
{
"type": "node",
"name": "arr.length = param",
"source_mapping": {
"start": 527,
"length": 18,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/controlled-array-length/array_length_assignment.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/controlled-array-length/array_length_assignment.sol",
"is_dependency": false,
"lines": [
26
],
"starting_column": 13,
"ending_column": 31
},
"type_specific_fields": {
"parent": {
"type": "function",
"name": "f",
"source_mapping": {
"start": 406,
"length": 647,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/controlled-array-length/array_length_assignment.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/controlled-array-length/array_length_assignment.sol",
"is_dependency": false,
"lines": [
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45
],
"starting_column": 5,
"ending_column": 6
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "ArrayLengthAssignment",
"source_mapping": {
"start": 0,
"length": 1055,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/controlled-array-length/array_length_assignment.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/controlled-array-length/array_length_assignment.sol",
"is_dependency": false,
"lines": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "f(uint256,uint256)"
}
}
}
}
],
"description": "ArrayLengthAssignment (tests/detectors/controlled-array-length/array_length_assignment.sol#1-46) contract sets array length with a user-controlled value:\n\t- arr.length = param (tests/detectors/controlled-array-length/array_length_assignment.sol#26)\n",
"markdown": "[ArrayLengthAssignment](tests/detectors/controlled-array-length/array_length_assignment.sol#L1-L46) contract sets array length with a user-controlled value:\n\t- [arr.length = param](tests/detectors/controlled-array-length/array_length_assignment.sol#L26)\n",
"id": "cb96ef1555863b421997853215ad3533faaffd35215987c6a2ebf21716d9bd1a",
"check": "controlled-array-length",
"impact": "High",
"confidence": "Medium"
},
{
"elements": [
{
"type": "contract",
"name": "ArrayLengthAssignment",
"source_mapping": {
"start": 0,
"length": 1055,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/controlled-array-length/array_length_assignment.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/controlled-array-length/array_length_assignment.sol",
"is_dependency": false,
"lines": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46
],
"starting_column": 1,
"ending_column": 2
}
},
{
"type": "node",
"name": "a.x.length = param",
"source_mapping": {
"start": 818,
"length": 18,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/controlled-array-length/array_length_assignment.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/controlled-array-length/array_length_assignment.sol",
"is_dependency": false,
"lines": [
36
],
"starting_column": 9,
"ending_column": 27
},
"type_specific_fields": {
"parent": {
"type": "function",
"name": "f",
"source_mapping": {
"start": 406,
"length": 647,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/controlled-array-length/array_length_assignment.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/controlled-array-length/array_length_assignment.sol",
"is_dependency": false,
"lines": [
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45
],
"starting_column": 5,
"ending_column": 6
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "ArrayLengthAssignment",
"source_mapping": {
"start": 0,
"length": 1055,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/controlled-array-length/array_length_assignment.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/controlled-array-length/array_length_assignment.sol",
"is_dependency": false,
"lines": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "f(uint256,uint256)"
}
}
}
}
],
"description": "ArrayLengthAssignment (tests/detectors/controlled-array-length/array_length_assignment.sol#1-46) contract sets array length with a user-controlled value:\n\t- a.x.length = param (tests/detectors/controlled-array-length/array_length_assignment.sol#36)\n",
"markdown": "[ArrayLengthAssignment](tests/detectors/controlled-array-length/array_length_assignment.sol#L1-L46) contract sets array length with a user-controlled value:\n\t- [a.x.length = param](tests/detectors/controlled-array-length/array_length_assignment.sol#L36)\n",
"id": "6a72386e40ef24dd02adf92179022559e26da5e66be4bb925d02756f90f38953",
"check": "controlled-array-length",
"impact": "High",
"confidence": "Medium"
}
]
]

@ -0,0 +1,35 @@
pragma solidity ^0.4.24;
contract CostlyOperationsInLoop{
uint loop_count = 100;
uint state_variable=0;
mapping (uint=>uint) map;
uint[100] arr;
function bad() external{
for (uint i=0; i < loop_count; i++){
state_variable++;
}
}
function ignore_for_now1() external {
for (uint i=0; i < 100; i++){
map[i] = i+1;
}
}
function ignore_for_now2() external {
for (uint i=0; i < 100; i++){
arr[i] = i+1;
}
}
function good() external{
uint local_variable = state_variable;
for (uint i=0; i < loop_count; i++){
local_variable++;
}
state_variable = local_variable;
}
}

@ -0,0 +1,184 @@
[
[
{
"elements": [
{
"type": "function",
"name": "bad",
"source_mapping": {
"start": 252,
"length": 373,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/costly-loop/multiple_costly_operations_in_loop.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/costly-loop/multiple_costly_operations_in_loop.sol",
"is_dependency": false,
"lines": [
10,
11,
12,
13,
14
],
"starting_column": 3,
"ending_column": 4
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "CostlyOperationsInLoop",
"source_mapping": {
"start": 26,
"length": 1081,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/costly-loop/multiple_costly_operations_in_loop.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/costly-loop/multiple_costly_operations_in_loop.sol",
"is_dependency": false,
"lines": [
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "bad()"
}
},
{
"type": "node",
"name": "state_variable ++",
"source_mapping": {
"start": 410,
"length": 16,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/costly-loop/multiple_costly_operations_in_loop.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/costly-loop/multiple_costly_operations_in_loop.sol",
"is_dependency": false,
"lines": [
12
],
"starting_column": 7,
"ending_column": 23
},
"type_specific_fields": {
"parent": {
"type": "function",
"name": "bad",
"source_mapping": {
"start": 252,
"length": 373,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/costly-loop/multiple_costly_operations_in_loop.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/costly-loop/multiple_costly_operations_in_loop.sol",
"is_dependency": false,
"lines": [
10,
11,
12,
13,
14
],
"starting_column": 3,
"ending_column": 4
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "CostlyOperationsInLoop",
"source_mapping": {
"start": 26,
"length": 1081,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/costly-loop/multiple_costly_operations_in_loop.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/costly-loop/multiple_costly_operations_in_loop.sol",
"is_dependency": false,
"lines": [
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "bad()"
}
}
}
}
],
"description": "CostlyOperationsInLoop.bad() (tests/detectors/costly-loop/multiple_costly_operations_in_loop.sol#10-14) has costly operations inside a loop:\n\t- state_variable ++ (tests/detectors/costly-loop/multiple_costly_operations_in_loop.sol#12)\n",
"markdown": "[CostlyOperationsInLoop.bad()](tests/detectors/costly-loop/multiple_costly_operations_in_loop.sol#L10-L14) has costly operations inside a loop:\n\t- [state_variable ++](tests/detectors/costly-loop/multiple_costly_operations_in_loop.sol#L12)\n",
"id": "245dbe07302f785326efd84e8b711d1691f045726e1098601f7e1058f1e72b2a",
"check": "costly-loop",
"impact": "Informational",
"confidence": "Medium"
}
]
]

@ -0,0 +1,46 @@
// This tests the detection of initializing a state variable using a non-constant function call or state variable.
contract StateVarInitFromFunction {
uint public v = set(); // should be flagged, initialized from function (sets to 77)
uint public w = 5;
uint public x = set(); // should be flagged, initialized from function (sets to 88)
uint public y1 = 5 + get(); // should be flagged, initialized from function (in expression)
uint public y2 = (10 + (5 + get())); // should be flagged, initialized from function (in expression)
uint public z1 = 5 + getPure(); // should not be flagged, is a pure function
uint public z2 = (10 + (5 + getPure())); // should not be flagged, is a pure function
uint constant public c1 = 40;
uint public z3 = c1 + 5; // should not be flagged, references a constant
uint public z4 = z3 + 5; // should be flagged, uses a non-constant state variable.
address public shouldntBeReported = address(8); // should not be flagged, not a *real* function call.
uint public constructorV;
uint public constructorX;
constructor(){
// By the time this code is hit, all state variable initialization has completed.
constructorV = v;
constructorX = x;
}
function set() public returns(uint) {
// If this function is being used to initialize a state variable before w, w will be zero.
// If it is declared after w, w will be set.
if(w == 0) {
return 77;
}
return 88;
}
function get() public returns(uint) {
return 55;
}
function getPure() public pure returns(uint) {
return 55;
}
}

@ -0,0 +1,464 @@
[
[
{
"elements": [
{
"type": "variable",
"name": "v",
"source_mapping": {
"start": 157,
"length": 21,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/function-init-state/function_init_state_variables.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/function-init-state/function_init_state_variables.sol",
"is_dependency": false,
"lines": [
5
],
"starting_column": 5,
"ending_column": 26
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "StateVarInitFromFunction",
"source_mapping": {
"start": 116,
"length": 1567,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/function-init-state/function_init_state_variables.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/function-init-state/function_init_state_variables.sol",
"is_dependency": false,
"lines": [
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46,
47
],
"starting_column": 1,
"ending_column": 0
}
}
}
}
],
"description": "StateVarInitFromFunction.v (tests/detectors/function-init-state/function_init_state_variables.sol#5) is set pre-construction with a non-constant function or state variable:\n\t- set()\n",
"markdown": "[StateVarInitFromFunction.v](tests/detectors/function-init-state/function_init_state_variables.sol#L5) is set pre-construction with a non-constant function or state variable:\n\t- set()\n",
"id": "4b87ea4c0a3b72be79ffde12c56c9dc7440445b79ff4b228e0937b3a05540e4b",
"check": "function-init-state",
"impact": "Informational",
"confidence": "High"
},
{
"elements": [
{
"type": "variable",
"name": "x",
"source_mapping": {
"start": 268,
"length": 21,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/function-init-state/function_init_state_variables.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/function-init-state/function_init_state_variables.sol",
"is_dependency": false,
"lines": [
7
],
"starting_column": 5,
"ending_column": 26
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "StateVarInitFromFunction",
"source_mapping": {
"start": 116,
"length": 1567,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/function-init-state/function_init_state_variables.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/function-init-state/function_init_state_variables.sol",
"is_dependency": false,
"lines": [
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46,
47
],
"starting_column": 1,
"ending_column": 0
}
}
}
}
],
"description": "StateVarInitFromFunction.x (tests/detectors/function-init-state/function_init_state_variables.sol#7) is set pre-construction with a non-constant function or state variable:\n\t- set()\n",
"markdown": "[StateVarInitFromFunction.x](tests/detectors/function-init-state/function_init_state_variables.sol#L7) is set pre-construction with a non-constant function or state variable:\n\t- set()\n",
"id": "adfa394934c8669a556cfa10c364fe526dd1e295a63959e1e88fe84a919ef354",
"check": "function-init-state",
"impact": "Informational",
"confidence": "High"
},
{
"elements": [
{
"type": "variable",
"name": "y1",
"source_mapping": {
"start": 357,
"length": 26,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/function-init-state/function_init_state_variables.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/function-init-state/function_init_state_variables.sol",
"is_dependency": false,
"lines": [
9
],
"starting_column": 5,
"ending_column": 31
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "StateVarInitFromFunction",
"source_mapping": {
"start": 116,
"length": 1567,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/function-init-state/function_init_state_variables.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/function-init-state/function_init_state_variables.sol",
"is_dependency": false,
"lines": [
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46,
47
],
"starting_column": 1,
"ending_column": 0
}
}
}
}
],
"description": "StateVarInitFromFunction.y1 (tests/detectors/function-init-state/function_init_state_variables.sol#9) is set pre-construction with a non-constant function or state variable:\n\t- 5 + get()\n",
"markdown": "[StateVarInitFromFunction.y1](tests/detectors/function-init-state/function_init_state_variables.sol#L9) is set pre-construction with a non-constant function or state variable:\n\t- 5 + get()\n",
"id": "b26f83c06e9aca87637dea02a0f4080fd4226c1ed90c6c2c63da85cb142d67ab",
"check": "function-init-state",
"impact": "Informational",
"confidence": "High"
},
{
"elements": [
{
"type": "variable",
"name": "y2",
"source_mapping": {
"start": 453,
"length": 35,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/function-init-state/function_init_state_variables.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/function-init-state/function_init_state_variables.sol",
"is_dependency": false,
"lines": [
10
],
"starting_column": 5,
"ending_column": 40
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "StateVarInitFromFunction",
"source_mapping": {
"start": 116,
"length": 1567,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/function-init-state/function_init_state_variables.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/function-init-state/function_init_state_variables.sol",
"is_dependency": false,
"lines": [
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46,
47
],
"starting_column": 1,
"ending_column": 0
}
}
}
}
],
"description": "StateVarInitFromFunction.y2 (tests/detectors/function-init-state/function_init_state_variables.sol#10) is set pre-construction with a non-constant function or state variable:\n\t- (10 + (5 + get()))\n",
"markdown": "[StateVarInitFromFunction.y2](tests/detectors/function-init-state/function_init_state_variables.sol#L10) is set pre-construction with a non-constant function or state variable:\n\t- (10 + (5 + get()))\n",
"id": "b6e231b9b735794e00b73dddb86b2ba8f7a738d916c99f302fb32b1095c67472",
"check": "function-init-state",
"impact": "Informational",
"confidence": "High"
},
{
"elements": [
{
"type": "variable",
"name": "z4",
"source_mapping": {
"start": 842,
"length": 23,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/function-init-state/function_init_state_variables.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/function-init-state/function_init_state_variables.sol",
"is_dependency": false,
"lines": [
17
],
"starting_column": 5,
"ending_column": 28
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "StateVarInitFromFunction",
"source_mapping": {
"start": 116,
"length": 1567,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/function-init-state/function_init_state_variables.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/function-init-state/function_init_state_variables.sol",
"is_dependency": false,
"lines": [
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46,
47
],
"starting_column": 1,
"ending_column": 0
}
}
}
}
],
"description": "StateVarInitFromFunction.z4 (tests/detectors/function-init-state/function_init_state_variables.sol#17) is set pre-construction with a non-constant function or state variable:\n\t- z3 + 5\n",
"markdown": "[StateVarInitFromFunction.z4](tests/detectors/function-init-state/function_init_state_variables.sol#L17) is set pre-construction with a non-constant function or state variable:\n\t- z3 + 5\n",
"id": "8b7eb9ab16397c2f23479d2c3043a675ab5e2b1da07e2697631812d6d7b68525",
"check": "function-init-state",
"impact": "Informational",
"confidence": "High"
}
]
]

@ -0,0 +1,43 @@
pragma solidity ^0.4.24;
library Lib{
struct MyStruct{
mapping(address => uint) maps;
}
function deleteSt(MyStruct[1] storage st){
delete st[0];
}
}
contract Balances {
struct BalancesStruct{
address owner;
mapping(address => uint) balances;
}
mapping(uint => BalancesStruct) public stackBalance;
function createBalance(uint idx) public {
require(stackBalance[idx].owner == 0);
stackBalance[idx] = BalancesStruct(msg.sender);
}
function deleteBalance(uint idx) public {
require(stackBalance[idx].owner == msg.sender);
delete stackBalance[idx];
}
function setBalance(uint idx, address addr, uint val) public {
require(stackBalance[idx].owner == msg.sender);
stackBalance[idx].balances[addr] = val;
}
function getBalance(uint idx, address addr) public view returns(uint){
return stackBalance[idx].balances[addr];
}
}

@ -0,0 +1,425 @@
[
[
{
"elements": [
{
"type": "function",
"name": "deleteSt",
"source_mapping": {
"start": 111,
"length": 70,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/mapping-deletion/MappingDeletion.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/mapping-deletion/MappingDeletion.sol",
"is_dependency": false,
"lines": [
9,
10,
11
],
"starting_column": 5,
"ending_column": 6
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "Lib",
"source_mapping": {
"start": 26,
"length": 158,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/mapping-deletion/MappingDeletion.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/mapping-deletion/MappingDeletion.sol",
"is_dependency": false,
"lines": [
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "deleteSt(Lib.MyStruct[1])"
}
},
{
"type": "struct",
"name": "MyStruct",
"source_mapping": {
"start": 44,
"length": 61,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/mapping-deletion/MappingDeletion.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/mapping-deletion/MappingDeletion.sol",
"is_dependency": false,
"lines": [
5,
6,
7
],
"starting_column": 5,
"ending_column": 6
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "Lib",
"source_mapping": {
"start": 26,
"length": 158,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/mapping-deletion/MappingDeletion.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/mapping-deletion/MappingDeletion.sol",
"is_dependency": false,
"lines": [
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13
],
"starting_column": 1,
"ending_column": 2
}
}
}
},
{
"type": "node",
"name": "delete st[0]",
"source_mapping": {
"start": 162,
"length": 12,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/mapping-deletion/MappingDeletion.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/mapping-deletion/MappingDeletion.sol",
"is_dependency": false,
"lines": [
10
],
"starting_column": 9,
"ending_column": 21
},
"type_specific_fields": {
"parent": {
"type": "function",
"name": "deleteSt",
"source_mapping": {
"start": 111,
"length": 70,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/mapping-deletion/MappingDeletion.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/mapping-deletion/MappingDeletion.sol",
"is_dependency": false,
"lines": [
9,
10,
11
],
"starting_column": 5,
"ending_column": 6
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "Lib",
"source_mapping": {
"start": 26,
"length": 158,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/mapping-deletion/MappingDeletion.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/mapping-deletion/MappingDeletion.sol",
"is_dependency": false,
"lines": [
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "deleteSt(Lib.MyStruct[1])"
}
}
}
}
],
"description": "Lib.deleteSt(Lib.MyStruct[1]) (tests/detectors/mapping-deletion/MappingDeletion.sol#9-11) deletes Lib.MyStruct (tests/detectors/mapping-deletion/MappingDeletion.sol#5-7) which contains a mapping:\n\t-delete st[0] (tests/detectors/mapping-deletion/MappingDeletion.sol#10)\n",
"markdown": "[Lib.deleteSt(Lib.MyStruct[1])](tests/detectors/mapping-deletion/MappingDeletion.sol#L9-L11) deletes [Lib.MyStruct](tests/detectors/mapping-deletion/MappingDeletion.sol#L5-L7) which contains a mapping:\n\t-[delete st[0]](tests/detectors/mapping-deletion/MappingDeletion.sol#L10)\n",
"id": "d618551637c257938461c33070c5339207b75de2bb11ff88d92bd9679252f307",
"check": "mapping-deletion",
"impact": "Medium",
"confidence": "High"
},
{
"elements": [
{
"type": "function",
"name": "deleteBalance",
"source_mapping": {
"start": 541,
"length": 137,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/mapping-deletion/MappingDeletion.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/mapping-deletion/MappingDeletion.sol",
"is_dependency": false,
"lines": [
28,
29,
30,
31
],
"starting_column": 5,
"ending_column": 6
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "Balances",
"source_mapping": {
"start": 186,
"length": 825,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/mapping-deletion/MappingDeletion.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/mapping-deletion/MappingDeletion.sol",
"is_dependency": false,
"lines": [
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "deleteBalance(uint256)"
}
},
{
"type": "struct",
"name": "BalancesStruct",
"source_mapping": {
"start": 215,
"length": 94,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/mapping-deletion/MappingDeletion.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/mapping-deletion/MappingDeletion.sol",
"is_dependency": false,
"lines": [
17,
18,
19,
20
],
"starting_column": 5,
"ending_column": 6
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "Balances",
"source_mapping": {
"start": 186,
"length": 825,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/mapping-deletion/MappingDeletion.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/mapping-deletion/MappingDeletion.sol",
"is_dependency": false,
"lines": [
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43
],
"starting_column": 1,
"ending_column": 2
}
}
}
},
{
"type": "node",
"name": "delete stackBalance[idx]",
"source_mapping": {
"start": 647,
"length": 24,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/mapping-deletion/MappingDeletion.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/mapping-deletion/MappingDeletion.sol",
"is_dependency": false,
"lines": [
30
],
"starting_column": 9,
"ending_column": 33
},
"type_specific_fields": {
"parent": {
"type": "function",
"name": "deleteBalance",
"source_mapping": {
"start": 541,
"length": 137,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/mapping-deletion/MappingDeletion.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/mapping-deletion/MappingDeletion.sol",
"is_dependency": false,
"lines": [
28,
29,
30,
31
],
"starting_column": 5,
"ending_column": 6
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "Balances",
"source_mapping": {
"start": 186,
"length": 825,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/mapping-deletion/MappingDeletion.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/mapping-deletion/MappingDeletion.sol",
"is_dependency": false,
"lines": [
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "deleteBalance(uint256)"
}
}
}
}
],
"description": "Balances.deleteBalance(uint256) (tests/detectors/mapping-deletion/MappingDeletion.sol#28-31) deletes Balances.BalancesStruct (tests/detectors/mapping-deletion/MappingDeletion.sol#17-20) which contains a mapping:\n\t-delete stackBalance[idx] (tests/detectors/mapping-deletion/MappingDeletion.sol#30)\n",
"markdown": "[Balances.deleteBalance(uint256)](tests/detectors/mapping-deletion/MappingDeletion.sol#L28-L31) deletes [Balances.BalancesStruct](tests/detectors/mapping-deletion/MappingDeletion.sol#L17-L20) which contains a mapping:\n\t-[delete stackBalance[idx]](tests/detectors/mapping-deletion/MappingDeletion.sol#L30)\n",
"id": "a1e8bc34ec8ef7969409701b3c851749c4ba00dcbbef2cabcdf7e3f49724034e",
"check": "mapping-deletion",
"impact": "Medium",
"confidence": "High"
}
]
]

@ -0,0 +1,72 @@
/* Interfaces */
interface ISomething0 {
function sth1(uint256) external;
}
interface ISomething1 {
function sth1(uint256) external;
function sth2(bytes calldata) external;
}
interface ISomething2 {
function sth(uint256) external;
}
interface ISomething3 {
function sth1(uint256) external;
function sth2(bool) external;
}
interface ISomething4 {
function sth1(uint256) external;
function sth2(bool) external;
function sth3(bytes calldata) external;
}
interface ISomething5 {
function sth(uint256) external;
function sth1(uint256) external;
}
/* Contracts */
contract bad0 { // forgets to say it is ISomething1
function sth1(uint256 x) external {}
function sth2(bytes calldata y) external {}
}
contract bad1 { // forgets to say it is ISomething4
function sth1(uint256 x) external {}
function sth2(bool b) external {}
function sth3(bytes calldata y) external {}
}
contract bad2 is ISomething3 { // forgets to say it is ISomething4 which is a superset of ISomething3
function sth1(uint256 x) external {}
function sth2(bool b) external {}
function sth3(bytes calldata y) external {}
}
contract good0 is ISomething2 {
function sth(uint256 x) external {}
}
/* Implements ISomething5 which is a superset of ISomething0 and ISomething2 */
contract good1 is ISomething5 {
function sth(uint256 x) external {}
function sth1(uint256 x) external {}
}
/* good2_i is not an Interface because sth5 is not external */
contract bad3_i {
function sth4(uint256 x) external;
function sth5(uint256 x) public;
}
contract bad3 {
function sth4(uint256 x) external {}
function sth5(uint256 x) public {}
}

@ -0,0 +1,785 @@
JSON AST (compact format):
======= multiple-constructors.sol =======
{
"absolutePath" : "multiple-constructors.sol",
"exportedSymbols" :
{
"A" :
[
54
]
},
"id" : 55,
"nodeType" : "SourceUnit",
"nodes" :
[
{
"id" : 1,
"literals" :
[
"solidity",
"0.4",
".22"
],
"nodeType" : "PragmaDirective",
"src" : "0:23:0"
},
{
"baseContracts" : [],
"contractDependencies" : [],
"contractKind" : "contract",
"documentation" : null,
"fullyImplemented" : true,
"id" : 54,
"linearizedBaseContracts" :
[
54
],
"name" : "A",
"nodeType" : "ContractDefinition",
"nodes" :
[
{
"constant" : false,
"id" : 5,
"name" : "x",
"nodeType" : "VariableDeclaration",
"scope" : 54,
"src" : "41:9:0",
"stateVariable" : true,
"storageLocation" : "default",
"typeDescriptions" :
{
"typeIdentifier" : "t_array$_t_uint256_$2_storage",
"typeString" : "uint256[2]"
},
"typeName" :
{
"baseType" :
{
"id" : 2,
"name" : "uint",
"nodeType" : "ElementaryTypeName",
"src" : "41:4:0",
"typeDescriptions" :
{
"typeIdentifier" : "t_uint256",
"typeString" : "uint256"
}
},
"id" : 4,
"length" :
{
"argumentTypes" : null,
"hexValue" : "32",
"id" : 3,
"isConstant" : false,
"isLValue" : false,
"isPure" : false,
"kind" : "number",
"lValueRequested" : false,
"nodeType" : "Literal",
"src" : "46:1:0",
"subdenomination" : null,
"typeDescriptions" :
{
"typeIdentifier" : null,
"typeString" : null
},
"value" : "2"
},
"nodeType" : "ArrayTypeName",
"src" : "41:7:0",
"typeDescriptions" :
{
"typeIdentifier" : "t_array$_t_uint256_$2_storage_ptr",
"typeString" : "uint256[2]"
}
},
"value" : null,
"visibility" : "internal"
},
{
"body" :
{
"id" : 20,
"nodeType" : "Block",
"src" : "76:45:0",
"statements" :
[
{
"expression" :
{
"argumentTypes" : null,
"id" : 12,
"isConstant" : false,
"isLValue" : false,
"isPure" : false,
"lValueRequested" : false,
"leftHandSide" :
{
"argumentTypes" : null,
"baseExpression" :
{
"argumentTypes" : null,
"id" : 8,
"name" : "x",
"nodeType" : "Identifier",
"overloadedDeclarations" : [],
"referencedDeclaration" : 5,
"src" : "86:1:0",
"typeDescriptions" :
{
"typeIdentifier" : "t_array$_t_uint256_$2_storage",
"typeString" : "uint256[2] storage ref"
}
},
"id" : 10,
"indexExpression" :
{
"argumentTypes" : null,
"hexValue" : "30",
"id" : 9,
"isConstant" : false,
"isLValue" : false,
"isPure" : true,
"kind" : "number",
"lValueRequested" : false,
"nodeType" : "Literal",
"src" : "88:1:0",
"subdenomination" : null,
"typeDescriptions" :
{
"typeIdentifier" : "t_rational_0_by_1",
"typeString" : "int_const 0"
},
"value" : "0"
},
"isConstant" : false,
"isLValue" : true,
"isPure" : false,
"lValueRequested" : true,
"nodeType" : "IndexAccess",
"src" : "86:4:0",
"typeDescriptions" :
{
"typeIdentifier" : "t_uint256",
"typeString" : "uint256"
}
},
"nodeType" : "Assignment",
"operator" : "=",
"rightHandSide" :
{
"argumentTypes" : null,
"hexValue" : "3838",
"id" : 11,
"isConstant" : false,
"isLValue" : false,
"isPure" : true,
"kind" : "number",
"lValueRequested" : false,
"nodeType" : "Literal",
"src" : "93:2:0",
"subdenomination" : null,
"typeDescriptions" :
{
"typeIdentifier" : "t_rational_88_by_1",
"typeString" : "int_const 88"
},
"value" : "88"
},
"src" : "86:9:0",
"typeDescriptions" :
{
"typeIdentifier" : "t_uint256",
"typeString" : "uint256"
}
},
"id" : 13,
"nodeType" : "ExpressionStatement",
"src" : "86:9:0"
},
{
"expression" :
{
"argumentTypes" : null,
"id" : 18,
"isConstant" : false,
"isLValue" : false,
"isPure" : false,
"lValueRequested" : false,
"leftHandSide" :
{
"argumentTypes" : null,
"baseExpression" :
{
"argumentTypes" : null,
"id" : 14,
"name" : "x",
"nodeType" : "Identifier",
"overloadedDeclarations" : [],
"referencedDeclaration" : 5,
"src" : "105:1:0",
"typeDescriptions" :
{
"typeIdentifier" : "t_array$_t_uint256_$2_storage",
"typeString" : "uint256[2] storage ref"
}
},
"id" : 16,
"indexExpression" :
{
"argumentTypes" : null,
"hexValue" : "31",
"id" : 15,
"isConstant" : false,
"isLValue" : false,
"isPure" : true,
"kind" : "number",
"lValueRequested" : false,
"nodeType" : "Literal",
"src" : "107:1:0",
"subdenomination" : null,
"typeDescriptions" :
{
"typeIdentifier" : "t_rational_1_by_1",
"typeString" : "int_const 1"
},
"value" : "1"
},
"isConstant" : false,
"isLValue" : true,
"isPure" : false,
"lValueRequested" : true,
"nodeType" : "IndexAccess",
"src" : "105:4:0",
"typeDescriptions" :
{
"typeIdentifier" : "t_uint256",
"typeString" : "uint256"
}
},
"nodeType" : "Assignment",
"operator" : "=",
"rightHandSide" :
{
"argumentTypes" : null,
"hexValue" : "3939",
"id" : 17,
"isConstant" : false,
"isLValue" : false,
"isPure" : true,
"kind" : "number",
"lValueRequested" : false,
"nodeType" : "Literal",
"src" : "112:2:0",
"subdenomination" : null,
"typeDescriptions" :
{
"typeIdentifier" : "t_rational_99_by_1",
"typeString" : "int_const 99"
},
"value" : "99"
},
"src" : "105:9:0",
"typeDescriptions" :
{
"typeIdentifier" : "t_uint256",
"typeString" : "uint256"
}
},
"id" : 19,
"nodeType" : "ExpressionStatement",
"src" : "105:9:0"
}
]
},
"documentation" : null,
"id" : 21,
"implemented" : true,
"isConstructor" : true,
"isDeclaredConst" : false,
"modifiers" : [],
"name" : "A",
"nodeType" : "FunctionDefinition",
"parameters" :
{
"id" : 6,
"nodeType" : "ParameterList",
"parameters" : [],
"src" : "66:2:0"
},
"payable" : false,
"returnParameters" :
{
"id" : 7,
"nodeType" : "ParameterList",
"parameters" : [],
"src" : "76:0:0"
},
"scope" : 54,
"src" : "56:65:0",
"stateMutability" : "nonpayable",
"superFunction" : null,
"visibility" : "public"
},
{
"body" :
{
"id" : 36,
"nodeType" : "Block",
"src" : "147:45:0",
"statements" :
[
{
"expression" :
{
"argumentTypes" : null,
"id" : 28,
"isConstant" : false,
"isLValue" : false,
"isPure" : false,
"lValueRequested" : false,
"leftHandSide" :
{
"argumentTypes" : null,
"baseExpression" :
{
"argumentTypes" : null,
"id" : 24,
"name" : "x",
"nodeType" : "Identifier",
"overloadedDeclarations" : [],
"referencedDeclaration" : 5,
"src" : "157:1:0",
"typeDescriptions" :
{
"typeIdentifier" : "t_array$_t_uint256_$2_storage",
"typeString" : "uint256[2] storage ref"
}
},
"id" : 26,
"indexExpression" :
{
"argumentTypes" : null,
"hexValue" : "30",
"id" : 25,
"isConstant" : false,
"isLValue" : false,
"isPure" : true,
"kind" : "number",
"lValueRequested" : false,
"nodeType" : "Literal",
"src" : "159:1:0",
"subdenomination" : null,
"typeDescriptions" :
{
"typeIdentifier" : "t_rational_0_by_1",
"typeString" : "int_const 0"
},
"value" : "0"
},
"isConstant" : false,
"isLValue" : true,
"isPure" : false,
"lValueRequested" : true,
"nodeType" : "IndexAccess",
"src" : "157:4:0",
"typeDescriptions" :
{
"typeIdentifier" : "t_uint256",
"typeString" : "uint256"
}
},
"nodeType" : "Assignment",
"operator" : "=",
"rightHandSide" :
{
"argumentTypes" : null,
"hexValue" : "3636",
"id" : 27,
"isConstant" : false,
"isLValue" : false,
"isPure" : true,
"kind" : "number",
"lValueRequested" : false,
"nodeType" : "Literal",
"src" : "164:2:0",
"subdenomination" : null,
"typeDescriptions" :
{
"typeIdentifier" : "t_rational_66_by_1",
"typeString" : "int_const 66"
},
"value" : "66"
},
"src" : "157:9:0",
"typeDescriptions" :
{
"typeIdentifier" : "t_uint256",
"typeString" : "uint256"
}
},
"id" : 29,
"nodeType" : "ExpressionStatement",
"src" : "157:9:0"
},
{
"expression" :
{
"argumentTypes" : null,
"id" : 34,
"isConstant" : false,
"isLValue" : false,
"isPure" : false,
"lValueRequested" : false,
"leftHandSide" :
{
"argumentTypes" : null,
"baseExpression" :
{
"argumentTypes" : null,
"id" : 30,
"name" : "x",
"nodeType" : "Identifier",
"overloadedDeclarations" : [],
"referencedDeclaration" : 5,
"src" : "176:1:0",
"typeDescriptions" :
{
"typeIdentifier" : "t_array$_t_uint256_$2_storage",
"typeString" : "uint256[2] storage ref"
}
},
"id" : 32,
"indexExpression" :
{
"argumentTypes" : null,
"hexValue" : "31",
"id" : 31,
"isConstant" : false,
"isLValue" : false,
"isPure" : true,
"kind" : "number",
"lValueRequested" : false,
"nodeType" : "Literal",
"src" : "178:1:0",
"subdenomination" : null,
"typeDescriptions" :
{
"typeIdentifier" : "t_rational_1_by_1",
"typeString" : "int_const 1"
},
"value" : "1"
},
"isConstant" : false,
"isLValue" : true,
"isPure" : false,
"lValueRequested" : true,
"nodeType" : "IndexAccess",
"src" : "176:4:0",
"typeDescriptions" :
{
"typeIdentifier" : "t_uint256",
"typeString" : "uint256"
}
},
"nodeType" : "Assignment",
"operator" : "=",
"rightHandSide" :
{
"argumentTypes" : null,
"hexValue" : "3737",
"id" : 33,
"isConstant" : false,
"isLValue" : false,
"isPure" : true,
"kind" : "number",
"lValueRequested" : false,
"nodeType" : "Literal",
"src" : "183:2:0",
"subdenomination" : null,
"typeDescriptions" :
{
"typeIdentifier" : "t_rational_77_by_1",
"typeString" : "int_const 77"
},
"value" : "77"
},
"src" : "176:9:0",
"typeDescriptions" :
{
"typeIdentifier" : "t_uint256",
"typeString" : "uint256"
}
},
"id" : 35,
"nodeType" : "ExpressionStatement",
"src" : "176:9:0"
}
]
},
"documentation" : null,
"id" : 37,
"implemented" : true,
"isConstructor" : true,
"isDeclaredConst" : false,
"modifiers" : [],
"name" : "",
"nodeType" : "FunctionDefinition",
"parameters" :
{
"id" : 22,
"nodeType" : "ParameterList",
"parameters" : [],
"src" : "137:2:0"
},
"payable" : false,
"returnParameters" :
{
"id" : 23,
"nodeType" : "ParameterList",
"parameters" : [],
"src" : "147:0:0"
},
"scope" : 54,
"src" : "126:66:0",
"stateMutability" : "nonpayable",
"superFunction" : null,
"visibility" : "public"
},
{
"body" :
{
"id" : 52,
"nodeType" : "Block",
"src" : "241:36:0",
"statements" :
[
{
"expression" :
{
"argumentTypes" : null,
"components" :
[
{
"argumentTypes" : null,
"baseExpression" :
{
"argumentTypes" : null,
"id" : 44,
"name" : "x",
"nodeType" : "Identifier",
"overloadedDeclarations" : [],
"referencedDeclaration" : 5,
"src" : "259:1:0",
"typeDescriptions" :
{
"typeIdentifier" : "t_array$_t_uint256_$2_storage",
"typeString" : "uint256[2] storage ref"
}
},
"id" : 46,
"indexExpression" :
{
"argumentTypes" : null,
"hexValue" : "30",
"id" : 45,
"isConstant" : false,
"isLValue" : false,
"isPure" : true,
"kind" : "number",
"lValueRequested" : false,
"nodeType" : "Literal",
"src" : "261:1:0",
"subdenomination" : null,
"typeDescriptions" :
{
"typeIdentifier" : "t_rational_0_by_1",
"typeString" : "int_const 0"
},
"value" : "0"
},
"isConstant" : false,
"isLValue" : true,
"isPure" : false,
"lValueRequested" : false,
"nodeType" : "IndexAccess",
"src" : "259:4:0",
"typeDescriptions" :
{
"typeIdentifier" : "t_uint256",
"typeString" : "uint256"
}
},
{
"argumentTypes" : null,
"baseExpression" :
{
"argumentTypes" : null,
"id" : 47,
"name" : "x",
"nodeType" : "Identifier",
"overloadedDeclarations" : [],
"referencedDeclaration" : 5,
"src" : "265:1:0",
"typeDescriptions" :
{
"typeIdentifier" : "t_array$_t_uint256_$2_storage",
"typeString" : "uint256[2] storage ref"
}
},
"id" : 49,
"indexExpression" :
{
"argumentTypes" : null,
"hexValue" : "31",
"id" : 48,
"isConstant" : false,
"isLValue" : false,
"isPure" : true,
"kind" : "number",
"lValueRequested" : false,
"nodeType" : "Literal",
"src" : "267:1:0",
"subdenomination" : null,
"typeDescriptions" :
{
"typeIdentifier" : "t_rational_1_by_1",
"typeString" : "int_const 1"
},
"value" : "1"
},
"isConstant" : false,
"isLValue" : true,
"isPure" : false,
"lValueRequested" : false,
"nodeType" : "IndexAccess",
"src" : "265:4:0",
"typeDescriptions" :
{
"typeIdentifier" : "t_uint256",
"typeString" : "uint256"
}
}
],
"id" : 50,
"isConstant" : false,
"isInlineArray" : false,
"isLValue" : false,
"isPure" : false,
"lValueRequested" : false,
"nodeType" : "TupleExpression",
"src" : "258:12:0",
"typeDescriptions" :
{
"typeIdentifier" : "t_tuple$_t_uint256_$_t_uint256_$",
"typeString" : "tuple(uint256,uint256)"
}
},
"functionReturnParameters" : 43,
"id" : 51,
"nodeType" : "Return",
"src" : "251:19:0"
}
]
},
"documentation" : null,
"id" : 53,
"implemented" : true,
"isConstructor" : false,
"isDeclaredConst" : false,
"modifiers" : [],
"name" : "test",
"nodeType" : "FunctionDefinition",
"parameters" :
{
"id" : 38,
"nodeType" : "ParameterList",
"parameters" : [],
"src" : "211:2:0"
},
"payable" : false,
"returnParameters" :
{
"id" : 43,
"nodeType" : "ParameterList",
"parameters" :
[
{
"constant" : false,
"id" : 40,
"name" : "",
"nodeType" : "VariableDeclaration",
"scope" : 53,
"src" : "229:4:0",
"stateVariable" : false,
"storageLocation" : "default",
"typeDescriptions" :
{
"typeIdentifier" : "t_uint256",
"typeString" : "uint256"
},
"typeName" :
{
"id" : 39,
"name" : "uint",
"nodeType" : "ElementaryTypeName",
"src" : "229:4:0",
"typeDescriptions" :
{
"typeIdentifier" : "t_uint256",
"typeString" : "uint256"
}
},
"value" : null,
"visibility" : "internal"
},
{
"constant" : false,
"id" : 42,
"name" : "",
"nodeType" : "VariableDeclaration",
"scope" : 53,
"src" : "235:4:0",
"stateVariable" : false,
"storageLocation" : "default",
"typeDescriptions" :
{
"typeIdentifier" : "t_uint256",
"typeString" : "uint256"
},
"typeName" :
{
"id" : 41,
"name" : "uint",
"nodeType" : "ElementaryTypeName",
"src" : "235:4:0",
"typeDescriptions" :
{
"typeIdentifier" : "t_uint256",
"typeString" : "uint256"
}
},
"value" : null,
"visibility" : "internal"
}
],
"src" : "228:12:0"
},
"scope" : 54,
"src" : "198:79:0",
"stateMutability" : "nonpayable",
"superFunction" : null,
"visibility" : "public"
}
],
"scope" : 55,
"src" : "24:255:0"
}
],
"src" : "0:280:0"
}

@ -0,0 +1,29 @@
// This is used to test detection of public mappings with nested variables. This was an issue in Solidity 0.4.x.
pragma solidity ^0.4.0;
contract Bug {
struct innerStruct {
uint x;
}
struct outerStruct {
innerStruct inner;
}
mapping(uint => outerStruct) public testMapping;
mapping(uint => uint) public testMapping2;
mapping(uint => address) public testMapping3;
constructor() public {
testMapping[0].inner.x = 42;
}
}
contract Test{
function f() public returns(uint){
Bug b = new Bug();
return b.testMapping(0).x;
}
}

@ -0,0 +1,69 @@
[
[
{
"elements": [
{
"type": "variable",
"name": "testMapping",
"source_mapping": {
"start": 265,
"length": 47,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/public-mappings-nested/public_mappings_nested.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/public-mappings-nested/public_mappings_nested.sol",
"is_dependency": false,
"lines": [
14
],
"starting_column": 5,
"ending_column": 52
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "Bug",
"source_mapping": {
"start": 138,
"length": 345,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/public-mappings-nested/public_mappings_nested.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/public-mappings-nested/public_mappings_nested.sol",
"is_dependency": false,
"lines": [
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21
],
"starting_column": 1,
"ending_column": 2
}
}
}
}
],
"description": "Bug.testMapping (tests/detectors/public-mappings-nested/public_mappings_nested.sol#14) is a public mapping with nested variables\n",
"markdown": "[Bug.testMapping](tests/detectors/public-mappings-nested/public_mappings_nested.sol#L14) is a public mapping with nested variables\n",
"id": "100978112524def620b003331f34b2b51eb78cae6f7eb2793d9671b4b7bb858a",
"check": "public-mappings-nested",
"impact": "High",
"confidence": "High"
}
]
]

@ -0,0 +1,17 @@
// This tests for redundant top-level expressions in statements.
contract RedundantStatementsContract {
constructor() public {
uint;
bool;
RedundantStatementsContract;
}
function test() public returns (uint) {
uint;
assert;
test;
return 777;
}
}

@ -0,0 +1,733 @@
[
[
{
"elements": [
{
"type": "node",
"name": "uint256",
"source_mapping": {
"start": 141,
"length": 4,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol",
"is_dependency": false,
"lines": [
6
],
"starting_column": 9,
"ending_column": 13
},
"type_specific_fields": {
"parent": {
"type": "function",
"name": "constructor",
"source_mapping": {
"start": 110,
"length": 93,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol",
"is_dependency": false,
"lines": [
5,
6,
7,
8,
9
],
"starting_column": 5,
"ending_column": 6
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "RedundantStatementsContract",
"source_mapping": {
"start": 66,
"length": 254,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol",
"is_dependency": false,
"lines": [
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18
],
"starting_column": 1,
"ending_column": 0
}
},
"signature": "constructor()"
}
}
}
},
{
"type": "contract",
"name": "RedundantStatementsContract",
"source_mapping": {
"start": 66,
"length": 254,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol",
"is_dependency": false,
"lines": [
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18
],
"starting_column": 1,
"ending_column": 0
}
}
],
"description": "Redundant expression \"uint256 (tests/detectors/redundant-statements/redundant_statements.sol#6)\" inRedundantStatementsContract (tests/detectors/redundant-statements/redundant_statements.sol#3-18)\n",
"markdown": "Redundant expression \"[uint256](tests/detectors/redundant-statements/redundant_statements.sol#L6)\" in[RedundantStatementsContract](tests/detectors/redundant-statements/redundant_statements.sol#L3-L18)\n",
"id": "cff54481eae76053f9cae0d4f77a2e5092461dc3fcb9e4e2f8605afb6aa832aa",
"check": "redundant-statements",
"impact": "Informational",
"confidence": "High"
},
{
"elements": [
{
"type": "node",
"name": "bool",
"source_mapping": {
"start": 155,
"length": 4,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol",
"is_dependency": false,
"lines": [
7
],
"starting_column": 9,
"ending_column": 13
},
"type_specific_fields": {
"parent": {
"type": "function",
"name": "constructor",
"source_mapping": {
"start": 110,
"length": 93,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol",
"is_dependency": false,
"lines": [
5,
6,
7,
8,
9
],
"starting_column": 5,
"ending_column": 6
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "RedundantStatementsContract",
"source_mapping": {
"start": 66,
"length": 254,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol",
"is_dependency": false,
"lines": [
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18
],
"starting_column": 1,
"ending_column": 0
}
},
"signature": "constructor()"
}
}
}
},
{
"type": "contract",
"name": "RedundantStatementsContract",
"source_mapping": {
"start": 66,
"length": 254,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol",
"is_dependency": false,
"lines": [
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18
],
"starting_column": 1,
"ending_column": 0
}
}
],
"description": "Redundant expression \"bool (tests/detectors/redundant-statements/redundant_statements.sol#7)\" inRedundantStatementsContract (tests/detectors/redundant-statements/redundant_statements.sol#3-18)\n",
"markdown": "Redundant expression \"[bool](tests/detectors/redundant-statements/redundant_statements.sol#L7)\" in[RedundantStatementsContract](tests/detectors/redundant-statements/redundant_statements.sol#L3-L18)\n",
"id": "bd643774adde96fa093cf2ec70d9a80fc2999dba8b61b60d0df19366003d74d5",
"check": "redundant-statements",
"impact": "Informational",
"confidence": "High"
},
{
"elements": [
{
"type": "node",
"name": "RedundantStatementsContract",
"source_mapping": {
"start": 169,
"length": 27,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol",
"is_dependency": false,
"lines": [
8
],
"starting_column": 9,
"ending_column": 36
},
"type_specific_fields": {
"parent": {
"type": "function",
"name": "constructor",
"source_mapping": {
"start": 110,
"length": 93,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol",
"is_dependency": false,
"lines": [
5,
6,
7,
8,
9
],
"starting_column": 5,
"ending_column": 6
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "RedundantStatementsContract",
"source_mapping": {
"start": 66,
"length": 254,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol",
"is_dependency": false,
"lines": [
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18
],
"starting_column": 1,
"ending_column": 0
}
},
"signature": "constructor()"
}
}
}
},
{
"type": "contract",
"name": "RedundantStatementsContract",
"source_mapping": {
"start": 66,
"length": 254,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol",
"is_dependency": false,
"lines": [
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18
],
"starting_column": 1,
"ending_column": 0
}
}
],
"description": "Redundant expression \"RedundantStatementsContract (tests/detectors/redundant-statements/redundant_statements.sol#8)\" inRedundantStatementsContract (tests/detectors/redundant-statements/redundant_statements.sol#3-18)\n",
"markdown": "Redundant expression \"[RedundantStatementsContract](tests/detectors/redundant-statements/redundant_statements.sol#L8)\" in[RedundantStatementsContract](tests/detectors/redundant-statements/redundant_statements.sol#L3-L18)\n",
"id": "d93991180e8fe3accc3157f286d3a6781ed5c03398d68c0b9fde918a01d65ede",
"check": "redundant-statements",
"impact": "Informational",
"confidence": "High"
},
{
"elements": [
{
"type": "node",
"name": "uint256",
"source_mapping": {
"start": 257,
"length": 4,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol",
"is_dependency": false,
"lines": [
12
],
"starting_column": 9,
"ending_column": 13
},
"type_specific_fields": {
"parent": {
"type": "function",
"name": "test",
"source_mapping": {
"start": 209,
"length": 109,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol",
"is_dependency": false,
"lines": [
11,
12,
13,
14,
15,
16
],
"starting_column": 5,
"ending_column": 6
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "RedundantStatementsContract",
"source_mapping": {
"start": 66,
"length": 254,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol",
"is_dependency": false,
"lines": [
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18
],
"starting_column": 1,
"ending_column": 0
}
},
"signature": "test()"
}
}
}
},
{
"type": "contract",
"name": "RedundantStatementsContract",
"source_mapping": {
"start": 66,
"length": 254,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol",
"is_dependency": false,
"lines": [
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18
],
"starting_column": 1,
"ending_column": 0
}
}
],
"description": "Redundant expression \"uint256 (tests/detectors/redundant-statements/redundant_statements.sol#12)\" inRedundantStatementsContract (tests/detectors/redundant-statements/redundant_statements.sol#3-18)\n",
"markdown": "Redundant expression \"[uint256](tests/detectors/redundant-statements/redundant_statements.sol#L12)\" in[RedundantStatementsContract](tests/detectors/redundant-statements/redundant_statements.sol#L3-L18)\n",
"id": "262267538723f822ebe065e5976738ef3f564c791aaddb26867d202602de1eea",
"check": "redundant-statements",
"impact": "Informational",
"confidence": "High"
},
{
"elements": [
{
"type": "node",
"name": "assert(bool)",
"source_mapping": {
"start": 271,
"length": 6,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol",
"is_dependency": false,
"lines": [
13
],
"starting_column": 9,
"ending_column": 15
},
"type_specific_fields": {
"parent": {
"type": "function",
"name": "test",
"source_mapping": {
"start": 209,
"length": 109,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol",
"is_dependency": false,
"lines": [
11,
12,
13,
14,
15,
16
],
"starting_column": 5,
"ending_column": 6
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "RedundantStatementsContract",
"source_mapping": {
"start": 66,
"length": 254,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol",
"is_dependency": false,
"lines": [
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18
],
"starting_column": 1,
"ending_column": 0
}
},
"signature": "test()"
}
}
}
},
{
"type": "contract",
"name": "RedundantStatementsContract",
"source_mapping": {
"start": 66,
"length": 254,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol",
"is_dependency": false,
"lines": [
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18
],
"starting_column": 1,
"ending_column": 0
}
}
],
"description": "Redundant expression \"assert(bool) (tests/detectors/redundant-statements/redundant_statements.sol#13)\" inRedundantStatementsContract (tests/detectors/redundant-statements/redundant_statements.sol#3-18)\n",
"markdown": "Redundant expression \"[assert(bool)](tests/detectors/redundant-statements/redundant_statements.sol#L13)\" in[RedundantStatementsContract](tests/detectors/redundant-statements/redundant_statements.sol#L3-L18)\n",
"id": "00295b0d55ceb6d73eec5a4905d137edf751e11c951252b54cd42c43ace68ffd",
"check": "redundant-statements",
"impact": "Informational",
"confidence": "High"
},
{
"elements": [
{
"type": "node",
"name": "test",
"source_mapping": {
"start": 287,
"length": 4,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol",
"is_dependency": false,
"lines": [
14
],
"starting_column": 9,
"ending_column": 13
},
"type_specific_fields": {
"parent": {
"type": "function",
"name": "test",
"source_mapping": {
"start": 209,
"length": 109,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol",
"is_dependency": false,
"lines": [
11,
12,
13,
14,
15,
16
],
"starting_column": 5,
"ending_column": 6
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "RedundantStatementsContract",
"source_mapping": {
"start": 66,
"length": 254,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol",
"is_dependency": false,
"lines": [
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18
],
"starting_column": 1,
"ending_column": 0
}
},
"signature": "test()"
}
}
}
},
{
"type": "contract",
"name": "RedundantStatementsContract",
"source_mapping": {
"start": 66,
"length": 254,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol",
"is_dependency": false,
"lines": [
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18
],
"starting_column": 1,
"ending_column": 0
}
}
],
"description": "Redundant expression \"test (tests/detectors/redundant-statements/redundant_statements.sol#14)\" inRedundantStatementsContract (tests/detectors/redundant-statements/redundant_statements.sol#3-18)\n",
"markdown": "Redundant expression \"[test](tests/detectors/redundant-statements/redundant_statements.sol#L14)\" in[RedundantStatementsContract](tests/detectors/redundant-statements/redundant_statements.sol#L3-L18)\n",
"id": "ac50e063af6ebd33a702aa136415f7babc5fef3dc5212730b054d8a089b04e23",
"check": "redundant-statements",
"impact": "Informational",
"confidence": "High"
}
]
]

@ -0,0 +1,37 @@
contract A{
uint num = 5;
constructor(uint x) public{
num += x;
}
}
contract B is A{
constructor(uint y) A(y * 3) public{
}
}
contract C is B{
constructor(uint y) A(y * 2) public{
}
}
contract D is B(1), C(1) {
constructor() B(3) C(2) public {
}
}
contract E is B(1), C, D() {
constructor() B(1) C(2) D() public {
}
}
contract F is B {
constructor() A(1) public {
}
}

@ -0,0 +1,45 @@
pragma solidity ^0.5.8;
contract A {
int[3] intArray; // storage signed integer array
uint[3] uintArray; // storage unsigned integer array
/* Signed integer array initializations with literal arrays are vulnerable */
function bad0() public {
intArray = [-1, -2, -3];
}
/* Signed integer array assignments are vulnerable if the base types are different e.g. int256 vs int128 */
function bad1(int128[3] memory userArray) public {
intArray = userArray;
}
/* Unsigned Int array initializations are not vulnerable */
function good0() public {
uintArray = [0, 1, 2];
}
/* Unsigned Int array assignments are not vulnerable */
function good1(uint[3] memory userArray) public {
uintArray = userArray;
}
/* Assigning individual array elements are not vulnerable */
function good2() public {
intArray[1] = -1;
}
/* Assignment between two signed integer arrays of same base type int256 are not vulnerable */
function good3(int[3] memory userArray) public {
intArray = userArray;
}
/* Array literal initialization of in-memory signed integer arrays are not vulnerable */
function good4() public {
int8[3] memory memIntArray;
memIntArray = [-1, -2, -3];
}
}

@ -0,0 +1,516 @@
[
[
{
"elements": [
{
"type": "contract",
"name": "A",
"source_mapping": {
"start": 25,
"length": 2256,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/storage-array/storage_signed_integer_array.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/storage-array/storage_signed_integer_array.sol",
"is_dependency": false,
"lines": [
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45
],
"starting_column": 1,
"ending_column": 2
}
},
{
"type": "function",
"name": "bad0",
"source_mapping": {
"start": 355,
"length": 132,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/storage-array/storage_signed_integer_array.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/storage-array/storage_signed_integer_array.sol",
"is_dependency": false,
"lines": [
10,
11,
12
],
"starting_column": 3,
"ending_column": 4
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "A",
"source_mapping": {
"start": 25,
"length": 2256,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/storage-array/storage_signed_integer_array.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/storage-array/storage_signed_integer_array.sol",
"is_dependency": false,
"lines": [
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "bad0()"
}
},
{
"type": "node",
"name": "intArray = (- 1,- 2,- 3)",
"source_mapping": {
"start": 384,
"length": 23,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/storage-array/storage_signed_integer_array.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/storage-array/storage_signed_integer_array.sol",
"is_dependency": false,
"lines": [
11
],
"starting_column": 5,
"ending_column": 28
},
"type_specific_fields": {
"parent": {
"type": "function",
"name": "bad0",
"source_mapping": {
"start": 355,
"length": 132,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/storage-array/storage_signed_integer_array.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/storage-array/storage_signed_integer_array.sol",
"is_dependency": false,
"lines": [
10,
11,
12
],
"starting_column": 3,
"ending_column": 4
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "A",
"source_mapping": {
"start": 25,
"length": 2256,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/storage-array/storage_signed_integer_array.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/storage-array/storage_signed_integer_array.sol",
"is_dependency": false,
"lines": [
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "bad0()"
}
}
}
}
],
"description": "Contract A (tests/detectors/storage-array/storage_signed_integer_array.sol#3-45) \n\t- Function A.bad0() (tests/detectors/storage-array/storage_signed_integer_array.sol#10-12)\n\t\t- intArray = (- 1,- 2,- 3) (tests/detectors/storage-array/storage_signed_integer_array.sol#11) has a storage signed integer array assignment\n",
"markdown": "Contract [A](tests/detectors/storage-array/storage_signed_integer_array.sol#L3-L45) \n\t- Function [A.bad0()](tests/detectors/storage-array/storage_signed_integer_array.sol#L10-L12)\n\t\t- [intArray = (- 1,- 2,- 3)](tests/detectors/storage-array/storage_signed_integer_array.sol#L11) has a storage signed integer array assignment\n",
"id": "9301f6205d07f9bc40477e940ab7093092a8616caab1c78a2b84412ff6dd2eb1",
"check": "storage-array",
"impact": "High",
"confidence": "Medium"
},
{
"elements": [
{
"type": "contract",
"name": "A",
"source_mapping": {
"start": 25,
"length": 2256,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/storage-array/storage_signed_integer_array.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/storage-array/storage_signed_integer_array.sol",
"is_dependency": false,
"lines": [
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45
],
"starting_column": 1,
"ending_column": 2
}
},
{
"type": "function",
"name": "bad1",
"source_mapping": {
"start": 601,
"length": 170,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/storage-array/storage_signed_integer_array.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/storage-array/storage_signed_integer_array.sol",
"is_dependency": false,
"lines": [
15,
16,
17
],
"starting_column": 3,
"ending_column": 4
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "A",
"source_mapping": {
"start": 25,
"length": 2256,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/storage-array/storage_signed_integer_array.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/storage-array/storage_signed_integer_array.sol",
"is_dependency": false,
"lines": [
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "bad1(int128[3])"
}
},
{
"type": "node",
"name": "intArray = userArray",
"source_mapping": {
"start": 746,
"length": 20,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/storage-array/storage_signed_integer_array.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/storage-array/storage_signed_integer_array.sol",
"is_dependency": false,
"lines": [
16
],
"starting_column": 5,
"ending_column": 25
},
"type_specific_fields": {
"parent": {
"type": "function",
"name": "bad1",
"source_mapping": {
"start": 601,
"length": 170,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/storage-array/storage_signed_integer_array.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/storage-array/storage_signed_integer_array.sol",
"is_dependency": false,
"lines": [
15,
16,
17
],
"starting_column": 3,
"ending_column": 4
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "A",
"source_mapping": {
"start": 25,
"length": 2256,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/storage-array/storage_signed_integer_array.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/storage-array/storage_signed_integer_array.sol",
"is_dependency": false,
"lines": [
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "bad1(int128[3])"
}
}
}
}
],
"description": "Contract A (tests/detectors/storage-array/storage_signed_integer_array.sol#3-45) \n\t- Function A.bad1(int128[3]) (tests/detectors/storage-array/storage_signed_integer_array.sol#15-17)\n\t\t- intArray = userArray (tests/detectors/storage-array/storage_signed_integer_array.sol#16) has a storage signed integer array assignment\n",
"markdown": "Contract [A](tests/detectors/storage-array/storage_signed_integer_array.sol#L3-L45) \n\t- Function [A.bad1(int128[3])](tests/detectors/storage-array/storage_signed_integer_array.sol#L15-L17)\n\t\t- [intArray = userArray](tests/detectors/storage-array/storage_signed_integer_array.sol#L16) has a storage signed integer array assignment\n",
"id": "e91a19803d53092184a9c091054f1ef371c8e5f9db15c5be6979bc4d06b70362",
"check": "storage-array",
"impact": "High",
"confidence": "Medium"
}
]
]

@ -0,0 +1,41 @@
interface BaseInterface {
function f1() external returns(uint);
function f2() external returns(uint);
}
interface BaseInterface2 {
function f3() external returns(uint);
}
contract DerivedContract_bad0 is BaseInterface, BaseInterface2 {
function f1() external returns(uint){
return 42;
}
}
contract AbstractContract_bad1 {
function f1() external returns(uint);
function f2() external returns(uint){
return 42;
}
}
contract BaseInterface3 {
function get(uint) external returns(uint);
}
contract DerivedContract_bad2 is BaseInterface3 {
// the mapping type get(uint => bool) does NOT match the function get(uint) => uint
mapping(uint => bool) public get;
function f1() external returns(uint){
return 42;
}
}
contract DerivedContract_good is BaseInterface3 {
// In solc >= 0.5.1, the mapping type get(uint => uint) matches the function get(uint) => uint
mapping(uint => uint) public get;
function f1() external returns(uint){
return 42;
}
}

@ -0,0 +1,346 @@
[
[
{
"elements": [
{
"type": "contract",
"name": "DerivedContract_bad0",
"source_mapping": {
"start": 185,
"length": 133,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/unimplemented-functions/unimplemented.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/unimplemented-functions/unimplemented.sol",
"is_dependency": false,
"lines": [
10,
11,
12,
13,
14
],
"starting_column": 1,
"ending_column": 2
}
},
{
"type": "function",
"name": "f2",
"source_mapping": {
"start": 72,
"length": 37,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/unimplemented-functions/unimplemented.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/unimplemented-functions/unimplemented.sol",
"is_dependency": false,
"lines": [
3
],
"starting_column": 5,
"ending_column": 42
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "BaseInterface",
"source_mapping": {
"start": 0,
"length": 111,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/unimplemented-functions/unimplemented.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/unimplemented-functions/unimplemented.sol",
"is_dependency": false,
"lines": [
1,
2,
3,
4
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "f2()"
}
},
{
"type": "function",
"name": "f3",
"source_mapping": {
"start": 144,
"length": 37,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/unimplemented-functions/unimplemented.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/unimplemented-functions/unimplemented.sol",
"is_dependency": false,
"lines": [
7
],
"starting_column": 5,
"ending_column": 42
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "BaseInterface2",
"source_mapping": {
"start": 113,
"length": 70,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/unimplemented-functions/unimplemented.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/unimplemented-functions/unimplemented.sol",
"is_dependency": false,
"lines": [
6,
7,
8
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "f3()"
}
}
],
"description": "DerivedContract_bad0 (tests/detectors/unimplemented-functions/unimplemented.sol#10-14) does not implement functions:\n\t- BaseInterface.f2() (tests/detectors/unimplemented-functions/unimplemented.sol#3)\n\t- BaseInterface2.f3() (tests/detectors/unimplemented-functions/unimplemented.sol#7)\n",
"markdown": "[DerivedContract_bad0](tests/detectors/unimplemented-functions/unimplemented.sol#L10-L14) does not implement functions:\n\t- [BaseInterface.f2()](tests/detectors/unimplemented-functions/unimplemented.sol#L3)\n\t- [BaseInterface2.f3()](tests/detectors/unimplemented-functions/unimplemented.sol#L7)\n",
"id": "8614d351f7aac0c05e8df6ef7c89c6b46a2b8acf6295c9d5a886ff6489c74a41",
"check": "unimplemented-functions",
"impact": "Informational",
"confidence": "High"
},
{
"elements": [
{
"type": "contract",
"name": "AbstractContract_bad1",
"source_mapping": {
"start": 320,
"length": 143,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/unimplemented-functions/unimplemented.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/unimplemented-functions/unimplemented.sol",
"is_dependency": false,
"lines": [
16,
17,
18,
19,
20,
21
],
"starting_column": 1,
"ending_column": 2
}
},
{
"type": "function",
"name": "f1",
"source_mapping": {
"start": 357,
"length": 37,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/unimplemented-functions/unimplemented.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/unimplemented-functions/unimplemented.sol",
"is_dependency": false,
"lines": [
17
],
"starting_column": 5,
"ending_column": 42
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "AbstractContract_bad1",
"source_mapping": {
"start": 320,
"length": 143,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/unimplemented-functions/unimplemented.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/unimplemented-functions/unimplemented.sol",
"is_dependency": false,
"lines": [
16,
17,
18,
19,
20,
21
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "f1()"
}
}
],
"description": "AbstractContract_bad1 (tests/detectors/unimplemented-functions/unimplemented.sol#16-21) does not implement functions:\n\t- AbstractContract_bad1.f1() (tests/detectors/unimplemented-functions/unimplemented.sol#17)\n",
"markdown": "[AbstractContract_bad1](tests/detectors/unimplemented-functions/unimplemented.sol#L16-L21) does not implement functions:\n\t- [AbstractContract_bad1.f1()](tests/detectors/unimplemented-functions/unimplemented.sol#L17)\n",
"id": "adc202df4717efc4e19b549c0e623a79fac759a36bffb5d5e4aac401e33375d7",
"check": "unimplemented-functions",
"impact": "Informational",
"confidence": "High"
},
{
"elements": [
{
"type": "contract",
"name": "DerivedContract_bad2",
"source_mapping": {
"start": 541,
"length": 232,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/unimplemented-functions/unimplemented.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/unimplemented-functions/unimplemented.sol",
"is_dependency": false,
"lines": [
27,
28,
29,
30,
31,
32,
33
],
"starting_column": 1,
"ending_column": 2
}
},
{
"type": "function",
"name": "get",
"source_mapping": {
"start": 495,
"length": 42,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/unimplemented-functions/unimplemented.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/unimplemented-functions/unimplemented.sol",
"is_dependency": false,
"lines": [
24
],
"starting_column": 5,
"ending_column": 47
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "BaseInterface3",
"source_mapping": {
"start": 465,
"length": 74,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/unimplemented-functions/unimplemented.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/unimplemented-functions/unimplemented.sol",
"is_dependency": false,
"lines": [
23,
24,
25
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "get(uint256)"
}
}
],
"description": "DerivedContract_bad2 (tests/detectors/unimplemented-functions/unimplemented.sol#27-33) does not implement functions:\n\t- BaseInterface3.get(uint256) (tests/detectors/unimplemented-functions/unimplemented.sol#24)\n",
"markdown": "[DerivedContract_bad2](tests/detectors/unimplemented-functions/unimplemented.sol#L27-L33) does not implement functions:\n\t- [BaseInterface3.get(uint256)](tests/detectors/unimplemented-functions/unimplemented.sol#L24)\n",
"id": "31915d2f480e24ddd054de973440a02abdac0ccd6332c47cd4eb8d836d3fddda",
"check": "unimplemented-functions",
"impact": "Informational",
"confidence": "High"
},
{
"elements": [
{
"type": "contract",
"name": "DerivedContract_good",
"source_mapping": {
"start": 775,
"length": 243,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/unimplemented-functions/unimplemented.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/unimplemented-functions/unimplemented.sol",
"is_dependency": false,
"lines": [
35,
36,
37,
38,
39,
40,
41
],
"starting_column": 1,
"ending_column": 2
}
},
{
"type": "function",
"name": "get",
"source_mapping": {
"start": 495,
"length": 42,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/unimplemented-functions/unimplemented.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/unimplemented-functions/unimplemented.sol",
"is_dependency": false,
"lines": [
24
],
"starting_column": 5,
"ending_column": 47
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "BaseInterface3",
"source_mapping": {
"start": 465,
"length": 74,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/unimplemented-functions/unimplemented.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/unimplemented-functions/unimplemented.sol",
"is_dependency": false,
"lines": [
23,
24,
25
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "get(uint256)"
}
}
],
"description": "DerivedContract_good (tests/detectors/unimplemented-functions/unimplemented.sol#35-41) does not implement functions:\n\t- BaseInterface3.get(uint256) (tests/detectors/unimplemented-functions/unimplemented.sol#24)\n",
"markdown": "[DerivedContract_good](tests/detectors/unimplemented-functions/unimplemented.sol#L35-L41) does not implement functions:\n\t- [BaseInterface3.get(uint256)](tests/detectors/unimplemented-functions/unimplemented.sol#L24)\n",
"id": "08d3e8a72b5da6d189acb46ecd36f00787a87812727526a0cae248a2bac348fc",
"check": "unimplemented-functions",
"impact": "Informational",
"confidence": "High"
}
]
]

@ -0,0 +1,136 @@
pragma solidity 0.5.8;
contract bad0 {
constructor() public {
/* Uninitialized function pointer */
function(uint256) internal returns(uint256) a;
a(10);
}
}
contract bad1 {
constructor() public {
/* Uninitialized function pointer but external visibility */
/* Although the Solidity bug report does not specify external visibility, we believe both internal/external may be vulnerable */
function(uint256) external returns(uint256) b;
b(10);
}
}
contract bad2 {
struct S {
/* Uninitialized function pointer within a struct*/
function(uint256) internal returns(uint256) a;
}
constructor() public {
S memory s;
s.a(10);
}
}
contract bad3 {
/* Uninitialized state variable function pointer written-to after call */
function(uint256) internal returns(uint256) a;
constructor() public {
a(10);
a = foo;
}
function foo(uint256 i) internal returns(uint256) {
return(i);
}
}
contract good0 {
constructor() public {
/* Uninitialized function pointer but not called */
function(uint256) internal returns(uint256) a;
}
}
contract good1 {
constructor() public {
/* Initialized function pointer */
function(uint256) internal returns(uint256) a = foo;
a(10);
}
function foo(uint256 i) internal returns(uint256) {
return(i);
}
}
contract good2 {
constructor() public {
}
function foo(uint256 i) internal returns(uint256) {
/* Uninitialized function pointer but not in constructor */
function(uint256) internal returns(uint256) a;
a(10);
return(i);
}
}
contract good3 {
constructor() public {
/* Normal function call */
foo(10);
}
function foo(uint256 i) internal returns(uint256) {
return(i);
}
}
contract good4 {
struct S {
uint S_i;
}
constructor() public {
/* Uninitialized variables of other types but not function pointer */
uint i;
address addr;
uint[] memory arr;
S memory s;
}
}
contract good5 {
constructor() public {
/* Uninitialized local function pointer written to later */
function(uint256) internal returns(uint256) a;
a = foo;
a(10);
}
function foo(uint256 i) internal returns(uint256) {
return(i);
}
}
contract good6 {
/* Uninitialized state variable function pointer written to later */
function(uint256) internal returns(uint256) a;
constructor() public {
a = foo;
a(10);
}
function foo(uint256 i) internal returns(uint256) {
return(i);
}
}
contract good7 {
struct S {
/* Uninitialized function pointer within a struct*/
function(uint256) internal returns(uint256) a;
}
constructor() public {
S memory s;
s.a = foo;
s.a(10);
}
function foo(uint256 i) internal returns(uint256) {
return(i);
}
}

@ -0,0 +1,325 @@
[
[
{
"elements": [
{
"type": "contract",
"name": "bad0",
"source_mapping": {
"start": 24,
"length": 149,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol",
"is_dependency": false,
"lines": [
3,
4,
5,
6,
7,
8,
9
],
"starting_column": 1,
"ending_column": 2
}
},
{
"type": "node",
"name": "a(10)",
"source_mapping": {
"start": 161,
"length": 5,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol",
"is_dependency": false,
"lines": [
7
],
"starting_column": 5,
"ending_column": 10
},
"type_specific_fields": {
"parent": {
"type": "function",
"name": "constructor",
"source_mapping": {
"start": 42,
"length": 129,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol",
"is_dependency": false,
"lines": [
4,
5,
6,
7,
8
],
"starting_column": 3,
"ending_column": 4
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "bad0",
"source_mapping": {
"start": 24,
"length": 149,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol",
"is_dependency": false,
"lines": [
3,
4,
5,
6,
7,
8,
9
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "constructor()"
}
}
}
}
],
"description": "Contract bad0 (tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol#3-9) \n\t a(10) (tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol#7) is an unintialized function pointer call in a constructor\n",
"markdown": "Contract [bad0](tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol#L3-L9) \n\t [a(10)](tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol#L7) is an unintialized function pointer call in a constructor\n",
"id": "6e9480c70e9d054243bb478398b26663f05444b4b9b858109d67f9c63dbbc3e2",
"check": "uninitialized-fptr-cst",
"impact": "Low",
"confidence": "High"
},
{
"elements": [
{
"type": "contract",
"name": "bad1",
"source_mapping": {
"start": 175,
"length": 306,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol",
"is_dependency": false,
"lines": [
11,
12,
13,
14,
15,
16,
17,
18
],
"starting_column": 1,
"ending_column": 2
}
},
{
"type": "node",
"name": "b(10)",
"source_mapping": {
"start": 469,
"length": 5,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol",
"is_dependency": false,
"lines": [
16
],
"starting_column": 5,
"ending_column": 10
},
"type_specific_fields": {
"parent": {
"type": "function",
"name": "constructor",
"source_mapping": {
"start": 193,
"length": 286,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol",
"is_dependency": false,
"lines": [
12,
13,
14,
15,
16,
17
],
"starting_column": 3,
"ending_column": 4
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "bad1",
"source_mapping": {
"start": 175,
"length": 306,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol",
"is_dependency": false,
"lines": [
11,
12,
13,
14,
15,
16,
17,
18
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "constructor()"
}
}
}
}
],
"description": "Contract bad1 (tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol#11-18) \n\t b(10) (tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol#16) is an unintialized function pointer call in a constructor\n",
"markdown": "Contract [bad1](tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol#L11-L18) \n\t [b(10)](tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol#L16) is an unintialized function pointer call in a constructor\n",
"id": "b0a15c051d9962762902c5565802334898e572e98018b42b85a89b45208c50d2",
"check": "uninitialized-fptr-cst",
"impact": "Low",
"confidence": "High"
},
{
"elements": [
{
"type": "contract",
"name": "bad3",
"source_mapping": {
"start": 684,
"length": 269,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol",
"is_dependency": false,
"lines": [
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42
],
"starting_column": 1,
"ending_column": 2
}
},
{
"type": "node",
"name": "a(10)",
"source_mapping": {
"start": 855,
"length": 5,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol",
"is_dependency": false,
"lines": [
36
],
"starting_column": 5,
"ending_column": 10
},
"type_specific_fields": {
"parent": {
"type": "function",
"name": "constructor",
"source_mapping": {
"start": 828,
"length": 50,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol",
"is_dependency": false,
"lines": [
35,
36,
37,
38
],
"starting_column": 3,
"ending_column": 4
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "bad3",
"source_mapping": {
"start": 684,
"length": 269,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol",
"is_dependency": false,
"lines": [
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "constructor()"
}
}
}
}
],
"description": "Contract bad3 (tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol#31-42) \n\t a(10) (tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol#36) is an unintialized function pointer call in a constructor\n",
"markdown": "Contract [bad3](tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol#L31-L42) \n\t [a(10)](tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol#L36) is an unintialized function pointer call in a constructor\n",
"id": "1f12cc039e869f6f13be8a85e2d98a53212dc95e859908a9188dd6b152fb804f",
"check": "uninitialized-fptr-cst",
"impact": "Low",
"confidence": "High"
}
]
]

@ -0,0 +1,28 @@
contract BadPRNG{
event Time(uint);
function bad0() external{
uint i = block.timestamp % 10;
}
function bad1() external{
uint i = now % 10;
}
function bad2() external{
uint i = uint256(blockhash(10000)) % 10;
}
function foo() public returns (uint) {
return(uint256(blockhash(10000)));
}
function bad3() external{
uint i = foo() % 10;
}
function good() external{
emit Time(block.timestamp);
}
}

@ -0,0 +1,660 @@
[
[
{
"elements": [
{
"type": "function",
"name": "bad0",
"source_mapping": {
"start": 45,
"length": 68,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/weak-prng/bad_prng.sol",
"is_dependency": false,
"lines": [
4,
5,
6
],
"starting_column": 5,
"ending_column": 6
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "BadPRNG",
"source_mapping": {
"start": 0,
"length": 499,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/weak-prng/bad_prng.sol",
"is_dependency": false,
"lines": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "bad0()"
}
},
{
"type": "node",
"name": "i = block.timestamp % 10",
"source_mapping": {
"start": 77,
"length": 29,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/weak-prng/bad_prng.sol",
"is_dependency": false,
"lines": [
5
],
"starting_column": 7,
"ending_column": 36
},
"type_specific_fields": {
"parent": {
"type": "function",
"name": "bad0",
"source_mapping": {
"start": 45,
"length": 68,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/weak-prng/bad_prng.sol",
"is_dependency": false,
"lines": [
4,
5,
6
],
"starting_column": 5,
"ending_column": 6
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "BadPRNG",
"source_mapping": {
"start": 0,
"length": 499,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/weak-prng/bad_prng.sol",
"is_dependency": false,
"lines": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "bad0()"
}
}
}
}
],
"description": "BadPRNG.bad0() (tests/detectors/weak-prng/bad_prng.sol#4-6) uses a weak PRNG: \"i = block.timestamp % 10 (tests/detectors/weak-prng/bad_prng.sol#5)\" \n",
"markdown": "[BadPRNG.bad0()](tests/detectors/weak-prng/bad_prng.sol#L4-L6) uses a weak PRNG: \"[i = block.timestamp % 10](tests/detectors/weak-prng/bad_prng.sol#L5)\" \n",
"id": "af624d9c7f3f688c1bad5ecaee81085e0d5cde4e6a55de34ff93684527619748",
"check": "weak-prng",
"impact": "High",
"confidence": "Medium"
},
{
"elements": [
{
"type": "function",
"name": "bad1",
"source_mapping": {
"start": 122,
"length": 56,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/weak-prng/bad_prng.sol",
"is_dependency": false,
"lines": [
8,
9,
10
],
"starting_column": 5,
"ending_column": 6
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "BadPRNG",
"source_mapping": {
"start": 0,
"length": 499,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/weak-prng/bad_prng.sol",
"is_dependency": false,
"lines": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "bad1()"
}
},
{
"type": "node",
"name": "i = now % 10",
"source_mapping": {
"start": 154,
"length": 17,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/weak-prng/bad_prng.sol",
"is_dependency": false,
"lines": [
9
],
"starting_column": 7,
"ending_column": 24
},
"type_specific_fields": {
"parent": {
"type": "function",
"name": "bad1",
"source_mapping": {
"start": 122,
"length": 56,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/weak-prng/bad_prng.sol",
"is_dependency": false,
"lines": [
8,
9,
10
],
"starting_column": 5,
"ending_column": 6
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "BadPRNG",
"source_mapping": {
"start": 0,
"length": 499,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/weak-prng/bad_prng.sol",
"is_dependency": false,
"lines": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "bad1()"
}
}
}
}
],
"description": "BadPRNG.bad1() (tests/detectors/weak-prng/bad_prng.sol#8-10) uses a weak PRNG: \"i = now % 10 (tests/detectors/weak-prng/bad_prng.sol#9)\" \n",
"markdown": "[BadPRNG.bad1()](tests/detectors/weak-prng/bad_prng.sol#L8-L10) uses a weak PRNG: \"[i = now % 10](tests/detectors/weak-prng/bad_prng.sol#L9)\" \n",
"id": "fe07d1e4f27274570cfb85530c1cbf7fb7a9004f475b91d1a3762452b017e1b9",
"check": "weak-prng",
"impact": "High",
"confidence": "Medium"
},
{
"elements": [
{
"type": "function",
"name": "bad2",
"source_mapping": {
"start": 184,
"length": 78,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/weak-prng/bad_prng.sol",
"is_dependency": false,
"lines": [
12,
13,
14
],
"starting_column": 5,
"ending_column": 6
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "BadPRNG",
"source_mapping": {
"start": 0,
"length": 499,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/weak-prng/bad_prng.sol",
"is_dependency": false,
"lines": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "bad2()"
}
},
{
"type": "node",
"name": "i = uint256(blockhash(uint256)(10000)) % 10",
"source_mapping": {
"start": 216,
"length": 39,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/weak-prng/bad_prng.sol",
"is_dependency": false,
"lines": [
13
],
"starting_column": 7,
"ending_column": 46
},
"type_specific_fields": {
"parent": {
"type": "function",
"name": "bad2",
"source_mapping": {
"start": 184,
"length": 78,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/weak-prng/bad_prng.sol",
"is_dependency": false,
"lines": [
12,
13,
14
],
"starting_column": 5,
"ending_column": 6
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "BadPRNG",
"source_mapping": {
"start": 0,
"length": 499,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/weak-prng/bad_prng.sol",
"is_dependency": false,
"lines": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "bad2()"
}
}
}
}
],
"description": "BadPRNG.bad2() (tests/detectors/weak-prng/bad_prng.sol#12-14) uses a weak PRNG: \"i = uint256(blockhash(uint256)(10000)) % 10 (tests/detectors/weak-prng/bad_prng.sol#13)\" \n",
"markdown": "[BadPRNG.bad2()](tests/detectors/weak-prng/bad_prng.sol#L12-L14) uses a weak PRNG: \"[i = uint256(blockhash(uint256)(10000)) % 10](tests/detectors/weak-prng/bad_prng.sol#L13)\" \n",
"id": "100d285386f797a469c6797fcce41350b1984f7e7aab1532580d9b69a774b6f5",
"check": "weak-prng",
"impact": "High",
"confidence": "Medium"
},
{
"elements": [
{
"type": "function",
"name": "bad3",
"source_mapping": {
"start": 363,
"length": 58,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/weak-prng/bad_prng.sol",
"is_dependency": false,
"lines": [
20,
21,
22
],
"starting_column": 5,
"ending_column": 6
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "BadPRNG",
"source_mapping": {
"start": 0,
"length": 499,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/weak-prng/bad_prng.sol",
"is_dependency": false,
"lines": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "bad3()"
}
},
{
"type": "node",
"name": "i = foo() % 10",
"source_mapping": {
"start": 395,
"length": 19,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/weak-prng/bad_prng.sol",
"is_dependency": false,
"lines": [
21
],
"starting_column": 7,
"ending_column": 26
},
"type_specific_fields": {
"parent": {
"type": "function",
"name": "bad3",
"source_mapping": {
"start": 363,
"length": 58,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/weak-prng/bad_prng.sol",
"is_dependency": false,
"lines": [
20,
21,
22
],
"starting_column": 5,
"ending_column": 6
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "BadPRNG",
"source_mapping": {
"start": 0,
"length": 499,
"filename_used": "/GENERIC_PATH",
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/weak-prng/bad_prng.sol",
"is_dependency": false,
"lines": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "bad3()"
}
}
}
}
],
"description": "BadPRNG.bad3() (tests/detectors/weak-prng/bad_prng.sol#20-22) uses a weak PRNG: \"i = foo() % 10 (tests/detectors/weak-prng/bad_prng.sol#21)\" \n",
"markdown": "[BadPRNG.bad3()](tests/detectors/weak-prng/bad_prng.sol#L20-L22) uses a weak PRNG: \"[i = foo() % 10](tests/detectors/weak-prng/bad_prng.sol#L21)\" \n",
"id": "a382f093e54d2c7beb2c10b3537790371f4b95545c48d1300fd25d20717d137a",
"check": "weak-prng",
"impact": "High",
"confidence": "Medium"
}
]
]

@ -10,48 +10,7 @@ from deepdiff import DeepDiff # pip install deepdiff
from slither import Slither
from slither.detectors.abstract_detector import AbstractDetector
from slither.detectors.attributes.const_functions_asm import ConstantFunctionsAsm
from slither.detectors.attributes.const_functions_state import ConstantFunctionsState
from slither.detectors.attributes.constant_pragma import ConstantPragma
from slither.detectors.attributes.incorrect_solc import IncorrectSolc
from slither.detectors.attributes.locked_ether import LockedEther
from slither.detectors.erc.incorrect_erc20_interface import IncorrectERC20InterfaceDetection
from slither.detectors.erc.incorrect_erc721_interface import IncorrectERC721InterfaceDetection
from slither.detectors.erc.unindexed_event_parameters import UnindexedERC20EventParameters
from slither.detectors.examples.backdoor import Backdoor
from slither.detectors.functions.arbitrary_send import ArbitrarySend
from slither.detectors.functions.external_function import ExternalFunction
from slither.detectors.functions.suicidal import Suicidal
from slither.detectors.naming_convention.naming_convention import NamingConvention
from slither.detectors.operations.block_timestamp import Timestamp
from slither.detectors.operations.low_level_calls import LowLevelCalls
from slither.detectors.operations.unchecked_low_level_return_values import UncheckedLowLevel
from slither.detectors.operations.unchecked_send_return_value import UncheckedSend
from slither.detectors.operations.unused_return_values import UnusedReturnValues
from slither.detectors.operations.void_constructor import VoidConstructor
from slither.detectors.reentrancy.reentrancy_eth import ReentrancyEth
from slither.detectors.reentrancy.reentrancy_events import ReentrancyEvent
from slither.detectors.shadowing.abstract import ShadowingAbstractDetection
from slither.detectors.shadowing.builtin_symbols import BuiltinSymbolShadowing
from slither.detectors.shadowing.local import LocalShadowing
from slither.detectors.shadowing.state import StateShadowing
from slither.detectors.source.rtlo import RightToLeftOverride
from slither.detectors.statements.assembly import Assembly
from slither.detectors.statements.boolean_constant_misuse import BooleanConstantMisuse
from slither.detectors.statements.boolean_constant_equality import BooleanEquality
from slither.detectors.statements.calls_in_loop import MultipleCallsInLoop
from slither.detectors.statements.controlled_delegatecall import ControlledDelegateCall
from slither.detectors.statements.incorrect_strict_equality import IncorrectStrictEquality
from slither.detectors.statements.too_many_digits import TooManyDigits
from slither.detectors.statements.tx_origin import TxOrigin
from slither.detectors.statements.unprotected_upgradeable import UnprotectedUpgradeable
from slither.detectors.variables.possible_const_state_variables import ConstCandidateStateVars
from slither.detectors.variables.uninitialized_local_variables import UninitializedLocalVars
from slither.detectors.variables.uninitialized_state_variables import (
UninitializedStateVarsDetection,
)
from slither.detectors.variables.uninitialized_storage_variables import UninitializedStorageVars
from slither.detectors.variables.unused_state_variables import UnusedStateVars
from slither.detectors import all_detectors
class Test: # pylint: disable=too-few-public-methods
@ -95,153 +54,330 @@ def id_test(test_item: Test):
ALL_TESTS = [
Test(
BooleanEquality,
all_detectors.BooleanEquality,
"tests/detectors/boolean-constant-equality/boolean-constant-equality.sol",
"0.4.25",
),
Test(
BooleanConstantMisuse,
all_detectors.BooleanConstantMisuse,
"tests/detectors/boolean-constant-misuse/boolean-constant-misuse.sol",
"0.6.0",
),
Test(UncheckedLowLevel, "tests/detectors/unchecked-lowlevel/unchecked_lowlevel.sol", "0.4.25"),
Test(
UncheckedLowLevel,
all_detectors.UncheckedLowLevel,
"tests/detectors/unchecked-lowlevel/unchecked_lowlevel.sol",
"0.4.25",
),
Test(
all_detectors.UncheckedLowLevel,
"tests/detectors/unchecked-lowlevel/unchecked_lowlevel-0.5.1.sol",
"0.5.1",
),
Test(
UncheckedLowLevel,
all_detectors.UncheckedLowLevel,
"tests/detectors/unchecked-lowlevel/unchecked_lowlevel-0.5.1.sol",
"0.5.1",
),
Test(
UnindexedERC20EventParameters, "tests/detectors/erc20-indexed/erc20_indexed.sol", "0.4.25"
all_detectors.UnindexedERC20EventParameters,
"tests/detectors/erc20-indexed/erc20_indexed.sol",
"0.4.25",
),
Test(
IncorrectERC20InterfaceDetection,
all_detectors.IncorrectERC20InterfaceDetection,
"tests/detectors/erc20-interface/incorrect_erc20_interface.sol",
"0.4.25",
),
Test(
IncorrectERC721InterfaceDetection,
all_detectors.IncorrectERC721InterfaceDetection,
"tests/detectors/erc721-interface/incorrect_erc721_interface.sol",
"0.4.25",
),
Test(
UninitializedStateVarsDetection,
all_detectors.UninitializedStateVarsDetection,
"tests/detectors/uninitialized-state/uninitialized.sol",
"0.4.25",
),
Test(
UninitializedStateVarsDetection,
all_detectors.UninitializedStateVarsDetection,
"tests/detectors/uninitialized-state/uninitialized-0.5.1.sol",
"0.5.1",
),
Test(Backdoor, "tests/detectors/backdoor/backdoor.sol", "0.4.25"),
Test(Backdoor, "tests/detectors/backdoor/backdoor.sol", "0.5.1"),
Test(Suicidal, "tests/detectors/backdoor/backdoor.sol", "0.4.25"),
Test(Suicidal, "tests/detectors/backdoor/backdoor.sol", "0.5.1"),
Test(all_detectors.Backdoor, "tests/detectors/backdoor/backdoor.sol", "0.4.25"),
Test(all_detectors.Backdoor, "tests/detectors/backdoor/backdoor.sol", "0.5.1"),
Test(all_detectors.Suicidal, "tests/detectors/backdoor/backdoor.sol", "0.4.25"),
Test(all_detectors.Suicidal, "tests/detectors/backdoor/backdoor.sol", "0.5.1"),
Test(
ConstantPragma,
all_detectors.ConstantPragma,
"tests/detectors/pragma/pragma.0.4.24.sol",
"0.4.25",
["tests/detectors/pragma/pragma.0.4.23.sol"],
),
Test(IncorrectSolc, "tests/detectors/solc-version/old_solc.sol", "0.4.21"),
Test(IncorrectSolc, "tests/detectors/solc-version/solc_version_incorrect.sol", "0.4.25"),
Test(IncorrectSolc, "tests/detectors/solc-version/solc_version_incorrect_05.sol", "0.5.7"),
Test(ReentrancyEth, "tests/detectors/reentrancy-eth/reentrancy.sol", "0.4.25"),
Test(ReentrancyEth, "tests/detectors/reentrancy-eth/reentrancy_indirect.sol", "0.4.25"),
Test(ReentrancyEth, "tests/detectors/reentrancy-eth/reentrancy-0.5.1.sol", "0.5.1"),
Test(all_detectors.IncorrectSolc, "tests/detectors/solc-version/old_solc.sol", "0.4.21"),
Test(
UninitializedStorageVars,
all_detectors.IncorrectSolc,
"tests/detectors/solc-version/solc_version_incorrect.sol",
"0.4.25",
),
Test(
all_detectors.IncorrectSolc,
"tests/detectors/solc-version/solc_version_incorrect_05.sol",
"0.5.7",
),
Test(all_detectors.ReentrancyEth, "tests/detectors/reentrancy-eth/reentrancy.sol", "0.4.25"),
Test(
all_detectors.ReentrancyEth,
"tests/detectors/reentrancy-eth/reentrancy_indirect.sol",
"0.4.25",
),
Test(
all_detectors.ReentrancyEth, "tests/detectors/reentrancy-eth/reentrancy-0.5.1.sol", "0.5.1"
),
Test(
all_detectors.UninitializedStorageVars,
"tests/detectors/uninitialized-storage/uninitialized_storage_pointer.sol",
"0.4.25",
),
Test(TxOrigin, "tests/detectors/tx-origin/tx_origin.sol", "0.4.25"),
Test(TxOrigin, "tests/detectors/tx-origin/tx_origin-0.5.1.sol", "0.5.1"),
Test(UnusedStateVars, "tests/detectors/unused-state/unused_state.sol", "0.4.25"),
Test(UnusedStateVars, "tests/detectors/unused-state/unused_state.sol", "0.5.1"),
Test(LockedEther, "tests/detectors/locked-ether/locked_ether.sol", "0.4.25"),
Test(LockedEther, "tests/detectors/locked-ether/locked_ether-0.5.1.sol", "0.5.1"),
Test(ArbitrarySend, "tests/detectors/arbitrary-send/arbitrary_send.sol", "0.4.25"),
Test(ArbitrarySend, "tests/detectors/arbitrary-send/arbitrary_send-0.5.1.sol", "0.5.1"),
Test(Assembly, "tests/detectors/assembly/inline_assembly_contract.sol", "0.4.25"),
Test(Assembly, "tests/detectors/assembly/inline_assembly_library.sol", "0.4.25"),
Test(Assembly, "tests/detectors/assembly/inline_assembly_contract-0.5.1.sol", "0.5.1"),
Test(Assembly, "tests/detectors/assembly/inline_assembly_library-0.5.1.sol", "0.5.1"),
Test(LowLevelCalls, "tests/detectors/low-level-calls/low_level_calls.sol", "0.4.25"),
Test(LowLevelCalls, "tests/detectors/low-level-calls/low_level_calls.sol", "0.5.1"),
Test(
ConstCandidateStateVars,
Test(all_detectors.TxOrigin, "tests/detectors/tx-origin/tx_origin.sol", "0.4.25"),
Test(all_detectors.TxOrigin, "tests/detectors/tx-origin/tx_origin-0.5.1.sol", "0.5.1"),
Test(all_detectors.UnusedStateVars, "tests/detectors/unused-state/unused_state.sol", "0.4.25"),
Test(all_detectors.UnusedStateVars, "tests/detectors/unused-state/unused_state.sol", "0.5.1"),
Test(all_detectors.LockedEther, "tests/detectors/locked-ether/locked_ether.sol", "0.4.25"),
Test(all_detectors.LockedEther, "tests/detectors/locked-ether/locked_ether-0.5.1.sol", "0.5.1"),
Test(
all_detectors.ArbitrarySend, "tests/detectors/arbitrary-send/arbitrary_send.sol", "0.4.25"
),
Test(
all_detectors.ArbitrarySend,
"tests/detectors/arbitrary-send/arbitrary_send-0.5.1.sol",
"0.5.1",
),
Test(all_detectors.Assembly, "tests/detectors/assembly/inline_assembly_contract.sol", "0.4.25"),
Test(all_detectors.Assembly, "tests/detectors/assembly/inline_assembly_library.sol", "0.4.25"),
Test(
all_detectors.Assembly,
"tests/detectors/assembly/inline_assembly_contract-0.5.1.sol",
"0.5.1",
),
Test(
all_detectors.Assembly,
"tests/detectors/assembly/inline_assembly_library-0.5.1.sol",
"0.5.1",
),
Test(
all_detectors.LowLevelCalls, "tests/detectors/low-level-calls/low_level_calls.sol", "0.4.25"
),
Test(
all_detectors.LowLevelCalls, "tests/detectors/low-level-calls/low_level_calls.sol", "0.5.1"
),
Test(
all_detectors.ConstCandidateStateVars,
"tests/detectors/constable-states/const_state_variables.sol",
"0.4.25",
),
Test(
ConstCandidateStateVars,
all_detectors.ConstCandidateStateVars,
"tests/detectors/constable-states/const_state_variables.sol",
"0.5.1",
),
Test(ExternalFunction, "tests/detectors/external-function/external_function.sol", "0.4.25"),
Test(ExternalFunction, "tests/detectors/external-function/external_function_2.sol", "0.4.25"),
Test(ExternalFunction, "tests/detectors/external-function/external_function.sol", "0.5.1"),
Test(ExternalFunction, "tests/detectors/external-function/external_function_2.sol", "0.5.1"),
Test(NamingConvention, "tests/detectors/naming-convention/naming_convention.sol", "0.4.25"),
Test(NamingConvention, "tests/detectors/naming-convention/naming_convention.sol", "0.5.1"),
Test(
ControlledDelegateCall,
all_detectors.ExternalFunction,
"tests/detectors/external-function/external_function.sol",
"0.4.25",
),
Test(
all_detectors.ExternalFunction,
"tests/detectors/external-function/external_function_2.sol",
"0.4.25",
),
Test(
all_detectors.ExternalFunction,
"tests/detectors/external-function/external_function.sol",
"0.5.1",
),
Test(
all_detectors.ExternalFunction,
"tests/detectors/external-function/external_function_2.sol",
"0.5.1",
),
Test(
all_detectors.NamingConvention,
"tests/detectors/naming-convention/naming_convention.sol",
"0.4.25",
),
Test(
all_detectors.NamingConvention,
"tests/detectors/naming-convention/naming_convention.sol",
"0.5.1",
),
Test(
all_detectors.ControlledDelegateCall,
"tests/detectors/controlled-delegatecall/controlled_delegatecall.sol",
"0.4.25",
),
Test(
ControlledDelegateCall,
all_detectors.ControlledDelegateCall,
"tests/detectors/controlled-delegatecall/controlled_delegatecall.sol",
"0.5.1",
),
Test(
UninitializedLocalVars,
all_detectors.UninitializedLocalVars,
"tests/detectors/uninitialized-local/uninitialized_local_variable.sol",
"0.4.25",
),
Test(ConstantFunctionsAsm, "tests/detectors/constant/constant.sol", "0.4.25"),
Test(ConstantFunctionsState, "tests/detectors/constant/constant.sol", "0.4.25"),
Test(ConstantFunctionsAsm, "tests/detectors/constant/constant-0.5.1.sol", "0.5.1"),
Test(ConstantFunctionsState, "tests/detectors/constant/constant-0.5.1.sol", "0.5.1"),
Test(UnusedReturnValues, "tests/detectors/unused-return/unused_return.sol", "0.4.25"),
Test(UnusedReturnValues, "tests/detectors/unused-return/unused_return.sol", "0.5.1"),
Test(all_detectors.ConstantFunctionsAsm, "tests/detectors/constant/constant.sol", "0.4.25"),
Test(all_detectors.ConstantFunctionsState, "tests/detectors/constant/constant.sol", "0.4.25"),
Test(
all_detectors.ConstantFunctionsAsm, "tests/detectors/constant/constant-0.5.1.sol", "0.5.1"
),
Test(
all_detectors.ConstantFunctionsState, "tests/detectors/constant/constant-0.5.1.sol", "0.5.1"
),
Test(
ShadowingAbstractDetection,
all_detectors.UnusedReturnValues,
"tests/detectors/unused-return/unused_return.sol",
"0.4.25",
),
Test(
all_detectors.UnusedReturnValues, "tests/detectors/unused-return/unused_return.sol", "0.5.1"
),
Test(
all_detectors.ShadowingAbstractDetection,
"tests/detectors/shadowing-abstract/shadowing_abstract.sol",
"0.4.25",
),
Test(StateShadowing, "tests/detectors/shadowing-state/shadowing_state_variable.sol", "0.4.25"),
Test(Timestamp, "tests/detectors/timestamp/timestamp.sol", "0.4.25"),
Test(Timestamp, "tests/detectors/timestamp/timestamp.sol", "0.5.1"),
Test(MultipleCallsInLoop, "tests/detectors/calls-loop/multiple_calls_in_loop.sol", "0.4.25"),
Test(
BuiltinSymbolShadowing,
all_detectors.StateShadowing,
"tests/detectors/shadowing-state/shadowing_state_variable.sol",
"0.4.25",
),
Test(all_detectors.Timestamp, "tests/detectors/timestamp/timestamp.sol", "0.4.25"),
Test(all_detectors.Timestamp, "tests/detectors/timestamp/timestamp.sol", "0.5.1"),
Test(
all_detectors.MultipleCallsInLoop,
"tests/detectors/calls-loop/multiple_calls_in_loop.sol",
"0.4.25",
),
Test(
all_detectors.BuiltinSymbolShadowing,
"tests/detectors/shadowing-builtin/shadowing_builtin_symbols.sol",
"0.4.25",
),
Test(LocalShadowing, "tests/detectors/shadowing-local/shadowing_local_variable.sol", "0.4.25"),
Test(RightToLeftOverride, "tests/detectors/rtlo/right_to_left_override.sol", "0.4.25"),
Test(VoidConstructor, "tests/detectors/void-cst/void-cst.sol", "0.5.1"),
Test(UncheckedSend, "tests/detectors/unchecked-send/unchecked_send-0.5.1.sol", "0.5.1"),
Test(ReentrancyEvent, "tests/detectors/reentrancy-events/reentrancy-0.5.1-events.sol", "0.5.1"),
Test(
IncorrectStrictEquality,
all_detectors.LocalShadowing,
"tests/detectors/shadowing-local/shadowing_local_variable.sol",
"0.4.25",
),
Test(
all_detectors.RightToLeftOverride,
"tests/detectors/rtlo/right_to_left_override.sol",
"0.4.25",
),
Test(all_detectors.VoidConstructor, "tests/detectors/void-cst/void-cst.sol", "0.5.1"),
Test(
all_detectors.UncheckedSend,
"tests/detectors/unchecked-send/unchecked_send-0.5.1.sol",
"0.5.1",
),
Test(
all_detectors.ReentrancyEvent,
"tests/detectors/reentrancy-events/reentrancy-0.5.1-events.sol",
"0.5.1",
),
Test(
all_detectors.IncorrectStrictEquality,
"tests/detectors/incorrect-equality/incorrect_equality.sol",
"0.5.1",
),
Test(TooManyDigits, "tests/detectors/too-many-digits/too_many_digits.sol", "0.5.1"),
Test(UnprotectedUpgradeable, "tests/detectors/unprotected-upgrade/Buggy.sol", "0.6.12",),
Test(UnprotectedUpgradeable, "tests/detectors/unprotected-upgrade/Fixed.sol", "0.6.12",),
Test(
NamingConvention,
all_detectors.TooManyDigits, "tests/detectors/too-many-digits/too_many_digits.sol", "0.5.1"
),
Test(
all_detectors.UnprotectedUpgradeable,
"tests/detectors/unprotected-upgrade/Buggy.sol",
"0.6.12",
),
Test(
all_detectors.UnprotectedUpgradeable,
"tests/detectors/unprotected-upgrade/Fixed.sol",
"0.6.12",
),
Test(
all_detectors.NamingConvention,
"tests/detectors/naming-convention/naming_convention_ignore.sol",
"0.4.25",
),
Test(
all_detectors.ABIEncoderV2Array,
"tests/detectors/abiencoderv2-array/storage_ABIEncoderV2_array.sol",
"0.4.25",
),
Test(
all_detectors.ArrayByReference,
"tests/detectors/array-by-reference/array_by_reference.sol",
"0.4.25",
),
Test(
all_detectors.AssertStateChange,
"tests/detectors/assert-state-change/assert_state_change.sol",
"0.5.8",
),
Test(
all_detectors.ArrayLengthAssignment,
"tests/detectors/controlled-array-length/array_length_assignment.sol",
"0.4.25",
),
Test(
all_detectors.CostlyOperationsInLoop,
"tests/detectors/costly-loop/multiple_costly_operations_in_loop.sol",
"0.4.25",
),
Test(
all_detectors.FunctionInitializedState,
"tests/detectors/function-init-state/function_init_state_variables.sol",
"0.4.25",
),
Test(
all_detectors.MappingDeletionDetection,
"tests/detectors/mapping-deletion/MappingDeletion.sol",
"0.4.25",
),
Test(
all_detectors.UnimplementedFunctionDetection,
"tests/detectors/missing-inheritance/unimplemented_interfaces.sol",
"0.5.12",
),
Test(
all_detectors.PublicMappingNested,
"tests/detectors/public-mappings-nested/public_mappings_nested.sol",
"0.4.25",
),
Test(
all_detectors.RedundantStatements,
"tests/detectors/redundant-statements/redundant_statements.sol",
"0.4.25",
),
Test(
all_detectors.ReusedBaseConstructor,
"tests/detectors/reused-constructor/reused_base_constructor.sol",
"0.4.25",
),
Test(
all_detectors.StorageSignedIntegerArray,
"tests/detectors/storage-array/storage_signed_integer_array.sol",
"0.5.8",
),
Test(
all_detectors.UnimplementedFunctionDetection,
"tests/detectors/unimplemented-functions/unimplemented.sol",
"0.4.25",
),
Test(
all_detectors.UninitializedFunctionPtrsConstructor,
"tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol",
"0.5.8",
),
Test(all_detectors.BadPRNG, "tests/detectors/weak-prng/bad_prng.sol", "0.4.25"),
]
GENERIC_PATH = "/GENERIC_PATH"

Loading…
Cancel
Save