eth-prototype 1.4.0__tar.gz → 1.5.0b1__tar.gz

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.
Files changed (72) hide show
  1. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/PKG-INFO +1 -1
  2. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/src/eth_prototype.egg-info/PKG-INFO +1 -1
  3. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/src/ethproto/aa_bundler.py +129 -18
  4. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/src/ethproto/w3wrappers.py +18 -21
  5. eth_prototype-1.5.0b1/tests/cassettes/test_aa_bundler/test_build_user_operation.yaml +93 -0
  6. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/tests/test_aa_bundler.py +35 -28
  7. eth_prototype-1.4.0/tests/cassettes/test_aa_bundler/test_build_user_operation.yaml +0 -89
  8. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/.coveragerc +0 -0
  9. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/.github/workflows/publish.yaml +0 -0
  10. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/.github/workflows/test.yaml +0 -0
  11. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/.gitignore +0 -0
  12. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/.isort.cfg +0 -0
  13. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/.pre-commit-config.yaml +0 -0
  14. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/.readthedocs.yml +0 -0
  15. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/AUTHORS.rst +0 -0
  16. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/CHANGELOG.rst +0 -0
  17. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/LICENSE.txt +0 -0
  18. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/README.md +0 -0
  19. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/docs/Makefile +0 -0
  20. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/docs/_static/.gitignore +0 -0
  21. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/docs/authors.rst +0 -0
  22. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/docs/changelog.rst +0 -0
  23. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/docs/conf.py +0 -0
  24. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/docs/index.rst +0 -0
  25. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/docs/license.rst +0 -0
  26. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/docs/readme.rst +0 -0
  27. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/docs/requirements.txt +0 -0
  28. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/pyproject.toml +0 -0
  29. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/setup.cfg +0 -0
  30. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/setup.py +0 -0
  31. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/src/eth_prototype.egg-info/SOURCES.txt +0 -0
  32. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/src/eth_prototype.egg-info/dependency_links.txt +0 -0
  33. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/src/eth_prototype.egg-info/not-zip-safe +0 -0
  34. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/src/eth_prototype.egg-info/requires.txt +0 -0
  35. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/src/eth_prototype.egg-info/top_level.txt +0 -0
  36. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/src/ethproto/__init__.py +0 -0
  37. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/src/ethproto/build_artifacts.py +0 -0
  38. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/src/ethproto/contracts.py +0 -0
  39. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/src/ethproto/defender_relay.py +0 -0
  40. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/src/ethproto/test_utils/__init__.py +0 -0
  41. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/src/ethproto/test_utils/factories.py +0 -0
  42. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/src/ethproto/test_utils/hardhat.py +0 -0
  43. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/src/ethproto/test_utils/vcr_utils.py +0 -0
  44. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/src/ethproto/wadray.py +0 -0
  45. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/src/ethproto/wrappers.py +0 -0
  46. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/tests/__init__.py +0 -0
  47. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/tests/conftest.py +0 -0
  48. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/tests/hardhat-project/README.md +0 -0
  49. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/tests/hardhat-project/artifacts2/TestCurrency.sol/TestCurrency.json +0 -0
  50. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/tests/hardhat-project/contracts/Count.sol +0 -0
  51. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/tests/hardhat-project/contracts/Counter.sol +0 -0
  52. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/tests/hardhat-project/contracts/CounterUpgradeable.sol +0 -0
  53. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/tests/hardhat-project/contracts/CounterUpgradeableWithLibrary.sol +0 -0
  54. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/tests/hardhat-project/contracts/CounterWithLibrary.sol +0 -0
  55. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/tests/hardhat-project/contracts/Datatypes.sol +0 -0
  56. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/tests/hardhat-project/contracts/EventLauncher.sol +0 -0
  57. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/tests/hardhat-project/contracts/TestCurrency.sol +0 -0
  58. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/tests/hardhat-project/contracts/TestCurrencyUUPS.sol +0 -0
  59. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/tests/hardhat-project/contracts/TestNFT.sol +0 -0
  60. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/tests/hardhat-project/hardhat.config.js +0 -0
  61. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/tests/hardhat-project/package-lock.json +0 -0
  62. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/tests/hardhat-project/package.json +0 -0
  63. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/tests/hardhat-project/verifiable-binaries/@anotherOrg/aPkg/1.0.2/build/contracts/TestCurrency.sol/TestCurrency.json +0 -0
  64. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/tests/hardhat-project/verifiable-binaries/@org/pkg/0.2.1/build/contracts/TestCurrency.json +0 -0
  65. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/tests/hardhat-project/verifiable-binaries/@org/pkg/0.3.0/build/contracts/TestCurrency.json +0 -0
  66. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/tests/test_build_artifacts.py +0 -0
  67. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/tests/test_contracts.py +0 -0
  68. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/tests/test_defender.py +0 -0
  69. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/tests/test_time_control.py +0 -0
  70. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/tests/test_w3.py +0 -0
  71. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/tests/test_wadray.py +0 -0
  72. {eth_prototype-1.4.0 → eth_prototype-1.5.0b1}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: eth-prototype
3
- Version: 1.4.0
3
+ Version: 1.5.0b1
4
4
  Summary: Prototype Ethereum Smart Contracts in Python
5
5
  Home-page: https://github.com/gnarvaja/eth-prototype
6
6
  Author: Guillermo M. Narvaja
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: eth-prototype
3
- Version: 1.4.0
3
+ Version: 1.5.0b1
4
4
  Summary: Prototype Ethereum Smart Contracts in Python
5
5
  Home-page: https://github.com/gnarvaja/eth-prototype
6
6
  Author: Guillermo M. Narvaja
@@ -7,6 +7,7 @@ from warnings import warn
7
7
 
8
8
  from environs import Env
9
9
  from eth_abi import encode
10
+ from eth_abi.packed import encode_packed
10
11
  from eth_account import Account
11
12
  from eth_account.messages import encode_defunct
12
13
  from eth_typing import HexAddress
@@ -24,7 +25,7 @@ AA_BUNDLER_URL = env.str("AA_BUNDLER_URL", env.str("WEB3_PROVIDER_URI", "http://
24
25
  AA_BUNDLER_SENDER = env.str("AA_BUNDLER_SENDER", None)
25
26
  AA_BUNDLER_ENTRYPOINT = env.str("AA_BUNDLER_ENTRYPOINT", "0x0000000071727De22E5E9d8BAf0edAc6f37da032")
26
27
  AA_BUNDLER_EXECUTOR_PK = env.str("AA_BUNDLER_EXECUTOR_PK", None)
27
- AA_BUNDLER_PROVIDER = env.str("AA_BUNDLER_PROVIDER", "alchemy")
28
+ AA_BUNDLER_PROVIDER = env.str("AA_BUNDLER_PROVIDER", "generic")
28
29
  AA_BUNDLER_GAS_LIMIT_FACTOR = env.float("AA_BUNDLER_GAS_LIMIT_FACTOR", 1)
29
30
  AA_BUNDLER_PRIORITY_GAS_PRICE_FACTOR = env.float("AA_BUNDLER_PRIORITY_GAS_PRICE_FACTOR", 1)
30
31
  AA_BUNDLER_BASE_GAS_PRICE_FACTOR = env.float("AA_BUNDLER_BASE_GAS_PRICE_FACTOR", 1)
@@ -47,7 +48,7 @@ NonceMode = Enum(
47
48
  AA_BUNDLER_NONCE_MODE = env.enum("AA_BUNDLER_NONCE_MODE", default="FIXED_KEY_LOCAL_NONCE", enum=NonceMode)
48
49
  AA_BUNDLER_NONCE_KEY = env.int("AA_BUNDLER_NONCE_KEY", 0)
49
50
  AA_BUNDLER_MAX_GETNONCE_RETRIES = env.int("AA_BUNDLER_MAX_GETNONCE_RETRIES", 3)
50
-
51
+ AA_BUNDLER_ALCHEMY_GAS_POLICY_ID = env.str("AA_BUNDLER_ALCHEMY_GAS_POLICY_ID", None)
51
52
 
52
53
  GET_NONCE_ABI = [
53
54
  {
@@ -81,6 +82,10 @@ class BundlerRevertError(RevertError):
81
82
  self.response = response
82
83
 
83
84
 
85
+ class BundlerError(Exception):
86
+ pass
87
+
88
+
84
89
  @dataclass(frozen=True)
85
90
  class UserOpEstimation:
86
91
  """eth_estimateUserOperationGas response"""
@@ -97,6 +102,21 @@ class GasPrice:
97
102
  max_fee_per_gas: int
98
103
 
99
104
 
105
+ @dataclass(frozen=True)
106
+ class PaymasterAndData:
107
+ paymaster: HexAddress
108
+ paymaster_data: HexBytes
109
+ paymaster_verification_gas_limit: int
110
+ paymaster_post_op_gas_limit: int
111
+
112
+
113
+ @dataclass(frozen=True)
114
+ class AlchemyGasAndPaymasterAndData:
115
+ estimation: UserOpEstimation
116
+ gas_price: GasPrice
117
+ paymaster_and_data: PaymasterAndData
118
+
119
+
100
120
  @dataclass(frozen=True)
101
121
  class Tx:
102
122
  target: HexAddress
@@ -141,7 +161,11 @@ class UserOperation:
141
161
  signature: HexBytes = DUMMY_SIGNATURE
142
162
 
143
163
  init_code: HexBytes = HexBytes("0x")
144
- paymaster_and_data: HexBytes = HexBytes("0x")
164
+
165
+ paymaster: HexAddress = None
166
+ paymaster_data: HexBytes = HexBytes("0x")
167
+ paymaster_verification_gas_limit: int = 0
168
+ paymaster_post_op_gas_limit: int = 0
145
169
 
146
170
  @classmethod
147
171
  def from_tx(cls, tx: Tx, nonce):
@@ -172,6 +196,10 @@ class UserOperation:
172
196
  "maxPriorityFeePerGas": "0x%x" % self.max_priority_fee_per_gas,
173
197
  "maxFeePerGas": "0x%x" % self.max_fee_per_gas,
174
198
  "signature": add_0x_prefix(self.signature.hex()),
199
+ "paymaster": self.paymaster,
200
+ "paymasterData": self.paymaster_data,
201
+ "paymasterVerificationGasLimit": "0x%x" % self.paymaster_verification_gas_limit,
202
+ "paymasterPostOpGasLimit": "0x%x" % self.paymaster_post_op_gas_limit,
175
203
  }
176
204
 
177
205
  def add_estimation(self, estimation: UserOpEstimation) -> "UserOperation":
@@ -189,6 +217,15 @@ class UserOperation:
189
217
  max_fee_per_gas=gas_price.max_fee_per_gas,
190
218
  )
191
219
 
220
+ def add_paymaster_and_data(self, paymaster_and_data: PaymasterAndData) -> "UserOperation":
221
+ return replace(
222
+ self,
223
+ paymaster=paymaster_and_data.paymaster,
224
+ paymaster_data=paymaster_and_data.paymaster_data,
225
+ paymaster_verification_gas_limit=paymaster_and_data.paymaster_verification_gas_limit,
226
+ paymaster_post_op_gas_limit=paymaster_and_data.paymaster_post_op_gas_limit,
227
+ )
228
+
192
229
  def sign(self, private_key: HexBytes, chain_id, entrypoint) -> "UserOperation":
193
230
  signature = Account.sign_message(
194
231
  encode_defunct(
@@ -225,7 +262,21 @@ class PackedUserOperation:
225
262
  pre_verification_gas=user_operation.pre_verification_gas,
226
263
  gas_fees=pack_two(user_operation.max_priority_fee_per_gas, user_operation.max_fee_per_gas),
227
264
  init_code=user_operation.init_code,
228
- paymaster_and_data=user_operation.paymaster_and_data,
265
+ paymaster_and_data=(
266
+ HexBytes(
267
+ encode_packed(
268
+ ["address", "uint128", "uint128", "bytes"],
269
+ [
270
+ user_operation.paymaster,
271
+ user_operation.paymaster_verification_gas_limit,
272
+ user_operation.paymaster_post_op_gas_limit,
273
+ user_operation.paymaster_data,
274
+ ],
275
+ )
276
+ )
277
+ if user_operation.paymaster is not None
278
+ else HexBytes("0x")
279
+ ).to_0x_hex(),
229
280
  signature=user_operation.signature,
230
281
  )
231
282
 
@@ -333,6 +384,7 @@ class Bundler:
333
384
  max_fee_per_gas: int = AA_BUNDLER_MAX_FEE_PER_GAS,
334
385
  executor_pk: HexBytes = AA_BUNDLER_EXECUTOR_PK,
335
386
  overrides: StateOverride = AA_BUNDLER_STATE_OVERRIDES,
387
+ alchemy_gas_policy_id: str = AA_BUNDLER_ALCHEMY_GAS_POLICY_ID,
336
388
  ):
337
389
  self.w3 = w3
338
390
  self.bundler = Web3(Web3.HTTPProvider(bundler_url), middleware=[])
@@ -351,6 +403,10 @@ class Bundler:
351
403
  # https://docs.alchemy.com/reference/eth-estimateuseroperationgas
352
404
  self.overrides = overrides
353
405
 
406
+ if alchemy_gas_policy_id is None and bundler_type == "alchemy":
407
+ raise BundlerError("Must provide alchemy_gas_policy_id when using alchemy bundler_type")
408
+ self.alchemy_gas_policy_id = alchemy_gas_policy_id
409
+
354
410
  def __str__(self):
355
411
  return (
356
412
  f"Bundler(type={self.bundler_type}, entrypoint={self.entrypoint}, nonce_mode={self.nonce_mode}, "
@@ -404,14 +460,61 @@ class Bundler:
404
460
  ),
405
461
  )
406
462
 
407
- def alchemy_gas_price(self):
408
- resp = self.bundler.provider.make_request("rundler_maxPriorityFeePerGas", [])
409
- if "error" in resp:
410
- raise BundlerRevertError(resp["error"]["message"], response=resp)
411
- max_priority_fee_per_gas = int(int(resp["result"], 16) * self.priority_gas_price_factor)
412
- max_fee_per_gas = min(max_priority_fee_per_gas + self.get_base_fee(), self.max_fee_per_gas)
463
+ def alchemy_estimation(self, user_operation: UserOperation) -> AlchemyGasAndPaymasterAndData:
464
+ resp = self.bundler.provider.make_request(
465
+ "alchemy_requestGasAndPaymasterAndData",
466
+ [
467
+ {
468
+ "policyId": self.alchemy_gas_policy_id,
469
+ "entryPoint": self.entrypoint,
470
+ "dummySignature": DUMMY_SIGNATURE,
471
+ "userOperation": user_operation.as_reduced_dict(),
472
+ "overrides": {
473
+ "maxFeePerGas": {"multiplier": self.base_gas_price_factor},
474
+ "maxPriorityFeePerGas": {"multiplier": self.priority_gas_price_factor},
475
+ "callGasLimit": {"multiplier": self.gas_limit_factor},
476
+ "verificationGasLimit": {"multiplier": self.verification_gas_factor},
477
+ },
478
+ }
479
+ ],
480
+ )
413
481
 
414
- return GasPrice(max_priority_fee_per_gas=max_priority_fee_per_gas, max_fee_per_gas=max_fee_per_gas)
482
+ if "error" in resp:
483
+ raise BundlerRevertError(resp["error"]["message"], userop=user_operation, response=resp)
484
+
485
+ # {
486
+ # "callGasLimit": "0x3dab",
487
+ # "paymasterVerificationGasLimit": "0x9afa",
488
+ # "paymasterPostOpGasLimit": "0x0",
489
+ # "verificationGasLimit": "0xac33",
490
+ # "maxPriorityFeePerGas": "0x7aef40a00",
491
+ # "paymaster": "0x2cc0c7981D846b9F2a16276556f6e8cb52BfB633",
492
+ # "maxFeePerGas": "0xaf9fe62e48",
493
+ # "paymasterData": "0xabcd...",
494
+ # "preVerificationGas": "0xb8ec"
495
+ # }
496
+
497
+ estimation = UserOpEstimation(
498
+ pre_verification_gas=int(resp["result"]["preVerificationGas"], 16),
499
+ verification_gas_limit=int(resp["result"]["verificationGasLimit"], 16),
500
+ call_gas_limit=int(resp["result"]["callGasLimit"], 16),
501
+ paymaster_verification_gas_limit=int(resp["result"]["paymasterVerificationGasLimit"], 16),
502
+ )
503
+ gas_price = GasPrice(
504
+ max_priority_fee_per_gas=int(resp["result"]["maxPriorityFeePerGas"], 16),
505
+ max_fee_per_gas=int(resp["result"]["maxFeePerGas"], 16),
506
+ )
507
+ paymaster_and_data = PaymasterAndData(
508
+ paymaster=resp["result"]["paymaster"],
509
+ paymaster_data=HexBytes(resp["result"]["paymasterData"]),
510
+ paymaster_verification_gas_limit=int(resp["result"]["paymasterVerificationGasLimit"], 16),
511
+ paymaster_post_op_gas_limit=int(resp["result"]["paymasterPostOpGasLimit"], 16),
512
+ )
513
+ return AlchemyGasAndPaymasterAndData(
514
+ estimation=estimation,
515
+ gas_price=gas_price,
516
+ paymaster_and_data=paymaster_and_data,
517
+ )
415
518
 
416
519
  def generic_gas_price(self):
417
520
  base_fee = self.get_base_fee()
@@ -426,21 +529,29 @@ class Bundler:
426
529
  consume_nonce(nonce_key, nonce)
427
530
 
428
531
  user_operation = UserOperation.from_tx(tx, make_nonce(nonce_key, nonce))
429
- estimation = self.estimate_user_operation_gas(user_operation)
430
-
431
- user_operation = user_operation.add_estimation(estimation)
432
532
 
433
533
  if self.bundler_type == "alchemy":
434
- gas_price = self.alchemy_gas_price()
534
+ estimation_and_paymaster = self.alchemy_estimation(user_operation)
535
+
536
+ user_operation = user_operation.add_estimation(estimation_and_paymaster.estimation)
537
+ user_operation = user_operation.add_gas_price(estimation_and_paymaster.gas_price)
538
+ user_operation = user_operation.add_paymaster_and_data(
539
+ estimation_and_paymaster.paymaster_and_data
540
+ )
435
541
 
436
542
  elif self.bundler_type == "generic":
543
+ estimation = self.estimate_user_operation_gas(user_operation)
544
+
545
+ user_operation = user_operation.add_estimation(estimation)
546
+
437
547
  gas_price = self.generic_gas_price()
438
548
 
549
+ user_operation = user_operation.add_gas_price(gas_price)
550
+
439
551
  else:
440
- warn(f"Unknown bundler_type: {self.bundler_type}")
441
- gas_price = GasPrice(0, 0)
552
+ raise BundlerError(f"Unknown bundler_type: {self.bundler_type}")
442
553
 
443
- return user_operation.add_gas_price(gas_price)
554
+ return user_operation
444
555
 
445
556
  def send_transaction(self, tx: Tx, retry_nonce=None):
446
557
  user_operation = self.build_user_operation(tx, retry_nonce).sign(
@@ -1,5 +1,5 @@
1
1
  import os
2
- from collections import defaultdict
2
+ from itertools import groupby
3
3
  from typing import Iterator, List, Union
4
4
 
5
5
  from environs import Env
@@ -246,30 +246,27 @@ class ReceiptWrapper:
246
246
  self._receipt = receipt
247
247
  self._contract = contract
248
248
 
249
+ def _find_event(self, contract, topic0):
250
+ for event in contract.events:
251
+ evt = event()
252
+ if HexBytes(event_abi_to_log_topic(evt.abi)) == topic0:
253
+ return evt
254
+ return None # Not found
255
+
249
256
  @property
250
257
  def events(self):
251
258
  if not hasattr(self, "_events"):
252
- # Lookup the events in all known contracts
253
- addresses = [log.address for log in self._receipt.logs]
254
- contracts = {addr: _contract_map[addr] for addr in addresses if addr in _contract_map}
255
- topic_map = {
256
- HexBytes(event_abi_to_log_topic(event().abi)): event()
257
- for contract in contracts.values()
258
- for event in contract.events
259
+ addr_topic0 = [(log.address, log.topics[0] if log.topics else None) for log in self._receipt.logs]
260
+ # find uniq event types
261
+ events = {topic0: self._find_event(_contract_map[addr], topic0) for (addr, topic0) in addr_topic0}
262
+ parsed_logs = sum(
263
+ [list(evt.process_receipt(self._receipt)) for evt in events.values() if evt is not None], []
264
+ )
265
+ parsed_logs.sort(key=lambda x: x.event)
266
+ self._events = {
267
+ evt_name: EventItem(evt_name, [pl.args for pl in parsed_logs_for_evt_name])
268
+ for (evt_name, parsed_logs_for_evt_name) in groupby(parsed_logs, key=lambda x: x.event)
259
269
  }
260
-
261
- parsed_logs = []
262
- for log in self._receipt.logs:
263
- for topic in log.topics:
264
- if topic in topic_map:
265
- parsed_logs += topic_map[topic].process_receipt(self._receipt)
266
-
267
- evts = defaultdict(list)
268
- for evt in parsed_logs:
269
- evt_name = evt.event
270
- evt_params = evt.args
271
- evts[evt_name].append(evt_params)
272
- self._events = {k: EventItem(k, v) for k, v in evts.items()}
273
270
  return self._events
274
271
 
275
272
  def __getattr__(self, attr_name):
@@ -0,0 +1,93 @@
1
+ interactions:
2
+ - request:
3
+ body: '{"jsonrpc": "2.0", "method": "alchemy_requestGasAndPaymasterAndData", "params":
4
+ [{"policyId": "01234567-89ab-cdef-0123-456789abcdef", "entryPoint": "0x0000000071727De22E5E9d8BAf0edAc6f37da032",
5
+ "dummySignature": "0xfffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c",
6
+ "userOperation": {"sender": "0xE8B412158c205B0F605e0FC09dCdA27d3F140FE9", "nonce":
7
+ "0xae85c374ae0606ed34d0ee009a9ca43a757a8a46a324510000000000000000", "callData":
8
+ "0xb61d27f60000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa84174000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000007ace242f32208d836a2245df957c08547059bf45ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000",
9
+ "signature": "0xfffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c"},
10
+ "overrides": {"maxFeePerGas": {"multiplier": 1}, "maxPriorityFeePerGas": {"multiplier":
11
+ 1}, "callGasLimit": {"multiplier": 1}, "verificationGasLimit": {"multiplier":
12
+ 1}}}], "id": 0}'
13
+ headers:
14
+ Accept:
15
+ - '*/*'
16
+ Accept-Encoding:
17
+ - gzip, deflate
18
+ Connection:
19
+ - keep-alive
20
+ Content-Length:
21
+ - '1304'
22
+ Content-Type:
23
+ - application/json
24
+ User-Agent:
25
+ - web3.py/7.14.0/web3.providers.rpc.rpc.HTTPProvider
26
+ method: POST
27
+ uri: https://polygon-mainnet.g.alchemy.com
28
+ response:
29
+ body:
30
+ string: Must be authenticated!
31
+ headers:
32
+ content-length:
33
+ - '22'
34
+ content-type:
35
+ - application/json
36
+ date:
37
+ - Wed, 04 Feb 2026 04:41:42 GMT
38
+ server:
39
+ - istio-envoy
40
+ x-alchemy-trace-id:
41
+ - 94eb57bc-3d0b-4c13-98ca-4085af84a4ee
42
+ x-envoy-upstream-service-time:
43
+ - '6'
44
+ status:
45
+ code: 401
46
+ message: Unauthorized
47
+ - request:
48
+ body: '{"jsonrpc": "2.0", "method": "alchemy_requestGasAndPaymasterAndData", "params":
49
+ [{"policyId": "d80ed67a-d8bc-4cd1-90ad-b50e0a58c93e", "entryPoint": "0x0000000071727De22E5E9d8BAf0edAc6f37da032",
50
+ "dummySignature": "0xfffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c",
51
+ "userOperation": {"sender": "0xE8B412158c205B0F605e0FC09dCdA27d3F140FE9", "nonce":
52
+ "0xae85c374ae0606ed34d0ee009a9ca43a757a8a46a324510000000000000000", "callData":
53
+ "0xb61d27f60000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa84174000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000007ace242f32208d836a2245df957c08547059bf45ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000",
54
+ "signature": "0xfffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c"},
55
+ "overrides": {"maxFeePerGas": {"multiplier": 1}, "maxPriorityFeePerGas": {"multiplier":
56
+ 1}, "callGasLimit": {"multiplier": 1}, "verificationGasLimit": {"multiplier":
57
+ 1}}}], "id": 0}'
58
+ headers:
59
+ Accept:
60
+ - '*/*'
61
+ Accept-Encoding:
62
+ - gzip, deflate
63
+ Connection:
64
+ - keep-alive
65
+ Content-Length:
66
+ - '1304'
67
+ Content-Type:
68
+ - application/json
69
+ User-Agent:
70
+ - web3.py/7.14.0/web3.providers.rpc.rpc.HTTPProvider
71
+ method: POST
72
+ uri: https://polygon-mainnet.g.alchemy.com
73
+ response:
74
+ body:
75
+ string: '{"jsonrpc":"2.0","id":0,"result":{"callGasLimit":"0xd912","paymasterVerificationGasLimit":"0x9b37","paymasterPostOpGasLimit":"0x0","verificationGasLimit":"0xac76","maxPriorityFeePerGas":"0x74c9b09800","paymaster":"0x2cc0c7981D846b9F2a16276556f6e8cb52BfB633","maxFeePerGas":"0x18754a776ce","paymasterData":"0x00000000000000006982d1843b144832bbf805ad7b7faa66b0514bc1f500ae5753543e4d7e90dc70f6f2aa6c3feef96f01d93e16a30da16e4513d2705ca79263d9d9884161a15bbee7d95c151b","preVerificationGas":"0xbd54"}}'
76
+ headers:
77
+ content-length:
78
+ - '495'
79
+ content-type:
80
+ - application/json
81
+ date:
82
+ - Wed, 04 Feb 2026 04:46:36 GMT
83
+ server:
84
+ - istio-envoy
85
+ x-alchemy-trace-id:
86
+ - b63c72e025030afd1c9589531801fc20
87
+ - 944c34cc-2cf6-4015-b321-83e9e4e2c51f
88
+ x-envoy-upstream-service-time:
89
+ - '106'
90
+ status:
91
+ code: 200
92
+ message: OK
93
+ version: 1
@@ -50,7 +50,6 @@ user_operation = aa_bundler.UserOperation(
50
50
  pre_verification_gas=999999,
51
51
  max_fee_per_gas=1000000000,
52
52
  max_priority_fee_per_gas=1000000000,
53
- paymaster_and_data="0x",
54
53
  signature="0x",
55
54
  )
56
55
 
@@ -189,62 +188,63 @@ def test_send_transaction(w3):
189
188
  )
190
189
 
191
190
  def make_request(method, params):
192
- if method == "eth_estimateUserOperationGas":
193
- assert len(params) == 3
194
- assert params[2] == {}
195
- assert params[1] == ENTRYPOINT
196
- assert params[0] == {
197
- "sender": "0xE8B412158c205B0F605e0FC09dCdA27d3F140FE9",
198
- "nonce": "0x0",
199
- "callData": "0xb61d27f60000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa84174000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000007ace242f32208d836a2245df957c08547059bf45ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000", # noqa
200
- "signature": "0xfffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c", # noqa
201
- }
191
+ if method == "alchemy_requestGasAndPaymasterAndData":
192
+ assert len(params) == 1
193
+ assert params[0]["policyId"] == "01234567-89ab-cdef-0123-456789abcdef"
194
+ assert "overrides" in params[0]
202
195
  return {
203
196
  "jsonrpc": "2.0",
204
- "id": 1,
197
+ "id": 2,
205
198
  "result": {
206
- "preVerificationGas": "0xb430",
207
- "callGasLimit": "0xcbb8",
199
+ "callGasLimit": "0xcbb8 ",
200
+ "paymasterVerificationGasLimit": "0x9afa",
201
+ "paymasterPostOpGasLimit": "0x0",
208
202
  "verificationGasLimit": "0x13664",
209
- "paymasterVerificationGasLimit": None,
203
+ "maxPriorityFeePerGas": "0x7ffffffff",
204
+ "paymaster": "0x2cc0c7981D846b9F2a16276556f6e8cb52BfB633",
205
+ "maxFeePerGas": "0x7ffffffff",
206
+ "paymasterData": "0x01234567",
207
+ "preVerificationGas": "0xb430",
210
208
  },
211
209
  }
212
- elif method == "rundler_maxPriorityFeePerGas":
213
- assert len(params) == 0
214
- return {"jsonrpc": "2.0", "id": 1, "result": "0x7ffffffff"}
215
210
  elif method == "eth_sendUserOperation":
216
211
  assert len(params) == 2
217
212
  assert params[1] == ENTRYPOINT
218
213
  assert params[0] == {
219
214
  "sender": "0xE8B412158c205B0F605e0FC09dCdA27d3F140FE9",
220
215
  "nonce": "0x0",
216
+ "paymaster": "0x2cc0c7981D846b9F2a16276556f6e8cb52BfB633",
217
+ "paymasterData": HexBytes("0x01234567"),
218
+ "paymasterPostOpGasLimit": "0x0",
219
+ "paymasterVerificationGasLimit": "0x9afa",
221
220
  "callData": "0xb61d27f60000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa84174000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000007ace242f32208d836a2245df957c08547059bf45ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000", # noqa
222
221
  "callGasLimit": "0xcbb8",
223
222
  "verificationGasLimit": "0x13664",
224
223
  "preVerificationGas": "0xb430",
225
224
  "maxFeePerGas": "0x7ffffffff",
226
225
  "maxPriorityFeePerGas": "0x7ffffffff",
227
- "signature": "0x7980544d044bc1202fed7edec96f2fa795ab8670b439935e6bbb5104e95d84ea32af8bff187913ff7eb2b442baab06d0c300273942e312332659ab0a194bbbe81c", # noqa
226
+ "signature": "0x4656e37ed587521b667b3f02fe079dc0be8600d527bb30824570ee5499f19af37354bbaa140a7e933f8d6d6c5a4ba1a23ffbcf49c43980b1a113947102d7dfe21b", # noqa
228
227
  }
229
228
  return {
230
229
  "jsonrpc": "2.0",
231
230
  "id": 1,
232
231
  "result": "0xa950a17ca1ed83e974fb1aa227360a007cb65f566518af117ffdbb04d8d2d524",
233
232
  }
233
+ else:
234
+ raise ValueError(f"Unexpected method {method} called")
234
235
 
235
236
  bundler = aa_bundler.Bundler(
236
237
  w3,
237
238
  executor_pk=TEST_PRIVATE_KEY,
238
239
  nonce_mode=aa_bundler.NonceMode.FIXED_KEY_LOCAL_NONCE,
239
240
  fixed_nonce_key=0,
241
+ bundler_type="alchemy",
242
+ alchemy_gas_policy_id="01234567-89ab-cdef-0123-456789abcdef",
240
243
  )
241
244
  make_request_mock = MagicMock(side_effect=make_request)
242
- get_base_fee_mock = MagicMock(return_value=0)
243
245
  bundler.bundler.provider.make_request = make_request_mock
244
- bundler.get_base_fee = get_base_fee_mock
245
246
 
246
247
  ret = bundler.send_transaction(tx)
247
- get_base_fee_mock.assert_called_once_with()
248
248
  assert aa_bundler.NONCE_CACHE[0] == 1
249
249
  assert ret == {"userOpHash": "0xa950a17ca1ed83e974fb1aa227360a007cb65f566518af117ffdbb04d8d2d524"}
250
250
 
@@ -284,7 +284,6 @@ def test_random_key_nonces_are_thread_safe():
284
284
 
285
285
  @pytest.mark.vcr
286
286
  def test_build_user_operation(w3):
287
-
288
287
  tx = aa_bundler.Tx(
289
288
  value=0,
290
289
  chain_id=137,
@@ -301,6 +300,8 @@ def test_build_user_operation(w3):
301
300
  fixed_nonce_key=0xAE85C374AE0606ED34D0EE009A9CA43A757A8A46A32451,
302
301
  executor_pk=TEST_PRIVATE_KEY,
303
302
  entrypoint=ENTRYPOINT,
303
+ bundler_type="alchemy",
304
+ alchemy_gas_policy_id="d80ed67a-d8bc-4cd1-90ad-b50e0a58c93e",
304
305
  ).build_user_operation(tx)
305
306
 
306
307
  assert userop.as_dict() == {
@@ -313,15 +314,21 @@ def test_build_user_operation(w3):
313
314
  "ffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000"
314
315
  "00000000000000"
315
316
  ),
316
- "callGasLimit": "0xcbb8",
317
- "maxFeePerGas": "0x89e80ffda",
318
- "maxPriorityFeePerGas": "0x7aef40a00",
317
+ "callGasLimit": "0xd912",
318
+ "maxFeePerGas": "0x18754a776ce",
319
+ "maxPriorityFeePerGas": "0x74c9b09800",
319
320
  "nonce": "0xae85c374ae0606ed34d0ee009a9ca43a757a8a46a324510000000000000000",
320
- "preVerificationGas": "0xb5c8",
321
+ "paymaster": "0x2cc0c7981D846b9F2a16276556f6e8cb52BfB633",
322
+ "paymasterData": HexBytes(
323
+ "0x00000000000000006982d1843b144832bbf805ad7b7faa66b0514bc1f500ae5753543e4d7e90dc70f6f2aa6c3feef96f01d93e16a30da16e4513d2705ca79263d9d9884161a15bbee7d95c151b" # noqa
324
+ ),
325
+ "paymasterPostOpGasLimit": "0x0",
326
+ "paymasterVerificationGasLimit": "0x9b37",
327
+ "preVerificationGas": "0xbd54",
321
328
  "sender": "0xE8B412158c205B0F605e0FC09dCdA27d3F140FE9",
322
329
  "signature": (
323
330
  "0xfffffffffffffffffffffffffffffff00000000000000000000000000000000"
324
331
  "07aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c"
325
332
  ),
326
- "verificationGasLimit": "0x1365b",
333
+ "verificationGasLimit": "0xac76",
327
334
  }
@@ -1,89 +0,0 @@
1
- interactions:
2
- - request:
3
- body: '{"jsonrpc": "2.0", "method": "web3_clientVersion", "params": [], "id":
4
- 0}'
5
- headers:
6
- Content-Length:
7
- - "73"
8
- Content-Type:
9
- - application/json
10
- method: POST
11
- uri: https://polygon-mainnet.g.alchemy.com
12
- response:
13
- body:
14
- string: '{"jsonrpc":"2.0","id":0,"result":"bor/v1.5.0/linux-amd64/go1.22.1"}'
15
- headers:
16
- Content-Type:
17
- - application/json
18
- status:
19
- code: 200
20
- message: OK
21
- - request:
22
- body: '{"jsonrpc": "2.0", "method": "eth_estimateUserOperationGas", "params":
23
- [{"sender": "0xE8B412158c205B0F605e0FC09dCdA27d3F140FE9", "nonce": "0xae85c374ae0606ed34d0ee009a9ca43a757a8a46a324510000000000000000",
24
- "callData": "0xb61d27f60000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa84174000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000007ace242f32208d836a2245df957c08547059bf45ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000",
25
- "signature": "0xfffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c"},
26
- "0x0000000071727De22E5E9d8BAf0edAc6f37da032", {}], "id": 0}'
27
- headers:
28
- Content-Length:
29
- - "885"
30
- Content-Type:
31
- - application/json
32
- method: POST
33
- uri: https://polygon-mainnet.g.alchemy.com
34
- response:
35
- body:
36
- string: '{"jsonrpc":"2.0","id":0,"result":{"preVerificationGas":"0xb5c8","callGasLimit":"0xcbb8","verificationGasLimit":"0x1365b","paymasterVerificationGasLimit":null}}'
37
- headers:
38
- Content-Type:
39
- - application/json
40
- status:
41
- code: 200
42
- message: OK
43
- - request:
44
- body: '{"jsonrpc": "2.0", "method": "rundler_maxPriorityFeePerGas", "params":
45
- [], "id": 1}'
46
- headers:
47
- Content-Length:
48
- - "83"
49
- Content-Type:
50
- - application/json
51
- method: POST
52
- uri: https://polygon-mainnet.g.alchemy.com
53
- response:
54
- body:
55
- string: '{"jsonrpc":"2.0","id":1,"result":"0x7aef40a00"}'
56
- headers:
57
- Content-Length:
58
- - "47"
59
- Content-Type:
60
- - application/json
61
- status:
62
- code: 200
63
- message: OK
64
- - request:
65
- body: '{"jsonrpc": "2.0", "method": "eth_getBlockByNumber", "params": ["latest",
66
- false], "id": 1}'
67
- headers:
68
- Accept:
69
- - "*/*"
70
- Content-Length:
71
- - "90"
72
- Content-Type:
73
- - application/json
74
- User-Agent:
75
- - web3.py/7.3.0/web3.providers.rpc.rpc.HTTPProvider
76
- method: POST
77
- uri: https://polygon-mainnet.g.alchemy.com
78
- response:
79
- body:
80
- string: '{"jsonrpc":"2.0","id":1,"result":{"baseFeePerGas":"0xef8cf5da","difficulty":"0x16","extraData":"0xd78301040183626f7288676f312e32322e37856c696e75780000000000000000f8d380f8d0c0c0c101c0c102c0c0c0c106c108c109c10ac0c0c104c10ec10fc110c111c112c113c114c115c116c117c21116c315190ec3171a12c3150f18c11cc0c0c31e1302c120c121c0c118c11dc122c22625c3271318c128c122c0c0c12ac12dc12ec0c0c130c21e2ec0c2262fc135c136c137c138c139c13ac13bc13cc13dc13ec13fc140c141c142c143c144c145c146c147c133c0c0c0c0c148c14ec14fc150c151c152c153c0c155c156c154c158c0c0c0c127c0c0c15fc159c161c3624824c0c163c0c15dc0c0c169c162c16ac165c0c036fbc1d83393ad7842e0f4e59d6bf40e3739a7537c8f67dd235f03fd567dbc8b532be94f21324dab9fe3bc04433e5d88aad7d5509acd965f18e86ea65e237b0501","gasLimit":"0x1c9c380","gasUsed":"0x11e2679","hash":"0x9812df824fe86ee7666ee52ba40e8a07bd840d179b2355584ee17c4f0b28bfac","logsBloom":"0xa7fbbb7f99f75e978e44ca40c6b732d58b0c834c509119afb9a3062ce3f7e354d33c8aff5435fbbffbc3829bf5056a7f2d7f879ac2da27613e010ba2c77832d4adf4369cf746e5a8438feadeb9facab22e3336ee155c9902dd5b8fed3132af81fcba60d65ec928a1097fc525086fef4e2f95fdc0d9ff9c7dd28fef3258de2a833b536a603be8f5e1019892d7a76c47f0bdf38ecb699cb15ef8872cd67fec1c6d3aed17eb9494333a7873fc78b6ab2fe74b5d381e7aa6179cb41f378baa4177c5fbcdc46be3cf473996232a3e68f6792c7107adeaa608ae11d5f3ff9be997ac4e42ddace1bd66c3cbccc5ffb04a22ab26dae95637930bbc5bc1fccf1cdad4d83d","miner":"0x0000000000000000000000000000000000000000","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","number":"0x3e0dfa3","parentHash":"0xc116078cf08fdc3698450f99c3fb8174b3f963f3ef69940798ecb80685bd5403","receiptsRoot":"0xa9dcec0fbae87f1ba0b6e00e24f1d4cc85e946f79efd09595dcee8adde3c308f","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x14a38","stateRoot":"0x91298e6d8f1f78389a8fa9ffd4fa8faba6df3874ac2378ff81f1b79ab8f2c0ca","timestamp":"0x67502bea","totalDifficulty":"0x49922530","transactions":["0x9467c7880dee353a78ddf750a671c77427959f1419f24721516b064a77e5cb14","0x2aeaee1abd69bcadd2d1409d0c20ddb1ca21e3f8371357d7dd354f2428c2f2cd","0xf52b3c9298195a53a4ac25f299e61b17e75e5f88e29456e47f0fcaf233829ae8","0x5d0892b203171f520ff6f712e0e532214f63d2ccdba02e62b231611ad6775bcc","0x9f02c7acaf92db5663c0d0d3ffbab5046e8691c28042465113c8b7df35ad92af","0x8f3eefed92190625cef38e1dc0068743fb2a36765a69775d0cb00fe191299f3b","0xef8c9786a01b9056d6e523e03f22878370c4181eadf7cc920f62b290c48c46b5","0x028dbcec1869203239ebebd9cdda153f748a89d846821af62f15eb59cbda24bb","0xa2184979376cd003dd3d4136355fa207a13a6c57cb91b369f3a84466148d27ef","0xd2f2c6ac1f5ba4bcca22de71a43b692fe220e63d6c5aa3265e021c5dea2c07ca","0x901a50d3407350cf8a0bc70e508532a718df4010474876b5ffa0a9cebe0a1283","0x6661e2d00576609d85848a9c274c496b31711493664cf754c004ca46c3075a89","0x9ec2e632cc7140d129ad80f04848fdee603596820aef775d4cf8ea5e3c6da4fe","0x08ead36f41411b692b42abf3a1b2ddefc9716fe61ed9fef30062f85ac1d907f2","0xdd52c363257371f554a86190b539c6eedcefa467f3321fece1a8642c441acdaa","0xbc36a622b69157e2e93290b25a2da00a1a871b5c37b69e77466ecfedf1777017","0x93caa9947534ddbdf3cdd632d391b0560725448256f12f9b5a8dfd5711722cdf","0x209292631fd5d359edb537a4c6a71425dfac541d2fdd2c439918038a10ac567a","0xfda41e6a50e7e2690a527927ac63d7ef16272f4421f31c10c6ba081b6d72314e","0xde4e8b79a8f4b694722d9fcf5be8532afbfcbb561cdcef99d54f96a58b8cb8b2","0x446930f11fbe56d3e3ccdc189c450c31051c46ad5eb79642782ff4ce1e454b12","0x0b1cedf3efe3571381fdda301f264e27940782dc51811315c0f98c36aa69f64a","0x8838c302df826f2efd21df59b94791c85a83c5afaa1cf1585016c89396d58ccb","0xc1a692e1da455a7707574361bea76c4c3fc1a249c6807c73c7dfb4f1456ffefa","0xffa5d659f0115253447ebd2544070bc3ff923d0df0ba6efc523ab30dc813177c","0xb7e2176f1aabe0b1a88334f281291d8c2aa2f5bd863b5447822eb06b89643599","0x079509573f1e3b81ef8a382199d7916ddbc637af015fd022e06bbbe3c7c59d36","0x2b86554f06f3885fc070f693899f81f40ab4f57bec426ac5c985aad0c716d569","0x80d703deafdac37b1ec50e14e7112a7260141f8c5118990f1696b129e02f9015","0x2ab499209082ecf9d52c5e777928fe4e250523cc1f36a7e553b9551e0207c85a","0x68ae0a7618c1c361fc457b27e27b6cb25711bf4f52780d83c087784048284640","0x3ef5754e36e395e177277ee213bf31d2e9bfb0b03ec73ee772f9fb145371a224","0x60404a9d0686fb05486af0a7ac1bd4fe2fe7814c170a440516d3b8668d9b1637","0x05911f20485c649e9b8096072b487d3f5b12da42c18f580b2a40f53d130e6b7f","0x079c7e93fd0da0a1b414c23a6130ff49ba45e7fa0b2db5e36ee50f98eba86248","0xeb3e28c8a4885fbf29aa4302e54beba30a652d23de4d0a200fc4aa96d95891df","0x35d89299631753af9d0e9090243638273b04878178253d012071cde1c1acad56","0xc090afb4928cf05560ed88353609ef8600e9c5e2a540c3e11475f669edeabe1c","0xe7d13a119ca701a531f44d64c3eb7196e2595ca872c4e41476451615a1176f95","0x5dd204491b05dce1e3e7e5ad59110eb56f07059b716916b2fa8029f146e20efa","0x9db22f1cddb27d05589479b42936e9b18ef15859b6abf52d16e12148fb90c134","0x2aff8676b986cfea88f89232b82e95854f65eb710786e6bd661e5c90e0c28987","0x8467aa2a85753a7c2fe2b13db1e454eaa226900d18e5a3b64c412a3415857266","0xe5a2df1308395b8ebd8be24e79f080faa3f397c5711615f64e92d22c9c8dc38a","0xe0f6b6a7589407dcd462bd6811b804843994449777995be60ce3f7bba4c33508","0xf34817162b2cf4d3388f0bc2d2a63788648abc83152a696fd732102e1b945dca","0x6c453737ace4db950dc29c620f922f2e0c8f4a90cc63f3a99969530538b394e3","0x1864f6a6114fa42c167ab4262a5628c62f7080542e4dac192f12370e0c70c7e7","0xf0926e427fa6c1c0726ba9ef57a3171282d48d369c1a088a64ce23065960d8a9","0x82084eaa79f267ccee4d1b7598c702dc60b7381ee705940dc89729bb8a402b2a","0xa40ee21e1b478547a5256c9efa96903d032545babd0292ef01531062242d9a88","0x69766eacc25cac03db983b44606226317c039b45052d63d1cd55c4f90aecdaba","0xc8e76268ad97b9f77d72f5698b79fbdc2d280157066153b423030277eedae0d3","0x87c81b17573f30c66e1eafc0e29777750a6f9910f82424ef7eac8356bc56ac27","0x8ec5d3051e6928dc69f285dc38c384abdb0d4d661d722d6f594abb38b89ba1f2","0xad453e2430f1884a36db126b3275612a796fae8feddd25d7bdc801cdd2b63629","0xd8adef0545a76940ffc11a4cca01079c3c8e1674d3074a49ace216a24c27f76c","0xef614fe6ba9ae78eaa996d01282b2edda35387684189eb5f08255b7b1ffbb087","0xbe5e5e695578c35b50acff70a2ba1999a330d080b65a33286eea250d4d0dbf48","0x5adbcc0a227540e5815b57e0c9710c8b864948f544f023b78fd569ac6c3c1f55","0x649e57394caceb1af49e093d4c7be905b51a0e3b89d6553254e97f0e97ca0364","0x749fbd1f138623f0fd4c7b3fb9b70ee891cb854a557107d05f2ee76e4768d49a","0xe6ddf788cab10f89a3d100a97bbaead4a048176f13845bb32413534167056965","0xa660b081401bedd5ea242cc214f356130d1548afa273a416de5e004a81447c07","0x432a7c13e86c21626359e3c452887da87e3a13ae60ef4416b5a06cbb270c8abe","0xa7c6ebe000b8e38dab5d06f0f8692c127f38f9de1aad87f0969d6e4ce4ef9612","0x73092537ea644320bf77393f0903a38005b181559fa06d1b0b9e965a44289a74","0x5dd72e461b83ca26cf13d8e2bbc316306fc73428834060330dde3c89989917f2","0x67a45e16233f812520d50f1aa0590968f56a0c8313c1bd5c19ed31e97e66078e","0x8f0b49330f079d4211e3ec86c02d9b3ec0cc988892842b7ab9da2e609aa0f484","0x45f6e96275911f5af90f0e5e594b2d1a9633b45d140bdac514515d346d6c28ad","0x5d3f1bdc15feeac7cd57b34d61cd033ca8809948b877e1f5187fceda839835fa","0x8532b3cc5edaf2f3fdf3383f080fff6d37f9704652f6252a0928501ec148e097","0x4b05e95f41ffc7f1e4bbbf4aae15a6a9ba4ec362e6895be732e931c7ff1c912e","0x14b2e5c406bab9e3c5ec05847514b55ae838ffb74247816b32475639864549d9","0x9ee4e0aadb2bf327ffc6f2ad147e854770d18769b9e97dac34a47c98acb64b1c","0x5b3d81327c6fa993e01c23eed82bfeb8af7d74389c5c8b7441cd564327cff526","0x718b58b5b24c1246003fb3350cf1990974da6a7bdb4547645d610fab8c4e4aef","0x6a122b47bd207f16253b1112df590cb20440e0f482ef7b761835be3482f933a2","0xe9b0b80b0179fdebcfb872c9b288b22104bfc23d50a37f2f13963c610af2ee6f","0x6b8974a4226e063e0d31f8bd1e644aa38370fed3f1bb7872018fbd7940eab5c8","0x762a8e38b253f4fca380c55038d40a678fd0d5421ae117b24436f6e8d6af2f5b","0x99edb1d86a6a0286875c7fa11d5d86de16650644ec7d788f655db3a76662c1c6","0x5fe2326620141bf79cb5270e03fd5bf6d0021dcd2eb2193259eadffffa7426bf","0x9605cbcc3ed7eb5b94fef3bde07ac737fe2b45da8049075166b3ce32be184c7a","0x73240b4fba4c2ae0632f85e8c8f53931fb8fc83b39d85d29bdfc2c31737cdbc2","0x5dc249897cbec45274c61e1cbee654e99cd612538b788afdc4dc6cbddb903d69","0xf150c25a5e623f34d931b64ab3a0ae2c73655b287dc1b3c328b4945981bfef89","0xa3e78ed6100bdcc973b316914da588f26705e1e0ca1516fef9cbd0e7d6c89333","0xfe2f254fa72723d3e3c87c931a154a30f309000235a703adb4ede0abac9fed5c","0x8e8898b5208755574768f31030e1b15ede1f31d9037177a2a9f30aec3d0461d2","0x1b1eab7319230bd4c17040a2105865875aaf9f4b563ffe5fa0fe26856c1a429c","0x7a706fc8003c49fcd935cf6244de0e8ece1d98afcb6aad90287d13ac3f4014f4","0x9a2c596d2dd56876d9d31ca51bbc0fa6d64fac5372ddac4405cb11bd916de98a","0xb452beb2c34b60e12bbc6bd4a230529257f1300f3b93d8d2bbd01d4efd4214bc","0x597127293efbc838d99f39928ad2a0b5290774fb2fa5fd5e0a5a4be2f4fac56b","0x7ea193cd63b3f45da8c4386af1a93959938591f69848559901204f38adc2ffb2","0xc3dff26f750923b047bb750fa9085d6f16c4997ea441f558210e0fd24f291b89","0x735b165364534e270dead9a4eecbe4334b410551af8884be206cfafc5a5067e6","0x343ee164ae7aaca37ea20abd638bb99197db5d6a8f50d499a2c1d557e0c66ba9","0xbe0c8a138b9ea8735ef2ceaaa3d6449730247d2013d16f91802c0490b22de6ae","0xd173a5684a6b47cf7e46b9fa324dfe79661284076d248acf656a9f6693d69fa0","0x42ff00b4fca45c51bdad3fb298ff8826a3f0a0c5ef36223aa1a2a39bca008422","0x0ba664b6149d498663110480d568ec62cb1dec2f748670a15a08babfc0380821","0xde32b9a10bca6b355f54282972057cf453109bd1b3d47c910fb5e8d16ec31038","0x1d11a0089905d9e563868cd023903e38404a6a0f6b9fbe43cb55ea102cd2c273","0x6647a553748e8484ff4cb8e7826dd62dd9f177107d4d1d5bec5fbef084c7735f","0x27302f702eb8553410d750824a5e327cfd7577cfa5719f723fbcb63fa27cba6d","0x15aed6e395006bf128c372dec290183b27a5496b5201e449bf8c1a93ee04df98","0x3039af717e97c777a7e8a497791ea88cb9de9058ccf69fba583551e190557b19","0xd842413ab6d7ddfbfeae4b06aeebfd87804291a087559018bbd84a8ffcac2417","0x89a190f819544c65cb94617009757c6d9221cdbf8554548f8fc3d534e06c53af"],"transactionsRoot":"0xb1785109127e5a11ae4dd1cca6150f6581cd43b9eae3654408643cb51f3b4060","uncles":[]}}'
81
- headers:
82
- Content-Length:
83
- - "5564"
84
- Content-Type:
85
- - application/json
86
- status:
87
- code: 200
88
- message: OK
89
- version: 1
File without changes
File without changes
File without changes
File without changes