--- a/Cargo.lock +++ b/Cargo.lock @@ -5850,34 +5850,34 @@ [[package]] name = "pallet-scheduler" version = "3.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc" dependencies = [ "frame-benchmarking", "frame-support", "frame-system", "log", "parity-scale-codec 2.1.3", - "serde", - "sp-core", "sp-io", "sp-runtime", "sp-std", - "substrate-test-utils", - "up-sponsorship", ] [[package]] name = "pallet-scheduler" version = "3.0.0" -source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc" dependencies = [ "frame-benchmarking", "frame-support", "frame-system", "log", "parity-scale-codec 2.1.3", + "serde", + "sp-core", "sp-io", "sp-runtime", "sp-std", + "substrate-test-utils", + "up-sponsorship", ] [[package]] --- a/node/cli/src/chain_spec.rs +++ b/node/cli/src/chain_spec.rs @@ -196,6 +196,7 @@ const_on_chain_schema: vec![], variable_on_chain_schema: vec![], limits: CollectionLimits::default(), + transfers_enabled: true, }, )], nft_item_id: vec![], --- a/pallets/inflation/src/tests.rs +++ b/pallets/inflation/src/tests.rs @@ -31,6 +31,8 @@ type ExistentialDeposit = ExistentialDeposit; type WeightInfo = (); type MaxLocks = MaxLocks; + type MaxReserves = (); + type ReserveIdentifier = (); } frame_support::construct_runtime!( --- a/pallets/nft/src/lib.rs +++ b/pallets/nft/src/lib.rs @@ -175,6 +175,8 @@ BadCreateRefungibleCall, /// Gas limit exceeded OutOfGas, + /// Collection settings not allowing items transferring + TransferNotAllowed, } } @@ -533,6 +535,7 @@ variable_on_chain_schema: Vec::new(), const_on_chain_schema: Vec::new(), limits, + transfers_enabled: true, }; // Add new collection to map @@ -922,6 +925,34 @@ Ok(()) } + // TODO! transaction weight + + /// Set transfers_enabled value for particular collection + /// + /// # Permissions + /// + /// * Collection Owner. + /// + /// # Arguments + /// + /// * collection_id: ID of the collection. + /// + /// * value: New flag value. + #[weight = ::WeightInfo::burn_item()] + #[transactional] + pub fn set_transfers_enabled_flag(origin, collection_id: CollectionId, value: bool) -> DispatchResult { + + let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?); + let mut target_collection = Self::get_collection(collection_id)?; + + Self::check_owner_permissions(&target_collection, sender.as_sub())?; + + target_collection.transfers_enabled = value; + Self::save_collection(target_collection); + + Ok(()) + } + /// Destroys a concrete instance of NFT. /// /// # Permissions @@ -1575,6 +1606,12 @@ Error::::AccountTokenLimitExceeded ); + // preliminary transfer check + ensure!( + collection.transfers_enabled, + Error::::TransferNotAllowed + ); + Ok(()) } --- a/pallets/nft/src/mock.rs +++ b/pallets/nft/src/mock.rs @@ -74,6 +74,8 @@ type ExistentialDeposit = ExistentialDeposit; type WeightInfo = (); type MaxLocks = MaxLocks; + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; } parameter_types! { @@ -100,40 +102,40 @@ type Timestamp = pallet_timestamp::Pallet; type Randomness = pallet_randomness_collective_flip::Pallet; -parameter_types! { - pub const TombstoneDeposit: u64 = 1; - pub const DepositPerContract: u64 = 1; - pub const DepositPerStorageByte: u64 = 1; - pub const DepositPerStorageItem: u64 = 1; - pub RentFraction: Perbill = Perbill::from_rational(1u32, 30 * 24 * 60 * 10); - pub const SurchargeReward: u64 = 1; - pub const SignedClaimHandicap: u32 = 2; - pub DeletionWeightLimit: u64 = u64::MAX;//Perbill::from_percent(10); - pub DeletionQueueDepth: u32 = 10; - pub Schedule: pallet_contracts::Schedule = Default::default(); -} +// parameter_types! { +// pub const TombstoneDeposit: u64 = 1; +// pub const DepositPerContract: u64 = 1; +// pub const DepositPerStorageByte: u64 = 1; +// pub const DepositPerStorageItem: u64 = 1; +// pub RentFraction: Perbill = Perbill::from_rational(1u32, 30 * 24 * 60 * 10); +// pub const SurchargeReward: u64 = 1; +// pub const SignedClaimHandicap: u32 = 2; +// pub DeletionWeightLimit: u64 = u64::MAX;//Perbill::from_percent(10); +// pub DeletionQueueDepth: u32 = 10; +// pub Schedule: pallet_contracts::Schedule = Default::default(); +// } -impl pallet_contracts::Config for Test { - type Time = Timestamp; - type Randomness = Randomness; - type Currency = pallet_balances::Pallet; - type Event = (); - type RentPayment = (); - type SignedClaimHandicap = SignedClaimHandicap; - type TombstoneDeposit = TombstoneDeposit; - type DepositPerContract = DepositPerContract; - type DepositPerStorageByte = DepositPerStorageByte; - type DepositPerStorageItem = DepositPerStorageItem; - type RentFraction = RentFraction; - type SurchargeReward = SurchargeReward; - type DeletionWeightLimit = DeletionWeightLimit; - type DeletionQueueDepth = DeletionQueueDepth; - type ChainExtension = (); - type WeightPrice = (); - type WeightInfo = pallet_contracts::weights::SubstrateWeight; - type Schedule = Schedule; - type CallStack = [pallet_contracts::Frame; 31]; -} +// impl pallet_contracts::Config for Test { +// type Time = Timestamp; +// type Randomness = Randomness; +// type Currency = pallet_balances::Pallet; +// type Event = (); +// type RentPayment = (); +// type SignedClaimHandicap = SignedClaimHandicap; +// type TombstoneDeposit = TombstoneDeposit; +// type DepositPerContract = DepositPerContract; +// type DepositPerStorageByte = DepositPerStorageByte; +// type DepositPerStorageItem = DepositPerStorageItem; +// type RentFraction = RentFraction; +// type SurchargeReward = SurchargeReward; +// type DeletionWeightLimit = DeletionWeightLimit; +// type DeletionQueueDepth = DeletionQueueDepth; +// type ChainExtension = (); +// type WeightPrice = (); +// type WeightInfo = pallet_contracts::weights::SubstrateWeight; +// type Schedule = Schedule; +// type CallStack = [pallet_contracts::Frame; 31]; +// } parameter_types! { pub const CollectionCreationPrice: u32 = 0; --- a/pallets/nft/src/tests.rs +++ b/pallets/nft/src/tests.rs @@ -2351,3 +2351,60 @@ ); }); } + +#[test] +fn collection_transfer_flag_works() { + new_test_ext().execute_with(|| { + default_limits(); + + let origin1 = Origin::signed(1); + + let collection_id = create_test_collection(&CollectionMode::NFT, 1); + assert_ok!(TemplateModule::set_transfers_enabled_flag(origin1, 1, true)); + + let data = default_nft_data(); + create_test_item(collection_id, &data.into()); + assert_eq!(TemplateModule::balance_count(1, 1), 1); + assert_eq!(TemplateModule::address_tokens(1, 1), [1]); + + let origin1 = Origin::signed(1); + + // default scenario + assert_ok!(TemplateModule::transfer(origin1, account(2), 1, 1, 1000)); + assert_eq!(TemplateModule::nft_item_id(1, 1).unwrap().owner, account(2)); + assert_eq!(TemplateModule::balance_count(1, 1), 0); + assert_eq!(TemplateModule::balance_count(1, 2), 1); + + assert_eq!(TemplateModule::address_tokens(1, 2), [1]); + }); +} + +#[test] +fn collection_transfer_flag_works_neg() { + new_test_ext().execute_with(|| { + default_limits(); + + let origin1 = Origin::signed(1); + + let collection_id = create_test_collection(&CollectionMode::NFT, 1); + assert_ok!(TemplateModule::set_transfers_enabled_flag(origin1, 1, false)); + + let data = default_nft_data(); + create_test_item(collection_id, &data.into()); + assert_eq!(TemplateModule::balance_count(1, 1), 1); + assert_eq!(TemplateModule::address_tokens(1, 1), [1]); + + let origin1 = Origin::signed(1); + + // default scenario + assert_noop!( + TemplateModule::transfer(origin1, account(2), 1, 1, 1000), + Error::::TransferNotAllowed + ); + assert_eq!(TemplateModule::nft_item_id(1, 1).unwrap().owner, account(1)); + assert_eq!(TemplateModule::balance_count(1, 1), 1); + assert_eq!(TemplateModule::balance_count(1, 2), 0); + + assert_eq!(TemplateModule::address_tokens(1, 1), [1]); + }); +} --- a/pallets/scheduler/src/lib.rs +++ b/pallets/scheduler/src/lib.rs @@ -947,900 +947,4 @@ fn root() -> OriginCaller { system::RawOrigin::Root.into() } - - #[test] - fn basic_scheduling_works() { - new_test_ext().execute_with(|| { - let call = Call::Logger(logger::Call::log(42, 1000)); - assert!(!::BaseCallFilter::filter( - &call - )); - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(4), - None, - 127, - root(), - call - )); - run_to_block(3); - assert!(logger::log().is_empty()); - run_to_block(4); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - run_to_block(100); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - }); - } - - #[test] - fn schedule_after_works() { - new_test_ext().execute_with(|| { - run_to_block(2); - let call = Call::Logger(logger::Call::log(42, 1000)); - assert!(!::BaseCallFilter::filter( - &call - )); - // This will schedule the call 3 blocks after the next block... so block 3 + 3 = 6 - assert_ok!(Scheduler::do_schedule( - DispatchTime::After(3), - None, - 127, - root(), - call - )); - run_to_block(5); - assert!(logger::log().is_empty()); - run_to_block(6); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - run_to_block(100); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - }); - } - - #[test] - fn schedule_after_zero_works() { - new_test_ext().execute_with(|| { - run_to_block(2); - let call = Call::Logger(logger::Call::log(42, 1000)); - assert!(!::BaseCallFilter::filter( - &call - )); - assert_ok!(Scheduler::do_schedule( - DispatchTime::After(0), - None, - 127, - root(), - call - )); - // Will trigger on the next block. - run_to_block(3); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - run_to_block(100); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - }); - } - - #[test] - fn periodic_scheduling_works() { - new_test_ext().execute_with(|| { - // at #4, every 3 blocks, 3 times. - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(4), - Some((3, 3)), - 127, - root(), - Call::Logger(logger::Call::log(42, 1000)) - )); - run_to_block(3); - assert!(logger::log().is_empty()); - run_to_block(4); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - run_to_block(6); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - run_to_block(7); - assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 42u32)]); - run_to_block(9); - assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 42u32)]); - run_to_block(10); - assert_eq!( - logger::log(), - vec![(root(), 42u32), (root(), 42u32), (root(), 42u32)] - ); - run_to_block(100); - assert_eq!( - logger::log(), - vec![(root(), 42u32), (root(), 42u32), (root(), 42u32)] - ); - }); - } - - #[test] - fn reschedule_works() { - new_test_ext().execute_with(|| { - let call = Call::Logger(logger::Call::log(42, 1000)); - assert!(!::BaseCallFilter::filter( - &call - )); - assert_eq!( - Scheduler::do_schedule(DispatchTime::At(4), None, 127, root(), call).unwrap(), - (4, 0) - ); - - run_to_block(3); - assert!(logger::log().is_empty()); - - assert_eq!( - Scheduler::do_reschedule((4, 0), DispatchTime::At(6)).unwrap(), - (6, 0) - ); - - assert_noop!( - Scheduler::do_reschedule((6, 0), DispatchTime::At(6)), - Error::::RescheduleNoChange - ); - - run_to_block(4); - assert!(logger::log().is_empty()); - - run_to_block(6); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - - run_to_block(100); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - }); - } - - #[test] - fn reschedule_named_works() { - new_test_ext().execute_with(|| { - let call = Call::Logger(logger::Call::log(42, 1000)); - assert!(!::BaseCallFilter::filter( - &call - )); - assert_eq!( - Scheduler::do_schedule_named( - 1u32.encode(), - DispatchTime::At(4), - None, - 127, - root(), - call - ) - .unwrap(), - (4, 0) - ); - - run_to_block(3); - assert!(logger::log().is_empty()); - - assert_eq!( - Scheduler::do_reschedule_named(1u32.encode(), DispatchTime::At(6)).unwrap(), - (6, 0) - ); - - assert_noop!( - Scheduler::do_reschedule_named(1u32.encode(), DispatchTime::At(6)), - Error::::RescheduleNoChange - ); - - run_to_block(4); - assert!(logger::log().is_empty()); - - run_to_block(6); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - - run_to_block(100); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - }); - } - - #[test] - fn reschedule_named_perodic_works() { - new_test_ext().execute_with(|| { - let call = Call::Logger(logger::Call::log(42, 1000)); - assert!(!::BaseCallFilter::filter( - &call - )); - assert_eq!( - Scheduler::do_schedule_named( - 1u32.encode(), - DispatchTime::At(4), - Some((3, 3)), - 127, - root(), - call - ) - .unwrap(), - (4, 0) - ); - - run_to_block(3); - assert!(logger::log().is_empty()); - - assert_eq!( - Scheduler::do_reschedule_named(1u32.encode(), DispatchTime::At(5)).unwrap(), - (5, 0) - ); - assert_eq!( - Scheduler::do_reschedule_named(1u32.encode(), DispatchTime::At(6)).unwrap(), - (6, 0) - ); - - run_to_block(5); - assert!(logger::log().is_empty()); - - run_to_block(6); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - - assert_eq!( - Scheduler::do_reschedule_named(1u32.encode(), DispatchTime::At(10)).unwrap(), - (10, 0) - ); - - run_to_block(9); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - - run_to_block(10); - assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 42u32)]); - - run_to_block(13); - assert_eq!( - logger::log(), - vec![(root(), 42u32), (root(), 42u32), (root(), 42u32)] - ); - - run_to_block(100); - assert_eq!( - logger::log(), - vec![(root(), 42u32), (root(), 42u32), (root(), 42u32)] - ); - }); - } - - #[test] - fn cancel_named_scheduling_works_with_normal_cancel() { - new_test_ext().execute_with(|| { - // at #4. - Scheduler::do_schedule_named( - 1u32.encode(), - DispatchTime::At(4), - None, - 127, - root(), - Call::Logger(logger::Call::log(69, 1000)), - ) - .unwrap(); - let i = Scheduler::do_schedule( - DispatchTime::At(4), - None, - 127, - root(), - Call::Logger(logger::Call::log(42, 1000)), - ) - .unwrap(); - run_to_block(3); - assert!(logger::log().is_empty()); - assert_ok!(Scheduler::do_cancel_named(None, 1u32.encode())); - assert_ok!(Scheduler::do_cancel(None, i)); - run_to_block(100); - assert!(logger::log().is_empty()); - }); - } - - #[test] - fn cancel_named_periodic_scheduling_works() { - new_test_ext().execute_with(|| { - // at #4, every 3 blocks, 3 times. - Scheduler::do_schedule_named( - 1u32.encode(), - DispatchTime::At(4), - Some((3, 3)), - 127, - root(), - Call::Logger(logger::Call::log(42, 1000)), - ) - .unwrap(); - // same id results in error. - assert!(Scheduler::do_schedule_named( - 1u32.encode(), - DispatchTime::At(4), - None, - 127, - root(), - Call::Logger(logger::Call::log(69, 1000)) - ) - .is_err()); - // different id is ok. - Scheduler::do_schedule_named( - 2u32.encode(), - DispatchTime::At(8), - None, - 127, - root(), - Call::Logger(logger::Call::log(69, 1000)), - ) - .unwrap(); - run_to_block(3); - assert!(logger::log().is_empty()); - run_to_block(4); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - run_to_block(6); - assert_ok!(Scheduler::do_cancel_named(None, 1u32.encode())); - run_to_block(100); - assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 69u32)]); - }); - } - - #[test] - fn scheduler_respects_weight_limits() { - new_test_ext().execute_with(|| { - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(4), - None, - 127, - root(), - Call::Logger(logger::Call::log(42, MaximumSchedulerWeight::get() / 2)) - )); - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(4), - None, - 127, - root(), - Call::Logger(logger::Call::log(69, MaximumSchedulerWeight::get() / 2)) - )); - // 69 and 42 do not fit together - run_to_block(4); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - run_to_block(5); - assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 69u32)]); - }); - } - - #[test] - fn scheduler_respects_hard_deadlines_more() { - new_test_ext().execute_with(|| { - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(4), - None, - 0, - root(), - Call::Logger(logger::Call::log(42, MaximumSchedulerWeight::get() / 2)) - )); - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(4), - None, - 0, - root(), - Call::Logger(logger::Call::log(69, MaximumSchedulerWeight::get() / 2)) - )); - // With base weights, 69 and 42 should not fit together, but do because of hard deadlines - run_to_block(4); - assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 69u32)]); - }); - } - - #[test] - fn scheduler_respects_priority_ordering() { - new_test_ext().execute_with(|| { - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(4), - None, - 1, - root(), - Call::Logger(logger::Call::log(42, MaximumSchedulerWeight::get() / 2)) - )); - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(4), - None, - 0, - root(), - Call::Logger(logger::Call::log(69, MaximumSchedulerWeight::get() / 2)) - )); - run_to_block(4); - assert_eq!(logger::log(), vec![(root(), 69u32), (root(), 42u32)]); - }); - } - - #[test] - fn scheduler_respects_priority_ordering_with_soft_deadlines() { - new_test_ext().execute_with(|| { - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(4), - None, - 255, - root(), - Call::Logger(logger::Call::log(42, MaximumSchedulerWeight::get() / 3)) - )); - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(4), - None, - 127, - root(), - Call::Logger(logger::Call::log(69, MaximumSchedulerWeight::get() / 2)) - )); - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(4), - None, - 126, - root(), - Call::Logger(logger::Call::log(2600, MaximumSchedulerWeight::get() / 2)) - )); - - // 2600 does not fit with 69 or 42, but has higher priority, so will go through - run_to_block(4); - assert_eq!(logger::log(), vec![(root(), 2600u32)]); - // 69 and 42 fit together - run_to_block(5); - assert_eq!( - logger::log(), - vec![(root(), 2600u32), (root(), 69u32), (root(), 42u32)] - ); - }); - } - - #[test] - fn on_initialize_weight_is_correct() { - new_test_ext().execute_with(|| { - let base_weight: Weight = - ::DbWeight::get().reads_writes(1, 2); - let base_multiplier = 0; - let named_multiplier = ::DbWeight::get().writes(1); - let periodic_multiplier = - ::DbWeight::get().reads_writes(1, 1); - - // Named - assert_ok!(Scheduler::do_schedule_named( - 1u32.encode(), - DispatchTime::At(1), - None, - 255, - root(), - Call::Logger(logger::Call::log(3, MaximumSchedulerWeight::get() / 3)) - )); - // Anon Periodic - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(1), - Some((1000, 3)), - 128, - root(), - Call::Logger(logger::Call::log(42, MaximumSchedulerWeight::get() / 3)) - )); - // Anon - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(1), - None, - 127, - root(), - Call::Logger(logger::Call::log(69, MaximumSchedulerWeight::get() / 2)) - )); - // Named Periodic - assert_ok!(Scheduler::do_schedule_named( - 2u32.encode(), - DispatchTime::At(1), - Some((1000, 3)), - 126, - root(), - Call::Logger(logger::Call::log(2600, MaximumSchedulerWeight::get() / 2)) - )); - - // Will include the named periodic only - let actual_weight = Scheduler::on_initialize(1); - let call_weight = MaximumSchedulerWeight::get() / 2; - assert_eq!( - actual_weight, - call_weight - + base_weight + base_multiplier - + named_multiplier + periodic_multiplier - ); - assert_eq!(logger::log(), vec![(root(), 2600u32)]); - - // Will include anon and anon periodic - let actual_weight = Scheduler::on_initialize(2); - let call_weight = MaximumSchedulerWeight::get() / 2 + MaximumSchedulerWeight::get() / 3; - assert_eq!( - actual_weight, - call_weight + base_weight + base_multiplier * 2 + periodic_multiplier - ); - assert_eq!( - logger::log(), - vec![(root(), 2600u32), (root(), 69u32), (root(), 42u32)] - ); - - // Will include named only - let actual_weight = Scheduler::on_initialize(3); - let call_weight = MaximumSchedulerWeight::get() / 3; - assert_eq!( - actual_weight, - call_weight + base_weight + base_multiplier + named_multiplier - ); - assert_eq!( - logger::log(), - vec![ - (root(), 2600u32), - (root(), 69u32), - (root(), 42u32), - (root(), 3u32) - ] - ); - - // Will contain none - let actual_weight = Scheduler::on_initialize(4); - assert_eq!(actual_weight, 0); - }); - } - - #[test] - fn root_calls_works() { - new_test_ext().execute_with(|| { - let call = Box::new(Call::Logger(logger::Call::log(69, 1000))); - let call2 = Box::new(Call::Logger(logger::Call::log(42, 1000))); - assert_ok!(Scheduler::schedule_named( - Origin::root(), - 1u32.encode(), - 4, - None, - 127, - call - )); - assert_ok!(Scheduler::schedule(Origin::root(), 4, None, 127, call2)); - run_to_block(3); - // Scheduled calls are in the agenda. - assert_eq!(Agenda::::get(4).len(), 2); - assert!(logger::log().is_empty()); - assert_ok!(Scheduler::cancel_named(Origin::root(), 1u32.encode())); - assert_ok!(Scheduler::cancel(Origin::root(), 4, 1)); - // Scheduled calls are made NONE, so should not effect state - run_to_block(100); - assert!(logger::log().is_empty()); - }); - } - - #[test] - fn fails_to_schedule_task_in_the_past() { - new_test_ext().execute_with(|| { - run_to_block(3); - - let call = Box::new(Call::Logger(logger::Call::log(69, 1000))); - let call2 = Box::new(Call::Logger(logger::Call::log(42, 1000))); - - assert_err!( - Scheduler::schedule_named(Origin::root(), 1u32.encode(), 2, None, 127, call), - Error::::TargetBlockNumberInPast, - ); - - assert_err!( - Scheduler::schedule(Origin::root(), 2, None, 127, call2.clone()), - Error::::TargetBlockNumberInPast, - ); - - assert_err!( - Scheduler::schedule(Origin::root(), 3, None, 127, call2), - Error::::TargetBlockNumberInPast, - ); - }); - } - - #[test] - fn should_use_orign() { - new_test_ext().execute_with(|| { - let call = Box::new(Call::Logger(logger::Call::log(69, 1000))); - let call2 = Box::new(Call::Logger(logger::Call::log(42, 1000))); - assert_ok!(Scheduler::schedule_named( - system::RawOrigin::Signed(1).into(), - 1u32.encode(), - 4, - None, - 127, - call - )); - assert_ok!(Scheduler::schedule( - system::RawOrigin::Signed(1).into(), - 4, - None, - 127, - call2 - )); - run_to_block(3); - // Scheduled calls are in the agenda. - assert_eq!(Agenda::::get(4).len(), 2); - assert!(logger::log().is_empty()); - assert_ok!(Scheduler::cancel_named( - system::RawOrigin::Signed(1).into(), - 1u32.encode() - )); - assert_ok!(Scheduler::cancel(system::RawOrigin::Signed(1).into(), 4, 1)); - // Scheduled calls are made NONE, so should not effect state - run_to_block(100); - assert!(logger::log().is_empty()); - }); - } - - #[test] - fn should_check_orign() { - new_test_ext().execute_with(|| { - let call = Box::new(Call::Logger(logger::Call::log(69, 1000))); - let call2 = Box::new(Call::Logger(logger::Call::log(42, 1000))); - assert_noop!( - Scheduler::schedule_named( - system::RawOrigin::Signed(2).into(), - 1u32.encode(), - 4, - None, - 127, - call - ), - BadOrigin - ); - assert_noop!( - Scheduler::schedule(system::RawOrigin::Signed(2).into(), 4, None, 127, call2), - BadOrigin - ); - }); - } - - #[test] - fn should_check_orign_for_cancel() { - new_test_ext().execute_with(|| { - let call = Box::new(Call::Logger(logger::Call::log_without_filter(69, 1000))); - let call2 = Box::new(Call::Logger(logger::Call::log_without_filter(42, 1000))); - assert_ok!(Scheduler::schedule_named( - system::RawOrigin::Signed(1).into(), - 1u32.encode(), - 4, - None, - 127, - call - )); - assert_ok!(Scheduler::schedule( - system::RawOrigin::Signed(1).into(), - 4, - None, - 127, - call2 - )); - run_to_block(3); - // Scheduled calls are in the agenda. - assert_eq!(Agenda::::get(4).len(), 2); - assert!(logger::log().is_empty()); - assert_noop!( - Scheduler::cancel_named(system::RawOrigin::Signed(2).into(), 1u32.encode()), - BadOrigin - ); - assert_noop!( - Scheduler::cancel(system::RawOrigin::Signed(2).into(), 4, 1), - BadOrigin - ); - assert_noop!( - Scheduler::cancel_named(system::RawOrigin::Root.into(), 1u32.encode()), - BadOrigin - ); - assert_noop!( - Scheduler::cancel(system::RawOrigin::Root.into(), 4, 1), - BadOrigin - ); - run_to_block(5); - assert_eq!( - logger::log(), - vec![ - (system::RawOrigin::Signed(1).into(), 69u32), - (system::RawOrigin::Signed(1).into(), 42u32) - ] - ); - }); - } - - #[test] - fn migration_to_v2_works() { - new_test_ext().execute_with(|| { - for i in 0..3u64 { - let k = i.twox_64_concat(); - let old = vec![ - Some(ScheduledV1 { - maybe_id: None, - priority: i as u8 + 10, - call: Call::Logger(logger::Call::log(96, 100)), - maybe_periodic: None, - }), - None, - Some(ScheduledV1 { - maybe_id: Some(b"test".to_vec()), - priority: 123, - call: Call::Logger(logger::Call::log(69, 1000)), - maybe_periodic: Some((456u64, 10)), - }), - ]; - frame_support::migration::put_storage_value(b"Scheduler", b"Agenda", &k, old); - } - - assert_eq!(StorageVersion::get(), Releases::V1); - - assert!(Scheduler::migrate_v1_to_t2()); - - assert_eq_uvec!( - Agenda::::iter().collect::>(), - vec![ - ( - 0, - vec![ - Some(ScheduledV2 { - maybe_id: None, - priority: 10, - call: Call::Logger(logger::Call::log(96, 100)), - maybe_periodic: None, - origin: root(), - _phantom: PhantomData::::default(), - }), - None, - Some(ScheduledV2 { - maybe_id: Some(b"test".to_vec()), - priority: 123, - call: Call::Logger(logger::Call::log(69, 1000)), - maybe_periodic: Some((456u64, 10)), - origin: root(), - _phantom: PhantomData::::default(), - }), - ] - ), - ( - 1, - vec![ - Some(ScheduledV2 { - maybe_id: None, - priority: 11, - call: Call::Logger(logger::Call::log(96, 100)), - maybe_periodic: None, - origin: root(), - _phantom: PhantomData::::default(), - }), - None, - Some(ScheduledV2 { - maybe_id: Some(b"test".to_vec()), - priority: 123, - call: Call::Logger(logger::Call::log(69, 1000)), - maybe_periodic: Some((456u64, 10)), - origin: root(), - _phantom: PhantomData::::default(), - }), - ] - ), - ( - 2, - vec![ - Some(ScheduledV2 { - maybe_id: None, - priority: 12, - call: Call::Logger(logger::Call::log(96, 100)), - maybe_periodic: None, - origin: root(), - _phantom: PhantomData::::default(), - }), - None, - Some(ScheduledV2 { - maybe_id: Some(b"test".to_vec()), - priority: 123, - call: Call::Logger(logger::Call::log(69, 1000)), - maybe_periodic: Some((456u64, 10)), - origin: root(), - _phantom: PhantomData::::default(), - }), - ] - ) - ] - ); - - assert_eq!(StorageVersion::get(), Releases::V2); - }); - } - - #[test] - fn test_migrate_origin() { - new_test_ext().execute_with(|| { - for i in 0..3u64 { - let k = i.twox_64_concat(); - let old: Vec>> = vec![ - Some(Scheduled { - maybe_id: None, - priority: i as u8 + 10, - call: Call::Logger(logger::Call::log(96, 100)), - origin: 3u32, - maybe_periodic: None, - _phantom: Default::default(), - }), - None, - Some(Scheduled { - maybe_id: Some(b"test".to_vec()), - priority: 123, - origin: 2u32, - call: Call::Logger(logger::Call::log(69, 1000)), - maybe_periodic: Some((456u64, 10)), - _phantom: Default::default(), - }), - ]; - frame_support::migration::put_storage_value(b"Scheduler", b"Agenda", &k, old); - } - - impl From for OriginCaller { - fn from(value: u32) -> Self { - match value { - 3 => system::RawOrigin::Root.into(), - 2 => system::RawOrigin::None.into(), - _ => unimplemented!(), - } - } - } - - Scheduler::migrate_origin::(); - - assert_eq_uvec!( - Agenda::::iter().collect::>(), - vec![ - ( - 0, - vec![ - Some(ScheduledV2::<_, _, OriginCaller, u64> { - maybe_id: None, - priority: 10, - call: Call::Logger(logger::Call::log(96, 100)), - maybe_periodic: None, - origin: system::RawOrigin::Root.into(), - _phantom: PhantomData::::default(), - }), - None, - Some(ScheduledV2 { - maybe_id: Some(b"test".to_vec()), - priority: 123, - call: Call::Logger(logger::Call::log(69, 1000)), - maybe_periodic: Some((456u64, 10)), - origin: system::RawOrigin::None.into(), - _phantom: PhantomData::::default(), - }), - ] - ), - ( - 1, - vec![ - Some(ScheduledV2 { - maybe_id: None, - priority: 11, - call: Call::Logger(logger::Call::log(96, 100)), - maybe_periodic: None, - origin: system::RawOrigin::Root.into(), - _phantom: PhantomData::::default(), - }), - None, - Some(ScheduledV2 { - maybe_id: Some(b"test".to_vec()), - priority: 123, - call: Call::Logger(logger::Call::log(69, 1000)), - maybe_periodic: Some((456u64, 10)), - origin: system::RawOrigin::None.into(), - _phantom: PhantomData::::default(), - }), - ] - ), - ( - 2, - vec![ - Some(ScheduledV2 { - maybe_id: None, - priority: 12, - call: Call::Logger(logger::Call::log(96, 100)), - maybe_periodic: None, - origin: system::RawOrigin::Root.into(), - _phantom: PhantomData::::default(), - }), - None, - Some(ScheduledV2 { - maybe_id: Some(b"test".to_vec()), - priority: 123, - call: Call::Logger(logger::Call::log(69, 1000)), - maybe_periodic: Some((456u64, 10)), - origin: system::RawOrigin::None.into(), - _phantom: PhantomData::::default(), - }), - ] - ) - ] - ); - }); - } } --- a/primitives/nft/src/lib.rs +++ b/primitives/nft/src/lib.rs @@ -144,6 +144,7 @@ pub limits: CollectionLimits, // Collection private restrictions pub variable_on_chain_schema: Vec, // pub const_on_chain_schema: Vec, // + pub transfers_enabled: bool, } #[derive(Encode, Decode, Debug, Clone, PartialEq)]