Skip to content

Commit 437b45c

Browse files
committed
Add support for nested tuples to event filters and logs
- 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. - Tweaks to some of the new tests added in the previous commit so that they are tested appropriately and pass
1 parent b47e2a5 commit 437b45c

File tree

11 files changed

+366
-189
lines changed

11 files changed

+366
-189
lines changed

tests/core/contracts/conftest.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -943,7 +943,6 @@ class LogFunctions:
943943
LogTripleWithIndex = 10
944944
LogQuadrupleWithIndex = 11
945945
LogBytes = 12
946-
LogStructArgs = 13
947946

948947

949948
@pytest.fixture()

tests/core/contracts/contract_sources/Emitter.sol

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
pragma solidity ^0.8.7;
1+
pragma solidity ^0.8.11;
22

33

44
contract Emitter {
@@ -11,7 +11,6 @@ contract Emitter {
1111
event LogString(string v);
1212
event LogBytes(bytes v);
1313

14-
// Indexed
1514
event LogSingleWithIndex(uint indexed arg0);
1615
event LogSingleAnonymous(uint indexed arg0) anonymous;
1716
event LogDoubleWithIndex(uint arg0, uint indexed arg1);
@@ -23,10 +22,13 @@ contract Emitter {
2322
event LogAddressIndexed(address indexed arg0, address arg1);
2423
event LogAddressNotIndexed(address arg0, address arg1);
2524

26-
// Nested type functionality
25+
struct NestedTestTuple {
26+
uint c;
27+
}
2728
struct TestTuple {
2829
uint a;
2930
uint b;
31+
NestedTestTuple nested;
3032
}
3133
event LogStructArgs(uint arg0, TestTuple arg1);
3234

tests/core/contracts/test_extracting_event_data.py

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def Emitter(web3, EMITTER):
3131
@pytest.fixture()
3232
def emitter(web3, Emitter, wait_for_transaction, wait_for_block, address_conversion_func):
3333
wait_for_block(web3)
34-
deploy_txn_hash = Emitter.constructor().transact({'from': web3.eth.coinbase, 'gas': 1000000})
34+
deploy_txn_hash = Emitter.constructor().transact({'from': web3.eth.coinbase, 'gas': 10000000})
3535
deploy_receipt = web3.eth.wait_for_transaction_receipt(deploy_txn_hash)
3636
contract_address = address_conversion_func(deploy_receipt['contractAddress'])
3737

@@ -566,17 +566,17 @@ def test_argument_extraction_strict_bytes_types(w3_strict_abi,
566566
),
567567
(
568568
'logStruct',
569-
'logStructArgs',
570-
[12345, {'a': 0, 'b': 1}],
571-
{'arg0': 12345, 'arg1': {'a': 0, 'b': 1}},
569+
'LogStructArgs',
570+
[1, (2, 3, (4,))],
571+
{'arg0': 1, 'arg1': (2, 3, (4,))},
572572
'The event signature did not match the provided ABI',
573573
True,
574574
),
575575
(
576576
'logStruct',
577-
'logStructArgs',
578-
[12345, {'a': 0, 'b': 1}],
579-
{'arg0': 12345, 'arg1': {'a': 0, 'b': 1}},
577+
'LogStructArgs',
578+
[1, (2, 3, (4,))],
579+
{'arg0': 1, 'arg1': (2, 3, (4,))},
580580
'The event signature did not match the provided ABI',
581581
False,
582582
),
@@ -595,8 +595,13 @@ def test_event_rich_log(
595595
expected_args):
596596

597597
emitter_fn = emitter.functions[contract_fn]
598-
event_id = getattr(emitter_event_ids, event_name)
599-
txn_hash = emitter_fn(event_id, *call_args).transact()
598+
try:
599+
event_id = getattr(emitter_event_ids, event_name)
600+
txn_hash = emitter_fn(event_id, *call_args).transact()
601+
except AttributeError:
602+
# Some tests do not rely on the event_id. Rather than changing this test too much,
603+
# bypass this here and just call the function with the provided args.
604+
txn_hash = emitter_fn(*call_args).transact()
600605
txn_receipt = wait_for_transaction(web3, txn_hash)
601606

602607
event_instance = emitter.events[event_name]()
@@ -759,3 +764,14 @@ def test_single_log_processing_with_errors(
759764

760765
with pytest.raises(LogTopicError, match="Expected 1 log topics. Got 0"):
761766
event_instance.processLog(dup_txn_receipt['logs'][0])
767+
768+
769+
def test_event_with_nested_tuple_types(web3, emitter):
770+
struct_args_filter = emitter.events.LogStructArgs.createFilter(fromBlock=0)
771+
772+
tx_hash = emitter.functions.logStruct(1, (2, 3, (4, ))).transact({'gas': 100000})
773+
web3.eth.wait_for_transaction_receipt(tx_hash)
774+
775+
entries = struct_args_filter.get_all_entries()
776+
777+
assert entries != []

tests/core/contracts/test_extracting_event_data_old.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def Emitter(web3, EMITTER):
1717
@pytest.fixture()
1818
def emitter(web3, Emitter, wait_for_transaction, wait_for_block, address_conversion_func):
1919
wait_for_block(web3)
20-
deploy_txn_hash = Emitter.constructor().transact({'from': web3.eth.coinbase, 'gas': 1000000})
20+
deploy_txn_hash = Emitter.constructor().transact({'from': web3.eth.coinbase, 'gas': 10000000})
2121
deploy_receipt = web3.eth.wait_for_transaction_receipt(deploy_txn_hash)
2222
contract_address = address_conversion_func(deploy_receipt['contractAddress'])
2323

tests/core/filtering/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ def emitter(web3, Emitter, wait_for_transaction, wait_for_block, address_convers
7575
wait_for_block(web3)
7676
deploy_txn_hash = Emitter.constructor().transact({
7777
'from': web3.eth.coinbase,
78-
'gas': 1000000,
78+
'gas': 10000000,
7979
'maxFeePerGas': 10 ** 9,
8080
'maxPriorityFeePerGas': 10 ** 9,
8181
})

tests/core/filtering/test_contract_data_filters.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ def emitter(web3, Emitter, wait_for_transaction, wait_for_block, address_convers
6969
wait_for_block(web3)
7070
deploy_txn_hash = Emitter.constructor().transact({
7171
'from': web3.eth.coinbase,
72-
'gas': 1000000,
72+
'gas': 10000000,
7373
'maxFeePerGas': 10 ** 9,
7474
'maxPriorityFeePerGas': 10 ** 9,
7575
})

tests/core/filtering/test_contract_getLogs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ def test_contract_get_available_events(
66
"""We can iterate over available contract events"""
77
contract = emitter
88
events = list(contract.events)
9-
assert len(events) == 18
9+
assert len(events) == 19
1010

1111

1212
def test_contract_getLogs_all(

tests/core/filtering/test_contract_topic_filters.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ def emitter(web3, Emitter, wait_for_transaction, wait_for_block, address_convers
7474
wait_for_block(web3)
7575
deploy_txn_hash = Emitter.constructor().transact({
7676
'from': web3.eth.coinbase,
77-
'gas': 1000000,
77+
'gas': 10000000,
7878
'maxFeePerGas': 10 ** 9,
7979
'maxPriorityFeePerGas': 10 ** 9,
8080
})

web3/_utils/events.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@
3939
to_hex,
4040
to_tuple,
4141
)
42-
from eth_utils.abi import collapse_if_tuple
42+
from eth_utils.abi import (
43+
collapse_if_tuple,
44+
)
4345
from eth_utils.curried import (
4446
apply_formatter_if,
4547
)
@@ -194,7 +196,7 @@ def get_event_abi_types_for_decoding(event_inputs: Sequence[ABIEventParams]) ->
194196
if input_abi['indexed'] and is_dynamic_sized_type(input_abi['type']):
195197
yield 'bytes32'
196198
else:
197-
yield collapse_if_tuple(input_abi)
199+
yield collapse_if_tuple(dict(input_abi))
198200

199201

200202
@curry
@@ -431,9 +433,9 @@ def _build_argument_filters_from_event_abi(
431433
key = item['name']
432434
value: 'BaseArgumentFilter'
433435
if item['indexed'] is True:
434-
value = TopicArgumentFilter(abi_codec=abi_codec, arg_type=item['type'])
436+
value = TopicArgumentFilter(abi_codec=abi_codec, arg_type=collapse_if_tuple(dict(item)))
435437
else:
436-
value = DataArgumentFilter(arg_type=item['type'])
438+
value = DataArgumentFilter(arg_type=collapse_if_tuple(dict(item)))
437439
yield key, value
438440

439441

@@ -479,7 +481,7 @@ class DataArgumentFilter(BaseArgumentFilter):
479481
# type ignore b/c conflict with BaseArgumentFilter.match_values type
480482
@property
481483
def match_values(self) -> Tuple[TypeStr, Tuple[Any, ...]]: # type: ignore
482-
return (self.arg_type, self._match_values)
484+
return self.arg_type, self._match_values
483485

484486

485487
class TopicArgumentFilter(BaseArgumentFilter):

web3/_utils/filters.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ class TransactionFilter(Filter):
186186
class LogFilter(Filter):
187187
data_filter_set = None
188188
data_filter_set_regex = None
189+
data_filter_set_function = None
189190
log_entry_formatter = None
190191
filter_params: FilterParams = None
191192
builder: EventFilterBuilder = None

0 commit comments

Comments
 (0)