Skip to content

Commit

Permalink
Add support for nested tuples to event filters and logs
Browse files Browse the repository at this point in the history
- Nested tuples seemed to be broken when parsing event filters. This commit piggy backs off previous work and uses the collapse_if_tuple() method in the _build_argument_filters_from_even_abi() method. From testing, this seemes to have been a missing piece to get these issues resolved and the added test passing.
  • Loading branch information
fselmo committed Jan 12, 2022
1 parent 1d7a03c commit 87b7159
Show file tree
Hide file tree
Showing 6 changed files with 352 additions and 178 deletions.
8 changes: 5 additions & 3 deletions tests/core/contracts/contract_sources/Emitter.sol
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pragma solidity ^0.8.7;
pragma solidity ^0.8.11;


contract Emitter {
Expand All @@ -11,7 +11,6 @@ contract Emitter {
event LogString(string v);
event LogBytes(bytes v);

// Indexed
event LogSingleWithIndex(uint indexed arg0);
event LogSingleAnonymous(uint indexed arg0) anonymous;
event LogDoubleWithIndex(uint arg0, uint indexed arg1);
Expand All @@ -23,10 +22,13 @@ contract Emitter {
event LogAddressIndexed(address indexed arg0, address arg1);
event LogAddressNotIndexed(address arg0, address arg1);

// Nested type functionality
struct NestedTestTuple {
uint c;
}
struct TestTuple {
uint a;
uint b;
NestedTestTuple nested;
}
event LogStructArgs(uint arg0, TestTuple arg1);

Expand Down
18 changes: 15 additions & 3 deletions tests/core/contracts/test_extracting_event_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,13 @@ def Emitter(web3, EMITTER):
@pytest.fixture()
def emitter(web3, Emitter, wait_for_transaction, wait_for_block, address_conversion_func):
wait_for_block(web3)
deploy_txn_hash = Emitter.constructor().transact({'from': web3.eth.coinbase, 'gas': 1000000})
deploy_txn_hash = Emitter.constructor().transact({'from': web3.eth.coinbase, 'gas': 10000000})
deploy_receipt = web3.eth.wait_for_transaction_receipt(deploy_txn_hash)
contract_address = address_conversion_func(deploy_receipt['contractAddress'])

bytecode = web3.eth.get_code(contract_address)
assert bytecode == Emitter.bytecode_runtime
bytecode_runtime = web3.eth.get_code(contract_address)
assert bytecode_runtime == Emitter.bytecode_runtime

_emitter = Emitter(address=contract_address)
assert _emitter.address == contract_address
return _emitter
Expand Down Expand Up @@ -759,3 +760,14 @@ def test_single_log_processing_with_errors(

with pytest.raises(LogTopicError, match="Expected 1 log topics. Got 0"):
event_instance.processLog(dup_txn_receipt['logs'][0])


def test_event_with_nested_tuple_types(web3, emitter):
struct_args_filter = emitter.events.LogStructArgs.createFilter(fromBlock=0)

tx_hash = emitter.functions.logStruct(1, (2, 3, (4, ))).transact({'gas': 100000})
web3.eth.wait_for_transaction_receipt(tx_hash)

entries = struct_args_filter.get_all_entries()

assert entries != []
2 changes: 1 addition & 1 deletion tests/core/filtering/test_contract_getLogs.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ def test_contract_get_available_events(
"""We can iterate over available contract events"""
contract = emitter
events = list(contract.events)
assert len(events) == 18
assert len(events) == 19


def test_contract_getLogs_all(
Expand Down
12 changes: 7 additions & 5 deletions web3/_utils/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@
to_hex,
to_tuple,
)
from eth_utils.abi import collapse_if_tuple
from eth_utils.abi import (
collapse_if_tuple,
)
from eth_utils.curried import (
apply_formatter_if,
)
Expand Down Expand Up @@ -194,7 +196,7 @@ def get_event_abi_types_for_decoding(event_inputs: Sequence[ABIEventParams]) ->
if input_abi['indexed'] and is_dynamic_sized_type(input_abi['type']):
yield 'bytes32'
else:
yield collapse_if_tuple(input_abi)
yield collapse_if_tuple(dict(input_abi))


@curry
Expand Down Expand Up @@ -431,9 +433,9 @@ def _build_argument_filters_from_event_abi(
key = item['name']
value: 'BaseArgumentFilter'
if item['indexed'] is True:
value = TopicArgumentFilter(abi_codec=abi_codec, arg_type=item['type'])
value = TopicArgumentFilter(abi_codec=abi_codec, arg_type=collapse_if_tuple(dict(item)))
else:
value = DataArgumentFilter(arg_type=item['type'])
value = DataArgumentFilter(arg_type=collapse_if_tuple(dict(item)))
yield key, value


Expand Down Expand Up @@ -479,7 +481,7 @@ class DataArgumentFilter(BaseArgumentFilter):
# type ignore b/c conflict with BaseArgumentFilter.match_values type
@property
def match_values(self) -> Tuple[TypeStr, Tuple[Any, ...]]: # type: ignore
return (self.arg_type, self._match_values)
return self.arg_type, self._match_values


class TopicArgumentFilter(BaseArgumentFilter):
Expand Down
1 change: 1 addition & 0 deletions web3/_utils/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ class TransactionFilter(Filter):
class LogFilter(Filter):
data_filter_set = None
data_filter_set_regex = None
data_filter_set_function = None
log_entry_formatter = None
filter_params: FilterParams = None
builder: EventFilterBuilder = None
Expand Down
Loading

0 comments on commit 87b7159

Please sign in to comment.