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
402222
		impl_runtime_apis! {
47
402222
			$($custom)*
48
402222

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

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

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

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

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

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

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

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

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

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

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

            
106
402222
			impl sp_session::SessionKeys<Block> for Runtime {
107
402222
				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
402222

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

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

            
124
402222
				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
402222

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

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

            
139
402222
			impl moonbeam_rpc_primitives_debug::DebugRuntimeApi<Block> for Runtime {
140
402222
				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
402222

            
217
402222
				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
402222

            
308
402222
				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
402222
			}
374
402222

            
375
402222
			impl moonbeam_rpc_primitives_txpool::TxPoolRuntimeApi<Block> for Runtime {
376
402222
				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
402222
							.filter_map(|xt| match xt.0.function {
384
402222
								RuntimeCall::Ethereum(transact { transaction }) => Some(transaction),
385
402222
								_ => None,
386
402222
							})
387
20
							.collect(),
388
20
						future: xts_future
389
20
							.into_iter()
390
402222
							.filter_map(|xt| match xt.0.function {
391
402222
								RuntimeCall::Ethereum(transact { transaction }) => Some(transaction),
392
402222
								_ => None,
393
402222
							})
394
20
							.collect(),
395
20
					}
396
20
				}
397
402222
			}
398
402222

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

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

            
409
402222
				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
402222

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

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

            
422
402222
				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
402222

            
427
402222
				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
402222
					let config = if estimate {
440
402222
						let mut config = <Runtime as pallet_evm::Config>::config().clone();
441
						config.estimate = true;
442
						Some(config)
443
402222
					} else {
444
402222
						None
445
402222
					};
446
402222
					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
402222

            
484
402222
				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
402222
					let config = if estimate {
496
402222
						let mut config = <Runtime as pallet_evm::Config>::config().clone();
497
						config.estimate = true;
498
						Some(config)
499
402222
					} else {
500
402222
						None
501
402222
					};
502
402222
					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
402222

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

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

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

            
552
402222
				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
402222

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

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

            
577
402222
				fn gas_limit_multiplier_support() {}
578
402222

            
579
402222
				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
402222
					for ext in xts.into_iter() {
585
						let _ = Executive::apply_extrinsic(ext);
586
					}
587
402222

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

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

            
596
402222
				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
402222
			}
602
402222

            
603
402222
			impl fp_rpc::ConvertTransactionRuntimeApi<Block> for Runtime {
604
402222
				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
402222
			}
612
402222

            
613
402222
			impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance>
614
402222
			for Runtime {
615
402222
				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
402222

            
622
402222
				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
402222

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

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

            
638
402222
			impl nimbus_primitives::NimbusApi<Block> for Runtime {
639
402262
				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
402222
					use pallet_parachain_staking::Config as PalletParachainStakingConfig;
645
402222

            
646
402262
					let block_number = parent_header.number + 1;
647
402222

            
648
402222
					// The Moonbeam runtimes use an entropy source that needs to do some accounting
649
402222
					// work during block initialization. Therefore we initialize it here to match
650
402222
					// the state it will be in when the next block is being executed.
651
402222
					use frame_support::traits::OnInitialize;
652
402262
					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
402222
						// get author account id
664
402222
						use nimbus_primitives::AccountLookup;
665
402222
						let author_account_id = if let Some(account) =
666
402222
							pallet_author_mapping::Pallet::<Self>::lookup_account(&author) {
667
402222
							account
668
402222
						} else {
669
402222
							// return false if author mapping not registered like in can_author impl
670
402222
							return false
671
402222
						};
672
402222
						let candidates = pallet_parachain_staking::Pallet::<Self>::compute_top_candidates();
673
						if candidates.is_empty() {
674
402222
							// If there are zero selected candidates, we use the same eligibility
675
402222
							// as the previous round
676
402222
							return AuthorInherent::can_author(&author, &slot);
677
402222
						}
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
402222
					} else {
687
402262
						AuthorInherent::can_author(&author, &slot)
688
402222
					}
689
402222
				}
690
402222
			}
691
402222

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

            
700
402222
			impl session_keys_primitives::VrfApi<Block> for Runtime {
701
402222
				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
402222
						return None;
705
402222
					}
706
					pallet_randomness::Pallet::<Self>::local_vrf_output()
707
402222
				}
708
402222
				fn vrf_key_lookup(
709
					nimbus_id: nimbus_primitives::NimbusId
710
				) -> Option<session_keys_primitives::VrfId> {
711
402222
					use session_keys_primitives::KeysLookup;
712
402222
					AuthorMapping::lookup_keys(&nimbus_id)
713
				}
714
402222
			}
715
402222

            
716
402222
			impl xcm_runtime_apis::fees::XcmPaymentApi<Block> for Runtime {
717
402222
				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
402222

            
723
402222
				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
402222

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

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

            
740
402222
			impl xcm_runtime_apis::dry_run::DryRunApi<Block, RuntimeCall, RuntimeEvent, OriginCaller>
741
402222
				for Runtime {
742
402222
					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
402222

            
754
402222
					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
402222
				}
765
402222

            
766
402222
			impl xcm_runtime_apis::conversions::LocationToAccountApi<Block, AccountId> for Runtime {
767
402222
				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
402222
			}
777
402222

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            
968
402222

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

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

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

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

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

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

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

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

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

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

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

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

            
402222
					$($bench_custom)*
402222

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

            
402222
					];
402222

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

            
402222
					add_benchmarks!(params, batches);
402222

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

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

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