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