def mload(computation: ComputationAPI) -> None: start_position = computation.stack_pop1_int() computation.extend_memory(start_position, 32) value = computation.memory_read_bytes(start_position, 32) computation.stack_push_bytes(value)
def revert(computation: ComputationAPI) -> None: start_position, size = computation.stack_pop_ints(2) computation.extend_memory(start_position, size) computation.output = computation.memory_read_bytes(start_position, size) raise Revert(computation.output)
def return_op(computation: ComputationAPI) -> None: start_position, size = computation.stack_pop_ints(2) computation.extend_memory(start_position, size) computation.output = computation.memory_read_bytes(start_position, size) raise Halt('RETURN')
def log_XX(computation: ComputationAPI, topic_count: int) -> None: if topic_count < 0 or topic_count > 4: raise TypeError("Invalid log topic size. Must be 0, 1, 2, 3, or 4") mem_start_position, size = computation.stack_pop_ints(2) if not topic_count: topics: Tuple[int, ...] = () elif topic_count > 1: topics = computation.stack_pop_ints(topic_count) else: topics = (computation.stack_pop1_int(), ) data_gas_cost = constants.GAS_LOGDATA * size topic_gas_cost = constants.GAS_LOGTOPIC * topic_count total_gas_cost = data_gas_cost + topic_gas_cost computation.consume_gas( total_gas_cost, reason="Log topic and data gas cost", ) computation.extend_memory(mem_start_position, size) log_data = computation.memory_read_bytes(mem_start_position, size) computation.add_log_entry( account=computation.msg.storage_address, topics=topics, data=log_data, )
def sha3(computation: ComputationAPI) -> None: start_position, size = computation.stack_pop_ints(2) computation.extend_memory(start_position, size) sha3_bytes = computation.memory_read_bytes(start_position, size) word_count = ceil32(len(sha3_bytes)) // 32 gas_cost = constants.GAS_SHA3WORD * word_count computation.consume_gas(gas_cost, reason="SHA3: word gas cost") result = keccak(sha3_bytes) computation.stack_push_bytes(result)
def __call__(self, computation: ComputationAPI) -> None: stack_data = self.get_stack_data(computation) gas_cost = self.get_gas_cost(stack_data) computation.consume_gas(gas_cost, reason=self.mnemonic) computation.extend_memory(stack_data.memory_start, stack_data.memory_length) insufficient_funds = computation.state.get_balance( computation.msg.storage_address ) < stack_data.endowment stack_too_deep = computation.msg.depth + 1 > constants.STACK_DEPTH_LIMIT if insufficient_funds or stack_too_deep: computation.stack_push_int(0) return call_data = computation.memory_read_bytes( stack_data.memory_start, stack_data.memory_length ) create_msg_gas = self.max_child_gas_modifier( computation.get_gas_remaining() ) computation.consume_gas(create_msg_gas, reason=self.mnemonic) contract_address = self.generate_contract_address(stack_data, call_data, computation) is_collision = computation.state.has_code_or_nonce(contract_address) if is_collision: self.logger.debug2( "Address collision while creating contract: %s", encode_hex(contract_address), ) computation.stack_push_int(0) return child_msg = computation.prepare_child_message( gas=create_msg_gas, to=constants.CREATE_CONTRACT_ADDRESS, value=stack_data.endowment, data=b'', code=call_data, create_address=contract_address, ) self.apply_create_message(computation, child_msg)