Example #1
0
def all_declarations_public(source: str) -> str:
    """
    Using a regex it makes public all the variable inside source
    :param source:
    :param ast:
    :return: edited_source: str
    """

    ast = asthelper.compile_from_source(source)

    nodes = asthelper.find_all_nodes(ast, {
        'nodeType': 'VariableDeclaration',
        'stateVariable': True
    })
    destination = source

    declaration_re = re.compile(
        r"(address|string|bool|bytes?\d*|u?int\d*|mapping.*\))(\[\d*\]|)?\s*(public|private|internal|external|)?\s+(\w+)\s*(;|=)"
    )

    for n in nodes:
        start, length, _ = n['src'].split(':')
        start = int(start)
        length = int(length)
        line = source[start:start + length + 1]
        #    print("before: ", line)
        left, right = tuple(destination.split(line, 1))
        middle = declaration_re.sub(r"\g<1>\g<2> public \g<4> \g<5>", line)
        destination = left + middle + right
    #    print("after: ", middle)

    return destination
    def before_test(self, source):
        ast_json = asthelper.compile_from_source(source)
        function_name = 'testFunction'

        function_node = asthelper.find_node(ast_json, {
            'nodeType': 'FunctionDefinition',
            'name': function_name
        })
        function_body = function_node['body']
        function_statements = function_body['statements']

        # Enumerate all the stataments with a require
        require_nodes = [
            i for (i, x) in enumerate(function_statements)
            if asthelper.find_node(x, {'name': 'require'})
        ]

        if not require_nodes:
            raise Exception("No requires")

        # stataments_under_inspection = All the stataments of the function until the last require (included)
        statements_under_inspection = function_statements[:require_nodes[-1] +
                                                          1]

        # Remove event emit statements
        # Remove banned statements
        events_definition_nodes = asthelper.find_all_nodes(
            ast_json, {'nodeType': 'EventDefinition'})

        return events_definition_nodes, statements_under_inspection
Example #3
0
def main(args):
    """
    Entry point of the program
    :param args:
    :return:
    """

    # read original source code
    with open(args.source) as r:
        edited_source_code = r.read()

    # apply operations
    if args.allpublic:
        # convert all variable declaration to public
        edited_source_code = all_declarations_public(edited_source_code)

    if args.getters:
        # creates getters for array length
        edited_source_code = inject_getter_functions(edited_source_code)

    if args.throwrevert:
        edited_source_code = throw2revert(edited_source_code)

    if args.ifrevert:
        edited_source_code = ifrevert2require(edited_source_code)

    if args.asserts:
        edited_source_code = edited_source_code.replace('assert(', 'require(')

    if args.fallback:
        edited_source_code = convert_fallback_function(edited_source_code)

    if args.reassigment:
        # convert 	balanceOf[target] += mintedAmount; to
        # to        var_something = balanceOf[target] + mintedAmount;
        edited_source_code = convert_reassignment(edited_source_code)

    # Check if compile or raise an exception
    asthelper.compile_from_source(edited_source_code)

    # write on output files
    with open(args.output, 'w') as w:
        w.write(edited_source_code)
Example #4
0
def inject_getter_functions(source: str):
    """
    Create getters for array's length member
    :param source: original source code
    :return: edited source code
    """
    ast = asthelper.compile_from_source(source)

    state_variables = \
        [x for x in asthelper.find_all_nodes(ast, {'nodeType': 'VariableDeclaration', 'stateVariable': True})]

    state_variables_list = [
        x for x in state_variables
        if 't_array' in x['typeDescriptions']['typeIdentifier']
    ]
    state_variables_names = [x['name'] for x in state_variables_list]

    edited_source = source
    for state_variable in state_variables_names:
        edited_source = _inject_getter_function(edited_source, state_variable)

    return edited_source
Example #5
0
def convert_reassignment(source: str) -> str:
    regex = r"^[\s|\t]*([^\s]+)\s+(\+|\-|\*)?=\s+([^;]*)"
    ast = asthelper.compile_from_source(source)
    assigment_nodes = asthelper.find_all_nodes(ast,
                                               {'nodeType': '^Assignment$'})

    edited_source = source

    for node in assigment_nodes:
        start, length, _ = node['src'].split(':')
        start = int(start)
        length = int(length)
        line = source[start:start + length + 1]
        line_rgx = r'^[\s|\t]*' + re.escape(line)
        pieces = re.compile(line_rgx, re.M).split(edited_source, 1)

        if len(pieces) != 2:
            # not exact "LINE" match found
            continue

        left, right = tuple(pieces)
        name = 'var nvar_{1}'.format(node['typeDescriptions']['typeString'],
                                     node['id'])

        new_line = line
        matches = re.search(regex, line, re.M)
        if matches and matches.group(2) is None:
            subst = name + ' = \g<3>'
            new_line = re.sub(regex, subst, new_line, re.M)
        elif matches and matches.group(2):
            subst = name + ' = \g<1> \g<2> \g<3>'
            new_line = re.sub(regex, subst, new_line, re.M)

        edited_source = left + new_line + right

    return edited_source
Example #6
0
 def before_test(self, source):
     ast_json = asthelper.compile_from_source(source)
     function_name = 'testFunction'
     return visit_ast(ast_json, function_name)
Example #7
0
def ifrevert2require(source: str) -> str:
    """
    Conver the assigment to newly created declarations
    :param source:
    :return:
    """
    ast = asthelper.compile_from_source(source)
    if_nodes = asthelper.find_all_nodes(ast, {'nodeType': '^IfStatement$'})

    edited_source = source

    for node in if_nodes:

        try:
            reverts = asthelper.find_node(node['trueBody'], {
                'nodeType': '^Identifier$',
                'name': '^revert$'
            })

            # Check for return false
            return_false = False
            if 'statements' in node['trueBody']:
                if_statements = node['trueBody']['statements']
                if len(if_statements) == 1:
                    return_statement = asthelper.find_node(
                        node['trueBody'], {'nodeType': '^Return$'})
                    if return_statement and asthelper.find_node(
                            node['trueBody'], {
                                'nodeType': '^Literal$',
                                'value': '^false$'
                            }):
                        return_false = True
            elif 'expression' in node['trueBody']:
                return_statement = asthelper.find_node(
                    node['trueBody'], {'nodeType': '^Return$'})
                if return_statement and asthelper.find_node(
                        node['trueBody'], {
                            'nodeType': '^Literal$',
                            'value': '^false$'
                        }):
                    return_false = True

            if reverts or return_false:
                start, length, _ = node['src'].split(':')
                start = int(start)
                length = int(length)
                line = source[start:start + length + 1]
                left, right = tuple(edited_source.split(line, 1))

                # other way
                # new_line = line.replace('if', 'require')
                # sa = new_line.split(')')
                # new_line = ')'.join(sa[:-2]) # remove the portion after the last if closed bracket

                if_condition = asthelper.astnode.AstNode(
                    None, node['condition']).to_sol_string()
                require_statement = 'require(({}) == false);\n'.format(
                    if_condition)
                edited_source = left + require_statement + right
        except Exception as e:
            # an error while editing some if, maybe contains a function
            # just skip
            continue

    return edited_source
	def before_test(self, source):
		ast_json = asthelper.compile_from_source(source)
		function_name = 'testFunction'
		inspected = visit_ast(ast_json, function_name)
		require_conditions = _requires_constraints(inspected['require_nodes'])
		return require_conditions, inspected['candidate_for_overflow']