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 apply_create_message(self, computation: ComputationAPI, child_msg: MessageAPI) -> None: child_computation = computation.apply_child_computation(child_msg) if child_computation.is_error: computation.stack_push_int(0) else: computation.stack_push_bytes(child_msg.storage_address) computation.return_gas(child_computation.get_gas_remaining())
def calldataload(computation: ComputationAPI) -> None: """ Load call data into memory. """ start_position = computation.stack_pop1_int() value = computation.msg.data_as_bytes[start_position:start_position + 32] padded_value = value.ljust(32, b'\x00') normalized_value = padded_value.lstrip(b'\x00') computation.stack_push_bytes(normalized_value)
def extcodehash(computation: ComputationAPI) -> None: """ Return the code hash for a given address. EIP: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1052.md """ account = force_bytes_to_address(computation.stack_pop1_bytes()) state = computation.state if state.account_is_empty(account): computation.stack_push_bytes(constants.NULL_BYTE) else: computation.stack_push_bytes(state.get_code_hash(account))
def push_XX(computation: ComputationAPI, size: int) -> None: raw_value = computation.code.read(size) # This is a performance-sensitive area. # Calling raw_value.ljust() when size == len(raw_value) is more expensive than # calling len(raw_value) and raw_len is typically the correct size already, # so this saves a bit of time: raw_len = len(raw_value) if raw_len == size: computation.stack_push_bytes(raw_value) else: padded_value = raw_value.ljust(size, b'\x00') computation.stack_push_bytes(padded_value)
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 apply_create_message(self, computation: ComputationAPI, child_msg: MessageAPI) -> None: # We need to ensure that creation operates on empty storage **and** # that if the initialization code fails that we revert the account back # to its original state root. snapshot = computation.state.snapshot() computation.state.delete_storage(child_msg.storage_address) child_computation = computation.apply_child_computation(child_msg) if child_computation.is_error: computation.state.revert(snapshot) computation.stack_push_int(0) else: computation.state.commit(snapshot) computation.stack_push_bytes(child_msg.storage_address) computation.return_gas(child_computation.get_gas_remaining())
def blockhash(computation: ComputationAPI) -> None: block_number = computation.stack_pop1_int() block_hash = computation.state.get_ancestor_hash(block_number) computation.stack_push_bytes(block_hash)
def coinbase(computation: ComputationAPI) -> None: computation.stack_push_bytes(computation.state.coinbase)
def calldataloadfunction(computation: ComputationAPI) -> None: value = computation.msg.data_as_bytes[0:4] padded_value = value.rjust(32, b'\x00') normalized_value = padded_value.rstrip(b'\x00') computation.stack_push_bytes(normalized_value)
def caller(computation: ComputationAPI) -> None: computation.stack_push_bytes(computation.msg.sender)
def address(computation: ComputationAPI) -> None: computation.stack_push_bytes(computation.msg.storage_address)
def origin(computation: ComputationAPI) -> None: computation.stack_push_bytes(computation.transaction_context.origin)