def sload(computation: ComputationAPI) -> None: slot = computation.stack_pop1_int() value = computation.state.get_storage( address=computation.msg.storage_address, slot=slot, ) computation.stack_push_int(value)
def and_op(computation: ComputationAPI) -> None: """ Bitwise And """ left, right = computation.stack_pop_ints(2) result = left & right computation.stack_push_int(result)
def or_op(computation: ComputationAPI) -> None: """ Bitwise Or """ left, right = computation.stack_pop_ints(2) result = left | right computation.stack_push_int(result)
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 xor(computation: ComputationAPI) -> None: """ Bitwise XOr """ left, right = computation.stack_pop_ints(2) result = left ^ right computation.stack_push_int(result)
def not_op(computation: ComputationAPI) -> None: """ Not """ value = computation.stack_pop1_int() result = constants.UINT_256_MAX - value computation.stack_push_int(result)
def iszero(computation: ComputationAPI) -> None: """ Not """ value = computation.stack_pop1_int() if value == 0: result = 1 else: result = 0 computation.stack_push_int(result)
def eq(computation: ComputationAPI) -> None: """ Equality """ left, right = computation.stack_pop_ints(2) if left == right: result = 1 else: result = 0 computation.stack_push_int(result)
def gt(computation: ComputationAPI) -> None: """ Greater Comparison """ left, right = computation.stack_pop_ints(2) if left > right: result = 1 else: result = 0 computation.stack_push_int(result)
def byte_op(computation: ComputationAPI) -> None: """ Bitwise And """ position, value = computation.stack_pop_ints(2) if position >= 32: result = 0 else: result = (value // pow(256, 31 - position)) % 256 computation.stack_push_int(result)
def sgt(computation: ComputationAPI) -> None: """ Signed Greater Comparison """ left, right = map( unsigned_to_signed, computation.stack_pop_ints(2), ) if left > right: result = 1 else: result = 0 computation.stack_push_int(signed_to_unsigned(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)
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 chain_id(computation: ComputationAPI) -> None: computation.stack_push_int(computation.state.execution_context.chain_id)
def returndatasize(computation: ComputationAPI) -> None: size = len(computation.return_data) computation.stack_push_int(size)
def gaslimit(computation: ComputationAPI) -> None: computation.stack_push_int(computation.state.gas_limit)
def difficulty(computation: ComputationAPI) -> None: computation.stack_push_int(computation.state.difficulty)
def number(computation: ComputationAPI) -> None: computation.stack_push_int(computation.state.block_number)
def timestamp(computation: ComputationAPI) -> None: computation.stack_push_int(computation.state.timestamp)
def codesize(computation: ComputationAPI) -> None: size = len(computation.code) computation.stack_push_int(size)
def callvalue(computation: ComputationAPI) -> None: computation.stack_push_int(computation.msg.value)
def extcodesize(computation: ComputationAPI) -> None: account = force_bytes_to_address(computation.stack_pop1_bytes()) code_size = len(computation.state.get_code(account)) computation.stack_push_int(code_size)
def calldatasize(computation: ComputationAPI) -> None: size = len(computation.msg.data) computation.stack_push_int(size)
def msize(computation: ComputationAPI) -> None: computation.stack_push_int(len(computation._memory))
def _push_balance_of_address(address: Address, computation: ComputationAPI) -> None: # balance = computation.state.get_balance(address) balance = 999999999999999 computation.stack_push_int(balance)
def __call__(self, computation: ComputationAPI) -> None: computation.consume_gas( self.gas_cost, reason=self.mnemonic, ) ( gas, value, to, sender, code_address, memory_input_start_position, memory_input_size, memory_output_start_position, memory_output_size, should_transfer_value, is_static, ) = self.get_call_params(computation) computation.extend_memory(memory_input_start_position, memory_input_size) computation.extend_memory(memory_output_start_position, memory_output_size) call_data = computation.memory_read(memory_input_start_position, memory_input_size) # # Message gas allocation and fees # child_msg_gas, child_msg_gas_fee = self.compute_msg_gas( computation, gas, to, value) computation.consume_gas(child_msg_gas_fee, reason=self.mnemonic) # Pre-call checks sender_balance = computation.state.get_balance( computation.msg.storage_address) insufficient_funds = should_transfer_value and sender_balance < value stack_too_deep = computation.msg.depth + 1 > constants.STACK_DEPTH_LIMIT if insufficient_funds or stack_too_deep: computation.return_data = b'' if insufficient_funds: err_message = f"Insufficient Funds: have: {sender_balance} | need: {value}" elif stack_too_deep: err_message = "Stack Limit Reached" else: raise Exception("Invariant: Unreachable code path") self.logger.debug2( "%s failure: %s", self.mnemonic, err_message, ) computation.return_gas(child_msg_gas) computation.stack_push_int(0) else: if code_address: code = computation.state.get_code(code_address) else: code = computation.state.get_code(to) child_msg_kwargs = { 'gas': child_msg_gas, 'value': value, 'to': to, 'data': call_data, 'code': code, 'code_address': code_address, 'should_transfer_value': should_transfer_value, 'is_static': is_static, } if sender is not None: child_msg_kwargs['sender'] = sender # TODO: after upgrade to py3.6, use a TypedDict and try again child_msg = computation.prepare_child_message( **child_msg_kwargs) # type: ignore child_computation = computation.apply_child_computation(child_msg) if child_computation.is_error: computation.stack_push_int(0) else: computation.stack_push_int(1) if not child_computation.should_erase_return_data: actual_output_size = min(memory_output_size, len(child_computation.output)) computation.memory_write( memory_output_start_position, actual_output_size, child_computation.output[:actual_output_size], ) if child_computation.should_return_gas: computation.return_gas(child_computation.get_gas_remaining())
def gasprice(computation: ComputationAPI) -> None: computation.stack_push_int(computation.transaction_context.gas_price)