@@ -591,6 +591,20 @@ impl<LoggerErrorT: Debug, TimerT: Clone + TimeSinceEpoch> ProviderData<LoggerErr
591
591
self . blockchain . chain_id ( )
592
592
}
593
593
594
+ pub fn chain_id_at_block_spec (
595
+ & self ,
596
+ block_spec : & BlockSpec ,
597
+ ) -> Result < u64 , ProviderError < LoggerErrorT > > {
598
+ let block_number = self . block_number_by_block_spec ( block_spec) ?;
599
+
600
+ let chain_id = if let Some ( block_number) = block_number {
601
+ self . chain_id_at_block_number ( block_number, block_spec) ?
602
+ } else {
603
+ self . blockchain . chain_id ( )
604
+ } ;
605
+
606
+ Ok ( chain_id)
607
+ }
594
608
pub fn coinbase ( & self ) -> Address {
595
609
self . beneficiary
596
610
}
@@ -607,9 +621,8 @@ impl<LoggerErrorT: Debug, TimerT: Clone + TimeSinceEpoch> ProviderData<LoggerErr
607
621
. ok_or_else ( || ProviderError :: InvalidTransactionHash ( * transaction_hash) ) ?;
608
622
609
623
let header = block. header ( ) ;
610
- let block_spec = Some ( BlockSpec :: Number ( header. number ) ) ;
611
624
612
- let cfg_env = self . create_evm_config ( block_spec . as_ref ( ) ) ?;
625
+ let cfg_env = self . create_evm_config_at_block_spec ( & BlockSpec :: Number ( header . number ) ) ?;
613
626
614
627
let transactions = block. transactions ( ) . to_vec ( ) ;
615
628
@@ -659,7 +672,7 @@ impl<LoggerErrorT: Debug, TimerT: Clone + TimeSinceEpoch> ProviderData<LoggerErr
659
672
block_spec : & BlockSpec ,
660
673
trace_config : DebugTraceConfig ,
661
674
) -> Result < DebugTraceResultWithTraces , ProviderError < LoggerErrorT > > {
662
- let cfg_env = self . create_evm_config ( Some ( block_spec) ) ?;
675
+ let cfg_env = self . create_evm_config_at_block_spec ( block_spec) ?;
663
676
664
677
let tx_env: TxEnv = transaction. into ( ) ;
665
678
@@ -691,7 +704,7 @@ impl<LoggerErrorT: Debug, TimerT: Clone + TimeSinceEpoch> ProviderData<LoggerErr
691
704
transaction : transaction:: Signed ,
692
705
block_spec : & BlockSpec ,
693
706
) -> Result < EstimateGasResult , ProviderError < LoggerErrorT > > {
694
- let cfg_env = self . create_evm_config ( Some ( block_spec) ) ?;
707
+ let cfg_env = self . create_evm_config_at_block_spec ( block_spec) ?;
695
708
// Minimum gas cost that is required for transaction to be included in
696
709
// a block
697
710
let minimum_cost = transaction:: initial_cost ( & transaction, self . spec_id ( ) ) ;
@@ -1422,7 +1435,7 @@ impl<LoggerErrorT: Debug, TimerT: Clone + TimeSinceEpoch> ProviderData<LoggerErr
1422
1435
block_spec : & BlockSpec ,
1423
1436
state_overrides : & StateOverrides ,
1424
1437
) -> Result < CallResult , ProviderError < LoggerErrorT > > {
1425
- let cfg_env = self . create_evm_config ( Some ( block_spec) ) ?;
1438
+ let cfg_env = self . create_evm_config_at_block_spec ( block_spec) ?;
1426
1439
let tx_env = transaction. into ( ) ;
1427
1440
1428
1441
let mut debugger = Debugger :: with_mocker (
@@ -1909,26 +1922,32 @@ impl<LoggerErrorT: Debug, TimerT: Clone + TimeSinceEpoch> ProviderData<LoggerErr
1909
1922
Ok ( transaction_hash)
1910
1923
}
1911
1924
1912
- /// Creates a configuration, taking into the hardfork at the provided
1913
- /// `BlockSpec`. If none is provided, assumes the hardfork for newly
1914
- /// mined blocks.
1925
+ /// Wrapper over `Blockchain::chain_id_at_block_number` that handles error
1926
+ /// conversion.
1927
+ fn chain_id_at_block_number (
1928
+ & self ,
1929
+ block_number : u64 ,
1930
+ block_spec : & BlockSpec ,
1931
+ ) -> Result < u64 , ProviderError < LoggerErrorT > > {
1932
+ self . blockchain
1933
+ . chain_id_at_block_number ( block_number)
1934
+ . map_err ( |err| match err {
1935
+ BlockchainError :: UnknownBlockNumber => ProviderError :: InvalidBlockNumberOrHash {
1936
+ block_spec : block_spec. clone ( ) ,
1937
+ latest_block_number : self . blockchain . last_block_number ( ) ,
1938
+ } ,
1939
+ _ => ProviderError :: Blockchain ( err) ,
1940
+ } )
1941
+ }
1942
+
1943
+ /// Creates an EVM configuration with the provided hardfork and chain id
1915
1944
fn create_evm_config (
1916
1945
& self ,
1917
- block_spec : Option < & BlockSpec > ,
1946
+ spec_id : SpecId ,
1947
+ chain_id : u64 ,
1918
1948
) -> Result < CfgEnvWithHandlerCfg , ProviderError < LoggerErrorT > > {
1919
- let block_number = block_spec
1920
- . map ( |block_spec| self . block_number_by_block_spec ( block_spec) )
1921
- . transpose ( ) ?
1922
- . flatten ( ) ;
1923
-
1924
- let spec_id = if let Some ( block_number) = block_number {
1925
- self . blockchain . spec_at_block_number ( block_number) ?
1926
- } else {
1927
- self . blockchain . spec_id ( )
1928
- } ;
1929
-
1930
1949
let mut cfg_env = CfgEnv :: default ( ) ;
1931
- cfg_env. chain_id = self . blockchain . chain_id ( ) ;
1950
+ cfg_env. chain_id = chain_id;
1932
1951
cfg_env. limit_contract_code_size = if self . allow_unlimited_contract_size {
1933
1952
Some ( usize:: MAX )
1934
1953
} else {
@@ -1939,6 +1958,29 @@ impl<LoggerErrorT: Debug, TimerT: Clone + TimeSinceEpoch> ProviderData<LoggerErr
1939
1958
Ok ( CfgEnvWithHandlerCfg :: new_with_spec_id ( cfg_env, spec_id) )
1940
1959
}
1941
1960
1961
+ /// Creates a configuration, taking into the hardfork and chain id at the
1962
+ /// provided `BlockSpec`.
1963
+ fn create_evm_config_at_block_spec (
1964
+ & self ,
1965
+ block_spec : & BlockSpec ,
1966
+ ) -> Result < CfgEnvWithHandlerCfg , ProviderError < LoggerErrorT > > {
1967
+ let block_number = self . block_number_by_block_spec ( block_spec) ?;
1968
+
1969
+ let spec_id = if let Some ( block_number) = block_number {
1970
+ self . spec_at_block_number ( block_number, block_spec) ?
1971
+ } else {
1972
+ self . blockchain . spec_id ( )
1973
+ } ;
1974
+
1975
+ let chain_id = if let Some ( block_number) = block_number {
1976
+ self . chain_id_at_block_number ( block_number, block_spec) ?
1977
+ } else {
1978
+ self . blockchain . chain_id ( )
1979
+ } ;
1980
+
1981
+ self . create_evm_config ( spec_id, chain_id)
1982
+ }
1983
+
1942
1984
fn execute_in_block_context < T > (
1943
1985
& mut self ,
1944
1986
block_spec : Option < & BlockSpec > ,
@@ -1995,7 +2037,8 @@ impl<LoggerErrorT: Debug, TimerT: Clone + TimeSinceEpoch> ProviderData<LoggerErr
1995
2037
options. beneficiary = Some ( options. beneficiary . unwrap_or ( self . beneficiary ) ) ;
1996
2038
options. gas_limit = Some ( options. gas_limit . unwrap_or_else ( || self . block_gas_limit ( ) ) ) ;
1997
2039
1998
- let evm_config = self . create_evm_config ( None ) ?;
2040
+ let evm_config =
2041
+ self . create_evm_config ( self . blockchain . spec_id ( ) , self . blockchain . chain_id ( ) ) ?;
1999
2042
2000
2043
if options. mix_hash . is_none ( ) && evm_config. handler_cfg . spec_id >= SpecId :: MERGE {
2001
2044
options. mix_hash = Some ( self . prev_randao_generator . next_value ( ) ) ;
@@ -2228,6 +2271,24 @@ impl<LoggerErrorT: Debug, TimerT: Clone + TimeSinceEpoch> ProviderData<LoggerErr
2228
2271
}
2229
2272
}
2230
2273
2274
+ /// Wrapper over `Blockchain::spec_at_block_number` that handles error
2275
+ /// conversion.
2276
+ fn spec_at_block_number (
2277
+ & self ,
2278
+ block_number : u64 ,
2279
+ block_spec : & BlockSpec ,
2280
+ ) -> Result < SpecId , ProviderError < LoggerErrorT > > {
2281
+ self . blockchain
2282
+ . spec_at_block_number ( block_number)
2283
+ . map_err ( |err| match err {
2284
+ BlockchainError :: UnknownBlockNumber => ProviderError :: InvalidBlockNumberOrHash {
2285
+ block_spec : block_spec. clone ( ) ,
2286
+ latest_block_number : self . blockchain . last_block_number ( ) ,
2287
+ } ,
2288
+ _ => ProviderError :: Blockchain ( err) ,
2289
+ } )
2290
+ }
2291
+
2231
2292
pub fn sign_transaction_request (
2232
2293
& self ,
2233
2294
transaction_request : TransactionRequestAndSender ,
@@ -2979,6 +3040,11 @@ mod tests {
2979
3040
let chain_id = fixture. provider_data . chain_id ( ) ;
2980
3041
assert_eq ! ( chain_id, fixture. config. chain_id) ;
2981
3042
3043
+ let chain_id_at_block = fixture
3044
+ . provider_data
3045
+ . chain_id_at_block_spec ( & BlockSpec :: Number ( 1 ) ) ?;
3046
+ assert_eq ! ( chain_id_at_block, 1 ) ;
3047
+
2982
3048
Ok ( ( ) )
2983
3049
}
2984
3050
0 commit comments