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