1
// Copyright 2019-2025 PureStake Inc.
2
// This file is part of Moonbeam.
3

            
4
// Moonbeam is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8

            
9
// Moonbeam is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13

            
14
// You should have received a copy of the GNU General Public License
15
// along with Moonbeam.  If not, see <http://www.gnu.org/licenses/>.
16

            
17
#[macro_export]
18
macro_rules! impl_runtime_apis_plus_common {
19
    ({$($custom:tt)*} {$($bench_custom:tt)*}) => {
20

            
21
		#[cfg(feature = "evm-tracing")]
22
		// Helper function to replay the "on_idle" hook for all pallets, we need this for
23
		// evm-tracing because some ethereum-xcm transactions might be executed at on_idle.
24
		//
25
		// We need to make sure that we replay on_idle exactly the same way as the
26
		// original block execution, but unfortunatly frame executive diosn't provide a function
27
		// to replay only on_idle, so we need to copy here some code inside frame executive.
28
20
		fn replay_on_idle() {
29
			use frame_system::pallet_prelude::BlockNumberFor;
30
			use frame_support::traits::OnIdle;
31

            
32
20
			let weight = <frame_system::Pallet<Runtime>>::block_weight();
33
20
			let max_weight = <
34
20
					<Runtime as frame_system::Config>::BlockWeights as
35
20
					frame_support::traits::Get<_>
36
20
				>::get().max_block;
37
20
			let remaining_weight = max_weight.saturating_sub(weight.total());
38
20
			if remaining_weight.all_gt(Weight::zero()) {
39
20
				let _ = <AllPalletsWithSystem as OnIdle<BlockNumberFor<Runtime>>>::on_idle(
40
20
					<frame_system::Pallet<Runtime>>::block_number(),
41
20
					remaining_weight,
42
20
				);
43
20
			}
44
20
		}
45
20

            
46
389810
		impl_runtime_apis! {
47
389810
			$($custom)*
48
389810

            
49
389810
			impl sp_api::Core<Block> for Runtime {
50
389810
				fn version() -> RuntimeVersion {
51
					VERSION
52
				}
53
389810

            
54
389810
				fn execute_block(block: Block) {
55
					Executive::execute_block(block)
56
				}
57
389810

            
58
389810
				fn initialize_block(header: &<Block as BlockT>::Header) -> sp_runtime::ExtrinsicInclusionMode {
59
					Executive::initialize_block(header)
60
				}
61
389810
			}
62
389810

            
63
389810
			impl sp_api::Metadata<Block> for Runtime {
64
389810
				fn metadata() -> OpaqueMetadata {
65
					OpaqueMetadata::new(Runtime::metadata().into())
66
				}
67
389810

            
68
389810
				fn metadata_at_version(version: u32) -> Option<OpaqueMetadata> {
69
					Runtime::metadata_at_version(version)
70
				}
71
389810

            
72
389810
				fn metadata_versions() -> Vec<u32> {
73
					Runtime::metadata_versions()
74
				}
75
389810
			}
76
389810

            
77
389810
			impl sp_block_builder::BlockBuilder<Block> for Runtime {
78
389810
				fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {
79
					Executive::apply_extrinsic(extrinsic)
80
				}
81
389810

            
82
389810
				fn finalize_block() -> <Block as BlockT>::Header {
83
					Executive::finalize_block()
84
				}
85
389810

            
86
389810
				fn inherent_extrinsics(
87
					data: sp_inherents::InherentData,
88
				) -> Vec<<Block as BlockT>::Extrinsic> {
89
					data.create_extrinsics()
90
				}
91
389810

            
92
389810
				fn check_inherents(
93
					block: Block,
94
					data: sp_inherents::InherentData,
95
				) -> sp_inherents::CheckInherentsResult {
96
					data.check_extrinsics(&block)
97
				}
98
389810
			}
99
389810

            
100
389810
			impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
101
389810
				fn offchain_worker(header: &<Block as BlockT>::Header) {
102
					Executive::offchain_worker(header)
103
				}
104
389810
			}
105
389810

            
106
389810
			impl sp_session::SessionKeys<Block> for Runtime {
107
389810
				fn decode_session_keys(
108
					encoded: Vec<u8>,
109
				) -> Option<Vec<(Vec<u8>, sp_core::crypto::KeyTypeId)>> {
110
					opaque::SessionKeys::decode_into_raw_public_keys(&encoded)
111
				}
112
389810

            
113
389810
				fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
114
					opaque::SessionKeys::generate(seed)
115
				}
116
389810
			}
117
389810

            
118
389810
			#[cfg(not(feature = "disable-genesis-builder"))]
119
389810
			impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
120
389810
				fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
121
					frame_support::genesis_builder_helper::build_state::<RuntimeGenesisConfig>(config)
122
				}
123
389810

            
124
389810
				fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
125
					frame_support::genesis_builder_helper::get_preset::<RuntimeGenesisConfig>(id, genesis_config_preset::get_preset)
126
				}
127
389810

            
128
389810
				fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
129
					genesis_config_preset::preset_names()
130
				}
131
389810
			}
132
389810

            
133
389810
			impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Index> for Runtime {
134
389810
				fn account_nonce(account: AccountId) -> Index {
135
					System::account_nonce(account)
136
				}
137
389810
			}
138
389810

            
139
389810
			impl moonbeam_rpc_primitives_debug::DebugRuntimeApi<Block> for Runtime {
140
389810
				fn trace_transaction(
141
20
					extrinsics: Vec<<Block as BlockT>::Extrinsic>,
142
20
					traced_transaction: &EthereumTransaction,
143
20
					header: &<Block as BlockT>::Header,
144
20
				) -> Result<
145
20
					(),
146
20
					sp_runtime::DispatchError,
147
20
				> {
148
20
					#[cfg(feature = "evm-tracing")]
149
20
					{
150
20
						use moonbeam_evm_tracer::tracer::{
151
20
							EthereumTracingStatus,
152
20
							EvmTracer,
153
20
							EthereumTracer
154
20
						};
155
20
						use frame_support::storage::unhashed;
156
20
						use frame_system::pallet_prelude::BlockNumberFor;
157
20

            
158
20
						// Tell the CallDispatcher we are tracing a specific Transaction.
159
20
						EthereumTracer::transaction(traced_transaction.hash(), || {
160
20
							// Initialize block: calls the "on_initialize" hook on every pallet
161
20
							// in AllPalletsWithSystem.
162
20
							// After pallet message queue was introduced, this must be done only after
163
20
							// enabling XCM tracing by calling ETHEREUM_TRACING_STATUS::using
164
20
							// in the storage
165
20
							Executive::initialize_block(header);
166
20

            
167
20
							// Apply the a subset of extrinsics: all the substrate-specific or ethereum
168
20
							// transactions that preceded the requested transaction.
169
40
							for ext in extrinsics.into_iter() {
170
20
								let _ = match &ext.0.function {
171
20
									RuntimeCall::Ethereum(transact { transaction }) => {
172
20
										// Reset the previously consumed weight when tracing ethereum transactions.
173
20
										// This is necessary because EVM tracing introduces additional
174
20
										// (ref_time) overhead, which differs from the production runtime behavior.
175
20
										// Without resetting the block weight, the extra tracing overhead could
176
20
										// leading to some transactions to incorrectly fail during tracing.
177
20
										frame_system::BlockWeight::<Runtime>::kill();
178
20

            
179
20
										if transaction == traced_transaction {
180
20
											EvmTracer::new().trace(|| Executive::apply_extrinsic(ext));
181
20
											return Ok(());
182
20
										} else {
183
20
											Executive::apply_extrinsic(ext)
184
20
										}
185
20
									}
186
20
									_ => Executive::apply_extrinsic(ext),
187
20
								};
188
20

            
189
20
								if let Some(EthereumTracingStatus::TransactionExited) = EthereumTracer::status() {
190
20
									return Ok(());
191
20
								}
192
20
							}
193
20

            
194
20
							if let Some(EthereumTracingStatus::Transaction(_)) = EthereumTracer::status() {
195
								// If the transaction was not found, it might be
196
								// an eth-xcm transaction that was executed at on_idle
197
								replay_on_idle();
198
20
							}
199
20

            
200
20
							if let Some(EthereumTracingStatus::TransactionExited) = EthereumTracer::status() {
201
20
								// The transaction was found
202
20
								Ok(())
203
20
							} else {
204
20
								// The transaction was not-found
205
20
								Err(sp_runtime::DispatchError::Other(
206
									"Failed to find Ethereum transaction among the extrinsics.",
207
								))
208
20
							}
209
20
						})
210
20
					}
211
20
					#[cfg(not(feature = "evm-tracing"))]
212
20
					Err(sp_runtime::DispatchError::Other(
213
20
						"Missing `evm-tracing` compile time feature flag.",
214
20
					))
215
20
				}
216
389810

            
217
389810
				fn trace_block(
218
20
					extrinsics: Vec<<Block as BlockT>::Extrinsic>,
219
20
					known_transactions: Vec<H256>,
220
20
					header: &<Block as BlockT>::Header,
221
20
				) -> Result<
222
20
					(),
223
20
					sp_runtime::DispatchError,
224
20
				> {
225
20
					#[cfg(feature = "evm-tracing")]
226
20
					{
227
20
						use moonbeam_evm_tracer::tracer::{
228
20
							EthereumTracingStatus,
229
20
							EvmTracer,
230
20
							EthereumTracer
231
20
						};
232
20
						use frame_system::pallet_prelude::BlockNumberFor;
233
20

            
234
20
						// Tell the CallDispatcher we are tracing a full Block.
235
20
						EthereumTracer::block(|| {
236
20
							let mut config = <Runtime as pallet_evm::Config>::config().clone();
237
20
							config.estimate = true;
238
20

            
239
20
							// Initialize block: calls the "on_initialize" hook on every pallet
240
20
							// in AllPalletsWithSystem.
241
20
							// After pallet message queue was introduced, this must be done only after
242
20
							// enabling XCM tracing by calling ETHEREUM_TRACING_STATUS::using
243
20
							// in the storage
244
20
							Executive::initialize_block(header);
245
20

            
246
20
							// Apply all extrinsics. Ethereum extrinsics are traced.
247
80
							for ext in extrinsics.into_iter() {
248
40
								match &ext.0.function {
249
40
									RuntimeCall::Ethereum(transact { transaction }) => {
250
40

            
251
40
										// Reset the previously consumed weight when tracing multiple transactions.
252
40
										// This is necessary because EVM tracing introduces additional
253
40
										// (ref_time) overhead, which differs from the production runtime behavior.
254
40
										// Without resetting the block weight, the extra tracing overhead could
255
40
										// leading to some transactions to incorrectly fail during tracing.
256
40
										frame_system::BlockWeight::<Runtime>::kill();
257
40

            
258
40
										let tx_hash = &transaction.hash();
259
40
										if known_transactions.contains(&tx_hash) {
260
40
											// Each known extrinsic is a new call stack.
261
40
											EvmTracer::emit_new();
262
40
											EvmTracer::new().trace(|| {
263
40
												if let Err(err) = Executive::apply_extrinsic(ext) {
264
40
													log::debug!(
265
20
														target: "tracing",
266
														"Could not trace eth transaction (hash: {}): {:?}",
267
														&tx_hash,
268
20
														err
269
20
													);
270
20
												}
271
40
											});
272
40
										} else {
273
20
											if let Err(err) = Executive::apply_extrinsic(ext) {
274
20
												log::debug!(
275
20
													target: "tracing",
276
													"Failed to apply eth extrinsic (hash: {}): {:?}",
277
													&tx_hash,
278
20
													err
279
20
												);
280
20
											}
281
20
										}
282
20
									}
283
20
									_ => {
284
40
										if let Err(err) = Executive::apply_extrinsic(ext) {
285
20
											log::debug!(
286
20
												target: "tracing",
287
												"Failed to apply non-eth extrinsic: {:?}",
288
20
												err
289
20
											);
290
20
										}
291
20
									}
292
20
								};
293
20
							}
294
20

            
295
20
							// Replay on_idle
296
20
							// Some XCM messages with eth-xcm transaction might be executed at on_idle
297
20
							replay_on_idle();
298
20

            
299
20
							Ok(())
300
20
						})
301
20
					}
302
20
					#[cfg(not(feature = "evm-tracing"))]
303
20
					Err(sp_runtime::DispatchError::Other(
304
20
						"Missing `evm-tracing` compile time feature flag.",
305
20
					))
306
20
				}
307
389810

            
308
389810
				fn trace_call(
309
20
					header: &<Block as BlockT>::Header,
310
20
					from: H160,
311
20
					to: H160,
312
20
					data: Vec<u8>,
313
20
					value: U256,
314
20
					gas_limit: U256,
315
20
					max_fee_per_gas: Option<U256>,
316
20
					max_priority_fee_per_gas: Option<U256>,
317
20
					nonce: Option<U256>,
318
20
					access_list: Option<Vec<(H160, Vec<H256>)>>,
319
20
				) -> Result<(), sp_runtime::DispatchError> {
320
20
					#[cfg(feature = "evm-tracing")]
321
20
					{
322
20
						use moonbeam_evm_tracer::tracer::EvmTracer;
323
20

            
324
20
						// Initialize block: calls the "on_initialize" hook on every pallet
325
20
						// in AllPalletsWithSystem.
326
20
						Executive::initialize_block(header);
327
20

            
328
20
						EvmTracer::new().trace(|| {
329
20
							let is_transactional = false;
330
20
							let validate = true;
331
20

            
332
20
							let transaction_data = pallet_ethereum::TransactionData::new(
333
20
								pallet_ethereum::TransactionAction::Call(to),
334
20
								data.clone(),
335
20
								nonce.unwrap_or_default(),
336
20
								gas_limit,
337
20
								None,
338
20
								max_fee_per_gas.or(Some(U256::default())),
339
20
								max_priority_fee_per_gas.or(Some(U256::default())),
340
20
								value,
341
20
								Some(<Runtime as pallet_evm::Config>::ChainId::get()),
342
20
								access_list.clone().unwrap_or_default(),
343
20
							);
344
20

            
345
20
							let gas_limit = gas_limit.min(u64::MAX.into()).low_u64();
346
20

            
347
20
							let (weight_limit, proof_size_base_cost) = pallet_ethereum::Pallet::<Runtime>::transaction_weight(&transaction_data);
348
20

            
349
20
							let _ = <Runtime as pallet_evm::Config>::Runner::call(
350
20
								from,
351
20
								to,
352
20
								data,
353
20
								value,
354
20
								gas_limit,
355
20
								max_fee_per_gas,
356
20
								max_priority_fee_per_gas,
357
20
								nonce,
358
20
								access_list.unwrap_or_default(),
359
20
								is_transactional,
360
20
								validate,
361
20
								weight_limit,
362
20
								proof_size_base_cost,
363
20
								<Runtime as pallet_evm::Config>::config(),
364
20
							);
365
20
						});
366
20
						Ok(())
367
20
					}
368
20
					#[cfg(not(feature = "evm-tracing"))]
369
20
					Err(sp_runtime::DispatchError::Other(
370
20
						"Missing `evm-tracing` compile time feature flag.",
371
20
					))
372
20
				}
373
389810
			}
374
389810

            
375
389810
			impl moonbeam_rpc_primitives_txpool::TxPoolRuntimeApi<Block> for Runtime {
376
389810
				fn extrinsic_filter(
377
20
					xts_ready: Vec<<Block as BlockT>::Extrinsic>,
378
20
					xts_future: Vec<<Block as BlockT>::Extrinsic>,
379
20
				) -> TxPoolResponse {
380
20
					TxPoolResponse {
381
20
						ready: xts_ready
382
20
							.into_iter()
383
389810
							.filter_map(|xt| match xt.0.function {
384
389810
								RuntimeCall::Ethereum(transact { transaction }) => Some(transaction),
385
389810
								_ => None,
386
389810
							})
387
20
							.collect(),
388
20
						future: xts_future
389
20
							.into_iter()
390
389810
							.filter_map(|xt| match xt.0.function {
391
389810
								RuntimeCall::Ethereum(transact { transaction }) => Some(transaction),
392
389810
								_ => None,
393
389810
							})
394
20
							.collect(),
395
20
					}
396
20
				}
397
389810
			}
398
389810

            
399
389810
			impl fp_rpc::EthereumRuntimeRPCApi<Block> for Runtime {
400
389810
				fn chain_id() -> u64 {
401
20
					<Runtime as pallet_evm::Config>::ChainId::get()
402
20
				}
403
389810

            
404
389810
				fn account_basic(address: H160) -> EVMAccount {
405
20
					let (account, _) = EVM::account_basic(&address);
406
20
					account
407
20
				}
408
389810

            
409
389810
				fn gas_price() -> U256 {
410
20
					let (gas_price, _) = <Runtime as pallet_evm::Config>::FeeCalculator::min_gas_price();
411
20
					gas_price
412
20
				}
413
389810

            
414
389810
				fn account_code_at(address: H160) -> Vec<u8> {
415
20
					pallet_evm::AccountCodes::<Runtime>::get(address)
416
20
				}
417
389810

            
418
389810
				fn author() -> H160 {
419
20
					<pallet_evm::Pallet<Runtime>>::find_author()
420
20
				}
421
389810

            
422
389810
				fn storage_at(address: H160, index: U256) -> H256 {
423
20
					let tmp: [u8; 32] = index.to_big_endian();
424
20
					pallet_evm::AccountStorages::<Runtime>::get(address, H256::from_slice(&tmp[..]))
425
20
				}
426
389810

            
427
389810
				fn call(
428
20
					from: H160,
429
20
					to: H160,
430
20
					data: Vec<u8>,
431
20
					value: U256,
432
20
					gas_limit: U256,
433
20
					max_fee_per_gas: Option<U256>,
434
20
					max_priority_fee_per_gas: Option<U256>,
435
20
					nonce: Option<U256>,
436
20
					estimate: bool,
437
20
					access_list: Option<Vec<(H160, Vec<H256>)>>,
438
20
				) -> Result<pallet_evm::CallInfo, sp_runtime::DispatchError> {
439
389810
					let config = if estimate {
440
389810
						let mut config = <Runtime as pallet_evm::Config>::config().clone();
441
						config.estimate = true;
442
						Some(config)
443
389810
					} else {
444
389810
						None
445
389810
					};
446
389810
					let is_transactional = false;
447
20
					let validate = true;
448
20

            
449
20
					let transaction_data = pallet_ethereum::TransactionData::new(
450
20
						pallet_ethereum::TransactionAction::Call(to),
451
20
						data.clone(),
452
20
						nonce.unwrap_or_default(),
453
20
						gas_limit,
454
20
						None,
455
20
						max_fee_per_gas.or(Some(U256::default())),
456
20
						max_priority_fee_per_gas.or(Some(U256::default())),
457
20
						value,
458
20
						Some(<Runtime as pallet_evm::Config>::ChainId::get()),
459
20
						access_list.clone().unwrap_or_default(),
460
20
					);
461
20

            
462
20
					let gas_limit = gas_limit.min(u64::MAX.into()).low_u64();
463
20

            
464
20
					let (weight_limit, proof_size_base_cost) = pallet_ethereum::Pallet::<Runtime>::transaction_weight(&transaction_data);
465
20

            
466
20
					<Runtime as pallet_evm::Config>::Runner::call(
467
20
						from,
468
20
						to,
469
20
						data,
470
20
						value,
471
20
						gas_limit,
472
20
						max_fee_per_gas,
473
20
						max_priority_fee_per_gas,
474
20
						nonce,
475
20
						access_list.unwrap_or_default(),
476
20
						is_transactional,
477
20
						validate,
478
20
						weight_limit,
479
20
						proof_size_base_cost,
480
20
						config.as_ref().unwrap_or(<Runtime as pallet_evm::Config>::config()),
481
20
					).map_err(|err| err.error.into())
482
20
				}
483
389810

            
484
389810
				fn create(
485
20
					from: H160,
486
20
					data: Vec<u8>,
487
20
					value: U256,
488
20
					gas_limit: U256,
489
20
					max_fee_per_gas: Option<U256>,
490
20
					max_priority_fee_per_gas: Option<U256>,
491
20
					nonce: Option<U256>,
492
20
					estimate: bool,
493
20
					access_list: Option<Vec<(H160, Vec<H256>)>>,
494
20
				) -> Result<pallet_evm::CreateInfo, sp_runtime::DispatchError> {
495
389810
					let config = if estimate {
496
389810
						let mut config = <Runtime as pallet_evm::Config>::config().clone();
497
						config.estimate = true;
498
						Some(config)
499
389810
					} else {
500
389810
						None
501
389810
					};
502
389810
					let is_transactional = false;
503
20
					let validate = true;
504
20

            
505
20
					let transaction_data = pallet_ethereum::TransactionData::new(
506
20
						pallet_ethereum::TransactionAction::Create,
507
20
						data.clone(),
508
20
						nonce.unwrap_or_default(),
509
20
						gas_limit,
510
20
						None,
511
20
						max_fee_per_gas.or(Some(U256::default())),
512
20
						max_priority_fee_per_gas.or(Some(U256::default())),
513
20
						value,
514
20
						Some(<Runtime as pallet_evm::Config>::ChainId::get()),
515
20
						access_list.clone().unwrap_or_default(),
516
20
					);
517
20

            
518
20
					let gas_limit = gas_limit.min(u64::MAX.into()).low_u64();
519
20

            
520
20
					let (weight_limit, proof_size_base_cost) = pallet_ethereum::Pallet::<Runtime>::transaction_weight(&transaction_data);
521
20

            
522
20
					#[allow(clippy::or_fun_call)] // suggestion not helpful here
523
20
					<Runtime as pallet_evm::Config>::Runner::create(
524
20
						from,
525
20
						data,
526
20
						value,
527
20
						gas_limit,
528
20
						max_fee_per_gas,
529
20
						max_priority_fee_per_gas,
530
20
						nonce,
531
20
						access_list.unwrap_or_default(),
532
20
						is_transactional,
533
20
						validate,
534
20
						weight_limit,
535
20
						proof_size_base_cost,
536
20
						config.as_ref().unwrap_or(<Runtime as pallet_evm::Config>::config()),
537
20
					).map_err(|err| err.error.into())
538
20
				}
539
389810

            
540
389810
				fn current_transaction_statuses() -> Option<Vec<TransactionStatus>> {
541
20
					pallet_ethereum::CurrentTransactionStatuses::<Runtime>::get()
542
20
				}
543
389810

            
544
389810
				fn current_block() -> Option<pallet_ethereum::Block> {
545
20
					pallet_ethereum::CurrentBlock::<Runtime>::get()
546
20
				}
547
389810

            
548
389810
				fn current_receipts() -> Option<Vec<pallet_ethereum::Receipt>> {
549
20
					pallet_ethereum::CurrentReceipts::<Runtime>::get()
550
20
				}
551
389810

            
552
389810
				fn current_all() -> (
553
					Option<pallet_ethereum::Block>,
554
					Option<Vec<pallet_ethereum::Receipt>>,
555
					Option<Vec<TransactionStatus>>,
556
				) {
557
					(
558
						pallet_ethereum::CurrentBlock::<Runtime>::get(),
559
						pallet_ethereum::CurrentReceipts::<Runtime>::get(),
560
						pallet_ethereum::CurrentTransactionStatuses::<Runtime>::get(),
561
					)
562
				}
563
389810

            
564
389810
				fn extrinsic_filter(
565
					xts: Vec<<Block as BlockT>::Extrinsic>,
566
				) -> Vec<EthereumTransaction> {
567
389810
					xts.into_iter().filter_map(|xt| match xt.0.function {
568
389810
						RuntimeCall::Ethereum(transact { transaction }) => Some(transaction),
569
389810
						_ => None
570
389810
					}).collect::<Vec<EthereumTransaction>>()
571
				}
572
389810

            
573
389810
				fn elasticity() -> Option<Permill> {
574
					None
575
				}
576
389810

            
577
389810
				fn gas_limit_multiplier_support() {}
578
389810

            
579
389810
				fn pending_block(
580
					xts: Vec<<Block as sp_runtime::traits::Block>::Extrinsic>
581
				) -> (
582
					Option<pallet_ethereum::Block>, Option<sp_std::prelude::Vec<TransactionStatus>>
583
				) {
584
389810
					for ext in xts.into_iter() {
585
						let _ = Executive::apply_extrinsic(ext);
586
					}
587
389810

            
588
389810
					Ethereum::on_finalize(System::block_number() + 1);
589

            
590
					(
591
						pallet_ethereum::CurrentBlock::<Runtime>::get(),
592
						pallet_ethereum::CurrentTransactionStatuses::<Runtime>::get()
593
					)
594
				 }
595
389810

            
596
389810
				fn initialize_pending_block(header: &<Block as BlockT>::Header) {
597
					pallet_randomness::vrf::using_fake_vrf(|| {
598
						let _ = Executive::initialize_block(header);
599
					})
600
				}
601
389810
			}
602
389810

            
603
389810
			impl fp_rpc::ConvertTransactionRuntimeApi<Block> for Runtime {
604
389810
				fn convert_transaction(
605
					transaction: pallet_ethereum::Transaction
606
				) -> <Block as BlockT>::Extrinsic {
607
					UncheckedExtrinsic::new_bare(
608
						pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),
609
					)
610
				}
611
389810
			}
612
389810

            
613
389810
			impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance>
614
389810
			for Runtime {
615
389810
				fn query_info(
616
					uxt: <Block as BlockT>::Extrinsic,
617
					len: u32,
618
				) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo<Balance> {
619
					TransactionPayment::query_info(uxt, len)
620
				}
621
389810

            
622
389810
				fn query_fee_details(
623
					uxt: <Block as BlockT>::Extrinsic,
624
					len: u32,
625
				) -> pallet_transaction_payment::FeeDetails<Balance> {
626
					TransactionPayment::query_fee_details(uxt, len)
627
				}
628
389810

            
629
389810
				fn query_weight_to_fee(weight: Weight) -> Balance {
630
					TransactionPayment::weight_to_fee(weight)
631
				}
632
389810

            
633
389810
				fn query_length_to_fee(length: u32) -> Balance {
634
					TransactionPayment::length_to_fee(length)
635
				}
636
389810
			}
637
389810

            
638
389810
			impl nimbus_primitives::NimbusApi<Block> for Runtime {
639
389850
				fn can_author(
640
60
					author: nimbus_primitives::NimbusId,
641
60
					slot: u32,
642
60
					parent_header: &<Block as BlockT>::Header
643
60
				) -> bool {
644
389810
					use pallet_parachain_staking::Config as PalletParachainStakingConfig;
645
389810

            
646
389850
					let block_number = parent_header.number + 1;
647
389810

            
648
389810
					// The Moonbeam runtimes use an entropy source that needs to do some accounting
649
389810
					// work during block initialization. Therefore we initialize it here to match
650
389810
					// the state it will be in when the next block is being executed.
651
389810
					use frame_support::traits::OnInitialize;
652
389850
					System::initialize(
653
60
						&block_number,
654
60
						&parent_header.hash(),
655
60
						&parent_header.digest,
656
60
					);
657
60

            
658
60
					// Because the staking solution calculates the next staking set at the beginning
659
60
					// of the first block in the new round, the only way to accurately predict the
660
60
					// authors is to compute the selection during prediction.
661
60
					if pallet_parachain_staking::Pallet::<Self>::round()
662
60
						.should_update(block_number) {
663
389810
						// get author account id
664
389810
						use nimbus_primitives::AccountLookup;
665
389810
						let author_account_id = if let Some(account) =
666
389810
							pallet_author_mapping::Pallet::<Self>::lookup_account(&author) {
667
389810
							account
668
389810
						} else {
669
389810
							// return false if author mapping not registered like in can_author impl
670
389810
							return false
671
389810
						};
672
389810
						let candidates = pallet_parachain_staking::Pallet::<Self>::compute_top_candidates();
673
						if candidates.is_empty() {
674
389810
							// If there are zero selected candidates, we use the same eligibility
675
389810
							// as the previous round
676
389810
							return AuthorInherent::can_author(&author, &slot);
677
389810
						}
678

            
679
						// predict eligibility post-selection by computing selection results now
680
						let (eligible, _) =
681
							pallet_author_slot_filter::compute_pseudo_random_subset::<Self>(
682
								candidates,
683
								&slot
684
							);
685
						eligible.contains(&author_account_id)
686
389810
					} else {
687
389850
						AuthorInherent::can_author(&author, &slot)
688
389810
					}
689
389810
				}
690
389810
			}
691
389810

            
692
389810
			impl cumulus_primitives_core::CollectCollationInfo<Block> for Runtime {
693
389810
				fn collect_collation_info(
694
					header: &<Block as BlockT>::Header
695
				) -> cumulus_primitives_core::CollationInfo {
696
					ParachainSystem::collect_collation_info(header)
697
				}
698
389810
			}
699
389810

            
700
389810
			impl session_keys_primitives::VrfApi<Block> for Runtime {
701
389810
				fn get_last_vrf_output() -> Option<<Block as BlockT>::Hash> {
702
					// TODO: remove in future runtime upgrade along with storage item
703
					if pallet_randomness::Pallet::<Self>::not_first_block().is_none() {
704
389810
						return None;
705
389810
					}
706
					pallet_randomness::Pallet::<Self>::local_vrf_output()
707
389810
				}
708
389810
				fn vrf_key_lookup(
709
					nimbus_id: nimbus_primitives::NimbusId
710
				) -> Option<session_keys_primitives::VrfId> {
711
389810
					use session_keys_primitives::KeysLookup;
712
389810
					AuthorMapping::lookup_keys(&nimbus_id)
713
				}
714
389810
			}
715
389810

            
716
389810
			impl xcm_runtime_apis::fees::XcmPaymentApi<Block> for Runtime {
717
389810
				fn query_acceptable_payment_assets(
718
					xcm_version: xcm::Version
719
				) -> Result<Vec<VersionedAssetId>, XcmPaymentApiError> {
720
					XcmWeightTrader::query_acceptable_payment_assets(xcm_version)
721
				}
722
389810

            
723
389810
				fn query_weight_to_asset_fee(
724
					weight: Weight, asset: VersionedAssetId
725
				) -> Result<u128, XcmPaymentApiError> {
726
					XcmWeightTrader::query_weight_to_asset_fee(weight, asset)
727
				}
728
389810

            
729
389810
				fn query_xcm_weight(message: VersionedXcm<()>) -> Result<Weight, XcmPaymentApiError> {
730
					PolkadotXcm::query_xcm_weight(message)
731
				}
732
389810

            
733
389810
				fn query_delivery_fees(
734
					destination: VersionedLocation, message: VersionedXcm<()>
735
				) -> Result<VersionedAssets, XcmPaymentApiError> {
736
					PolkadotXcm::query_delivery_fees(destination, message)
737
				}
738
389810
			}
739
389810

            
740
389810
			impl xcm_runtime_apis::dry_run::DryRunApi<Block, RuntimeCall, RuntimeEvent, OriginCaller>
741
389810
				for Runtime {
742
389810
					fn dry_run_call(
743
						origin: OriginCaller,
744
						call: RuntimeCall,
745
						result_xcms_version: XcmVersion
746
					) -> Result<CallDryRunEffects<RuntimeEvent>, XcmDryRunApiError> {
747
						PolkadotXcm::dry_run_call::<
748
							Runtime,
749
							xcm_config::XcmRouter,
750
							OriginCaller,
751
							RuntimeCall>(origin, call, result_xcms_version)
752
					}
753
389810

            
754
389810
					fn dry_run_xcm(
755
						origin_location: VersionedLocation,
756
						xcm: VersionedXcm<RuntimeCall>
757
					) -> Result<XcmDryRunEffects<RuntimeEvent>, XcmDryRunApiError> {
758
						PolkadotXcm::dry_run_xcm::<
759
							Runtime,
760
							xcm_config::XcmRouter,
761
							RuntimeCall,
762
							xcm_config::XcmExecutorConfig>(origin_location, xcm)
763
					}
764
389810
				}
765
389810

            
766
389810
			impl xcm_runtime_apis::conversions::LocationToAccountApi<Block, AccountId> for Runtime {
767
389810
				fn convert_location(location: VersionedLocation) -> Result<
768
					AccountId,
769
					xcm_runtime_apis::conversions::Error
770
				> {
771
					xcm_runtime_apis::conversions::LocationToAccountHelper::<
772
						AccountId,
773
						xcm_config::LocationToAccountId,
774
					>::convert_location(location)
775
				}
776
389810
			}
777
389810

            
778
389810
			#[cfg(feature = "runtime-benchmarks")]
779
389810
			impl frame_benchmarking::Benchmark<Block> for Runtime {
780
389810

            
781
389810
				fn benchmark_metadata(extra: bool) -> (
782
389810
					Vec<frame_benchmarking::BenchmarkList>,
783
389810
					Vec<frame_support::traits::StorageInfo>,
784
389810
				) {
785
389810
					use frame_benchmarking::{list_benchmark, Benchmarking, BenchmarkList};
786
389810
					use frame_system_benchmarking::Pallet as SystemBench;
787
389810
					use frame_support::traits::StorageInfoTrait;
788
389810

            
789
389810
					use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark;
790
389810
					use pallet_transaction_payment::benchmarking::Pallet as PalletTransactionPaymentBenchmark;
791
389810

            
792
389810
					let mut list = Vec::<BenchmarkList>::new();
793
389810
					list_benchmarks!(list, extra);
794
389810

            
795
389810
					let storage_info = AllPalletsWithSystem::storage_info();
796
389810

            
797
389810
					return (list, storage_info)
798
389810
				}
799
389810

            
800
389810
				fn dispatch_benchmark(
801
389810
					config: frame_benchmarking::BenchmarkConfig,
802
389810
				) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> {
803
389810
					use frame_benchmarking::{add_benchmark, BenchmarkBatch, Benchmarking};
804
389810
					use frame_support::traits::TrackedStorageKey;
805
389810
					use cumulus_primitives_core::ParaId;
806
389810

            
807
389810
					use xcm::latest::prelude::{
808
389810
						GeneralIndex, Junction, Junctions, Location, Response, NetworkId, AssetId,
809
389810
						Assets as XcmAssets, Fungible, Asset, ParentThen, Parachain, Parent, WeightLimit
810
389810
					};
811
389810
					use xcm_config::SelfReserve;
812
389810
					use frame_benchmarking::BenchmarkError;
813
389810

            
814
389810
					use frame_system_benchmarking::Pallet as SystemBench;
815
389810
					// Needed to run `set_code` and `apply_authorized_upgrade` frame_system benchmarks
816
389810
					// https://github.com/paritytech/cumulus/pull/2766
817
389810
					impl frame_system_benchmarking::Config for Runtime {
818
389810
						fn setup_set_code_requirements(code: &Vec<u8>) -> Result<(), BenchmarkError> {
819
389810
							ParachainSystem::initialize_for_set_code_benchmark(code.len() as u32);
820
389810
							Ok(())
821
389810
						}
822
389810

            
823
389810
						fn verify_set_code() {
824
389810
							System::assert_last_event(cumulus_pallet_parachain_system::Event::<Runtime>::ValidationFunctionStored.into());
825
389810
						}
826
389810
					}
827
389810

            
828
389810
					use pallet_asset_manager::Config as PalletAssetManagerConfig;
829
389810

            
830
389810
					use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark;
831
389810
					parameter_types! {
832
389810
						pub const RandomParaId: ParaId = ParaId::new(43211234);
833
389810
					}
834
389810

            
835
389810
					pub struct TestDeliveryHelper;
836
389810
					impl xcm_builder::EnsureDelivery for TestDeliveryHelper {
837
389810
						fn ensure_successful_delivery(
838
389810
							origin_ref: &Location,
839
389810
							_dest: &Location,
840
389810
							_fee_reason: xcm_executor::traits::FeeReason,
841
389810
						) -> (Option<xcm_executor::FeesMode>, Option<XcmAssets>) {
842
389810
							use xcm_executor::traits::ConvertLocation;
843
389810
							let account = xcm_config::LocationToH160::convert_location(origin_ref)
844
389810
								.expect("Invalid location");
845
389810
							// Give the existential deposit at least
846
389810
							let balance = ExistentialDeposit::get();
847
389810
							let _ = <Balances as frame_support::traits::Currency<_>>::
848
389810
								make_free_balance_be(&account.into(), balance);
849
389810

            
850
389810
							(None, None)
851
389810
						}
852
389810
					}
853
389810

            
854
389810
					use pallet_transaction_payment::benchmarking::Pallet as PalletTransactionPaymentBenchmark;
855
389810
					impl pallet_transaction_payment::benchmarking::Config for Runtime {
856
389810
						fn setup_benchmark_environment() {
857
389810
							let alice = AccountId::from(sp_core::hex2array!("f24FF3a9CF04c71Dbc94D0b566f7A27B94566cac"));
858
389810
							pallet_author_inherent::Author::<Runtime>::put(&alice);
859
389810
						}
860
389810
					}
861
389810

            
862
389810
					impl pallet_xcm::benchmarking::Config for Runtime {
863
389810
				        type DeliveryHelper = TestDeliveryHelper;
864
389810

            
865
389810
						fn get_asset() -> Asset {
866
389810
							Asset {
867
389810
								id: AssetId(SelfReserve::get()),
868
389810
								fun: Fungible(ExistentialDeposit::get()),
869
389810
							}
870
389810
						}
871
389810

            
872
389810
						fn reachable_dest() -> Option<Location> {
873
389810
							Some(Parent.into())
874
389810
						}
875
389810

            
876
389810
						fn teleportable_asset_and_dest() -> Option<(Asset, Location)> {
877
389810
							None
878
389810
						}
879
389810

            
880
389810
						fn reserve_transferable_asset_and_dest() -> Option<(Asset, Location)> {
881
389810
							use xcm_config::SelfReserve;
882
389810

            
883
389810
							ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests(
884
389810
								RandomParaId::get().into()
885
389810
							);
886
389810

            
887
389810
							Some((
888
389810
								Asset {
889
389810
									fun: Fungible(ExistentialDeposit::get()),
890
389810
									id: AssetId(SelfReserve::get().into())
891
389810
								},
892
389810
								// Moonbeam can reserve transfer native token to
893
389810
								// some random parachain.
894
389810
								ParentThen(Parachain(RandomParaId::get().into()).into()).into(),
895
389810
							))
896
389810
						}
897
389810

            
898
389810
						fn set_up_complex_asset_transfer(
899
389810
						) -> Option<(XcmAssets, u32, Location, Box<dyn FnOnce()>)> {
900
389810
							use xcm_config::SelfReserve;
901
389810

            
902
389810
							let destination: xcm::v5::Location = Parent.into();
903
389810

            
904
389810
							let fee_amount: u128 = <Runtime as pallet_balances::Config>::ExistentialDeposit::get();
905
389810
							let fee_asset: Asset = (SelfReserve::get(), fee_amount).into();
906
389810

            
907
389810
							// Give some multiple of transferred amount
908
389810
							let balance = fee_amount * 1000;
909
389810
							let who = frame_benchmarking::whitelisted_caller();
910
389810
							let _ =
911
389810
								<Balances as frame_support::traits::Currency<_>>::make_free_balance_be(&who, balance);
912
389810

            
913
389810
							// verify initial balance
914
389810
							assert_eq!(Balances::free_balance(&who), balance);
915
389810

            
916
389810
							// set up local asset
917
389810
							let asset_amount: u128 = 10u128;
918
389810
							let initial_asset_amount: u128 = asset_amount * 10;
919
389810

            
920
389810
							let (asset_id, _, _) = pallet_assets::benchmarking::create_default_minted_asset::<
921
389810
								Runtime,
922
389810
								()
923
389810
							>(true, initial_asset_amount);
924
389810
							let transfer_asset: Asset = (SelfReserve::get(), asset_amount).into();
925
389810

            
926
389810
							let assets: XcmAssets = vec![fee_asset.clone(), transfer_asset].into();
927
389810
							let fee_index: u32 = 0;
928
389810

            
929
389810
							let verify: Box<dyn FnOnce()> = Box::new(move || {
930
389810
								// verify balance after transfer, decreased by
931
389810
								// transferred amount (and delivery fees)
932
389810
								assert!(Balances::free_balance(&who) <= balance - fee_amount);
933
389810
							});
934
389810

            
935
389810
							Some((assets, fee_index, destination, verify))
936
389810
						}
937
389810
					}
938
389810

            
939
389810
					impl pallet_xcm_benchmarks::Config for Runtime {
940
389810
						type XcmConfig = xcm_config::XcmExecutorConfig;
941
389810
						type AccountIdConverter = xcm_config::LocationToAccountId;
942
389810
						type DeliveryHelper = ();
943
389810
						fn valid_destination() -> Result<Location, BenchmarkError> {
944
389810
							Ok(Location::parent())
945
389810
						}
946
389810
						fn worst_case_holding(_depositable_count: u32) -> XcmAssets {
947
389810
						// 100 fungibles
948
389810
							const HOLDING_FUNGIBLES: u32 = 100;
949
389810
							let fungibles_amount: u128 = 100;
950
389810
							let assets = (0..HOLDING_FUNGIBLES).map(|i| {
951
389810
								let location: Location = GeneralIndex(i as u128).into();
952
389810
								Asset {
953
389810
									id: AssetId(location),
954
389810
									fun: Fungible(fungibles_amount * i as u128),
955
389810
								}
956
389810
								.into()
957
389810
							})
958
389810
							.chain(
959
389810
								core::iter::once(
960
389810
									Asset {
961
389810
										id: AssetId(Location::parent()),
962
389810
										fun: Fungible(u128::MAX)
963
389810
									}
964
389810
								)
965
389810
							)
966
389810
							.collect::<Vec<_>>();
967
389810

            
968
389810

            
969
389810
							for (i, asset) in assets.iter().enumerate() {
970
389810
								if let Asset {
971
389810
									id: AssetId(location),
972
389810
									fun: Fungible(_)
973
389810
								} = asset {
974
389810
									EvmForeignAssets::set_asset(
975
389810
										location.clone(),
976
389810
										i as u128
977
389810
									);
978
389810
									XcmWeightTrader::set_asset_price(
979
389810
										location.clone(),
980
389810
										1u128.pow(18)
981
389810
									);
982
389810
								}
983
389810
							}
984
389810
							assets.into()
985
389810
						}
986
389810
					}
987
389810

            
988
389810
					impl pallet_xcm_benchmarks::generic::Config for Runtime {
989
389810
						type RuntimeCall = RuntimeCall;
990
389810
						type TransactAsset = Balances;
991
389810

            
992
389810
						fn worst_case_response() -> (u64, Response) {
993
389810
							(0u64, Response::Version(Default::default()))
994
389810
						}
995
389810

            
996
389810
						fn worst_case_asset_exchange()
997
389810
							-> Result<(XcmAssets, XcmAssets), BenchmarkError> {
998
389810
							Err(BenchmarkError::Skip)
999
389810
						}
389810

            
389810
						fn universal_alias() -> Result<(Location, Junction), BenchmarkError> {
389810
							Err(BenchmarkError::Skip)
389810
						}
389810

            
389810
						fn export_message_origin_and_destination()
389810
							-> Result<(Location, NetworkId, Junctions), BenchmarkError> {
389810
							Err(BenchmarkError::Skip)
389810
						}
389810

            
389810
						fn transact_origin_and_runtime_call()
389810
							-> Result<(Location, RuntimeCall), BenchmarkError> {
389810
							Ok((Location::parent(), frame_system::Call::remark_with_event {
389810
								remark: vec![]
389810
							}.into()))
389810
						}
389810

            
389810
						fn subscribe_origin() -> Result<Location, BenchmarkError> {
389810
							Ok(Location::parent())
389810
						}
389810

            
389810
						fn claimable_asset()
389810
							-> Result<(Location, Location, XcmAssets), BenchmarkError> {
389810
							let origin = Location::parent();
389810
							let assets: XcmAssets = (AssetId(Location::parent()), 1_000u128)
389810
								.into();
389810
							let ticket = Location { parents: 0, interior: [].into() /* Here */ };
389810
							Ok((origin, ticket, assets))
389810
						}
389810

            
389810
						fn worst_case_for_trader() -> Result<(Asset, WeightLimit), BenchmarkError> {
389810
							Err(BenchmarkError::Skip)
389810
						}
389810

            
389810
						fn unlockable_asset()
389810
							-> Result<(Location, Location, Asset), BenchmarkError> {
389810
							Err(BenchmarkError::Skip)
389810
						}
389810

            
389810
						fn alias_origin() -> Result<(Location, Location), BenchmarkError> {
389810
							Err(BenchmarkError::Skip)
389810
						}
389810
					}
389810

            
389810
					$($bench_custom)*
389810

            
389810
					let whitelist: Vec<TrackedStorageKey> = vec![
389810
						// Block Number
389810
						hex_literal::hex!(  "26aa394eea5630e07c48ae0c9558cef7"
389810
											"02a5c1b19ab7a04f536c519aca4983ac")
389810
							.to_vec().into(),
389810
						// Total Issuance
389810
						hex_literal::hex!(  "c2261276cc9d1f8598ea4b6a74b15c2f"
389810
											"57c875e4cff74148e4628f264b974c80")
389810
							.to_vec().into(),
389810
						// Execution Phase
389810
						hex_literal::hex!(  "26aa394eea5630e07c48ae0c9558cef7"
389810
											"ff553b5a9862a516939d82b3d3d8661a")
389810
							.to_vec().into(),
389810
						// Event Count
389810
						hex_literal::hex!(  "26aa394eea5630e07c48ae0c9558cef7"
389810
											"0a98fdbe9ce6c55837576c60c7af3850")
389810
							.to_vec().into(),
389810
						// System Events
389810
						hex_literal::hex!(  "26aa394eea5630e07c48ae0c9558cef7"
389810
											"80d41e5e16056765bc8461851072c9d7")
389810
							.to_vec().into(),
389810
						// System BlockWeight
389810
						hex_literal::hex!(  "26aa394eea5630e07c48ae0c9558cef7"
389810
											"34abf5cb34d6244378cddbf18e849d96")
389810
							.to_vec().into(),
389810
						// ParachainStaking Round
389810
						hex_literal::hex!(  "a686a3043d0adcf2fa655e57bc595a78"
389810
											"13792e785168f725b60e2969c7fc2552")
389810
							.to_vec().into(),
389810
						// Treasury Account (py/trsry)
389810
						hex_literal::hex!(  "26aa394eea5630e07c48ae0c9558cef7"
389810
											"b99d880ec681799c0cf30e8886371da9"
389810
											"7be2919ac397ba499ea5e57132180ec6"
389810
											"6d6f646c70792f747273727900000000"
389810
											"00000000"
389810
						).to_vec().into(),
389810
						// Treasury Account (pc/trsry)
389810
						hex_literal::hex!(  "26aa394eea5630e07c48ae0c9558cef7"
389810
											"b99d880ec681799c0cf30e8886371da9"
389810
											"7be2919ac397ba499ea5e57132180ec6"
389810
											"6d6f646c70632f747273727900000000"
389810
											"00000000"
389810
						).to_vec().into(),
389810
						// ParachainInfo ParachainId
389810
						hex_literal::hex!(  "0d715f2646c8f85767b5d2764bb27826"
389810
											"04a74d81251e398fd8a0a4d55023bb3f")
389810
							.to_vec().into(),
389810
						// Parameters Parameters
389810
						hex_literal::hex!(  "c63bdd4a39095ccf55623a6f2872bf8a" // Pallet: "Parameters"
389810
											"c63bdd4a39095ccf55623a6f2872bf8a" // Storage Prefix: "Parameters"
389810
											// MoonbaseRuntimeRuntimeParamsRuntimeParametersKey(FeesTreasuryProportion)
389810
											"71d0aacb690b61280d0c97c6b6a666640000"
389810
										)
389810
							.to_vec().into(),
389810

            
389810
					];
389810

            
389810
					let mut batches = Vec::<BenchmarkBatch>::new();
389810
					let params = (&config, &whitelist);
389810

            
389810
					add_benchmarks!(params, batches);
389810

            
389810
					if batches.is_empty() {
389810
						return Err("Benchmark not found for this pallet.".into());
389810
					}
389810
					Ok(batches)
389810
				}
389810
			}
389810

            
389810
			#[cfg(feature = "try-runtime")]
389810
			impl frame_try_runtime::TryRuntime<Block> for Runtime {
389810
				fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) {
389810
					log::info!("try-runtime::on_runtime_upgrade()");
389810
					// NOTE: intentional expect: we don't want to propagate the error backwards,
389810
					// and want to have a backtrace here. If any of the pre/post migration checks
389810
					// fail, we shall stop right here and right now.
389810
					let weight = Executive::try_runtime_upgrade(checks)
389810
						.expect("runtime upgrade logic *must* be infallible");
389810
					(weight, RuntimeBlockWeights::get().max_block)
389810
				}
389810

            
389810
				fn execute_block(
389810
					block: Block,
389810
					state_root_check: bool,
389810
					signature_check: bool,
389810
					select: frame_try_runtime::TryStateSelect
389810
				) -> Weight {
389810
					log::info!(
389810
						"try-runtime: executing block {:?} / root checks: {:?} / try-state-select: {:?}",
389810
						block.header.hash(),
389810
						state_root_check,
389810
						select,
389810
					);
389810
					// NOTE: intentional unwrap: we don't want to propagate the error backwards,
389810
					// and want to have a backtrace here.
389810
					Executive::try_execute_block(
389810
						block,
389810
						state_root_check,
389810
						signature_check,
389810
						select,
389810
					).expect("execute-block failed")
389810
				}
389810
			}
389810
		}
	};
}