web3 7.6.0__py3-none-any.whl → 7.6.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- web3/_utils/contract_sources/contract_data/ambiguous_function_contract.py +42 -0
- web3/_utils/contracts.py +1 -1
- web3/contract/async_contract.py +123 -76
- web3/contract/base_contract.py +70 -40
- web3/contract/contract.py +140 -84
- web3/contract/utils.py +4 -1
- web3/providers/ipc.py +1 -1
- web3/providers/persistent/async_ipc.py +1 -1
- web3/utils/abi.py +39 -56
- web3/utils/address.py +8 -0
- {web3-7.6.0.dist-info → web3-7.6.1.dist-info}/METADATA +7 -7
- {web3-7.6.0.dist-info → web3-7.6.1.dist-info}/RECORD +15 -14
- {web3-7.6.0.dist-info → web3-7.6.1.dist-info}/LICENSE +0 -0
- {web3-7.6.0.dist-info → web3-7.6.1.dist-info}/WHEEL +0 -0
- {web3-7.6.0.dist-info → web3-7.6.1.dist-info}/top_level.txt +0 -0
web3/contract/contract.py
CHANGED
|
@@ -13,14 +13,14 @@ from typing import (
|
|
|
13
13
|
|
|
14
14
|
from eth_typing import (
|
|
15
15
|
ABI,
|
|
16
|
+
ABIFunction,
|
|
16
17
|
ChecksumAddress,
|
|
17
18
|
)
|
|
18
19
|
from eth_utils import (
|
|
19
20
|
abi_to_signature,
|
|
20
21
|
combomethod,
|
|
22
|
+
filter_abi_by_type,
|
|
21
23
|
get_abi_input_names,
|
|
22
|
-
get_abi_input_types,
|
|
23
|
-
get_all_function_abis,
|
|
24
24
|
)
|
|
25
25
|
from eth_utils.toolz import (
|
|
26
26
|
partial,
|
|
@@ -31,8 +31,6 @@ from hexbytes import (
|
|
|
31
31
|
|
|
32
32
|
from web3._utils.abi import (
|
|
33
33
|
fallback_func_abi_exists,
|
|
34
|
-
filter_by_types,
|
|
35
|
-
get_abi_element_signature,
|
|
36
34
|
get_name_from_abi_element_identifier,
|
|
37
35
|
receive_func_abi_exists,
|
|
38
36
|
)
|
|
@@ -90,6 +88,7 @@ from web3.contract.utils import (
|
|
|
90
88
|
from web3.exceptions import (
|
|
91
89
|
ABIEventNotFound,
|
|
92
90
|
ABIFunctionNotFound,
|
|
91
|
+
MismatchedABI,
|
|
93
92
|
NoABIEventsFound,
|
|
94
93
|
NoABIFound,
|
|
95
94
|
NoABIFunctionsFound,
|
|
@@ -105,8 +104,9 @@ from web3.types import (
|
|
|
105
104
|
TxParams,
|
|
106
105
|
)
|
|
107
106
|
from web3.utils.abi import (
|
|
107
|
+
_filter_by_argument_count,
|
|
108
108
|
_get_any_abi_signature_with_name,
|
|
109
|
-
|
|
109
|
+
_mismatched_abi_error_diagnosis,
|
|
110
110
|
get_abi_element,
|
|
111
111
|
)
|
|
112
112
|
|
|
@@ -120,26 +120,7 @@ class ContractEvent(BaseContractEvent):
|
|
|
120
120
|
w3: "Web3"
|
|
121
121
|
|
|
122
122
|
def __call__(self, *args: Any, **kwargs: Any) -> "ContractEvent":
|
|
123
|
-
|
|
124
|
-
filter_abi_by_type("event", self.contract_abi),
|
|
125
|
-
self.name,
|
|
126
|
-
*args,
|
|
127
|
-
abi_codec=self.w3.codec,
|
|
128
|
-
**kwargs,
|
|
129
|
-
)
|
|
130
|
-
argument_types = get_abi_input_types(event_abi)
|
|
131
|
-
event_signature = str(
|
|
132
|
-
get_abi_element_signature(self.abi_element_identifier, argument_types)
|
|
133
|
-
)
|
|
134
|
-
contract_event = ContractEvent.factory(
|
|
135
|
-
event_signature,
|
|
136
|
-
w3=self.w3,
|
|
137
|
-
contract_abi=self.contract_abi,
|
|
138
|
-
address=self.address,
|
|
139
|
-
abi_element_identifier=event_signature,
|
|
140
|
-
)
|
|
141
|
-
|
|
142
|
-
return copy_contract_event(contract_event, *args, **kwargs)
|
|
123
|
+
return copy_contract_event(self, *args, **kwargs)
|
|
143
124
|
|
|
144
125
|
@combomethod
|
|
145
126
|
def get_logs(
|
|
@@ -290,7 +271,7 @@ class ContractEvents(BaseContractEvents):
|
|
|
290
271
|
raise NoABIFound(
|
|
291
272
|
"There is no ABI found for this contract.",
|
|
292
273
|
)
|
|
293
|
-
|
|
274
|
+
elif "_events" not in self.__dict__ or len(self._events) == 0:
|
|
294
275
|
raise NoABIEventsFound(
|
|
295
276
|
"The abi for this contract contains no event definitions. ",
|
|
296
277
|
"Are you sure you provided the correct contract abi?",
|
|
@@ -303,18 +284,23 @@ class ContractEvents(BaseContractEvents):
|
|
|
303
284
|
f"The event '{event_name}' was not found in this contract's abi. ",
|
|
304
285
|
"Are you sure you provided the correct contract abi?",
|
|
305
286
|
)
|
|
287
|
+
|
|
288
|
+
if "(" not in event_name:
|
|
289
|
+
event_name = _get_any_abi_signature_with_name(event_name, self._events)
|
|
306
290
|
else:
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
return super().__getattribute__(event_signature)
|
|
291
|
+
event_name = f"_{event_name}"
|
|
292
|
+
|
|
293
|
+
return super().__getattribute__(event_name)
|
|
311
294
|
|
|
312
295
|
def __getitem__(self, event_name: str) -> "ContractEvent":
|
|
313
296
|
return getattr(self, event_name)
|
|
314
297
|
|
|
315
298
|
def __iter__(self) -> Iterable["ContractEvent"]:
|
|
299
|
+
if not hasattr(self, "_events") or not self._events:
|
|
300
|
+
return
|
|
301
|
+
|
|
316
302
|
for event in self._events:
|
|
317
|
-
yield self[event
|
|
303
|
+
yield self[abi_to_signature(event)]
|
|
318
304
|
|
|
319
305
|
|
|
320
306
|
class ContractFunction(BaseContractFunction):
|
|
@@ -322,39 +308,103 @@ class ContractFunction(BaseContractFunction):
|
|
|
322
308
|
w3: "Web3"
|
|
323
309
|
|
|
324
310
|
def __call__(self, *args: Any, **kwargs: Any) -> "ContractFunction":
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
311
|
+
# When a function is called, check arguments to obtain the correct function
|
|
312
|
+
# in the contract. self will be used if all args and kwargs are
|
|
313
|
+
# encodable to self.abi, otherwise the correct function is obtained from
|
|
314
|
+
# the contract.
|
|
315
|
+
if (
|
|
316
|
+
self.abi_element_identifier in [FallbackFn, ReceiveFn]
|
|
317
|
+
or self.abi_element_identifier == "constructor"
|
|
318
|
+
):
|
|
319
|
+
return copy_contract_function(self, *args, **kwargs)
|
|
320
|
+
|
|
321
|
+
all_functions = cast(
|
|
322
|
+
List[ABIFunction],
|
|
323
|
+
filter_abi_by_type(
|
|
324
|
+
"function",
|
|
334
325
|
self.contract_abi,
|
|
335
326
|
),
|
|
336
|
-
element_name,
|
|
337
|
-
*args,
|
|
338
|
-
abi_codec=self.w3.codec,
|
|
339
|
-
**kwargs,
|
|
340
327
|
)
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
argument_types = get_abi_input_types(function_abi)
|
|
345
|
-
|
|
346
|
-
function_signature = str(
|
|
347
|
-
get_abi_element_signature(self.abi_element_identifier, argument_types)
|
|
328
|
+
# Filter functions by name to obtain function signatures
|
|
329
|
+
function_name = get_name_from_abi_element_identifier(
|
|
330
|
+
self.abi_element_identifier
|
|
348
331
|
)
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
332
|
+
function_abis = [
|
|
333
|
+
function for function in all_functions if function["name"] == function_name
|
|
334
|
+
]
|
|
335
|
+
num_args = len(args) + len(kwargs)
|
|
336
|
+
function_abis_with_arg_count = cast(
|
|
337
|
+
List[ABIFunction],
|
|
338
|
+
_filter_by_argument_count(
|
|
339
|
+
num_args,
|
|
340
|
+
function_abis,
|
|
341
|
+
),
|
|
356
342
|
)
|
|
357
343
|
|
|
344
|
+
if not len(function_abis_with_arg_count):
|
|
345
|
+
# Build an ABI without arguments to determine if one exists
|
|
346
|
+
function_abis_with_arg_count = [
|
|
347
|
+
ABIFunction({"type": "function", "name": function_name})
|
|
348
|
+
]
|
|
349
|
+
|
|
350
|
+
# Check that arguments in call match a function ABI
|
|
351
|
+
num_attempts = 0
|
|
352
|
+
function_abi_matches = []
|
|
353
|
+
contract_function = None
|
|
354
|
+
for abi in function_abis_with_arg_count:
|
|
355
|
+
try:
|
|
356
|
+
num_attempts += 1
|
|
357
|
+
|
|
358
|
+
# Search for a function ABI that matches the arguments used
|
|
359
|
+
function_abi_matches.append(
|
|
360
|
+
cast(
|
|
361
|
+
ABIFunction,
|
|
362
|
+
get_abi_element(
|
|
363
|
+
function_abis,
|
|
364
|
+
abi_to_signature(abi),
|
|
365
|
+
*args,
|
|
366
|
+
abi_codec=self.w3.codec,
|
|
367
|
+
**kwargs,
|
|
368
|
+
),
|
|
369
|
+
)
|
|
370
|
+
)
|
|
371
|
+
except MismatchedABI:
|
|
372
|
+
# ignore exceptions
|
|
373
|
+
continue
|
|
374
|
+
|
|
375
|
+
if len(function_abi_matches) == 1:
|
|
376
|
+
function_abi = function_abi_matches[0]
|
|
377
|
+
if abi_to_signature(self.abi) == abi_to_signature(function_abi):
|
|
378
|
+
contract_function = self
|
|
379
|
+
else:
|
|
380
|
+
# Found a match that is not self
|
|
381
|
+
contract_function = ContractFunction.factory(
|
|
382
|
+
abi_to_signature(function_abi),
|
|
383
|
+
w3=self.w3,
|
|
384
|
+
contract_abi=self.contract_abi,
|
|
385
|
+
address=self.address,
|
|
386
|
+
abi_element_identifier=abi_to_signature(function_abi),
|
|
387
|
+
abi=function_abi,
|
|
388
|
+
)
|
|
389
|
+
else:
|
|
390
|
+
for abi in function_abi_matches:
|
|
391
|
+
if abi_to_signature(self.abi) == abi_to_signature(abi):
|
|
392
|
+
contract_function = self
|
|
393
|
+
break
|
|
394
|
+
else:
|
|
395
|
+
# Raise exception if multiple found
|
|
396
|
+
raise MismatchedABI(
|
|
397
|
+
_mismatched_abi_error_diagnosis(
|
|
398
|
+
function_name,
|
|
399
|
+
self.contract_abi,
|
|
400
|
+
len(function_abi_matches),
|
|
401
|
+
num_args,
|
|
402
|
+
*args,
|
|
403
|
+
abi_codec=self.w3.codec,
|
|
404
|
+
**kwargs,
|
|
405
|
+
)
|
|
406
|
+
)
|
|
407
|
+
|
|
358
408
|
return copy_contract_function(contract_function, *args, **kwargs)
|
|
359
409
|
|
|
360
410
|
@classmethod
|
|
@@ -364,7 +414,7 @@ class ContractFunction(BaseContractFunction):
|
|
|
364
414
|
def call(
|
|
365
415
|
self,
|
|
366
416
|
transaction: Optional[TxParams] = None,
|
|
367
|
-
block_identifier: BlockIdentifier = None,
|
|
417
|
+
block_identifier: Optional[BlockIdentifier] = None,
|
|
368
418
|
state_override: Optional[StateOverride] = None,
|
|
369
419
|
ccip_read_enabled: Optional[bool] = None,
|
|
370
420
|
) -> Any:
|
|
@@ -389,9 +439,9 @@ class ContractFunction(BaseContractFunction):
|
|
|
389
439
|
addr = contract.functions.owner().call()
|
|
390
440
|
|
|
391
441
|
:param transaction: Dictionary of transaction info for web3 interface
|
|
392
|
-
:param block_identifier:
|
|
393
|
-
:param state_override
|
|
394
|
-
:param ccip_read_enabled
|
|
442
|
+
:param block_identifier: Block number or string "latest", "pending", "earliest"
|
|
443
|
+
:param state_override: Dictionary of state override values
|
|
444
|
+
:param ccip_read_enabled: Enable CCIP read operations for the call
|
|
395
445
|
:return: ``Caller`` object that has contract public functions
|
|
396
446
|
and variables exposed as Python methods
|
|
397
447
|
"""
|
|
@@ -475,12 +525,14 @@ class ContractFunction(BaseContractFunction):
|
|
|
475
525
|
address: Optional[ChecksumAddress] = None,
|
|
476
526
|
) -> "ContractFunction":
|
|
477
527
|
if abi and fallback_func_abi_exists(abi):
|
|
528
|
+
fallback_abi = filter_abi_by_type("fallback", abi)[0]
|
|
478
529
|
return ContractFunction.factory(
|
|
479
530
|
"fallback",
|
|
480
531
|
w3=w3,
|
|
481
532
|
contract_abi=abi,
|
|
482
533
|
address=address,
|
|
483
534
|
abi_element_identifier=FallbackFn,
|
|
535
|
+
abi=fallback_abi,
|
|
484
536
|
)()
|
|
485
537
|
return cast(ContractFunction, NonExistentFallbackFunction())
|
|
486
538
|
|
|
@@ -491,12 +543,14 @@ class ContractFunction(BaseContractFunction):
|
|
|
491
543
|
address: Optional[ChecksumAddress] = None,
|
|
492
544
|
) -> "ContractFunction":
|
|
493
545
|
if abi and receive_func_abi_exists(abi):
|
|
546
|
+
receive_abi = filter_abi_by_type("receive", abi)[0]
|
|
494
547
|
return ContractFunction.factory(
|
|
495
548
|
"receive",
|
|
496
549
|
w3=w3,
|
|
497
550
|
contract_abi=abi,
|
|
498
551
|
address=address,
|
|
499
552
|
abi_element_identifier=ReceiveFn,
|
|
553
|
+
abi=receive_abi,
|
|
500
554
|
)()
|
|
501
555
|
return cast(ContractFunction, NonExistentReceiveFunction())
|
|
502
556
|
|
|
@@ -533,19 +587,19 @@ class ContractFunctions(BaseContractFunctions):
|
|
|
533
587
|
for function in self._functions
|
|
534
588
|
]:
|
|
535
589
|
raise ABIFunctionNotFound(
|
|
536
|
-
f"The function '{function_name}' was not found in this
|
|
537
|
-
"
|
|
590
|
+
f"The function '{function_name}' was not found in this ",
|
|
591
|
+
"contract's abi.",
|
|
538
592
|
)
|
|
539
593
|
|
|
540
|
-
function_identifier = function_name
|
|
541
|
-
|
|
542
594
|
if "(" not in function_name:
|
|
543
|
-
|
|
595
|
+
function_name = _get_any_abi_signature_with_name(
|
|
544
596
|
function_name, self._functions
|
|
545
597
|
)
|
|
598
|
+
else:
|
|
599
|
+
function_name = f"_{function_name}"
|
|
546
600
|
|
|
547
601
|
return super().__getattribute__(
|
|
548
|
-
|
|
602
|
+
function_name,
|
|
549
603
|
)
|
|
550
604
|
|
|
551
605
|
def __getitem__(self, function_name: str) -> "ContractFunction":
|
|
@@ -574,7 +628,8 @@ class Contract(BaseContract):
|
|
|
574
628
|
)
|
|
575
629
|
|
|
576
630
|
if address:
|
|
577
|
-
|
|
631
|
+
# invoke ``w3._ens`` over ``w3.ens`` to avoid premature instantiation
|
|
632
|
+
self.address = normalize_address(cast("ENS", _w3._ens), address)
|
|
578
633
|
|
|
579
634
|
if not self.address:
|
|
580
635
|
raise Web3TypeError(
|
|
@@ -585,7 +640,11 @@ class Contract(BaseContract):
|
|
|
585
640
|
self.abi, _w3, self.address, decode_tuples=self.decode_tuples
|
|
586
641
|
)
|
|
587
642
|
self.caller = ContractCaller(
|
|
588
|
-
self.abi,
|
|
643
|
+
self.abi,
|
|
644
|
+
_w3,
|
|
645
|
+
self.address,
|
|
646
|
+
decode_tuples=self.decode_tuples,
|
|
647
|
+
contract_functions=self.functions,
|
|
589
648
|
)
|
|
590
649
|
self.events = ContractEvents(self.abi, _w3, self.address)
|
|
591
650
|
self.fallback = Contract.get_fallback_function(
|
|
@@ -609,7 +668,8 @@ class Contract(BaseContract):
|
|
|
609
668
|
|
|
610
669
|
normalizers = {
|
|
611
670
|
"abi": normalize_abi,
|
|
612
|
-
|
|
671
|
+
# invoke ``w3._ens`` over ``w3.ens`` to avoid premature instantiation
|
|
672
|
+
"address": partial(normalize_address, w3._ens),
|
|
613
673
|
"bytecode": normalize_bytecode,
|
|
614
674
|
"bytecode_runtime": normalize_bytecode,
|
|
615
675
|
}
|
|
@@ -641,6 +701,7 @@ class Contract(BaseContract):
|
|
|
641
701
|
contract.w3,
|
|
642
702
|
contract.address,
|
|
643
703
|
decode_tuples=contract.decode_tuples,
|
|
704
|
+
contract_functions=contract.functions,
|
|
644
705
|
)
|
|
645
706
|
contract.events = ContractEvents(contract.abi, contract.w3)
|
|
646
707
|
contract.fallback = Contract.get_fallback_function(
|
|
@@ -706,7 +767,7 @@ class Contract(BaseContract):
|
|
|
706
767
|
|
|
707
768
|
@combomethod
|
|
708
769
|
def get_event_by_identifier(
|
|
709
|
-
|
|
770
|
+
self, events: Sequence["ContractEvent"], identifier: str
|
|
710
771
|
) -> "ContractEvent":
|
|
711
772
|
return get_event_by_identifier(events, identifier)
|
|
712
773
|
|
|
@@ -724,6 +785,7 @@ class ContractCaller(BaseContractCaller):
|
|
|
724
785
|
block_identifier: BlockIdentifier = None,
|
|
725
786
|
ccip_read_enabled: Optional[bool] = None,
|
|
726
787
|
decode_tuples: Optional[bool] = False,
|
|
788
|
+
contract_functions: Optional[ContractFunctions] = None,
|
|
727
789
|
) -> None:
|
|
728
790
|
super().__init__(abi, w3, address, decode_tuples=decode_tuples)
|
|
729
791
|
|
|
@@ -731,18 +793,13 @@ class ContractCaller(BaseContractCaller):
|
|
|
731
793
|
if transaction is None:
|
|
732
794
|
transaction = {}
|
|
733
795
|
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
abi_signature = abi_to_signature(func)
|
|
738
|
-
fn = ContractFunction.factory(
|
|
739
|
-
abi_signature,
|
|
740
|
-
w3=w3,
|
|
741
|
-
contract_abi=self.abi,
|
|
742
|
-
address=self.address,
|
|
743
|
-
decode_tuples=decode_tuples,
|
|
796
|
+
if contract_functions is None:
|
|
797
|
+
contract_functions = ContractFunctions(
|
|
798
|
+
abi, w3, address=address, decode_tuples=decode_tuples
|
|
744
799
|
)
|
|
745
800
|
|
|
801
|
+
self._functions = contract_functions._functions
|
|
802
|
+
for fn in contract_functions.__iter__():
|
|
746
803
|
caller_method = partial(
|
|
747
804
|
self.call_function,
|
|
748
805
|
fn,
|
|
@@ -750,8 +807,7 @@ class ContractCaller(BaseContractCaller):
|
|
|
750
807
|
block_identifier=block_identifier,
|
|
751
808
|
ccip_read_enabled=ccip_read_enabled,
|
|
752
809
|
)
|
|
753
|
-
|
|
754
|
-
setattr(self, abi_signature, caller_method)
|
|
810
|
+
setattr(self, str(fn.abi_element_identifier), caller_method)
|
|
755
811
|
|
|
756
812
|
def __call__(
|
|
757
813
|
self,
|
web3/contract/utils.py
CHANGED
|
@@ -343,7 +343,10 @@ def find_functions_by_identifier(
|
|
|
343
343
|
"""
|
|
344
344
|
Given a contract ABI, return a list of TContractFunction instances.
|
|
345
345
|
"""
|
|
346
|
-
fns_abi =
|
|
346
|
+
fns_abi = sorted(
|
|
347
|
+
filter_abi_by_type("function", contract_abi),
|
|
348
|
+
key=lambda fn: (fn["name"], len(fn.get("inputs", []))),
|
|
349
|
+
)
|
|
347
350
|
return [
|
|
348
351
|
function_type.factory(
|
|
349
352
|
abi_to_signature(fn_abi),
|
web3/providers/ipc.py
CHANGED
|
@@ -164,7 +164,7 @@ class IPCProvider(JSONBaseProvider):
|
|
|
164
164
|
def _make_request(self, request: bytes) -> RPCResponse:
|
|
165
165
|
with self._lock, self._socket as sock:
|
|
166
166
|
try:
|
|
167
|
-
sock.sendall(request)
|
|
167
|
+
sock.sendall(request + b"\n")
|
|
168
168
|
except BrokenPipeError:
|
|
169
169
|
# one extra attempt, then give up
|
|
170
170
|
sock = self._socket.reset()
|
|
@@ -116,7 +116,7 @@ class AsyncIPCProvider(PersistentConnectionProvider):
|
|
|
116
116
|
|
|
117
117
|
async def _socket_send(self, request_data: bytes) -> None:
|
|
118
118
|
try:
|
|
119
|
-
self._writer.write(request_data)
|
|
119
|
+
self._writer.write(request_data + b"\n")
|
|
120
120
|
await self._writer.drain()
|
|
121
121
|
except OSError as e:
|
|
122
122
|
# Broken pipe
|
web3/utils/abi.py
CHANGED
|
@@ -32,6 +32,16 @@ from eth_typing import (
|
|
|
32
32
|
HexStr,
|
|
33
33
|
Primitives,
|
|
34
34
|
)
|
|
35
|
+
from eth_utils.abi import (
|
|
36
|
+
abi_to_signature,
|
|
37
|
+
event_abi_to_log_topic,
|
|
38
|
+
filter_abi_by_name,
|
|
39
|
+
filter_abi_by_type,
|
|
40
|
+
function_abi_to_4byte_selector,
|
|
41
|
+
get_abi_input_types,
|
|
42
|
+
get_aligned_abi_inputs,
|
|
43
|
+
get_normalized_abi_inputs,
|
|
44
|
+
)
|
|
35
45
|
from eth_utils.address import (
|
|
36
46
|
is_binary_address,
|
|
37
47
|
is_checksum_address,
|
|
@@ -55,7 +65,6 @@ from hexbytes import (
|
|
|
55
65
|
|
|
56
66
|
from web3._utils.abi import (
|
|
57
67
|
filter_by_argument_name,
|
|
58
|
-
filter_by_argument_type,
|
|
59
68
|
get_abi_element_signature,
|
|
60
69
|
get_name_from_abi_element_identifier,
|
|
61
70
|
)
|
|
@@ -77,17 +86,6 @@ from web3.types import (
|
|
|
77
86
|
ABIElementIdentifier,
|
|
78
87
|
)
|
|
79
88
|
|
|
80
|
-
from eth_utils.abi import ( # noqa
|
|
81
|
-
abi_to_signature,
|
|
82
|
-
event_abi_to_log_topic,
|
|
83
|
-
filter_abi_by_name,
|
|
84
|
-
filter_abi_by_type,
|
|
85
|
-
function_abi_to_4byte_selector,
|
|
86
|
-
get_aligned_abi_inputs,
|
|
87
|
-
get_normalized_abi_inputs,
|
|
88
|
-
get_abi_input_types,
|
|
89
|
-
)
|
|
90
|
-
|
|
91
89
|
|
|
92
90
|
def _filter_by_signature(signature: str, contract_abi: ABI) -> List[ABIElement]:
|
|
93
91
|
return [abi for abi in contract_abi if abi_to_signature(abi) == signature]
|
|
@@ -167,32 +165,35 @@ def _get_fallback_function_abi(contract_abi: ABI) -> ABIFallback:
|
|
|
167
165
|
raise ABIFallbackNotFound("No fallback function was found in the contract ABI.")
|
|
168
166
|
|
|
169
167
|
|
|
170
|
-
def _get_any_abi_signature_with_name(
|
|
168
|
+
def _get_any_abi_signature_with_name(
|
|
169
|
+
element_name: str, elements: Sequence[ABIElement]
|
|
170
|
+
) -> str:
|
|
171
171
|
"""
|
|
172
172
|
Find an ABI identifier signature by element name. A signature identifier is
|
|
173
173
|
returned, "name(arg1Type,arg2Type,...)".
|
|
174
174
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
175
|
+
If multiple ABIs match the name and every one contain arguments, the first
|
|
176
|
+
result is returned. Otherwise the signature without arguments is returned.
|
|
177
|
+
Returns None if no ABI exists with the provided name.
|
|
178
178
|
"""
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
return abi_to_signature(function_abi)
|
|
185
|
-
except MismatchedABI:
|
|
186
|
-
# If all matching functions have arguments, cannot determine which one
|
|
187
|
-
# to use. Instead of an exception, return the first matching function.
|
|
188
|
-
function_abis = filter_abi_by_name(element_name, contract_abi)
|
|
189
|
-
if len(function_abis) > 0 and all(
|
|
190
|
-
len(get_abi_input_types(fn)) > 0 for fn in function_abis
|
|
191
|
-
):
|
|
192
|
-
return abi_to_signature(function_abis[0])
|
|
179
|
+
element_signatures_with_name = [
|
|
180
|
+
abi_to_signature(element)
|
|
181
|
+
for element in elements
|
|
182
|
+
if element.get("name", "") == get_name_from_abi_element_identifier(element_name)
|
|
183
|
+
]
|
|
193
184
|
|
|
194
|
-
|
|
195
|
-
return
|
|
185
|
+
if len(element_signatures_with_name) == 1:
|
|
186
|
+
return element_signatures_with_name[0]
|
|
187
|
+
elif len(element_signatures_with_name) > 1:
|
|
188
|
+
# Check for function signature without args
|
|
189
|
+
signature_without_args = f"{element_name}()"
|
|
190
|
+
if signature_without_args not in element_signatures_with_name:
|
|
191
|
+
# Element without arguments not found, use the first available signature
|
|
192
|
+
return element_signatures_with_name[0]
|
|
193
|
+
else:
|
|
194
|
+
return signature_without_args
|
|
195
|
+
else:
|
|
196
|
+
return None
|
|
196
197
|
|
|
197
198
|
|
|
198
199
|
def _build_abi_input_error(
|
|
@@ -375,9 +376,6 @@ def _get_argument_readable_type(arg: Any) -> str:
|
|
|
375
376
|
def _build_abi_filters(
|
|
376
377
|
abi_element_identifier: ABIElementIdentifier,
|
|
377
378
|
*args: Optional[Any],
|
|
378
|
-
abi_type: Optional[str] = None,
|
|
379
|
-
argument_names: Optional[Sequence[str]] = None,
|
|
380
|
-
argument_types: Optional[Sequence[str]] = None,
|
|
381
379
|
abi_codec: Optional[Any] = None,
|
|
382
380
|
**kwargs: Optional[Any],
|
|
383
381
|
) -> List[Callable[..., Sequence[ABIElement]]]:
|
|
@@ -405,15 +403,14 @@ def _build_abi_filters(
|
|
|
405
403
|
|
|
406
404
|
filters: List[Callable[..., Sequence[ABIElement]]] = []
|
|
407
405
|
|
|
408
|
-
if abi_type:
|
|
409
|
-
filters.append(functools.partial(filter_abi_by_type, abi_type))
|
|
410
|
-
|
|
411
406
|
arg_count = 0
|
|
412
|
-
if
|
|
413
|
-
arg_count = len(argument_names)
|
|
414
|
-
elif args or kwargs:
|
|
407
|
+
if args or kwargs:
|
|
415
408
|
arg_count = len(args) + len(kwargs)
|
|
416
409
|
|
|
410
|
+
# Filter by arg count only if the identifier contains arguments
|
|
411
|
+
if "()" not in abi_element_identifier and arg_count:
|
|
412
|
+
filters.append(functools.partial(_filter_by_argument_count, arg_count))
|
|
413
|
+
|
|
417
414
|
if arg_count > 0:
|
|
418
415
|
filters.append(
|
|
419
416
|
functools.partial(
|
|
@@ -421,7 +418,6 @@ def _build_abi_filters(
|
|
|
421
418
|
get_name_from_abi_element_identifier(abi_element_identifier),
|
|
422
419
|
)
|
|
423
420
|
)
|
|
424
|
-
filters.append(functools.partial(_filter_by_argument_count, arg_count))
|
|
425
421
|
|
|
426
422
|
if args or kwargs:
|
|
427
423
|
if abi_codec is None:
|
|
@@ -436,19 +432,6 @@ def _build_abi_filters(
|
|
|
436
432
|
)
|
|
437
433
|
)
|
|
438
434
|
|
|
439
|
-
if argument_names:
|
|
440
|
-
filters.append(functools.partial(filter_by_argument_name, argument_names))
|
|
441
|
-
|
|
442
|
-
if argument_types:
|
|
443
|
-
if arg_count != len(argument_types):
|
|
444
|
-
raise Web3ValidationError(
|
|
445
|
-
"The number of argument names and types must match."
|
|
446
|
-
)
|
|
447
|
-
|
|
448
|
-
filters.append(
|
|
449
|
-
functools.partial(filter_by_argument_type, argument_types)
|
|
450
|
-
)
|
|
451
|
-
|
|
452
435
|
if "(" in abi_element_identifier:
|
|
453
436
|
filters.append(
|
|
454
437
|
functools.partial(_filter_by_signature, abi_element_identifier)
|
|
@@ -619,7 +602,7 @@ def get_abi_element(
|
|
|
619
602
|
|
|
620
603
|
num_matches = len(abi_element_matches)
|
|
621
604
|
|
|
622
|
-
# Raise MismatchedABI
|
|
605
|
+
# Raise MismatchedABI unless one match is found
|
|
623
606
|
if num_matches != 1:
|
|
624
607
|
error_diagnosis = _mismatched_abi_error_diagnosis(
|
|
625
608
|
abi_element_identifier,
|
web3/utils/address.py
CHANGED
|
@@ -9,6 +9,9 @@ from eth_utils import (
|
|
|
9
9
|
)
|
|
10
10
|
import rlp
|
|
11
11
|
|
|
12
|
+
from web3.exceptions import (
|
|
13
|
+
Web3ValidationError,
|
|
14
|
+
)
|
|
12
15
|
from web3.types import (
|
|
13
16
|
HexStr,
|
|
14
17
|
Nonce,
|
|
@@ -30,6 +33,11 @@ def get_create2_address(
|
|
|
30
33
|
Determine the resulting `CREATE2` opcode contract address for a sender, salt and
|
|
31
34
|
bytecode.
|
|
32
35
|
"""
|
|
36
|
+
if len(to_bytes(hexstr=salt)) != 32:
|
|
37
|
+
raise Web3ValidationError(
|
|
38
|
+
f"`salt` must be 32 bytes, {len(to_bytes(hexstr=salt))} != 32"
|
|
39
|
+
)
|
|
40
|
+
|
|
33
41
|
contract_address = keccak(
|
|
34
42
|
b"\xff"
|
|
35
43
|
+ to_bytes(hexstr=sender)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: web3
|
|
3
|
-
Version: 7.6.
|
|
3
|
+
Version: 7.6.1
|
|
4
4
|
Summary: web3: A Python library for interacting with Ethereum
|
|
5
5
|
Home-page: https://github.com/ethereum/web3.py
|
|
6
6
|
Author: The Ethereum Foundation
|
|
@@ -56,8 +56,8 @@ Requires-Dist: hypothesis >=3.31.2 ; extra == 'dev'
|
|
|
56
56
|
Requires-Dist: tox >=4.0.0 ; extra == 'dev'
|
|
57
57
|
Requires-Dist: mypy ==1.10.0 ; extra == 'dev'
|
|
58
58
|
Requires-Dist: pre-commit >=3.4.0 ; extra == 'dev'
|
|
59
|
-
Requires-Dist: eth-tester[py-evm] <0.13.0b1,>=0.
|
|
60
|
-
Requires-Dist: py-geth >=5.
|
|
59
|
+
Requires-Dist: eth-tester[py-evm] <0.13.0b1,>=0.12.0b1 ; extra == 'dev'
|
|
60
|
+
Requires-Dist: py-geth >=5.1.0 ; extra == 'dev'
|
|
61
61
|
Provides-Extra: docs
|
|
62
62
|
Requires-Dist: sphinx >=6.0.0 ; extra == 'docs'
|
|
63
63
|
Requires-Dist: sphinx-autobuild >=2021.3.14 ; extra == 'docs'
|
|
@@ -73,11 +73,11 @@ Requires-Dist: hypothesis >=3.31.2 ; extra == 'test'
|
|
|
73
73
|
Requires-Dist: tox >=4.0.0 ; extra == 'test'
|
|
74
74
|
Requires-Dist: mypy ==1.10.0 ; extra == 'test'
|
|
75
75
|
Requires-Dist: pre-commit >=3.4.0 ; extra == 'test'
|
|
76
|
-
Requires-Dist: eth-tester[py-evm] <0.13.0b1,>=0.
|
|
77
|
-
Requires-Dist: py-geth >=5.
|
|
76
|
+
Requires-Dist: eth-tester[py-evm] <0.13.0b1,>=0.12.0b1 ; extra == 'test'
|
|
77
|
+
Requires-Dist: py-geth >=5.1.0 ; extra == 'test'
|
|
78
78
|
Provides-Extra: tester
|
|
79
|
-
Requires-Dist: eth-tester[py-evm] <0.13.0b1,>=0.
|
|
80
|
-
Requires-Dist: py-geth >=5.
|
|
79
|
+
Requires-Dist: eth-tester[py-evm] <0.13.0b1,>=0.12.0b1 ; extra == 'tester'
|
|
80
|
+
Requires-Dist: py-geth >=5.1.0 ; extra == 'tester'
|
|
81
81
|
|
|
82
82
|
# web3.py
|
|
83
83
|
|