-
Notifications
You must be signed in to change notification settings - Fork 590
JSON-RPC method eth_getLogs returns empty array when specifying topics only #1511
Description
System info: Ethermint current version, Ubuntu 20.04
Steps to reproduce:
- Start a local node
- Deploy a contract that emits an event on a particular contract call
- Make the contract call to emit the event
- Call the
eth_getLogsmethod specifying the topic/s
Expected behavior: Return the (last) log inside the log array
Actual behavior: Returns empty array
Additional info: For some reason, when trying to capture this behavior on a test, the response is the expected one. Locally, a test case was added in the integration tests at tests/integration_tests/test_filters.py to cover this case:
def test_get_logs_by_topic(cluster):
w3: Web3 = cluster.w3
contract, _ = deploy_contract(w3, CONTRACTS["Greeter"])
topic = Web3.keccak(text="ChangeGreeting(address,string)")
# with tx
tx = contract.functions.setGreeting("world").build_transaction()
receipt = send_transaction(w3, tx)
assert receipt.status == 1
logs = w3.eth.get_logs({"topics": [topic.hex()]})
assert len(logs) == 1
assert logs[0].address == contract.addressThis test passes without any issue. However, when performing the same actions manually, the method returns an empty array.
When a block range is specified along with the topics array on the getLogs call, the response is the expected one.
Edit: Quoting the web3py docs, the method web3.eth.get_logs() uses other JSON-RPC methods under the hood:
This is the equivalent of: creating a new filter, running get_filter_logs(), and then uninstalling the filter. See filter() for details on allowed filter parameters.
This seems to be the reason of the discrepancy between the test result and the manual test response.
Update: The getLogs method under the hood works as a filter with the specified topics and a block range. If the block range is not specified, it defaults to fromBlock: "latest", toBlock: "latest". Then, if we call getLogs within the same block that the transaction happened, we will get a log in the result. However, if we make the same call one or more blocks later, the result will be an empty array. The mentioned test passes because it makes the call within the same block of the transaction.