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/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
- filter_abi_by_type,
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
- event_abi = get_abi_element(
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
- if "_events" not in self.__dict__ or len(self._events) == 0:
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
- event_abi = get_abi_element(self._events, event_name)
308
- argument_types = get_abi_input_types(event_abi)
309
- event_signature = str(get_abi_element_signature(event_name, argument_types))
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["name"]]
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
- element_name = self.abi_element_identifier
326
- if element_name in ["fallback", "receive"] or len(args) + len(kwargs):
327
- # Use only the name if a fallback, receive function
328
- # or when args/kwargs are present to find the proper element
329
- element_name = self.fn_name
330
-
331
- function_abi = get_abi_element(
332
- filter_by_types(
333
- ["function", "constructor", "fallback", "receive"],
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
- argument_types = None
343
- if function_abi["type"] not in ["fallback", "receive"]:
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
- contract_function = ContractFunction.factory(
350
- function_signature,
351
- w3=self.w3,
352
- contract_abi=self.contract_abi,
353
- address=self.address,
354
- abi_element_identifier=function_signature,
355
- decode_tuples=self.decode_tuples,
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: TODO
393
- :param state_override TODO
394
- :param ccip_read_enabled TODO
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 contract's "
537
- "abi. Are you sure you provided the correct contract abi?",
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
- function_identifier = _get_any_abi_signature_with_name(
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
- function_identifier,
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
- self.address = normalize_address(cast("ENS", _w3.ens), address)
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, _w3, self.address, decode_tuples=self.decode_tuples
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
- "address": partial(normalize_address, w3.ens),
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
- cls, events: Sequence["ContractEvent"], identifier: str
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
- self._functions = get_all_function_abis(self.abi)
735
-
736
- for func in self._functions:
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 = filter_abi_by_type("function", contract_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(element_name: str, contract_abi: ABI) -> str:
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
- This function forces one result to be returned even if multiple are found.
176
- If multiple ABIs are found and all contain arguments, the first result is returned.
177
- Otherwise when one of the ABIs has zero arguments, that signature is returned.
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
- try:
180
- # search for function abis with the same name
181
- function_abi = get_abi_element(
182
- contract_abi, get_name_from_abi_element_identifier(element_name)
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
- # Use signature for function that does not take arguments
195
- return str(get_abi_element_signature(element_name))
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 argument_names:
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 when more than one found
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.0
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.11.0b1 ; extra == 'dev'
60
- Requires-Dist: py-geth >=5.0.0 ; extra == 'dev'
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.11.0b1 ; extra == 'test'
77
- Requires-Dist: py-geth >=5.0.0 ; extra == 'test'
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.11.0b1 ; extra == 'tester'
80
- Requires-Dist: py-geth >=5.0.0 ; extra == 'tester'
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