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