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.rsdiffbeforeafterboth--- a/pallets/nft/src/lib.rs
+++ b/pallets/nft/src/lib.rs
@@ -41,7 +41,7 @@
MAX_DECIMAL_POINTS, MAX_SPONSOR_TIMEOUT, MAX_TOKEN_OWNERSHIP, MAX_REFUNGIBLE_PIECES,
AccessMode, ChainLimits, Collection, CreateItemData, CollectionLimits, CollectionId,
CollectionMode, TokenId, SchemaVersion, SponsorshipState, Ownership, NftItemType,
- FungibleItemType, ReFungibleItemType,
+ FungibleItemType, ReFungibleItemType, MetaUpdatePermission,
};
use pallet_ethereum::EthereumTransactionSender;
@@ -175,6 +175,10 @@
BadCreateRefungibleCall,
/// Gas limit exceeded
OutOfGas,
+ /// Metadata update denied by collection settings
+ MetadataUpdateDenied,
+ /// Metadata update flag become unmutable with None option
+ MetadataFlagFrozen,
}
}
@@ -533,6 +537,7 @@
variable_on_chain_schema: Vec::new(),
const_on_chain_schema: Vec::new(),
limits,
+ meta_update_permission: MetaUpdatePermission::default(),
};
// Add new collection to map
@@ -922,6 +927,37 @@
Ok(())
}
+ // TODO! transaction weight
+ /// Set meta_update_permission value for particular collection
+ ///
+ /// # Permissions
+ ///
+ /// * Collection Owner.
+ ///
+ /// # Arguments
+ ///
+ /// * collection_id: ID of the collection.
+ ///
+ /// * value: New flag value.
+ #[weight = <T as Config>::WeightInfo::burn_item()]
+ #[transactional]
+ pub fn set_meta_update_permission_flag(origin, collection_id: CollectionId, value: MetaUpdatePermission) -> DispatchResult {
+
+ let sender = ensure_signed(origin)?;
+ let mut target_collection = Self::get_collection(collection_id)?;
+
+ ensure!(
+ target_collection.meta_update_permission != MetaUpdatePermission::None,
+ Error::<T>::MetadataFlagFrozen
+ );
+ Self::check_owner_permissions(&target_collection, &sender)?;
+
+ target_collection.meta_update_permission = value;
+ Self::save_collection(target_collection);
+
+ Ok(())
+ }
+
/// Destroys a concrete instance of NFT.
///
/// # Permissions
@@ -1481,11 +1517,7 @@
);
// Modify permissions check
- ensure!(
- Self::is_item_owner(sender, collection, item_id)
- || Self::is_owner_or_admin_permissions(collection, sender),
- Error::<T>::NoPermission
- );
+ Self::meta_update_check(sender, collection, item_id)?;
match collection.mode {
CollectionMode::NFT => Self::set_nft_variable_data(collection, item_id, data)?,
@@ -1499,6 +1531,32 @@
Ok(())
}
+ pub fn meta_update_check(
+ sender: &T::CrossAccountId,
+ collection: &CollectionHandle<T>,
+ item_id: TokenId) -> DispatchResult {
+
+ match collection.meta_update_permission {
+ MetaUpdatePermission::ItemOwner => {
+ ensure!(
+ Self::is_item_owner(sender, collection, item_id),
+ Error::<T>::NoPermission
+ );
+ },
+ MetaUpdatePermission::Admin => {
+ ensure!(
+ Self::is_owner_or_admin_permissions(collection, sender),
+ Error::<T>::NoPermission
+ );
+ },
+ MetaUpdatePermission::None => {
+ fail!(Error::<T>::MetadataUpdateDenied);
+ },
+ }
+
+ Ok(())
+ }
+
pub fn create_multiple_items_internal(
sender: &T::CrossAccountId,
collection: &CollectionHandle<T>,
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.rsdiffbeforeafterboth2352 });2352 });2353}2353}235423542355#[test]2356fn set_variable_meta_data_on_nft_with_item_owner_permission_flag() {2357 new_test_ext().execute_with(|| {2358 default_limits();23592360 let collection_id = create_test_collection(&CollectionMode::NFT, 1);23612362 let origin1 = Origin::signed(1);23632364 let data = default_nft_data();2365 create_test_item(1, &data.into());23662367 TemplateModule::set_meta_update_permission_flag(origin1.clone(), collection_id, MetaUpdatePermission::ItemOwner);23682369 let variable_data = b"test set_variable_meta_data method.".to_vec();2370 assert_ok!(TemplateModule::set_variable_meta_data(2371 origin1,2372 collection_id,2373 1,2374 variable_data.clone()2375 ));23762377 assert_eq!(2378 TemplateModule::nft_item_id(collection_id, 1)2379 .unwrap()2380 .variable_data,2381 variable_data2382 );2383 });2384}23852386#[test]2387fn set_variable_meta_data_on_nft_with_item_owner_permission_flag_neg() {2388 new_test_ext().execute_with(|| {2389 default_limits();23902391 let collection_id = create_test_collection_for_owner(&CollectionMode::NFT, 2, 1);23922393 let origin1 = Origin::signed(1);2394 let origin2 = Origin::signed(2);23952396 assert_ok!(TemplateModule::set_mint_permission(2397 origin2.clone(),2398 collection_id,2399 true2400 ));2401 assert_ok!(TemplateModule::add_to_white_list(2402 origin2.clone(),2403 collection_id,2404 account(1)2405 ));24062407 let data = default_nft_data();2408 create_test_item(1, &data.into());24092410 TemplateModule::set_meta_update_permission_flag(origin2.clone(), collection_id, MetaUpdatePermission::ItemOwner);24112412 let variable_data = b"test set_variable_meta_data method.".to_vec();2413 assert_noop!(TemplateModule::set_variable_meta_data(2414 origin2,2415 collection_id,2416 1,2417 variable_data.clone()),2418 Error::<Test>::NoPermission2419 );2420 });2421}24222423#[test]2424fn set_variable_meta_data_on_nft_with_admin_flag() {2425 new_test_ext().execute_with(|| {2426 default_limits();24272428 let collection_id = create_test_collection_for_owner(&CollectionMode::NFT, 2, 1);24292430 let origin1 = Origin::signed(1);2431 let origin2 = Origin::signed(2);24322433 assert_ok!(TemplateModule::set_mint_permission(2434 origin2.clone(),2435 collection_id,2436 true2437 ));2438 assert_ok!(TemplateModule::add_to_white_list(2439 origin2.clone(),2440 collection_id,2441 account(1)2442 ));24432444 assert_ok!(TemplateModule::add_collection_admin(2445 origin2.clone(),2446 collection_id,2447 account(1)2448 ));24492450 let data = default_nft_data();2451 create_test_item(1, &data.into());24522453 TemplateModule::set_meta_update_permission_flag(origin2.clone(), collection_id, MetaUpdatePermission::Admin);24542455 let variable_data = b"test set_variable_meta_data method.".to_vec();2456 assert_ok!(TemplateModule::set_variable_meta_data(2457 origin1,2458 collection_id,2459 1,2460 variable_data.clone()2461 ));24622463 assert_eq!(2464 TemplateModule::nft_item_id(collection_id, 1)2465 .unwrap()2466 .variable_data,2467 variable_data2468 );2469 });2470}24712472#[test]2473fn set_variable_meta_data_on_nft_with_admin_flag_neg() {2474 new_test_ext().execute_with(|| {2475 default_limits();24762477 let collection_id = create_test_collection_for_owner(&CollectionMode::NFT, 2, 1);24782479 let origin1 = Origin::signed(1);2480 let origin2 = Origin::signed(2);24812482 assert_ok!(TemplateModule::set_mint_permission(2483 origin2.clone(),2484 collection_id,2485 true2486 ));2487 assert_ok!(TemplateModule::add_to_white_list(2488 origin2.clone(),2489 collection_id,2490 account(1)2491 ));24922493 let data = default_nft_data();2494 create_test_item(1, &data.into());24952496 TemplateModule::set_meta_update_permission_flag(origin2.clone(), collection_id, MetaUpdatePermission::Admin);24972498 let variable_data = b"test set_variable_meta_data method.".to_vec();2499 assert_noop!(TemplateModule::set_variable_meta_data(2500 origin1,2501 collection_id,2502 1,2503 variable_data.clone()),2504 Error::<Test>::NoPermission2505 );2506 });2507}25082509#[test]2510fn set_variable_meta_flag_after_freeze() {2511 new_test_ext().execute_with(|| {2512 default_limits();25132514 let collection_id = create_test_collection_for_owner(&CollectionMode::NFT, 2, 1);25152516 let origin2 = Origin::signed(2);25172518 TemplateModule::set_meta_update_permission_flag(origin2.clone(), collection_id, MetaUpdatePermission::None);2519 assert_noop!(TemplateModule::set_meta_update_permission_flag(2520 origin2.clone(),2521 collection_id,2522 MetaUpdatePermission::Admin),2523 Error::<Test>::MetadataFlagFrozen2524 );2525 });2526}25272528#[test]2529fn set_variable_meta_data_on_nft_with_none_flag_neg() {2530 new_test_ext().execute_with(|| {2531 default_limits();25322533 let collection_id = create_test_collection_for_owner(&CollectionMode::NFT, 1, 1);2534 let origin1 = Origin::signed(1);25352536 let data = default_nft_data();2537 create_test_item(1, &data.into());25382539 TemplateModule::set_meta_update_permission_flag(origin1.clone(), collection_id, MetaUpdatePermission::None);25402541 let variable_data = b"test set_variable_meta_data method.".to_vec();2542 assert_noop!(TemplateModule::set_variable_meta_data(2543 origin1.clone(),2544 collection_id,2545 1,2546 variable_data.clone()),2547 Error::<Test>::MetadataUpdateDenied2548 );2549 });2550}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),