1pub mod benchmarking;
27pub mod migration;
28
29use crate::{
30 slots::{self, Pallet as Slots, WeightInfo as SlotsWeightInfo},
31 traits::{LeaseError, Leaser, Registrar},
32};
33use alloc::vec::Vec;
34use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
35use frame_support::{pallet_prelude::*, traits::Currency};
36use frame_system::pallet_prelude::*;
37pub use pallet::*;
38use polkadot_primitives::Id as ParaId;
39use polkadot_runtime_parachains::{
40 configuration,
41 paras::{self},
42};
43use scale_info::TypeInfo;
44use sp_runtime::traits::{One, Saturating, Zero};
45
46const LOG_TARGET: &str = "runtime::assigned_slots";
47
48#[derive(
50 Encode, Decode, DecodeWithMemTracking, Clone, Copy, Eq, PartialEq, RuntimeDebug, TypeInfo,
51)]
52pub enum SlotLeasePeriodStart {
53 Current,
54 Next,
55}
56
57#[derive(Encode, Decode, Clone, PartialEq, Eq, Default, MaxEncodedLen, RuntimeDebug, TypeInfo)]
59pub struct ParachainTemporarySlot<AccountId, LeasePeriod> {
60 pub manager: AccountId,
62 pub period_begin: LeasePeriod,
66 pub period_count: LeasePeriod,
69 pub last_lease: Option<LeasePeriod>,
72 pub lease_count: u32,
74}
75
76pub trait WeightInfo {
77 fn assign_perm_parachain_slot() -> Weight;
78 fn assign_temp_parachain_slot() -> Weight;
79 fn unassign_parachain_slot() -> Weight;
80 fn set_max_permanent_slots() -> Weight;
81 fn set_max_temporary_slots() -> Weight;
82}
83
84pub struct TestWeightInfo;
85impl WeightInfo for TestWeightInfo {
86 fn assign_perm_parachain_slot() -> Weight {
87 Weight::zero()
88 }
89 fn assign_temp_parachain_slot() -> Weight {
90 Weight::zero()
91 }
92 fn unassign_parachain_slot() -> Weight {
93 Weight::zero()
94 }
95 fn set_max_permanent_slots() -> Weight {
96 Weight::zero()
97 }
98 fn set_max_temporary_slots() -> Weight {
99 Weight::zero()
100 }
101}
102
103type BalanceOf<T> = <<<T as Config>::Leaser as Leaser<BlockNumberFor<T>>>::Currency as Currency<
104 <T as frame_system::Config>::AccountId,
105>>::Balance;
106type LeasePeriodOf<T> = <<T as Config>::Leaser as Leaser<BlockNumberFor<T>>>::LeasePeriod;
107
108#[frame_support::pallet]
109pub mod pallet {
110 use super::*;
111
112 const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
114
115 #[pallet::pallet]
116 #[pallet::storage_version(STORAGE_VERSION)]
117 pub struct Pallet<T>(_);
118
119 #[pallet::config]
120 #[pallet::disable_frame_system_supertrait_check]
121 pub trait Config: configuration::Config + paras::Config + slots::Config {
122 type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
124
125 type AssignSlotOrigin: EnsureOrigin<<Self as frame_system::Config>::RuntimeOrigin>;
127
128 type Leaser: Leaser<
130 BlockNumberFor<Self>,
131 AccountId = Self::AccountId,
132 LeasePeriod = BlockNumberFor<Self>,
133 >;
134
135 #[pallet::constant]
137 type PermanentSlotLeasePeriodLength: Get<u32>;
138
139 #[pallet::constant]
141 type TemporarySlotLeasePeriodLength: Get<u32>;
142
143 #[pallet::constant]
145 type MaxTemporarySlotPerLeasePeriod: Get<u32>;
146
147 type WeightInfo: WeightInfo;
149 }
150
151 #[pallet::storage]
153 pub type PermanentSlots<T: Config> =
154 StorageMap<_, Twox64Concat, ParaId, (LeasePeriodOf<T>, LeasePeriodOf<T>), OptionQuery>;
155
156 #[pallet::storage]
158 pub type PermanentSlotCount<T: Config> = StorageValue<_, u32, ValueQuery>;
159
160 #[pallet::storage]
162 pub type TemporarySlots<T: Config> = StorageMap<
163 _,
164 Twox64Concat,
165 ParaId,
166 ParachainTemporarySlot<T::AccountId, LeasePeriodOf<T>>,
167 OptionQuery,
168 >;
169
170 #[pallet::storage]
172 pub type TemporarySlotCount<T: Config> = StorageValue<_, u32, ValueQuery>;
173
174 #[pallet::storage]
176 pub type ActiveTemporarySlotCount<T: Config> = StorageValue<_, u32, ValueQuery>;
177
178 #[pallet::storage]
180 pub type MaxTemporarySlots<T: Config> = StorageValue<_, u32, ValueQuery>;
181
182 #[pallet::storage]
184 pub type MaxPermanentSlots<T: Config> = StorageValue<_, u32, ValueQuery>;
185
186 #[pallet::genesis_config]
187 #[derive(frame_support::DefaultNoBound)]
188 pub struct GenesisConfig<T: Config> {
189 pub max_temporary_slots: u32,
190 pub max_permanent_slots: u32,
191 #[serde(skip)]
192 pub _config: PhantomData<T>,
193 }
194
195 #[pallet::genesis_build]
196 impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
197 fn build(&self) {
198 MaxPermanentSlots::<T>::put(&self.max_permanent_slots);
199 MaxTemporarySlots::<T>::put(&self.max_temporary_slots);
200 }
201 }
202
203 #[pallet::event]
204 #[pallet::generate_deposit(pub(super) fn deposit_event)]
205 pub enum Event<T: Config> {
206 PermanentSlotAssigned(ParaId),
208 TemporarySlotAssigned(ParaId),
210 MaxPermanentSlotsChanged { slots: u32 },
212 MaxTemporarySlotsChanged { slots: u32 },
214 }
215
216 #[pallet::error]
217 pub enum Error<T> {
218 ParaDoesntExist,
220 NotParathread,
222 CannotUpgrade,
225 CannotDowngrade,
228 SlotAlreadyAssigned,
230 SlotNotAssigned,
232 OngoingLeaseExists,
234 MaxPermanentSlotsExceeded,
236 MaxTemporarySlotsExceeded,
238 }
239
240 #[pallet::hooks]
241 impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
242 fn on_initialize(n: BlockNumberFor<T>) -> Weight {
243 if let Some((lease_period, first_block)) = Self::lease_period_index(n) {
244 if first_block {
246 return Self::manage_lease_period_start(lease_period)
247 }
248 }
249
250 Weight::zero()
252 }
253 }
254
255 #[pallet::call]
256 impl<T: Config> Pallet<T> {
257 #[pallet::call_index(0)]
259 #[pallet::weight((<T as Config>::WeightInfo::assign_perm_parachain_slot(), DispatchClass::Operational))]
260 pub fn assign_perm_parachain_slot(origin: OriginFor<T>, id: ParaId) -> DispatchResult {
261 T::AssignSlotOrigin::ensure_origin(origin)?;
262
263 let manager = T::Registrar::manager_of(id).ok_or(Error::<T>::ParaDoesntExist)?;
264
265 ensure!(T::Registrar::is_parathread(id), Error::<T>::NotParathread);
266
267 ensure!(
268 !Self::has_permanent_slot(id) && !Self::has_temporary_slot(id),
269 Error::<T>::SlotAlreadyAssigned
270 );
271
272 let current_lease_period: BlockNumberFor<T> = Self::current_lease_period_index();
273 ensure!(
274 !T::Leaser::already_leased(
275 id,
276 current_lease_period,
277 current_lease_period.saturating_add(
279 BlockNumberFor::<T>::from(2u32)
280 .saturating_mul(T::PermanentSlotLeasePeriodLength::get().into())
281 )
282 ),
283 Error::<T>::OngoingLeaseExists
284 );
285
286 ensure!(
287 PermanentSlotCount::<T>::get() < MaxPermanentSlots::<T>::get(),
288 Error::<T>::MaxPermanentSlotsExceeded
289 );
290
291 Self::configure_slot_lease(
293 id,
294 manager,
295 current_lease_period,
296 T::PermanentSlotLeasePeriodLength::get().into(),
297 )
298 .map_err(|_| Error::<T>::CannotUpgrade)?;
299
300 PermanentSlots::<T>::insert(
301 id,
302 (
303 current_lease_period,
304 LeasePeriodOf::<T>::from(T::PermanentSlotLeasePeriodLength::get()),
305 ),
306 );
307 PermanentSlotCount::<T>::mutate(|count| count.saturating_inc());
308
309 Self::deposit_event(Event::<T>::PermanentSlotAssigned(id));
310 Ok(())
311 }
312
313 #[pallet::call_index(1)]
317 #[pallet::weight((<T as Config>::WeightInfo::assign_temp_parachain_slot(), DispatchClass::Operational))]
318 pub fn assign_temp_parachain_slot(
319 origin: OriginFor<T>,
320 id: ParaId,
321 lease_period_start: SlotLeasePeriodStart,
322 ) -> DispatchResult {
323 T::AssignSlotOrigin::ensure_origin(origin)?;
324
325 let manager = T::Registrar::manager_of(id).ok_or(Error::<T>::ParaDoesntExist)?;
326
327 ensure!(T::Registrar::is_parathread(id), Error::<T>::NotParathread);
328
329 ensure!(
330 !Self::has_permanent_slot(id) && !Self::has_temporary_slot(id),
331 Error::<T>::SlotAlreadyAssigned
332 );
333
334 let current_lease_period: BlockNumberFor<T> = Self::current_lease_period_index();
335 ensure!(
336 !T::Leaser::already_leased(
337 id,
338 current_lease_period,
339 current_lease_period.saturating_add(
341 BlockNumberFor::<T>::from(2u32)
342 .saturating_mul(T::TemporarySlotLeasePeriodLength::get().into())
343 )
344 ),
345 Error::<T>::OngoingLeaseExists
346 );
347
348 ensure!(
349 TemporarySlotCount::<T>::get() < MaxTemporarySlots::<T>::get(),
350 Error::<T>::MaxTemporarySlotsExceeded
351 );
352
353 let mut temp_slot = ParachainTemporarySlot {
354 manager: manager.clone(),
355 period_begin: match lease_period_start {
356 SlotLeasePeriodStart::Current => current_lease_period,
357 SlotLeasePeriodStart::Next => current_lease_period + One::one(),
358 },
359 period_count: T::TemporarySlotLeasePeriodLength::get().into(),
360 last_lease: None,
361 lease_count: 0,
362 };
363
364 if lease_period_start == SlotLeasePeriodStart::Current &&
365 ActiveTemporarySlotCount::<T>::get() < T::MaxTemporarySlotPerLeasePeriod::get()
366 {
367 match Self::configure_slot_lease(
369 id,
370 manager,
371 temp_slot.period_begin,
372 temp_slot.period_count,
373 ) {
374 Ok(_) => {
375 ActiveTemporarySlotCount::<T>::mutate(|count| count.saturating_inc());
376 temp_slot.last_lease = Some(temp_slot.period_begin);
377 temp_slot.lease_count += 1;
378 },
379 Err(err) => {
380 log::warn!(
384 target: LOG_TARGET,
385 "Failed to allocate a temp slot for para {:?} at period {:?}: {:?}",
386 id,
387 current_lease_period,
388 err
389 );
390 },
391 }
392 }
393
394 TemporarySlots::<T>::insert(id, temp_slot);
395 TemporarySlotCount::<T>::mutate(|count| count.saturating_inc());
396
397 Self::deposit_event(Event::<T>::TemporarySlotAssigned(id));
398
399 Ok(())
400 }
401
402 #[pallet::call_index(2)]
404 #[pallet::weight((<T as Config>::WeightInfo::unassign_parachain_slot(), DispatchClass::Operational))]
405 pub fn unassign_parachain_slot(origin: OriginFor<T>, id: ParaId) -> DispatchResult {
406 T::AssignSlotOrigin::ensure_origin(origin.clone())?;
407
408 ensure!(
409 Self::has_permanent_slot(id) || Self::has_temporary_slot(id),
410 Error::<T>::SlotNotAssigned
411 );
412
413 let is_parachain = Self::is_parachain(id);
415
416 Self::clear_slot_leases(origin.clone(), id)?;
418
419 if PermanentSlots::<T>::contains_key(id) {
420 PermanentSlots::<T>::remove(id);
421 PermanentSlotCount::<T>::mutate(|count| *count = count.saturating_sub(One::one()));
422 } else if TemporarySlots::<T>::contains_key(id) {
423 TemporarySlots::<T>::remove(id);
424 TemporarySlotCount::<T>::mutate(|count| *count = count.saturating_sub(One::one()));
425 if is_parachain {
426 ActiveTemporarySlotCount::<T>::mutate(|active_count| {
427 *active_count = active_count.saturating_sub(One::one())
428 });
429 }
430 }
431
432 if is_parachain {
434 if let Err(err) = polkadot_runtime_parachains::schedule_parachain_downgrade::<T>(id)
435 {
436 log::warn!(
440 target: LOG_TARGET,
441 "Failed to downgrade parachain {:?} at period {:?}: {:?}",
442 id,
443 Self::current_lease_period_index(),
444 err
445 );
446 }
447 }
448
449 Ok(())
450 }
451
452 #[pallet::call_index(3)]
454 #[pallet::weight((<T as Config>::WeightInfo::set_max_permanent_slots(), DispatchClass::Operational))]
455 pub fn set_max_permanent_slots(origin: OriginFor<T>, slots: u32) -> DispatchResult {
456 ensure_root(origin)?;
457
458 MaxPermanentSlots::<T>::put(slots);
459
460 Self::deposit_event(Event::<T>::MaxPermanentSlotsChanged { slots });
461 Ok(())
462 }
463
464 #[pallet::call_index(4)]
466 #[pallet::weight((<T as Config>::WeightInfo::set_max_temporary_slots(), DispatchClass::Operational))]
467 pub fn set_max_temporary_slots(origin: OriginFor<T>, slots: u32) -> DispatchResult {
468 ensure_root(origin)?;
469
470 MaxTemporarySlots::<T>::put(slots);
471
472 Self::deposit_event(Event::<T>::MaxTemporarySlotsChanged { slots });
473 Ok(())
474 }
475 }
476}
477
478impl<T: Config> Pallet<T> {
479 fn allocate_temporary_slot_leases(lease_period_index: LeasePeriodOf<T>) -> DispatchResult {
493 let mut active_temp_slots = 0u32;
494 let mut pending_temp_slots = Vec::new();
495 TemporarySlots::<T>::iter().for_each(|(para, slot)| {
496 match slot.last_lease {
497 Some(last_lease)
498 if last_lease <= lease_period_index &&
499 lease_period_index <
500 (last_lease.saturating_add(slot.period_count)) =>
501 {
502 active_temp_slots += 1;
504 }
505 Some(last_lease)
506 if last_lease.saturating_add(slot.period_count.saturating_mul(2u32.into())) <= lease_period_index => {
508 pending_temp_slots.push((para, slot));
509 },
510 None if slot.period_begin <= lease_period_index => {
511 pending_temp_slots.insert(0, (para, slot));
513 },
514 _ => {
515 },
517 }
518 });
519
520 let mut newly_created_lease = 0u32;
521 if active_temp_slots < T::MaxTemporarySlotPerLeasePeriod::get() &&
522 !pending_temp_slots.is_empty()
523 {
524 pending_temp_slots.sort_by(|a, b| {
527 a.1.lease_count
528 .cmp(&b.1.lease_count)
529 .then_with(|| a.1.last_lease.cmp(&b.1.last_lease))
530 .then_with(|| a.0.cmp(&b.0))
531 });
532
533 let slots_to_be_upgraded = pending_temp_slots.iter().take(
534 (T::MaxTemporarySlotPerLeasePeriod::get().saturating_sub(active_temp_slots))
535 as usize,
536 );
537
538 for (id, temp_slot) in slots_to_be_upgraded {
539 TemporarySlots::<T>::try_mutate::<_, _, Error<T>, _>(id, |s| {
540 Self::configure_slot_lease(
542 *id,
543 temp_slot.manager.clone(),
544 lease_period_index,
545 temp_slot.period_count,
546 )
547 .map_err(|_| Error::<T>::CannotUpgrade)?;
548
549 *s = Some(ParachainTemporarySlot {
551 manager: temp_slot.manager.clone(),
552 period_begin: temp_slot.period_begin,
553 period_count: temp_slot.period_count,
554 last_lease: Some(lease_period_index),
555 lease_count: temp_slot.lease_count + 1,
556 });
557
558 newly_created_lease += 1;
559
560 Ok(())
561 })?;
562 }
563 }
564
565 ActiveTemporarySlotCount::<T>::set(active_temp_slots + newly_created_lease);
566
567 Ok(())
568 }
569
570 fn clear_slot_leases(origin: OriginFor<T>, id: ParaId) -> DispatchResult {
573 Slots::<T>::clear_all_leases(origin, id)
574 }
575
576 fn configure_slot_lease(
579 para: ParaId,
580 manager: T::AccountId,
581 lease_period: LeasePeriodOf<T>,
582 lease_duration: LeasePeriodOf<T>,
583 ) -> Result<(), LeaseError> {
584 T::Leaser::lease_out(para, &manager, BalanceOf::<T>::zero(), lease_period, lease_duration)
585 }
586
587 fn has_permanent_slot(id: ParaId) -> bool {
589 PermanentSlots::<T>::contains_key(id)
590 }
591
592 fn has_temporary_slot(id: ParaId) -> bool {
594 TemporarySlots::<T>::contains_key(id)
595 }
596
597 fn is_parachain(id: ParaId) -> bool {
599 T::Registrar::is_parachain(id)
600 }
601
602 fn current_lease_period_index() -> LeasePeriodOf<T> {
604 T::Leaser::lease_period_index(frame_system::Pallet::<T>::block_number())
605 .and_then(|x| Some(x.0))
606 .unwrap()
607 }
608
609 fn lease_period_index(block: BlockNumberFor<T>) -> Option<(LeasePeriodOf<T>, bool)> {
611 T::Leaser::lease_period_index(block)
612 }
613
614 fn manage_lease_period_start(lease_period_index: LeasePeriodOf<T>) -> Weight {
616 if let Err(err) = Self::allocate_temporary_slot_leases(lease_period_index) {
619 log::error!(
620 target: LOG_TARGET,
621 "Allocating slots failed for lease period {:?}, with: {:?}",
622 lease_period_index,
623 err
624 );
625 }
626 <T as slots::Config>::WeightInfo::force_lease() *
627 (T::MaxTemporarySlotPerLeasePeriod::get() as u64)
628 }
629}
630
631#[cfg(test)]
633mod tests {
634 use super::*;
635
636 use crate::{assigned_slots, mock::TestRegistrar, slots};
637 use frame_support::{assert_noop, assert_ok, derive_impl, parameter_types};
638 use frame_system::EnsureRoot;
639 use pallet_balances;
640 use polkadot_primitives::BlockNumber;
641 use polkadot_primitives_test_helpers::{dummy_head_data, dummy_validation_code};
642 use polkadot_runtime_parachains::{
643 configuration as parachains_configuration, paras as parachains_paras,
644 shared as parachains_shared,
645 };
646 use sp_core::H256;
647 use sp_runtime::{
648 traits::{BlakeTwo256, IdentityLookup},
649 transaction_validity::TransactionPriority,
650 BuildStorage,
651 DispatchError::BadOrigin,
652 };
653
654 type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
655 type Block = frame_system::mocking::MockBlockU32<Test>;
656
657 frame_support::construct_runtime!(
658 pub enum Test
659 {
660 System: frame_system,
661 Balances: pallet_balances,
662 Configuration: parachains_configuration,
663 ParasShared: parachains_shared,
664 Parachains: parachains_paras,
665 Slots: slots,
666 AssignedSlots: assigned_slots,
667 }
668 );
669
670 impl<C> frame_system::offchain::CreateTransactionBase<C> for Test
671 where
672 RuntimeCall: From<C>,
673 {
674 type Extrinsic = UncheckedExtrinsic;
675 type RuntimeCall = RuntimeCall;
676 }
677
678 impl<C> frame_system::offchain::CreateInherent<C> for Test
679 where
680 RuntimeCall: From<C>,
681 {
682 fn create_inherent(call: Self::RuntimeCall) -> Self::Extrinsic {
683 UncheckedExtrinsic::new_bare(call)
684 }
685 }
686
687 #[derive_impl(frame_system::config_preludes::TestDefaultConfig)]
688 impl frame_system::Config for Test {
689 type BaseCallFilter = frame_support::traits::Everything;
690 type BlockWeights = ();
691 type BlockLength = ();
692 type RuntimeOrigin = RuntimeOrigin;
693 type RuntimeCall = RuntimeCall;
694 type Nonce = u64;
695 type Hash = H256;
696 type Hashing = BlakeTwo256;
697 type AccountId = u64;
698 type Lookup = IdentityLookup<Self::AccountId>;
699 type Block = Block;
700 type RuntimeEvent = RuntimeEvent;
701 type DbWeight = ();
702 type Version = ();
703 type PalletInfo = PalletInfo;
704 type AccountData = pallet_balances::AccountData<u64>;
705 type OnNewAccount = ();
706 type OnKilledAccount = ();
707 type SystemWeightInfo = ();
708 type SS58Prefix = ();
709 type OnSetCode = ();
710 type MaxConsumers = frame_support::traits::ConstU32<16>;
711 }
712
713 #[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)]
714 impl pallet_balances::Config for Test {
715 type AccountStore = System;
716 }
717
718 impl parachains_configuration::Config for Test {
719 type WeightInfo = parachains_configuration::TestWeightInfo;
720 }
721
722 parameter_types! {
723 pub const ParasUnsignedPriority: TransactionPriority = TransactionPriority::max_value();
724 }
725
726 impl parachains_paras::Config for Test {
727 type RuntimeEvent = RuntimeEvent;
728 type WeightInfo = parachains_paras::TestWeightInfo;
729 type UnsignedPriority = ParasUnsignedPriority;
730 type QueueFootprinter = ();
731 type NextSessionRotation = crate::mock::TestNextSessionRotation;
732 type OnNewHead = ();
733 type AssignCoretime = ();
734 }
735
736 impl parachains_shared::Config for Test {
737 type DisabledValidators = ();
738 }
739
740 parameter_types! {
741 pub const LeasePeriod: BlockNumber = 3;
742 pub static LeaseOffset: BlockNumber = 0;
743 pub const ParaDeposit: u64 = 1;
744 }
745
746 impl slots::Config for Test {
747 type RuntimeEvent = RuntimeEvent;
748 type Currency = Balances;
749 type Registrar = TestRegistrar<Test>;
750 type LeasePeriod = LeasePeriod;
751 type LeaseOffset = LeaseOffset;
752 type ForceOrigin = EnsureRoot<Self::AccountId>;
753 type WeightInfo = crate::slots::TestWeightInfo;
754 }
755
756 parameter_types! {
757 pub const PermanentSlotLeasePeriodLength: u32 = 3;
758 pub const TemporarySlotLeasePeriodLength: u32 = 2;
759 pub const MaxTemporarySlotPerLeasePeriod: u32 = 2;
760 }
761
762 impl assigned_slots::Config for Test {
763 type RuntimeEvent = RuntimeEvent;
764 type AssignSlotOrigin = EnsureRoot<Self::AccountId>;
765 type Leaser = Slots;
766 type PermanentSlotLeasePeriodLength = PermanentSlotLeasePeriodLength;
767 type TemporarySlotLeasePeriodLength = TemporarySlotLeasePeriodLength;
768 type MaxTemporarySlotPerLeasePeriod = MaxTemporarySlotPerLeasePeriod;
769 type WeightInfo = crate::assigned_slots::TestWeightInfo;
770 }
771
772 pub fn new_test_ext() -> sp_io::TestExternalities {
775 let mut t = frame_system::GenesisConfig::<Test>::default().build_storage().unwrap();
776 pallet_balances::GenesisConfig::<Test> {
777 balances: vec![(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)],
778 ..Default::default()
779 }
780 .assimilate_storage(&mut t)
781 .unwrap();
782
783 crate::assigned_slots::GenesisConfig::<Test> {
784 max_temporary_slots: 6,
785 max_permanent_slots: 2,
786 _config: Default::default(),
787 }
788 .assimilate_storage(&mut t)
789 .unwrap();
790
791 t.into()
792 }
793
794 #[test]
795 fn basic_setup_works() {
796 new_test_ext().execute_with(|| {
797 System::run_to_block::<AllPalletsWithSystem>(1);
798 assert_eq!(AssignedSlots::current_lease_period_index(), 0);
799 assert_eq!(Slots::deposit_held(1.into(), &1), 0);
800
801 System::run_to_block::<AllPalletsWithSystem>(3);
802 assert_eq!(AssignedSlots::current_lease_period_index(), 1);
803 });
804 }
805
806 #[test]
807 fn assign_perm_slot_fails_for_unknown_para() {
808 new_test_ext().execute_with(|| {
809 System::run_to_block::<AllPalletsWithSystem>(1);
810
811 assert_noop!(
812 AssignedSlots::assign_perm_parachain_slot(
813 RuntimeOrigin::root(),
814 ParaId::from(1_u32),
815 ),
816 Error::<Test>::ParaDoesntExist
817 );
818 });
819 }
820
821 #[test]
822 fn assign_perm_slot_fails_for_invalid_origin() {
823 new_test_ext().execute_with(|| {
824 System::run_to_block::<AllPalletsWithSystem>(1);
825
826 assert_noop!(
827 AssignedSlots::assign_perm_parachain_slot(
828 RuntimeOrigin::signed(1),
829 ParaId::from(1_u32),
830 ),
831 BadOrigin
832 );
833 });
834 }
835
836 #[test]
837 fn assign_perm_slot_fails_when_not_parathread() {
838 new_test_ext().execute_with(|| {
839 System::run_to_block::<AllPalletsWithSystem>(1);
840
841 assert_ok!(TestRegistrar::<Test>::register(
842 1,
843 ParaId::from(1_u32),
844 dummy_head_data(),
845 dummy_validation_code(),
846 ));
847 assert_ok!(TestRegistrar::<Test>::make_parachain(ParaId::from(1_u32)));
848
849 assert_noop!(
850 AssignedSlots::assign_perm_parachain_slot(
851 RuntimeOrigin::root(),
852 ParaId::from(1_u32),
853 ),
854 Error::<Test>::NotParathread
855 );
856 });
857 }
858
859 #[test]
860 fn assign_perm_slot_fails_when_existing_lease() {
861 new_test_ext().execute_with(|| {
862 System::run_to_block::<AllPalletsWithSystem>(1);
863
864 assert_ok!(TestRegistrar::<Test>::register(
865 1,
866 ParaId::from(1_u32),
867 dummy_head_data(),
868 dummy_validation_code(),
869 ));
870
871 assert_ok!(Slots::lease_out(ParaId::from(1_u32), &1, 1, 1, 1));
873 assert_noop!(
875 AssignedSlots::assign_perm_parachain_slot(
876 RuntimeOrigin::root(),
877 ParaId::from(1_u32),
878 ),
879 Error::<Test>::OngoingLeaseExists
880 );
881
882 assert_ok!(Slots::clear_all_leases(RuntimeOrigin::root(), 1.into()));
884
885 assert_ok!(Slots::lease_out(ParaId::from(1_u32), &1, 1, 2, 1));
887 assert_noop!(
889 AssignedSlots::assign_perm_parachain_slot(
890 RuntimeOrigin::root(),
891 ParaId::from(1_u32),
892 ),
893 Error::<Test>::OngoingLeaseExists
894 );
895 });
896 }
897
898 #[test]
899 fn assign_perm_slot_fails_when_max_perm_slots_exceeded() {
900 new_test_ext().execute_with(|| {
901 System::run_to_block::<AllPalletsWithSystem>(1);
902
903 assert_ok!(TestRegistrar::<Test>::register(
904 1,
905 ParaId::from(1_u32),
906 dummy_head_data(),
907 dummy_validation_code(),
908 ));
909
910 assert_ok!(TestRegistrar::<Test>::register(
911 2,
912 ParaId::from(2_u32),
913 dummy_head_data(),
914 dummy_validation_code(),
915 ));
916
917 assert_ok!(TestRegistrar::<Test>::register(
918 3,
919 ParaId::from(3_u32),
920 dummy_head_data(),
921 dummy_validation_code(),
922 ));
923
924 assert_ok!(AssignedSlots::assign_perm_parachain_slot(
925 RuntimeOrigin::root(),
926 ParaId::from(1_u32),
927 ));
928 assert_ok!(AssignedSlots::assign_perm_parachain_slot(
929 RuntimeOrigin::root(),
930 ParaId::from(2_u32),
931 ));
932 assert_eq!(assigned_slots::PermanentSlotCount::<Test>::get(), 2);
933
934 assert_noop!(
935 AssignedSlots::assign_perm_parachain_slot(
936 RuntimeOrigin::root(),
937 ParaId::from(3_u32),
938 ),
939 Error::<Test>::MaxPermanentSlotsExceeded
940 );
941 });
942 }
943
944 #[test]
945 fn assign_perm_slot_succeeds_for_parathread() {
946 new_test_ext().execute_with(|| {
947 let mut block = 1;
948 System::run_to_block::<AllPalletsWithSystem>(block);
949 assert_ok!(TestRegistrar::<Test>::register(
950 1,
951 ParaId::from(1_u32),
952 dummy_head_data(),
953 dummy_validation_code(),
954 ));
955
956 assert_eq!(assigned_slots::PermanentSlotCount::<Test>::get(), 0);
957 assert_eq!(assigned_slots::PermanentSlots::<Test>::get(ParaId::from(1_u32)), None);
958
959 assert_ok!(AssignedSlots::assign_perm_parachain_slot(
960 RuntimeOrigin::root(),
961 ParaId::from(1_u32),
962 ));
963
964 while block < 9 {
967 println!("block #{}", block);
968
969 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(1_u32)), true);
970
971 assert_eq!(assigned_slots::PermanentSlotCount::<Test>::get(), 1);
972 assert_eq!(AssignedSlots::has_permanent_slot(ParaId::from(1_u32)), true);
973 assert_eq!(
974 assigned_slots::PermanentSlots::<Test>::get(ParaId::from(1_u32)),
975 Some((0, 3))
976 );
977
978 assert_eq!(Slots::already_leased(ParaId::from(1_u32), 0, 2), true);
979
980 block += 1;
981 System::run_to_block::<AllPalletsWithSystem>(block);
982 }
983
984 assert_eq!(TestRegistrar::<Test>::is_parathread(ParaId::from(1_u32)), true);
986 assert_eq!(Slots::already_leased(ParaId::from(1_u32), 0, 5), false);
987 });
988 }
989
990 #[test]
991 fn assign_temp_slot_fails_for_unknown_para() {
992 new_test_ext().execute_with(|| {
993 System::run_to_block::<AllPalletsWithSystem>(1);
994
995 assert_noop!(
996 AssignedSlots::assign_temp_parachain_slot(
997 RuntimeOrigin::root(),
998 ParaId::from(1_u32),
999 SlotLeasePeriodStart::Current
1000 ),
1001 Error::<Test>::ParaDoesntExist
1002 );
1003 });
1004 }
1005
1006 #[test]
1007 fn assign_temp_slot_fails_for_invalid_origin() {
1008 new_test_ext().execute_with(|| {
1009 System::run_to_block::<AllPalletsWithSystem>(1);
1010
1011 assert_noop!(
1012 AssignedSlots::assign_temp_parachain_slot(
1013 RuntimeOrigin::signed(1),
1014 ParaId::from(1_u32),
1015 SlotLeasePeriodStart::Current
1016 ),
1017 BadOrigin
1018 );
1019 });
1020 }
1021
1022 #[test]
1023 fn assign_temp_slot_fails_when_not_parathread() {
1024 new_test_ext().execute_with(|| {
1025 System::run_to_block::<AllPalletsWithSystem>(1);
1026
1027 assert_ok!(TestRegistrar::<Test>::register(
1028 1,
1029 ParaId::from(1_u32),
1030 dummy_head_data(),
1031 dummy_validation_code(),
1032 ));
1033 assert_ok!(TestRegistrar::<Test>::make_parachain(ParaId::from(1_u32)));
1034
1035 assert_noop!(
1036 AssignedSlots::assign_temp_parachain_slot(
1037 RuntimeOrigin::root(),
1038 ParaId::from(1_u32),
1039 SlotLeasePeriodStart::Current
1040 ),
1041 Error::<Test>::NotParathread
1042 );
1043 });
1044 }
1045
1046 #[test]
1047 fn assign_temp_slot_fails_when_existing_lease() {
1048 new_test_ext().execute_with(|| {
1049 System::run_to_block::<AllPalletsWithSystem>(1);
1050
1051 assert_ok!(TestRegistrar::<Test>::register(
1052 1,
1053 ParaId::from(1_u32),
1054 dummy_head_data(),
1055 dummy_validation_code(),
1056 ));
1057
1058 assert_ok!(Slots::lease_out(ParaId::from(1_u32), &1, 1, 1, 1));
1060 assert_noop!(
1062 AssignedSlots::assign_temp_parachain_slot(
1063 RuntimeOrigin::root(),
1064 ParaId::from(1_u32),
1065 SlotLeasePeriodStart::Current
1066 ),
1067 Error::<Test>::OngoingLeaseExists
1068 );
1069
1070 assert_ok!(Slots::clear_all_leases(RuntimeOrigin::root(), 1.into()));
1072
1073 assert_ok!(Slots::lease_out(ParaId::from(1_u32), &1, 1, 2, 1));
1075 assert_noop!(
1077 AssignedSlots::assign_temp_parachain_slot(
1078 RuntimeOrigin::root(),
1079 ParaId::from(1_u32),
1080 SlotLeasePeriodStart::Current
1081 ),
1082 Error::<Test>::OngoingLeaseExists
1083 );
1084 });
1085 }
1086
1087 #[test]
1088 fn assign_temp_slot_fails_when_max_temp_slots_exceeded() {
1089 new_test_ext().execute_with(|| {
1090 System::run_to_block::<AllPalletsWithSystem>(1);
1091
1092 for n in 0..=5 {
1094 assert_ok!(TestRegistrar::<Test>::register(
1095 n,
1096 ParaId::from(n as u32),
1097 dummy_head_data(),
1098 dummy_validation_code()
1099 ));
1100
1101 assert_ok!(AssignedSlots::assign_temp_parachain_slot(
1102 RuntimeOrigin::root(),
1103 ParaId::from(n as u32),
1104 SlotLeasePeriodStart::Current
1105 ));
1106 }
1107
1108 assert_eq!(assigned_slots::TemporarySlotCount::<Test>::get(), 6);
1109
1110 assert_ok!(TestRegistrar::<Test>::register(
1112 7,
1113 ParaId::from(7_u32),
1114 dummy_head_data(),
1115 dummy_validation_code(),
1116 ));
1117 assert_noop!(
1118 AssignedSlots::assign_temp_parachain_slot(
1119 RuntimeOrigin::root(),
1120 ParaId::from(7_u32),
1121 SlotLeasePeriodStart::Current
1122 ),
1123 Error::<Test>::MaxTemporarySlotsExceeded
1124 );
1125 });
1126 }
1127
1128 #[test]
1129 fn assign_temp_slot_succeeds_for_single_parathread() {
1130 new_test_ext().execute_with(|| {
1131 let mut block = 1;
1132 System::run_to_block::<AllPalletsWithSystem>(block);
1133 assert_ok!(TestRegistrar::<Test>::register(
1134 1,
1135 ParaId::from(1_u32),
1136 dummy_head_data(),
1137 dummy_validation_code(),
1138 ));
1139
1140 assert_eq!(assigned_slots::TemporarySlots::<Test>::get(ParaId::from(1_u32)), None);
1141
1142 assert_ok!(AssignedSlots::assign_temp_parachain_slot(
1143 RuntimeOrigin::root(),
1144 ParaId::from(1_u32),
1145 SlotLeasePeriodStart::Current
1146 ));
1147 assert_eq!(assigned_slots::TemporarySlotCount::<Test>::get(), 1);
1148 assert_eq!(assigned_slots::ActiveTemporarySlotCount::<Test>::get(), 1);
1149
1150 while block < 6 {
1154 println!("block #{}", block);
1155 println!("lease period #{}", AssignedSlots::current_lease_period_index());
1156 println!("lease {:?}", slots::Leases::<Test>::get(ParaId::from(1_u32)));
1157
1158 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(1_u32)), true);
1159
1160 assert_eq!(AssignedSlots::has_temporary_slot(ParaId::from(1_u32)), true);
1161 assert_eq!(assigned_slots::ActiveTemporarySlotCount::<Test>::get(), 1);
1162 assert_eq!(
1163 assigned_slots::TemporarySlots::<Test>::get(ParaId::from(1_u32)),
1164 Some(ParachainTemporarySlot {
1165 manager: 1,
1166 period_begin: 0,
1167 period_count: 2, last_lease: Some(0),
1169 lease_count: 1
1170 })
1171 );
1172
1173 assert_eq!(Slots::already_leased(ParaId::from(1_u32), 0, 1), true);
1174
1175 block += 1;
1176 System::run_to_block::<AllPalletsWithSystem>(block);
1177 }
1178
1179 println!("block #{}", block);
1181 println!("lease period #{}", AssignedSlots::current_lease_period_index());
1182 println!("lease {:?}", slots::Leases::<Test>::get(ParaId::from(1_u32)));
1183
1184 assert_eq!(TestRegistrar::<Test>::is_parathread(ParaId::from(1_u32)), true);
1186 assert_eq!(Slots::already_leased(ParaId::from(1_u32), 0, 3), false);
1187 assert_eq!(assigned_slots::ActiveTemporarySlotCount::<Test>::get(), 0);
1188
1189 System::run_to_block::<AllPalletsWithSystem>(12);
1192 println!("block #{}", block);
1193 println!("lease period #{}", AssignedSlots::current_lease_period_index());
1194 println!("lease {:?}", slots::Leases::<Test>::get(ParaId::from(1_u32)));
1195
1196 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(1_u32)), true);
1197 assert_eq!(Slots::already_leased(ParaId::from(1_u32), 4, 5), true);
1198 assert_eq!(assigned_slots::ActiveTemporarySlotCount::<Test>::get(), 1);
1199 });
1200 }
1201
1202 #[test]
1203 fn assign_temp_slot_succeeds_for_multiple_parathreads() {
1204 new_test_ext().execute_with(|| {
1205 System::run_to_block::<AllPalletsWithSystem>(1);
1207
1208 for n in 0..=5 {
1211 assert_ok!(TestRegistrar::<Test>::register(
1212 n,
1213 ParaId::from(n as u32),
1214 dummy_head_data(),
1215 dummy_validation_code()
1216 ));
1217
1218 assert_ok!(AssignedSlots::assign_temp_parachain_slot(
1219 RuntimeOrigin::root(),
1220 ParaId::from(n as u32),
1221 if (n % 2).is_zero() {
1222 SlotLeasePeriodStart::Current
1223 } else {
1224 SlotLeasePeriodStart::Next
1225 }
1226 ));
1227 }
1228
1229 for n in 1..=5 {
1231 if n > 1 {
1232 System::run_to_block::<AllPalletsWithSystem>(n);
1233 }
1234 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(0)), true);
1235 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(1_u32)), false);
1236 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(2_u32)), true);
1237 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(3_u32)), false);
1238 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(4_u32)), false);
1239 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(5_u32)), false);
1240 assert_eq!(assigned_slots::ActiveTemporarySlotCount::<Test>::get(), 2);
1241 }
1242
1243 for n in 6..=11 {
1245 System::run_to_block::<AllPalletsWithSystem>(n);
1246 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(0)), false);
1247 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(1_u32)), true);
1248 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(2_u32)), false);
1249 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(3_u32)), true);
1250 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(4_u32)), false);
1251 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(5_u32)), false);
1252 assert_eq!(assigned_slots::ActiveTemporarySlotCount::<Test>::get(), 2);
1253 }
1254
1255 for n in 12..=17 {
1257 System::run_to_block::<AllPalletsWithSystem>(n);
1258 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(0)), false);
1259 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(1_u32)), false);
1260 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(2_u32)), false);
1261 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(3_u32)), false);
1262 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(4_u32)), true);
1263 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(5_u32)), true);
1264 assert_eq!(assigned_slots::ActiveTemporarySlotCount::<Test>::get(), 2);
1265 }
1266
1267 for n in 18..=23 {
1269 System::run_to_block::<AllPalletsWithSystem>(n);
1270 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(0)), true);
1271 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(1_u32)), false);
1272 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(2_u32)), true);
1273 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(3_u32)), false);
1274 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(4_u32)), false);
1275 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(5_u32)), false);
1276 assert_eq!(assigned_slots::ActiveTemporarySlotCount::<Test>::get(), 2);
1277 }
1278
1279 for n in 24..=29 {
1281 System::run_to_block::<AllPalletsWithSystem>(n);
1282 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(0)), false);
1283 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(1_u32)), true);
1284 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(2_u32)), false);
1285 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(3_u32)), true);
1286 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(4_u32)), false);
1287 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(5_u32)), false);
1288 assert_eq!(assigned_slots::ActiveTemporarySlotCount::<Test>::get(), 2);
1289 }
1290
1291 for n in 30..=35 {
1293 System::run_to_block::<AllPalletsWithSystem>(n);
1294 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(0)), false);
1295 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(1_u32)), false);
1296 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(2_u32)), false);
1297 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(3_u32)), false);
1298 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(4_u32)), true);
1299 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(5_u32)), true);
1300 assert_eq!(assigned_slots::ActiveTemporarySlotCount::<Test>::get(), 2);
1301 }
1302 });
1303 }
1304
1305 #[test]
1306 fn unassign_slot_fails_for_unknown_para() {
1307 new_test_ext().execute_with(|| {
1308 System::run_to_block::<AllPalletsWithSystem>(1);
1309
1310 assert_noop!(
1311 AssignedSlots::unassign_parachain_slot(RuntimeOrigin::root(), ParaId::from(1_u32),),
1312 Error::<Test>::SlotNotAssigned
1313 );
1314 });
1315 }
1316
1317 #[test]
1318 fn unassign_slot_fails_for_invalid_origin() {
1319 new_test_ext().execute_with(|| {
1320 System::run_to_block::<AllPalletsWithSystem>(1);
1321
1322 assert_noop!(
1323 AssignedSlots::assign_perm_parachain_slot(
1324 RuntimeOrigin::signed(1),
1325 ParaId::from(1_u32),
1326 ),
1327 BadOrigin
1328 );
1329 });
1330 }
1331
1332 #[test]
1333 fn unassign_perm_slot_succeeds() {
1334 new_test_ext().execute_with(|| {
1335 System::run_to_block::<AllPalletsWithSystem>(1);
1336
1337 assert_ok!(TestRegistrar::<Test>::register(
1338 1,
1339 ParaId::from(1_u32),
1340 dummy_head_data(),
1341 dummy_validation_code(),
1342 ));
1343
1344 assert_ok!(AssignedSlots::assign_perm_parachain_slot(
1345 RuntimeOrigin::root(),
1346 ParaId::from(1_u32),
1347 ));
1348
1349 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(1_u32)), true);
1350
1351 assert_ok!(AssignedSlots::unassign_parachain_slot(
1352 RuntimeOrigin::root(),
1353 ParaId::from(1_u32),
1354 ));
1355
1356 assert_eq!(assigned_slots::PermanentSlotCount::<Test>::get(), 0);
1357 assert_eq!(AssignedSlots::has_permanent_slot(ParaId::from(1_u32)), false);
1358 assert_eq!(assigned_slots::PermanentSlots::<Test>::get(ParaId::from(1_u32)), None);
1359
1360 assert_eq!(Slots::already_leased(ParaId::from(1_u32), 0, 2), false);
1361 });
1362 }
1363
1364 #[test]
1365 fn unassign_temp_slot_succeeds() {
1366 new_test_ext().execute_with(|| {
1367 System::run_to_block::<AllPalletsWithSystem>(1);
1368
1369 assert_ok!(TestRegistrar::<Test>::register(
1370 1,
1371 ParaId::from(1_u32),
1372 dummy_head_data(),
1373 dummy_validation_code(),
1374 ));
1375
1376 assert_ok!(AssignedSlots::assign_temp_parachain_slot(
1377 RuntimeOrigin::root(),
1378 ParaId::from(1_u32),
1379 SlotLeasePeriodStart::Current
1380 ));
1381
1382 assert_eq!(TestRegistrar::<Test>::is_parachain(ParaId::from(1_u32)), true);
1383
1384 assert_ok!(AssignedSlots::unassign_parachain_slot(
1385 RuntimeOrigin::root(),
1386 ParaId::from(1_u32),
1387 ));
1388
1389 assert_eq!(assigned_slots::TemporarySlotCount::<Test>::get(), 0);
1390 assert_eq!(assigned_slots::ActiveTemporarySlotCount::<Test>::get(), 0);
1391 assert_eq!(AssignedSlots::has_temporary_slot(ParaId::from(1_u32)), false);
1392 assert_eq!(assigned_slots::TemporarySlots::<Test>::get(ParaId::from(1_u32)), None);
1393
1394 assert_eq!(Slots::already_leased(ParaId::from(1_u32), 0, 1), false);
1395 });
1396 }
1397 #[test]
1398 fn set_max_permanent_slots_fails_for_no_root_origin() {
1399 new_test_ext().execute_with(|| {
1400 System::run_to_block::<AllPalletsWithSystem>(1);
1401
1402 assert_noop!(
1403 AssignedSlots::set_max_permanent_slots(RuntimeOrigin::signed(1), 5),
1404 BadOrigin
1405 );
1406 });
1407 }
1408 #[test]
1409 fn set_max_permanent_slots_succeeds() {
1410 new_test_ext().execute_with(|| {
1411 System::run_to_block::<AllPalletsWithSystem>(1);
1412
1413 assert_eq!(MaxPermanentSlots::<Test>::get(), 2);
1414 assert_ok!(AssignedSlots::set_max_permanent_slots(RuntimeOrigin::root(), 10),);
1415 assert_eq!(MaxPermanentSlots::<Test>::get(), 10);
1416 });
1417 }
1418
1419 #[test]
1420 fn set_max_temporary_slots_fails_for_no_root_origin() {
1421 new_test_ext().execute_with(|| {
1422 System::run_to_block::<AllPalletsWithSystem>(1);
1423
1424 assert_noop!(
1425 AssignedSlots::set_max_temporary_slots(RuntimeOrigin::signed(1), 5),
1426 BadOrigin
1427 );
1428 });
1429 }
1430 #[test]
1431 fn set_max_temporary_slots_succeeds() {
1432 new_test_ext().execute_with(|| {
1433 System::run_to_block::<AllPalletsWithSystem>(1);
1434
1435 assert_eq!(MaxTemporarySlots::<Test>::get(), 6);
1436 assert_ok!(AssignedSlots::set_max_temporary_slots(RuntimeOrigin::root(), 12),);
1437 assert_eq!(MaxTemporarySlots::<Test>::get(), 12);
1438 });
1439 }
1440}