diff --git a/utils/upgradability/__main__.py b/utils/upgradability/__main__.py index 8b3edfcbd..471e92a79 100644 --- a/utils/upgradability/__main__.py +++ b/utils/upgradability/__main__.py @@ -4,7 +4,7 @@ import sys from slither import Slither -from .compare_variables_order import compare_variables_order +from .compare_variables_order import compare_variables_order_implementation, compare_variables_order_proxy from .compare_function_ids import compare_function_ids logging.basicConfig() @@ -13,17 +13,17 @@ logger = logging.getLogger("Slither-check-upgradability") def parse_args(): parser = argparse.ArgumentParser(description='Slither Upgradability Checks', - usage="slither-check-upgradability proxy.sol ProxyName v1.sol V1Name v2.sol V2Name") + usage="slither-check-upgradability proxy.sol ProxyName implem.sol ContractName") parser.add_argument('proxy.sol', help='Proxy filename') parser.add_argument('ProxyName', help='Contract name') - parser.add_argument('v1.sol', help='Version 1 filename') - parser.add_argument('V1Name', help='Contract name') + parser.add_argument('implem.sol', help='Implementation filename') + parser.add_argument('ContractName', help='Contract name') - parser.add_argument('v2.sol', help='Version 2 filename') - parser.add_argument('V2Name', help='Contract name') + parser.add_argument('--new-version', help='New implementation filename') + parser.add_argument('--new-contract-name', help='New contract name (if changed)') if len(sys.argv) == 1: parser.print_help(sys.stderr) @@ -34,13 +34,23 @@ def parse_args(): def main(): args = parse_args() - proxy = Slither(vars(args)['proxy.sol']) proxy_name = args.ProxyName - v1 = Slither(vars(args)['v1.sol']) - v1_name = args.V1Name - v2 = Slither(vars(args)['v2.sol']) - v2_name = args.V2Name + v1 = Slither(vars(args)['implem.sol']) + v1_name = args.ContractName + + last_contract = v1 + last_name = v1_name + + if args.new_version: + v2 = Slither(args.new_version) + last_contract = v2 + + if args.new_contract_name: + last_name = args.new_contract_name + + compare_function_ids(last_contract, proxy) + compare_variables_order_proxy(last_contract, last_name, proxy, proxy_name) - compare_variables_order(v1, v1_name, v2, v2_name) - compare_function_ids(v2, proxy) + if args.new_version: + compare_variables_order_implementation(v1, v1_name, v2, last_name) diff --git a/utils/upgradability/compare_function_ids.py b/utils/upgradability/compare_function_ids.py index b95e7f110..aaee290d7 100644 --- a/utils/upgradability/compare_function_ids.py +++ b/utils/upgradability/compare_function_ids.py @@ -34,9 +34,9 @@ def compare_function_ids(implem, proxy): for (k, _) in signatures_ids_implem.items(): if k in signatures_ids_proxy: found = True - logger.info(red('Collision found {} {}'.format(signatures_ids_implem[k], - signatures_ids_proxy[k]))) + logger.info(red('Function id collision found {} {}'.format(signatures_ids_implem[k], + signatures_ids_proxy[k]))) if not found: - logger.info(green('No collision found')) + logger.info(green('No function id collision found')) diff --git a/utils/upgradability/compare_variables_order.py b/utils/upgradability/compare_variables_order.py index c26ac1213..4a658c07f 100644 --- a/utils/upgradability/compare_variables_order.py +++ b/utils/upgradability/compare_variables_order.py @@ -4,21 +4,21 @@ import logging from slither import Slither from slither.utils.function import get_function_id -from slither.utils.colors import red, green +from slither.utils.colors import red, green, yellow logger = logging.getLogger("VariablesOrder") logger.setLevel(logging.INFO) -def compare_variables_order(v1, contract_name1, v2, contract_name2): +def compare_variables_order_implementation(v1, contract_name1, v2, contract_name2): contract_v1 = v1.get_contract_from_name(contract_name1) if contract_v1 is None: - logger.info(red('Contract {} not found'.format(contract_name1))) + logger.info(red('Contract {} not found in {}'.format(contract_name1, v1.filename))) exit(-1) contract_v2 = v2.get_contract_from_name(contract_name2) if contract_v2 is None: - logger.info(red('Contract {} not found'.format(contract_name2))) + logger.info(red('Contract {} not found in {}'.format(contract_name2, v2.filename))) exit(-1) @@ -39,7 +39,7 @@ def compare_variables_order(v1, contract_name1, v2, contract_name2): logger.info(red('Different variable: {} {} -> {} {}'.format(v1_name, v1_type, v2_name, - v2_type))) + v2_type))) if len(order_v2) > len(order_v1): new_variables = order_v2[len(order_v1):] @@ -47,5 +47,50 @@ def compare_variables_order(v1, contract_name1, v2, contract_name2): logger.info(green('New variable: {} {}'.format(name, t))) if not found: - logger.info(green('No error found')) + logger.info(green('No error found (variables ordering between implementations)')) + +def compare_variables_order_proxy(implem, implem_name, proxy, proxy_name): + + contract_implem = implem.get_contract_from_name(implem_name) + if contract_implem is None: + logger.info(red('Contract {} not found in {}'.format(implem_name, implem.filename))) + exit(-1) + + contract_proxy = proxy.get_contract_from_name(proxy_name) + if contract_proxy is None: + logger.info(red('Contract {} not found in {}'.format(proxy_name, proxy.filename))) + exit(-1) + + + order_implem = [(variable.name, variable.type) for variable in contract_implem.state_variables if not variable.is_constant] + order_proxy = [(variable.name, variable.type) for variable in contract_proxy.state_variables if not variable.is_constant] + + + found = False + for idx in range(0, len(order_proxy)): + (proxy_name, proxy_type) = order_proxy[idx] + if len(order_proxy) < idx: + logger.info(red('Extra variable in the proxy: {} {}'.format(proxy_name, proxy_type))) + continue + (implem_name, implem_type) = order_implem[idx] + + if (proxy_name != implem_name) or (proxy_type != implem_type): + found = True + logger.info(red('Different variable: {} {} -> {} {}'.format(proxy_name, + proxy_type, + implem_name, + implem_type))) + else: + logger.info(yellow('Variable in the proxy: {} {}'.format(proxy_name, + proxy_type))) + + + #if len(order_implem) > len(order_proxy): + # new_variables = order_implem[len(order_proxy):] + # for (name, t) in new_variables: + # logger.info(green('Variable only in implem: {} {}'.format(name, t))) + + if not found: + logger.info(green('No error found (variables ordering proxy <-> implementation)')) +