mirror of https://github.com/crytic/slither
commit
369dbddeaf
@ -0,0 +1,133 @@ |
|||||||
|
""" |
||||||
|
Module detecting reserved keyword shadowing |
||||||
|
""" |
||||||
|
|
||||||
|
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification |
||||||
|
|
||||||
|
|
||||||
|
class BuiltinSymbolShadowing(AbstractDetector): |
||||||
|
""" |
||||||
|
Built-in symbol shadowing |
||||||
|
""" |
||||||
|
|
||||||
|
ARGUMENT = 'shadowing-builtin' |
||||||
|
HELP = 'Built-in symbol shadowing' |
||||||
|
IMPACT = DetectorClassification.LOW |
||||||
|
CONFIDENCE = DetectorClassification.HIGH |
||||||
|
|
||||||
|
WIKI = 'https://github.com/trailofbits/slither/wiki/Vulnerabilities-Description#builtin-symbol-shadowing' |
||||||
|
|
||||||
|
vuln_name = 'ShadowingBuiltinSymbols' |
||||||
|
|
||||||
|
SHADOWING_FUNCTION = "function" |
||||||
|
SHADOWING_MODIFIER = "modifier" |
||||||
|
SHADOWING_LOCAL_VARIABLE = "local variable" |
||||||
|
SHADOWING_STATE_VARIABLE = "state variable" |
||||||
|
SHADOWING_EVENT = "event" |
||||||
|
|
||||||
|
# Reserved keywords reference: https://solidity.readthedocs.io/en/v0.5.2/units-and-global-variables.html |
||||||
|
BUILTIN_SYMBOLS = ["assert", "require", "revert", "block", "blockhash", |
||||||
|
"gasleft", "msg", "now", "tx", "this", "addmod", "mulmod", |
||||||
|
"keccak256", "sha256", "sha3", "ripemd160", "ecrecover", |
||||||
|
"selfdestruct", "suicide", "abi"] |
||||||
|
|
||||||
|
# https://solidity.readthedocs.io/en/v0.5.2/miscellaneous.html#reserved-keywords |
||||||
|
RESERVED_KEYWORDS = ['abstract', 'after', 'alias', 'apply', 'auto', 'case', 'catch', 'copyof', |
||||||
|
'default', 'define', 'final', 'immutable', 'implements', 'in', 'inline', |
||||||
|
'let', 'macro', 'match', 'mutable', 'null', 'of', 'override', 'partial', |
||||||
|
'promise', 'reference', 'relocatable', 'sealed', 'sizeof', 'static', |
||||||
|
'supports', 'switch', 'try', 'type', 'typedef', 'typeof', 'unchecked'] |
||||||
|
|
||||||
|
def is_builtin_symbol(self, word): |
||||||
|
""" Detects if a given word is a built-in symbol. |
||||||
|
|
||||||
|
Returns: |
||||||
|
boolean: True if the given word represents a built-in symbol.""" |
||||||
|
|
||||||
|
return word in self.BUILTIN_SYMBOLS or word in self.RESERVED_KEYWORDS |
||||||
|
|
||||||
|
def detect_builtin_shadowing_locals(self, function_or_modifier): |
||||||
|
""" Detects if local variables in a given function/modifier are named after built-in symbols. |
||||||
|
Any such items are returned in a list. |
||||||
|
|
||||||
|
Returns: |
||||||
|
list of tuple: (type, definition, local variable parent)""" |
||||||
|
|
||||||
|
results = [] |
||||||
|
for local in function_or_modifier.variables: |
||||||
|
if self.is_builtin_symbol(local.name): |
||||||
|
results.append((self.SHADOWING_LOCAL_VARIABLE, local, function_or_modifier)) |
||||||
|
return results |
||||||
|
|
||||||
|
def detect_builtin_shadowing_definitions(self, contract): |
||||||
|
""" Detects if functions, access modifiers, events, state variables, or local variables are named after built-in |
||||||
|
symbols. Any such definitions are returned in a list. |
||||||
|
|
||||||
|
Returns: |
||||||
|
list of tuple: (type, definition, [local variable parent])""" |
||||||
|
|
||||||
|
result = [] |
||||||
|
|
||||||
|
# Loop through all functions, modifiers, variables (state and local) to detect any built-in symbol keywords. |
||||||
|
for function in contract.functions: |
||||||
|
if function.contract == contract: |
||||||
|
if self.is_builtin_symbol(function.name): |
||||||
|
result.append((self.SHADOWING_FUNCTION, function, None)) |
||||||
|
result += self.detect_builtin_shadowing_locals(function) |
||||||
|
for modifier in contract.modifiers: |
||||||
|
if modifier.contract == contract: |
||||||
|
if self.is_builtin_symbol(modifier.name): |
||||||
|
result.append((self.SHADOWING_MODIFIER, modifier, None)) |
||||||
|
result += self.detect_builtin_shadowing_locals(modifier) |
||||||
|
for variable in contract.variables: |
||||||
|
if variable.contract == contract: |
||||||
|
if self.is_builtin_symbol(variable.name): |
||||||
|
result.append((self.SHADOWING_STATE_VARIABLE, variable, None)) |
||||||
|
for event in contract.events: |
||||||
|
if event.contract == contract: |
||||||
|
if self.is_builtin_symbol(event.name): |
||||||
|
result.append((self.SHADOWING_EVENT, event, None)) |
||||||
|
|
||||||
|
return result |
||||||
|
|
||||||
|
def detect(self): |
||||||
|
""" Detect shadowing of built-in symbols |
||||||
|
|
||||||
|
Recursively visit the calls |
||||||
|
Returns: |
||||||
|
list: {'vuln', 'filename,'contract','func', 'shadow'} |
||||||
|
|
||||||
|
""" |
||||||
|
|
||||||
|
results = [] |
||||||
|
for contract in self.contracts: |
||||||
|
shadows = self.detect_builtin_shadowing_definitions(contract) |
||||||
|
if shadows: |
||||||
|
for shadow in shadows: |
||||||
|
# Obtain components |
||||||
|
shadow_type = shadow[0] |
||||||
|
shadow_object = shadow[1] |
||||||
|
local_variable_parent = shadow[2] |
||||||
|
|
||||||
|
# Build the path for our info string |
||||||
|
local_variable_path = contract.name + "." |
||||||
|
if local_variable_parent is not None: |
||||||
|
local_variable_path += local_variable_parent.name + "." |
||||||
|
local_variable_path += shadow_object.name |
||||||
|
|
||||||
|
info = '{} ({} @ {}) shadows built-in symbol \"{}"\n'.format(local_variable_path, |
||||||
|
shadow_type, |
||||||
|
shadow_object.source_mapping_str, |
||||||
|
shadow_object.name) |
||||||
|
# Print relevant information to the log |
||||||
|
self.log(info) |
||||||
|
|
||||||
|
# Generate relevant JSON data for this shadowing definition. |
||||||
|
json = self.generate_json_result(info) |
||||||
|
if shadow_type in [self.SHADOWING_FUNCTION, self.SHADOWING_MODIFIER, self.SHADOWING_EVENT]: |
||||||
|
self.add_function_to_json(shadow_object, json) |
||||||
|
elif shadow_type in [self.SHADOWING_STATE_VARIABLE, self.SHADOWING_LOCAL_VARIABLE]: |
||||||
|
self.add_variable_to_json(shadow_object, json) |
||||||
|
results.append(json) |
||||||
|
|
||||||
|
return results |
@ -0,0 +1,109 @@ |
|||||||
|
""" |
||||||
|
Module detecting local variable shadowing |
||||||
|
""" |
||||||
|
|
||||||
|
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification |
||||||
|
|
||||||
|
|
||||||
|
class LocalShadowing(AbstractDetector): |
||||||
|
""" |
||||||
|
Local variable shadowing |
||||||
|
""" |
||||||
|
|
||||||
|
ARGUMENT = 'shadowing-local' |
||||||
|
HELP = 'Local variables shadowing' |
||||||
|
IMPACT = DetectorClassification.LOW |
||||||
|
CONFIDENCE = DetectorClassification.HIGH |
||||||
|
|
||||||
|
WIKI = 'https://github.com/trailofbits/slither/wiki/Vulnerabilities-Description#local-variable-shadowing' |
||||||
|
|
||||||
|
vuln_name = 'ShadowingLocalVariable' |
||||||
|
|
||||||
|
OVERSHADOWED_FUNCTION = "function" |
||||||
|
OVERSHADOWED_MODIFIER = "modifier" |
||||||
|
OVERSHADOWED_STATE_VARIABLE = "state variable" |
||||||
|
OVERSHADOWED_EVENT = "event" |
||||||
|
|
||||||
|
def detect_shadowing_definitions(self, contract): |
||||||
|
""" Detects if functions, access modifiers, events, state variables, and local variables are named after |
||||||
|
reserved keywords. Any such definitions are returned in a list. |
||||||
|
|
||||||
|
Returns: |
||||||
|
list of tuple: (type, contract name, definition)""" |
||||||
|
result = [] |
||||||
|
|
||||||
|
# Loop through all functions + modifiers in this contract. |
||||||
|
for function in contract.functions + contract.modifiers: |
||||||
|
# We should only look for functions declared directly in this contract (not in a base contract). |
||||||
|
if function.contract != contract: |
||||||
|
continue |
||||||
|
|
||||||
|
# This function was declared in this contract, we check what its local variables might shadow. |
||||||
|
for variable in function.variables: |
||||||
|
overshadowed = [] |
||||||
|
for scope_contract in [contract] + contract.inheritance: |
||||||
|
# Check functions |
||||||
|
for scope_function in scope_contract.functions: |
||||||
|
if variable.name == scope_function.name and scope_function.contract == scope_contract: |
||||||
|
overshadowed.append((self.OVERSHADOWED_FUNCTION, scope_contract.name, scope_function)) |
||||||
|
# Check modifiers |
||||||
|
for scope_modifier in scope_contract.modifiers: |
||||||
|
if variable.name == scope_modifier.name and scope_modifier.contract == scope_contract: |
||||||
|
overshadowed.append((self.OVERSHADOWED_MODIFIER, scope_contract.name, scope_modifier)) |
||||||
|
# Check events |
||||||
|
for scope_event in scope_contract.events: |
||||||
|
if variable.name == scope_event.name and scope_event.contract == scope_contract: |
||||||
|
overshadowed.append((self.OVERSHADOWED_EVENT, scope_contract.name, scope_event)) |
||||||
|
# Check state variables |
||||||
|
for scope_state_variable in scope_contract.variables: |
||||||
|
if variable.name == scope_state_variable.name and scope_state_variable.contract == scope_contract: |
||||||
|
overshadowed.append((self.OVERSHADOWED_STATE_VARIABLE, scope_contract.name, scope_state_variable)) |
||||||
|
|
||||||
|
# If we have found any overshadowed objects, we'll want to add it to our result list. |
||||||
|
if overshadowed: |
||||||
|
result.append((contract.name, function.name, variable, overshadowed)) |
||||||
|
|
||||||
|
return result |
||||||
|
|
||||||
|
def detect(self): |
||||||
|
""" Detect shadowing local variables |
||||||
|
|
||||||
|
Recursively visit the calls |
||||||
|
Returns: |
||||||
|
list: {'vuln', 'filename,'contract','func', 'shadow'} |
||||||
|
|
||||||
|
""" |
||||||
|
|
||||||
|
results = [] |
||||||
|
for contract in self.contracts: |
||||||
|
shadows = self.detect_shadowing_definitions(contract) |
||||||
|
if shadows: |
||||||
|
for shadow in shadows: |
||||||
|
local_parent_name = shadow[1] |
||||||
|
local_variable = shadow[2] |
||||||
|
overshadowed = shadow[3] |
||||||
|
info = '{}.{}.{} (local variable @ {}) shadows:\n'.format(contract.name, |
||||||
|
local_parent_name, |
||||||
|
local_variable.name, |
||||||
|
local_variable.source_mapping_str) |
||||||
|
for overshadowed_entry in overshadowed: |
||||||
|
info += "\t- {}.{} ({} @ {})\n".format(overshadowed_entry[1], |
||||||
|
overshadowed_entry[2], |
||||||
|
overshadowed_entry[0], |
||||||
|
overshadowed_entry[2].source_mapping_str) |
||||||
|
|
||||||
|
# Print relevant information to the log |
||||||
|
self.log(info) |
||||||
|
|
||||||
|
# Generate relevant JSON data for this shadowing definition. |
||||||
|
json = self.generate_json_result(info) |
||||||
|
self.add_variable_to_json(local_variable, json) |
||||||
|
for overshadowed_entry in overshadowed: |
||||||
|
if overshadowed_entry[0] in [self.OVERSHADOWED_FUNCTION, self.OVERSHADOWED_MODIFIER, |
||||||
|
self.OVERSHADOWED_EVENT]: |
||||||
|
self.add_function_to_json(overshadowed_entry[2], json) |
||||||
|
elif overshadowed_entry[0] == self.OVERSHADOWED_STATE_VARIABLE: |
||||||
|
self.add_variable_to_json(overshadowed_entry[2], json) |
||||||
|
results.append(json) |
||||||
|
|
||||||
|
return results |
@ -0,0 +1,119 @@ |
|||||||
|
""" |
||||||
|
Module detecting dangerous strict equality |
||||||
|
|
||||||
|
""" |
||||||
|
|
||||||
|
import itertools |
||||||
|
from slither.analyses.data_dependency.data_dependency import is_dependent_ssa |
||||||
|
from slither.core.declarations import Function |
||||||
|
from slither.detectors.abstract_detector import (AbstractDetector, |
||||||
|
DetectorClassification) |
||||||
|
from slither.slithir.operations import (Assignment, Balance, Binary, BinaryType, |
||||||
|
HighLevelCall) |
||||||
|
|
||||||
|
from slither.core.solidity_types import MappingType, ElementaryType |
||||||
|
|
||||||
|
from slither.core.variables.state_variable import StateVariable |
||||||
|
from slither.core.declarations.solidity_variables import SolidityVariable, SolidityVariableComposed |
||||||
|
from slither.slithir.variables import ReferenceVariable |
||||||
|
|
||||||
|
class IncorrectStrictEquality(AbstractDetector): |
||||||
|
ARGUMENT = 'incorrect-equality' |
||||||
|
HELP = 'Dangerous strict equalities' |
||||||
|
IMPACT = DetectorClassification.MEDIUM |
||||||
|
CONFIDENCE = DetectorClassification.HIGH |
||||||
|
|
||||||
|
WIKI = 'https://github.com/trailofbits/slither/wiki/Vulnerabilities-Description#dangerous-strict-equalities' |
||||||
|
|
||||||
|
sources_taint = [SolidityVariable('now'), |
||||||
|
SolidityVariableComposed('block.number'), |
||||||
|
SolidityVariableComposed('block.timestamp')] |
||||||
|
|
||||||
|
@staticmethod |
||||||
|
def is_direct_comparison(ir): |
||||||
|
return isinstance(ir, Binary) and ir.type == BinaryType.EQUAL |
||||||
|
|
||||||
|
@staticmethod |
||||||
|
def is_any_tainted(variables, taints, function): |
||||||
|
return any([is_dependent_ssa(var, taint, function.contract) for var in variables for taint in taints]) |
||||||
|
|
||||||
|
def taint_balance_equalities(self, functions): |
||||||
|
taints = [] |
||||||
|
for func in functions: |
||||||
|
for node in func.nodes: |
||||||
|
for ir in node.irs_ssa: |
||||||
|
if isinstance(ir, Balance): |
||||||
|
taints.append(ir.lvalue) |
||||||
|
if isinstance(ir, HighLevelCall): |
||||||
|
#print(ir.function.full_name) |
||||||
|
if isinstance(ir.function, Function) and\ |
||||||
|
ir.function.full_name == 'balanceOf(address)': |
||||||
|
taints.append(ir.lvalue) |
||||||
|
if isinstance(ir.function, StateVariable) and\ |
||||||
|
isinstance(ir.function.type, MappingType) and\ |
||||||
|
ir.function.name == 'balanceOf' and\ |
||||||
|
ir.function.type.type_from == ElementaryType('address') and\ |
||||||
|
ir.function.type.type_to == ElementaryType('uint256'): |
||||||
|
taints.append(ir.lvalue) |
||||||
|
if isinstance(ir, Assignment): |
||||||
|
if ir.rvalue in self.sources_taint: |
||||||
|
taints.append(ir.lvalue) |
||||||
|
|
||||||
|
return taints |
||||||
|
|
||||||
|
# Retrieve all tainted (node, function) pairs |
||||||
|
def tainted_equality_nodes(self, funcs, taints): |
||||||
|
results = dict() |
||||||
|
taints += self.sources_taint |
||||||
|
|
||||||
|
for func in funcs: |
||||||
|
for node in func.nodes: |
||||||
|
for ir in node.irs_ssa: |
||||||
|
|
||||||
|
# Filter to only tainted equality (==) comparisons |
||||||
|
if self.is_direct_comparison(ir) and self.is_any_tainted(ir.used, taints, func): |
||||||
|
if func not in results: |
||||||
|
results[func] = [] |
||||||
|
results[func].append(node) |
||||||
|
|
||||||
|
return results |
||||||
|
|
||||||
|
def detect_strict_equality(self, contract): |
||||||
|
funcs = contract.all_functions_called + contract.modifiers |
||||||
|
|
||||||
|
# Taint all BALANCE accesses |
||||||
|
taints = self.taint_balance_equalities(funcs) |
||||||
|
|
||||||
|
# Accumulate tainted (node,function) pairs involved in strict equality (==) comparisons |
||||||
|
results = self.tainted_equality_nodes(funcs, taints) |
||||||
|
|
||||||
|
return results |
||||||
|
|
||||||
|
def detect(self): |
||||||
|
results = [] |
||||||
|
|
||||||
|
for c in self.slither.contracts_derived: |
||||||
|
ret = self.detect_strict_equality(c) |
||||||
|
|
||||||
|
info = '' |
||||||
|
# sort ret to get deterministic results |
||||||
|
ret = sorted(list(ret.items()), key=lambda x:x[0].name) |
||||||
|
for f, nodes in ret: |
||||||
|
info += "{}.{} ({}) uses a dangerous strict equality:\n".format(f.contract.name, |
||||||
|
f.name, |
||||||
|
f.source_mapping_str) |
||||||
|
|
||||||
|
# sort the nodes to get deterministic results |
||||||
|
nodes.sort(key=lambda x: x.node_id) |
||||||
|
for node in nodes: |
||||||
|
info += "\t- {}\n".format(str(node.expression)) |
||||||
|
|
||||||
|
json = self.generate_json_result(info) |
||||||
|
self.add_function_to_json(f, json) |
||||||
|
self.add_nodes_to_json(nodes, json) |
||||||
|
results.append(json) |
||||||
|
|
||||||
|
if info: |
||||||
|
self.log(info) |
||||||
|
|
||||||
|
return results |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1 @@ |
|||||||
|
[{"check": "shadowing-local", "impact": "Low", "confidence": "High", "description": "FurtherExtendedContract.shadowingParent.x (local variable @ tests/shadowing_local_variable.sol#25) shadows:\n\t- FurtherExtendedContract.x (state variable @ tests/shadowing_local_variable.sol#17)\n\t- ExtendedContract.x (state variable @ tests/shadowing_local_variable.sol#9)\n\t- BaseContract.x (state variable @ tests/shadowing_local_variable.sol#4)\n", "elements": [{"type": "variable", "name": "x", "source_mapping": {"start": 376, "length": 6, "filename": "tests/shadowing_local_variable.sol", "lines": [25]}}, {"type": "variable", "name": "x", "source_mapping": {"start": 256, "length": 10, "filename": "tests/shadowing_local_variable.sol", "lines": [17]}}, {"type": "variable", "name": "x", "source_mapping": {"start": 133, "length": 10, "filename": "tests/shadowing_local_variable.sol", "lines": [9]}}, {"type": "variable", "name": "x", "source_mapping": {"start": 54, "length": 10, "filename": "tests/shadowing_local_variable.sol", "lines": [4]}}]}, {"check": "shadowing-local", "impact": "Low", "confidence": "High", "description": "FurtherExtendedContract.shadowingParent.y (local variable @ tests/shadowing_local_variable.sol#25) shadows:\n\t- BaseContract.y (state variable @ tests/shadowing_local_variable.sol#5)\n", "elements": [{"type": "variable", "name": "y", "source_mapping": {"start": 398, "length": 5, "filename": "tests/shadowing_local_variable.sol", "lines": [25]}}, {"type": "variable", "name": "y", "source_mapping": {"start": 70, "length": 10, "filename": "tests/shadowing_local_variable.sol", "lines": [5]}}]}, {"check": "shadowing-local", "impact": "Low", "confidence": "High", "description": "FurtherExtendedContract.shadowingParent.z (local variable @ tests/shadowing_local_variable.sol#25) shadows:\n\t- ExtendedContract.z (function @ tests/shadowing_local_variable.sol#11)\n", "elements": [{"type": "variable", "name": "z", "source_mapping": {"start": 405, "length": 6, "filename": "tests/shadowing_local_variable.sol", "lines": [25]}}, {"type": "function", "name": "z", "source_mapping": {"start": 150, "length": 27, "filename": "tests/shadowing_local_variable.sol", "lines": [11]}, "contract": {"type": "contract", "name": "ExtendedContract", "source_mapping": {"start": 85, "length": 110, "filename": "tests/shadowing_local_variable.sol", "lines": [8, 9, 10, 11, 12, 13, 14]}}}]}, {"check": "shadowing-local", "impact": "Low", "confidence": "High", "description": "FurtherExtendedContract.shadowingParent.w (local variable @ tests/shadowing_local_variable.sol#25) shadows:\n\t- FurtherExtendedContract.w (modifier @ tests/shadowing_local_variable.sol#20-23)\n", "elements": [{"type": "variable", "name": "w", "source_mapping": {"start": 413, "length": 6, "filename": "tests/shadowing_local_variable.sol", "lines": [25]}}, {"type": "function", "name": "w", "source_mapping": {"start": 274, "length": 71, "filename": "tests/shadowing_local_variable.sol", "lines": [20, 21, 22, 23]}, "contract": {"type": "contract", "name": "FurtherExtendedContract", "source_mapping": {"start": 197, "length": 235, "filename": "tests/shadowing_local_variable.sol", "lines": [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]}}}]}, {"check": "shadowing-local", "impact": "Low", "confidence": "High", "description": "FurtherExtendedContract.shadowingParent.v (local variable @ tests/shadowing_local_variable.sol#25) shadows:\n\t- ExtendedContract.v (event @ tests/shadowing_local_variable.sol#13)\n", "elements": [{"type": "variable", "name": "v", "source_mapping": {"start": 421, "length": 6, "filename": "tests/shadowing_local_variable.sol", "lines": [25]}}, {"type": "function", "name": "v", "source_mapping": {"start": 183, "length": 10, "filename": "tests/shadowing_local_variable.sol", "lines": [13]}, "contract": {"type": "contract", "name": "ExtendedContract", "source_mapping": {"start": 85, "length": 110, "filename": "tests/shadowing_local_variable.sol", "lines": [8, 9, 10, 11, 12, 13, 14]}}}]}] |
@ -0,0 +1,136 @@ |
|||||||
|
contract ERC20Function{ |
||||||
|
function balanceOf(address _owner) external returns(uint); |
||||||
|
} |
||||||
|
|
||||||
|
contract ERC20Variable{ |
||||||
|
mapping(address => uint) public balanceOf; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
contract ERC20TestBalance{ |
||||||
|
|
||||||
|
|
||||||
|
function good0(ERC20Function erc) external{ |
||||||
|
require(erc.balanceOf(msg.sender) > 0); |
||||||
|
} |
||||||
|
|
||||||
|
function good1(ERC20Variable erc) external{ |
||||||
|
require(erc.balanceOf(msg.sender) > 0); |
||||||
|
} |
||||||
|
|
||||||
|
function bad0(ERC20Function erc) external{ |
||||||
|
require(erc.balanceOf(address(this)) == 10); |
||||||
|
} |
||||||
|
|
||||||
|
function bad1(ERC20Variable erc) external{ |
||||||
|
require(erc.balanceOf(msg.sender) ==10); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
contract TestContractBalance { |
||||||
|
|
||||||
|
function bad0() external { |
||||||
|
require(address(address(this)).balance == 10 ether); |
||||||
|
msg.sender.transfer(0.1 ether); |
||||||
|
} |
||||||
|
|
||||||
|
function bad1() external { |
||||||
|
require(10 ether == address(address(this)).balance); |
||||||
|
msg.sender.transfer(0.1 ether); |
||||||
|
} |
||||||
|
|
||||||
|
function bad2() external { |
||||||
|
require(address(this).balance == 10 ether); |
||||||
|
msg.sender.transfer(0.1 ether); |
||||||
|
} |
||||||
|
|
||||||
|
function bad3() external { |
||||||
|
require(10 ether == address(this).balance); |
||||||
|
msg.sender.transfer(0.1 ether); |
||||||
|
} |
||||||
|
|
||||||
|
function bad4() external { |
||||||
|
uint256 balance = address(this).balance; |
||||||
|
if (balance == 10 ether) { |
||||||
|
msg.sender.transfer(0.1 ether); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function bad5() external { |
||||||
|
uint256 balance = address(this).balance; |
||||||
|
if (10 ether == balance) { |
||||||
|
msg.sender.transfer(0.1 ether); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function bad6() external { |
||||||
|
uint256 balance = address(address(this)).balance; |
||||||
|
if (balance == 10 ether) { |
||||||
|
msg.sender.transfer(0.1 ether); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function myfunc(uint256 balance) pure internal returns (uint256) { |
||||||
|
return balance - balance; |
||||||
|
} |
||||||
|
|
||||||
|
function good1() external { |
||||||
|
require (address(address(this)).balance >= 10 ether); |
||||||
|
msg.sender.transfer(0.1 ether); |
||||||
|
} |
||||||
|
|
||||||
|
function good2() external { |
||||||
|
require (10 <= address(address(this)).balance); |
||||||
|
msg.sender.transfer(0.1 ether); |
||||||
|
} |
||||||
|
|
||||||
|
function good3() external { |
||||||
|
require (address(this).balance >= 10 ether); |
||||||
|
msg.sender.transfer(0.1 ether); |
||||||
|
} |
||||||
|
|
||||||
|
function good4() external { |
||||||
|
require (10 <= address(this).balance); |
||||||
|
msg.sender.transfer(0.1 ether); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
contract TestSolidityKeyword{ |
||||||
|
|
||||||
|
function good0() external{ |
||||||
|
require(now > 0); |
||||||
|
} |
||||||
|
|
||||||
|
function good1() external{ |
||||||
|
require(block.number > 0); |
||||||
|
} |
||||||
|
|
||||||
|
function good2() external{ |
||||||
|
require(block.timestamp > 0); |
||||||
|
} |
||||||
|
|
||||||
|
function good3(uint param) public{ |
||||||
|
// address(this) simulate a particular corner case |
||||||
|
// where the SSA is better |
||||||
|
// the naive data dependency without SSA |
||||||
|
// will consider param and block.number to have a dep |
||||||
|
if(param == 0){ |
||||||
|
param = block.number; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function bad0() external{ |
||||||
|
require(now == 0); |
||||||
|
} |
||||||
|
|
||||||
|
function bad1() external{ |
||||||
|
require(block.number== 0); |
||||||
|
} |
||||||
|
|
||||||
|
function bad2() external{ |
||||||
|
require(block.number == 0); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
@ -0,0 +1,34 @@ |
|||||||
|
pragma solidity ^0.4.25; |
||||||
|
|
||||||
|
contract BaseContract { |
||||||
|
uint blockhash; |
||||||
|
uint now; |
||||||
|
|
||||||
|
event revert(bool condition); |
||||||
|
} |
||||||
|
|
||||||
|
contract ExtendedContract is BaseContract { |
||||||
|
uint ecrecover = 7; |
||||||
|
|
||||||
|
function assert(bool condition) public { |
||||||
|
uint msg; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
contract FurtherExtendedContract is ExtendedContract { |
||||||
|
uint blockhash = 7; |
||||||
|
uint this = 5; |
||||||
|
uint abi; |
||||||
|
|
||||||
|
modifier require { |
||||||
|
assert(msg.sender != address(0)); |
||||||
|
uint keccak256; |
||||||
|
uint sha3; |
||||||
|
_; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
contract Reserved{ |
||||||
|
address mutable; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,26 @@ |
|||||||
|
pragma solidity ^0.4.24; |
||||||
|
|
||||||
|
contract BaseContract { |
||||||
|
uint x = 5; |
||||||
|
uint y = 5; |
||||||
|
} |
||||||
|
|
||||||
|
contract ExtendedContract is BaseContract { |
||||||
|
uint x = 7; |
||||||
|
|
||||||
|
function z() public pure {} |
||||||
|
|
||||||
|
event v(); |
||||||
|
} |
||||||
|
|
||||||
|
contract FurtherExtendedContract is ExtendedContract { |
||||||
|
uint x = 7; |
||||||
|
|
||||||
|
|
||||||
|
modifier w { |
||||||
|
assert(msg.sender != address(0)); |
||||||
|
_; |
||||||
|
} |
||||||
|
|
||||||
|
function shadowingParent(uint x) public pure { int y; uint z; uint w; uint v; } |
||||||
|
} |
Loading…
Reference in new issue