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