mirror of https://github.com/crytic/slither
parent
c23c0c41d0
commit
afb7342619
@ -0,0 +1,45 @@ |
||||
from typing import List, Dict |
||||
from slither.utils.output import Output |
||||
from slither.core.compilation_unit import SlitherCompilationUnit |
||||
from slither.formatters.variables.unchanged_state_variables import custom_format |
||||
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification |
||||
from .unchanged_state_variables import UnchangedStateVariables |
||||
|
||||
|
||||
class CouldBeConstant(AbstractDetector): |
||||
""" |
||||
State variables that could be declared as constant. |
||||
Not all types for constants are implemented in Solidity as of 0.4.25. |
||||
The only supported types are value types and strings (ElementaryType). |
||||
Reference: https://solidity.readthedocs.io/en/latest/contracts.html#constant-state-variables |
||||
""" |
||||
|
||||
ARGUMENT = "constable-states" |
||||
HELP = "State variables that could be declared constant" |
||||
IMPACT = DetectorClassification.OPTIMIZATION |
||||
CONFIDENCE = DetectorClassification.HIGH |
||||
|
||||
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#state-variables-that-could-be-declared-constant" |
||||
|
||||
WIKI_TITLE = "State variables that could be declared constant" |
||||
WIKI_DESCRIPTION = "State variables that are not updated following deployment should be declared constant to save gas." |
||||
WIKI_RECOMMENDATION = "Add the `constant` attribute to state variables that never change." |
||||
|
||||
def _detect(self) -> List[Output]: |
||||
"""Detect state variables that could be constant""" |
||||
results = {} |
||||
|
||||
unchanged_state_variables = UnchangedStateVariables(self.compilation_unit) |
||||
unchanged_state_variables.detect() |
||||
|
||||
for variable in unchanged_state_variables.constant_candidates: |
||||
results[variable.canonical_name] = self.generate_result( |
||||
[variable, " should be constant \n"] |
||||
) |
||||
|
||||
# Order by canonical name for deterministic results |
||||
return [results[k] for k in sorted(results)] |
||||
|
||||
@staticmethod |
||||
def _format(compilation_unit: SlitherCompilationUnit, result: Dict) -> None: |
||||
custom_format(compilation_unit, result, "constant") |
@ -0,0 +1,44 @@ |
||||
from typing import List, Dict |
||||
from slither.utils.output import Output |
||||
from slither.core.compilation_unit import SlitherCompilationUnit |
||||
from slither.formatters.variables.unchanged_state_variables import custom_format |
||||
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification |
||||
from .unchanged_state_variables import UnchangedStateVariables |
||||
|
||||
|
||||
class CouldBeImmutable(AbstractDetector): |
||||
""" |
||||
State variables that could be declared immutable. |
||||
# Immutable attribute available in Solidity 0.6.5 and above |
||||
# https://blog.soliditylang.org/2020/04/06/solidity-0.6.5-release-announcement/ |
||||
""" |
||||
|
||||
# VULNERABLE_SOLC_VERSIONS = |
||||
ARGUMENT = "immutable-states" |
||||
HELP = "State variables that could be declared immutable" |
||||
IMPACT = DetectorClassification.OPTIMIZATION |
||||
CONFIDENCE = DetectorClassification.HIGH |
||||
|
||||
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#state-variables-that-could-be-declared-immutable" |
||||
|
||||
WIKI_TITLE = "State variables that could be declared immutable" |
||||
WIKI_DESCRIPTION = "State variables that are not updated following deployment should be declared immutable to save gas." |
||||
WIKI_RECOMMENDATION = "Add the `immutable` attribute to state variables that never change or are set only in the constructor." |
||||
|
||||
def _detect(self) -> List[Output]: |
||||
"""Detect state variables that could be immutable""" |
||||
results = {} |
||||
unchanged_state_variables = UnchangedStateVariables(self.compilation_unit) |
||||
unchanged_state_variables.detect() |
||||
|
||||
for variable in unchanged_state_variables.immutable_candidates: |
||||
results[variable.canonical_name] = self.generate_result( |
||||
[variable, " should be immutable \n"] |
||||
) |
||||
|
||||
# Order by canonical name for deterministic results |
||||
return [results[k] for k in sorted(results)] |
||||
|
||||
@staticmethod |
||||
def _format(compilation_unit: SlitherCompilationUnit, result: Dict) -> None: |
||||
custom_format(compilation_unit, result, "immutable") |
@ -1,141 +0,0 @@ |
||||
""" |
||||
Module detecting state variables that could be declared as constant |
||||
""" |
||||
from typing import Set, List, Dict |
||||
|
||||
from slither.core.compilation_unit import SlitherCompilationUnit |
||||
from slither.core.solidity_types.elementary_type import ElementaryType |
||||
from slither.core.solidity_types.user_defined_type import UserDefinedType |
||||
from slither.core.variables.variable import Variable |
||||
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification |
||||
from slither.utils.output import Output |
||||
from slither.visitors.expression.export_values import ExportValues |
||||
from slither.core.declarations import Contract, Function |
||||
from slither.core.declarations.solidity_variables import SolidityFunction |
||||
from slither.core.variables.state_variable import StateVariable |
||||
from slither.formatters.variables.possible_const_state_variables import custom_format |
||||
from slither.core.expressions import CallExpression, NewContract |
||||
from slither.utils.standard_libraries import is_openzeppelin |
||||
|
||||
|
||||
def _is_valid_type(v: StateVariable) -> bool: |
||||
t = v.type |
||||
if isinstance(t, ElementaryType): |
||||
return True |
||||
if isinstance(t, UserDefinedType) and isinstance(t.type, Contract): |
||||
return True |
||||
return False |
||||
|
||||
|
||||
def _valid_candidate(v: StateVariable) -> bool: |
||||
return _is_valid_type(v) and not (v.is_constant or v.is_immutable) |
||||
|
||||
|
||||
def _is_constant_var(v: Variable) -> bool: |
||||
if isinstance(v, StateVariable): |
||||
return v.is_constant |
||||
return False |
||||
|
||||
|
||||
class ConstCandidateStateVars(AbstractDetector): |
||||
""" |
||||
State variables that could be declared as constant detector. |
||||
Not all types for constants are implemented in Solidity as of 0.4.25. |
||||
The only supported types are value types and strings (ElementaryType). |
||||
Reference: https://solidity.readthedocs.io/en/latest/contracts.html#constant-state-variables |
||||
""" |
||||
|
||||
ARGUMENT = "constable-states" |
||||
HELP = "State variables that could be declared constant or immutable" |
||||
IMPACT = DetectorClassification.OPTIMIZATION |
||||
CONFIDENCE = DetectorClassification.HIGH |
||||
|
||||
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#state-variables-that-could-be-declared-constant-or-immutable" |
||||
|
||||
WIKI_TITLE = "State variables that could be declared constant or immutable" |
||||
WIKI_DESCRIPTION = "State variables that are not updated following deployment should be declared constant or immutable to save gas." |
||||
WIKI_RECOMMENDATION = ( |
||||
"Add the `constant` or `immutable` attribute to state variables that never change." |
||||
) |
||||
|
||||
# https://solidity.readthedocs.io/en/v0.5.2/contracts.html#constant-state-variables |
||||
valid_solidity_function = [ |
||||
SolidityFunction("keccak256()"), |
||||
SolidityFunction("keccak256(bytes)"), |
||||
SolidityFunction("sha256()"), |
||||
SolidityFunction("sha256(bytes)"), |
||||
SolidityFunction("ripemd160()"), |
||||
SolidityFunction("ripemd160(bytes)"), |
||||
SolidityFunction("ecrecover(bytes32,uint8,bytes32,bytes32)"), |
||||
SolidityFunction("addmod(uint256,uint256,uint256)"), |
||||
SolidityFunction("mulmod(uint256,uint256,uint256)"), |
||||
] |
||||
|
||||
def _constant_initial_expression(self, v: Variable) -> bool: |
||||
if not v.expression: |
||||
return True |
||||
|
||||
# B b = new B(); b cannot be constant, so filter out and recommend it be immutable |
||||
if isinstance(v.expression, CallExpression) and isinstance( |
||||
v.expression.called, NewContract |
||||
): |
||||
return False |
||||
|
||||
export = ExportValues(v.expression) |
||||
values = export.result() |
||||
if not values: |
||||
return True |
||||
|
||||
return all((val in self.valid_solidity_function or _is_constant_var(val) for val in values)) |
||||
|
||||
def _detect(self) -> List[Output]: |
||||
"""Detect state variables that could be constant or immutable""" |
||||
results = {} |
||||
|
||||
variables = [] |
||||
functions = [] |
||||
for c in self.compilation_unit.contracts: |
||||
if is_openzeppelin(c): |
||||
continue |
||||
variables.append(c.state_variables) |
||||
functions.append(c.all_functions_called) |
||||
|
||||
valid_candidates: Set[StateVariable] = { |
||||
item for sublist in variables for item in sublist if _valid_candidate(item) |
||||
} |
||||
|
||||
all_functions: List[Function] = list( |
||||
{item1 for sublist in functions for item1 in sublist if isinstance(item1, Function)} |
||||
) |
||||
|
||||
variables_written = [] |
||||
constructor_variables_written = [] |
||||
for f in all_functions: |
||||
if f.is_constructor_variables: |
||||
constructor_variables_written.append(f.state_variables_written) |
||||
else: |
||||
variables_written.append(f.state_variables_written) |
||||
|
||||
variables_written = {item for sublist in variables_written for item in sublist} |
||||
constructor_variables_written = { |
||||
item for sublist in constructor_variables_written for item in sublist |
||||
} |
||||
for v in valid_candidates: |
||||
if v not in variables_written: |
||||
if self._constant_initial_expression(v): |
||||
results[v.canonical_name] = self.generate_result([v, " should be constant \n"]) |
||||
|
||||
# immutable attribute available in Solidity 0.6.5 and above |
||||
# https://blog.soliditylang.org/2020/04/06/solidity-0.6.5-release-announcement/ |
||||
elif ( |
||||
v in constructor_variables_written |
||||
and self.compilation_unit.solc_version > "0.6.4" |
||||
): |
||||
results[v.canonical_name] = self.generate_result([v, " should be immutable \n"]) |
||||
|
||||
# Order by canonical name for deterministic results |
||||
return [results[k] for k in sorted(results)] |
||||
|
||||
@staticmethod |
||||
def _format(compilation_unit: SlitherCompilationUnit, result: Dict) -> None: |
||||
custom_format(compilation_unit, result) |
@ -0,0 +1,123 @@ |
||||
""" |
||||
Module detecting state variables that could be declared as constant |
||||
""" |
||||
from typing import Set, List |
||||
|
||||
from slither.core.compilation_unit import SlitherCompilationUnit |
||||
from slither.core.solidity_types.elementary_type import ElementaryType |
||||
from slither.core.solidity_types.user_defined_type import UserDefinedType |
||||
from slither.core.variables.variable import Variable |
||||
|
||||
from slither.visitors.expression.export_values import ExportValues |
||||
from slither.core.declarations import Contract, Function |
||||
from slither.core.declarations.solidity_variables import SolidityFunction |
||||
from slither.core.variables.state_variable import StateVariable |
||||
from slither.core.expressions import CallExpression, NewContract |
||||
|
||||
|
||||
def _is_valid_type(v: StateVariable) -> bool: |
||||
t = v.type |
||||
if isinstance(t, ElementaryType): |
||||
return True |
||||
if isinstance(t, UserDefinedType) and isinstance(t.type, Contract): |
||||
return True |
||||
return False |
||||
|
||||
|
||||
def _valid_candidate(v: StateVariable) -> bool: |
||||
return _is_valid_type(v) and not (v.is_constant or v.is_immutable) |
||||
|
||||
|
||||
def _is_constant_var(v: Variable) -> bool: |
||||
if isinstance(v, StateVariable): |
||||
return v.is_constant |
||||
return False |
||||
|
||||
|
||||
# https://solidity.readthedocs.io/en/v0.5.2/contracts.html#constant-state-variables |
||||
valid_solidity_function = [ |
||||
SolidityFunction("keccak256()"), |
||||
SolidityFunction("keccak256(bytes)"), |
||||
SolidityFunction("sha256()"), |
||||
SolidityFunction("sha256(bytes)"), |
||||
SolidityFunction("ripemd160()"), |
||||
SolidityFunction("ripemd160(bytes)"), |
||||
SolidityFunction("ecrecover(bytes32,uint8,bytes32,bytes32)"), |
||||
SolidityFunction("addmod(uint256,uint256,uint256)"), |
||||
SolidityFunction("mulmod(uint256,uint256,uint256)"), |
||||
] |
||||
|
||||
|
||||
def _constant_initial_expression(v: Variable) -> bool: |
||||
if not v.expression: |
||||
return True |
||||
|
||||
# B b = new B(); b cannot be constant, so filter out and recommend it be immutable |
||||
if isinstance(v.expression, CallExpression) and isinstance(v.expression.called, NewContract): |
||||
return False |
||||
|
||||
export = ExportValues(v.expression) |
||||
values = export.result() |
||||
if not values: |
||||
return True |
||||
|
||||
return all((val in valid_solidity_function or _is_constant_var(val) for val in values)) |
||||
|
||||
|
||||
class UnchangedStateVariables: |
||||
""" |
||||
Find state variables that could be declared as constant or immutable (not written after deployment). |
||||
""" |
||||
|
||||
def __init__(self, compilation_unit: SlitherCompilationUnit): |
||||
self.compilation_unit = compilation_unit |
||||
self._constant_candidates: List[StateVariable] = [] |
||||
self._immutable_candidates: List[StateVariable] = [] |
||||
|
||||
@property |
||||
def immutable_candidates(self) -> List[StateVariable]: |
||||
"""Return the immutable candidates""" |
||||
return self._immutable_candidates |
||||
|
||||
@property |
||||
def constant_candidates(self) -> List[StateVariable]: |
||||
"""Return the constant candidates""" |
||||
return self._constant_candidates |
||||
|
||||
def detect(self): |
||||
"""Detect state variables that could be constant or immutable""" |
||||
for c in self.compilation_unit.contracts_derived: |
||||
variables = [] |
||||
functions = [] |
||||
|
||||
variables.append(c.state_variables) |
||||
functions.append(c.all_functions_called) |
||||
|
||||
valid_candidates: Set[StateVariable] = { |
||||
item for sublist in variables for item in sublist if _valid_candidate(item) |
||||
} |
||||
|
||||
all_functions: List[Function] = list( |
||||
{item1 for sublist in functions for item1 in sublist if isinstance(item1, Function)} |
||||
) |
||||
|
||||
variables_written = [] |
||||
constructor_variables_written = [] |
||||
variables_initialized = [] |
||||
for f in all_functions: |
||||
if f.is_constructor_variables: |
||||
variables_initialized.extend(f.state_variables_written) |
||||
elif f.is_constructor: |
||||
constructor_variables_written.extend(f.state_variables_written) |
||||
else: |
||||
variables_written.extend(f.state_variables_written) |
||||
|
||||
for v in valid_candidates: |
||||
if v not in variables_written: |
||||
if _constant_initial_expression(v) and v not in constructor_variables_written: |
||||
self.constant_candidates.append(v) |
||||
|
||||
elif ( |
||||
v in constructor_variables_written or v in variables_initialized |
||||
) and self.compilation_unit.solc_version >= "0.6.5": |
||||
self.immutable_candidates.append(v) |
@ -0,0 +1,57 @@ |
||||
//pragma solidity ^0.4.24; |
||||
|
||||
|
||||
contract A { |
||||
|
||||
address constant public MY_ADDRESS = 0xE0f5206BBD039e7b0592d8918820024e2a7437b9; |
||||
address public myFriendsAddress = 0xc0ffee254729296a45a3885639AC7E10F9d54979; |
||||
|
||||
uint public used; |
||||
uint public test = 5; |
||||
|
||||
uint constant X = 32**22 + 8; |
||||
string constant TEXT1 = "abc"; |
||||
string text2 = "xyz"; |
||||
|
||||
function setUsed() public { |
||||
if (msg.sender == MY_ADDRESS) { |
||||
used = test; |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
contract B is A { |
||||
|
||||
address public mySistersAddress = 0x999999cf1046e68e36E1aA2E0E07105eDDD1f08E; |
||||
|
||||
function () external { |
||||
used = 0; |
||||
} |
||||
|
||||
function setUsed(uint a) public { |
||||
if (msg.sender == MY_ADDRESS) { |
||||
used = a; |
||||
} |
||||
} |
||||
} |
||||
|
||||
contract MyConc{ |
||||
|
||||
uint constant A = 1; |
||||
bytes32 should_be_constant = sha256('abc'); |
||||
uint should_be_constant_2 = A + 1; |
||||
address not_constant = msg.sender; |
||||
uint not_constant_2 = getNumber(); |
||||
uint not_constant_3 = 10 + block.number; |
||||
uint not_constant_5; |
||||
|
||||
constructor(uint b) public { |
||||
not_constant_5 = b; |
||||
} |
||||
|
||||
function getNumber() public returns(uint){ |
||||
return block.number; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,3 @@ |
||||
[ |
||||
[] |
||||
] |
@ -0,0 +1,58 @@ |
||||
//pragma solidity ^0.4.24; |
||||
|
||||
|
||||
contract A { |
||||
|
||||
address constant public MY_ADDRESS = 0xE0f5206BBD039e7b0592d8918820024e2a7437b9; |
||||
address public myFriendsAddress = 0xc0ffee254729296a45a3885639AC7E10F9d54979; |
||||
|
||||
uint public used; |
||||
uint public test = 5; |
||||
|
||||
uint constant X = 32**22 + 8; |
||||
string constant TEXT1 = "abc"; |
||||
string text2 = "xyz"; |
||||
|
||||
function setUsed() public { |
||||
if (msg.sender == MY_ADDRESS) { |
||||
used = test; |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
contract B is A { |
||||
|
||||
address public mySistersAddress = 0x999999cf1046e68e36E1aA2E0E07105eDDD1f08E; |
||||
|
||||
function () external { |
||||
used = 0; |
||||
} |
||||
|
||||
function setUsed(uint a) public { |
||||
if (msg.sender == MY_ADDRESS) { |
||||
used = a; |
||||
} |
||||
} |
||||
} |
||||
|
||||
contract MyConc{ |
||||
|
||||
uint constant A = 1; |
||||
bytes32 should_be_constant = sha256('abc'); |
||||
uint should_be_constant_2 = A + 1; |
||||
B should_be_constant_3 = B(address(0)); |
||||
address not_constant = msg.sender; |
||||
uint not_constant_2 = getNumber(); |
||||
uint not_constant_3 = 10 + block.number; |
||||
uint not_constant_5; |
||||
|
||||
constructor(uint b) public { |
||||
not_constant_5 = b; |
||||
} |
||||
|
||||
function getNumber() public returns(uint){ |
||||
return block.number; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,3 @@ |
||||
[ |
||||
[] |
||||
] |
@ -0,0 +1,79 @@ |
||||
|
||||
contract A { |
||||
|
||||
address constant public MY_ADDRESS = 0xE0f5206BBD039e7b0592d8918820024e2a7437b9; |
||||
address public myFriendsAddress = 0xc0ffee254729296a45a3885639AC7E10F9d54979; |
||||
|
||||
uint public used; |
||||
uint public test = 5; |
||||
|
||||
uint constant X = 32**22 + 8; |
||||
string constant TEXT1 = "abc"; |
||||
string text2 = "xyz"; |
||||
|
||||
function setUsed() public { |
||||
if (msg.sender == MY_ADDRESS) { |
||||
used = test; |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
contract B is A { |
||||
|
||||
address public mySistersAddress = 0x999999cf1046e68e36E1aA2E0E07105eDDD1f08E; |
||||
|
||||
fallback () external { |
||||
used = 0; |
||||
} |
||||
|
||||
function setUsed(uint a) public { |
||||
if (msg.sender == MY_ADDRESS) { |
||||
used = a; |
||||
} |
||||
} |
||||
} |
||||
|
||||
contract Bad { |
||||
|
||||
uint constant A = 1; |
||||
bytes32 should_be_constant = sha256('abc'); |
||||
uint should_be_constant_2 = A + 1; |
||||
B should_be_constant_3 = B(address(0)); |
||||
address should_be_immutable = msg.sender; |
||||
uint should_be_immutable_2 = getNumber(); |
||||
uint should_be_immutable_3 = 10 + block.number; |
||||
B should_be_immutable_4 = new B(); |
||||
uint should_be_immutable_5; |
||||
|
||||
constructor(uint b) public { |
||||
should_be_immutable_5 = b; |
||||
} |
||||
|
||||
function getNumber() public returns(uint){ |
||||
return block.number; |
||||
} |
||||
|
||||
} |
||||
|
||||
contract Good { |
||||
|
||||
uint constant A = 1; |
||||
bytes32 constant should_be_constant = sha256('abc'); |
||||
uint constant should_be_constant_2 = A + 1; |
||||
B constant should_be_constant_3 = B(address(0)); |
||||
address immutable should_be_immutable = msg.sender; |
||||
uint immutable should_be_immutable_2 = getNumber(); |
||||
uint immutable should_be_immutable_3 = 10 + block.number; |
||||
B immutable should_be_immutable_4 = new B(); |
||||
uint immutable should_be_immutable_5; |
||||
|
||||
constructor(uint b) public { |
||||
should_be_immutable_5 = b; |
||||
} |
||||
|
||||
function getNumber() public returns(uint){ |
||||
return block.number; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,3 @@ |
||||
[ |
||||
[] |
||||
] |
@ -0,0 +1,78 @@ |
||||
|
||||
contract A { |
||||
|
||||
address constant public MY_ADDRESS = 0xE0f5206BBD039e7b0592d8918820024e2a7437b9; |
||||
address public myFriendsAddress = 0xc0ffee254729296a45a3885639AC7E10F9d54979; |
||||
|
||||
uint public used; |
||||
uint public test = 5; |
||||
|
||||
uint constant X = 32**22 + 8; |
||||
string constant TEXT1 = "abc"; |
||||
string text2 = "xyz"; |
||||
|
||||
function setUsed() public { |
||||
if (msg.sender == MY_ADDRESS) { |
||||
used = test; |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
contract B is A { |
||||
|
||||
address public mySistersAddress = 0x999999cf1046e68e36E1aA2E0E07105eDDD1f08E; |
||||
|
||||
fallback () external { |
||||
used = 0; |
||||
} |
||||
|
||||
function setUsed(uint a) public { |
||||
if (msg.sender == MY_ADDRESS) { |
||||
used = a; |
||||
} |
||||
} |
||||
} |
||||
|
||||
contract Bad { |
||||
|
||||
uint constant A = 1; |
||||
bytes32 should_be_constant = sha256('abc'); |
||||
uint should_be_constant_2 = A + 1; |
||||
B should_be_constant_3 = B(address(0)); |
||||
address should_be_immutable = msg.sender; |
||||
uint should_be_immutable_2 = getNumber(); |
||||
uint should_be_immutable_3 = 10 + block.number; |
||||
B should_be_immutable_4 = new B(); |
||||
uint should_be_immutable_5; |
||||
|
||||
constructor(uint b) { |
||||
should_be_immutable_5 = b; |
||||
} |
||||
|
||||
function getNumber() public returns(uint){ |
||||
return block.number; |
||||
} |
||||
} |
||||
|
||||
contract Good { |
||||
|
||||
uint constant A = 1; |
||||
bytes32 constant should_be_constant = sha256('abc'); |
||||
uint constant should_be_constant_2 = A + 1; |
||||
B constant should_be_constant_3 = B(address(0)); |
||||
address immutable should_be_immutable = msg.sender; |
||||
uint immutable should_be_immutable_2 = getNumber(); |
||||
uint immutable should_be_immutable_3 = 10 + block.number; |
||||
B immutable should_be_immutable_4 = new B(); |
||||
uint immutable should_be_immutable_5; |
||||
|
||||
constructor(uint b) { |
||||
should_be_immutable_5 = b; |
||||
} |
||||
|
||||
function getNumber() public returns(uint){ |
||||
return block.number; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,334 @@ |
||||
[ |
||||
[ |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "variable", |
||||
"name": "should_be_immutable_5", |
||||
"source_mapping": { |
||||
"start": 1077, |
||||
"length": 26, |
||||
"filename_relative": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
47 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 31 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "Bad", |
||||
"source_mapping": { |
||||
"start": 718, |
||||
"length": 531, |
||||
"filename_relative": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41, |
||||
42, |
||||
43, |
||||
44, |
||||
45, |
||||
46, |
||||
47, |
||||
48, |
||||
49, |
||||
50, |
||||
51, |
||||
52, |
||||
53, |
||||
54, |
||||
55, |
||||
56 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "Bad.should_be_immutable_5 (tests/detectors/immutable-states/0.7.6/immut_state_variables.sol#47) should be immutable \n", |
||||
"markdown": "[Bad.should_be_immutable_5](tests/detectors/immutable-states/0.7.6/immut_state_variables.sol#L47) should be immutable \n", |
||||
"first_markdown_element": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol#L47", |
||||
"id": "42d50245236163ceca90dea732165e65c2155934b149a5a1a5c51bddc0b5b02a", |
||||
"check": "immutable-states", |
||||
"impact": "Optimization", |
||||
"confidence": "High" |
||||
}, |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "variable", |
||||
"name": "should_be_immutable_2", |
||||
"source_mapping": { |
||||
"start": 940, |
||||
"length": 40, |
||||
"filename_relative": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
44 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 45 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "Bad", |
||||
"source_mapping": { |
||||
"start": 718, |
||||
"length": 531, |
||||
"filename_relative": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41, |
||||
42, |
||||
43, |
||||
44, |
||||
45, |
||||
46, |
||||
47, |
||||
48, |
||||
49, |
||||
50, |
||||
51, |
||||
52, |
||||
53, |
||||
54, |
||||
55, |
||||
56 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "Bad.should_be_immutable_2 (tests/detectors/immutable-states/0.7.6/immut_state_variables.sol#44) should be immutable \n", |
||||
"markdown": "[Bad.should_be_immutable_2](tests/detectors/immutable-states/0.7.6/immut_state_variables.sol#L44) should be immutable \n", |
||||
"first_markdown_element": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol#L44", |
||||
"id": "70d57aa51dda92c28444a466db8567fa783c85d484259aa5eee2ebc63f97a200", |
||||
"check": "immutable-states", |
||||
"impact": "Optimization", |
||||
"confidence": "High" |
||||
}, |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "variable", |
||||
"name": "should_be_immutable_4", |
||||
"source_mapping": { |
||||
"start": 1038, |
||||
"length": 33, |
||||
"filename_relative": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
46 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 38 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "Bad", |
||||
"source_mapping": { |
||||
"start": 718, |
||||
"length": 531, |
||||
"filename_relative": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41, |
||||
42, |
||||
43, |
||||
44, |
||||
45, |
||||
46, |
||||
47, |
||||
48, |
||||
49, |
||||
50, |
||||
51, |
||||
52, |
||||
53, |
||||
54, |
||||
55, |
||||
56 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "Bad.should_be_immutable_4 (tests/detectors/immutable-states/0.7.6/immut_state_variables.sol#46) should be immutable \n", |
||||
"markdown": "[Bad.should_be_immutable_4](tests/detectors/immutable-states/0.7.6/immut_state_variables.sol#L46) should be immutable \n", |
||||
"first_markdown_element": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol#L46", |
||||
"id": "a26d6df4087ac010928bc4bd18aa70ac58a28e584b1288e348d9c255473c300d", |
||||
"check": "immutable-states", |
||||
"impact": "Optimization", |
||||
"confidence": "High" |
||||
}, |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "variable", |
||||
"name": "should_be_immutable", |
||||
"source_mapping": { |
||||
"start": 894, |
||||
"length": 40, |
||||
"filename_relative": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
43 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 45 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "Bad", |
||||
"source_mapping": { |
||||
"start": 718, |
||||
"length": 531, |
||||
"filename_relative": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41, |
||||
42, |
||||
43, |
||||
44, |
||||
45, |
||||
46, |
||||
47, |
||||
48, |
||||
49, |
||||
50, |
||||
51, |
||||
52, |
||||
53, |
||||
54, |
||||
55, |
||||
56 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "Bad.should_be_immutable (tests/detectors/immutable-states/0.7.6/immut_state_variables.sol#43) should be immutable \n", |
||||
"markdown": "[Bad.should_be_immutable](tests/detectors/immutable-states/0.7.6/immut_state_variables.sol#L43) should be immutable \n", |
||||
"first_markdown_element": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol#L43", |
||||
"id": "b163d277f544f7f05ed4bcddda61e444be893e65ba0469688abd7b401a1db222", |
||||
"check": "immutable-states", |
||||
"impact": "Optimization", |
||||
"confidence": "High" |
||||
}, |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "variable", |
||||
"name": "should_be_immutable_3", |
||||
"source_mapping": { |
||||
"start": 986, |
||||
"length": 46, |
||||
"filename_relative": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
45 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 51 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "Bad", |
||||
"source_mapping": { |
||||
"start": 718, |
||||
"length": 531, |
||||
"filename_relative": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41, |
||||
42, |
||||
43, |
||||
44, |
||||
45, |
||||
46, |
||||
47, |
||||
48, |
||||
49, |
||||
50, |
||||
51, |
||||
52, |
||||
53, |
||||
54, |
||||
55, |
||||
56 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "Bad.should_be_immutable_3 (tests/detectors/immutable-states/0.7.6/immut_state_variables.sol#45) should be immutable \n", |
||||
"markdown": "[Bad.should_be_immutable_3](tests/detectors/immutable-states/0.7.6/immut_state_variables.sol#L45) should be immutable \n", |
||||
"first_markdown_element": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol#L45", |
||||
"id": "f19f7a22a6f17ffd8b5c29021226388aab7548f996b686a8e0b2bc861f72d447", |
||||
"check": "immutable-states", |
||||
"impact": "Optimization", |
||||
"confidence": "High" |
||||
} |
||||
] |
||||
] |
@ -0,0 +1,78 @@ |
||||
|
||||
contract A { |
||||
|
||||
address constant public MY_ADDRESS = 0xE0f5206BBD039e7b0592d8918820024e2a7437b9; |
||||
address public myFriendsAddress = 0xc0ffee254729296a45a3885639AC7E10F9d54979; |
||||
|
||||
uint public used; |
||||
uint public test = 5; |
||||
|
||||
uint constant X = 32**22 + 8; |
||||
string constant TEXT1 = "abc"; |
||||
string text2 = "xyz"; |
||||
|
||||
function setUsed() public { |
||||
if (msg.sender == MY_ADDRESS) { |
||||
used = test; |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
contract B is A { |
||||
|
||||
address public mySistersAddress = 0x999999cf1046e68e36E1aA2E0E07105eDDD1f08E; |
||||
|
||||
fallback () external { |
||||
used = 0; |
||||
} |
||||
|
||||
function setUsed(uint a) public { |
||||
if (msg.sender == MY_ADDRESS) { |
||||
used = a; |
||||
} |
||||
} |
||||
} |
||||
|
||||
contract Bad { |
||||
|
||||
uint constant A = 1; |
||||
bytes32 should_be_constant = sha256('abc'); |
||||
uint should_be_constant_2 = A + 1; |
||||
B should_be_constant_3 = B(address(0)); |
||||
address should_be_immutable = msg.sender; |
||||
uint should_be_immutable_2 = getNumber(); |
||||
uint should_be_immutable_3 = 10 + block.number; |
||||
uint should_be_immutable_5; |
||||
|
||||
constructor(uint b) { |
||||
should_be_immutable_5 = b; |
||||
} |
||||
|
||||
function getNumber() public returns(uint){ |
||||
return block.number; |
||||
} |
||||
|
||||
} |
||||
|
||||
contract Good { |
||||
|
||||
uint constant A = 1; |
||||
bytes32 constant should_be_constant = sha256('abc'); |
||||
uint constant should_be_constant_2 = A + 1; |
||||
B constant should_be_constant_3 = B(address(0)); |
||||
address immutable should_be_immutable = msg.sender; |
||||
uint immutable should_be_immutable_2 = getNumber(); |
||||
uint immutable should_be_immutable_3 = 10 + block.number; |
||||
B immutable should_be_immutable_4 = new B(); |
||||
uint immutable should_be_immutable_5; |
||||
|
||||
constructor(uint b) { |
||||
should_be_immutable_5 = b; |
||||
} |
||||
|
||||
function getNumber() public returns(uint){ |
||||
return block.number; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,268 @@ |
||||
[ |
||||
[ |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "variable", |
||||
"name": "should_be_immutable_5", |
||||
"source_mapping": { |
||||
"start": 1038, |
||||
"length": 26, |
||||
"filename_relative": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
46 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 31 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "Bad", |
||||
"source_mapping": { |
||||
"start": 718, |
||||
"length": 493, |
||||
"filename_relative": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41, |
||||
42, |
||||
43, |
||||
44, |
||||
45, |
||||
46, |
||||
47, |
||||
48, |
||||
49, |
||||
50, |
||||
51, |
||||
52, |
||||
53, |
||||
54, |
||||
55, |
||||
56 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "Bad.should_be_immutable_5 (tests/detectors/immutable-states/0.8.0/immut_state_variables.sol#46) should be immutable \n", |
||||
"markdown": "[Bad.should_be_immutable_5](tests/detectors/immutable-states/0.8.0/immut_state_variables.sol#L46) should be immutable \n", |
||||
"first_markdown_element": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol#L46", |
||||
"id": "42d50245236163ceca90dea732165e65c2155934b149a5a1a5c51bddc0b5b02a", |
||||
"check": "immutable-states", |
||||
"impact": "Optimization", |
||||
"confidence": "High" |
||||
}, |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "variable", |
||||
"name": "should_be_immutable_2", |
||||
"source_mapping": { |
||||
"start": 940, |
||||
"length": 40, |
||||
"filename_relative": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
44 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 45 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "Bad", |
||||
"source_mapping": { |
||||
"start": 718, |
||||
"length": 493, |
||||
"filename_relative": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41, |
||||
42, |
||||
43, |
||||
44, |
||||
45, |
||||
46, |
||||
47, |
||||
48, |
||||
49, |
||||
50, |
||||
51, |
||||
52, |
||||
53, |
||||
54, |
||||
55, |
||||
56 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "Bad.should_be_immutable_2 (tests/detectors/immutable-states/0.8.0/immut_state_variables.sol#44) should be immutable \n", |
||||
"markdown": "[Bad.should_be_immutable_2](tests/detectors/immutable-states/0.8.0/immut_state_variables.sol#L44) should be immutable \n", |
||||
"first_markdown_element": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol#L44", |
||||
"id": "70d57aa51dda92c28444a466db8567fa783c85d484259aa5eee2ebc63f97a200", |
||||
"check": "immutable-states", |
||||
"impact": "Optimization", |
||||
"confidence": "High" |
||||
}, |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "variable", |
||||
"name": "should_be_immutable", |
||||
"source_mapping": { |
||||
"start": 894, |
||||
"length": 40, |
||||
"filename_relative": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
43 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 45 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "Bad", |
||||
"source_mapping": { |
||||
"start": 718, |
||||
"length": 493, |
||||
"filename_relative": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41, |
||||
42, |
||||
43, |
||||
44, |
||||
45, |
||||
46, |
||||
47, |
||||
48, |
||||
49, |
||||
50, |
||||
51, |
||||
52, |
||||
53, |
||||
54, |
||||
55, |
||||
56 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "Bad.should_be_immutable (tests/detectors/immutable-states/0.8.0/immut_state_variables.sol#43) should be immutable \n", |
||||
"markdown": "[Bad.should_be_immutable](tests/detectors/immutable-states/0.8.0/immut_state_variables.sol#L43) should be immutable \n", |
||||
"first_markdown_element": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol#L43", |
||||
"id": "b163d277f544f7f05ed4bcddda61e444be893e65ba0469688abd7b401a1db222", |
||||
"check": "immutable-states", |
||||
"impact": "Optimization", |
||||
"confidence": "High" |
||||
}, |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "variable", |
||||
"name": "should_be_immutable_3", |
||||
"source_mapping": { |
||||
"start": 986, |
||||
"length": 46, |
||||
"filename_relative": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
45 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 51 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "Bad", |
||||
"source_mapping": { |
||||
"start": 718, |
||||
"length": 493, |
||||
"filename_relative": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41, |
||||
42, |
||||
43, |
||||
44, |
||||
45, |
||||
46, |
||||
47, |
||||
48, |
||||
49, |
||||
50, |
||||
51, |
||||
52, |
||||
53, |
||||
54, |
||||
55, |
||||
56 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "Bad.should_be_immutable_3 (tests/detectors/immutable-states/0.8.0/immut_state_variables.sol#45) should be immutable \n", |
||||
"markdown": "[Bad.should_be_immutable_3](tests/detectors/immutable-states/0.8.0/immut_state_variables.sol#L45) should be immutable \n", |
||||
"first_markdown_element": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol#L45", |
||||
"id": "f19f7a22a6f17ffd8b5c29021226388aab7548f996b686a8e0b2bc861f72d447", |
||||
"check": "immutable-states", |
||||
"impact": "Optimization", |
||||
"confidence": "High" |
||||
} |
||||
] |
||||
] |
Loading…
Reference in new issue