Esempio n. 1
0
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})
Esempio n. 2
0
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)
Esempio n. 3
0
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)
Esempio n. 4
0
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)))
Esempio n. 5
0
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)
Esempio n. 6
0
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
Esempio n. 7
0
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
Esempio n. 9
0
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    
Esempio n. 10
0
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)
Esempio n. 11
0
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
Esempio n. 12
0
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')