diff --git a/CHANGELOG b/CHANGELOG index db339478..61f5e195 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,7 +1,9 @@ Unreleased ------------- -None +- Features + + - Add support for gas estimate block identifiers v0.4.0-beta.2 ------------- diff --git a/eth_tester/backends/base.py b/eth_tester/backends/base.py index 1ebb0a31..3a0ca03d 100644 --- a/eth_tester/backends/base.py +++ b/eth_tester/backends/base.py @@ -91,7 +91,7 @@ def send_signed_transaction(self, transaction): raise NotImplementedError("Must be implemented by subclasses") @abstractmethod - def estimate_gas(self, transaction): + def estimate_gas(self, transaction, block_number="latest"): raise NotImplementedError("Must be implemented by subclasses") @abstractmethod diff --git a/eth_tester/backends/pyevm/main.py b/eth_tester/backends/pyevm/main.py index fe9a8b87..eee7cf94 100644 --- a/eth_tester/backends/pyevm/main.py +++ b/eth_tester/backends/pyevm/main.py @@ -465,12 +465,26 @@ def _max_available_gas(self): @replace_exceptions({ EVMInvalidInstruction: TransactionFailed, EVMRevert: TransactionFailed}) - def estimate_gas(self, transaction): - evm_transaction = self._get_normalized_and_unsigned_evm_transaction(assoc( - transaction, 'gas', 21000)) + def estimate_gas(self, transaction, block_number="latest"): + evm_transaction = self._get_normalized_and_unsigned_evm_transaction( + assoc(transaction, 'gas', 21000), + block_number + ) spoofed_transaction = EVMSpoofTransaction(evm_transaction, from_=transaction['from']) - return self.chain.estimate_gas(spoofed_transaction) + if block_number == "latest": + return self.chain.estimate_gas(spoofed_transaction) + elif block_number == "earliest": + return self.chain.estimate_gas( + spoofed_transaction, self.chain.get_canonical_block_header_by_number(0) + ) + elif block_number == "pending": + raise NotImplementedError('"pending" block identifier is unsupported in eth-tester') + else: + return self.chain.estimate_gas( + spoofed_transaction, + self.chain.get_canonical_block_header_by_number(block_number), + ) def is_eip838_error(self, error): if not isinstance(error, EVMRevert): diff --git a/eth_tester/main.py b/eth_tester/main.py index 62a6ae31..74907352 100644 --- a/eth_tester/main.py +++ b/eth_tester/main.py @@ -428,10 +428,12 @@ def call(self, transaction, block_number="latest"): result = self.normalizer.normalize_outbound_return_data(raw_result) return result - def estimate_gas(self, transaction): + def estimate_gas(self, transaction, block_number="latest"): self.validator.validate_inbound_transaction(transaction, txn_type='estimate') raw_transaction = self.normalizer.normalize_inbound_transaction(transaction) - raw_gas_estimate = self.backend.estimate_gas(raw_transaction) + self.validator.validate_inbound_block_number(block_number) + raw_block_number = self.normalizer.normalize_inbound_block_number(block_number) + raw_gas_estimate = self.backend.estimate_gas(raw_transaction, raw_block_number) self.validator.validate_outbound_gas_estimate(raw_gas_estimate) gas_estimate = self.normalizer.normalize_outbound_gas_estimate(raw_gas_estimate) return gas_estimate diff --git a/eth_tester/utils/backend_testing.py b/eth_tester/utils/backend_testing.py index fc200457..3c7d7672 100644 --- a/eth_tester/utils/backend_testing.py +++ b/eth_tester/utils/backend_testing.py @@ -686,6 +686,21 @@ def test_estimate_gas(self, eth_tester): # https://github.com/ethereum/py-evm/blob/f0276e684edebd7cd9e84cd04b3229ab9dd958b9/evm/estimators/__init__.py#L11 assert receipt['gas_used'] >= gas_estimation - 21000 + def test_estimate_gas_with_block_identifier(self, eth_tester): + self.skip_if_no_evm_execution() + + math_address = _deploy_math(eth_tester) + estimate_call_math_transaction = _make_call_math_transaction( + eth_tester, math_address, "increment", + ) + latest_gas_estimation = eth_tester.estimate_gas( + estimate_call_math_transaction, "latest" + ) + earliest_gas_estimation = eth_tester.estimate_gas( + estimate_call_math_transaction, "earliest" + ) + assert latest_gas_estimation != earliest_gas_estimation + def test_can_call_after_exception_raised_calling(self, eth_tester): self.skip_if_no_evm_execution()