@@ -33,9 +33,12 @@ use zksync_web3_decl::{
33
33
} ;
34
34
use zksync_web3_decl:: { namespaces:: EthNamespaceClient , types:: Index } ;
35
35
36
- use crate :: system_contracts;
37
36
use crate :: { cache:: CacheConfig , node:: TEST_NODE_NETWORK_ID } ;
38
37
use crate :: { deps:: InMemoryStorage , http_fork_source:: HttpForkSource } ;
38
+ use crate :: {
39
+ node:: { DEFAULT_ESTIMATE_GAS_PRICE_SCALE_FACTOR , DEFAULT_ESTIMATE_GAS_SCALE_FACTOR } ,
40
+ system_contracts,
41
+ } ;
39
42
40
43
pub fn block_on < F : Future + Send + ' static > ( future : F ) -> F :: Output
41
44
where
52
55
. unwrap ( )
53
56
}
54
57
58
+ /// The possible networks to fork from.
59
+ #[ derive( Debug , Clone ) ]
60
+ pub enum ForkNetwork {
61
+ Mainnet ,
62
+ SepoliaTestnet ,
63
+ GoerliTestnet ,
64
+ Other ( String ) ,
65
+ }
66
+
67
+ impl ForkNetwork {
68
+ /// Return the URL for the underlying fork source.
69
+ pub fn to_url ( & self ) -> & str {
70
+ match self {
71
+ ForkNetwork :: Mainnet => "https://mainnet.era.zksync.io:443" ,
72
+ ForkNetwork :: SepoliaTestnet => "https://sepolia.era.zksync.dev:443" ,
73
+ ForkNetwork :: GoerliTestnet => "https://testnet.era.zksync.dev:443" ,
74
+ ForkNetwork :: Other ( url) => url,
75
+ }
76
+ }
77
+
78
+ /// Returns the local gas scale factors currently in use by the upstream network.
79
+ pub fn local_gas_scale_factors ( & self ) -> ( f64 , f32 ) {
80
+ match self {
81
+ ForkNetwork :: Mainnet => ( 1.5 , 1.2 ) ,
82
+ ForkNetwork :: SepoliaTestnet => ( 2.0 , 1.2 ) ,
83
+ ForkNetwork :: GoerliTestnet => ( 1.2 , 1.2 ) ,
84
+ ForkNetwork :: Other ( _) => (
85
+ DEFAULT_ESTIMATE_GAS_PRICE_SCALE_FACTOR ,
86
+ DEFAULT_ESTIMATE_GAS_SCALE_FACTOR ,
87
+ ) ,
88
+ }
89
+ }
90
+ }
91
+
55
92
/// In memory storage, that allows 'forking' from other network.
56
93
/// If forking is enabled, it reads missing data from remote location.
57
94
/// S - is a struct that is used for source of the fork.
@@ -100,77 +137,77 @@ impl<S: ForkSource> ForkStorage<S> {
100
137
}
101
138
}
102
139
103
- fn read_value_internal ( & self , key : & StorageKey ) -> zksync_types:: StorageValue {
140
+ pub fn read_value_internal (
141
+ & self ,
142
+ key : & StorageKey ,
143
+ ) -> eyre:: Result < zksync_types:: StorageValue > {
104
144
let mut mutator = self . inner . write ( ) . unwrap ( ) ;
105
145
let local_storage = mutator. raw_storage . read_value ( key) ;
106
146
107
147
if let Some ( fork) = & mutator. fork {
108
148
if !H256 :: is_zero ( & local_storage) {
109
- return local_storage;
149
+ return Ok ( local_storage) ;
110
150
}
111
151
112
152
if let Some ( value) = mutator. value_read_cache . get ( key) {
113
- return * value;
153
+ return Ok ( * value) ;
114
154
}
115
155
let l2_miniblock = fork. l2_miniblock ;
116
156
let key_ = * key;
117
157
118
- let result = fork
119
- . fork_source
120
- . get_storage_at (
121
- * key_. account ( ) . address ( ) ,
122
- h256_to_u256 ( * key_. key ( ) ) ,
123
- Some ( BlockIdVariant :: BlockNumber ( BlockNumber :: Number ( U64 :: from (
124
- l2_miniblock,
125
- ) ) ) ) ,
126
- )
127
- . unwrap ( ) ;
158
+ let result = fork. fork_source . get_storage_at (
159
+ * key_. account ( ) . address ( ) ,
160
+ h256_to_u256 ( * key_. key ( ) ) ,
161
+ Some ( BlockIdVariant :: BlockNumber ( BlockNumber :: Number ( U64 :: from (
162
+ l2_miniblock,
163
+ ) ) ) ) ,
164
+ ) ?;
128
165
129
166
mutator. value_read_cache . insert ( * key, result) ;
130
- result
167
+ Ok ( result)
131
168
} else {
132
- local_storage
169
+ Ok ( local_storage)
133
170
}
134
171
}
135
172
136
- fn load_factory_dep_internal ( & self , hash : H256 ) -> Option < Vec < u8 > > {
173
+ pub fn load_factory_dep_internal ( & self , hash : H256 ) -> eyre :: Result < Option < Vec < u8 > > > {
137
174
let mut mutator = self . inner . write ( ) . unwrap ( ) ;
138
175
let local_storage = mutator. raw_storage . load_factory_dep ( hash) ;
139
176
if let Some ( fork) = & mutator. fork {
140
177
if local_storage. is_some ( ) {
141
- return local_storage;
178
+ return Ok ( local_storage) ;
142
179
}
143
180
if let Some ( value) = mutator. factory_dep_cache . get ( & hash) {
144
- return value. clone ( ) ;
181
+ return Ok ( value. clone ( ) ) ;
145
182
}
146
183
147
- let result = fork. fork_source . get_bytecode_by_hash ( hash) . unwrap ( ) ;
184
+ let result = fork. fork_source . get_bytecode_by_hash ( hash) ? ;
148
185
mutator. factory_dep_cache . insert ( hash, result. clone ( ) ) ;
149
- result
186
+ Ok ( result)
150
187
} else {
151
- local_storage
188
+ Ok ( local_storage)
152
189
}
153
190
}
154
191
155
192
/// Check if this is the first time when we're ever writing to this key.
156
193
/// This has impact on amount of pubdata that we have to spend for the write.
157
- fn is_write_initial_internal ( & self , key : & StorageKey ) -> bool {
194
+ pub fn is_write_initial_internal ( & self , key : & StorageKey ) -> eyre :: Result < bool > {
158
195
// Currently we don't have the zks API to return us the information on whether a given
159
196
// key was written to before a given block.
160
197
// This means, we have to depend on the following heuristic: we'll read the value of the slot.
161
198
// - if value != 0 -> this means that the slot was written to in the past (so we can return intitial_write = false)
162
199
// - but if the value = 0 - there is a chance, that slot was written to in the past - and later was reset.
163
200
// but unfortunately we cannot detect that with the current zks api, so we'll attempt to do it
164
201
// only on local storage.
165
- let value = self . read_value_internal ( key) ;
202
+ let value = self . read_value_internal ( key) ? ;
166
203
if value != H256 :: zero ( ) {
167
- return false ;
204
+ return Ok ( false ) ;
168
205
}
169
206
170
207
// If value was 0, there is still a chance, that the slot was written to in the past - and only now set to 0.
171
208
// We unfortunately don't have the API to check it on the fork, but we can at least try to check it on local storage.
172
209
let mut mutator = self . inner . write ( ) . unwrap ( ) ;
173
- mutator. raw_storage . is_write_initial ( key)
210
+ Ok ( mutator. raw_storage . is_write_initial ( key) )
174
211
}
175
212
176
213
/// Retrieves the enumeration index for a given `key`.
@@ -182,15 +219,15 @@ impl<S: ForkSource> ForkStorage<S> {
182
219
183
220
impl < S : std:: fmt:: Debug + ForkSource > ReadStorage for ForkStorage < S > {
184
221
fn is_write_initial ( & mut self , key : & StorageKey ) -> bool {
185
- self . is_write_initial_internal ( key)
222
+ self . is_write_initial_internal ( key) . unwrap ( )
186
223
}
187
224
188
225
fn load_factory_dep ( & mut self , hash : H256 ) -> Option < Vec < u8 > > {
189
- self . load_factory_dep_internal ( hash)
226
+ self . load_factory_dep_internal ( hash) . unwrap ( )
190
227
}
191
228
192
229
fn read_value ( & mut self , key : & StorageKey ) -> zksync_types:: StorageValue {
193
- self . read_value_internal ( key)
230
+ self . read_value_internal ( key) . unwrap ( )
194
231
}
195
232
196
233
fn get_enumeration_index ( & mut self , key : & StorageKey ) -> Option < u64 > {
@@ -200,15 +237,15 @@ impl<S: std::fmt::Debug + ForkSource> ReadStorage for ForkStorage<S> {
200
237
201
238
impl < S : std:: fmt:: Debug + ForkSource > ReadStorage for & ForkStorage < S > {
202
239
fn read_value ( & mut self , key : & StorageKey ) -> zksync_types:: StorageValue {
203
- self . read_value_internal ( key)
240
+ self . read_value_internal ( key) . unwrap ( )
204
241
}
205
242
206
243
fn is_write_initial ( & mut self , key : & StorageKey ) -> bool {
207
- self . is_write_initial_internal ( key)
244
+ self . is_write_initial_internal ( key) . unwrap ( )
208
245
}
209
246
210
247
fn load_factory_dep ( & mut self , hash : H256 ) -> Option < Vec < u8 > > {
211
- self . load_factory_dep_internal ( hash)
248
+ self . load_factory_dep_internal ( hash) . unwrap ( )
212
249
}
213
250
214
251
fn get_enumeration_index ( & mut self , key : & StorageKey ) -> Option < u64 > {
@@ -321,6 +358,10 @@ pub struct ForkDetails<S> {
321
358
pub overwrite_chain_id : Option < L2ChainId > ,
322
359
pub l1_gas_price : u64 ,
323
360
pub l2_fair_gas_price : u64 ,
361
+ /// L1 Gas Price Scale Factor for gas estimation.
362
+ pub estimate_gas_price_scale_factor : f64 ,
363
+ /// The factor by which to scale the gasLimit.
364
+ pub estimate_gas_scale_factor : f32 ,
324
365
}
325
366
326
367
const SUPPORTED_VERSIONS : & [ ProtocolVersionId ] = & [
@@ -356,13 +397,14 @@ pub fn supported_versions_to_string() -> String {
356
397
}
357
398
358
399
impl ForkDetails < HttpForkSource > {
359
- pub async fn from_url_and_miniblock_and_chain (
360
- url : & str ,
400
+ pub async fn from_network_and_miniblock_and_chain (
401
+ network : ForkNetwork ,
361
402
client : Client < L2 > ,
362
403
miniblock : u64 ,
363
404
chain_id : Option < L2ChainId > ,
364
405
cache_config : CacheConfig ,
365
406
) -> Self {
407
+ let url = network. to_url ( ) ;
366
408
let block_details = client
367
409
. get_block_details ( L2BlockNumber ( miniblock as u32 ) )
368
410
. await
@@ -402,6 +444,8 @@ impl ForkDetails<HttpForkSource> {
402
444
) ;
403
445
}
404
446
447
+ let ( estimate_gas_price_scale_factor, estimate_gas_scale_factor) =
448
+ network. local_gas_scale_factors ( ) ;
405
449
ForkDetails {
406
450
fork_source : HttpForkSource :: new ( url. to_owned ( ) , cache_config) ,
407
451
l1_block : l1_batch_number,
@@ -412,23 +456,32 @@ impl ForkDetails<HttpForkSource> {
412
456
overwrite_chain_id : chain_id,
413
457
l1_gas_price : block_details. base . l1_gas_price ,
414
458
l2_fair_gas_price : block_details. base . l2_fair_gas_price ,
459
+ estimate_gas_price_scale_factor,
460
+ estimate_gas_scale_factor,
415
461
}
416
462
}
417
463
/// Create a fork from a given network at a given height.
418
464
pub async fn from_network ( fork : & str , fork_at : Option < u64 > , cache_config : CacheConfig ) -> Self {
419
- let ( url , client) = Self :: fork_to_url_and_client ( fork) ;
465
+ let ( network , client) = Self :: fork_network_and_client ( fork) ;
420
466
let l2_miniblock = if let Some ( fork_at) = fork_at {
421
467
fork_at
422
468
} else {
423
469
client. get_block_number ( ) . await . unwrap ( ) . as_u64 ( )
424
470
} ;
425
- Self :: from_url_and_miniblock_and_chain ( url, client, l2_miniblock, None , cache_config) . await
471
+ Self :: from_network_and_miniblock_and_chain (
472
+ network,
473
+ client,
474
+ l2_miniblock,
475
+ None ,
476
+ cache_config,
477
+ )
478
+ . await
426
479
}
427
480
428
481
/// Create a fork from a given network, at a height BEFORE a transaction.
429
482
/// This will allow us to apply this transaction locally on top of this fork.
430
483
pub async fn from_network_tx ( fork : & str , tx : H256 , cache_config : CacheConfig ) -> Self {
431
- let ( url , client) = Self :: fork_to_url_and_client ( fork) ;
484
+ let ( network , client) = Self :: fork_network_and_client ( fork) ;
432
485
let tx_details = client. get_transaction_by_hash ( tx) . await . unwrap ( ) . unwrap ( ) ;
433
486
let overwrite_chain_id = Some (
434
487
L2ChainId :: try_from ( tx_details. chain_id . as_u64 ( ) ) . unwrap_or_else ( |err| {
@@ -439,8 +492,8 @@ impl ForkDetails<HttpForkSource> {
439
492
// We have to sync to the one-miniblock before the one where transaction is.
440
493
let l2_miniblock = miniblock_number. saturating_sub ( 1 ) as u64 ;
441
494
442
- Self :: from_url_and_miniblock_and_chain (
443
- url ,
495
+ Self :: from_network_and_miniblock_and_chain (
496
+ network ,
444
497
client,
445
498
l2_miniblock,
446
499
overwrite_chain_id,
@@ -451,22 +504,23 @@ impl ForkDetails<HttpForkSource> {
451
504
}
452
505
453
506
impl < S : ForkSource > ForkDetails < S > {
454
- /// Return URL and HTTP client for a given fork name.
455
- pub fn fork_to_url_and_client ( fork : & str ) -> ( & str , Client < L2 > ) {
456
- let url = match fork {
457
- "mainnet" => "https://mainnet.era.zksync.io:443" ,
458
- "sepolia-testnet" => "https://sepolia.era.zksync.dev:443" ,
459
- "goerli-testnet" => "https://testnet.era.zksync.dev:443" ,
460
- _ => fork,
507
+ /// Return [`ForkNetwork`] and HTTP client for a given fork name.
508
+ pub fn fork_network_and_client ( fork : & str ) -> ( ForkNetwork , Client < L2 > ) {
509
+ let network = match fork {
510
+ "mainnet" => ForkNetwork :: Mainnet ,
511
+ "sepolia-testnet" => ForkNetwork :: SepoliaTestnet ,
512
+ "goerli-testnet" => ForkNetwork :: GoerliTestnet ,
513
+ _ => ForkNetwork :: Other ( fork. to_string ( ) ) ,
461
514
} ;
462
515
516
+ let url = network. to_url ( ) ;
463
517
let parsed_url = SensitiveUrl :: from_str ( url)
464
518
. unwrap_or_else ( |_| panic ! ( "Unable to parse client URL: {}" , & url) ) ;
465
519
let client = Client :: http ( parsed_url)
466
520
. unwrap_or_else ( |_| panic ! ( "Unable to create a client for fork: {}" , & url) )
467
521
. build ( ) ;
468
522
469
- ( url , client)
523
+ ( network , client)
470
524
}
471
525
472
526
/// Returns transactions that are in the same L2 miniblock as replay_tx, but were executed before it.
@@ -508,7 +562,14 @@ mod tests {
508
562
use zksync_state:: ReadStorage ;
509
563
use zksync_types:: { api:: TransactionVariant , StorageKey } ;
510
564
511
- use crate :: { deps:: InMemoryStorage , node:: DEFAULT_L2_GAS_PRICE , system_contracts, testing} ;
565
+ use crate :: {
566
+ deps:: InMemoryStorage ,
567
+ node:: {
568
+ DEFAULT_ESTIMATE_GAS_PRICE_SCALE_FACTOR , DEFAULT_ESTIMATE_GAS_SCALE_FACTOR ,
569
+ DEFAULT_L2_GAS_PRICE ,
570
+ } ,
571
+ system_contracts, testing,
572
+ } ;
512
573
513
574
use super :: { ForkDetails , ForkStorage } ;
514
575
@@ -538,6 +599,8 @@ mod tests {
538
599
overwrite_chain_id : None ,
539
600
l1_gas_price : 100 ,
540
601
l2_fair_gas_price : DEFAULT_L2_GAS_PRICE ,
602
+ estimate_gas_price_scale_factor : DEFAULT_ESTIMATE_GAS_PRICE_SCALE_FACTOR ,
603
+ estimate_gas_scale_factor : DEFAULT_ESTIMATE_GAS_SCALE_FACTOR ,
541
604
} ;
542
605
543
606
let mut fork_storage = ForkStorage :: new ( Some ( fork_details) , & options) ;
0 commit comments