Skip to content

Commit

Permalink
fix: issue with kwargs for get_logs using eth-tester (#2006)
Browse files Browse the repository at this point in the history
  • Loading branch information
antazoey authored Apr 16, 2024
1 parent 7529492 commit 6f2172d
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 38 deletions.
12 changes: 6 additions & 6 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,13 +123,13 @@
"eth-typing>=3.5.2,<4",
"eth-utils>=2.3.1,<3",
"py-geth>=4.4.0,<5",
"web3[tester]>=6.16.0,<7",
"web3[tester]>=6.16.0,<6.17.1",
# ** Dependencies maintained by ApeWorX **
"eip712>=0.2.3,<0.4",
"ethpm-types>=0.6.7,<0.7",
"eth_pydantic_types>=0.1.0a5,<0.2",
"evmchains>=0.0.2,<0.1",
"evm-trace>=0.1.2",
"eip712>=0.2.7,<0.3",
"ethpm-types>=0.6.9,<0.7",
"eth_pydantic_types>=0.1.0,<0.2",
"evmchains>=0.0.6,<0.1",
"evm-trace>=0.1.3,<0.2",
],
entry_points={
"console_scripts": ["ape=ape._cli:cli"],
Expand Down
14 changes: 9 additions & 5 deletions src/ape_ethereum/ecosystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -935,14 +935,18 @@ def get_abi(_topic: HexStr) -> Optional[LogInputABICollection]:
converted_arguments[key] = value

yield ContractLog(
block_hash=log["blockHash"],
block_number=log["blockNumber"],
block_hash=log.get("blockHash") or log.get("block_hash") or "",
block_number=log.get("blockNumber") or log.get("block_number") or 0,
contract_address=self.decode_address(log["address"]),
event_arguments=converted_arguments,
event_name=abi.event_name,
log_index=log["logIndex"],
transaction_hash=log["transactionHash"],
transaction_index=log["transactionIndex"],
log_index=log.get("logIndex") or log.get("log_index") or 0,
transaction_hash=log.get("transactionHash") or log.get("transaction_hash") or "",
transaction_index=(
log.get("transactionIndex")
if "transactionIndex" in log
else log.get("transaction_index")
),
)

def enrich_calltree(self, call: CallTreeNode, **kwargs) -> CallTreeNode:
Expand Down
11 changes: 2 additions & 9 deletions src/ape_ethereum/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -863,21 +863,14 @@ def fetch_log_page(block_range):
start, stop = block_range
update = {"start_block": start, "stop_block": stop}
page_filter = log_filter.model_copy(update=update)
# eth-tester expects a different format, let web3 handle the conversions for it.
raw = "EthereumTester" not in self.client_version
logs = self._get_logs(page_filter.model_dump(mode="json"), raw)
filter_params = page_filter.model_dump(mode="json")
logs = self._make_request("eth_getLogs", [filter_params])
return self.network.ecosystem.decode_logs(logs, *log_filter.events)

with ThreadPoolExecutor(self.concurrency) as pool:
for page in pool.map(fetch_log_page, block_ranges):
yield from page

def _get_logs(self, filter_params, raw=True) -> List[Dict]:
if not raw:
return [vars(d) for d in self.web3.eth.get_logs(filter_params)]

return self._make_request("eth_getLogs", [filter_params])

def prepare_transaction(self, txn: TransactionAPI) -> TransactionAPI:
# NOTE: Use "expected value" for Chain ID, so if it doesn't match actual, we raise
txn.chain_id = self.network.chain_id
Expand Down
25 changes: 23 additions & 2 deletions src/ape_test/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from ast import literal_eval
from functools import cached_property
from re import Pattern
from typing import Any, Dict, Optional, cast
from typing import Any, Dict, Iterator, Optional, cast

from eth.exceptions import HeaderNotFound
from eth_pydantic_types import HexBytes
Expand All @@ -25,7 +25,7 @@
UnknownSnapshotError,
VirtualMachineError,
)
from ape.types import BlockID, SnapshotID
from ape.types import BlockID, ContractLog, LogFilter, SnapshotID
from ape.utils import DEFAULT_TEST_CHAIN_ID, DEFAULT_TEST_HD_PATH, gas_estimation_error_message
from ape_ethereum.provider import Web3Provider

Expand Down Expand Up @@ -268,6 +268,27 @@ def set_timestamp(self, new_timestamp: int):
def mine(self, num_blocks: int = 1):
self.evm_backend.mine_blocks(num_blocks)

def get_contract_logs(self, log_filter: LogFilter) -> Iterator[ContractLog]:
from_block = max(0, log_filter.start_block)

if log_filter.stop_block is None:
to_block = None
else:
latest_block = self.get_block("latest").number
to_block = (
min(latest_block, log_filter.stop_block)
if latest_block is not None
else log_filter.stop_block
)

log_gen = self.tester.ethereum_tester.get_logs(
address=log_filter.addresses,
from_block=from_block,
to_block=to_block,
topics=log_filter.topic_filter,
)
yield from self.network.ecosystem.decode_logs(log_gen, *log_filter.events)

def get_virtual_machine_error(self, exception: Exception, **kwargs) -> VirtualMachineError:
if isinstance(exception, ValidationError):
match = self._CANNOT_AFFORD_GAS_PATTERN.match(str(exception))
Expand Down
4 changes: 2 additions & 2 deletions tests/functional/test_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def test_block_dict(block):
"num_transactions": 0,
"number": 0,
"parentHash": block.parent_hash.hex(),
"size": 548,
"size": block.size,
"timestamp": block.timestamp,
"totalDifficulty": 0,
"transactions": [],
Expand All @@ -32,7 +32,7 @@ def test_block_json(block):
f'"hash":"{block.hash.hex()}",'
'"num_transactions":0,"number":0,'
f'"parentHash":"{block.parent_hash.hex()}",'
f'"size":548,"timestamp":{block.timestamp},'
f'"size":{block.size},"timestamp":{block.timestamp},'
f'"totalDifficulty":0,"transactions":[]}}'
)
assert actual == expected
27 changes: 13 additions & 14 deletions tests/functional/test_contract_event.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import pytest
from eth_pydantic_types import HexBytes
from eth_utils import to_hex
from ethpm_types import ContractType

from ape.api import ReceiptAPI
Expand Down Expand Up @@ -124,7 +123,7 @@ def test_contract_logs_range(chain, contract_instance, owner, assert_log_values)
def test_contract_logs_range_by_address(
mocker, chain, eth_tester_provider, test_accounts, contract_instance, owner, assert_log_values
):
get_logs_spy = mocker.spy(eth_tester_provider.web3.eth, "get_logs")
get_logs_spy = mocker.spy(eth_tester_provider.tester.ethereum_tester, "get_logs")
contract_instance.setAddress(test_accounts[1], sender=owner)
height = chain.blocks.height
logs = [
Expand All @@ -137,18 +136,18 @@ def test_contract_logs_range_by_address(
# NOTE: This spy assertion tests against a bug where address queries were not
# 0x-prefixed. However, this was still valid in EthTester and thus was not causing
# test failures.
height_arg = to_hex(chain.blocks.height)
get_logs_spy.assert_called_once_with(
{
"address": [contract_instance.address],
"fromBlock": height_arg,
"toBlock": height_arg,
"topics": [
"0x7ff7bacc6cd661809ed1ddce28d4ad2c5b37779b61b9e3235f8262be529101a9",
"0x00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8",
],
}
)
height_arg = chain.blocks.height
actual = get_logs_spy.call_args[-1]
expected = {
"address": [contract_instance.address],
"from_block": height_arg,
"to_block": height_arg,
"topics": [
"0x7ff7bacc6cd661809ed1ddce28d4ad2c5b37779b61b9e3235f8262be529101a9",
"0x00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8",
],
}
assert actual == expected
assert logs == [contract_instance.AddressChange(newAddress=test_accounts[1])]


Expand Down

0 comments on commit 6f2172d

Please sign in to comment.