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
    	use ethereum::AuthorizationList;
21

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

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

            
47
		/// AccountId Converter used for benchmarks.
48
		///
49
		/// * AccountId32 Junction is being used in pallet_xcm_benchmarks
50
		/// * Parent is used as valid destination location for benchmarking.
51
		#[cfg(feature = "runtime-benchmarks")]
52
		pub struct BenchAccountIdConverter<AccountId>(sp_std::marker::PhantomData<AccountId>);
53

            
54
		#[cfg(feature = "runtime-benchmarks")]
55
		impl<AccountId: From<[u8; 20]> + Into<[u8; 20]> + Clone> xcm_executor::traits::ConvertLocation<AccountId>
56
			for BenchAccountIdConverter<AccountId>
57
		{
58
			fn convert_location(location: &xcm::latest::prelude::Location) -> Option<AccountId> {
59
				match location.unpack() {
60
					(0, [xcm::latest::prelude::AccountId32 { id, network: None }]) => {
61
						// take the first 20 bytes of the id and convert to fixed-size array
62
						let mut id20: [u8; 20] = [0u8; 20];
63
						id20.copy_from_slice(&id[..20]);
64
						Some(id20.into())
65
					},
66
					(1, []) => {
67
						Some([1u8; 20].into())
68
					},
69
					_ => return None,
70
				}
71
			}
72
		}
73

            
74
		impl_runtime_apis! {
75
			$($custom)*
76

            
77
			impl sp_api::Core<Block> for Runtime {
78
				fn version() -> RuntimeVersion {
79
					VERSION
80
				}
81

            
82
				fn execute_block(block: <Block as BlockT>::LazyBlock) {
83
					Executive::execute_block(block)
84
				}
85

            
86
				fn initialize_block(header: &<Block as BlockT>::Header) -> sp_runtime::ExtrinsicInclusionMode {
87
					Executive::initialize_block(header)
88
				}
89
			}
90

            
91
			impl cumulus_primitives_core::RelayParentOffsetApi<Block> for Runtime {
92
				fn relay_parent_offset() -> u32 {
93
					crate::RELAY_PARENT_OFFSET
94
				}
95
			}
96

            
97
			impl sp_api::Metadata<Block> for Runtime {
98
				fn metadata() -> OpaqueMetadata {
99
					OpaqueMetadata::new(Runtime::metadata().into())
100
				}
101

            
102
				fn metadata_at_version(version: u32) -> Option<OpaqueMetadata> {
103
					Runtime::metadata_at_version(version)
104
				}
105

            
106
				fn metadata_versions() -> Vec<u32> {
107
					Runtime::metadata_versions()
108
				}
109
			}
110

            
111
			impl sp_block_builder::BlockBuilder<Block> for Runtime {
112
				fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {
113
					Executive::apply_extrinsic(extrinsic)
114
				}
115

            
116
				fn finalize_block() -> <Block as BlockT>::Header {
117
					Executive::finalize_block()
118
				}
119

            
120
				fn inherent_extrinsics(
121
					data: sp_inherents::InherentData,
122
				) -> Vec<<Block as BlockT>::Extrinsic> {
123
					data.create_extrinsics()
124
				}
125

            
126
				fn check_inherents(
127
					block: <Block as BlockT>::LazyBlock,
128
					data: sp_inherents::InherentData,
129
				) -> sp_inherents::CheckInherentsResult {
130
					data.check_extrinsics(&block)
131
				}
132
			}
133

            
134
			impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
135
				fn offchain_worker(header: &<Block as BlockT>::Header) {
136
					Executive::offchain_worker(header)
137
				}
138
			}
139

            
140
			impl sp_session::SessionKeys<Block> for Runtime {
141
				fn decode_session_keys(
142
					encoded: Vec<u8>,
143
				) -> Option<Vec<(Vec<u8>, sp_core::crypto::KeyTypeId)>> {
144
					opaque::SessionKeys::decode_into_raw_public_keys(&encoded)
145
				}
146

            
147
				fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
148
					opaque::SessionKeys::generate(seed)
149
				}
150
			}
151

            
152
			impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
153
				fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
154
					frame_support::genesis_builder_helper::build_state::<RuntimeGenesisConfig>(config)
155
				}
156

            
157
				#[cfg(not(feature = "disable-genesis-builder"))]
158
				fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
159
					frame_support::genesis_builder_helper::get_preset::<RuntimeGenesisConfig>(id, genesis_config_preset::get_preset)
160
				}
161
				#[cfg(feature = "disable-genesis-builder")]
162
				fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
163
					None
164
				}
165

            
166
				#[cfg(not(feature = "disable-genesis-builder"))]
167
				fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
168
					genesis_config_preset::preset_names()
169
				}
170
				#[cfg(feature = "disable-genesis-builder")]
171
				fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
172
					Default::default()
173
				}
174
			}
175

            
176
			impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Index> for Runtime {
177
				fn account_nonce(account: AccountId) -> Index {
178
					System::account_nonce(account)
179
				}
180
			}
181

            
182
			impl moonbeam_rpc_primitives_debug::DebugRuntimeApi<Block> for Runtime {
183
21
				fn trace_transaction(
184
21
					extrinsics: Vec<<Block as BlockT>::Extrinsic>,
185
21
					traced_transaction: &EthereumTransaction,
186
21
					header: &<Block as BlockT>::Header,
187
21
				) -> Result<
188
21
					(),
189
21
					sp_runtime::DispatchError,
190
21
				> {
191
					#[cfg(feature = "evm-tracing")]
192
					{
193
						use moonbeam_evm_tracer::tracer::{
194
							EthereumTracingStatus,
195
							EvmTracer,
196
							EthereumTracer
197
						};
198
						use frame_support::storage::unhashed;
199
						use frame_system::pallet_prelude::BlockNumberFor;
200

            
201
						// Tell the CallDispatcher we are tracing a specific Transaction.
202
21
						EthereumTracer::transaction(traced_transaction.hash(), || {
203
							// Initialize block: calls the "on_initialize" hook on every pallet
204
							// in AllPalletsWithSystem.
205
							// After pallet message queue was introduced, this must be done only after
206
							// enabling XCM tracing by calling ETHEREUM_TRACING_STATUS::using
207
							// in the storage
208
21
							Executive::initialize_block(header);
209

            
210
							// Apply a subset of extrinsics: all the substrate-specific or ethereum
211
							// transactions that preceded the requested transaction.
212
42
							for ext in extrinsics.into_iter() {
213
42
								let _ = match &ext.0.function {
214
21
									RuntimeCall::Ethereum(transact { transaction }) => {
215
										// Reset the previously consumed weight when tracing ethereum transactions.
216
										// This is necessary because EVM tracing introduces additional
217
										// (ref_time) overhead, which differs from the production runtime behavior.
218
										// Without resetting the block weight, the extra tracing overhead could
219
										// leading to some transactions to incorrectly fail during tracing.
220
21
										frame_system::BlockWeight::<Runtime>::kill();
221

            
222
21
										if transaction == traced_transaction {
223
21
											EvmTracer::new().trace(|| Executive::apply_extrinsic(ext));
224
21
											return Ok(());
225
										} else {
226
											Executive::apply_extrinsic(ext)
227
										}
228
									}
229
21
									_ => Executive::apply_extrinsic(ext),
230
								};
231

            
232
21
								if let Some(EthereumTracingStatus::TransactionExited) = EthereumTracer::status() {
233
									return Ok(());
234
21
								}
235
							}
236

            
237
							if let Some(EthereumTracingStatus::Transaction(_)) = EthereumTracer::status() {
238
								// If the transaction was not found, it might be
239
								// an eth-xcm transaction that was executed at on_idle
240
								replay_on_idle();
241
							}
242

            
243
							if let Some(EthereumTracingStatus::TransactionExited) = EthereumTracer::status() {
244
								// The transaction was found
245
								Ok(())
246
							} else {
247
								// The transaction was not-found
248
								Err(sp_runtime::DispatchError::Other(
249
									"Failed to find Ethereum transaction among the extrinsics.",
250
								))
251
							}
252
21
						})
253
					}
254
					#[cfg(not(feature = "evm-tracing"))]
255
					Err(sp_runtime::DispatchError::Other(
256
						"Missing `evm-tracing` compile time feature flag.",
257
					))
258
21
				}
259

            
260
21
				fn trace_block(
261
21
					extrinsics: Vec<<Block as BlockT>::Extrinsic>,
262
21
					known_transactions: Vec<H256>,
263
21
					header: &<Block as BlockT>::Header,
264
21
				) -> Result<
265
21
					(),
266
21
					sp_runtime::DispatchError,
267
21
				> {
268
					#[cfg(feature = "evm-tracing")]
269
					{
270
						use moonbeam_evm_tracer::tracer::{
271
							EthereumTracingStatus,
272
							EvmTracer,
273
							EthereumTracer
274
						};
275
						use frame_system::pallet_prelude::BlockNumberFor;
276

            
277
						// Tell the CallDispatcher we are tracing a full Block.
278
21
						EthereumTracer::block(|| {
279
21
							let mut config = <Runtime as pallet_evm::Config>::config().clone();
280
21
							config.estimate = true;
281

            
282
							// Initialize block: calls the "on_initialize" hook on every pallet
283
							// in AllPalletsWithSystem.
284
							// After pallet message queue was introduced, this must be done only after
285
							// enabling XCM tracing by calling ETHEREUM_TRACING_STATUS::using
286
							// in the storage
287
21
							Executive::initialize_block(header);
288

            
289
							// Apply all extrinsics. Ethereum extrinsics are traced.
290
84
							for ext in extrinsics.into_iter() {
291
84
								match &ext.0.function {
292
42
									RuntimeCall::Ethereum(transact { transaction }) => {
293

            
294
										// Reset the previously consumed weight when tracing multiple transactions.
295
										// This is necessary because EVM tracing introduces additional
296
										// (ref_time) overhead, which differs from the production runtime behavior.
297
										// Without resetting the block weight, the extra tracing overhead could
298
										// leading to some transactions to incorrectly fail during tracing.
299
42
										frame_system::BlockWeight::<Runtime>::kill();
300

            
301
42
										let tx_hash = &transaction.hash();
302
42
										if known_transactions.contains(&tx_hash) {
303
											// Each known extrinsic is a new call stack.
304
42
											EvmTracer::emit_new();
305
42
											EvmTracer::new().trace(|| {
306
42
												if let Err(err) = Executive::apply_extrinsic(ext) {
307
42
													log::debug!(
308
														target: "tracing",
309
														"Could not trace eth transaction (hash: {}): {:?}",
310
														&tx_hash,
311
														err
312
													);
313
												}
314
42
											});
315
										} else {
316
											if let Err(err) = Executive::apply_extrinsic(ext) {
317
												log::debug!(
318
													target: "tracing",
319
													"Failed to apply eth extrinsic (hash: {}): {:?}",
320
													&tx_hash,
321
													err
322
												);
323
											}
324
										}
325
									}
326
									_ => {
327
42
										if let Err(err) = Executive::apply_extrinsic(ext) {
328
											log::debug!(
329
												target: "tracing",
330
												"Failed to apply non-eth extrinsic: {:?}",
331
												err
332
											);
333
42
										}
334
									}
335
								};
336
							}
337

            
338
							// Replay on_idle
339
							// Some XCM messages with eth-xcm transaction might be executed at on_idle
340
21
							replay_on_idle();
341

            
342
21
							Ok(())
343
21
						})
344
					}
345
					#[cfg(not(feature = "evm-tracing"))]
346
					Err(sp_runtime::DispatchError::Other(
347
						"Missing `evm-tracing` compile time feature flag.",
348
					))
349
21
				}
350

            
351
21
				fn trace_call(
352
21
					header: &<Block as BlockT>::Header,
353
21
					from: H160,
354
21
					to: H160,
355
21
					data: Vec<u8>,
356
21
					value: U256,
357
21
					gas_limit: U256,
358
21
					max_fee_per_gas: Option<U256>,
359
21
					max_priority_fee_per_gas: Option<U256>,
360
21
					nonce: Option<U256>,
361
21
					access_list: Option<Vec<(H160, Vec<H256>)>>,
362
21
					authorization_list: Option<AuthorizationList>,
363
21
				) -> Result<(), sp_runtime::DispatchError> {
364
					#[cfg(feature = "evm-tracing")]
365
					{
366
						use moonbeam_evm_tracer::tracer::EvmTracer;
367

            
368
						// Initialize block: calls the "on_initialize" hook on every pallet
369
						// in AllPalletsWithSystem.
370
21
						Executive::initialize_block(header);
371

            
372
21
						EvmTracer::new().trace(|| {
373
21
							let is_transactional = false;
374
21
							let validate = true;
375

            
376
21
							let transaction_data = pallet_ethereum::TransactionData::new(
377
21
								pallet_ethereum::TransactionAction::Call(to),
378
21
								data.clone(),
379
21
								nonce.unwrap_or_default(),
380
21
								gas_limit,
381
21
								None,
382
21
								max_fee_per_gas.or(Some(U256::default())),
383
21
								max_priority_fee_per_gas.or(Some(U256::default())),
384
21
								value,
385
21
								Some(<Runtime as pallet_evm::Config>::ChainId::get()),
386
21
								access_list.clone().unwrap_or_default(),
387
21
								authorization_list.clone().unwrap_or_default(),
388
							);
389

            
390
21
							let gas_limit = gas_limit.min(u64::MAX.into()).low_u64();
391

            
392
21
							let (weight_limit, proof_size_base_cost) = pallet_ethereum::Pallet::<Runtime>::transaction_weight(&transaction_data);
393

            
394
21
							let _ = <Runtime as pallet_evm::Config>::Runner::call(
395
21
								from,
396
21
								to,
397
21
								data,
398
21
								value,
399
21
								gas_limit,
400
21
								max_fee_per_gas,
401
21
								max_priority_fee_per_gas,
402
21
								nonce,
403
21
								access_list.unwrap_or_default(),
404
21
								authorization_list.unwrap_or_default(),
405
21
								is_transactional,
406
21
								validate,
407
21
								weight_limit,
408
21
								proof_size_base_cost,
409
21
								<Runtime as pallet_evm::Config>::config(),
410
21
							);
411
21
						});
412
21
						Ok(())
413
					}
414
					#[cfg(not(feature = "evm-tracing"))]
415
					Err(sp_runtime::DispatchError::Other(
416
						"Missing `evm-tracing` compile time feature flag.",
417
					))
418
21
				}
419
			}
420

            
421
			impl moonbeam_rpc_primitives_txpool::TxPoolRuntimeApi<Block> for Runtime {
422
21
				fn extrinsic_filter(
423
21
					xts_ready: Vec<<Block as BlockT>::Extrinsic>,
424
21
					xts_future: Vec<<Block as BlockT>::Extrinsic>,
425
21
				) -> TxPoolResponse {
426
					TxPoolResponse {
427
21
						ready: xts_ready
428
21
							.into_iter()
429
42
							.filter_map(|xt| match xt.0.function {
430
21
								RuntimeCall::Ethereum(transact { transaction }) => Some(transaction),
431
21
								_ => None,
432
42
							})
433
21
							.collect(),
434
21
						future: xts_future
435
21
							.into_iter()
436
42
							.filter_map(|xt| match xt.0.function {
437
21
								RuntimeCall::Ethereum(transact { transaction }) => Some(transaction),
438
21
								_ => None,
439
42
							})
440
21
							.collect(),
441
					}
442
21
				}
443
			}
444

            
445
			impl fp_rpc::EthereumRuntimeRPCApi<Block> for Runtime {
446
21
				fn chain_id() -> u64 {
447
21
					<Runtime as pallet_evm::Config>::ChainId::get()
448
21
				}
449

            
450
21
				fn account_basic(address: H160) -> EVMAccount {
451
21
					let (account, _) = EVM::account_basic(&address);
452
21
					account
453
21
				}
454

            
455
21
				fn gas_price() -> U256 {
456
21
					let (gas_price, _) = <Runtime as pallet_evm::Config>::FeeCalculator::min_gas_price();
457
21
					gas_price
458
21
				}
459

            
460
21
				fn account_code_at(address: H160) -> Vec<u8> {
461
21
					pallet_evm::AccountCodes::<Runtime>::get(address)
462
21
				}
463

            
464
21
				fn author() -> H160 {
465
21
					<pallet_evm::Pallet<Runtime>>::find_author()
466
21
				}
467

            
468
21
				fn storage_at(address: H160, index: U256) -> H256 {
469
21
					let tmp: [u8; 32] = index.to_big_endian();
470
21
					pallet_evm::AccountStorages::<Runtime>::get(address, H256::from_slice(&tmp[..]))
471
21
				}
472

            
473
21
				fn call(
474
21
					from: H160,
475
21
					to: H160,
476
21
					data: Vec<u8>,
477
21
					value: U256,
478
21
					gas_limit: U256,
479
21
					max_fee_per_gas: Option<U256>,
480
21
					max_priority_fee_per_gas: Option<U256>,
481
21
					nonce: Option<U256>,
482
21
					estimate: bool,
483
21
					access_list: Option<Vec<(H160, Vec<H256>)>>,
484
21
					authorization_list: Option<AuthorizationList>,
485
21
				) -> Result<pallet_evm::CallInfo, sp_runtime::DispatchError> {
486
21
					let config = if estimate {
487
						let mut config = <Runtime as pallet_evm::Config>::config().clone();
488
						config.estimate = true;
489
						Some(config)
490
					} else {
491
21
						None
492
					};
493
21
					let is_transactional = false;
494
21
					let validate = true;
495

            
496
21
					let transaction_data = pallet_ethereum::TransactionData::new(
497
21
						pallet_ethereum::TransactionAction::Call(to),
498
21
						data.clone(),
499
21
						nonce.unwrap_or_default(),
500
21
						gas_limit,
501
21
						None,
502
21
						max_fee_per_gas.or(Some(U256::default())),
503
21
						max_priority_fee_per_gas.or(Some(U256::default())),
504
21
						value,
505
21
						Some(<Runtime as pallet_evm::Config>::ChainId::get()),
506
21
						access_list.clone().unwrap_or_default(),
507
21
						authorization_list.clone().unwrap_or_default(),
508
					);
509

            
510
21
					let gas_limit = gas_limit.min(u64::MAX.into()).low_u64();
511

            
512
21
					let (weight_limit, proof_size_base_cost) = pallet_ethereum::Pallet::<Runtime>::transaction_weight(&transaction_data);
513

            
514
21
					<Runtime as pallet_evm::Config>::Runner::call(
515
21
						from,
516
21
						to,
517
21
						data,
518
21
						value,
519
21
						gas_limit,
520
21
						max_fee_per_gas,
521
21
						max_priority_fee_per_gas,
522
21
						nonce,
523
21
						access_list.unwrap_or_default(),
524
21
						authorization_list.unwrap_or_default(),
525
21
						is_transactional,
526
21
						validate,
527
21
						weight_limit,
528
21
						proof_size_base_cost,
529
21
						config.as_ref().unwrap_or(<Runtime as pallet_evm::Config>::config()),
530
21
					).map_err(|err| err.error.into())
531
21
				}
532

            
533
21
				fn create(
534
21
					from: H160,
535
21
					data: Vec<u8>,
536
21
					value: U256,
537
21
					gas_limit: U256,
538
21
					max_fee_per_gas: Option<U256>,
539
21
					max_priority_fee_per_gas: Option<U256>,
540
21
					nonce: Option<U256>,
541
21
					estimate: bool,
542
21
					access_list: Option<Vec<(H160, Vec<H256>)>>,
543
21
					authorization_list: Option<AuthorizationList>,
544
21
				) -> Result<pallet_evm::CreateInfo, sp_runtime::DispatchError> {
545
21
					let config = if estimate {
546
						let mut config = <Runtime as pallet_evm::Config>::config().clone();
547
						config.estimate = true;
548
						Some(config)
549
					} else {
550
21
						None
551
					};
552
21
					let is_transactional = false;
553
21
					let validate = true;
554

            
555
21
					let transaction_data = pallet_ethereum::TransactionData::new(
556
21
						pallet_ethereum::TransactionAction::Create,
557
21
						data.clone(),
558
21
						nonce.unwrap_or_default(),
559
21
						gas_limit,
560
21
						None,
561
21
						max_fee_per_gas.or(Some(U256::default())),
562
21
						max_priority_fee_per_gas.or(Some(U256::default())),
563
21
						value,
564
21
						Some(<Runtime as pallet_evm::Config>::ChainId::get()),
565
21
						access_list.clone().unwrap_or_default(),
566
21
						authorization_list.clone().unwrap_or_default(),
567
					);
568

            
569
21
					let gas_limit = gas_limit.min(u64::MAX.into()).low_u64();
570

            
571
21
					let (weight_limit, proof_size_base_cost) = pallet_ethereum::Pallet::<Runtime>::transaction_weight(&transaction_data);
572

            
573
					#[allow(clippy::or_fun_call)] // suggestion not helpful here
574
21
					<Runtime as pallet_evm::Config>::Runner::create(
575
21
						from,
576
21
						data,
577
21
						value,
578
21
						gas_limit,
579
21
						max_fee_per_gas,
580
21
						max_priority_fee_per_gas,
581
21
						nonce,
582
21
						access_list.unwrap_or_default(),
583
21
						authorization_list.unwrap_or_default(),
584
21
						is_transactional,
585
21
						validate,
586
21
						weight_limit,
587
21
						proof_size_base_cost,
588
21
						config.as_ref().unwrap_or(<Runtime as pallet_evm::Config>::config()),
589
21
					).map_err(|err| err.error.into())
590
21
				}
591

            
592
21
				fn current_transaction_statuses() -> Option<Vec<TransactionStatus>> {
593
21
					pallet_ethereum::CurrentTransactionStatuses::<Runtime>::get()
594
21
				}
595

            
596
21
				fn current_block() -> Option<pallet_ethereum::Block> {
597
21
					pallet_ethereum::CurrentBlock::<Runtime>::get()
598
21
				}
599

            
600
21
				fn current_receipts() -> Option<Vec<pallet_ethereum::Receipt>> {
601
21
					pallet_ethereum::CurrentReceipts::<Runtime>::get()
602
21
				}
603

            
604
				fn current_all() -> (
605
					Option<pallet_ethereum::Block>,
606
					Option<Vec<pallet_ethereum::Receipt>>,
607
					Option<Vec<TransactionStatus>>,
608
				) {
609
					(
610
						pallet_ethereum::CurrentBlock::<Runtime>::get(),
611
						pallet_ethereum::CurrentReceipts::<Runtime>::get(),
612
						pallet_ethereum::CurrentTransactionStatuses::<Runtime>::get(),
613
					)
614
				}
615

            
616
				fn extrinsic_filter(
617
					xts: Vec<<Block as BlockT>::Extrinsic>,
618
				) -> Vec<EthereumTransaction> {
619
					xts.into_iter().filter_map(|xt| match xt.0.function {
620
						RuntimeCall::Ethereum(transact { transaction }) => Some(transaction),
621
						_ => None
622
					}).collect::<Vec<EthereumTransaction>>()
623
				}
624

            
625
				fn elasticity() -> Option<Permill> {
626
					None
627
				}
628

            
629
				fn gas_limit_multiplier_support() {}
630

            
631
				fn pending_block(
632
					xts: Vec<<Block as sp_runtime::traits::Block>::Extrinsic>
633
				) -> (
634
					Option<pallet_ethereum::Block>, Option<sp_std::prelude::Vec<TransactionStatus>>
635
				) {
636
					for ext in xts.into_iter() {
637
						let _ = Executive::apply_extrinsic(ext);
638
					}
639

            
640
					Ethereum::on_finalize(System::block_number() + 1);
641

            
642
					(
643
						pallet_ethereum::CurrentBlock::<Runtime>::get(),
644
						pallet_ethereum::CurrentTransactionStatuses::<Runtime>::get()
645
					)
646
				 }
647

            
648
				fn initialize_pending_block(header: &<Block as BlockT>::Header) {
649
					pallet_randomness::vrf::using_fake_vrf(|| {
650
						pallet_author_slot_filter::using_fake_author(|| {
651
							let _ = Executive::initialize_block(header);
652
						})
653
					})
654
				}
655
			}
656

            
657
			impl fp_rpc::ConvertTransactionRuntimeApi<Block> for Runtime {
658
				fn convert_transaction(
659
					transaction: pallet_ethereum::Transaction
660
				) -> <Block as BlockT>::Extrinsic {
661
					UncheckedExtrinsic::new_bare(
662
						pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),
663
					)
664
				}
665
			}
666

            
667
			impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance>
668
			for Runtime {
669
				fn query_info(
670
					uxt: <Block as BlockT>::Extrinsic,
671
					len: u32,
672
				) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo<Balance> {
673
					TransactionPayment::query_info(uxt, len)
674
				}
675

            
676
				fn query_fee_details(
677
					uxt: <Block as BlockT>::Extrinsic,
678
					len: u32,
679
				) -> pallet_transaction_payment::FeeDetails<Balance> {
680
					TransactionPayment::query_fee_details(uxt, len)
681
				}
682

            
683
				fn query_weight_to_fee(weight: Weight) -> Balance {
684
					TransactionPayment::weight_to_fee(weight)
685
				}
686

            
687
				fn query_length_to_fee(length: u32) -> Balance {
688
					TransactionPayment::length_to_fee(length)
689
				}
690
			}
691

            
692
			impl nimbus_primitives::NimbusApi<Block> for Runtime {
693
63
				fn can_author(
694
63
					author: nimbus_primitives::NimbusId,
695
63
					slot: u32,
696
63
					parent_header: &<Block as BlockT>::Header
697
63
				) -> bool {
698
					use pallet_parachain_staking::Config as PalletParachainStakingConfig;
699

            
700
63
					let block_number = parent_header.number + 1;
701

            
702
					// The Moonbeam runtimes use an entropy source that needs to do some accounting
703
					// work during block initialization. Therefore we initialize it here to match
704
					// the state it will be in when the next block is being executed.
705
					use frame_support::traits::OnInitialize;
706
63
					System::initialize(
707
63
						&block_number,
708
63
						&parent_header.hash(),
709
63
						&parent_header.digest,
710
					);
711

            
712
					// Because the staking solution calculates the next staking set at the beginning
713
					// of the first block in the new round, the only way to accurately predict the
714
					// authors is to compute the selection during prediction.
715
63
					if pallet_parachain_staking::Pallet::<Self>::round()
716
63
						.should_update(block_number) {
717
						// get author account id
718
						use nimbus_primitives::AccountLookup;
719
						let author_account_id = if let Some(account) =
720
							pallet_author_mapping::Pallet::<Self>::lookup_account(&author) {
721
							account
722
						} else {
723
							// return false if author mapping not registered like in can_author impl
724
							return false
725
						};
726
						let candidates = pallet_parachain_staking::Pallet::<Self>::compute_top_candidates();
727
						if candidates.is_empty() {
728
							// If there are zero selected candidates, we use the same eligibility
729
							// as the previous round
730
							return AuthorInherent::can_author(&author, &slot);
731
						}
732

            
733
						// predict eligibility post-selection by computing selection results now
734
						let (eligible, _) =
735
							pallet_author_slot_filter::compute_pseudo_random_subset::<Self>(
736
								candidates,
737
								&slot
738
							);
739
						eligible.contains(&author_account_id)
740
					} else {
741
63
						AuthorInherent::can_author(&author, &slot)
742
					}
743
63
				}
744
			}
745

            
746
			impl cumulus_primitives_core::CollectCollationInfo<Block> for Runtime {
747
				fn collect_collation_info(
748
					header: &<Block as BlockT>::Header
749
				) -> cumulus_primitives_core::CollationInfo {
750
					ParachainSystem::collect_collation_info(header)
751
				}
752
			}
753

            
754
			impl session_keys_primitives::VrfApi<Block> for Runtime {
755
				fn get_last_vrf_output() -> Option<<Block as BlockT>::Hash> {
756
					// TODO: remove in future runtime upgrade along with storage item
757
					if pallet_randomness::Pallet::<Self>::not_first_block().is_none() {
758
						return None;
759
					}
760
					pallet_randomness::Pallet::<Self>::local_vrf_output()
761
				}
762
				fn vrf_key_lookup(
763
					nimbus_id: nimbus_primitives::NimbusId
764
				) -> Option<session_keys_primitives::VrfId> {
765
					use session_keys_primitives::KeysLookup;
766
					AuthorMapping::lookup_keys(&nimbus_id)
767
				}
768
			}
769

            
770
			impl xcm_runtime_apis::fees::XcmPaymentApi<Block> for Runtime {
771
				fn query_acceptable_payment_assets(
772
					xcm_version: xcm::Version
773
				) -> Result<Vec<VersionedAssetId>, XcmPaymentApiError> {
774
					XcmWeightTrader::query_acceptable_payment_assets(xcm_version)
775
				}
776

            
777
				fn query_weight_to_asset_fee(
778
					weight: Weight, asset: VersionedAssetId
779
				) -> Result<u128, XcmPaymentApiError> {
780
					XcmWeightTrader::query_weight_to_asset_fee(weight, asset)
781
				}
782

            
783
				fn query_xcm_weight(message: VersionedXcm<()>) -> Result<Weight, XcmPaymentApiError> {
784
					PolkadotXcm::query_xcm_weight(message)
785
				}
786

            
787
				fn query_delivery_fees(
788
					destination: VersionedLocation, message: VersionedXcm<()>, asset_id: VersionedAssetId
789
				) -> Result<VersionedAssets, XcmPaymentApiError> {
790
					type AssetExchanger = <xcm_config::XcmExecutorConfig as xcm_executor::Config>::AssetExchanger;
791
					PolkadotXcm::query_delivery_fees::<AssetExchanger>(destination, message, asset_id)
792
				}
793
			}
794

            
795
			impl xcm_runtime_apis::dry_run::DryRunApi<Block, RuntimeCall, RuntimeEvent, OriginCaller>
796
				for Runtime {
797
					fn dry_run_call(
798
						origin: OriginCaller,
799
						call: RuntimeCall,
800
						result_xcms_version: XcmVersion
801
					) -> Result<CallDryRunEffects<RuntimeEvent>, XcmDryRunApiError> {
802
						PolkadotXcm::dry_run_call::<
803
							Runtime,
804
							xcm_config::XcmRouter,
805
							OriginCaller,
806
							RuntimeCall>(origin, call, result_xcms_version)
807
					}
808

            
809
					fn dry_run_xcm(
810
						origin_location: VersionedLocation,
811
						xcm: VersionedXcm<RuntimeCall>
812
					) -> Result<XcmDryRunEffects<RuntimeEvent>, XcmDryRunApiError> {
813
						PolkadotXcm::dry_run_xcm::<xcm_config::XcmRouter>(origin_location, xcm)
814
					}
815
				}
816

            
817
			impl xcm_runtime_apis::conversions::LocationToAccountApi<Block, AccountId> for Runtime {
818
				fn convert_location(location: VersionedLocation) -> Result<
819
					AccountId,
820
					xcm_runtime_apis::conversions::Error
821
				> {
822
					xcm_runtime_apis::conversions::LocationToAccountHelper::<
823
						AccountId,
824
						xcm_config::LocationToAccountId,
825
					>::convert_location(location)
826
				}
827
			}
828

            
829
			#[cfg(feature = "runtime-benchmarks")]
830
			impl frame_benchmarking::Benchmark<Block> for Runtime {
831

            
832
				fn benchmark_metadata(extra: bool) -> (
833
					Vec<frame_benchmarking::BenchmarkList>,
834
					Vec<frame_support::traits::StorageInfo>,
835
				) {
836
					use frame_benchmarking::{list_benchmark, Benchmarking, BenchmarkList};
837
					use frame_system_benchmarking::Pallet as SystemBench;
838
					use frame_support::traits::StorageInfoTrait;
839

            
840
					use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark;
841
					use pallet_transaction_payment::benchmarking::Pallet as TransactionPaymentBenchmark;
842

            
843
					let mut list = Vec::<BenchmarkList>::new();
844
					list_benchmarks!(list, extra);
845

            
846
					let storage_info = AllPalletsWithSystem::storage_info();
847

            
848
					return (list, storage_info)
849
				}
850

            
851
				#[allow(non_local_definitions)]
852
				fn dispatch_benchmark(
853
					config: frame_benchmarking::BenchmarkConfig,
854
				) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> {
855
					use frame_benchmarking::{add_benchmark, BenchmarkBatch, Benchmarking};
856
					use frame_support::traits::TrackedStorageKey;
857
					use cumulus_primitives_core::ParaId;
858

            
859
					use xcm::latest::prelude::{
860
						GeneralIndex, Junction, Junctions, Location, Response, NetworkId, AssetId, Here,
861
						Assets as XcmAssets, Fungible, Asset, ParentThen, Parachain, Parent, WeightLimit,
862
						AccountId32,
863
					};
864
					use xcm_config::{SelfReserve, MaxAssetsIntoHolding, AssetHubLocation, RelayLocation};
865
					use frame_benchmarking::BenchmarkError;
866
					use xcm_executor::traits::ConvertLocation;
867

            
868
					use frame_system_benchmarking::Pallet as SystemBench;
869
					// Needed to run `set_code` and `apply_authorized_upgrade` frame_system benchmarks
870
					// https://github.com/paritytech/cumulus/pull/2766
871
					impl frame_system_benchmarking::Config for Runtime {
872
						fn setup_set_code_requirements(code: &Vec<u8>) -> Result<(), BenchmarkError> {
873
							ParachainSystem::initialize_for_set_code_benchmark(code.len() as u32);
874
							Ok(())
875
						}
876

            
877
						fn verify_set_code() {
878
							System::assert_last_event(cumulus_pallet_parachain_system::Event::<Runtime>::ValidationFunctionStored.into());
879
						}
880
					}
881

            
882
					// Needed to run `charge_transaction_payment` benchmark which distributes
883
					// fees to block author. Moonbeam requires an author to be set for fee distribution.
884
					use pallet_transaction_payment::benchmarking::Pallet as TransactionPaymentBenchmark;
885
					impl pallet_transaction_payment::benchmarking::Config for Runtime {
886
						fn setup_benchmark_environment() {
887
							// Set a dummy author for the block so fee distribution doesn't panic
888
							let author: AccountId = frame_benchmarking::whitelisted_caller();
889
							pallet_author_inherent::Author::<Runtime>::put(author);
890
						}
891
					}
892

            
893
					use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark;
894
					parameter_types! {
895
						pub const RandomParaId: ParaId = ParaId::new(43211234);
896
					}
897

            
898
					/// Custom delivery helper for Moonbeam that works with H160 accounts.
899
					/// This is needed because Moonbeam uses AccountKey20 (H160) accounts
900
					/// instead of AccountId32, and the standard ToParentDeliveryHelper
901
					/// fails when trying to deposit assets to an origin location.
902
					pub struct TestDeliveryHelper;
903
					impl xcm_builder::EnsureDelivery for TestDeliveryHelper {
904
						fn ensure_successful_delivery(
905
							origin_ref: &Location,
906
							dest: &Location,
907
							_fee_reason: xcm_executor::traits::FeeReason,
908
						) -> (Option<xcm_executor::FeesMode>, Option<XcmAssets>) {
909
							use xcm_executor::traits::ConvertLocation;
910

            
911
							// Ensure the XCM sender is properly configured for benchmarks
912
							// This sets up the HostConfiguration for sending messages
913
							<xcm_config::XcmRouter as xcm::latest::SendXcm>::ensure_successful_delivery(Some(dest.clone()));
914

            
915
							// Open HRMP channel for sibling parachain destinations
916
							if let Some(Parachain(para_id)) = dest.interior().first() {
917
								ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests(
918
									(*para_id).into()
919
								);
920
							}
921

            
922
							// Deposit existential deposit to the origin account if we can convert it
923
							if let Some(account) = xcm_config::LocationToH160::convert_location(origin_ref) {
924
								let balance = ExistentialDeposit::get() * 1000u128;
925
								let _ = <Balances as frame_support::traits::Currency<_>>::
926
									make_free_balance_be(&account.into(), balance);
927
							}
928

            
929
							(None, None)
930
						}
931
					}
932

            
933
					impl pallet_xcm::benchmarking::Config for Runtime {
934
				        type DeliveryHelper = TestDeliveryHelper;
935

            
936
						fn get_asset() -> Asset {
937
							Asset {
938
								id: AssetId(SelfReserve::get()),
939
								fun: Fungible(ExistentialDeposit::get()),
940
							}
941
						}
942

            
943
						fn reachable_dest() -> Option<Location> {
944
							Some(Parent.into())
945
						}
946

            
947
						fn teleportable_asset_and_dest() -> Option<(Asset, Location)> {
948
							None
949
						}
950

            
951
						fn reserve_transferable_asset_and_dest() -> Option<(Asset, Location)> {
952
							use xcm_config::SelfReserve;
953

            
954
							ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests(
955
								RandomParaId::get().into()
956
							);
957

            
958
							Some((
959
								Asset {
960
									fun: Fungible(ExistentialDeposit::get()),
961
									id: AssetId(SelfReserve::get().into())
962
								},
963
								// Moonbeam can reserve transfer native token to
964
								// some random parachain.
965
								ParentThen(Parachain(RandomParaId::get().into()).into()).into(),
966
							))
967
						}
968

            
969
						fn set_up_complex_asset_transfer(
970
						) -> Option<(XcmAssets, u32, Location, Box<dyn FnOnce()>)> {
971
							use xcm_config::SelfReserve;
972

            
973
							let destination: xcm::v5::Location = Parent.into();
974

            
975
							let fee_amount: u128 = <Runtime as pallet_balances::Config>::ExistentialDeposit::get();
976
							let fee_asset: Asset = (SelfReserve::get(), fee_amount).into();
977

            
978
							// Give some multiple of transferred amount
979
							let balance = fee_amount * 1000;
980
							let who = frame_benchmarking::whitelisted_caller();
981
							let _ =
982
								<Balances as frame_support::traits::Currency<_>>::make_free_balance_be(&who, balance);
983

            
984
							// verify initial balance
985
							assert_eq!(Balances::free_balance(&who), balance);
986

            
987
							// set up foreign asset
988
							let asset_amount: u128 = 10u128;
989
							let initial_asset_amount: u128 = asset_amount * 10;
990

            
991
							let asset_id = pallet_moonbeam_foreign_assets::default_asset_id::<Runtime>() + 1;
992
							let (_, location, _) = pallet_moonbeam_foreign_assets::create_default_minted_foreign_asset::<Runtime>(
993
								asset_id,
994
								initial_asset_amount,
995
							);
996
							let transfer_asset: Asset = (AssetId(location), asset_amount).into();
997

            
998
							let assets: XcmAssets = vec![fee_asset.clone(), transfer_asset].into();
999
							let fee_index: u32 = 0;
							let verify: Box<dyn FnOnce()> = Box::new(move || {
								// verify balance after transfer, decreased by
								// transferred amount (and delivery fees)
								assert!(Balances::free_balance(&who) <= balance - fee_amount);
							});
							Some((assets, fee_index, destination, verify))
						}
					}
					impl pallet_xcm_benchmarks::Config for Runtime {
						type XcmConfig = xcm_config::XcmExecutorConfig;
						type AccountIdConverter = BenchAccountIdConverter<AccountId>;
						type DeliveryHelper = TestDeliveryHelper;
						fn valid_destination() -> Result<Location, BenchmarkError> {
							Ok(Location::parent())
						}
						fn worst_case_holding(_depositable_count: u32) -> XcmAssets {
							const HOLDING_FUNGIBLES: u32 = MaxAssetsIntoHolding::get();
							let fungibles_amount: u128 = 1_000 * ExistentialDeposit::get();
							let assets = (1..=HOLDING_FUNGIBLES).map(|i| {
								let location: Location = GeneralIndex(i as u128).into();
								Asset {
									id: AssetId(location),
									fun: Fungible(fungibles_amount * i as u128),
								}
								.into()
							})
							.chain(
								core::iter::once(
									Asset {
										id: AssetId(Location::parent()),
										fun: Fungible(u128::MAX)
									}
								)
							)
							.collect::<Vec<_>>();
							for (i, asset) in assets.iter().enumerate() {
								if let Asset {
									id: AssetId(location),
									fun: Fungible(_)
								} = asset {
									EvmForeignAssets::set_asset(
										location.clone(),
										i as u128
									);
									XcmWeightTrader::set_asset_price(
										location.clone(),
										10u128.pow(18)
									);
								}
							}
							assets.into()
						}
					}
					parameter_types! {
						// Native token location
						pub const TokenLocation: Location = Here.into_location();
						pub TrustedTeleporter: Option<(Location, Asset)> = None;
						pub CheckedAccount: Option<(AccountId, xcm_builder::MintLocation)> = None;
						// Reserve location and asset used by the `reserve_asset_deposited` benchmark.
						// We use DOT (asset id = `RelayLocation`) whose reserve is Asset Hub.
						pub TrustedReserve: Option<(Location, Asset)> = Some((
							AssetHubLocation::get(),
							Asset {
								id: AssetId(RelayLocation::get()),
								fun: Fungible(100 * ExistentialDeposit::get()),
							}
						));
					}
					impl pallet_xcm_benchmarks::fungible::Config for Runtime {
						type TransactAsset = Balances;
						type CheckedAccount = CheckedAccount;
						type TrustedTeleporter = TrustedTeleporter;
						type TrustedReserve = TrustedReserve;
						fn get_asset() -> Asset {
							// We put more than ED here for being able to keep accounts alive when transferring
							// and paying the delivery fees.
							let location: Location = GeneralIndex(1).into();
							let asset_id = 1u128;
							let decimals = 18u8;
							let asset = Asset {
								id: AssetId(location.clone()),
								fun: Fungible(100 * ExistentialDeposit::get()),
							};
							EvmForeignAssets::set_asset(
								location.clone(),
								asset_id,
							);
							XcmWeightTrader::set_asset_price(
								location.clone(),
								10u128.pow(decimals as u32)
							);
							EvmForeignAssets::create_asset_contract(
								asset_id,
								decimals,
								"TKN",
								"Token",
							).unwrap();
							asset
						}
					}
					impl pallet_xcm_benchmarks::generic::Config for Runtime {
						type RuntimeCall = RuntimeCall;
						type TransactAsset = Balances;
						fn worst_case_response() -> (u64, Response) {
							(0u64, Response::Version(Default::default()))
						}
						fn worst_case_asset_exchange()
							-> Result<(XcmAssets, XcmAssets), BenchmarkError> {
							Err(BenchmarkError::Skip)
						}
						fn universal_alias() -> Result<(Location, Junction), BenchmarkError> {
							Err(BenchmarkError::Skip)
						}
						fn export_message_origin_and_destination()
							-> Result<(Location, NetworkId, Junctions), BenchmarkError> {
							Err(BenchmarkError::Skip)
						}
						fn transact_origin_and_runtime_call()
							-> Result<(Location, RuntimeCall), BenchmarkError> {
							Ok((Location::parent(), frame_system::Call::remark_with_event {
								remark: vec![]
							}.into()))
						}
						fn subscribe_origin() -> Result<Location, BenchmarkError> {
							Ok(Location::parent())
						}
						fn claimable_asset()
							-> Result<(Location, Location, XcmAssets), BenchmarkError> {
							let origin = Location::parent();
							let assets: XcmAssets = (AssetId(Location::parent()), 1_000u128)
								.into();
							let ticket = Location { parents: 0, interior: [].into() /* Here */ };
							Ok((origin, ticket, assets))
						}
						fn worst_case_for_trader() -> Result<(Asset, WeightLimit), BenchmarkError> {
							let location: Location = GeneralIndex(1).into();
							Ok((
								Asset {
									id: AssetId(Location::parent()),
									fun: Fungible(1_000_000_000_000_000 as u128)
								},
								WeightLimit::Limited(Weight::from_parts(5000, 5000)),
							))
						}
						fn unlockable_asset()
							-> Result<(Location, Location, Asset), BenchmarkError> {
							Err(BenchmarkError::Skip)
						}
						fn alias_origin() -> Result<(Location, Location), BenchmarkError> {
							Err(BenchmarkError::Skip)
						}
					}
					$($bench_custom)*
					let whitelist: Vec<TrackedStorageKey> = vec![
						// Block Number
						hex_literal::hex!(  "26aa394eea5630e07c48ae0c9558cef7"
											"02a5c1b19ab7a04f536c519aca4983ac")
							.to_vec().into(),
						// Total Issuance
						hex_literal::hex!(  "c2261276cc9d1f8598ea4b6a74b15c2f"
											"57c875e4cff74148e4628f264b974c80")
							.to_vec().into(),
						// Execution Phase
						hex_literal::hex!(  "26aa394eea5630e07c48ae0c9558cef7"
											"ff553b5a9862a516939d82b3d3d8661a")
							.to_vec().into(),
						// Event Count
						hex_literal::hex!(  "26aa394eea5630e07c48ae0c9558cef7"
											"0a98fdbe9ce6c55837576c60c7af3850")
							.to_vec().into(),
						// System Events
						hex_literal::hex!(  "26aa394eea5630e07c48ae0c9558cef7"
											"80d41e5e16056765bc8461851072c9d7")
							.to_vec().into(),
						// System BlockWeight
						hex_literal::hex!(  "26aa394eea5630e07c48ae0c9558cef7"
											"34abf5cb34d6244378cddbf18e849d96")
							.to_vec().into(),
						// ParachainStaking Round
						hex_literal::hex!(  "a686a3043d0adcf2fa655e57bc595a78"
											"13792e785168f725b60e2969c7fc2552")
							.to_vec().into(),
						// Treasury Account (py/trsry)
						hex_literal::hex!(  "26aa394eea5630e07c48ae0c9558cef7"
											"b99d880ec681799c0cf30e8886371da9"
											"7be2919ac397ba499ea5e57132180ec6"
											"6d6f646c70792f747273727900000000"
											"00000000"
						).to_vec().into(),
						// Treasury Account (pc/trsry)
						hex_literal::hex!(  "26aa394eea5630e07c48ae0c9558cef7"
											"b99d880ec681799c0cf30e8886371da9"
											"7be2919ac397ba499ea5e57132180ec6"
											"6d6f646c70632f747273727900000000"
											"00000000"
						).to_vec().into(),
						// ParachainInfo ParachainId
						hex_literal::hex!(  "0d715f2646c8f85767b5d2764bb27826"
											"04a74d81251e398fd8a0a4d55023bb3f")
							.to_vec().into(),
						// Parameters Parameters
						hex_literal::hex!(  "c63bdd4a39095ccf55623a6f2872bf8a" // Pallet: "Parameters"
											"c63bdd4a39095ccf55623a6f2872bf8a" // Storage Prefix: "Parameters"
											// MoonbaseRuntimeRuntimeParamsRuntimeParametersKey(FeesTreasuryProportion)
											"71d0aacb690b61280d0c97c6b6a666640000"
										)
							.to_vec().into(),
					];
					let mut batches = Vec::<BenchmarkBatch>::new();
					let params = (&config, &whitelist);
					add_benchmarks!(params, batches);
					Ok(batches)
				}
			}
			#[cfg(feature = "try-runtime")]
			impl frame_try_runtime::TryRuntime<Block> for Runtime {
				fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) {
					log::info!("try-runtime::on_runtime_upgrade()");
					// NOTE: intentional expect: we don't want to propagate the error backwards,
					// and want to have a backtrace here. If any of the pre/post migration checks
					// fail, we shall stop right here and right now.
					let weight = Executive::try_runtime_upgrade(checks)
						.expect("runtime upgrade logic *must* be infallible");
					(weight, RuntimeBlockWeights::get().max_block)
				}
				fn execute_block(
					block: <Block as BlockT>::LazyBlock,
					state_root_check: bool,
					signature_check: bool,
					select: frame_try_runtime::TryStateSelect
				) -> Weight {
					log::info!(
						"try-runtime: executing block {:?} / root checks: {:?} / try-state-select: {:?}",
						block.header.hash(),
						state_root_check,
						select,
					);
					// NOTE: intentional unwrap: we don't want to propagate the error backwards,
					// and want to have a backtrace here.
					Executive::try_execute_block(
						block,
						state_root_check,
						signature_check,
						select,
					).expect("execute-block failed")
				}
			}
926303
		}
	};
}