Example #1
0
def test_delegate_call(sym_mock, concrete_mock, curr_instruction):
    # arrange
    # sym_mock = mocker.patch.object(delegatecall, "_symbolic_call")
    # concrete_mock = mocker.patch.object(delegatecall, "_concrete_call")
    sym_mock.return_value = []
    concrete_mock.return_value = []
    curr_instruction.return_value = {"address": "0x10"}

    active_account = Account("0x10")
    active_account.code = Disassembly("00")

    environment = Environment(active_account, None, None, None, None, None)
    state = GlobalState(None, environment, Node)
    state.mstate.memory = ["placeholder", "calldata_bling_0"]
    state.mstate.stack = [1, 2, 3]
    assert state.get_current_instruction() == {"address": "0x10"}

    node = Node("example")
    node.contract_name = "the contract name"
    node.function_name = "fallback"

    to = Variable("storage_1", VarType.SYMBOLIC)
    call = Call(node, state, None, "DELEGATECALL", to, None)

    statespace = MagicMock()
    statespace.calls = [call]

    # act
    execute(statespace)

    # assert
    assert concrete_mock.call_count == 1
    assert sym_mock.call_count == 1
Example #2
0
    def _add_external_call(global_state: GlobalState) -> None:
        gas = global_state.mstate.stack[-1]
        to = global_state.mstate.stack[-2]
        try:
            constraints = copy(global_state.mstate.constraints)
            solver.get_model(constraints + [
                UGT(gas, symbol_factory.BitVecVal(2300, 256)),
                Or(
                    to > symbol_factory.BitVecVal(16, 256),
                    to == symbol_factory.BitVecVal(0, 256),
                ),
            ])

            # Check whether we can also set the callee address
            try:
                constraints += [
                    to == 0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF
                ]
                solver.get_model(constraints)

                global_state.annotate(
                    StateChangeCallsAnnotation(global_state, True))
            except UnsatError:
                global_state.annotate(
                    StateChangeCallsAnnotation(global_state, False))
        except UnsatError:
            pass
Example #3
0
def get_dependency_annotation(state: GlobalState) -> DependencyAnnotation:
    """ Returns a dependency annotation

    :param state: A global state object
    """

    annotations = cast(List[DependencyAnnotation],
                       list(state.get_annotations(DependencyAnnotation)))

    if len(annotations) == 0:
        """FIXME: Hack for carrying over state annotations from the STOP and RETURN states of
        the previous states. The states are pushed on a stack in the world state annotation
        and popped off the stack in the subsequent iteration. This might break if any
        other strategy than bfs is used (?).
        """

        try:
            world_state_annotation = get_ws_dependency_annotation(state)
            annotation = world_state_annotation.annotations_stack.pop()
        except IndexError:
            annotation = DependencyAnnotation()

        state.annotate(annotation)
    else:
        annotation = annotations[0]

    return annotation
Example #4
0
    def _end_message_call(
        self,
        return_global_state: GlobalState,
        global_state: GlobalState,
        revert_changes=False,
        return_data=None,
    ) -> List[GlobalState]:
        # Resume execution of the transaction initializing instruction
        op_code = return_global_state.environment.code.instruction_list[
            return_global_state.mstate.pc]["opcode"]

        # Set execution result in the return_state
        return_global_state.last_return_data = return_data
        if not revert_changes:
            return_global_state.world_state = copy(global_state.world_state)
            return_global_state.environment.active_account = global_state.accounts[
                return_global_state.environment.active_account.address]

        # Execute the post instruction handler
        new_global_states = Instruction(op_code, self.dynamic_loader).evaluate(
            return_global_state, True)

        # In order to get a nice call graph we need to set the nodes here
        for state in new_global_states:
            state.node = global_state.node

        return new_global_states
def test_execute_node(mocker):
    record = TaintRecord()
    record.stack = [True, True, False, False]

    state_1 = GlobalState(None, None, None)
    state_1.mstate.stack = [1, 2, 3, 1]
    state_1.mstate.pc = 1
    mocker.patch.object(state_1, "get_current_instruction")
    state_1.get_current_instruction.return_value = {"opcode": "SWAP1"}

    state_2 = GlobalState(None, 1, None)
    state_2.mstate.stack = [1, 2, 4, 1]
    mocker.patch.object(state_2, "get_current_instruction")
    state_2.get_current_instruction.return_value = {"opcode": "ADD"}

    node = Node("Test contract")
    node.states = [state_1, state_2]

    # Act
    records = TaintRunner.execute_node(node, record)

    # Assert
    assert len(records) == 2

    assert records[0].stack == [True, True, False, False]
    assert records[1].stack == [True, True, False]

    assert state_2 in records[0].states
    assert state_1 in record.states
Example #6
0
    def _analyze_state(global_state: GlobalState) -> List[Issue]:

        annotations = cast(
            List[StateChangeCallsAnnotation],
            list(global_state.get_annotations(StateChangeCallsAnnotation)),
        )
        op_code = global_state.get_current_instruction()["opcode"]

        if len(annotations) == 0:
            if op_code in ("SSTORE", "CREATE", "CREATE2"):
                return []
        if op_code in ("SSTORE", "CREATE", "CREATE2"):
            for annotation in annotations:
                annotation.state_change_states.append(global_state)

        # Record state changes following from a transfer of ether
        if op_code in ("CALL", "DELEGATECALL", "CALLCODE"):
            value = global_state.mstate.stack[-3]  # type: BitVec
            if StateChange._balance_change(value, global_state):
                for annotation in annotations:
                    annotation.state_change_states.append(global_state)

        # Record external calls
        if op_code in ("CALL", "DELEGATECALL", "CALLCODE"):
            StateChange._add_external_call(global_state)

        # Check for vulnerabilities
        vulnerabilities = []
        for annotation in annotations:
            if not annotation.state_change_states:
                continue
            issue = annotation.get_issue(global_state)
            if issue:
                vulnerabilities.append(issue)
        return vulnerabilities
Example #7
0
    def _handle_transaction_end(self, state: GlobalState) -> None:

        state_annotation = _get_overflowunderflow_state_annotation(state)

        for annotation in state_annotation.overflowing_state_annotations:

            ostate = annotation.overflowing_state

            if ostate in self._ostates_unsatisfiable:
                continue

            if ostate not in self._ostates_satisfiable:
                try:
                    constraints = ostate.mstate.constraints + [
                        annotation.constraint
                    ]
                    solver.get_model(constraints)
                    self._ostates_satisfiable.add(ostate)
                except:
                    self._ostates_unsatisfiable.add(ostate)
                    continue

            log.debug(
                "Checking overflow in {} at transaction end address {}, ostate address {}"
                .format(
                    state.get_current_instruction()["opcode"],
                    state.get_current_instruction()["address"],
                    ostate.get_current_instruction()["address"],
                ))

            try:

                constraints = state.mstate.constraints + [
                    annotation.constraint
                ]
                transaction_sequence = solver.get_transaction_sequence(
                    state, constraints)
            except UnsatError:
                continue

            _type = "Underflow" if annotation.operator == "subtraction" else "Overflow"
            issue = Issue(
                contract=ostate.environment.active_account.contract_name,
                function_name=ostate.environment.active_function_name,
                address=ostate.get_current_instruction()["address"],
                swc_id=INTEGER_OVERFLOW_AND_UNDERFLOW,
                bytecode=ostate.environment.code.bytecode,
                title=self._get_title(_type),
                severity="High",
                description_head=self._get_description_head(annotation, _type),
                description_tail=self._get_description_tail(annotation, _type),
                gas_used=(state.mstate.min_gas_used,
                          state.mstate.max_gas_used),
                transaction_sequence=transaction_sequence,
            )

            address = _get_address_from_state(ostate)
            self.cache.add(address)
            self.issues.append(issue)
Example #8
0
 def __init__(self, call_state: GlobalState, constraints: List) -> None:
     """
     Initialize DelegateCall Annotation
     :param call_state: Call state
     """
     self.call_state = call_state
     self.constraints = constraints
     self.return_value = call_state.new_bitvec(
         "retval_{}".format(call_state.get_current_instruction()["address"]), 256
     )
Example #9
0
def _get_overflowunderflow_state_annotation(
        state: GlobalState) -> OverUnderflowStateAnnotation:
    state_annotations = cast(
        List[OverUnderflowStateAnnotation],
        list(state.get_annotations(OverUnderflowStateAnnotation)),
    )

    if len(state_annotations) == 0:
        state_annotation = OverUnderflowStateAnnotation()
        state.annotate(state_annotation)
        return state_annotation
    else:
        return state_annotations[0]
Example #10
0
def native_call(
    global_state: GlobalState,
    callee_address: Union[str, BitVec],
    call_data: BaseCalldata,
    memory_out_offset: Union[int, Expression],
    memory_out_size: Union[int, Expression],
) -> Optional[List[GlobalState]]:

    if (
        isinstance(callee_address, BitVec)
        or not 0 < int(callee_address, 16) <= PRECOMPILE_COUNT
    ):
        return None

    log.debug("Native contract called: " + callee_address)
    try:
        mem_out_start = util.get_concrete_int(memory_out_offset)
        mem_out_sz = util.get_concrete_int(memory_out_size)
    except TypeError:
        log.debug("CALL with symbolic start or offset not supported")
        return [global_state]

    contract_list = ["ecrecover", "sha256", "ripemd160", "identity"]
    call_address_int = int(callee_address, 16)
    native_gas_min, native_gas_max = calculate_native_gas(
        global_state.mstate.calculate_extension_size(mem_out_start, mem_out_sz),
        contract_list[call_address_int - 1],
    )
    global_state.mstate.min_gas_used += native_gas_min
    global_state.mstate.max_gas_used += native_gas_max
    global_state.mstate.mem_extend(mem_out_start, mem_out_sz)
    try:
        data = natives.native_contracts(call_address_int, call_data)
    except natives.NativeContractException:
        for i in range(mem_out_sz):
            global_state.mstate.memory[mem_out_start + i] = global_state.new_bitvec(
                contract_list[call_address_int - 1] + "(" + str(call_data) + ")", 8
            )
        return [global_state]

    for i in range(
        min(len(data), mem_out_sz)
    ):  # If more data is used then it's chopped off
        global_state.mstate.memory[mem_out_start + i] = data[i]

    retval = global_state.new_bitvec(
        "retval_" + str(global_state.get_current_instruction()["address"]), 256
    )
    global_state.mstate.stack.append(retval)
    global_state.node.constraints.append(retval == 1)
    return [global_state]
Example #11
0
 def _handle_sstore(state: GlobalState) -> None:
     stack = state.mstate.stack
     value = stack[-2]
     if not isinstance(value, Expression):
         return
     for annotation in value.annotations:
         if not isinstance(annotation, OverUnderflowAnnotation):
             continue
         state.annotate(
             OverUnderflowStateAnnotation(
                 annotation.overflowing_state,
                 annotation.operator,
                 annotation.constraint,
             ))
Example #12
0
def _analyze_states(state: GlobalState) -> List[Issue]:
    """
    :param state: the current state
    :return: returns the issues for that corresponding state
    """
    issues = []
    op_code = state.get_current_instruction()["opcode"]
    annotations = cast(
        List[DelegateCallAnnotation],
        list(state.get_annotations(DelegateCallAnnotation)),
    )

    if len(annotations) == 0 and op_code in ("RETURN", "STOP"):
        return []

    if op_code == "DELEGATECALL":
        gas = state.mstate.stack[-1]
        to = state.mstate.stack[-2]

        constraints = [
            to == ATTACKER_ADDRESS,
            UGT(gas, symbol_factory.BitVecVal(2300, 256)),
        ]

        for tx in state.world_state.transaction_sequence:
            if not isinstance(tx, ContractCreationTransaction):
                constraints.append(tx.caller == ATTACKER_ADDRESS)

        state.annotate(DelegateCallAnnotation(state, constraints))

        return []
    else:
        for annotation in annotations:
            try:
                transaction_sequence = solver.get_transaction_sequence(
                    state,
                    state.mstate.constraints
                    + annotation.constraints
                    + [annotation.return_value == 1],
                )
                issues.append(
                    annotation.get_issue(
                        state, transaction_sequence=transaction_sequence
                    )
                )
            except UnsatError:
                continue

        return issues
Example #13
0
    def _execute(self, state: GlobalState) -> None:
        """Executes analysis module for integer underflow and integer overflow.

        :param state: Statespace to analyse
        :return: Found issues
        """

        address = _get_address_from_state(state)

        if address in self.cache:
            return

        opcode = state.get_current_instruction()["opcode"]

        funcs = {
            "ADD": [self._handle_add],
            "SUB": [self._handle_sub],
            "MUL": [self._handle_mul],
            "SSTORE": [self._handle_sstore],
            "JUMPI": [self._handle_jumpi],
            "CALL": [self._handle_call],
            "RETURN": [self._handle_return, self._handle_transaction_end],
            "STOP": [self._handle_transaction_end],
            "EXP": [self._handle_exp],
        }
        for func in funcs[opcode]:
            func(state)
Example #14
0
 def _execute(self, state: GlobalState) -> None:
     if state.get_current_instruction()["address"] in self._cache:
         return
     issues = self._analyze_state(state)
     for issue in issues:
         self._cache.add(issue.address)
     self._issues.extend(issues)
Example #15
0
    def _execute(self, state: GlobalState) -> None:
        if state.get_current_instruction()["address"] in self.cache:
            return
        issues = self._analyze_state(state)

        annotation = get_potential_issues_annotation(state)
        annotation.potential_issues.extend(issues)
Example #16
0
    def execute_state(record: TaintRecord, state: GlobalState) -> TaintRecord:
        assert len(state.mstate.stack) == len(record.stack)
        """ Runs taint analysis on a state """
        record.add_state(state)
        new_record = record.clone()

        # Apply Change
        op = state.get_current_instruction()["opcode"]

        if op in TaintRunner.stack_taint_table.keys():
            mutator = TaintRunner.stack_taint_table[op]
            TaintRunner.mutate_stack(new_record, mutator)
        elif op.startswith("PUSH"):
            TaintRunner.mutate_push(op, new_record)
        elif op.startswith("DUP"):
            TaintRunner.mutate_dup(op, new_record)
        elif op.startswith("SWAP"):
            TaintRunner.mutate_swap(op, new_record)
        elif op is "MLOAD":
            TaintRunner.mutate_mload(new_record, state.mstate.stack[-1])
        elif op.startswith("MSTORE"):
            TaintRunner.mutate_mstore(new_record, state.mstate.stack[-1])
        elif op is "SLOAD":
            TaintRunner.mutate_sload(new_record, state.mstate.stack[-1])
        elif op is "SSTORE":
            TaintRunner.mutate_sstore(new_record, state.mstate.stack[-1])
        elif op.startswith("LOG"):
            TaintRunner.mutate_log(new_record, op)
        elif op in ("CALL", "CALLCODE", "DELEGATECALL", "STATICCALL"):
            TaintRunner.mutate_call(new_record, op)
        else:
            logging.debug("Unknown operation encountered: {}".format(op))

        return new_record
Example #17
0
def get_potential_issues_annotation(
        state: GlobalState) -> PotentialIssuesAnnotation:
    """
    Returns the potential issues annotation of the given global state, and creates one if
    one does not already exist.

    :param state: The global state
    :return:
    """
    for annotation in state.annotations:
        if isinstance(annotation, PotentialIssuesAnnotation):
            return annotation

    annotation = PotentialIssuesAnnotation()
    state.annotate(annotation)
    return annotation
    def get_issue(self, global_state: GlobalState) -> Optional[Issue]:
        if not self.state_change_states:
            return None

        severity = "Medium" if self.user_defined_address else "Low"
        address = global_state.get_current_instruction()["address"]
        logging.debug(
            "[EXTERNAL_CALLS] Detected state changes at addresses: {}".format(
                address))
        description_head = (
            "The contract account state is changed after an external call. ")
        description_tail = (
            "Consider that the called contract could re-enter the function before this "
            "state change takes place. This can lead to business logic vulnerabilities."
        )

        return Issue(
            contract=global_state.environment.active_account.contract_name,
            function_name=global_state.environment.active_function_name,
            address=address,
            title="State change after external call",
            severity=severity,
            description_head=description_head,
            description_tail=description_tail,
            swc_id=REENTRANCY,
            bytecode=global_state.environment.code.bytecode,
        )
Example #19
0
def execute_create():
    global last_state
    global created_contract_account
    if not last_state and not created_contract_account:
        code_raw = []
        for i in range(len(contract_init_code) // 2):
            code_raw.append(int(contract_init_code[2 * i:2 * (i + 1)], 16))
        calldata = ConcreteCalldata(0, code_raw)

        world_state = WorldState()
        account = world_state.create_account(balance=1000000, address=101)
        account.code = Disassembly("60a760006000f000")
        environment = Environment(account, None, calldata, None, None, None)
        og_state = GlobalState(world_state, environment, None,
                               MachineState(gas_limit=8000000))
        og_state.transaction_stack.append(
            (MessageCallTransaction(world_state=WorldState(),
                                    gas_limit=8000000), None))

        laser = LaserEVM()
        states = [og_state]
        last_state = og_state
        for state in states:
            new_states, op_code = laser.execute_state(state)
            last_state = state
            if op_code == "STOP":
                break
            states.extend(new_states)

        created_contract_address = last_state.mstate.stack[-1].value
        created_contract_account = last_state.world_state.accounts[
            created_contract_address]

    return last_state, created_contract_account
Example #20
0
        def world_state_filter_hook(state: GlobalState):

            if isinstance(state.current_transaction,
                          ContractCreationTransaction):
                # Reset iteration variable
                self.iteration = 0
                return

            world_state_annotation = get_ws_dependency_annotation(state)
            annotation = get_dependency_annotation(state)

            # Reset the state annotation except for storage written which is carried on to
            # the next transaction

            annotation.path = [0]
            annotation.storage_loaded = []
            annotation.has_call = False

            world_state_annotation.annotations_stack.append(annotation)

            log.debug(
                "Iteration {}: Adding world state at address {}, end of function {}.\nDependency map: {}\nStorage written: {}"
                .format(
                    self.iteration,
                    state.get_current_instruction()["address"],
                    state.node.function_name,
                    self.dependency_map,
                    annotation.storage_written[self.iteration],
                ))
        def jumpi_hook(state: GlobalState):
            address = state.get_current_instruction()["address"]

            annotation = get_dependency_annotation(state)
            annotation.path.append(address)

            _check_basic_block(address, annotation)
Example #22
0
def test_concrete_call_symbolic_to():
    # arrange
    address = "0x10"

    active_account = Account(address)
    active_account.code = Disassembly("00")
    environment = Environment(active_account, None, None, None, None, None)
    state = GlobalState(None, environment, None)
    state.mstate.memory = ["placeholder", "calldata_bling_0"]

    node = Node("example")
    node.contract_name = "the contract name"
    node.function_name = "the function name"

    to = Variable("calldata_3", VarType.SYMBOLIC)
    meminstart = Variable(1, VarType.CONCRETE)
    call = Call(node, state, None, None, to, None)

    # act
    issues = _concrete_call(call, state, address, meminstart)

    # assert
    issue = issues[0]
    assert issue.address == address
    assert issue.contract == node.contract_name
    assert issue.function == node.function_name
    assert issue.title == "Call data forwarded with delegatecall()"
    assert issue.type == "Informational"
    assert (
        issue.description
        == "This contract forwards its call data via DELEGATECALL in its fallback function."
        " This means that any function in the called contract can be executed."
        " Note that the callee contract will have access to the storage of the "
        "calling contract.\n DELEGATECALL target: calldata_3"
    )
Example #23
0
def get_state():
    active_account = Account("0x0", code=Disassembly("60606040"))
    environment = Environment(active_account, None, None, None, None, None)
    state = GlobalState(None, environment, None, MachineState(gas_limit=8000000))
    state.transaction_stack.append(
        (MessageCallTransaction(world_state=WorldState(), gas_limit=8000000), None)
    )
    return state
Example #24
0
    def _new_node_state(
        self, state: GlobalState, edge_type=JumpType.UNCONDITIONAL, condition=None
    ) -> None:
        """

        :param state:
        :param edge_type:
        :param condition:
        """
        new_node = Node(state.environment.active_account.contract_name)
        old_node = state.node
        state.node = new_node
        new_node.constraints = state.mstate.constraints
        if self.requires_statespace:
            self.nodes[new_node.uid] = new_node
            self.edges.append(
                Edge(
                    old_node.uid, new_node.uid, edge_type=edge_type, condition=condition
                )
            )

        if edge_type == JumpType.RETURN:
            new_node.flags |= NodeFlags.CALL_RETURN
        elif edge_type == JumpType.CALL:
            try:
                if "retval" in str(state.mstate.stack[-1]):
                    new_node.flags |= NodeFlags.CALL_RETURN
                else:
                    new_node.flags |= NodeFlags.FUNC_ENTRY
            except StackUnderflowException:
                new_node.flags |= NodeFlags.FUNC_ENTRY

        address = state.environment.code.instruction_list[state.mstate.pc]["address"]

        environment = state.environment
        disassembly = environment.code
        if isinstance(
            state.world_state.transaction_sequence[-1], ContractCreationTransaction
        ):
            environment.active_function_name = "constructor"
        elif address in disassembly.address_to_function_name:
            # Enter a new function
            environment.active_function_name = disassembly.address_to_function_name[
                address
            ]
            new_node.flags |= NodeFlags.FUNC_ENTRY

            log.debug(
                "- Entering function "
                + environment.active_account.contract_name
                + ":"
                + new_node.function_name
            )
        elif address == 0:
            environment.active_function_name = "fallback"

        new_node.function_name = environment.active_function_name
Example #25
0
    def _end_message_call(
        self,
        return_global_state: GlobalState,
        global_state: GlobalState,
        revert_changes=False,
        return_data=None,
    ) -> List[GlobalState]:
        """

        :param return_global_state:
        :param global_state:
        :param revert_changes:
        :param return_data:
        :return:
        """

        return_global_state.mstate.constraints += global_state.mstate.constraints
        # Resume execution of the transaction initializing instruction
        op_code = return_global_state.environment.code.instruction_list[
            return_global_state.mstate.pc]["opcode"]

        # Set execution result in the return_state
        return_global_state.last_return_data = return_data
        if not revert_changes:
            return_global_state.world_state = copy(global_state.world_state)
            return_global_state.environment.active_account = global_state.accounts[
                return_global_state.environment.active_account.address.value]
            if isinstance(global_state.current_transaction,
                          ContractCreationTransaction):
                return_global_state.mstate.min_gas_used += (
                    global_state.mstate.min_gas_used)
                return_global_state.mstate.max_gas_used += (
                    global_state.mstate.max_gas_used)

        # Execute the post instruction handler
        new_global_states = Instruction(op_code, self.dynamic_loader,
                                        self.iprof).evaluate(
                                            return_global_state, True)

        # In order to get a nice call graph we need to set the nodes here
        for state in new_global_states:
            state.node = global_state.node

        return new_global_states
Example #26
0
    def _handle_transaction_end(self, state: GlobalState) -> None:
        for annotation in cast(
                List[OverUnderflowStateAnnotation],
                state.get_annotations(OverUnderflowStateAnnotation),
        ):

            ostate = annotation.overflowing_state
            address = _get_address_from_state(ostate)

            if annotation.operator == "subtraction" and self._underflow_cache.get(
                    address, False):
                continue

            if annotation.operator != "subtraction" and self._overflow_cache.get(
                    address, False):
                continue

            try:
                # This check can be disabled if the contraints are to difficult for z3 to solve
                # within any reasonable time.
                if DISABLE_EFFECT_CHECK:
                    constraints = ostate.mstate.constraints + [
                        annotation.constraint
                    ]
                else:
                    constraints = state.mstate.constraints + [
                        annotation.constraint
                    ]

                transaction_sequence = solver.get_transaction_sequence(
                    state, constraints)
            except UnsatError:
                continue

            _type = "Underflow" if annotation.operator == "subtraction" else "Overflow"
            issue = Issue(
                contract=ostate.environment.active_account.contract_name,
                function_name=ostate.environment.active_function_name,
                address=ostate.get_current_instruction()["address"],
                swc_id=INTEGER_OVERFLOW_AND_UNDERFLOW,
                bytecode=ostate.environment.code.bytecode,
                title=self._get_title(_type),
                severity="High",
                description_head=self._get_description_head(annotation, _type),
                description_tail=self._get_description_tail(annotation, _type),
                gas_used=(state.mstate.min_gas_used,
                          state.mstate.max_gas_used),
            )

            issue.debug = json.dumps(transaction_sequence, indent=4)

            if annotation.operator == "subtraction":
                self._underflow_cache[address] = True
            else:
                self._overflow_cache[address] = True
            self._issues.append(issue)
def _get_global_state():
    active_account = Account("0x0", code=Disassembly("60606040"))
    passive_account = Account("0x325345346564645654645",
                              code=Disassembly("6060604061626364"))
    environment = Environment(active_account, None, None, None, None, None)
    world_state = WorldState()
    world_state.put_account(active_account)
    world_state.put_account(passive_account)
    return GlobalState(world_state, environment, None,
                       MachineState(gas_limit=8000000))
def test_execute(mocker):
    active_account = Account("0x00")
    environment = Environment(active_account, None, None, None, None, None)
    state_1 = GlobalState(None, environment, None,
                          MachineState(gas_limit=8000000))
    state_1.mstate.stack = [1, 2]
    mocker.patch.object(state_1, "get_current_instruction")
    state_1.get_current_instruction.return_value = {"opcode": "PUSH"}

    state_2 = GlobalState(None, environment, None,
                          MachineState(gas_limit=8000000))
    state_2.mstate.stack = [1, 2, 3]
    mocker.patch.object(state_2, "get_current_instruction")
    state_2.get_current_instruction.return_value = {"opcode": "ADD"}

    node_1 = Node("Test contract")
    node_1.states = [state_1, state_2]

    state_3 = GlobalState(None, environment, None,
                          MachineState(gas_limit=8000000))
    state_3.mstate.stack = [1, 2]
    mocker.patch.object(state_3, "get_current_instruction")
    state_3.get_current_instruction.return_value = {"opcode": "ADD"}

    node_2 = Node("Test contract")
    node_2.states = [state_3]

    edge = Edge(node_1.uid, node_2.uid)

    statespace = LaserEVM(None)
    statespace.edges = [edge]
    statespace.nodes[node_1.uid] = node_1
    statespace.nodes[node_2.uid] = node_2

    # Act
    result = TaintRunner.execute(statespace, node_1, state_1, [True, True])

    # Assert
    print(result)
    assert len(result.records) == 3
    assert result.records[2].states == []
    assert state_3 in result.records[1].states
Example #29
0
 def initial_global_state_from_environment(self,
                                           environment,
                                           active_function,
                                           last_function_called=None):
     # Initialize the execution environment
     global_state = GlobalState(self.world_state,
                                environment,
                                None,
                                last_function_called=last_function_called)
     global_state.environment.active_function_name = active_function
     return global_state
Example #30
0
def test_concrete_call_not_calldata():
    # arrange
    state = GlobalState(None, None, None)
    state.mstate.memory = ["placeholder", "not_calldata"]
    meminstart = Variable(1, VarType.CONCRETE)

    # act
    issues = _concrete_call(None, state, None, meminstart)

    # assert
    assert issues == []