difftreelog
CORE-37 Metadata update permissions
in: master
7 files changed
node/cli/src/chain_spec.rsdiffbeforeafterboth--- 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(),
+ meta_update_permission: MetaUpdatePermission::ItemOwner,
},
)],
nft_item_id: vec![],
pallets/inflation/src/tests.rsdiffbeforeafterboth--- 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 = [u8; 8];
}
frame_support::construct_runtime!(
pallets/nft/src/lib.rsdiffbeforeafterboth41 MAX_DECIMAL_POINTS, MAX_SPONSOR_TIMEOUT, MAX_TOKEN_OWNERSHIP, MAX_REFUNGIBLE_PIECES,41 MAX_DECIMAL_POINTS, MAX_SPONSOR_TIMEOUT, MAX_TOKEN_OWNERSHIP, MAX_REFUNGIBLE_PIECES,42 AccessMode, ChainLimits, Collection, CreateItemData, CollectionLimits, CollectionId,42 AccessMode, ChainLimits, Collection, CreateItemData, CollectionLimits, CollectionId,43 CollectionMode, TokenId, SchemaVersion, SponsorshipState, Ownership, NftItemType,43 CollectionMode, TokenId, SchemaVersion, SponsorshipState, Ownership, NftItemType,44 FungibleItemType, ReFungibleItemType,44 FungibleItemType, ReFungibleItemType, MetaUpdatePermission,45};45};46use pallet_ethereum::EthereumTransactionSender;46use pallet_ethereum::EthereumTransactionSender;4747175 BadCreateRefungibleCall,175 BadCreateRefungibleCall,176 /// Gas limit exceeded176 /// Gas limit exceeded177 OutOfGas,177 OutOfGas,178 /// Metadata update denied by collection settings 179 MetadataUpdateDenied,180 /// Metadata update flag become unmutable with None option181 MetadataFlagFrozen,178 }182 }179}183}180184533 variable_on_chain_schema: Vec::new(),537 variable_on_chain_schema: Vec::new(),534 const_on_chain_schema: Vec::new(),538 const_on_chain_schema: Vec::new(),535 limits,539 limits,540 meta_update_permission: MetaUpdatePermission::default(),536 };541 };537542538 // Add new collection to map543 // Add new collection to map922 Ok(())927 Ok(())923 }928 }929930 // TODO! transaction weight931 /// Set meta_update_permission value for particular collection932 ///933 /// # Permissions934 ///935 /// * Collection Owner.936 ///937 /// # Arguments938 ///939 /// * collection_id: ID of the collection.940 ///941 /// * value: New flag value.942 #[weight = <T as Config>::WeightInfo::burn_item()]943 #[transactional]944 pub fn set_meta_update_permission_flag(origin, collection_id: CollectionId, value: MetaUpdatePermission) -> DispatchResult {945946 let sender = ensure_signed(origin)?;947 let mut target_collection = Self::get_collection(collection_id)?;948949 ensure!(950 target_collection.meta_update_permission != MetaUpdatePermission::None,951 Error::<T>::MetadataFlagFrozen952 );953 Self::check_owner_permissions(&target_collection, &sender)?;954 955 target_collection.meta_update_permission = value;956 Self::save_collection(target_collection);957958 Ok(())959 }924960925 /// Destroys a concrete instance of NFT.961 /// Destroys a concrete instance of NFT.926 ///962 ///1481 );1517 );148215181483 // Modify permissions check1519 // Modify permissions check1484 ensure!(1485 Self::is_item_owner(sender, collection, item_id)1520 Self::meta_update_check(sender, collection, item_id)?;1486 || Self::is_owner_or_admin_permissions(collection, sender),1487 Error::<T>::NoPermission1488 );148915211490 match collection.mode {1522 match collection.mode {1491 CollectionMode::NFT => Self::set_nft_variable_data(collection, item_id, data)?,1523 CollectionMode::NFT => Self::set_nft_variable_data(collection, item_id, data)?,1499 Ok(())1531 Ok(())1500 }1532 }15331534 pub fn meta_update_check( 1535 sender: &T::CrossAccountId,1536 collection: &CollectionHandle<T>,1537 item_id: TokenId) -> DispatchResult {15381539 match collection.meta_update_permission {1540 MetaUpdatePermission::ItemOwner => {1541 ensure!(1542 Self::is_item_owner(sender, collection, item_id), 1543 Error::<T>::NoPermission1544 );1545 },1546 MetaUpdatePermission::Admin => {1547 ensure!(1548 Self::is_owner_or_admin_permissions(collection, sender), 1549 Error::<T>::NoPermission1550 );1551 },1552 MetaUpdatePermission::None => {1553 fail!(Error::<T>::MetadataUpdateDenied);1554 },1555 }15561557 Ok(())1558 }150115591502 pub fn create_multiple_items_internal(1560 pub fn create_multiple_items_internal(1503 sender: &T::CrossAccountId,1561 sender: &T::CrossAccountId,pallets/nft/src/mock.rsdiffbeforeafterboth--- 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! {
@@ -99,41 +101,6 @@
type Timestamp = pallet_timestamp::Pallet<Test>;
type Randomness = pallet_randomness_collective_flip::Pallet<Test>;
-
-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<Test> = Default::default();
-}
-
-impl pallet_contracts::Config for Test {
- type Time = Timestamp;
- type Randomness = Randomness;
- type Currency = pallet_balances::Pallet<Test>;
- 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<Self>;
- type Schedule = Schedule;
- type CallStack = [pallet_contracts::Frame<Self>; 31];
-}
parameter_types! {
pub const CollectionCreationPrice: u32 = 0;
pallets/nft/src/tests.rsdiffbeforeafterboth--- a/pallets/nft/src/tests.rs
+++ b/pallets/nft/src/tests.rs
@@ -2351,3 +2351,200 @@
);
});
}
+
+#[test]
+fn set_variable_meta_data_on_nft_with_item_owner_permission_flag() {
+ new_test_ext().execute_with(|| {
+ default_limits();
+
+ let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+ let origin1 = Origin::signed(1);
+
+ let data = default_nft_data();
+ create_test_item(1, &data.into());
+
+ TemplateModule::set_meta_update_permission_flag(origin1.clone(), collection_id, MetaUpdatePermission::ItemOwner);
+
+ let variable_data = b"test set_variable_meta_data method.".to_vec();
+ assert_ok!(TemplateModule::set_variable_meta_data(
+ origin1,
+ collection_id,
+ 1,
+ variable_data.clone()
+ ));
+
+ assert_eq!(
+ TemplateModule::nft_item_id(collection_id, 1)
+ .unwrap()
+ .variable_data,
+ variable_data
+ );
+ });
+}
+
+#[test]
+fn set_variable_meta_data_on_nft_with_item_owner_permission_flag_neg() {
+ new_test_ext().execute_with(|| {
+ default_limits();
+
+ let collection_id = create_test_collection_for_owner(&CollectionMode::NFT, 2, 1);
+
+ let origin1 = Origin::signed(1);
+ let origin2 = Origin::signed(2);
+
+ assert_ok!(TemplateModule::set_mint_permission(
+ origin2.clone(),
+ collection_id,
+ true
+ ));
+ assert_ok!(TemplateModule::add_to_white_list(
+ origin2.clone(),
+ collection_id,
+ account(1)
+ ));
+
+ let data = default_nft_data();
+ create_test_item(1, &data.into());
+
+ TemplateModule::set_meta_update_permission_flag(origin2.clone(), collection_id, MetaUpdatePermission::ItemOwner);
+
+ let variable_data = b"test set_variable_meta_data method.".to_vec();
+ assert_noop!(TemplateModule::set_variable_meta_data(
+ origin2,
+ collection_id,
+ 1,
+ variable_data.clone()),
+ Error::<Test>::NoPermission
+ );
+ });
+}
+
+#[test]
+fn set_variable_meta_data_on_nft_with_admin_flag() {
+ new_test_ext().execute_with(|| {
+ default_limits();
+
+ let collection_id = create_test_collection_for_owner(&CollectionMode::NFT, 2, 1);
+
+ let origin1 = Origin::signed(1);
+ let origin2 = Origin::signed(2);
+
+ assert_ok!(TemplateModule::set_mint_permission(
+ origin2.clone(),
+ collection_id,
+ true
+ ));
+ assert_ok!(TemplateModule::add_to_white_list(
+ origin2.clone(),
+ collection_id,
+ account(1)
+ ));
+
+ assert_ok!(TemplateModule::add_collection_admin(
+ origin2.clone(),
+ collection_id,
+ account(1)
+ ));
+
+ let data = default_nft_data();
+ create_test_item(1, &data.into());
+
+ TemplateModule::set_meta_update_permission_flag(origin2.clone(), collection_id, MetaUpdatePermission::Admin);
+
+ let variable_data = b"test set_variable_meta_data method.".to_vec();
+ assert_ok!(TemplateModule::set_variable_meta_data(
+ origin1,
+ collection_id,
+ 1,
+ variable_data.clone()
+ ));
+
+ assert_eq!(
+ TemplateModule::nft_item_id(collection_id, 1)
+ .unwrap()
+ .variable_data,
+ variable_data
+ );
+ });
+}
+
+#[test]
+fn set_variable_meta_data_on_nft_with_admin_flag_neg() {
+ new_test_ext().execute_with(|| {
+ default_limits();
+
+ let collection_id = create_test_collection_for_owner(&CollectionMode::NFT, 2, 1);
+
+ let origin1 = Origin::signed(1);
+ let origin2 = Origin::signed(2);
+
+ assert_ok!(TemplateModule::set_mint_permission(
+ origin2.clone(),
+ collection_id,
+ true
+ ));
+ assert_ok!(TemplateModule::add_to_white_list(
+ origin2.clone(),
+ collection_id,
+ account(1)
+ ));
+
+ let data = default_nft_data();
+ create_test_item(1, &data.into());
+
+ TemplateModule::set_meta_update_permission_flag(origin2.clone(), collection_id, MetaUpdatePermission::Admin);
+
+ let variable_data = b"test set_variable_meta_data method.".to_vec();
+ assert_noop!(TemplateModule::set_variable_meta_data(
+ origin1,
+ collection_id,
+ 1,
+ variable_data.clone()),
+ Error::<Test>::NoPermission
+ );
+ });
+}
+
+#[test]
+fn set_variable_meta_flag_after_freeze() {
+ new_test_ext().execute_with(|| {
+ default_limits();
+
+ let collection_id = create_test_collection_for_owner(&CollectionMode::NFT, 2, 1);
+
+ let origin2 = Origin::signed(2);
+
+ TemplateModule::set_meta_update_permission_flag(origin2.clone(), collection_id, MetaUpdatePermission::None);
+ assert_noop!(TemplateModule::set_meta_update_permission_flag(
+ origin2.clone(),
+ collection_id,
+ MetaUpdatePermission::Admin),
+ Error::<Test>::MetadataFlagFrozen
+ );
+ });
+}
+
+#[test]
+fn set_variable_meta_data_on_nft_with_none_flag_neg() {
+ new_test_ext().execute_with(|| {
+ default_limits();
+
+ let collection_id = create_test_collection_for_owner(&CollectionMode::NFT, 1, 1);
+ let origin1 = Origin::signed(1);
+
+ let data = default_nft_data();
+ create_test_item(1, &data.into());
+
+ TemplateModule::set_meta_update_permission_flag(origin1.clone(), collection_id, MetaUpdatePermission::None);
+
+ let variable_data = b"test set_variable_meta_data method.".to_vec();
+ assert_noop!(TemplateModule::set_variable_meta_data(
+ origin1.clone(),
+ collection_id,
+ 1,
+ variable_data.clone()),
+ Error::<Test>::MetadataUpdateDenied
+ );
+ });
+}
\ No newline at end of file
pallets/scheduler/src/lib.rsdiffbeforeafterboth--- 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!(!<Test as frame_system::Config>::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!(!<Test as frame_system::Config>::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!(!<Test as frame_system::Config>::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!(!<Test as frame_system::Config>::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::<Test>::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!(!<Test as frame_system::Config>::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::<Test>::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!(!<Test as frame_system::Config>::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 =
- <Test as frame_system::Config>::DbWeight::get().reads_writes(1, 2);
- let base_multiplier = 0;
- let named_multiplier = <Test as frame_system::Config>::DbWeight::get().writes(1);
- let periodic_multiplier =
- <Test as frame_system::Config>::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::<Test>::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::<Test>::TargetBlockNumberInPast,
- );
-
- assert_err!(
- Scheduler::schedule(Origin::root(), 2, None, 127, call2.clone()),
- Error::<Test>::TargetBlockNumberInPast,
- );
-
- assert_err!(
- Scheduler::schedule(Origin::root(), 3, None, 127, call2),
- Error::<Test>::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::<Test>::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::<Test>::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::<Test>::iter().collect::<Vec<_>>(),
- 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::<u64>::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::<u64>::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::<u64>::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::<u64>::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::<u64>::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::<u64>::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<Option<Scheduled<_, _, u32, u64>>> = 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<u32> for OriginCaller {
- fn from(value: u32) -> Self {
- match value {
- 3 => system::RawOrigin::Root.into(),
- 2 => system::RawOrigin::None.into(),
- _ => unimplemented!(),
- }
- }
- }
-
- Scheduler::migrate_origin::<u32>();
-
- assert_eq_uvec!(
- Agenda::<Test>::iter().collect::<Vec<_>>(),
- 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::<u64>::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::<u64>::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::<u64>::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::<u64>::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::<u64>::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::<u64>::default(),
- }),
- ]
- )
- ]
- );
- });
- }
}
primitives/nft/src/lib.rsdiffbeforeafterboth--- a/primitives/nft/src/lib.rs
+++ b/primitives/nft/src/lib.rs
@@ -144,6 +144,7 @@
pub limits: CollectionLimits<T::BlockNumber>, // Collection private restrictions
pub variable_on_chain_schema: Vec<u8>, //
pub const_on_chain_schema: Vec<u8>, //
+ pub meta_update_permission: MetaUpdatePermission,
}
#[derive(Encode, Decode, Debug, Clone, PartialEq)]
@@ -241,6 +242,20 @@
#[derive(Encode, Decode, Debug, Clone, PartialEq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+pub enum MetaUpdatePermission {
+ ItemOwner,
+ Admin,
+ None,
+}
+
+impl Default for MetaUpdatePermission {
+ fn default() -> Self {
+ Self::ItemOwner
+ }
+}
+
+#[derive(Encode, Decode, Debug, Clone, PartialEq)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub enum CreateItemData {
NFT(CreateNftData),
Fungible(CreateFungibleData),