def run(self, open_world_states: list, evm): """ Runs this transaction on the evm starting from the open world states """ # Consume the open states open_states = open_world_states[:] del open_world_states[:] for open_world_state in open_states: # Initialize the execution environment environment = Environment( open_world_state[self.callee_address], self.caller, [], self.gas_price, self.call_value, self.origin, calldata_type=CalldataType.SYMBOLIC, ) new_node = Node(environment.active_account.contract_name) evm.instructions_covered = [False for _ in environment.code.instruction_list] evm.nodes[new_node.uid] = new_node if open_world_state.node: evm.edges.append(Edge(open_world_state.node.uid, new_node.uid, edge_type=JumpType.Transaction, condition=None)) global_state = GlobalState(open_world_state.accounts, environment, new_node) global_state.environment.active_function_name = 'fallback' new_node.states.append(global_state) evm.work_list.append(global_state) evm.exec() logging.info("Execution complete") logging.info("Achieved {0:.3g}% coverage".format(evm.coverage))
def _setup_global_state_for_execution(laser_evm, transaction) -> None: """Sets up global state and cfg for a transactions execution. :param laser_evm: :param transaction: """ # TODO: Resolve circular import between .transaction and ..svm to import LaserEVM here global_state = transaction.initial_global_state() global_state.transaction_stack.append((transaction, None)) new_node = Node( global_state.environment.active_account.contract_name, function_name=global_state.environment.active_function_name, ) if laser_evm.requires_statespace: laser_evm.nodes[new_node.uid] = new_node if transaction.world_state.node: if laser_evm.requires_statespace: laser_evm.edges.append( Edge( transaction.world_state.node.uid, new_node.uid, edge_type=JumpType.Transaction, condition=None, )) global_state.mstate.constraints += transaction.world_state.node.constraints new_node.constraints = global_state.mstate.constraints.as_list global_state.world_state.transaction_sequence.append(transaction) global_state.node = new_node new_node.states.append(global_state) laser_evm.work_list.append(global_state)
def _new_node_state(self, state, edge_type=JumpType.UNCONDITIONAL, condition=None): new_node = Node(state.environment.active_account.contract_name) old_node = state.node state.node = new_node new_node.constraints = state.mstate.constraints 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 address in state.environment.code.addr_to_func: # Enter a new function environment.active_function_name = disassembly.addr_to_func[address] new_node.flags |= NodeFlags.FUNC_ENTRY logging.info( "- 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
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
def _setup_global_state_for_execution(laser_evm, transaction): """ Sets up global state and cfg for a transactions execution""" global_state = transaction.initial_global_state() global_state.transaction_stack.append((transaction, None)) new_node = Node(global_state.environment.active_account.contract_name) laser_evm.nodes[new_node.uid] = new_node if transaction.world_state.node: laser_evm.edges.append(Edge(transaction.world_state.node.uid, new_node.uid, edge_type=JumpType.Transaction, condition=None)) global_state.node = new_node new_node.states.append(global_state) laser_evm.work_list.append(global_state)
def execute_message_call(self, callee_address): caller = BitVec("caller", 256) gas_price = BitVec("gasprice", 256) call_value = BitVec("callvalue", 256) origin = BitVec("origin", 256) open_states = self.open_states[:] del self.open_states[:] for open_world_state in open_states: transaction = MessageCallTransaction( open_world_state, open_world_state[callee_address], caller, [], gas_price, call_value, origin, CalldataType.SYMBOLIC, ) global_state = transaction.initial_global_state() global_state.transaction_stack.append((transaction, None)) new_node = Node( global_state.environment.active_account.contract_name) self.instructions_covered = [ False for _ in global_state.environment.code.instruction_list ] self.nodes[new_node.uid] = new_node if open_world_state.node: self.edges.append( Edge(open_world_state.node.uid, new_node.uid, edge_type=JumpType.Transaction, condition=None)) global_state.node = new_node new_node.states.append(global_state) self.work_list.append(global_state) self.exec() logging.info("Execution complete") logging.info("Achieved {0:.3g}% coverage".format(self.coverage))
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
def _setup_global_state_for_execution(laser_evm, transaction) -> None: """ Sets up global state and cfg for a transactions execution""" # TODO: Resolve circular import between .transaction and ..svm to import LaserEVM here global_state = transaction.initial_global_state() global_state.transaction_stack.append((transaction, None)) new_node = Node(global_state.environment.active_account.contract_name) laser_evm.nodes[new_node.uid] = new_node if transaction.world_state.node: laser_evm.edges.append( Edge( transaction.world_state.node.uid, new_node.uid, edge_type=JumpType.Transaction, condition=None, )) global_state.node = new_node new_node.states.append(global_state) laser_evm.work_list.append(global_state)