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 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 fn trace_transaction(
184 extrinsics: Vec<<Block as BlockT>::Extrinsic>,
185 traced_transaction: &EthereumTransaction,
186 header: &<Block as BlockT>::Header,
187 ) -> Result<
188 (),
189 sp_runtime::DispatchError,
190 > {
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 EthereumTracer::transaction(traced_transaction.hash(), || {
203 Executive::initialize_block(header);
209
210 for ext in extrinsics.into_iter() {
213 let _ = match &ext.0.function {
214 RuntimeCall::Ethereum(transact { transaction }) => {
215 frame_system::BlockWeight::<Runtime>::kill();
221
222 if transaction == traced_transaction {
223 EvmTracer::new().trace(|| Executive::apply_extrinsic(ext));
224 return Ok(());
225 } else {
226 Executive::apply_extrinsic(ext)
227 }
228 }
229 _ => Executive::apply_extrinsic(ext),
230 };
231
232 if let Some(EthereumTracingStatus::TransactionExited) = EthereumTracer::status() {
233 return Ok(());
234 }
235 }
236
237 if let Some(EthereumTracingStatus::Transaction(_)) = EthereumTracer::status() {
238 replay_on_idle();
241 }
242
243 if let Some(EthereumTracingStatus::TransactionExited) = EthereumTracer::status() {
244 Ok(())
246 } else {
247 Err(sp_runtime::DispatchError::Other(
249 "Failed to find Ethereum transaction among the extrinsics.",
250 ))
251 }
252 })
253 }
254 #[cfg(not(feature = "evm-tracing"))]
255 Err(sp_runtime::DispatchError::Other(
256 "Missing `evm-tracing` compile time feature flag.",
257 ))
258 }
259
260 fn trace_block(
261 extrinsics: Vec<<Block as BlockT>::Extrinsic>,
262 known_transactions: Vec<H256>,
263 header: &<Block as BlockT>::Header,
264 ) -> Result<
265 (),
266 sp_runtime::DispatchError,
267 > {
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 EthereumTracer::block(|| {
279 let mut config = <Runtime as pallet_evm::Config>::config().clone();
280 config.estimate = true;
281
282 Executive::initialize_block(header);
288
289 for ext in extrinsics.into_iter() {
291 match &ext.0.function {
292 RuntimeCall::Ethereum(transact { transaction }) => {
293
294 frame_system::BlockWeight::<Runtime>::kill();
300
301 let tx_hash = &transaction.hash();
302 if known_transactions.contains(&tx_hash) {
303 EvmTracer::emit_new();
305 EvmTracer::new().trace(|| {
306 if let Err(err) = Executive::apply_extrinsic(ext) {
307 log::debug!(
308 target: "tracing",
309 "Could not trace eth transaction (hash: {}): {:?}",
310 &tx_hash,
311 err
312 );
313 }
314 });
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 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 }
334 }
335 };
336 }
337
338 replay_on_idle();
341
342 Ok(())
343 })
344 }
345 #[cfg(not(feature = "evm-tracing"))]
346 Err(sp_runtime::DispatchError::Other(
347 "Missing `evm-tracing` compile time feature flag.",
348 ))
349 }
350
351 fn trace_call(
352 header: &<Block as BlockT>::Header,
353 from: H160,
354 to: H160,
355 data: Vec<u8>,
356 value: U256,
357 gas_limit: U256,
358 max_fee_per_gas: Option<U256>,
359 max_priority_fee_per_gas: Option<U256>,
360 nonce: Option<U256>,
361 access_list: Option<Vec<(H160, Vec<H256>)>>,
362 authorization_list: Option<AuthorizationList>,
363 ) -> Result<(), sp_runtime::DispatchError> {
364 #[cfg(feature = "evm-tracing")]
365 {
366 use moonbeam_evm_tracer::tracer::EvmTracer;
367
368 Executive::initialize_block(header);
371
372 EvmTracer::new().trace(|| {
373 let is_transactional = false;
374 let validate = true;
375
376 let transaction_data = pallet_ethereum::TransactionData::new(
377 pallet_ethereum::TransactionAction::Call(to),
378 data.clone(),
379 nonce.unwrap_or_default(),
380 gas_limit,
381 None,
382 max_fee_per_gas.or(Some(U256::default())),
383 max_priority_fee_per_gas.or(Some(U256::default())),
384 value,
385 Some(<Runtime as pallet_evm::Config>::ChainId::get()),
386 access_list.clone().unwrap_or_default(),
387 authorization_list.clone().unwrap_or_default(),
388 );
389
390 let gas_limit = gas_limit.min(u64::MAX.into()).low_u64();
391
392 let (weight_limit, proof_size_base_cost) = pallet_ethereum::Pallet::<Runtime>::transaction_weight(&transaction_data);
393
394 let _ = <Runtime as pallet_evm::Config>::Runner::call(
395 from,
396 to,
397 data,
398 value,
399 gas_limit,
400 max_fee_per_gas,
401 max_priority_fee_per_gas,
402 nonce,
403 access_list.unwrap_or_default(),
404 authorization_list.unwrap_or_default(),
405 is_transactional,
406 validate,
407 weight_limit,
408 proof_size_base_cost,
409 <Runtime as pallet_evm::Config>::config(),
410 );
411 });
412 Ok(())
413 }
414 #[cfg(not(feature = "evm-tracing"))]
415 Err(sp_runtime::DispatchError::Other(
416 "Missing `evm-tracing` compile time feature flag.",
417 ))
418 }
419 }
420
421 impl moonbeam_rpc_primitives_txpool::TxPoolRuntimeApi<Block> for Runtime {
422 fn extrinsic_filter(
423 xts_ready: Vec<<Block as BlockT>::Extrinsic>,
424 xts_future: Vec<<Block as BlockT>::Extrinsic>,
425 ) -> TxPoolResponse {
426 TxPoolResponse {
427 ready: xts_ready
428 .into_iter()
429 .filter_map(|xt| match xt.0.function {
430 RuntimeCall::Ethereum(transact { transaction }) => Some(transaction),
431 _ => None,
432 })
433 .collect(),
434 future: xts_future
435 .into_iter()
436 .filter_map(|xt| match xt.0.function {
437 RuntimeCall::Ethereum(transact { transaction }) => Some(transaction),
438 _ => None,
439 })
440 .collect(),
441 }
442 }
443 }
444
445 impl fp_rpc::EthereumRuntimeRPCApi<Block> for Runtime {
446 fn chain_id() -> u64 {
447 <Runtime as pallet_evm::Config>::ChainId::get()
448 }
449
450 fn account_basic(address: H160) -> EVMAccount {
451 let (account, _) = EVM::account_basic(&address);
452 account
453 }
454
455 fn gas_price() -> U256 {
456 let (gas_price, _) = <Runtime as pallet_evm::Config>::FeeCalculator::min_gas_price();
457 gas_price
458 }
459
460 fn account_code_at(address: H160) -> Vec<u8> {
461 pallet_evm::AccountCodes::<Runtime>::get(address)
462 }
463
464 fn author() -> H160 {
465 <pallet_evm::Pallet<Runtime>>::find_author()
466 }
467
468 fn storage_at(address: H160, index: U256) -> H256 {
469 let tmp: [u8; 32] = index.to_big_endian();
470 pallet_evm::AccountStorages::<Runtime>::get(address, H256::from_slice(&tmp[..]))
471 }
472
473 fn call(
474 from: H160,
475 to: H160,
476 data: Vec<u8>,
477 value: U256,
478 gas_limit: U256,
479 max_fee_per_gas: Option<U256>,
480 max_priority_fee_per_gas: Option<U256>,
481 nonce: Option<U256>,
482 estimate: bool,
483 access_list: Option<Vec<(H160, Vec<H256>)>>,
484 authorization_list: Option<AuthorizationList>,
485 ) -> Result<pallet_evm::CallInfo, sp_runtime::DispatchError> {
486 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 None
492 };
493 let is_transactional = false;
494 let validate = true;
495
496 let transaction_data = pallet_ethereum::TransactionData::new(
497 pallet_ethereum::TransactionAction::Call(to),
498 data.clone(),
499 nonce.unwrap_or_default(),
500 gas_limit,
501 None,
502 max_fee_per_gas.or(Some(U256::default())),
503 max_priority_fee_per_gas.or(Some(U256::default())),
504 value,
505 Some(<Runtime as pallet_evm::Config>::ChainId::get()),
506 access_list.clone().unwrap_or_default(),
507 authorization_list.clone().unwrap_or_default(),
508 );
509
510 let gas_limit = gas_limit.min(u64::MAX.into()).low_u64();
511
512 let (weight_limit, proof_size_base_cost) = pallet_ethereum::Pallet::<Runtime>::transaction_weight(&transaction_data);
513
514 <Runtime as pallet_evm::Config>::Runner::call(
515 from,
516 to,
517 data,
518 value,
519 gas_limit,
520 max_fee_per_gas,
521 max_priority_fee_per_gas,
522 nonce,
523 access_list.unwrap_or_default(),
524 authorization_list.unwrap_or_default(),
525 is_transactional,
526 validate,
527 weight_limit,
528 proof_size_base_cost,
529 config.as_ref().unwrap_or(<Runtime as pallet_evm::Config>::config()),
530 ).map_err(|err| err.error.into())
531 }
532
533 fn create(
534 from: H160,
535 data: Vec<u8>,
536 value: U256,
537 gas_limit: U256,
538 max_fee_per_gas: Option<U256>,
539 max_priority_fee_per_gas: Option<U256>,
540 nonce: Option<U256>,
541 estimate: bool,
542 access_list: Option<Vec<(H160, Vec<H256>)>>,
543 authorization_list: Option<AuthorizationList>,
544 ) -> Result<pallet_evm::CreateInfo, sp_runtime::DispatchError> {
545 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 None
551 };
552 let is_transactional = false;
553 let validate = true;
554
555 let transaction_data = pallet_ethereum::TransactionData::new(
556 pallet_ethereum::TransactionAction::Create,
557 data.clone(),
558 nonce.unwrap_or_default(),
559 gas_limit,
560 None,
561 max_fee_per_gas.or(Some(U256::default())),
562 max_priority_fee_per_gas.or(Some(U256::default())),
563 value,
564 Some(<Runtime as pallet_evm::Config>::ChainId::get()),
565 access_list.clone().unwrap_or_default(),
566 authorization_list.clone().unwrap_or_default(),
567 );
568
569 let gas_limit = gas_limit.min(u64::MAX.into()).low_u64();
570
571 let (weight_limit, proof_size_base_cost) = pallet_ethereum::Pallet::<Runtime>::transaction_weight(&transaction_data);
572
573 #[allow(clippy::or_fun_call)] <Runtime as pallet_evm::Config>::Runner::create(
575 from,
576 data,
577 value,
578 gas_limit,
579 max_fee_per_gas,
580 max_priority_fee_per_gas,
581 nonce,
582 access_list.unwrap_or_default(),
583 authorization_list.unwrap_or_default(),
584 is_transactional,
585 validate,
586 weight_limit,
587 proof_size_base_cost,
588 config.as_ref().unwrap_or(<Runtime as pallet_evm::Config>::config()),
589 ).map_err(|err| err.error.into())
590 }
591
592 fn current_transaction_statuses() -> Option<Vec<TransactionStatus>> {
593 pallet_ethereum::CurrentTransactionStatuses::<Runtime>::get()
594 }
595
596 fn current_block() -> Option<pallet_ethereum::Block> {
597 pallet_ethereum::CurrentBlock::<Runtime>::get()
598 }
599
600 fn current_receipts() -> Option<Vec<pallet_ethereum::Receipt>> {
601 pallet_ethereum::CurrentReceipts::<Runtime>::get()
602 }
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 fn can_author(
694 author: nimbus_primitives::NimbusId,
695 slot: u32,
696 parent_header: &<Block as BlockT>::Header
697 ) -> bool {
698 use pallet_parachain_staking::Config as PalletParachainStakingConfig;
699
700 let block_number = parent_header.number + 1;
701
702 use frame_support::traits::OnInitialize;
706 System::initialize(
707 &block_number,
708 &parent_header.hash(),
709 &parent_header.digest,
710 );
711
712 if pallet_parachain_staking::Pallet::<Self>::round()
716 .should_update(block_number) {
717 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
725 };
726 let candidates = pallet_parachain_staking::Pallet::<Self>::compute_top_candidates();
727 if candidates.is_empty() {
728 return AuthorInherent::can_author(&author, &slot);
731 }
732
733 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 AuthorInherent::can_author(&author, &slot)
742 }
743 }
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 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 let _: xcm::latest::Location = destination
794 .try_into()
795 .map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?;
796 let _: xcm::latest::Xcm<()> = message
797 .try_into()
798 .map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?;
799 let _: xcm::latest::AssetId = asset_id
800 .try_into()
801 .map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?;
802
803 Ok(VersionedAssets::from(xcm::latest::Assets::new()))
804 }
805 }
806
807 impl xcm_runtime_apis::dry_run::DryRunApi<Block, RuntimeCall, RuntimeEvent, OriginCaller>
808 for Runtime {
809 fn dry_run_call(
810 origin: OriginCaller,
811 call: RuntimeCall,
812 result_xcms_version: XcmVersion
813 ) -> Result<CallDryRunEffects<RuntimeEvent>, XcmDryRunApiError> {
814 PolkadotXcm::dry_run_call::<
815 Runtime,
816 xcm_config::XcmRouter,
817 OriginCaller,
818 RuntimeCall>(origin, call, result_xcms_version)
819 }
820
821 fn dry_run_xcm(
822 origin_location: VersionedLocation,
823 xcm: VersionedXcm<RuntimeCall>
824 ) -> Result<XcmDryRunEffects<RuntimeEvent>, XcmDryRunApiError> {
825 PolkadotXcm::dry_run_xcm::<xcm_config::XcmRouter>(origin_location, xcm)
826 }
827 }
828
829 impl xcm_runtime_apis::conversions::LocationToAccountApi<Block, AccountId> for Runtime {
830 fn convert_location(location: VersionedLocation) -> Result<
831 AccountId,
832 xcm_runtime_apis::conversions::Error
833 > {
834 xcm_runtime_apis::conversions::LocationToAccountHelper::<
835 AccountId,
836 xcm_config::LocationToAccountId,
837 >::convert_location(location)
838 }
839 }
840
841 #[cfg(feature = "runtime-benchmarks")]
842 impl frame_benchmarking::Benchmark<Block> for Runtime {
843
844 fn benchmark_metadata(extra: bool) -> (
845 Vec<frame_benchmarking::BenchmarkList>,
846 Vec<frame_support::traits::StorageInfo>,
847 ) {
848 use frame_benchmarking::{list_benchmark, Benchmarking, BenchmarkList};
849 use frame_system_benchmarking::Pallet as SystemBench;
850 use frame_support::traits::StorageInfoTrait;
851
852 use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark;
853 use pallet_transaction_payment::benchmarking::Pallet as TransactionPaymentBenchmark;
854
855 let mut list = Vec::<BenchmarkList>::new();
856 list_benchmarks!(list, extra);
857
858 let storage_info = AllPalletsWithSystem::storage_info();
859
860 return (list, storage_info)
861 }
862
863 #[allow(non_local_definitions)]
864 fn dispatch_benchmark(
865 config: frame_benchmarking::BenchmarkConfig,
866 ) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> {
867 use frame_benchmarking::{add_benchmark, BenchmarkBatch, Benchmarking};
868 use frame_support::traits::TrackedStorageKey;
869 use cumulus_primitives_core::ParaId;
870
871 use xcm::latest::prelude::{
872 GeneralIndex, Junction, Junctions, Location, Response, NetworkId, AssetId, Here,
873 Assets as XcmAssets, Fungible, Asset, ParentThen, Parachain, Parent, WeightLimit,
874 AccountId32,
875 };
876 use xcm_config::{SelfReserve, MaxAssetsIntoHolding, AssetHubLocation, RelayLocation};
877 use frame_benchmarking::BenchmarkError;
878 use xcm_executor::traits::ConvertLocation;
879
880 use frame_system_benchmarking::Pallet as SystemBench;
881 impl frame_system_benchmarking::Config for Runtime {
884 fn setup_set_code_requirements(code: &Vec<u8>) -> Result<(), BenchmarkError> {
885 ParachainSystem::initialize_for_set_code_benchmark(code.len() as u32);
886 Ok(())
887 }
888
889 fn verify_set_code() {
890 System::assert_last_event(cumulus_pallet_parachain_system::Event::<Runtime>::ValidationFunctionStored.into());
891 }
892 }
893
894 use pallet_transaction_payment::benchmarking::Pallet as TransactionPaymentBenchmark;
897 impl pallet_transaction_payment::benchmarking::Config for Runtime {
898 fn setup_benchmark_environment() {
899 let author: AccountId = frame_benchmarking::whitelisted_caller();
901 pallet_author_inherent::Author::<Runtime>::put(author);
902 }
903 }
904
905 use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark;
906 parameter_types! {
907 pub const RandomParaId: ParaId = ParaId::new(43211234);
908 }
909
910 pub struct TestDeliveryHelper;
915 impl xcm_builder::EnsureDelivery for TestDeliveryHelper {
916 fn ensure_successful_delivery(
917 origin_ref: &Location,
918 dest: &Location,
919 _fee_reason: xcm_executor::traits::FeeReason,
920 ) -> (Option<xcm_executor::FeesMode>, Option<XcmAssets>) {
921 use xcm_executor::traits::ConvertLocation;
922
923 <xcm_config::XcmRouter as xcm::latest::SendXcm>::ensure_successful_delivery(Some(dest.clone()));
926
927 if let Some(Parachain(para_id)) = dest.interior().first() {
929 ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests(
930 (*para_id).into()
931 );
932 }
933
934 if let Some(account) = xcm_config::LocationToH160::convert_location(origin_ref) {
936 let balance = ExistentialDeposit::get() * 1000u128;
937 let _ = <Balances as frame_support::traits::Currency<_>>::
938 make_free_balance_be(&account.into(), balance);
939 }
940
941 (None, None)
942 }
943 }
944
945 impl pallet_xcm::benchmarking::Config for Runtime {
946 type DeliveryHelper = TestDeliveryHelper;
947
948 fn get_asset() -> Asset {
949 Asset {
950 id: AssetId(SelfReserve::get()),
951 fun: Fungible(ExistentialDeposit::get()),
952 }
953 }
954
955 fn reachable_dest() -> Option<Location> {
956 Some(Parent.into())
957 }
958
959 fn teleportable_asset_and_dest() -> Option<(Asset, Location)> {
960 None
961 }
962
963 fn reserve_transferable_asset_and_dest() -> Option<(Asset, Location)> {
964 use xcm_config::SelfReserve;
965
966 ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests(
967 RandomParaId::get().into()
968 );
969
970 Some((
971 Asset {
972 fun: Fungible(ExistentialDeposit::get()),
973 id: AssetId(SelfReserve::get().into())
974 },
975 ParentThen(Parachain(RandomParaId::get().into()).into()).into(),
978 ))
979 }
980
981 fn set_up_complex_asset_transfer(
982 ) -> Option<(XcmAssets, u32, Location, Box<dyn FnOnce()>)> {
983 use xcm_config::SelfReserve;
984
985 let destination: xcm::v5::Location = Parent.into();
986
987 let fee_amount: u128 = <Runtime as pallet_balances::Config>::ExistentialDeposit::get();
988 let fee_asset: Asset = (SelfReserve::get(), fee_amount).into();
989
990 let balance = fee_amount * 1000;
992 let who = frame_benchmarking::whitelisted_caller();
993 let _ =
994 <Balances as frame_support::traits::Currency<_>>::make_free_balance_be(&who, balance);
995
996 assert_eq!(Balances::free_balance(&who), balance);
998
999 let asset_amount: u128 = 10u128;
1001 let initial_asset_amount: u128 = asset_amount * 10;
1002
1003 let asset_id = pallet_moonbeam_foreign_assets::default_asset_id::<Runtime>() + 1;
1004 let (_, location, _) = pallet_moonbeam_foreign_assets::create_default_minted_foreign_asset::<Runtime>(
1005 asset_id,
1006 initial_asset_amount,
1007 );
1008 let transfer_asset: Asset = (AssetId(location), asset_amount).into();
1009
1010 let assets: XcmAssets = vec![fee_asset.clone(), transfer_asset].into();
1011 let fee_index: u32 = 0;
1012
1013 let verify: Box<dyn FnOnce()> = Box::new(move || {
1014 assert!(Balances::free_balance(&who) <= balance - fee_amount);
1017 });
1018
1019 Some((assets, fee_index, destination, verify))
1020 }
1021 }
1022
1023 impl pallet_xcm_benchmarks::Config for Runtime {
1024 type XcmConfig = xcm_config::XcmExecutorConfig;
1025 type AccountIdConverter = BenchAccountIdConverter<AccountId>;
1026 type DeliveryHelper = TestDeliveryHelper;
1027 fn valid_destination() -> Result<Location, BenchmarkError> {
1028 Ok(Location::parent())
1029 }
1030 fn worst_case_holding(_depositable_count: u32) -> XcmAssets {
1031 const HOLDING_FUNGIBLES: u32 = MaxAssetsIntoHolding::get();
1032 let fungibles_amount: u128 = 1_000 * ExistentialDeposit::get();
1033 let assets = (1..=HOLDING_FUNGIBLES).map(|i| {
1034 let location: Location = GeneralIndex(i as u128).into();
1035 Asset {
1036 id: AssetId(location),
1037 fun: Fungible(fungibles_amount * i as u128),
1038 }
1039 .into()
1040 })
1041 .chain(
1042 core::iter::once(
1043 Asset {
1044 id: AssetId(Location::parent()),
1045 fun: Fungible(u128::MAX)
1046 }
1047 )
1048 )
1049 .collect::<Vec<_>>();
1050
1051
1052 for (i, asset) in assets.iter().enumerate() {
1053 if let Asset {
1054 id: AssetId(location),
1055 fun: Fungible(_)
1056 } = asset {
1057 EvmForeignAssets::set_asset(
1058 location.clone(),
1059 i as u128
1060 );
1061 XcmWeightTrader::set_asset_price(
1062 location.clone(),
1063 10u128.pow(18)
1064 );
1065 }
1066 }
1067 assets.into()
1068 }
1069 }
1070
1071 parameter_types! {
1072 pub const TokenLocation: Location = Here.into_location();
1074 pub TrustedTeleporter: Option<(Location, Asset)> = None;
1075 pub CheckedAccount: Option<(AccountId, xcm_builder::MintLocation)> = None;
1076 pub TrustedReserve: Option<(Location, Asset)> = Some((
1079 AssetHubLocation::get(),
1080 Asset {
1081 id: AssetId(RelayLocation::get()),
1082 fun: Fungible(100 * ExistentialDeposit::get()),
1083 }
1084 ));
1085 }
1086
1087 impl pallet_xcm_benchmarks::fungible::Config for Runtime {
1088 type TransactAsset = Balances;
1089
1090 type CheckedAccount = CheckedAccount;
1091 type TrustedTeleporter = TrustedTeleporter;
1092 type TrustedReserve = TrustedReserve;
1093
1094 fn get_asset() -> Asset {
1095 let location: Location = GeneralIndex(1).into();
1098 let asset_id = 1u128;
1099 let decimals = 18u8;
1100 let asset = Asset {
1101 id: AssetId(location.clone()),
1102 fun: Fungible(100 * ExistentialDeposit::get()),
1103 };
1104 EvmForeignAssets::set_asset(
1105 location.clone(),
1106 asset_id,
1107 );
1108 XcmWeightTrader::set_asset_price(
1109 location.clone(),
1110 10u128.pow(decimals as u32)
1111 );
1112 EvmForeignAssets::create_asset_contract(
1113 asset_id,
1114 decimals,
1115 "TKN",
1116 "Token",
1117 ).unwrap();
1118 asset
1119 }
1120 }
1121
1122 impl pallet_xcm_benchmarks::generic::Config for Runtime {
1123 type RuntimeCall = RuntimeCall;
1124 type TransactAsset = Balances;
1125
1126 fn worst_case_response() -> (u64, Response) {
1127 (0u64, Response::Version(Default::default()))
1128 }
1129
1130 fn worst_case_asset_exchange()
1131 -> Result<(XcmAssets, XcmAssets), BenchmarkError> {
1132 Err(BenchmarkError::Skip)
1133 }
1134
1135 fn universal_alias() -> Result<(Location, Junction), BenchmarkError> {
1136 Err(BenchmarkError::Skip)
1137 }
1138
1139 fn export_message_origin_and_destination()
1140 -> Result<(Location, NetworkId, Junctions), BenchmarkError> {
1141 Err(BenchmarkError::Skip)
1142 }
1143
1144 fn transact_origin_and_runtime_call()
1145 -> Result<(Location, RuntimeCall), BenchmarkError> {
1146 Ok((Location::parent(), frame_system::Call::remark_with_event {
1147 remark: vec![]
1148 }.into()))
1149 }
1150
1151 fn subscribe_origin() -> Result<Location, BenchmarkError> {
1152 Ok(Location::parent())
1153 }
1154
1155 fn claimable_asset()
1156 -> Result<(Location, Location, XcmAssets), BenchmarkError> {
1157 let origin = Location::parent();
1158 let assets: XcmAssets = (AssetId(Location::parent()), 1_000u128)
1159 .into();
1160 let ticket = Location { parents: 0, interior: [].into() };
1161 Ok((origin, ticket, assets))
1162 }
1163
1164 fn worst_case_for_trader() -> Result<(Asset, WeightLimit), BenchmarkError> {
1165 let location: Location = GeneralIndex(1).into();
1166 Ok((
1167 Asset {
1168 id: AssetId(Location::parent()),
1169 fun: Fungible(1_000_000_000_000_000 as u128)
1170 },
1171 WeightLimit::Limited(Weight::from_parts(5000, 5000)),
1172 ))
1173 }
1174
1175 fn unlockable_asset()
1176 -> Result<(Location, Location, Asset), BenchmarkError> {
1177 Err(BenchmarkError::Skip)
1178 }
1179
1180 fn alias_origin() -> Result<(Location, Location), BenchmarkError> {
1181 Err(BenchmarkError::Skip)
1182 }
1183 }
1184
1185 $($bench_custom)*
1186
1187 let whitelist: Vec<TrackedStorageKey> = vec![
1188 hex_literal::hex!( "26aa394eea5630e07c48ae0c9558cef7"
1190 "02a5c1b19ab7a04f536c519aca4983ac")
1191 .to_vec().into(),
1192 hex_literal::hex!( "c2261276cc9d1f8598ea4b6a74b15c2f"
1194 "57c875e4cff74148e4628f264b974c80")
1195 .to_vec().into(),
1196 hex_literal::hex!( "26aa394eea5630e07c48ae0c9558cef7"
1198 "ff553b5a9862a516939d82b3d3d8661a")
1199 .to_vec().into(),
1200 hex_literal::hex!( "26aa394eea5630e07c48ae0c9558cef7"
1202 "0a98fdbe9ce6c55837576c60c7af3850")
1203 .to_vec().into(),
1204 hex_literal::hex!( "26aa394eea5630e07c48ae0c9558cef7"
1206 "80d41e5e16056765bc8461851072c9d7")
1207 .to_vec().into(),
1208 hex_literal::hex!( "26aa394eea5630e07c48ae0c9558cef7"
1210 "34abf5cb34d6244378cddbf18e849d96")
1211 .to_vec().into(),
1212 hex_literal::hex!( "a686a3043d0adcf2fa655e57bc595a78"
1214 "13792e785168f725b60e2969c7fc2552")
1215 .to_vec().into(),
1216 hex_literal::hex!( "26aa394eea5630e07c48ae0c9558cef7"
1218 "b99d880ec681799c0cf30e8886371da9"
1219 "7be2919ac397ba499ea5e57132180ec6"
1220 "6d6f646c70792f747273727900000000"
1221 "00000000"
1222 ).to_vec().into(),
1223 hex_literal::hex!( "26aa394eea5630e07c48ae0c9558cef7"
1225 "b99d880ec681799c0cf30e8886371da9"
1226 "7be2919ac397ba499ea5e57132180ec6"
1227 "6d6f646c70632f747273727900000000"
1228 "00000000"
1229 ).to_vec().into(),
1230 hex_literal::hex!( "0d715f2646c8f85767b5d2764bb27826"
1232 "04a74d81251e398fd8a0a4d55023bb3f")
1233 .to_vec().into(),
1234 hex_literal::hex!( "c63bdd4a39095ccf55623a6f2872bf8a" "c63bdd4a39095ccf55623a6f2872bf8a" "71d0aacb690b61280d0c97c6b6a666640000"
1239 )
1240 .to_vec().into(),
1241
1242 ];
1243
1244 let mut batches = Vec::<BenchmarkBatch>::new();
1245 let params = (&config, &whitelist);
1246
1247 add_benchmarks!(params, batches);
1248
1249 Ok(batches)
1250 }
1251 }
1252
1253 #[cfg(feature = "try-runtime")]
1254 impl frame_try_runtime::TryRuntime<Block> for Runtime {
1255 fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) {
1256 log::info!("try-runtime::on_runtime_upgrade()");
1257 let weight = Executive::try_runtime_upgrade(checks)
1261 .expect("runtime upgrade logic *must* be infallible");
1262 (weight, RuntimeBlockWeights::get().max_block)
1263 }
1264
1265 fn execute_block(
1266 block: <Block as BlockT>::LazyBlock,
1267 state_root_check: bool,
1268 signature_check: bool,
1269 select: frame_try_runtime::TryStateSelect
1270 ) -> Weight {
1271 log::info!(
1272 "try-runtime: executing block {:?} / root checks: {:?} / try-state-select: {:?}",
1273 block.header.hash(),
1274 state_root_check,
1275 select,
1276 );
1277 Executive::try_execute_block(
1280 block,
1281 state_root_check,
1282 signature_check,
1283 select,
1284 ).expect("execute-block failed")
1285 }
1286 }
1287 }
1288 };
1289}