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