Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support block id for provider get_code() [APE-1203] #1547

Merged
merged 2 commits into from
Jul 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 32 additions & 12 deletions src/ape/api/providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,12 +200,13 @@ def get_balance(self, address: AddressType) -> int:
"""

@abstractmethod
def get_code(self, address: AddressType) -> ContractCode:
def get_code(self, address: AddressType, **kwargs) -> ContractCode:
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so i made sure, we are allowed to add **kwargs to abstract methods without it breaking the plugins that override and dont yet have it

"""
Get the bytes a contract.

Args:
address (``AddressType``): The address of the contract.
**kwargs: Additional, provider-specific kwargs.

Returns:
:class:`~ape.types.ContractCode`: The contract bytecode.
Expand Down Expand Up @@ -786,8 +787,9 @@ def estimate_gas_cost(self, txn: TransactionAPI, **kwargs) -> int:
The transaction to estimate the gas for.
kwargs:
* ``block_identifier`` (:class:`~ape.types.BlockID`): The block ID
to use when estimating the transaction. Useful for
checking a past estimation cost of a transaction.
to use when estimating the transaction. Useful for checking a
past estimation cost of a transaction. Also, you can alias
``block_id``.
* ``state_overrides`` (Dict): Modify the state of the blockchain
prior to estimation.

Expand All @@ -813,7 +815,7 @@ def estimate_gas_cost(self, txn: TransactionAPI, **kwargs) -> int:
txn_dict.pop("maxPriorityFeePerGas", None)

try:
block_id = kwargs.pop("block_identifier", None)
block_id = kwargs.pop("block_identifier", kwargs.pop("block_id", None))
txn_params = cast(TxParams, txn_dict)
return self.web3.eth.estimate_gas(txn_params, block_identifier=block_id)
except (ValueError, Web3ContractLogicError) as err:
Expand Down Expand Up @@ -892,20 +894,36 @@ def get_nonce(self, address: AddressType, **kwargs) -> int:
address (AddressType): The address of the account.
kwargs:
* ``block_identifier`` (:class:`~ape.types.BlockID`): The block ID
for checking a previous account nonce.
for checking a previous account nonce. Also, you can use alias
``block_id``.

Returns:
int
"""

block_id = kwargs.pop("block_identifier", None)
block_id = kwargs.pop("block_identifier", kwargs.pop("block_id", None))
return self.web3.eth.get_transaction_count(address, block_identifier=block_id)

def get_balance(self, address: AddressType) -> int:
return self.web3.eth.get_balance(address)

def get_code(self, address: AddressType) -> ContractCode:
return self.web3.eth.get_code(address)
def get_code(self, address: AddressType, **kwargs) -> ContractCode:
"""
Get the bytes a contract.

Args:
address (``AddressType``): The address of the contract.
kwargs:
* ``block_identifier`` (:class:`~ape.types.BlockID`): The block ID
for checking a previous account nonce. Also, you can use
alias ``block_id``.

Returns:
:class:`~ape.types.ContractCode`: The contract bytecode.
"""

block_id = kwargs.pop("block_identifier", kwargs.pop("block_id", None))
return self.web3.eth.get_code(address, block_identifier=block_id)

def get_storage_at(self, address: AddressType, slot: int, **kwargs) -> bytes:
"""
Expand All @@ -916,13 +934,14 @@ def get_storage_at(self, address: AddressType, slot: int, **kwargs) -> bytes:
slot (int): Storage slot to read the value of.
kwargs:
* ``block_identifier`` (:class:`~ape.types.BlockID`): The block ID
for checking previous contract storage values.
for checking previous contract storage values. Also, you can use
alias ``block_id``.

Returns:
bytes: The value of the storage slot.
"""

block_id = kwargs.pop("block_identifier", None)
block_id = kwargs.pop("block_identifier", kwargs.pop("block_id", None))
try:
return self.web3.eth.get_storage_at(
address, slot, block_identifier=block_id # type: ignore
Expand All @@ -942,7 +961,8 @@ def send_call(self, txn: TransactionAPI, **kwargs) -> bytes:
txn: :class:`~ape.api.transactions.TransactionAPI`
kwargs:
* ``block_identifier`` (:class:`~ape.types.BlockID`): The block ID
to use to send a call at a historical point of a contract.
to use to send a call at a historical point of a contract. Also,
you can us alias ``block_id``.
checking a past estimation cost of a transaction.
* ``state_overrides`` (Dict): Modify the state of the blockchain
prior to sending the call, for testing purposes.
Expand Down Expand Up @@ -1075,7 +1095,7 @@ def _prepare_call(self, txn: TransactionAPI, **kwargs) -> List:
txn_dict.pop("maxFeePerGas", None)
txn_dict.pop("maxPriorityFeePerGas", None)

block_identifier = kwargs.pop("block_identifier", "latest")
block_identifier = kwargs.pop("block_identifier", kwargs.pop("block_id", "latest"))
if isinstance(block_identifier, int):
block_identifier = to_hex(block_identifier)
arguments = [txn_dict, block_identifier]
Expand Down
7 changes: 7 additions & 0 deletions tests/functional/test_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,3 +237,10 @@ def test_get_virtual_machine_error_panic(eth_tester_provider, mocker):
def test_gas_price(eth_tester_provider):
actual = eth_tester_provider.gas_price
assert isinstance(actual, int)


def test_get_code(eth_tester_provider, vyper_contract_instance):
address = vyper_contract_instance.address
assert eth_tester_provider.get_code(address) == eth_tester_provider.get_code(
address, block_id=1
)
Loading