1#![cfg_attr(not(feature = "std"), no_std)]
99
100extern crate alloc;
101
102use alloc::{borrow::Cow, boxed::Box, vec, vec::Vec};
103use core::{fmt::Debug, marker::PhantomData};
104use pallet_prelude::{BlockNumberFor, HeaderFor};
105#[cfg(feature = "std")]
106use serde::Serialize;
107use sp_io::hashing::blake2_256;
108#[cfg(feature = "runtime-benchmarks")]
109use sp_runtime::traits::TrailingZeroInput;
110use sp_runtime::{
111 generic,
112 traits::{
113 self, AtLeast32Bit, BadOrigin, BlockNumberProvider, Bounded, CheckEqual, Dispatchable,
114 Hash, Header, Lookup, LookupError, MaybeDisplay, MaybeSerializeDeserialize, Member, One,
115 Saturating, SimpleBitOps, StaticLookup, Zero,
116 },
117 transaction_validity::{
118 InvalidTransaction, TransactionLongevity, TransactionSource, TransactionValidity,
119 ValidTransaction,
120 },
121 DispatchError, RuntimeDebug,
122};
123use sp_version::RuntimeVersion;
124
125use codec::{Decode, DecodeWithMemTracking, Encode, EncodeLike, FullCodec, MaxEncodedLen};
126#[cfg(feature = "std")]
127use frame_support::traits::BuildGenesisConfig;
128use frame_support::{
129 dispatch::{
130 extract_actual_pays_fee, extract_actual_weight, DispatchClass, DispatchInfo,
131 DispatchResult, DispatchResultWithPostInfo, GetDispatchInfo, PerDispatchClass,
132 PostDispatchInfo,
133 },
134 ensure, impl_ensure_origin_with_arg_ignoring_arg,
135 migrations::MultiStepMigrator,
136 pallet_prelude::Pays,
137 storage::{self, StorageStreamIter},
138 traits::{
139 ConstU32, Contains, EnsureOrigin, EnsureOriginWithArg, Get, HandleLifetime,
140 OnKilledAccount, OnNewAccount, OnRuntimeUpgrade, OriginTrait, PalletInfo, SortedMembers,
141 StoredMap, TypedGet,
142 },
143 Parameter,
144};
145use scale_info::TypeInfo;
146use sp_core::storage::well_known_keys;
147use sp_runtime::{
148 traits::{DispatchInfoOf, PostDispatchInfoOf},
149 transaction_validity::TransactionValidityError,
150};
151use sp_weights::{RuntimeDbWeight, Weight};
152
153#[cfg(any(feature = "std", test))]
154use sp_io::TestExternalities;
155
156pub mod limits;
157#[cfg(test)]
158pub(crate) mod mock;
159
160pub mod offchain;
161
162mod extensions;
163#[cfg(feature = "std")]
164pub mod mocking;
165#[cfg(test)]
166mod tests;
167pub mod weights;
168
169pub mod migrations;
170
171pub use extensions::{
172 check_genesis::CheckGenesis, check_mortality::CheckMortality,
173 check_non_zero_sender::CheckNonZeroSender, check_nonce::CheckNonce,
174 check_spec_version::CheckSpecVersion, check_tx_version::CheckTxVersion,
175 check_weight::CheckWeight, weight_reclaim::WeightReclaim,
176 weights::SubstrateWeight as SubstrateExtensionsWeight, WeightInfo as ExtensionsWeightInfo,
177};
178pub use extensions::check_mortality::CheckMortality as CheckEra;
180pub use frame_support::dispatch::RawOrigin;
181use frame_support::traits::{PostInherents, PostTransactions, PreInherents};
182use sp_core::storage::StateVersion;
183pub use weights::WeightInfo;
184
185const LOG_TARGET: &str = "runtime::system";
186
187pub fn extrinsics_root<H: Hash, E: codec::Encode>(
192 extrinsics: &[E],
193 state_version: StateVersion,
194) -> H::Output {
195 extrinsics_data_root::<H>(extrinsics.iter().map(codec::Encode::encode).collect(), state_version)
196}
197
198pub fn extrinsics_data_root<H: Hash>(xts: Vec<Vec<u8>>, state_version: StateVersion) -> H::Output {
203 H::ordered_trie_root(xts, state_version)
204}
205
206pub type ConsumedWeight = PerDispatchClass<Weight>;
208
209pub use pallet::*;
210
211pub trait SetCode<T: Config> {
213 fn set_code(code: Vec<u8>) -> DispatchResult;
215}
216
217impl<T: Config> SetCode<T> for () {
218 fn set_code(code: Vec<u8>) -> DispatchResult {
219 <Pallet<T>>::update_code_in_storage(&code);
220 Ok(())
221 }
222}
223
224pub trait ConsumerLimits {
226 fn max_consumers() -> RefCount;
228 fn max_overflow() -> RefCount;
234}
235
236impl<const Z: u32> ConsumerLimits for ConstU32<Z> {
237 fn max_consumers() -> RefCount {
238 Z
239 }
240 fn max_overflow() -> RefCount {
241 Z
242 }
243}
244
245impl<MaxNormal: Get<u32>, MaxOverflow: Get<u32>> ConsumerLimits for (MaxNormal, MaxOverflow) {
246 fn max_consumers() -> RefCount {
247 MaxNormal::get()
248 }
249 fn max_overflow() -> RefCount {
250 MaxOverflow::get()
251 }
252}
253
254#[derive(Decode, Encode, Default, PartialEq, Eq, MaxEncodedLen, TypeInfo)]
257#[scale_info(skip_type_params(T))]
258pub struct CodeUpgradeAuthorization<T>
259where
260 T: Config,
261{
262 code_hash: T::Hash,
264 check_version: bool,
266}
267
268#[derive(
272 Clone,
273 Copy,
274 Eq,
275 PartialEq,
276 Default,
277 RuntimeDebug,
278 Encode,
279 Decode,
280 DecodeWithMemTracking,
281 TypeInfo,
282)]
283pub struct DispatchEventInfo {
284 pub weight: Weight,
286 pub class: DispatchClass,
288 pub pays_fee: Pays,
290}
291
292#[frame_support::pallet]
293pub mod pallet {
294 use crate::{self as frame_system, pallet_prelude::*, *};
295 use codec::HasCompact;
296 use frame_support::pallet_prelude::*;
297
298 pub mod config_preludes {
300 use super::{inject_runtime_type, DefaultConfig};
301 use frame_support::{derive_impl, traits::Get};
302
303 pub struct TestBlockHashCount<C: Get<u32>>(core::marker::PhantomData<C>);
309 impl<I: From<u32>, C: Get<u32>> Get<I> for TestBlockHashCount<C> {
310 fn get() -> I {
311 C::get().into()
312 }
313 }
314
315 pub struct TestDefaultConfig;
322
323 #[frame_support::register_default_impl(TestDefaultConfig)]
324 impl DefaultConfig for TestDefaultConfig {
325 type Nonce = u32;
326 type Hash = sp_core::hash::H256;
327 type Hashing = sp_runtime::traits::BlakeTwo256;
328 type AccountId = u64;
329 type Lookup = sp_runtime::traits::IdentityLookup<Self::AccountId>;
330 type MaxConsumers = frame_support::traits::ConstU32<16>;
331 type AccountData = ();
332 type OnNewAccount = ();
333 type OnKilledAccount = ();
334 type SystemWeightInfo = ();
335 type ExtensionsWeightInfo = ();
336 type SS58Prefix = ();
337 type Version = ();
338 type BlockWeights = ();
339 type BlockLength = ();
340 type DbWeight = ();
341 #[inject_runtime_type]
342 type RuntimeEvent = ();
343 #[inject_runtime_type]
344 type RuntimeOrigin = ();
345 #[inject_runtime_type]
346 type RuntimeCall = ();
347 #[inject_runtime_type]
348 type PalletInfo = ();
349 #[inject_runtime_type]
350 type RuntimeTask = ();
351 type BaseCallFilter = frame_support::traits::Everything;
352 type BlockHashCount = TestBlockHashCount<frame_support::traits::ConstU32<10>>;
353 type OnSetCode = ();
354 type SingleBlockMigrations = ();
355 type MultiBlockMigrator = ();
356 type PreInherents = ();
357 type PostInherents = ();
358 type PostTransactions = ();
359 }
360
361 pub struct SolochainDefaultConfig;
375
376 #[frame_support::register_default_impl(SolochainDefaultConfig)]
377 impl DefaultConfig for SolochainDefaultConfig {
378 type Nonce = u32;
380
381 type Hash = sp_core::hash::H256;
383
384 type Hashing = sp_runtime::traits::BlakeTwo256;
386
387 type AccountId = sp_runtime::AccountId32;
389
390 type Lookup = sp_runtime::traits::AccountIdLookup<Self::AccountId, ()>;
392
393 type MaxConsumers = frame_support::traits::ConstU32<128>;
395
396 type AccountData = ();
398
399 type OnNewAccount = ();
401
402 type OnKilledAccount = ();
404
405 type SystemWeightInfo = ();
407
408 type ExtensionsWeightInfo = ();
410
411 type SS58Prefix = ();
413
414 type Version = ();
416
417 type BlockWeights = ();
419
420 type BlockLength = ();
422
423 type DbWeight = ();
425
426 #[inject_runtime_type]
428 type RuntimeEvent = ();
429
430 #[inject_runtime_type]
432 type RuntimeOrigin = ();
433
434 #[inject_runtime_type]
437 type RuntimeCall = ();
438
439 #[inject_runtime_type]
441 type RuntimeTask = ();
442
443 #[inject_runtime_type]
445 type PalletInfo = ();
446
447 type BaseCallFilter = frame_support::traits::Everything;
449
450 type BlockHashCount = TestBlockHashCount<frame_support::traits::ConstU32<256>>;
453
454 type OnSetCode = ();
456 type SingleBlockMigrations = ();
457 type MultiBlockMigrator = ();
458 type PreInherents = ();
459 type PostInherents = ();
460 type PostTransactions = ();
461 }
462
463 pub struct RelayChainDefaultConfig;
465
466 #[derive_impl(SolochainDefaultConfig as DefaultConfig, no_aggregated_types)]
468 #[frame_support::register_default_impl(RelayChainDefaultConfig)]
469 impl DefaultConfig for RelayChainDefaultConfig {}
470
471 pub struct ParaChainDefaultConfig;
473
474 #[derive_impl(SolochainDefaultConfig as DefaultConfig, no_aggregated_types)]
476 #[frame_support::register_default_impl(ParaChainDefaultConfig)]
477 impl DefaultConfig for ParaChainDefaultConfig {}
478 }
479
480 #[pallet::config(with_default)]
482 #[pallet::disable_frame_system_supertrait_check]
483 pub trait Config: 'static + Eq + Clone {
484 #[pallet::no_default_bounds]
486 type RuntimeEvent: Parameter
487 + Member
488 + From<Event<Self>>
489 + Debug
490 + IsType<<Self as frame_system::Config>::RuntimeEvent>;
491
492 #[pallet::no_default_bounds]
503 type BaseCallFilter: Contains<Self::RuntimeCall>;
504
505 #[pallet::constant]
507 type BlockWeights: Get<limits::BlockWeights>;
508
509 #[pallet::constant]
511 type BlockLength: Get<limits::BlockLength>;
512
513 #[pallet::no_default_bounds]
515 type RuntimeOrigin: Into<Result<RawOrigin<Self::AccountId>, Self::RuntimeOrigin>>
516 + From<RawOrigin<Self::AccountId>>
517 + Clone
518 + OriginTrait<Call = Self::RuntimeCall, AccountId = Self::AccountId>;
519
520 #[docify::export(system_runtime_call)]
521 #[pallet::no_default_bounds]
523 type RuntimeCall: Parameter
524 + Dispatchable<RuntimeOrigin = Self::RuntimeOrigin>
525 + Debug
526 + GetDispatchInfo
527 + From<Call<Self>>;
528
529 #[pallet::no_default_bounds]
531 type RuntimeTask: Task;
532
533 type Nonce: Parameter
535 + HasCompact<Type: DecodeWithMemTracking>
536 + Member
537 + MaybeSerializeDeserialize
538 + Debug
539 + Default
540 + MaybeDisplay
541 + AtLeast32Bit
542 + Copy
543 + MaxEncodedLen;
544
545 type Hash: Parameter
547 + Member
548 + MaybeSerializeDeserialize
549 + Debug
550 + MaybeDisplay
551 + SimpleBitOps
552 + Ord
553 + Default
554 + Copy
555 + CheckEqual
556 + core::hash::Hash
557 + AsRef<[u8]>
558 + AsMut<[u8]>
559 + MaxEncodedLen;
560
561 type Hashing: Hash<Output = Self::Hash> + TypeInfo;
563
564 type AccountId: Parameter
566 + Member
567 + MaybeSerializeDeserialize
568 + Debug
569 + MaybeDisplay
570 + Ord
571 + MaxEncodedLen;
572
573 type Lookup: StaticLookup<Target = Self::AccountId>;
580
581 #[pallet::no_default]
584 type Block: Parameter + Member + traits::Block<Hash = Self::Hash>;
585
586 #[pallet::constant]
588 #[pallet::no_default_bounds]
589 type BlockHashCount: Get<BlockNumberFor<Self>>;
590
591 #[pallet::constant]
593 type DbWeight: Get<RuntimeDbWeight>;
594
595 #[pallet::constant]
597 type Version: Get<RuntimeVersion>;
598
599 #[pallet::no_default_bounds]
606 type PalletInfo: PalletInfo;
607
608 type AccountData: Member + FullCodec + Clone + Default + TypeInfo + MaxEncodedLen;
611
612 type OnNewAccount: OnNewAccount<Self::AccountId>;
614
615 type OnKilledAccount: OnKilledAccount<Self::AccountId>;
619
620 type SystemWeightInfo: WeightInfo;
622
623 type ExtensionsWeightInfo: extensions::WeightInfo;
625
626 #[pallet::constant]
632 type SS58Prefix: Get<u16>;
633
634 #[pallet::no_default_bounds]
642 type OnSetCode: SetCode<Self>;
643
644 type MaxConsumers: ConsumerLimits;
646
647 type SingleBlockMigrations: OnRuntimeUpgrade;
654
655 type MultiBlockMigrator: MultiStepMigrator;
660
661 type PreInherents: PreInherents;
665
666 type PostInherents: PostInherents;
670
671 type PostTransactions: PostTransactions;
675 }
676
677 #[pallet::pallet]
678 pub struct Pallet<T>(_);
679
680 #[pallet::hooks]
681 impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
682 #[cfg(feature = "std")]
683 fn integrity_test() {
684 T::BlockWeights::get().validate().expect("The weights are invalid.");
685 }
686 }
687
688 #[pallet::call]
689 impl<T: Config> Pallet<T> {
690 #[pallet::call_index(0)]
694 #[pallet::weight(T::SystemWeightInfo::remark(remark.len() as u32))]
695 pub fn remark(_origin: OriginFor<T>, remark: Vec<u8>) -> DispatchResultWithPostInfo {
696 let _ = remark; Ok(().into())
698 }
699
700 #[pallet::call_index(1)]
702 #[pallet::weight((T::SystemWeightInfo::set_heap_pages(), DispatchClass::Operational))]
703 pub fn set_heap_pages(origin: OriginFor<T>, pages: u64) -> DispatchResultWithPostInfo {
704 ensure_root(origin)?;
705 storage::unhashed::put_raw(well_known_keys::HEAP_PAGES, &pages.encode());
706 Self::deposit_log(generic::DigestItem::RuntimeEnvironmentUpdated);
707 Ok(().into())
708 }
709
710 #[pallet::call_index(2)]
712 #[pallet::weight((T::SystemWeightInfo::set_code(), DispatchClass::Operational))]
713 pub fn set_code(origin: OriginFor<T>, code: Vec<u8>) -> DispatchResultWithPostInfo {
714 ensure_root(origin)?;
715 Self::can_set_code(&code, true).into_result()?;
716 T::OnSetCode::set_code(code)?;
717 Ok(Some(T::BlockWeights::get().max_block).into())
719 }
720
721 #[pallet::call_index(3)]
726 #[pallet::weight((T::SystemWeightInfo::set_code(), DispatchClass::Operational))]
727 pub fn set_code_without_checks(
728 origin: OriginFor<T>,
729 code: Vec<u8>,
730 ) -> DispatchResultWithPostInfo {
731 ensure_root(origin)?;
732 Self::can_set_code(&code, false).into_result()?;
733 T::OnSetCode::set_code(code)?;
734 Ok(Some(T::BlockWeights::get().max_block).into())
735 }
736
737 #[pallet::call_index(4)]
739 #[pallet::weight((
740 T::SystemWeightInfo::set_storage(items.len() as u32),
741 DispatchClass::Operational,
742 ))]
743 pub fn set_storage(
744 origin: OriginFor<T>,
745 items: Vec<KeyValue>,
746 ) -> DispatchResultWithPostInfo {
747 ensure_root(origin)?;
748 for i in &items {
749 storage::unhashed::put_raw(&i.0, &i.1);
750 }
751 Ok(().into())
752 }
753
754 #[pallet::call_index(5)]
756 #[pallet::weight((
757 T::SystemWeightInfo::kill_storage(keys.len() as u32),
758 DispatchClass::Operational,
759 ))]
760 pub fn kill_storage(origin: OriginFor<T>, keys: Vec<Key>) -> DispatchResultWithPostInfo {
761 ensure_root(origin)?;
762 for key in &keys {
763 storage::unhashed::kill(key);
764 }
765 Ok(().into())
766 }
767
768 #[pallet::call_index(6)]
773 #[pallet::weight((
774 T::SystemWeightInfo::kill_prefix(subkeys.saturating_add(1)),
775 DispatchClass::Operational,
776 ))]
777 pub fn kill_prefix(
778 origin: OriginFor<T>,
779 prefix: Key,
780 subkeys: u32,
781 ) -> DispatchResultWithPostInfo {
782 ensure_root(origin)?;
783 let _ = storage::unhashed::clear_prefix(&prefix, Some(subkeys), None);
784 Ok(().into())
785 }
786
787 #[pallet::call_index(7)]
789 #[pallet::weight(T::SystemWeightInfo::remark_with_event(remark.len() as u32))]
790 pub fn remark_with_event(
791 origin: OriginFor<T>,
792 remark: Vec<u8>,
793 ) -> DispatchResultWithPostInfo {
794 let who = ensure_signed(origin)?;
795 let hash = T::Hashing::hash(&remark[..]);
796 Self::deposit_event(Event::Remarked { sender: who, hash });
797 Ok(().into())
798 }
799
800 #[cfg(feature = "experimental")]
801 #[pallet::call_index(8)]
802 #[pallet::weight(task.weight())]
803 pub fn do_task(_origin: OriginFor<T>, task: T::RuntimeTask) -> DispatchResultWithPostInfo {
804 if !task.is_valid() {
805 return Err(Error::<T>::InvalidTask.into())
806 }
807
808 Self::deposit_event(Event::TaskStarted { task: task.clone() });
809 if let Err(err) = task.run() {
810 Self::deposit_event(Event::TaskFailed { task, err });
811 return Err(Error::<T>::FailedTask.into())
812 }
813
814 Self::deposit_event(Event::TaskCompleted { task });
816
817 Ok(().into())
819 }
820
821 #[pallet::call_index(9)]
826 #[pallet::weight((T::SystemWeightInfo::authorize_upgrade(), DispatchClass::Operational))]
827 pub fn authorize_upgrade(origin: OriginFor<T>, code_hash: T::Hash) -> DispatchResult {
828 ensure_root(origin)?;
829 Self::do_authorize_upgrade(code_hash, true);
830 Ok(())
831 }
832
833 #[pallet::call_index(10)]
842 #[pallet::weight((T::SystemWeightInfo::authorize_upgrade(), DispatchClass::Operational))]
843 pub fn authorize_upgrade_without_checks(
844 origin: OriginFor<T>,
845 code_hash: T::Hash,
846 ) -> DispatchResult {
847 ensure_root(origin)?;
848 Self::do_authorize_upgrade(code_hash, false);
849 Ok(())
850 }
851
852 #[pallet::call_index(11)]
862 #[pallet::weight((T::SystemWeightInfo::apply_authorized_upgrade(), DispatchClass::Operational))]
863 pub fn apply_authorized_upgrade(
864 _: OriginFor<T>,
865 code: Vec<u8>,
866 ) -> DispatchResultWithPostInfo {
867 let res = Self::validate_code_is_authorized(&code)?;
868 AuthorizedUpgrade::<T>::kill();
869
870 match Self::can_set_code(&code, res.check_version) {
871 CanSetCodeResult::Ok => {},
872 CanSetCodeResult::MultiBlockMigrationsOngoing =>
873 return Err(Error::<T>::MultiBlockMigrationsOngoing.into()),
874 CanSetCodeResult::InvalidVersion(error) => {
875 Self::deposit_event(Event::RejectedInvalidAuthorizedUpgrade {
877 code_hash: res.code_hash,
878 error: error.into(),
879 });
880
881 return Ok(Pays::No.into())
883 },
884 };
885 T::OnSetCode::set_code(code)?;
886
887 Ok(PostDispatchInfo {
888 actual_weight: Some(T::BlockWeights::get().max_block),
890 pays_fee: Pays::No,
892 })
893 }
894 }
895
896 #[pallet::event]
898 pub enum Event<T: Config> {
899 ExtrinsicSuccess { dispatch_info: DispatchEventInfo },
901 ExtrinsicFailed { dispatch_error: DispatchError, dispatch_info: DispatchEventInfo },
903 CodeUpdated,
905 NewAccount { account: T::AccountId },
907 KilledAccount { account: T::AccountId },
909 Remarked { sender: T::AccountId, hash: T::Hash },
911 #[cfg(feature = "experimental")]
912 TaskStarted { task: T::RuntimeTask },
914 #[cfg(feature = "experimental")]
915 TaskCompleted { task: T::RuntimeTask },
917 #[cfg(feature = "experimental")]
918 TaskFailed { task: T::RuntimeTask, err: DispatchError },
920 UpgradeAuthorized { code_hash: T::Hash, check_version: bool },
922 RejectedInvalidAuthorizedUpgrade { code_hash: T::Hash, error: DispatchError },
924 }
925
926 #[pallet::error]
928 pub enum Error<T> {
929 InvalidSpecName,
932 SpecVersionNeedsToIncrease,
935 FailedToExtractRuntimeVersion,
939 NonDefaultComposite,
941 NonZeroRefCount,
943 CallFiltered,
945 MultiBlockMigrationsOngoing,
947 #[cfg(feature = "experimental")]
948 InvalidTask,
950 #[cfg(feature = "experimental")]
951 FailedTask,
953 NothingAuthorized,
955 Unauthorized,
957 }
958
959 #[pallet::origin]
961 pub type Origin<T> = RawOrigin<<T as Config>::AccountId>;
962
963 #[pallet::storage]
965 #[pallet::getter(fn account)]
966 pub type Account<T: Config> = StorageMap<
967 _,
968 Blake2_128Concat,
969 T::AccountId,
970 AccountInfo<T::Nonce, T::AccountData>,
971 ValueQuery,
972 >;
973
974 #[pallet::storage]
976 pub(super) type ExtrinsicCount<T: Config> = StorageValue<_, u32>;
977
978 #[pallet::storage]
980 pub type InherentsApplied<T: Config> = StorageValue<_, bool, ValueQuery>;
981
982 #[pallet::storage]
984 #[pallet::whitelist_storage]
985 #[pallet::getter(fn block_weight)]
986 pub type BlockWeight<T: Config> = StorageValue<_, ConsumedWeight, ValueQuery>;
987
988 #[pallet::storage]
990 #[pallet::whitelist_storage]
991 pub type AllExtrinsicsLen<T: Config> = StorageValue<_, u32>;
992
993 #[pallet::storage]
995 #[pallet::getter(fn block_hash)]
996 pub type BlockHash<T: Config> =
997 StorageMap<_, Twox64Concat, BlockNumberFor<T>, T::Hash, ValueQuery>;
998
999 #[pallet::storage]
1001 #[pallet::getter(fn extrinsic_data)]
1002 #[pallet::unbounded]
1003 pub(super) type ExtrinsicData<T: Config> =
1004 StorageMap<_, Twox64Concat, u32, Vec<u8>, ValueQuery>;
1005
1006 #[pallet::storage]
1008 #[pallet::whitelist_storage]
1009 #[pallet::getter(fn block_number)]
1010 pub(super) type Number<T: Config> = StorageValue<_, BlockNumberFor<T>, ValueQuery>;
1011
1012 #[pallet::storage]
1014 #[pallet::getter(fn parent_hash)]
1015 pub(super) type ParentHash<T: Config> = StorageValue<_, T::Hash, ValueQuery>;
1016
1017 #[pallet::storage]
1019 #[pallet::whitelist_storage]
1020 #[pallet::unbounded]
1021 #[pallet::getter(fn digest)]
1022 pub(super) type Digest<T: Config> = StorageValue<_, generic::Digest, ValueQuery>;
1023
1024 #[pallet::storage]
1032 #[pallet::whitelist_storage]
1033 #[pallet::disable_try_decode_storage]
1034 #[pallet::unbounded]
1035 pub(super) type Events<T: Config> =
1036 StorageValue<_, Vec<Box<EventRecord<T::RuntimeEvent, T::Hash>>>, ValueQuery>;
1037
1038 #[pallet::storage]
1040 #[pallet::whitelist_storage]
1041 #[pallet::getter(fn event_count)]
1042 pub(super) type EventCount<T: Config> = StorageValue<_, EventIndex, ValueQuery>;
1043
1044 #[pallet::storage]
1055 #[pallet::unbounded]
1056 #[pallet::getter(fn event_topics)]
1057 pub(super) type EventTopics<T: Config> =
1058 StorageMap<_, Blake2_128Concat, T::Hash, Vec<(BlockNumberFor<T>, EventIndex)>, ValueQuery>;
1059
1060 #[pallet::storage]
1062 #[pallet::unbounded]
1063 pub type LastRuntimeUpgrade<T: Config> = StorageValue<_, LastRuntimeUpgradeInfo>;
1064
1065 #[pallet::storage]
1067 pub(super) type UpgradedToU32RefCount<T: Config> = StorageValue<_, bool, ValueQuery>;
1068
1069 #[pallet::storage]
1072 pub(super) type UpgradedToTripleRefCount<T: Config> = StorageValue<_, bool, ValueQuery>;
1073
1074 #[pallet::storage]
1076 #[pallet::whitelist_storage]
1077 pub(super) type ExecutionPhase<T: Config> = StorageValue<_, Phase>;
1078
1079 #[pallet::storage]
1081 #[pallet::getter(fn authorized_upgrade)]
1082 pub(super) type AuthorizedUpgrade<T: Config> =
1083 StorageValue<_, CodeUpgradeAuthorization<T>, OptionQuery>;
1084
1085 #[pallet::storage]
1093 #[pallet::whitelist_storage]
1094 pub type ExtrinsicWeightReclaimed<T: Config> = StorageValue<_, Weight, ValueQuery>;
1095
1096 #[derive(frame_support::DefaultNoBound)]
1097 #[pallet::genesis_config]
1098 pub struct GenesisConfig<T: Config> {
1099 #[serde(skip)]
1100 pub _config: core::marker::PhantomData<T>,
1101 }
1102
1103 #[pallet::genesis_build]
1104 impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
1105 fn build(&self) {
1106 <BlockHash<T>>::insert::<_, T::Hash>(BlockNumberFor::<T>::zero(), hash69());
1107 <ParentHash<T>>::put::<T::Hash>(hash69());
1108 <LastRuntimeUpgrade<T>>::put(LastRuntimeUpgradeInfo::from(T::Version::get()));
1109 <UpgradedToU32RefCount<T>>::put(true);
1110 <UpgradedToTripleRefCount<T>>::put(true);
1111
1112 sp_io::storage::set(well_known_keys::EXTRINSIC_INDEX, &0u32.encode());
1113 }
1114 }
1115
1116 #[pallet::validate_unsigned]
1117 impl<T: Config> sp_runtime::traits::ValidateUnsigned for Pallet<T> {
1118 type Call = Call<T>;
1119 fn validate_unsigned(_source: TransactionSource, call: &Self::Call) -> TransactionValidity {
1120 if let Call::apply_authorized_upgrade { ref code } = call {
1121 if let Ok(res) = Self::validate_code_is_authorized(&code[..]) {
1122 if Self::can_set_code(&code, false).is_ok() {
1123 return Ok(ValidTransaction {
1124 priority: u64::max_value(),
1125 requires: Vec::new(),
1126 provides: vec![res.code_hash.encode()],
1127 longevity: TransactionLongevity::max_value(),
1128 propagate: true,
1129 })
1130 }
1131 }
1132 }
1133
1134 #[cfg(feature = "experimental")]
1135 if let Call::do_task { ref task } = call {
1136 if task.is_valid() {
1137 return Ok(ValidTransaction {
1138 priority: u64::max_value(),
1139 requires: Vec::new(),
1140 provides: vec![T::Hashing::hash_of(&task.encode()).as_ref().to_vec()],
1141 longevity: TransactionLongevity::max_value(),
1142 propagate: true,
1143 })
1144 }
1145 }
1146
1147 Err(InvalidTransaction::Call.into())
1148 }
1149 }
1150}
1151
1152pub type Key = Vec<u8>;
1153pub type KeyValue = (Vec<u8>, Vec<u8>);
1154
1155#[derive(Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)]
1157#[cfg_attr(feature = "std", derive(Serialize, PartialEq, Eq, Clone))]
1158pub enum Phase {
1159 ApplyExtrinsic(u32),
1161 Finalization,
1163 Initialization,
1165}
1166
1167impl Default for Phase {
1168 fn default() -> Self {
1169 Self::Initialization
1170 }
1171}
1172
1173#[derive(Encode, Decode, RuntimeDebug, TypeInfo)]
1175#[cfg_attr(feature = "std", derive(Serialize, PartialEq, Eq, Clone))]
1176pub struct EventRecord<E: Parameter + Member, T> {
1177 pub phase: Phase,
1179 pub event: E,
1181 pub topics: Vec<T>,
1183}
1184
1185fn hash69<T: AsMut<[u8]> + Default>() -> T {
1188 let mut h = T::default();
1189 h.as_mut().iter_mut().for_each(|byte| *byte = 69);
1190 h
1191}
1192
1193type EventIndex = u32;
1198
1199pub type RefCount = u32;
1201
1202#[derive(Clone, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen)]
1204pub struct AccountInfo<Nonce, AccountData> {
1205 pub nonce: Nonce,
1207 pub consumers: RefCount,
1210 pub providers: RefCount,
1213 pub sufficients: RefCount,
1216 pub data: AccountData,
1219}
1220
1221#[derive(RuntimeDebug, Encode, Decode, TypeInfo)]
1224#[cfg_attr(feature = "std", derive(PartialEq))]
1225pub struct LastRuntimeUpgradeInfo {
1226 pub spec_version: codec::Compact<u32>,
1227 pub spec_name: Cow<'static, str>,
1228}
1229
1230impl LastRuntimeUpgradeInfo {
1231 pub fn was_upgraded(&self, current: &RuntimeVersion) -> bool {
1235 current.spec_version > self.spec_version.0 || current.spec_name != self.spec_name
1236 }
1237}
1238
1239impl From<RuntimeVersion> for LastRuntimeUpgradeInfo {
1240 fn from(version: RuntimeVersion) -> Self {
1241 Self { spec_version: version.spec_version.into(), spec_name: version.spec_name }
1242 }
1243}
1244
1245pub struct EnsureRoot<AccountId>(core::marker::PhantomData<AccountId>);
1247impl<O: OriginTrait, AccountId> EnsureOrigin<O> for EnsureRoot<AccountId> {
1248 type Success = ();
1249 fn try_origin(o: O) -> Result<Self::Success, O> {
1250 match o.as_system_ref() {
1251 Some(RawOrigin::Root) => Ok(()),
1252 _ => Err(o),
1253 }
1254 }
1255
1256 #[cfg(feature = "runtime-benchmarks")]
1257 fn try_successful_origin() -> Result<O, ()> {
1258 Ok(O::root())
1259 }
1260}
1261
1262impl_ensure_origin_with_arg_ignoring_arg! {
1263 impl< { O: .., AccountId: Decode, T } >
1264 EnsureOriginWithArg<O, T> for EnsureRoot<AccountId>
1265 {}
1266}
1267
1268pub struct EnsureRootWithSuccess<AccountId, Success>(
1270 core::marker::PhantomData<(AccountId, Success)>,
1271);
1272impl<O: OriginTrait, AccountId, Success: TypedGet> EnsureOrigin<O>
1273 for EnsureRootWithSuccess<AccountId, Success>
1274{
1275 type Success = Success::Type;
1276 fn try_origin(o: O) -> Result<Self::Success, O> {
1277 match o.as_system_ref() {
1278 Some(RawOrigin::Root) => Ok(Success::get()),
1279 _ => Err(o),
1280 }
1281 }
1282
1283 #[cfg(feature = "runtime-benchmarks")]
1284 fn try_successful_origin() -> Result<O, ()> {
1285 Ok(O::root())
1286 }
1287}
1288
1289impl_ensure_origin_with_arg_ignoring_arg! {
1290 impl< { O: .., AccountId: Decode, Success: TypedGet, T } >
1291 EnsureOriginWithArg<O, T> for EnsureRootWithSuccess<AccountId, Success>
1292 {}
1293}
1294
1295pub struct EnsureWithSuccess<Ensure, AccountId, Success>(
1297 core::marker::PhantomData<(Ensure, AccountId, Success)>,
1298);
1299
1300impl<O: OriginTrait, Ensure: EnsureOrigin<O>, AccountId, Success: TypedGet> EnsureOrigin<O>
1301 for EnsureWithSuccess<Ensure, AccountId, Success>
1302{
1303 type Success = Success::Type;
1304
1305 fn try_origin(o: O) -> Result<Self::Success, O> {
1306 Ensure::try_origin(o).map(|_| Success::get())
1307 }
1308
1309 #[cfg(feature = "runtime-benchmarks")]
1310 fn try_successful_origin() -> Result<O, ()> {
1311 Ensure::try_successful_origin()
1312 }
1313}
1314
1315pub struct EnsureSigned<AccountId>(core::marker::PhantomData<AccountId>);
1317impl<O: OriginTrait<AccountId = AccountId>, AccountId: Decode + Clone> EnsureOrigin<O>
1318 for EnsureSigned<AccountId>
1319{
1320 type Success = AccountId;
1321 fn try_origin(o: O) -> Result<Self::Success, O> {
1322 match o.as_system_ref() {
1323 Some(RawOrigin::Signed(who)) => Ok(who.clone()),
1324 _ => Err(o),
1325 }
1326 }
1327
1328 #[cfg(feature = "runtime-benchmarks")]
1329 fn try_successful_origin() -> Result<O, ()> {
1330 let zero_account_id =
1331 AccountId::decode(&mut TrailingZeroInput::zeroes()).map_err(|_| ())?;
1332 Ok(O::signed(zero_account_id))
1333 }
1334}
1335
1336impl_ensure_origin_with_arg_ignoring_arg! {
1337 impl< { O: OriginTrait<AccountId = AccountId>, AccountId: Decode + Clone, T } >
1338 EnsureOriginWithArg<O, T> for EnsureSigned<AccountId>
1339 {}
1340}
1341
1342pub struct EnsureSignedBy<Who, AccountId>(core::marker::PhantomData<(Who, AccountId)>);
1344impl<
1345 O: OriginTrait<AccountId = AccountId>,
1346 Who: SortedMembers<AccountId>,
1347 AccountId: PartialEq + Clone + Ord + Decode,
1348 > EnsureOrigin<O> for EnsureSignedBy<Who, AccountId>
1349{
1350 type Success = AccountId;
1351 fn try_origin(o: O) -> Result<Self::Success, O> {
1352 match o.as_system_ref() {
1353 Some(RawOrigin::Signed(ref who)) if Who::contains(who) => Ok(who.clone()),
1354 _ => Err(o),
1355 }
1356 }
1357
1358 #[cfg(feature = "runtime-benchmarks")]
1359 fn try_successful_origin() -> Result<O, ()> {
1360 let first_member = match Who::sorted_members().first() {
1361 Some(account) => account.clone(),
1362 None => AccountId::decode(&mut TrailingZeroInput::zeroes()).map_err(|_| ())?,
1363 };
1364 Ok(O::signed(first_member))
1365 }
1366}
1367
1368impl_ensure_origin_with_arg_ignoring_arg! {
1369 impl< { O: OriginTrait<AccountId = AccountId>, Who: SortedMembers<AccountId>, AccountId: PartialEq + Clone + Ord + Decode, T } >
1370 EnsureOriginWithArg<O, T> for EnsureSignedBy<Who, AccountId>
1371 {}
1372}
1373
1374pub struct EnsureNone<AccountId>(core::marker::PhantomData<AccountId>);
1376impl<O: OriginTrait<AccountId = AccountId>, AccountId> EnsureOrigin<O> for EnsureNone<AccountId> {
1377 type Success = ();
1378 fn try_origin(o: O) -> Result<Self::Success, O> {
1379 match o.as_system_ref() {
1380 Some(RawOrigin::None) => Ok(()),
1381 _ => Err(o),
1382 }
1383 }
1384
1385 #[cfg(feature = "runtime-benchmarks")]
1386 fn try_successful_origin() -> Result<O, ()> {
1387 Ok(O::none())
1388 }
1389}
1390
1391impl_ensure_origin_with_arg_ignoring_arg! {
1392 impl< { O: OriginTrait<AccountId = AccountId>, AccountId, T } >
1393 EnsureOriginWithArg<O, T> for EnsureNone<AccountId>
1394 {}
1395}
1396
1397pub struct EnsureNever<Success>(core::marker::PhantomData<Success>);
1399impl<O, Success> EnsureOrigin<O> for EnsureNever<Success> {
1400 type Success = Success;
1401 fn try_origin(o: O) -> Result<Self::Success, O> {
1402 Err(o)
1403 }
1404
1405 #[cfg(feature = "runtime-benchmarks")]
1406 fn try_successful_origin() -> Result<O, ()> {
1407 Err(())
1408 }
1409}
1410
1411impl_ensure_origin_with_arg_ignoring_arg! {
1412 impl< { O, Success, T } >
1413 EnsureOriginWithArg<O, T> for EnsureNever<Success>
1414 {}
1415}
1416
1417#[docify::export]
1418pub fn ensure_signed<OuterOrigin, AccountId>(o: OuterOrigin) -> Result<AccountId, BadOrigin>
1421where
1422 OuterOrigin: Into<Result<RawOrigin<AccountId>, OuterOrigin>>,
1423{
1424 match o.into() {
1425 Ok(RawOrigin::Signed(t)) => Ok(t),
1426 _ => Err(BadOrigin),
1427 }
1428}
1429
1430pub fn ensure_signed_or_root<OuterOrigin, AccountId>(
1434 o: OuterOrigin,
1435) -> Result<Option<AccountId>, BadOrigin>
1436where
1437 OuterOrigin: Into<Result<RawOrigin<AccountId>, OuterOrigin>>,
1438{
1439 match o.into() {
1440 Ok(RawOrigin::Root) => Ok(None),
1441 Ok(RawOrigin::Signed(t)) => Ok(Some(t)),
1442 _ => Err(BadOrigin),
1443 }
1444}
1445
1446pub fn ensure_root<OuterOrigin, AccountId>(o: OuterOrigin) -> Result<(), BadOrigin>
1448where
1449 OuterOrigin: Into<Result<RawOrigin<AccountId>, OuterOrigin>>,
1450{
1451 match o.into() {
1452 Ok(RawOrigin::Root) => Ok(()),
1453 _ => Err(BadOrigin),
1454 }
1455}
1456
1457pub fn ensure_none<OuterOrigin, AccountId>(o: OuterOrigin) -> Result<(), BadOrigin>
1459where
1460 OuterOrigin: Into<Result<RawOrigin<AccountId>, OuterOrigin>>,
1461{
1462 match o.into() {
1463 Ok(RawOrigin::None) => Ok(()),
1464 _ => Err(BadOrigin),
1465 }
1466}
1467
1468#[derive(RuntimeDebug)]
1470pub enum RefStatus {
1471 Referenced,
1472 Unreferenced,
1473}
1474
1475#[derive(Eq, PartialEq, RuntimeDebug)]
1477pub enum IncRefStatus {
1478 Created,
1480 Existed,
1482}
1483
1484#[derive(Eq, PartialEq, RuntimeDebug)]
1486pub enum DecRefStatus {
1487 Reaped,
1489 Exists,
1491}
1492
1493pub enum CanSetCodeResult<T: Config> {
1495 Ok,
1497 MultiBlockMigrationsOngoing,
1499 InvalidVersion(Error<T>),
1501}
1502
1503impl<T: Config> CanSetCodeResult<T> {
1504 pub fn into_result(self) -> Result<(), DispatchError> {
1506 match self {
1507 Self::Ok => Ok(()),
1508 Self::MultiBlockMigrationsOngoing =>
1509 Err(Error::<T>::MultiBlockMigrationsOngoing.into()),
1510 Self::InvalidVersion(err) => Err(err.into()),
1511 }
1512 }
1513
1514 pub fn is_ok(&self) -> bool {
1516 matches!(self, Self::Ok)
1517 }
1518}
1519
1520impl<T: Config> Pallet<T> {
1521 #[doc = docify::embed!("src/tests.rs", last_runtime_upgrade_spec_version_usage)]
1535 pub fn last_runtime_upgrade_spec_version() -> u32 {
1536 LastRuntimeUpgrade::<T>::get().map_or(0, |l| l.spec_version.0)
1537 }
1538
1539 pub fn account_exists(who: &T::AccountId) -> bool {
1541 Account::<T>::contains_key(who)
1542 }
1543
1544 pub fn update_code_in_storage(code: &[u8]) {
1550 storage::unhashed::put_raw(well_known_keys::CODE, code);
1551 Self::deposit_log(generic::DigestItem::RuntimeEnvironmentUpdated);
1552 Self::deposit_event(Event::CodeUpdated);
1553 }
1554
1555 pub fn inherents_applied() -> bool {
1557 InherentsApplied::<T>::get()
1558 }
1559
1560 pub fn note_inherents_applied() {
1565 InherentsApplied::<T>::put(true);
1566 }
1567
1568 #[deprecated = "Use `inc_consumers` instead"]
1570 pub fn inc_ref(who: &T::AccountId) {
1571 let _ = Self::inc_consumers(who);
1572 }
1573
1574 #[deprecated = "Use `dec_consumers` instead"]
1577 pub fn dec_ref(who: &T::AccountId) {
1578 let _ = Self::dec_consumers(who);
1579 }
1580
1581 #[deprecated = "Use `consumers` instead"]
1583 pub fn refs(who: &T::AccountId) -> RefCount {
1584 Self::consumers(who)
1585 }
1586
1587 #[deprecated = "Use `!is_provider_required` instead"]
1589 pub fn allow_death(who: &T::AccountId) -> bool {
1590 !Self::is_provider_required(who)
1591 }
1592
1593 pub fn inc_providers(who: &T::AccountId) -> IncRefStatus {
1595 Account::<T>::mutate(who, |a| {
1596 if a.providers == 0 && a.sufficients == 0 {
1597 a.providers = 1;
1599 Self::on_created_account(who.clone(), a);
1600 IncRefStatus::Created
1601 } else {
1602 a.providers = a.providers.saturating_add(1);
1603 IncRefStatus::Existed
1604 }
1605 })
1606 }
1607
1608 pub fn dec_providers(who: &T::AccountId) -> Result<DecRefStatus, DispatchError> {
1612 Account::<T>::try_mutate_exists(who, |maybe_account| {
1613 if let Some(mut account) = maybe_account.take() {
1614 if account.providers == 0 {
1615 log::error!(
1617 target: LOG_TARGET,
1618 "Logic error: Unexpected underflow in reducing provider",
1619 );
1620 account.providers = 1;
1621 }
1622 match (account.providers, account.consumers, account.sufficients) {
1623 (1, 0, 0) => {
1624 Pallet::<T>::on_killed_account(who.clone());
1627 Ok(DecRefStatus::Reaped)
1628 },
1629 (1, c, _) if c > 0 => {
1630 Err(DispatchError::ConsumerRemaining)
1632 },
1633 (x, _, _) => {
1634 account.providers = x - 1;
1637 *maybe_account = Some(account);
1638 Ok(DecRefStatus::Exists)
1639 },
1640 }
1641 } else {
1642 log::error!(
1643 target: LOG_TARGET,
1644 "Logic error: Account already dead when reducing provider",
1645 );
1646 Ok(DecRefStatus::Reaped)
1647 }
1648 })
1649 }
1650
1651 pub fn inc_sufficients(who: &T::AccountId) -> IncRefStatus {
1653 Account::<T>::mutate(who, |a| {
1654 if a.providers + a.sufficients == 0 {
1655 a.sufficients = 1;
1657 Self::on_created_account(who.clone(), a);
1658 IncRefStatus::Created
1659 } else {
1660 a.sufficients = a.sufficients.saturating_add(1);
1661 IncRefStatus::Existed
1662 }
1663 })
1664 }
1665
1666 pub fn dec_sufficients(who: &T::AccountId) -> DecRefStatus {
1670 Account::<T>::mutate_exists(who, |maybe_account| {
1671 if let Some(mut account) = maybe_account.take() {
1672 if account.sufficients == 0 {
1673 log::error!(
1675 target: LOG_TARGET,
1676 "Logic error: Unexpected underflow in reducing sufficients",
1677 );
1678 }
1679 match (account.sufficients, account.providers) {
1680 (0, 0) | (1, 0) => {
1681 Pallet::<T>::on_killed_account(who.clone());
1682 DecRefStatus::Reaped
1683 },
1684 (x, _) => {
1685 account.sufficients = x.saturating_sub(1);
1686 *maybe_account = Some(account);
1687 DecRefStatus::Exists
1688 },
1689 }
1690 } else {
1691 log::error!(
1692 target: LOG_TARGET,
1693 "Logic error: Account already dead when reducing provider",
1694 );
1695 DecRefStatus::Reaped
1696 }
1697 })
1698 }
1699
1700 pub fn providers(who: &T::AccountId) -> RefCount {
1702 Account::<T>::get(who).providers
1703 }
1704
1705 pub fn sufficients(who: &T::AccountId) -> RefCount {
1707 Account::<T>::get(who).sufficients
1708 }
1709
1710 pub fn reference_count(who: &T::AccountId) -> RefCount {
1712 let a = Account::<T>::get(who);
1713 a.providers + a.sufficients
1714 }
1715
1716 pub fn inc_consumers(who: &T::AccountId) -> Result<(), DispatchError> {
1721 Account::<T>::try_mutate(who, |a| {
1722 if a.providers > 0 {
1723 if a.consumers < T::MaxConsumers::max_consumers() {
1724 a.consumers = a.consumers.saturating_add(1);
1725 Ok(())
1726 } else {
1727 Err(DispatchError::TooManyConsumers)
1728 }
1729 } else {
1730 Err(DispatchError::NoProviders)
1731 }
1732 })
1733 }
1734
1735 pub fn inc_consumers_without_limit(who: &T::AccountId) -> Result<(), DispatchError> {
1739 Account::<T>::try_mutate(who, |a| {
1740 if a.providers > 0 {
1741 a.consumers = a.consumers.saturating_add(1);
1742 Ok(())
1743 } else {
1744 Err(DispatchError::NoProviders)
1745 }
1746 })
1747 }
1748
1749 pub fn dec_consumers(who: &T::AccountId) {
1752 Account::<T>::mutate(who, |a| {
1753 if a.consumers > 0 {
1754 a.consumers -= 1;
1755 } else {
1756 log::error!(
1757 target: LOG_TARGET,
1758 "Logic error: Unexpected underflow in reducing consumer",
1759 );
1760 }
1761 })
1762 }
1763
1764 pub fn consumers(who: &T::AccountId) -> RefCount {
1766 Account::<T>::get(who).consumers
1767 }
1768
1769 pub fn is_provider_required(who: &T::AccountId) -> bool {
1771 Account::<T>::get(who).consumers != 0
1772 }
1773
1774 pub fn can_dec_provider(who: &T::AccountId) -> bool {
1776 let a = Account::<T>::get(who);
1777 a.consumers == 0 || a.providers > 1
1778 }
1779
1780 pub fn can_accrue_consumers(who: &T::AccountId, amount: u32) -> bool {
1783 let a = Account::<T>::get(who);
1784 match a.consumers.checked_add(amount) {
1785 Some(c) => a.providers > 0 && c <= T::MaxConsumers::max_consumers(),
1786 None => false,
1787 }
1788 }
1789
1790 pub fn can_inc_consumer(who: &T::AccountId) -> bool {
1793 Self::can_accrue_consumers(who, 1)
1794 }
1795
1796 pub fn deposit_event(event: impl Into<T::RuntimeEvent>) {
1800 Self::deposit_event_indexed(&[], event.into());
1801 }
1802
1803 pub fn deposit_event_indexed(topics: &[T::Hash], event: T::RuntimeEvent) {
1811 let block_number = Self::block_number();
1812
1813 if block_number.is_zero() {
1815 return
1816 }
1817
1818 let phase = ExecutionPhase::<T>::get().unwrap_or_default();
1819 let event = EventRecord { phase, event, topics: topics.to_vec() };
1820
1821 let event_idx = {
1823 let old_event_count = EventCount::<T>::get();
1824 let new_event_count = match old_event_count.checked_add(1) {
1825 None => return,
1828 Some(nc) => nc,
1829 };
1830 EventCount::<T>::put(new_event_count);
1831 old_event_count
1832 };
1833
1834 Events::<T>::append(event);
1835
1836 for topic in topics {
1837 <EventTopics<T>>::append(topic, &(block_number, event_idx));
1838 }
1839 }
1840
1841 pub fn extrinsic_index() -> Option<u32> {
1843 storage::unhashed::get(well_known_keys::EXTRINSIC_INDEX)
1844 }
1845
1846 pub fn extrinsic_count() -> u32 {
1848 ExtrinsicCount::<T>::get().unwrap_or_default()
1849 }
1850
1851 pub fn all_extrinsics_len() -> u32 {
1852 AllExtrinsicsLen::<T>::get().unwrap_or_default()
1853 }
1854
1855 pub fn register_extra_weight_unchecked(weight: Weight, class: DispatchClass) {
1871 BlockWeight::<T>::mutate(|current_weight| {
1872 current_weight.accrue(weight, class);
1873 });
1874 }
1875
1876 pub fn initialize(number: &BlockNumberFor<T>, parent_hash: &T::Hash, digest: &generic::Digest) {
1878 ExecutionPhase::<T>::put(Phase::Initialization);
1880 storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &0u32);
1881 let entropy = (b"frame_system::initialize", parent_hash).using_encoded(blake2_256);
1882 storage::unhashed::put_raw(well_known_keys::INTRABLOCK_ENTROPY, &entropy[..]);
1883 <Number<T>>::put(number);
1884 <Digest<T>>::put(digest);
1885 <ParentHash<T>>::put(parent_hash);
1886 <BlockHash<T>>::insert(*number - One::one(), parent_hash);
1887 <InherentsApplied<T>>::kill();
1888
1889 BlockWeight::<T>::kill();
1891 }
1892
1893 pub fn finalize() -> HeaderFor<T> {
1896 log::debug!(
1897 target: LOG_TARGET,
1898 "[{:?}] {} extrinsics, length: {} (normal {}%, op: {}%, mandatory {}%) / normal weight:\
1899 {} ({}%) op weight {} ({}%) / mandatory weight {} ({}%)",
1900 Self::block_number(),
1901 Self::extrinsic_count(),
1902 Self::all_extrinsics_len(),
1903 sp_runtime::Percent::from_rational(
1904 Self::all_extrinsics_len(),
1905 *T::BlockLength::get().max.get(DispatchClass::Normal)
1906 ).deconstruct(),
1907 sp_runtime::Percent::from_rational(
1908 Self::all_extrinsics_len(),
1909 *T::BlockLength::get().max.get(DispatchClass::Operational)
1910 ).deconstruct(),
1911 sp_runtime::Percent::from_rational(
1912 Self::all_extrinsics_len(),
1913 *T::BlockLength::get().max.get(DispatchClass::Mandatory)
1914 ).deconstruct(),
1915 Self::block_weight().get(DispatchClass::Normal),
1916 sp_runtime::Percent::from_rational(
1917 Self::block_weight().get(DispatchClass::Normal).ref_time(),
1918 T::BlockWeights::get().get(DispatchClass::Normal).max_total.unwrap_or(Bounded::max_value()).ref_time()
1919 ).deconstruct(),
1920 Self::block_weight().get(DispatchClass::Operational),
1921 sp_runtime::Percent::from_rational(
1922 Self::block_weight().get(DispatchClass::Operational).ref_time(),
1923 T::BlockWeights::get().get(DispatchClass::Operational).max_total.unwrap_or(Bounded::max_value()).ref_time()
1924 ).deconstruct(),
1925 Self::block_weight().get(DispatchClass::Mandatory),
1926 sp_runtime::Percent::from_rational(
1927 Self::block_weight().get(DispatchClass::Mandatory).ref_time(),
1928 T::BlockWeights::get().get(DispatchClass::Mandatory).max_total.unwrap_or(Bounded::max_value()).ref_time()
1929 ).deconstruct(),
1930 );
1931 ExecutionPhase::<T>::kill();
1932 AllExtrinsicsLen::<T>::kill();
1933 storage::unhashed::kill(well_known_keys::INTRABLOCK_ENTROPY);
1934 InherentsApplied::<T>::kill();
1935
1936 let number = <Number<T>>::get();
1947 let parent_hash = <ParentHash<T>>::get();
1948 let digest = <Digest<T>>::get();
1949
1950 let extrinsics = (0..ExtrinsicCount::<T>::take().unwrap_or_default())
1951 .map(ExtrinsicData::<T>::take)
1952 .collect();
1953 let extrinsics_root_state_version = T::Version::get().extrinsics_root_state_version();
1954 let extrinsics_root =
1955 extrinsics_data_root::<T::Hashing>(extrinsics, extrinsics_root_state_version);
1956
1957 let block_hash_count = T::BlockHashCount::get();
1959 let to_remove = number.saturating_sub(block_hash_count).saturating_sub(One::one());
1960
1961 if !to_remove.is_zero() {
1963 <BlockHash<T>>::remove(to_remove);
1964 }
1965
1966 let version = T::Version::get().state_version();
1967 let storage_root = T::Hash::decode(&mut &sp_io::storage::root(version)[..])
1968 .expect("Node is configured to use the same hash; qed");
1969
1970 HeaderFor::<T>::new(number, extrinsics_root, storage_root, parent_hash, digest)
1971 }
1972
1973 pub fn deposit_log(item: generic::DigestItem) {
1975 <Digest<T>>::append(item);
1976 }
1977
1978 #[cfg(any(feature = "std", test))]
1980 pub fn externalities() -> TestExternalities {
1981 TestExternalities::new(sp_core::storage::Storage {
1982 top: [
1983 (<BlockHash<T>>::hashed_key_for(BlockNumberFor::<T>::zero()), [69u8; 32].encode()),
1984 (<Number<T>>::hashed_key().to_vec(), BlockNumberFor::<T>::one().encode()),
1985 (<ParentHash<T>>::hashed_key().to_vec(), [69u8; 32].encode()),
1986 ]
1987 .into_iter()
1988 .collect(),
1989 children_default: Default::default(),
1990 })
1991 }
1992
1993 #[cfg(any(feature = "std", feature = "runtime-benchmarks", test))]
2001 pub fn events() -> Vec<EventRecord<T::RuntimeEvent, T::Hash>> {
2002 Self::read_events_no_consensus().map(|e| *e).collect()
2004 }
2005
2006 pub fn event_no_consensus(index: usize) -> Option<T::RuntimeEvent> {
2011 Self::read_events_no_consensus().nth(index).map(|e| e.event.clone())
2012 }
2013
2014 pub fn read_events_no_consensus(
2019 ) -> impl Iterator<Item = Box<EventRecord<T::RuntimeEvent, T::Hash>>> {
2020 Events::<T>::stream_iter()
2021 }
2022
2023 pub fn read_events_for_pallet<E>() -> Vec<E>
2028 where
2029 T::RuntimeEvent: TryInto<E>,
2030 {
2031 Events::<T>::get()
2032 .into_iter()
2033 .map(|er| er.event)
2034 .filter_map(|e| e.try_into().ok())
2035 .collect::<_>()
2036 }
2037
2038 #[cfg(any(feature = "std", feature = "runtime-benchmarks", test))]
2047 pub fn run_to_block_with<AllPalletsWithSystem>(
2048 n: BlockNumberFor<T>,
2049 mut hooks: RunToBlockHooks<T>,
2050 ) where
2051 AllPalletsWithSystem: frame_support::traits::OnInitialize<BlockNumberFor<T>>
2052 + frame_support::traits::OnFinalize<BlockNumberFor<T>>,
2053 {
2054 let mut bn = Self::block_number();
2055
2056 while bn < n {
2057 if !bn.is_zero() {
2059 (hooks.before_finalize)(bn);
2060 AllPalletsWithSystem::on_finalize(bn);
2061 (hooks.after_finalize)(bn);
2062 }
2063
2064 bn += One::one();
2065
2066 Self::set_block_number(bn);
2067 (hooks.before_initialize)(bn);
2068 AllPalletsWithSystem::on_initialize(bn);
2069 (hooks.after_initialize)(bn);
2070 }
2071 }
2072
2073 #[cfg(any(feature = "std", feature = "runtime-benchmarks", test))]
2075 pub fn run_to_block<AllPalletsWithSystem>(n: BlockNumberFor<T>)
2076 where
2077 AllPalletsWithSystem: frame_support::traits::OnInitialize<BlockNumberFor<T>>
2078 + frame_support::traits::OnFinalize<BlockNumberFor<T>>,
2079 {
2080 Self::run_to_block_with::<AllPalletsWithSystem>(n, Default::default());
2081 }
2082
2083 #[cfg(any(feature = "std", feature = "runtime-benchmarks", test))]
2086 pub fn set_block_number(n: BlockNumberFor<T>) {
2087 <Number<T>>::put(n);
2088 }
2089
2090 #[cfg(any(feature = "std", test))]
2092 pub fn set_extrinsic_index(extrinsic_index: u32) {
2093 storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &extrinsic_index)
2094 }
2095
2096 #[cfg(any(feature = "std", test))]
2099 pub fn set_parent_hash(n: T::Hash) {
2100 <ParentHash<T>>::put(n);
2101 }
2102
2103 #[cfg(any(feature = "std", test))]
2105 pub fn set_block_consumed_resources(weight: Weight, len: usize) {
2106 BlockWeight::<T>::mutate(|current_weight| {
2107 current_weight.set(weight, DispatchClass::Normal)
2108 });
2109 AllExtrinsicsLen::<T>::put(len as u32);
2110 }
2111
2112 pub fn reset_events() {
2117 <Events<T>>::kill();
2118 EventCount::<T>::kill();
2119 let _ = <EventTopics<T>>::clear(u32::max_value(), None);
2120 }
2121
2122 #[cfg(any(feature = "std", feature = "runtime-benchmarks", test))]
2126 #[track_caller]
2127 pub fn assert_has_event(event: T::RuntimeEvent) {
2128 let warn = if Self::block_number().is_zero() {
2129 "WARNING: block number is zero, and events are not registered at block number zero.\n"
2130 } else {
2131 ""
2132 };
2133
2134 let events = Self::events();
2135 assert!(
2136 events.iter().any(|record| record.event == event),
2137 "{warn}expected event {event:?} not found in events {events:?}",
2138 );
2139 }
2140
2141 #[cfg(any(feature = "std", feature = "runtime-benchmarks", test))]
2145 #[track_caller]
2146 pub fn assert_last_event(event: T::RuntimeEvent) {
2147 let warn = if Self::block_number().is_zero() {
2148 "WARNING: block number is zero, and events are not registered at block number zero.\n"
2149 } else {
2150 ""
2151 };
2152
2153 let last_event = Self::events()
2154 .last()
2155 .expect(&alloc::format!("{warn}events expected"))
2156 .event
2157 .clone();
2158 assert_eq!(
2159 last_event, event,
2160 "{warn}expected event {event:?} is not equal to the last event {last_event:?}",
2161 );
2162 }
2163
2164 pub fn runtime_version() -> RuntimeVersion {
2166 T::Version::get()
2167 }
2168
2169 pub fn account_nonce(who: impl EncodeLike<T::AccountId>) -> T::Nonce {
2171 Account::<T>::get(who).nonce
2172 }
2173
2174 pub fn inc_account_nonce(who: impl EncodeLike<T::AccountId>) {
2176 Account::<T>::mutate(who, |a| a.nonce += T::Nonce::one());
2177 }
2178
2179 pub fn note_extrinsic(encoded_xt: Vec<u8>) {
2184 ExtrinsicData::<T>::insert(Self::extrinsic_index().unwrap_or_default(), encoded_xt);
2185 }
2186
2187 pub fn note_applied_extrinsic(r: &DispatchResultWithPostInfo, info: DispatchInfo) {
2193 let weight = extract_actual_weight(r, &info)
2194 .saturating_add(T::BlockWeights::get().get(info.class).base_extrinsic);
2195 let class = info.class;
2196 let pays_fee = extract_actual_pays_fee(r, &info);
2197 let dispatch_event_info = DispatchEventInfo { weight, class, pays_fee };
2198
2199 Self::deposit_event(match r {
2200 Ok(_) => Event::ExtrinsicSuccess { dispatch_info: dispatch_event_info },
2201 Err(err) => {
2202 log::trace!(
2203 target: LOG_TARGET,
2204 "Extrinsic failed at block({:?}): {:?}",
2205 Self::block_number(),
2206 err,
2207 );
2208 Event::ExtrinsicFailed {
2209 dispatch_error: err.error,
2210 dispatch_info: dispatch_event_info,
2211 }
2212 },
2213 });
2214
2215 log::trace!(
2216 target: LOG_TARGET,
2217 "Used block weight: {:?}",
2218 BlockWeight::<T>::get(),
2219 );
2220
2221 log::trace!(
2222 target: LOG_TARGET,
2223 "Used block length: {:?}",
2224 Pallet::<T>::all_extrinsics_len(),
2225 );
2226
2227 let next_extrinsic_index = Self::extrinsic_index().unwrap_or_default() + 1u32;
2228
2229 storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &next_extrinsic_index);
2230 ExecutionPhase::<T>::put(Phase::ApplyExtrinsic(next_extrinsic_index));
2231 ExtrinsicWeightReclaimed::<T>::kill();
2232 }
2233
2234 pub fn note_finished_extrinsics() {
2237 let extrinsic_index: u32 =
2238 storage::unhashed::take(well_known_keys::EXTRINSIC_INDEX).unwrap_or_default();
2239 ExtrinsicCount::<T>::put(extrinsic_index);
2240 ExecutionPhase::<T>::put(Phase::Finalization);
2241 }
2242
2243 pub fn note_finished_initialize() {
2246 ExecutionPhase::<T>::put(Phase::ApplyExtrinsic(0))
2247 }
2248
2249 pub fn on_created_account(who: T::AccountId, _a: &mut AccountInfo<T::Nonce, T::AccountData>) {
2251 T::OnNewAccount::on_new_account(&who);
2252 Self::deposit_event(Event::NewAccount { account: who });
2253 }
2254
2255 fn on_killed_account(who: T::AccountId) {
2257 T::OnKilledAccount::on_killed_account(&who);
2258 Self::deposit_event(Event::KilledAccount { account: who });
2259 }
2260
2261 pub fn can_set_code(code: &[u8], check_version: bool) -> CanSetCodeResult<T> {
2265 if T::MultiBlockMigrator::ongoing() {
2266 return CanSetCodeResult::MultiBlockMigrationsOngoing
2267 }
2268
2269 if check_version {
2270 let current_version = T::Version::get();
2271 let Some(new_version) = sp_io::misc::runtime_version(code)
2272 .and_then(|v| RuntimeVersion::decode(&mut &v[..]).ok())
2273 else {
2274 return CanSetCodeResult::InvalidVersion(Error::<T>::FailedToExtractRuntimeVersion)
2275 };
2276
2277 cfg_if::cfg_if! {
2278 if #[cfg(all(feature = "runtime-benchmarks", not(test)))] {
2279 core::hint::black_box((new_version, current_version));
2281 } else {
2282 if new_version.spec_name != current_version.spec_name {
2283 return CanSetCodeResult::InvalidVersion( Error::<T>::InvalidSpecName)
2284 }
2285
2286 if new_version.spec_version <= current_version.spec_version {
2287 return CanSetCodeResult::InvalidVersion(Error::<T>::SpecVersionNeedsToIncrease)
2288 }
2289 }
2290 }
2291 }
2292
2293 CanSetCodeResult::Ok
2294 }
2295
2296 pub fn do_authorize_upgrade(code_hash: T::Hash, check_version: bool) {
2298 AuthorizedUpgrade::<T>::put(CodeUpgradeAuthorization { code_hash, check_version });
2299 Self::deposit_event(Event::UpgradeAuthorized { code_hash, check_version });
2300 }
2301
2302 fn validate_code_is_authorized(
2306 code: &[u8],
2307 ) -> Result<CodeUpgradeAuthorization<T>, DispatchError> {
2308 let authorization = AuthorizedUpgrade::<T>::get().ok_or(Error::<T>::NothingAuthorized)?;
2309 let actual_hash = T::Hashing::hash(code);
2310 ensure!(actual_hash == authorization.code_hash, Error::<T>::Unauthorized);
2311 Ok(authorization)
2312 }
2313
2314 pub fn reclaim_weight(
2319 info: &DispatchInfoOf<T::RuntimeCall>,
2320 post_info: &PostDispatchInfoOf<T::RuntimeCall>,
2321 ) -> Result<(), TransactionValidityError>
2322 where
2323 T::RuntimeCall: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
2324 {
2325 let already_reclaimed = crate::ExtrinsicWeightReclaimed::<T>::get();
2326 let unspent = post_info.calc_unspent(info);
2327 let accurate_reclaim = already_reclaimed.max(unspent);
2328 let to_reclaim_more = accurate_reclaim.saturating_sub(already_reclaimed);
2330 if to_reclaim_more != Weight::zero() {
2331 crate::BlockWeight::<T>::mutate(|current_weight| {
2332 current_weight.reduce(to_reclaim_more, info.class);
2333 });
2334 crate::ExtrinsicWeightReclaimed::<T>::put(accurate_reclaim);
2335 }
2336
2337 Ok(())
2338 }
2339}
2340
2341pub fn unique(entropy: impl Encode) -> [u8; 32] {
2344 let mut last = [0u8; 32];
2345 sp_io::storage::read(well_known_keys::INTRABLOCK_ENTROPY, &mut last[..], 0);
2346 let next = (b"frame_system::unique", entropy, last).using_encoded(blake2_256);
2347 sp_io::storage::set(well_known_keys::INTRABLOCK_ENTROPY, &next);
2348 next
2349}
2350
2351pub struct Provider<T>(PhantomData<T>);
2353impl<T: Config> HandleLifetime<T::AccountId> for Provider<T> {
2354 fn created(t: &T::AccountId) -> Result<(), DispatchError> {
2355 Pallet::<T>::inc_providers(t);
2356 Ok(())
2357 }
2358 fn killed(t: &T::AccountId) -> Result<(), DispatchError> {
2359 Pallet::<T>::dec_providers(t).map(|_| ())
2360 }
2361}
2362
2363pub struct SelfSufficient<T>(PhantomData<T>);
2365impl<T: Config> HandleLifetime<T::AccountId> for SelfSufficient<T> {
2366 fn created(t: &T::AccountId) -> Result<(), DispatchError> {
2367 Pallet::<T>::inc_sufficients(t);
2368 Ok(())
2369 }
2370 fn killed(t: &T::AccountId) -> Result<(), DispatchError> {
2371 Pallet::<T>::dec_sufficients(t);
2372 Ok(())
2373 }
2374}
2375
2376pub struct Consumer<T>(PhantomData<T>);
2378impl<T: Config> HandleLifetime<T::AccountId> for Consumer<T> {
2379 fn created(t: &T::AccountId) -> Result<(), DispatchError> {
2380 Pallet::<T>::inc_consumers(t)
2381 }
2382 fn killed(t: &T::AccountId) -> Result<(), DispatchError> {
2383 Pallet::<T>::dec_consumers(t);
2384 Ok(())
2385 }
2386}
2387
2388impl<T: Config> BlockNumberProvider for Pallet<T> {
2389 type BlockNumber = BlockNumberFor<T>;
2390
2391 fn current_block_number() -> Self::BlockNumber {
2392 Pallet::<T>::block_number()
2393 }
2394
2395 #[cfg(feature = "runtime-benchmarks")]
2396 fn set_block_number(n: BlockNumberFor<T>) {
2397 Self::set_block_number(n)
2398 }
2399}
2400
2401impl<T: Config> StoredMap<T::AccountId, T::AccountData> for Pallet<T> {
2407 fn get(k: &T::AccountId) -> T::AccountData {
2408 Account::<T>::get(k).data
2409 }
2410
2411 fn try_mutate_exists<R, E: From<DispatchError>>(
2412 k: &T::AccountId,
2413 f: impl FnOnce(&mut Option<T::AccountData>) -> Result<R, E>,
2414 ) -> Result<R, E> {
2415 let account = Account::<T>::get(k);
2416 let is_default = account.data == T::AccountData::default();
2417 let mut some_data = if is_default { None } else { Some(account.data) };
2418 let result = f(&mut some_data)?;
2419 if Self::providers(k) > 0 || Self::sufficients(k) > 0 {
2420 Account::<T>::mutate(k, |a| a.data = some_data.unwrap_or_default());
2421 } else {
2422 Account::<T>::remove(k)
2423 }
2424 Ok(result)
2425 }
2426}
2427
2428pub fn split_inner<T, R, S>(
2430 option: Option<T>,
2431 splitter: impl FnOnce(T) -> (R, S),
2432) -> (Option<R>, Option<S>) {
2433 match option {
2434 Some(inner) => {
2435 let (r, s) = splitter(inner);
2436 (Some(r), Some(s))
2437 },
2438 None => (None, None),
2439 }
2440}
2441
2442pub struct ChainContext<T>(PhantomData<T>);
2443impl<T> Default for ChainContext<T> {
2444 fn default() -> Self {
2445 ChainContext(PhantomData)
2446 }
2447}
2448
2449impl<T: Config> Lookup for ChainContext<T> {
2450 type Source = <T::Lookup as StaticLookup>::Source;
2451 type Target = <T::Lookup as StaticLookup>::Target;
2452
2453 fn lookup(&self, s: Self::Source) -> Result<Self::Target, LookupError> {
2454 <T::Lookup as StaticLookup>::lookup(s)
2455 }
2456}
2457
2458#[cfg(any(feature = "std", feature = "runtime-benchmarks", test))]
2460pub struct RunToBlockHooks<'a, T>
2461where
2462 T: 'a + Config,
2463{
2464 before_initialize: Box<dyn 'a + FnMut(BlockNumberFor<T>)>,
2465 after_initialize: Box<dyn 'a + FnMut(BlockNumberFor<T>)>,
2466 before_finalize: Box<dyn 'a + FnMut(BlockNumberFor<T>)>,
2467 after_finalize: Box<dyn 'a + FnMut(BlockNumberFor<T>)>,
2468}
2469
2470#[cfg(any(feature = "std", feature = "runtime-benchmarks", test))]
2471impl<'a, T> RunToBlockHooks<'a, T>
2472where
2473 T: 'a + Config,
2474{
2475 pub fn before_initialize<F>(mut self, f: F) -> Self
2477 where
2478 F: 'a + FnMut(BlockNumberFor<T>),
2479 {
2480 self.before_initialize = Box::new(f);
2481 self
2482 }
2483 pub fn after_initialize<F>(mut self, f: F) -> Self
2485 where
2486 F: 'a + FnMut(BlockNumberFor<T>),
2487 {
2488 self.after_initialize = Box::new(f);
2489 self
2490 }
2491 pub fn before_finalize<F>(mut self, f: F) -> Self
2493 where
2494 F: 'a + FnMut(BlockNumberFor<T>),
2495 {
2496 self.before_finalize = Box::new(f);
2497 self
2498 }
2499 pub fn after_finalize<F>(mut self, f: F) -> Self
2501 where
2502 F: 'a + FnMut(BlockNumberFor<T>),
2503 {
2504 self.after_finalize = Box::new(f);
2505 self
2506 }
2507}
2508
2509#[cfg(any(feature = "std", feature = "runtime-benchmarks", test))]
2510impl<'a, T> Default for RunToBlockHooks<'a, T>
2511where
2512 T: Config,
2513{
2514 fn default() -> Self {
2515 Self {
2516 before_initialize: Box::new(|_| {}),
2517 after_initialize: Box::new(|_| {}),
2518 before_finalize: Box::new(|_| {}),
2519 after_finalize: Box::new(|_| {}),
2520 }
2521 }
2522}
2523
2524pub mod pallet_prelude {
2526 pub use crate::{ensure_none, ensure_root, ensure_signed, ensure_signed_or_root};
2527
2528 pub type OriginFor<T> = <T as crate::Config>::RuntimeOrigin;
2530
2531 pub type HeaderFor<T> =
2533 <<T as crate::Config>::Block as sp_runtime::traits::HeaderProvider>::HeaderT;
2534
2535 pub type BlockNumberFor<T> = <HeaderFor<T> as sp_runtime::traits::Header>::Number;
2537
2538 pub type ExtrinsicFor<T> =
2540 <<T as crate::Config>::Block as sp_runtime::traits::Block>::Extrinsic;
2541
2542 pub type RuntimeCallFor<T> = <T as crate::Config>::RuntimeCall;
2544}