3
3
from typing import Optional
4
4
5
5
import eth_abi
6
- import eth_utils
7
- import rlp
8
6
from eth_utils import to_bytes
9
7
from eth_utils .abi import get_abi_output_types , get_abi_input_types
10
8
from web3 .contract .contract import ContractFunction , ContractConstructor
11
9
from web3 .exceptions import ContractLogicError
10
+ from web3 .types import StateOverride
12
11
13
- from IceCreamSwapWeb3 import Web3Advanced
12
+ from . AddressCalculator import calculate_create_address
14
13
from .FastChecksumAddress import to_checksum_address
14
+ from .Web3Advanced import Web3Advanced
15
15
16
16
# load multicall abi
17
17
with files ("IceCreamSwapWeb3" ).joinpath ("./abi/Multicall.abi" ).open ('r' ) as f :
@@ -54,7 +54,7 @@ def __init__(
54
54
abi = MULTICALL_ABI ,
55
55
address = to_checksum_address (self .MULTICALL_DEPLOYMENTS [self .chain_id ])
56
56
)
57
- self .undeployed_contract_address = self . calculate_create_address (sender = self .multicall .address , nonce = 1 )
57
+ self .undeployed_contract_address = calculate_create_address (sender = self .multicall .address , nonce = 1 )
58
58
else :
59
59
self .multicall = self .w3 .eth .contract (abi = UNDEPLOYED_MULTICALL_ABI , bytecode = UNDEPLOYED_MULTICALL_BYTECODE )
60
60
self .undeployed_contract_address = self .calculate_expected_contract_address (sender = self .CALLER_ADDRESS , nonce = 0 )
@@ -75,30 +75,53 @@ def add_undeployed_contract_call(self, contract_func: ContractFunction):
75
75
contract_func .address = 0 # self.undeployed_contract_address
76
76
self .calls .append (contract_func )
77
77
78
- def call (self , use_revert : Optional [bool ] = None , batch_size : int = 1_000 ):
79
- results , _ = self .call_with_gas (use_revert = use_revert , batch_size = batch_size )
78
+ def call (
79
+ self ,
80
+ use_revert : Optional [bool ] = None ,
81
+ batch_size : int = 1_000 ,
82
+ state_override : Optional [StateOverride ] = None
83
+ ):
84
+ results , _ = self .call_with_gas (
85
+ use_revert = use_revert ,
86
+ batch_size = batch_size ,
87
+ state_override = state_override
88
+ )
80
89
return results
81
90
82
- def call_with_gas (self , use_revert : Optional [bool ] = None , batch_size : int = 1_000 ):
91
+ def call_with_gas (
92
+ self ,
93
+ use_revert : Optional [bool ] = None ,
94
+ batch_size : int = 1_000 ,
95
+ state_override : Optional [StateOverride ] = None
96
+ ):
97
+ if state_override is not None :
98
+ assert self .w3 .overwrites_available
83
99
if use_revert is None :
84
100
use_revert = self .w3 .revert_reason_available
85
101
86
102
calls = self .calls
87
103
calls_with_calldata = self .add_calls_calldata (calls )
88
104
89
- return self ._inner_call (use_revert = use_revert , calls_with_calldata = calls_with_calldata , batch_size = batch_size )
105
+ return self ._inner_call (
106
+ use_revert = use_revert ,
107
+ calls_with_calldata = calls_with_calldata ,
108
+ batch_size = batch_size ,
109
+ state_override = state_override
110
+ )
90
111
91
112
def _inner_call (
92
113
self ,
93
114
use_revert : bool ,
94
115
calls_with_calldata : list [tuple [ContractFunction , bytes ]],
95
- batch_size : int
116
+ batch_size : int ,
117
+ state_override : Optional [StateOverride ] = None
96
118
) -> tuple [list [Exception | tuple [any , ...]], list [int ]]:
97
119
if len (calls_with_calldata ) == 0 :
98
120
return [], []
99
121
kwargs = dict (
100
122
use_revert = use_revert ,
101
123
batch_size = batch_size ,
124
+ state_override = state_override ,
102
125
)
103
126
# make sure calls are not bigger than batch_size
104
127
if len (calls_with_calldata ) > batch_size :
@@ -128,15 +151,17 @@ def _inner_call(
128
151
raw_returns , gas_usages = self ._call_multicall (
129
152
multicall_call = multicall_call ,
130
153
use_revert = use_revert ,
131
- retry = False
154
+ retry = False ,
155
+ state_override = state_override
132
156
)
133
157
except Exception as e :
134
158
if len (calls_with_calldata ) == 1 :
135
159
try :
136
160
raw_returns , gas_usages = self ._call_multicall (
137
161
multicall_call = multicall_call ,
138
162
use_revert = use_revert ,
139
- retry = True
163
+ retry = True ,
164
+ state_override = state_override
140
165
)
141
166
except Exception as e :
142
167
raw_returns = [e ]
@@ -161,19 +186,10 @@ def _inner_call(
161
186
162
187
@staticmethod
163
188
def calculate_expected_contract_address (sender : str , nonce : int ):
164
- undeployed_contract_runner_address = MultiCall . calculate_create_address (sender = sender , nonce = nonce )
165
- contract_address = MultiCall . calculate_create_address (sender = undeployed_contract_runner_address , nonce = 1 )
189
+ undeployed_contract_runner_address = calculate_create_address (sender = sender , nonce = nonce )
190
+ contract_address = calculate_create_address (sender = undeployed_contract_runner_address , nonce = 1 )
166
191
return contract_address
167
192
168
- @staticmethod
169
- def calculate_create_address (sender : str , nonce : int ) -> str :
170
- assert len (sender ) == 42
171
- sender_bytes = to_bytes (hexstr = sender )
172
- raw = rlp .encode ([sender_bytes , nonce ])
173
- h = eth_utils .keccak (raw )
174
- address_bytes = h [12 :]
175
- return eth_utils .to_checksum_address (address_bytes )
176
-
177
193
@staticmethod
178
194
def add_calls_calldata (calls : list [ContractFunction ]) -> list [tuple [ContractFunction , bytes ]]:
179
195
calls_with_calldata = []
@@ -340,7 +356,8 @@ def _call_multicall(
340
356
self ,
341
357
multicall_call : ContractConstructor | ContractFunction ,
342
358
use_revert : bool ,
343
- retry : bool = False
359
+ retry : bool = False ,
360
+ state_override : Optional [StateOverride ] = None
344
361
):
345
362
# call transaction
346
363
try :
@@ -350,7 +367,7 @@ def _call_multicall(
350
367
"nonce" : 0 ,
351
368
"data" : multicall_call .data_in_transaction ,
352
369
"no_retry" : not retry ,
353
- })
370
+ }, state_override = state_override )
354
371
else :
355
372
assert isinstance (multicall_call , ContractFunction )
356
373
# manually encoding and decoding call because web3.py is sooooo slow...
@@ -369,7 +386,7 @@ def _call_multicall(
369
386
"nonce" : 0 ,
370
387
"data" : calldata ,
371
388
"no_retry" : not retry ,
372
- })
389
+ }, state_override = state_override )
373
390
_ , multicall_result = eth_abi .decode (get_abi_output_types (multicall_call .abi ), raw_response )
374
391
375
392
if len (multicall_result ) > 0 and self .undeployed_contract_constructor is not None :
@@ -416,6 +433,8 @@ def main(
416
433
node_url = "https://rpc-core.icecreamswap.com" ,
417
434
usdt_address = to_checksum_address ("0x900101d06A7426441Ae63e9AB3B9b0F63Be145F1" ),
418
435
):
436
+ from IceCreamSwapWeb3 import Web3Advanced
437
+
419
438
w3 = Web3Advanced (node_url = node_url )
420
439
421
440
with files ("IceCreamSwapWeb3" ).joinpath ("./abi/Counter.abi" ).open ('r' ) as f :
0 commit comments