def sstore_eip2200(computation: BaseComputation) -> None: gas_remaining = computation.get_gas_remaining() if gas_remaining <= 2300: raise OutOfGas( "Net-metered SSTORE always fails below 2300 gas, per EIP-2200", gas_remaining, ) else: return net_sstore(GAS_SCHEDULE_EIP2200, computation)
def compute_eip150_msg_gas(*, computation: ComputationAPI, gas: int, extra_gas: int, value: int, mnemonic: str, callstipend: int) -> Tuple[int, int]: if computation.get_gas_remaining() < extra_gas: # It feels wrong to raise an OutOfGas exception outside of GasMeter, # but I don't see an easy way around it. raise OutOfGas(f"Out of gas: Needed {extra_gas}" f" - Remaining {computation.get_gas_remaining()}" f" - Reason: {mnemonic}") gas = min( gas, max_child_gas_eip150(computation.get_gas_remaining() - extra_gas)) total_fee = gas + extra_gas child_msg_gas = gas + (callstipend if value else 0) return child_msg_gas, total_fee
def apply_create_message(self): snapshot = self.state.snapshot() # EIP161 nonce incrementation self.state.account_db.increment_nonce(self.msg.storage_address) computation = self.apply_message() if computation.is_error: self.state.revert(snapshot) return computation else: contract_code = computation.output if contract_code and len(contract_code) >= EIP170_CODE_SIZE_LIMIT: computation._error = OutOfGas( "Contract code size exceeds EIP170 limit of {0}. Got code of " "size: {1}".format( EIP170_CODE_SIZE_LIMIT, len(contract_code), )) self.state.revert(snapshot) elif contract_code: contract_code_gas_cost = len( contract_code) * constants.GAS_CODEDEPOSIT try: computation.consume_gas( contract_code_gas_cost, reason="Write contract code for CREATE", ) except OutOfGas as err: # Different from Frontier: reverts state on gas failure while # writing contract code. computation._error = err self.state.revert(snapshot) else: if self.logger: self.logger.trace( "SETTING CODE: %s -> length: %s | hash: %s", encode_hex(self.msg.storage_address), len(contract_code), encode_hex(keccak(contract_code))) self.state.account_db.set_code(self.msg.storage_address, contract_code) self.state.commit(snapshot) else: self.state.commit(snapshot) return computation
def apply_create_message( cls, state: StateAPI, message: MessageAPI, transaction_context: TransactionContextAPI) -> ComputationAPI: snapshot = state.snapshot() # EIP161 nonce incrementation state.increment_nonce(message.storage_address) computation = cls.apply_message(state, message, transaction_context) if computation.is_error: state.revert(snapshot) return computation else: contract_code = computation.output if contract_code and len(contract_code) >= EIP170_CODE_SIZE_LIMIT: computation.error = OutOfGas( f"Contract code size exceeds EIP170 limit of {EIP170_CODE_SIZE_LIMIT}." f" Got code of size: {len(contract_code)}") state.revert(snapshot) elif contract_code: contract_code_gas_cost = len( contract_code) * constants.GAS_CODEDEPOSIT try: computation.consume_gas( contract_code_gas_cost, reason="Write contract code for CREATE", ) except OutOfGas as err: # Different from Frontier: reverts state on gas failure while # writing contract code. computation.error = err state.revert(snapshot) else: if cls.logger: cls.logger.debug2( "SETTING CODE: %s -> length: %s | hash: %s", encode_hex(message.storage_address), len(contract_code), encode_hex(keccak(contract_code))) state.set_code(message.storage_address, contract_code) state.commit(snapshot) else: state.commit(snapshot) return computation
def compute_eip150_msg_gas(computation, gas, extra_gas, value, mnemonic, callstipend): if computation.get_gas_remaining() < extra_gas: # It feels wrong to raise an OutOfGas exception outside of GasMeter, # but I don't see an easy way around it. raise OutOfGas( "Out of gas: Needed {0} - Remaining {1} - Reason: {2}".format( extra_gas, computation.get_gas_remaining(), mnemonic, )) gas = min( gas, max_child_gas_eip150(computation.get_gas_remaining() - extra_gas)) total_fee = gas + extra_gas child_msg_gas = gas + (callstipend if value else 0) return child_msg_gas, total_fee
def consume_gas(self, amount: int, reason: str) -> None: if amount < 0: raise ValidationError("Gas consumption amount must be positive") if amount > self.gas_remaining: raise OutOfGas(f"Out of gas: Needed {amount} " f"- Remaining {self.gas_remaining} " f"- Reason: {reason}") self.gas_remaining -= amount if self.logger.show_debug2: self.logger.debug2( 'GAS CONSUMPTION: %s - %s -> %s (%s)', self.gas_remaining + amount, amount, self.gas_remaining, reason, )
def consume_gas(self, amount: int, reason: str) -> None: if amount < 0: raise ValidationError("Gas consumption amount must be positive") if amount > self.gas_remaining: raise OutOfGas("Out of gas: Needed {0} - Remaining {1} - Reason: {2}".format( amount, self.gas_remaining, reason, )) self.gas_remaining -= amount self.logger.trace( 'GAS CONSUMPTION: %s - %s -> %s (%s)', self.gas_remaining + amount, amount, self.gas_remaining, reason, )
def validate_contract_code(cls, contract_code: bytes) -> None: if len(contract_code) >= EIP170_CODE_SIZE_LIMIT: raise OutOfGas( f"Contract code size exceeds EIP170 limit of {EIP170_CODE_SIZE_LIMIT}." f" Got code of size: {len(contract_code)}")