1#[macro_export]
18macro_rules! impl_runtime_apis_plus_common {
19 ({$($custom:tt)*} {$($bench_custom:tt)*}) => {
20 use ethereum::AuthorizationList;
21
22 #[cfg(feature = "evm-tracing")]
23 fn replay_on_idle() {
30 use frame_system::pallet_prelude::BlockNumberFor;
31 use frame_support::traits::OnIdle;
32
33 let weight = <frame_system::Pallet<Runtime>>::block_weight();
34 let max_weight = <
35 <Runtime as frame_system::Config>::BlockWeights as
36 frame_support::traits::Get<_>
37 >::get().max_block;
38 let remaining_weight = max_weight.saturating_sub(weight.total());
39 if remaining_weight.all_gt(Weight::zero()) {
40 let _ = <AllPalletsWithSystem as OnIdle<BlockNumberFor<Runtime>>>::on_idle(
41 <frame_system::Pallet<Runtime>>::block_number(),
42 remaining_weight,
43 );
44 }
45 }
46
47 impl_runtime_apis! {
48 $($custom)*
49
50 impl sp_api::Core<Block> for Runtime {
51 fn version() -> RuntimeVersion {
52 VERSION
53 }
54
55 fn execute_block(block: Block) {
56 Executive::execute_block(block)
57 }
58
59 fn initialize_block(header: &<Block as BlockT>::Header) -> sp_runtime::ExtrinsicInclusionMode {
60 Executive::initialize_block(header)
61 }
62 }
63
64 impl cumulus_primitives_core::RelayParentOffsetApi<Block> for Runtime {
65 fn relay_parent_offset() -> u32 {
66 crate::RELAY_PARENT_OFFSET
67 }
68 }
69
70 impl cumulus_primitives_core::GetCoreSelectorApi<Block> for Runtime {
71 fn core_selector() -> (cumulus_primitives_core::CoreSelector, cumulus_primitives_core::ClaimQueueOffset) {
72 ParachainSystem::core_selector()
73 }
74 }
75
76 impl sp_api::Metadata<Block> for Runtime {
77 fn metadata() -> OpaqueMetadata {
78 OpaqueMetadata::new(Runtime::metadata().into())
79 }
80
81 fn metadata_at_version(version: u32) -> Option<OpaqueMetadata> {
82 Runtime::metadata_at_version(version)
83 }
84
85 fn metadata_versions() -> Vec<u32> {
86 Runtime::metadata_versions()
87 }
88 }
89
90 impl sp_block_builder::BlockBuilder<Block> for Runtime {
91 fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {
92 Executive::apply_extrinsic(extrinsic)
93 }
94
95 fn finalize_block() -> <Block as BlockT>::Header {
96 Executive::finalize_block()
97 }
98
99 fn inherent_extrinsics(
100 data: sp_inherents::InherentData,
101 ) -> Vec<<Block as BlockT>::Extrinsic> {
102 data.create_extrinsics()
103 }
104
105 fn check_inherents(
106 block: Block,
107 data: sp_inherents::InherentData,
108 ) -> sp_inherents::CheckInherentsResult {
109 data.check_extrinsics(&block)
110 }
111 }
112
113 impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
114 fn offchain_worker(header: &<Block as BlockT>::Header) {
115 Executive::offchain_worker(header)
116 }
117 }
118
119 impl sp_session::SessionKeys<Block> for Runtime {
120 fn decode_session_keys(
121 encoded: Vec<u8>,
122 ) -> Option<Vec<(Vec<u8>, sp_core::crypto::KeyTypeId)>> {
123 opaque::SessionKeys::decode_into_raw_public_keys(&encoded)
124 }
125
126 fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
127 opaque::SessionKeys::generate(seed)
128 }
129 }
130
131 impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
132 fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
133 frame_support::genesis_builder_helper::build_state::<RuntimeGenesisConfig>(config)
134 }
135
136 #[cfg(not(feature = "disable-genesis-builder"))]
137 fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
138 frame_support::genesis_builder_helper::get_preset::<RuntimeGenesisConfig>(id, genesis_config_preset::get_preset)
139 }
140 #[cfg(feature = "disable-genesis-builder")]
141 fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
142 None
143 }
144
145 #[cfg(not(feature = "disable-genesis-builder"))]
146 fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
147 genesis_config_preset::preset_names()
148 }
149 #[cfg(feature = "disable-genesis-builder")]
150 fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
151 Default::default()
152 }
153 }
154
155 impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Index> for Runtime {
156 fn account_nonce(account: AccountId) -> Index {
157 System::account_nonce(account)
158 }
159 }
160
161 impl moonbeam_rpc_primitives_debug::DebugRuntimeApi<Block> for Runtime {
162 fn trace_transaction(
163 extrinsics: Vec<<Block as BlockT>::Extrinsic>,
164 traced_transaction: &EthereumTransaction,
165 header: &<Block as BlockT>::Header,
166 ) -> Result<
167 (),
168 sp_runtime::DispatchError,
169 > {
170 #[cfg(feature = "evm-tracing")]
171 {
172 use moonbeam_evm_tracer::tracer::{
173 EthereumTracingStatus,
174 EvmTracer,
175 EthereumTracer
176 };
177 use frame_support::storage::unhashed;
178 use frame_system::pallet_prelude::BlockNumberFor;
179
180 EthereumTracer::transaction(traced_transaction.hash(), || {
182 Executive::initialize_block(header);
188
189 for ext in extrinsics.into_iter() {
192 let _ = match &ext.0.function {
193 RuntimeCall::Ethereum(transact { transaction }) => {
194 frame_system::BlockWeight::<Runtime>::kill();
200
201 if transaction == traced_transaction {
202 EvmTracer::new().trace(|| Executive::apply_extrinsic(ext));
203 return Ok(());
204 } else {
205 Executive::apply_extrinsic(ext)
206 }
207 }
208 _ => Executive::apply_extrinsic(ext),
209 };
210
211 if let Some(EthereumTracingStatus::TransactionExited) = EthereumTracer::status() {
212 return Ok(());
213 }
214 }
215
216 if let Some(EthereumTracingStatus::Transaction(_)) = EthereumTracer::status() {
217 replay_on_idle();
220 }
221
222 if let Some(EthereumTracingStatus::TransactionExited) = EthereumTracer::status() {
223 Ok(())
225 } else {
226 Err(sp_runtime::DispatchError::Other(
228 "Failed to find Ethereum transaction among the extrinsics.",
229 ))
230 }
231 })
232 }
233 #[cfg(not(feature = "evm-tracing"))]
234 Err(sp_runtime::DispatchError::Other(
235 "Missing `evm-tracing` compile time feature flag.",
236 ))
237 }
238
239 fn trace_block(
240 extrinsics: Vec<<Block as BlockT>::Extrinsic>,
241 known_transactions: Vec<H256>,
242 header: &<Block as BlockT>::Header,
243 ) -> Result<
244 (),
245 sp_runtime::DispatchError,
246 > {
247 #[cfg(feature = "evm-tracing")]
248 {
249 use moonbeam_evm_tracer::tracer::{
250 EthereumTracingStatus,
251 EvmTracer,
252 EthereumTracer
253 };
254 use frame_system::pallet_prelude::BlockNumberFor;
255
256 EthereumTracer::block(|| {
258 let mut config = <Runtime as pallet_evm::Config>::config().clone();
259 config.estimate = true;
260
261 Executive::initialize_block(header);
267
268 for ext in extrinsics.into_iter() {
270 match &ext.0.function {
271 RuntimeCall::Ethereum(transact { transaction }) => {
272
273 frame_system::BlockWeight::<Runtime>::kill();
279
280 let tx_hash = &transaction.hash();
281 if known_transactions.contains(&tx_hash) {
282 EvmTracer::emit_new();
284 EvmTracer::new().trace(|| {
285 if let Err(err) = Executive::apply_extrinsic(ext) {
286 log::debug!(
287 target: "tracing",
288 "Could not trace eth transaction (hash: {}): {:?}",
289 &tx_hash,
290 err
291 );
292 }
293 });
294 } else {
295 if let Err(err) = Executive::apply_extrinsic(ext) {
296 log::debug!(
297 target: "tracing",
298 "Failed to apply eth extrinsic (hash: {}): {:?}",
299 &tx_hash,
300 err
301 );
302 }
303 }
304 }
305 _ => {
306 if let Err(err) = Executive::apply_extrinsic(ext) {
307 log::debug!(
308 target: "tracing",
309 "Failed to apply non-eth extrinsic: {:?}",
310 err
311 );
312 }
313 }
314 };
315 }
316
317 replay_on_idle();
320
321 Ok(())
322 })
323 }
324 #[cfg(not(feature = "evm-tracing"))]
325 Err(sp_runtime::DispatchError::Other(
326 "Missing `evm-tracing` compile time feature flag.",
327 ))
328 }
329
330 fn trace_call(
331 header: &<Block as BlockT>::Header,
332 from: H160,
333 to: H160,
334 data: Vec<u8>,
335 value: U256,
336 gas_limit: U256,
337 max_fee_per_gas: Option<U256>,
338 max_priority_fee_per_gas: Option<U256>,
339 nonce: Option<U256>,
340 access_list: Option<Vec<(H160, Vec<H256>)>>,
341 authorization_list: Option<AuthorizationList>,
342 ) -> Result<(), sp_runtime::DispatchError> {
343 #[cfg(feature = "evm-tracing")]
344 {
345 use moonbeam_evm_tracer::tracer::EvmTracer;
346
347 Executive::initialize_block(header);
350
351 EvmTracer::new().trace(|| {
352 let is_transactional = false;
353 let validate = true;
354
355 let transaction_data = pallet_ethereum::TransactionData::new(
356 pallet_ethereum::TransactionAction::Call(to),
357 data.clone(),
358 nonce.unwrap_or_default(),
359 gas_limit,
360 None,
361 max_fee_per_gas.or(Some(U256::default())),
362 max_priority_fee_per_gas.or(Some(U256::default())),
363 value,
364 Some(<Runtime as pallet_evm::Config>::ChainId::get()),
365 access_list.clone().unwrap_or_default(),
366 authorization_list.clone().unwrap_or_default(),
367 );
368
369 let gas_limit = gas_limit.min(u64::MAX.into()).low_u64();
370
371 let (weight_limit, proof_size_base_cost) = pallet_ethereum::Pallet::<Runtime>::transaction_weight(&transaction_data);
372
373 let _ = <Runtime as pallet_evm::Config>::Runner::call(
374 from,
375 to,
376 data,
377 value,
378 gas_limit,
379 max_fee_per_gas,
380 max_priority_fee_per_gas,
381 nonce,
382 access_list.unwrap_or_default(),
383 authorization_list.unwrap_or_default(),
384 is_transactional,
385 validate,
386 weight_limit,
387 proof_size_base_cost,
388 <Runtime as pallet_evm::Config>::config(),
389 );
390 });
391 Ok(())
392 }
393 #[cfg(not(feature = "evm-tracing"))]
394 Err(sp_runtime::DispatchError::Other(
395 "Missing `evm-tracing` compile time feature flag.",
396 ))
397 }
398 }
399
400 impl moonbeam_rpc_primitives_txpool::TxPoolRuntimeApi<Block> for Runtime {
401 fn extrinsic_filter(
402 xts_ready: Vec<<Block as BlockT>::Extrinsic>,
403 xts_future: Vec<<Block as BlockT>::Extrinsic>,
404 ) -> TxPoolResponse {
405 TxPoolResponse {
406 ready: xts_ready
407 .into_iter()
408 .filter_map(|xt| match xt.0.function {
409 RuntimeCall::Ethereum(transact { transaction }) => Some(transaction),
410 _ => None,
411 })
412 .collect(),
413 future: xts_future
414 .into_iter()
415 .filter_map(|xt| match xt.0.function {
416 RuntimeCall::Ethereum(transact { transaction }) => Some(transaction),
417 _ => None,
418 })
419 .collect(),
420 }
421 }
422 }
423
424 impl fp_rpc::EthereumRuntimeRPCApi<Block> for Runtime {
425 fn chain_id() -> u64 {
426 <Runtime as pallet_evm::Config>::ChainId::get()
427 }
428
429 fn account_basic(address: H160) -> EVMAccount {
430 let (account, _) = EVM::account_basic(&address);
431 account
432 }
433
434 fn gas_price() -> U256 {
435 let (gas_price, _) = <Runtime as pallet_evm::Config>::FeeCalculator::min_gas_price();
436 gas_price
437 }
438
439 fn account_code_at(address: H160) -> Vec<u8> {
440 pallet_evm::AccountCodes::<Runtime>::get(address)
441 }
442
443 fn author() -> H160 {
444 <pallet_evm::Pallet<Runtime>>::find_author()
445 }
446
447 fn storage_at(address: H160, index: U256) -> H256 {
448 let tmp: [u8; 32] = index.to_big_endian();
449 pallet_evm::AccountStorages::<Runtime>::get(address, H256::from_slice(&tmp[..]))
450 }
451
452 fn call(
453 from: H160,
454 to: H160,
455 data: Vec<u8>,
456 value: U256,
457 gas_limit: U256,
458 max_fee_per_gas: Option<U256>,
459 max_priority_fee_per_gas: Option<U256>,
460 nonce: Option<U256>,
461 estimate: bool,
462 access_list: Option<Vec<(H160, Vec<H256>)>>,
463 authorization_list: Option<AuthorizationList>,
464 ) -> Result<pallet_evm::CallInfo, sp_runtime::DispatchError> {
465 let config = if estimate {
466 let mut config = <Runtime as pallet_evm::Config>::config().clone();
467 config.estimate = true;
468 Some(config)
469 } else {
470 None
471 };
472 let is_transactional = false;
473 let validate = true;
474
475 let transaction_data = pallet_ethereum::TransactionData::new(
476 pallet_ethereum::TransactionAction::Call(to),
477 data.clone(),
478 nonce.unwrap_or_default(),
479 gas_limit,
480 None,
481 max_fee_per_gas.or(Some(U256::default())),
482 max_priority_fee_per_gas.or(Some(U256::default())),
483 value,
484 Some(<Runtime as pallet_evm::Config>::ChainId::get()),
485 access_list.clone().unwrap_or_default(),
486 authorization_list.clone().unwrap_or_default(),
487 );
488
489 let gas_limit = gas_limit.min(u64::MAX.into()).low_u64();
490
491 let (weight_limit, proof_size_base_cost) = pallet_ethereum::Pallet::<Runtime>::transaction_weight(&transaction_data);
492
493 <Runtime as pallet_evm::Config>::Runner::call(
494 from,
495 to,
496 data,
497 value,
498 gas_limit,
499 max_fee_per_gas,
500 max_priority_fee_per_gas,
501 nonce,
502 access_list.unwrap_or_default(),
503 authorization_list.unwrap_or_default(),
504 is_transactional,
505 validate,
506 weight_limit,
507 proof_size_base_cost,
508 config.as_ref().unwrap_or(<Runtime as pallet_evm::Config>::config()),
509 ).map_err(|err| err.error.into())
510 }
511
512 fn create(
513 from: H160,
514 data: Vec<u8>,
515 value: U256,
516 gas_limit: U256,
517 max_fee_per_gas: Option<U256>,
518 max_priority_fee_per_gas: Option<U256>,
519 nonce: Option<U256>,
520 estimate: bool,
521 access_list: Option<Vec<(H160, Vec<H256>)>>,
522 authorization_list: Option<AuthorizationList>,
523 ) -> Result<pallet_evm::CreateInfo, sp_runtime::DispatchError> {
524 let config = if estimate {
525 let mut config = <Runtime as pallet_evm::Config>::config().clone();
526 config.estimate = true;
527 Some(config)
528 } else {
529 None
530 };
531 let is_transactional = false;
532 let validate = true;
533
534 let transaction_data = pallet_ethereum::TransactionData::new(
535 pallet_ethereum::TransactionAction::Create,
536 data.clone(),
537 nonce.unwrap_or_default(),
538 gas_limit,
539 None,
540 max_fee_per_gas.or(Some(U256::default())),
541 max_priority_fee_per_gas.or(Some(U256::default())),
542 value,
543 Some(<Runtime as pallet_evm::Config>::ChainId::get()),
544 access_list.clone().unwrap_or_default(),
545 authorization_list.clone().unwrap_or_default(),
546 );
547
548 let gas_limit = gas_limit.min(u64::MAX.into()).low_u64();
549
550 let (weight_limit, proof_size_base_cost) = pallet_ethereum::Pallet::<Runtime>::transaction_weight(&transaction_data);
551
552 #[allow(clippy::or_fun_call)] <Runtime as pallet_evm::Config>::Runner::create(
554 from,
555 data,
556 value,
557 gas_limit,
558 max_fee_per_gas,
559 max_priority_fee_per_gas,
560 nonce,
561 access_list.unwrap_or_default(),
562 authorization_list.unwrap_or_default(),
563 is_transactional,
564 validate,
565 weight_limit,
566 proof_size_base_cost,
567 config.as_ref().unwrap_or(<Runtime as pallet_evm::Config>::config()),
568 ).map_err(|err| err.error.into())
569 }
570
571 fn current_transaction_statuses() -> Option<Vec<TransactionStatus>> {
572 pallet_ethereum::CurrentTransactionStatuses::<Runtime>::get()
573 }
574
575 fn current_block() -> Option<pallet_ethereum::Block> {
576 pallet_ethereum::CurrentBlock::<Runtime>::get()
577 }
578
579 fn current_receipts() -> Option<Vec<pallet_ethereum::Receipt>> {
580 pallet_ethereum::CurrentReceipts::<Runtime>::get()
581 }
582
583 fn current_all() -> (
584 Option<pallet_ethereum::Block>,
585 Option<Vec<pallet_ethereum::Receipt>>,
586 Option<Vec<TransactionStatus>>,
587 ) {
588 (
589 pallet_ethereum::CurrentBlock::<Runtime>::get(),
590 pallet_ethereum::CurrentReceipts::<Runtime>::get(),
591 pallet_ethereum::CurrentTransactionStatuses::<Runtime>::get(),
592 )
593 }
594
595 fn extrinsic_filter(
596 xts: Vec<<Block as BlockT>::Extrinsic>,
597 ) -> Vec<EthereumTransaction> {
598 xts.into_iter().filter_map(|xt| match xt.0.function {
599 RuntimeCall::Ethereum(transact { transaction }) => Some(transaction),
600 _ => None
601 }).collect::<Vec<EthereumTransaction>>()
602 }
603
604 fn elasticity() -> Option<Permill> {
605 None
606 }
607
608 fn gas_limit_multiplier_support() {}
609
610 fn pending_block(
611 xts: Vec<<Block as sp_runtime::traits::Block>::Extrinsic>
612 ) -> (
613 Option<pallet_ethereum::Block>, Option<sp_std::prelude::Vec<TransactionStatus>>
614 ) {
615 for ext in xts.into_iter() {
616 let _ = Executive::apply_extrinsic(ext);
617 }
618
619 Ethereum::on_finalize(System::block_number() + 1);
620
621 (
622 pallet_ethereum::CurrentBlock::<Runtime>::get(),
623 pallet_ethereum::CurrentTransactionStatuses::<Runtime>::get()
624 )
625 }
626
627 fn initialize_pending_block(header: &<Block as BlockT>::Header) {
628 pallet_randomness::vrf::using_fake_vrf(|| {
629 let _ = Executive::initialize_block(header);
630 })
631 }
632 }
633
634 impl fp_rpc::ConvertTransactionRuntimeApi<Block> for Runtime {
635 fn convert_transaction(
636 transaction: pallet_ethereum::Transaction
637 ) -> <Block as BlockT>::Extrinsic {
638 UncheckedExtrinsic::new_bare(
639 pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),
640 )
641 }
642 }
643
644 impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance>
645 for Runtime {
646 fn query_info(
647 uxt: <Block as BlockT>::Extrinsic,
648 len: u32,
649 ) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo<Balance> {
650 TransactionPayment::query_info(uxt, len)
651 }
652
653 fn query_fee_details(
654 uxt: <Block as BlockT>::Extrinsic,
655 len: u32,
656 ) -> pallet_transaction_payment::FeeDetails<Balance> {
657 TransactionPayment::query_fee_details(uxt, len)
658 }
659
660 fn query_weight_to_fee(weight: Weight) -> Balance {
661 TransactionPayment::weight_to_fee(weight)
662 }
663
664 fn query_length_to_fee(length: u32) -> Balance {
665 TransactionPayment::length_to_fee(length)
666 }
667 }
668
669 impl nimbus_primitives::NimbusApi<Block> for Runtime {
670 fn can_author(
671 author: nimbus_primitives::NimbusId,
672 slot: u32,
673 parent_header: &<Block as BlockT>::Header
674 ) -> bool {
675 use pallet_parachain_staking::Config as PalletParachainStakingConfig;
676
677 let block_number = parent_header.number + 1;
678
679 use frame_support::traits::OnInitialize;
683 System::initialize(
684 &block_number,
685 &parent_header.hash(),
686 &parent_header.digest,
687 );
688
689 if pallet_parachain_staking::Pallet::<Self>::round()
693 .should_update(block_number) {
694 use nimbus_primitives::AccountLookup;
696 let author_account_id = if let Some(account) =
697 pallet_author_mapping::Pallet::<Self>::lookup_account(&author) {
698 account
699 } else {
700 return false
702 };
703 let candidates = pallet_parachain_staking::Pallet::<Self>::compute_top_candidates();
704 if candidates.is_empty() {
705 return AuthorInherent::can_author(&author, &slot);
708 }
709
710 let (eligible, _) =
712 pallet_author_slot_filter::compute_pseudo_random_subset::<Self>(
713 candidates,
714 &slot
715 );
716 eligible.contains(&author_account_id)
717 } else {
718 AuthorInherent::can_author(&author, &slot)
719 }
720 }
721 }
722
723 impl cumulus_primitives_core::CollectCollationInfo<Block> for Runtime {
724 fn collect_collation_info(
725 header: &<Block as BlockT>::Header
726 ) -> cumulus_primitives_core::CollationInfo {
727 ParachainSystem::collect_collation_info(header)
728 }
729 }
730
731 impl session_keys_primitives::VrfApi<Block> for Runtime {
732 fn get_last_vrf_output() -> Option<<Block as BlockT>::Hash> {
733 if pallet_randomness::Pallet::<Self>::not_first_block().is_none() {
735 return None;
736 }
737 pallet_randomness::Pallet::<Self>::local_vrf_output()
738 }
739 fn vrf_key_lookup(
740 nimbus_id: nimbus_primitives::NimbusId
741 ) -> Option<session_keys_primitives::VrfId> {
742 use session_keys_primitives::KeysLookup;
743 AuthorMapping::lookup_keys(&nimbus_id)
744 }
745 }
746
747 impl xcm_runtime_apis::fees::XcmPaymentApi<Block> for Runtime {
748 fn query_acceptable_payment_assets(
749 xcm_version: xcm::Version
750 ) -> Result<Vec<VersionedAssetId>, XcmPaymentApiError> {
751 XcmWeightTrader::query_acceptable_payment_assets(xcm_version)
752 }
753
754 fn query_weight_to_asset_fee(
755 weight: Weight, asset: VersionedAssetId
756 ) -> Result<u128, XcmPaymentApiError> {
757 XcmWeightTrader::query_weight_to_asset_fee(weight, asset)
758 }
759
760 fn query_xcm_weight(message: VersionedXcm<()>) -> Result<Weight, XcmPaymentApiError> {
761 PolkadotXcm::query_xcm_weight(message)
762 }
763
764 fn query_delivery_fees(
765 destination: VersionedLocation, message: VersionedXcm<()>
766 ) -> Result<VersionedAssets, XcmPaymentApiError> {
767 PolkadotXcm::query_delivery_fees(destination, message)
768 }
769 }
770
771 impl xcm_runtime_apis::dry_run::DryRunApi<Block, RuntimeCall, RuntimeEvent, OriginCaller>
772 for Runtime {
773 fn dry_run_call(
774 origin: OriginCaller,
775 call: RuntimeCall,
776 result_xcms_version: XcmVersion
777 ) -> Result<CallDryRunEffects<RuntimeEvent>, XcmDryRunApiError> {
778 PolkadotXcm::dry_run_call::<
779 Runtime,
780 xcm_config::XcmRouter,
781 OriginCaller,
782 RuntimeCall>(origin, call, result_xcms_version)
783 }
784
785 fn dry_run_xcm(
786 origin_location: VersionedLocation,
787 xcm: VersionedXcm<RuntimeCall>
788 ) -> Result<XcmDryRunEffects<RuntimeEvent>, XcmDryRunApiError> {
789 PolkadotXcm::dry_run_xcm::<xcm_config::XcmRouter>(origin_location, xcm)
790 }
791 }
792
793 impl xcm_runtime_apis::conversions::LocationToAccountApi<Block, AccountId> for Runtime {
794 fn convert_location(location: VersionedLocation) -> Result<
795 AccountId,
796 xcm_runtime_apis::conversions::Error
797 > {
798 xcm_runtime_apis::conversions::LocationToAccountHelper::<
799 AccountId,
800 xcm_config::LocationToAccountId,
801 >::convert_location(location)
802 }
803 }
804
805 #[cfg(feature = "runtime-benchmarks")]
806 impl frame_benchmarking::Benchmark<Block> for Runtime {
807
808 fn benchmark_metadata(extra: bool) -> (
809 Vec<frame_benchmarking::BenchmarkList>,
810 Vec<frame_support::traits::StorageInfo>,
811 ) {
812 use frame_benchmarking::{list_benchmark, Benchmarking, BenchmarkList};
813 use frame_system_benchmarking::Pallet as SystemBench;
814 use frame_support::traits::StorageInfoTrait;
815
816 use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark;
817 use pallet_transaction_payment::benchmarking::Pallet as TransactionPaymentBenchmark;
818
819 let mut list = Vec::<BenchmarkList>::new();
820 list_benchmarks!(list, extra);
821
822 let storage_info = AllPalletsWithSystem::storage_info();
823
824 return (list, storage_info)
825 }
826
827 #[allow(non_local_definitions)]
828 fn dispatch_benchmark(
829 config: frame_benchmarking::BenchmarkConfig,
830 ) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> {
831 use frame_benchmarking::{add_benchmark, BenchmarkBatch, Benchmarking};
832 use frame_support::traits::TrackedStorageKey;
833 use cumulus_primitives_core::ParaId;
834
835 use xcm::latest::prelude::{
836 GeneralIndex, Junction, Junctions, Location, Response, NetworkId, AssetId,
837 Assets as XcmAssets, Fungible, Asset, ParentThen, Parachain, Parent, WeightLimit
838 };
839 use xcm_config::SelfReserve;
840 use frame_benchmarking::BenchmarkError;
841
842 use frame_system_benchmarking::Pallet as SystemBench;
843 impl frame_system_benchmarking::Config for Runtime {
846 fn setup_set_code_requirements(code: &Vec<u8>) -> Result<(), BenchmarkError> {
847 ParachainSystem::initialize_for_set_code_benchmark(code.len() as u32);
848 Ok(())
849 }
850
851 fn verify_set_code() {
852 System::assert_last_event(cumulus_pallet_parachain_system::Event::<Runtime>::ValidationFunctionStored.into());
853 }
854 }
855
856 use pallet_transaction_payment::benchmarking::Pallet as TransactionPaymentBenchmark;
859 impl pallet_transaction_payment::benchmarking::Config for Runtime {
860 fn setup_benchmark_environment() {
861 let author: AccountId = frame_benchmarking::whitelisted_caller();
863 pallet_author_inherent::Author::<Runtime>::put(author);
864 }
865 }
866
867 use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark;
868 parameter_types! {
869 pub const RandomParaId: ParaId = ParaId::new(43211234);
870 }
871
872 pub struct TestDeliveryHelper;
877 impl xcm_builder::EnsureDelivery for TestDeliveryHelper {
878 fn ensure_successful_delivery(
879 origin_ref: &Location,
880 dest: &Location,
881 _fee_reason: xcm_executor::traits::FeeReason,
882 ) -> (Option<xcm_executor::FeesMode>, Option<XcmAssets>) {
883 use xcm_executor::traits::ConvertLocation;
884
885 <xcm_config::XcmRouter as xcm::latest::SendXcm>::ensure_successful_delivery(Some(dest.clone()));
888
889 if let Some(Parachain(para_id)) = dest.interior().first() {
891 ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests(
892 (*para_id).into()
893 );
894 }
895
896 if let Some(account) = xcm_config::LocationToH160::convert_location(origin_ref) {
898 let balance = ExistentialDeposit::get() * 1000u128;
899 let _ = <Balances as frame_support::traits::Currency<_>>::
900 make_free_balance_be(&account.into(), balance);
901 }
902
903 (None, None)
904 }
905 }
906
907 impl pallet_xcm::benchmarking::Config for Runtime {
908 type DeliveryHelper = TestDeliveryHelper;
909
910 fn get_asset() -> Asset {
911 Asset {
912 id: AssetId(SelfReserve::get()),
913 fun: Fungible(ExistentialDeposit::get()),
914 }
915 }
916
917 fn reachable_dest() -> Option<Location> {
918 Some(Parent.into())
919 }
920
921 fn teleportable_asset_and_dest() -> Option<(Asset, Location)> {
922 None
923 }
924
925 fn reserve_transferable_asset_and_dest() -> Option<(Asset, Location)> {
926 use xcm_config::SelfReserve;
927
928 ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests(
929 RandomParaId::get().into()
930 );
931
932 Some((
933 Asset {
934 fun: Fungible(ExistentialDeposit::get()),
935 id: AssetId(SelfReserve::get().into())
936 },
937 ParentThen(Parachain(RandomParaId::get().into()).into()).into(),
940 ))
941 }
942
943 fn set_up_complex_asset_transfer(
944 ) -> Option<(XcmAssets, u32, Location, Box<dyn FnOnce()>)> {
945 use xcm_config::SelfReserve;
946
947 let destination: xcm::v5::Location = Parent.into();
948
949 let fee_amount: u128 = <Runtime as pallet_balances::Config>::ExistentialDeposit::get();
950 let fee_asset: Asset = (SelfReserve::get(), fee_amount).into();
951
952 let balance = fee_amount * 1000;
954 let who = frame_benchmarking::whitelisted_caller();
955 let _ =
956 <Balances as frame_support::traits::Currency<_>>::make_free_balance_be(&who, balance);
957
958 assert_eq!(Balances::free_balance(&who), balance);
960
961 let asset_amount: u128 = 10u128;
963 let initial_asset_amount: u128 = asset_amount * 10;
964
965 let asset_id = pallet_moonbeam_foreign_assets::default_asset_id::<Runtime>() + 1;
966 let (_, location, _) = pallet_moonbeam_foreign_assets::create_default_minted_foreign_asset::<Runtime>(
967 asset_id,
968 initial_asset_amount,
969 );
970 let transfer_asset: Asset = (AssetId(location), asset_amount).into();
971
972 let assets: XcmAssets = vec![fee_asset.clone(), transfer_asset].into();
973 let fee_index: u32 = 0;
974
975 let verify: Box<dyn FnOnce()> = Box::new(move || {
976 assert!(Balances::free_balance(&who) <= balance - fee_amount);
979 });
980
981 Some((assets, fee_index, destination, verify))
982 }
983 }
984
985 impl pallet_xcm_benchmarks::Config for Runtime {
986 type XcmConfig = xcm_config::XcmExecutorConfig;
987 type AccountIdConverter = xcm_config::LocationToAccountId;
988 type DeliveryHelper = TestDeliveryHelper;
989 fn valid_destination() -> Result<Location, BenchmarkError> {
990 Ok(Location::parent())
991 }
992 fn worst_case_holding(_depositable_count: u32) -> XcmAssets {
993 const HOLDING_FUNGIBLES: u32 = 100;
995 let fungibles_amount: u128 = 100;
996 let assets = (0..HOLDING_FUNGIBLES).map(|i| {
997 let location: Location = GeneralIndex(i as u128).into();
998 Asset {
999 id: AssetId(location),
1000 fun: Fungible(fungibles_amount * i as u128),
1001 }
1002 .into()
1003 })
1004 .chain(
1005 core::iter::once(
1006 Asset {
1007 id: AssetId(Location::parent()),
1008 fun: Fungible(u128::MAX)
1009 }
1010 )
1011 )
1012 .collect::<Vec<_>>();
1013
1014
1015 for (i, asset) in assets.iter().enumerate() {
1016 if let Asset {
1017 id: AssetId(location),
1018 fun: Fungible(_)
1019 } = asset {
1020 EvmForeignAssets::set_asset(
1021 location.clone(),
1022 i as u128
1023 );
1024 XcmWeightTrader::set_asset_price(
1025 location.clone(),
1026 1u128.pow(18)
1027 );
1028 }
1029 }
1030 assets.into()
1031 }
1032 }
1033
1034 impl pallet_xcm_benchmarks::generic::Config for Runtime {
1035 type RuntimeCall = RuntimeCall;
1036 type TransactAsset = Balances;
1037
1038 fn worst_case_response() -> (u64, Response) {
1039 (0u64, Response::Version(Default::default()))
1040 }
1041
1042 fn worst_case_asset_exchange()
1043 -> Result<(XcmAssets, XcmAssets), BenchmarkError> {
1044 Err(BenchmarkError::Skip)
1045 }
1046
1047 fn universal_alias() -> Result<(Location, Junction), BenchmarkError> {
1048 Err(BenchmarkError::Skip)
1049 }
1050
1051 fn export_message_origin_and_destination()
1052 -> Result<(Location, NetworkId, Junctions), BenchmarkError> {
1053 Err(BenchmarkError::Skip)
1054 }
1055
1056 fn transact_origin_and_runtime_call()
1057 -> Result<(Location, RuntimeCall), BenchmarkError> {
1058 Ok((Location::parent(), frame_system::Call::remark_with_event {
1059 remark: vec![]
1060 }.into()))
1061 }
1062
1063 fn subscribe_origin() -> Result<Location, BenchmarkError> {
1064 Ok(Location::parent())
1065 }
1066
1067 fn claimable_asset()
1068 -> Result<(Location, Location, XcmAssets), BenchmarkError> {
1069 let origin = Location::parent();
1070 let assets: XcmAssets = (AssetId(Location::parent()), 1_000u128)
1071 .into();
1072 let ticket = Location { parents: 0, interior: [].into() };
1073 Ok((origin, ticket, assets))
1074 }
1075
1076 fn worst_case_for_trader() -> Result<(Asset, WeightLimit), BenchmarkError> {
1077 Err(BenchmarkError::Skip)
1078 }
1079
1080 fn unlockable_asset()
1081 -> Result<(Location, Location, Asset), BenchmarkError> {
1082 Err(BenchmarkError::Skip)
1083 }
1084
1085 fn alias_origin() -> Result<(Location, Location), BenchmarkError> {
1086 Err(BenchmarkError::Skip)
1087 }
1088 }
1089
1090 $($bench_custom)*
1091
1092 let whitelist: Vec<TrackedStorageKey> = vec![
1093 hex_literal::hex!( "26aa394eea5630e07c48ae0c9558cef7"
1095 "02a5c1b19ab7a04f536c519aca4983ac")
1096 .to_vec().into(),
1097 hex_literal::hex!( "c2261276cc9d1f8598ea4b6a74b15c2f"
1099 "57c875e4cff74148e4628f264b974c80")
1100 .to_vec().into(),
1101 hex_literal::hex!( "26aa394eea5630e07c48ae0c9558cef7"
1103 "ff553b5a9862a516939d82b3d3d8661a")
1104 .to_vec().into(),
1105 hex_literal::hex!( "26aa394eea5630e07c48ae0c9558cef7"
1107 "0a98fdbe9ce6c55837576c60c7af3850")
1108 .to_vec().into(),
1109 hex_literal::hex!( "26aa394eea5630e07c48ae0c9558cef7"
1111 "80d41e5e16056765bc8461851072c9d7")
1112 .to_vec().into(),
1113 hex_literal::hex!( "26aa394eea5630e07c48ae0c9558cef7"
1115 "34abf5cb34d6244378cddbf18e849d96")
1116 .to_vec().into(),
1117 hex_literal::hex!( "a686a3043d0adcf2fa655e57bc595a78"
1119 "13792e785168f725b60e2969c7fc2552")
1120 .to_vec().into(),
1121 hex_literal::hex!( "26aa394eea5630e07c48ae0c9558cef7"
1123 "b99d880ec681799c0cf30e8886371da9"
1124 "7be2919ac397ba499ea5e57132180ec6"
1125 "6d6f646c70792f747273727900000000"
1126 "00000000"
1127 ).to_vec().into(),
1128 hex_literal::hex!( "26aa394eea5630e07c48ae0c9558cef7"
1130 "b99d880ec681799c0cf30e8886371da9"
1131 "7be2919ac397ba499ea5e57132180ec6"
1132 "6d6f646c70632f747273727900000000"
1133 "00000000"
1134 ).to_vec().into(),
1135 hex_literal::hex!( "0d715f2646c8f85767b5d2764bb27826"
1137 "04a74d81251e398fd8a0a4d55023bb3f")
1138 .to_vec().into(),
1139 hex_literal::hex!( "c63bdd4a39095ccf55623a6f2872bf8a" "c63bdd4a39095ccf55623a6f2872bf8a" "71d0aacb690b61280d0c97c6b6a666640000"
1144 )
1145 .to_vec().into(),
1146
1147 ];
1148
1149 let mut batches = Vec::<BenchmarkBatch>::new();
1150 let params = (&config, &whitelist);
1151
1152 add_benchmarks!(params, batches);
1153
1154 if batches.is_empty() {
1155 return Err("Benchmark not found for this pallet.".into());
1156 }
1157 Ok(batches)
1158 }
1159 }
1160
1161 #[cfg(feature = "try-runtime")]
1162 impl frame_try_runtime::TryRuntime<Block> for Runtime {
1163 fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) {
1164 log::info!("try-runtime::on_runtime_upgrade()");
1165 let weight = Executive::try_runtime_upgrade(checks)
1169 .expect("runtime upgrade logic *must* be infallible");
1170 (weight, RuntimeBlockWeights::get().max_block)
1171 }
1172
1173 fn execute_block(
1174 block: Block,
1175 state_root_check: bool,
1176 signature_check: bool,
1177 select: frame_try_runtime::TryStateSelect
1178 ) -> Weight {
1179 log::info!(
1180 "try-runtime: executing block {:?} / root checks: {:?} / try-state-select: {:?}",
1181 block.header.hash(),
1182 state_root_check,
1183 select,
1184 );
1185 Executive::try_execute_block(
1188 block,
1189 state_root_check,
1190 signature_check,
1191 select,
1192 ).expect("execute-block failed")
1193 }
1194 }
1195 }
1196 };
1197}