def main(): args = parse_args() # Perform slither analysis on the given filename slither = Slither(args.project, **vars(args)) ret = defaultdict(list) if args.erc.upper() in ERCS: contract = slither.get_contract_from_name(args.contract_name) if not contract: err = f"Contract not found: {args.contract_name}" _log_error(err, args) return # First elem is the function, second is the event erc = ERCS[args.erc.upper()] generic_erc_checks(contract, erc[0], erc[1], ret) if args.erc.upper() in ADDITIONAL_CHECKS: ADDITIONAL_CHECKS[args.erc.upper()](contract, ret) else: err = f"Incorrect ERC selected {args.erc}" _log_error(err, args) return if args.json: output_to_json(args.json, None, {"upgradeability-check": ret})
def main() -> None: args = parse_args() if len(args.contract_source) == 2: # Source code is file.sol or project directory source_code, target = args.contract_source slither = Slither(source_code, **vars(args)) else: # Source code is published and retrieved via etherscan target = args.contract_source[0] slither = Slither(target, **vars(args)) if args.contract_name: contracts = slither.get_contract_from_name(args.contract_name) else: contracts = slither.contracts srs = SlitherReadStorage(contracts, args.max_depth) if args.rpc_url: # Remove target prefix e.g. rinkeby:0x0 -> 0x0. address = target[target.find(":") + 1:] # Default to implementation address unless a storage address is given. if not args.storage_address: args.storage_address = address srs.storage_address = args.storage_address srs.rpc = args.rpc_url if args.layout: srs.get_all_storage_variables() srs.get_storage_layout() else: assert args.variable_name # Use a lambda func to only return variables that have same name as target. # x is a tuple (`Contract`, `StateVariable`). srs.get_all_storage_variables( lambda x: bool(x[1].name == args.variable_name)) srs.get_target_variables(**vars(args)) # To retrieve slot values an rpc url is required. if args.value: assert args.rpc_url srs.get_slot_values() # Only write file if storage layout is used. if len(srs.slot_info) > 1: with open("storage_layout.json", "w", encoding="utf-8") as file: json.dump(srs.slot_info, file, indent=4)
def main(): args = parse_args() # Perform slither analysis on the given filename slither = Slither(args.filename, **vars(args)) contract = slither.get_contract_from_name(args.contract) if not contract: if len(slither.contracts) == 1: contract = slither.contracts[0] else: if args.contract is None: logger.error(f'Specify the target: --contract ContractName') else: logger.error(f'{args.contract} not found') return addresses = Addresses(args.address_owner, args.address_user, args.address_attacker) generate_erc20(contract, args.scenario, addresses)
from slither import Slither from slither.analyses.data_dependency.data_dependency import is_dependent, is_tainted, pprint_dependency from slither.core.declarations.solidity_variables import SolidityVariableComposed slither = Slither('data_dependency.sol') contract = slither.get_contract_from_name('Simple') destination = contract.get_state_variable_from_name('destination') source = contract.get_state_variable_from_name('source') print('{} is dependent of {}: {}'.format( source, destination, is_dependent(source, destination, contract))) assert not is_dependent(source, destination, contract) print('{} is dependent of {}: {}'.format( destination, source, is_dependent(destination, source, contract))) assert is_dependent(destination, source, contract) print('{} is tainted {}'.format(source, is_tainted(source, contract, slither))) assert not is_tainted(source, contract, slither) print('{} is tainted {}'.format(destination, is_tainted(destination, contract, slither))) assert is_tainted(destination, contract, slither) contract = slither.get_contract_from_name('Reference') destination = contract.get_state_variable_from_name('destination') source = contract.get_state_variable_from_name('source') print('Reference contract') print('{} is dependent of {}: {}'.format( source, destination, is_dependent(source, destination, contract)))
import sys from slither import Slither from slither.analyses.data_dependency.data_dependency import ( is_dependent, is_tainted, ) from slither.core.declarations.solidity_variables import SolidityVariableComposed if len(sys.argv) != 2: print("Usage: python data_dependency.py file.sol") sys.exit(-1) slither = Slither(sys.argv[1]) contract = slither.get_contract_from_name("Simple") assert contract destination = contract.get_state_variable_from_name("destination") source = contract.get_state_variable_from_name("source") print("{} is dependent of {}: {}".format( source, destination, is_dependent(source, destination, contract))) assert not is_dependent(source, destination, contract) print("{} is dependent of {}: {}".format( destination, source, is_dependent(destination, source, contract))) assert is_dependent(destination, source, contract) print("{} is tainted {}".format(source, is_tainted(source, contract))) assert not is_tainted(source, contract) print("{} is tainted {}".format(destination, is_tainted(destination, contract))) assert is_tainted(destination, contract)
def main(): json_results = { 'check-initialization': defaultdict(dict), 'variable-initialization': defaultdict(dict), 'compare-function-ids': defaultdict(dict), 'compare-variables-order-implementation': defaultdict(dict), 'compare-variables-order-proxy': defaultdict(dict), 'constant_conformance': defaultdict(dict), 'proxy-present': False, 'contract_v2-present': False } args = parse_args() v1_filename = vars(args)['contract.sol'] try: v1 = Slither(v1_filename, **vars(args)) # Analyze logic contract v1_name = args.ContractName v1_contract = v1.get_contract_from_name(v1_name) if v1_contract is None: info = 'Contract {} not found in {}'.format(v1_name, v1.filename) logger.error(red(info)) if args.json: output_to_json(args.json, str(info), {"upgradeability-check": json_results}) return _checks_on_contract(v1_contract, json_results) # Analyze Proxy proxy_contract = None if args.proxy_name: if args.proxy_filename: proxy = Slither(args.proxy_filename, **vars(args)) else: proxy = v1 proxy_contract = proxy.get_contract_from_name(args.proxy_name) if proxy_contract is None: info = 'Proxy {} not found in {}'.format( args.proxy_name, proxy.filename) logger.error(red(info)) if args.json: output_to_json(args.json, str(info), {"upgradeability-check": json_results}) return json_results['proxy-present'] = True _checks_on_contract_and_proxy(v1_contract, proxy_contract, json_results) # Analyze new version if args.new_contract_name: if args.new_contract_filename: v2 = Slither(args.new_contract_filename, **vars(args)) else: v2 = v1 v2_contract = v2.get_contract_from_name(args.new_contract_name) if v2_contract is None: info = 'New logic contract {} not found in {}'.format( args.new_contract_name, v2.filename) logger.error(red(info)) if args.json: output_to_json(args.json, str(info), {"upgradeability-check": json_results}) return json_results['contract_v2-present'] = True if proxy_contract: _checks_on_contract_and_proxy(v2_contract, proxy_contract, json_results, missing_variable_check=False) _checks_on_contract_update(v1_contract, v2_contract, json_results) if args.json: output_to_json(args.json, None, {"upgradeability-check": json_results}) except SlitherException as e: logger.error(str(e)) if args.json: output_to_json(args.json, str(e), {"upgradeability-check": json_results}) return
from slither import Slither # from analysis import is_dependent, pprint_dependency, compute_dependency_contract from dependency import Dependency from refinement import Refinement slither = Slither('data_dependency_simple_example.sol') myContract = slither.get_contract_from_name('MyContract') funcA = myContract.get_function_from_signature('foo()') a = myContract.get_state_variable_from_name('a') b = myContract.get_state_variable_from_name('b') c = myContract.get_state_variable_from_name('c') d = myContract.get_state_variable_from_name('d') D = Dependency() D.compute_contract(myContract, slither) D.dependencies = funcA.context[D.KEY_NON_SSA] R = Refinement() R.compute_contract(myContract, slither) guards = [] for var in R.types[R.Typ.GUARD]: if var in D.dependencies: guards += D.dependencies[var] R.types[R.Typ.GUARD] += guards
def main(): json_results = { "proxy-present": False, "contract_v2-present": False, "detectors": [], } args = parse_args() v1_filename = vars(args)["contract.sol"] number_detectors_run = 0 detectors = _get_checks() try: variable1 = Slither(v1_filename, **vars(args)) # Analyze logic contract v1_name = args.ContractName v1_contracts = variable1.get_contract_from_name(v1_name) if len(v1_contracts) != 1: info = f"Contract {v1_name} not found in {variable1.filename}" logger.error(red(info)) if args.json: output_to_json(args.json, str(info), json_results) return v1_contract = v1_contracts[0] detectors_results, number_detectors = _checks_on_contract( detectors, v1_contract) json_results["detectors"] += detectors_results number_detectors_run += number_detectors # Analyze Proxy proxy_contract = None if args.proxy_name: if args.proxy_filename: proxy = Slither(args.proxy_filename, **vars(args)) else: proxy = variable1 proxy_contracts = proxy.get_contract_from_name(args.proxy_name) if len(proxy_contracts) != 1: info = f"Proxy {args.proxy_name} not found in {proxy.filename}" logger.error(red(info)) if args.json: output_to_json(args.json, str(info), json_results) return proxy_contract = proxy_contracts[0] json_results["proxy-present"] = True detectors_results, number_detectors = _checks_on_contract_and_proxy( detectors, v1_contract, proxy_contract) json_results["detectors"] += detectors_results number_detectors_run += number_detectors # Analyze new version if args.new_contract_name: if args.new_contract_filename: variable2 = Slither(args.new_contract_filename, **vars(args)) else: variable2 = variable1 v2_contracts = variable2.get_contract_from_name( args.new_contract_name) if len(v2_contracts) != 1: info = ( f"New logic contract {args.new_contract_name} not found in {variable2.filename}" ) logger.error(red(info)) if args.json: output_to_json(args.json, str(info), json_results) return v2_contract = v2_contracts[0] json_results["contract_v2-present"] = True if proxy_contract: detectors_results, _ = _checks_on_contract_and_proxy( detectors, v2_contract, proxy_contract) json_results["detectors"] += detectors_results detectors_results, number_detectors = _checks_on_contract_update( detectors, v1_contract, v2_contract) json_results["detectors"] += detectors_results number_detectors_run += number_detectors # If there is a V2, we run the contract-only check on the V2 detectors_results, _ = _checks_on_contract(detectors, v2_contract) json_results["detectors"] += detectors_results number_detectors_run += number_detectors to_log = f'{len(json_results["detectors"])} findings, {number_detectors_run} detectors run' logger.info(to_log) if args.json: output_to_json(args.json, None, json_results) except SlitherException as slither_exception: logger.error(str(slither_exception)) if args.json: output_to_json(args.json, str(slither_exception), json_results) return
def analyze(fname, cname='MyContract', funcname='foo()'): slither = Slither(fname) myContract = slither.get_contract_from_name(cname) funcA = myContract.get_function_from_signature(funcname) # Dependency Analysis D = Dependency() D.compute_contract(myContract, slither) D.dependencies = funcA.context[D.KEY_NON_SSA] # Refinement Analysis R = Refinement() R.compute_contract(myContract, slither, fname) # Lambda Analysis lambdas = get_lambda_analysis(fname, myContract, slither) # For Guard Types, use Dependency Analysis to fetch all vars which affect # the Guard (i.e. on which the guard depends) guards = [] for var in R.types[R.Typ.GUARD]: if var in D.dependencies: guards += D.dependencies[var] R.types[R.Typ.GUARD] += guards # Remove temporary variables and ref vars from types to_delete = {} for typ in R.types: to_delete[typ] = [] if typ != 6 and typ != 7: for var in R.types[typ]: if var.name.startswith("REF") or var.name.startswith("TMP"): to_delete[typ].append(var) for k,vals in to_delete.items(): for v in vals: R.types[k].remove(v) # Remove temporary variables and ref vars from dependencies to_delete = [] for var in D.dependencies: if var.name.startswith("REF") or var.name.startswith("TMP"): to_delete.append(var) else: to_delete2 = [] for var2 in D.dependencies[var]: if var2.name.startswith("REF") or var2.name.startswith("TMP"): to_delete2.append(var2) for x in to_delete2: D.dependencies[var].remove(x) if len(D.dependencies[var]) == 0: to_delete.append(var) for x in to_delete: D.dependencies.pop(x, None) # Fetch written and read types from dependencies R.types[R.Typ.WRITTEN] += D.dependencies.keys() R.types[R.Typ.READ] += [x for vals in D.dependencies.values() for x in vals] # Anything that is an index or guard is also read R.types[R.Typ.READ] += R.types[R.Typ.INDEX] R.types[R.Typ.READ] += R.types[R.Typ.GUARD] R.types[R.Typ.READ] += R.types[R.Typ.GUARDSTART] R.types[R.Typ.READ] += R.types[R.Typ.GUARDEND] # Reformat refinement type entries R_types_formatted = {} for typ, vrs in R.types.items(): # Special check for lower casing True and False constants rhs = set(map(lambda v: v.lower() if v=="True" or v=="False" else v, set(map(str, vrs)))) typ = typ.lower() if typ == "True" or typ == "False" else typ R_types_formatted[typ] = rhs R.types = R_types_formatted # Reformat dependencies entries dependencies_formatted = {} for v, vrs in D.dependencies.items(): # Special check for lower casing True and False constants lhs = str(v).lower() if str(v) == "True" or str(v) == "False" else str(v) rhs = set(map(lambda v: v.lower() if v=="True" or v=="False" else v, set(map(str, vrs)))) dependencies_formatted[lhs] = rhs D.dependencies = dependencies_formatted # Add lambdas to dependencies based on sub-parts dependencies_lambdas = {} for v, vrs in D.dependencies.items(): dependencies_lambdas[v] = vrs for lam in lambdas: lam_vrs = re.findall(r"[\w']+", lam[lam.index(":")+1:]) if any(map(lambda lv: lv in vrs, lam_vrs)): dependencies_lambdas[v].add(lam) D.dependencies = dependencies_lambdas # # Transitive Closure of Dependencies # D.dependencies = transitive_close(D.dependencies) return D, R
def analyze_lambdas(fname, cname='MyContract', funcname='foo()'): slither = Slither(fname) myContract = slither.get_contract_from_name(cname) return get_lambda_analysis(fname, myContract, slither)
def main(): json_results = { 'proxy-present': False, 'contract_v2-present': False, 'detectors': [] } args = parse_args() v1_filename = vars(args)['contract.sol'] number_detectors_run = 0 detectors = _get_checks() try: v1 = Slither(v1_filename, **vars(args)) # Analyze logic contract v1_name = args.ContractName v1_contract = v1.get_contract_from_name(v1_name) if v1_contract is None: info = 'Contract {} not found in {}'.format(v1_name, v1.filename) logger.error(red(info)) if args.json: output_to_json(args.json, str(info), json_results) return detectors_results, number_detectors = _checks_on_contract( detectors, v1_contract) json_results['detectors'] += detectors_results number_detectors_run += number_detectors # Analyze Proxy proxy_contract = None if args.proxy_name: if args.proxy_filename: proxy = Slither(args.proxy_filename, **vars(args)) else: proxy = v1 proxy_contract = proxy.get_contract_from_name(args.proxy_name) if proxy_contract is None: info = 'Proxy {} not found in {}'.format( args.proxy_name, proxy.filename) logger.error(red(info)) if args.json: output_to_json(args.json, str(info), json_results) return json_results['proxy-present'] = True detectors_results, number_detectors = _checks_on_contract_and_proxy( detectors, v1_contract, proxy_contract) json_results['detectors'] += detectors_results number_detectors_run += number_detectors # Analyze new version if args.new_contract_name: if args.new_contract_filename: v2 = Slither(args.new_contract_filename, **vars(args)) else: v2 = v1 v2_contract = v2.get_contract_from_name(args.new_contract_name) if v2_contract is None: info = 'New logic contract {} not found in {}'.format( args.new_contract_name, v2.filename) logger.error(red(info)) if args.json: output_to_json(args.json, str(info), json_results) return json_results['contract_v2-present'] = True if proxy_contract: detectors_results, _ = _checks_on_contract_and_proxy( detectors, v2_contract, proxy_contract) json_results['detectors'] += detectors_results detectors_results, number_detectors = _checks_on_contract_update( detectors, v1_contract, v2_contract) json_results['detectors'] += detectors_results number_detectors_run += number_detectors # If there is a V2, we run the contract-only check on the V2 detectors_results, _ = _checks_on_contract(detectors, v2_contract) json_results['detectors'] += detectors_results number_detectors_run += number_detectors logger.info( f'{len(json_results["detectors"])} findings, {number_detectors_run} detectors run' ) if args.json: output_to_json(args.json, None, json_results) except SlitherException as e: logger.error(str(e)) if args.json: output_to_json(args.json, str(e), json_results) return
import sys from slither import Slither from slither.analyses.data_dependency.data_dependency import is_dependent, is_tainted, pprint_dependency from slither.core.declarations.solidity_variables import SolidityVariableComposed if len(sys.argv) != 2: print('Usage: python data_dependency.py file.sol') exit(-1) slither = Slither(sys.argv[1]) contract = slither.get_contract_from_name('Simple') destination = contract.get_state_variable_from_name('destination') source = contract.get_state_variable_from_name('source') print('{} is dependent of {}: {}'.format( source, destination, is_dependent(source, destination, contract))) assert not is_dependent(source, destination, contract) print('{} is dependent of {}: {}'.format( destination, source, is_dependent(destination, source, contract))) assert is_dependent(destination, source, contract) print('{} is tainted {}'.format(source, is_tainted(source, contract))) assert not is_tainted(source, contract) print('{} is tainted {}'.format(destination, is_tainted(destination, contract))) assert is_tainted(destination, contract) contract = slither.get_contract_from_name('Reference') destination = contract.get_state_variable_from_name('destination')