def delegatecall_(self, global_state): instr = global_state.get_current_instruction() environment = global_state.environment try: callee_address, callee_account, call_data, _, call_data_type, gas, _, _ = get_call_parameters(global_state, self.dynamic_loader) except ValueError as e: logging.info( "Could not determine required parameters for call, putting fresh symbol on the stack. \n{}".format(e) ) global_state.mstate.stack.append(BitVec("retval_" + str(instr['address']), 256)) return [global_state] transaction = MessageCallTransaction(global_state.world_state, environment.active_account, environment.sender, call_data, environment.gasprice, environment.callvalue, environment.origin, call_data_type, callee_account.code ) raise TransactionStartSignal(transaction, self.op_code)
def call_(self, global_state): instr = global_state.get_current_instruction() environment = global_state.environment try: callee_address, callee_account, call_data, value, call_data_type, gas, memory_out_offset, memory_out_size = get_call_parameters( global_state, self.dynamic_loader, True) except ValueError as e: logging.info( "Could not determine required parameters for call, putting fresh symbol on the stack. \n{}".format(e) ) # TODO: decide what to do in this case global_state.mstate.stack.append(global_state.new_bitvec("retval_" + str(instr['address']), 256)) return [global_state] global_state.mstate.stack.append(global_state.new_bitvec("retval_" + str(instr['address']), 256)) if 0 < int(callee_address, 16) < 5: logging.info("Native contract called: " + callee_address) if call_data == [] and call_data_type == CalldataType.SYMBOLIC: logging.debug("CALL with symbolic data not supported") return [global_state] try: mem_out_start = helper.get_concrete_int(memory_out_offset) mem_out_sz = memory_out_size.as_long() except AttributeError: logging.debug("CALL with symbolic start or offset not supported") return [global_state] global_state.mstate.mem_extend(mem_out_start, mem_out_sz) call_address_int = int(callee_address, 16) try: data = natives.native_contracts(call_address_int, call_data) except natives.NativeContractException: contract_list = ['ecerecover', 'sha256', 'ripemd160', 'identity'] 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) + ")", 256) 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] # TODO: maybe use BitVec here constrained to 1 return [global_state] transaction = MessageCallTransaction(global_state.world_state, callee_account, BitVecVal(int(environment.active_account.address, 16), 256), call_data=call_data, gas_price=environment.gasprice, call_value=value, origin=environment.origin, call_data_type=call_data_type) raise TransactionStartSignal(transaction, self.op_code)
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_calldata_constraints_in_transaction(): # Arrange laser_evm = LaserEVM({}) world_state = WorldState() correct_constraints = [MagicMock(), MagicMock(), MagicMock()] transaction = MessageCallTransaction(world_state, Account("ca11ee"), Account("ca114")) transaction.call_data = MagicMock() transaction.call_data.constraints = correct_constraints # Act _setup_global_state_for_execution(laser_evm, transaction) # Assert state = laser_evm.work_list[0] for constraint in correct_constraints: assert constraint in state.environment.calldata.constraints