123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566#![recursion_limit = "1024"]67#![cfg_attr(not(feature = "std"), no_std)]68#![allow(69 clippy::too_many_arguments,70 clippy::unnecessary_mut_passed,71 clippy::unused_unit72)]7374extern crate alloc;7576use frame_support::{77 decl_module, decl_storage, decl_error, decl_event,78 dispatch::DispatchResult,79 ensure, fail,80 weights::{Weight},81 pallet_prelude::{DispatchResultWithPostInfo, ConstU32},82 BoundedVec,83};84use scale_info::TypeInfo;85use frame_system::{self as system, ensure_signed};86use sp_std::{vec, vec::Vec};87use up_data_structs::{88 MAX_COLLECTION_NAME_LENGTH, MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_TOKEN_PREFIX_LENGTH,89 MAX_PROPERTIES_PER_ITEM, MAX_PROPERTY_KEY_LENGTH, MAX_PROPERTY_VALUE_LENGTH,90 MAX_COLLECTION_PROPERTIES_SIZE, COLLECTION_ADMINS_LIMIT, MAX_TOKEN_PROPERTIES_SIZE,91 CreateItemData, CollectionLimits, CollectionPermissions, CollectionId, CollectionMode, TokenId,92 SponsorshipState, CreateCollectionData, CreateItemExData, budget, Property, PropertyKey,93 PropertyKeyPermission,94};95use pallet_evm::account::CrossAccountId;96use pallet_common::{97 CollectionHandle, Pallet as PalletCommon, CommonWeightInfo, dispatch::dispatch_tx,98 dispatch::CollectionDispatch, RefungibleExtensionsWeightInfo,99};100pub mod eth;101102#[cfg(feature = "runtime-benchmarks")]103pub mod benchmarking;104pub mod weights;105use weights::WeightInfo;106107108pub const NESTING_BUDGET: u32 = 5;109110decl_error! {111 112 pub enum Error for Module<T: Config> {113 114 CollectionDecimalPointLimitExceeded,115 116 ConfirmUnsetSponsorFail,117 118 EmptyArgument,119 120 RepartitionCalledOnNonRefungibleCollection,121 }122}123124125pub trait Config: system::Config + pallet_common::Config + Sized + TypeInfo {126 127 type RuntimeEvent: From<Event<Self>> + Into<<Self as frame_system::Config>::RuntimeEvent>;128129 130 type WeightInfo: WeightInfo;131132 133 type CommonWeightInfo: CommonWeightInfo<Self::CrossAccountId>;134135 136 type RefungibleExtensionsWeightInfo: RefungibleExtensionsWeightInfo;137}138139decl_event! {140 pub enum Event<T>141 where142 <T as frame_system::Config>::AccountId,143 <T as pallet_evm::Config>::CrossAccountId,144 {145 146 147 148 149 CollectionSponsorRemoved(CollectionId),150151 152 153 154 155 156 CollectionAdminAdded(CollectionId, CrossAccountId),157158 159 160 161 162 163 CollectionOwnedChanged(CollectionId, AccountId),164165 166 167 168 169 170 CollectionSponsorSet(CollectionId, AccountId),171172 173 174 175 176 177 SponsorshipConfirmed(CollectionId, AccountId),178179 180 181 182 183 184 CollectionAdminRemoved(CollectionId, CrossAccountId),185186 187 188 189 190 191 AllowListAddressRemoved(CollectionId, CrossAccountId),192193 194 195 196 197 198 AllowListAddressAdded(CollectionId, CrossAccountId),199200 201 202 203 204 CollectionLimitSet(CollectionId),205206 207 208 209 210 CollectionPermissionSet(CollectionId),211 }212}213214type SelfWeightOf<T> = <T as Config>::WeightInfo;215216217218219220221222223224225226227228229230231232233234235236237238decl_storage! {239 trait Store for Module<T: Config> as Unique {240241 242 243 ChainVersion: u64;244 245246 247 248 249 pub CreateItemBasket get(fn create_item_basket): map hasher(blake2_128_concat) (CollectionId, T::AccountId) => Option<T::BlockNumber>;250 251 pub NftTransferBasket get(fn nft_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;252 253 pub FungibleTransferBasket get(fn fungible_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;254 255 pub ReFungibleTransferBasket get(fn refungible_transfer_basket): nmap hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;256 257258 259 260 #[deprecated]261 pub VariableMetaDataBasket get(fn variable_meta_data_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;262 263 pub TokenPropertyBasket get(fn token_property_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;264265 266 pub NftApproveBasket get(fn nft_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;267 268 pub FungibleApproveBasket get(fn fungible_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;269 270 pub RefungibleApproveBasket get(fn refungible_approve_basket): nmap hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;271 }272}273274decl_module! {275 276 pub struct Module<T: Config> for enum Call277 where278 origin: T::RuntimeOrigin279 {280 type Error = Error<T>;281282 #[doc = "Maximum number of levels of depth in the token nesting tree."]283 const NESTING_BUDGET: u32 = NESTING_BUDGET;284285 #[doc = "Maximum length for collection name."]286 const MAX_COLLECTION_NAME_LENGTH: u32 = MAX_COLLECTION_NAME_LENGTH;287288 #[doc = "Maximum length for collection description."]289 const MAX_COLLECTION_DESCRIPTION_LENGTH: u32 = MAX_COLLECTION_DESCRIPTION_LENGTH;290291 #[doc = "Maximal token prefix length."]292 const MAX_TOKEN_PREFIX_LENGTH: u32 = MAX_TOKEN_PREFIX_LENGTH;293294 #[doc = "Maximum admins per collection."]295 const COLLECTION_ADMINS_LIMIT: u32 = COLLECTION_ADMINS_LIMIT;296297 #[doc = "Maximal lenght of property key."]298 const MAX_PROPERTY_KEY_LENGTH: u32 = MAX_PROPERTY_KEY_LENGTH;299300 #[doc = "Maximal lenght of property value."]301 const MAX_PROPERTY_VALUE_LENGTH: u32 = MAX_PROPERTY_VALUE_LENGTH;302303 #[doc = "Maximum properties that can be assigned to token."]304 const MAX_PROPERTIES_PER_ITEM: u32 = MAX_PROPERTIES_PER_ITEM;305306 #[doc = "Maximum size for all collection properties."]307 const MAX_COLLECTION_PROPERTIES_SIZE: u32 = MAX_COLLECTION_PROPERTIES_SIZE;308309 #[doc = "Maximum size for all token properties."]310 const MAX_TOKEN_PROPERTIES_SIZE: u32 = MAX_TOKEN_PROPERTIES_SIZE;311312 #[doc = "Default NFT collection limit."]313 const NFT_DEFAULT_COLLECTION_LIMITS: CollectionLimits = CollectionLimits::with_default_limits(CollectionMode::NFT);314315 #[doc = "Default RFT collection limit."]316 const RFT_DEFAULT_COLLECTION_LIMITS: CollectionLimits = CollectionLimits::with_default_limits(CollectionMode::ReFungible);317318 #[doc = "Default FT collection limit."]319 const FT_DEFAULT_COLLECTION_LIMITS: CollectionLimits = CollectionLimits::with_default_limits(CollectionMode::Fungible(0));320321322 pub fn deposit_event() = default;323324 fn on_initialize(_now: T::BlockNumber) -> Weight {325 Weight::zero()326 }327328 fn on_runtime_upgrade() -> Weight {329 Weight::zero()330 }331332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 #[weight = <SelfWeightOf<T>>::create_collection()]355 #[deprecated(note = "`create_collection_ex` is more up-to-date and advanced, prefer it instead")]356 pub fn create_collection(357 origin,358 collection_name: BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>,359 collection_description: BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>,360 token_prefix: BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>,361 mode: CollectionMode362 ) -> DispatchResult {363 let data: CreateCollectionData<T::AccountId> = CreateCollectionData {364 name: collection_name,365 description: collection_description,366 token_prefix,367 mode,368 ..Default::default()369 };370 Self::create_collection_ex(origin, data)371 }372373 374 375 376 377 378 379 380 381 382 383 384 #[weight = <SelfWeightOf<T>>::create_collection()]385 pub fn create_collection_ex(origin, data: CreateCollectionData<T::AccountId>) -> DispatchResult {386 let sender = ensure_signed(origin)?;387388 389 let sender = T::CrossAccountId::from_sub(sender);390 let _id = T::CollectionDispatch::create(sender.clone(), sender, data, Default::default())?;391392 Ok(())393 }394395 396 397 398 399 400 401 402 403 404 #[weight = <SelfWeightOf<T>>::destroy_collection()]405 pub fn destroy_collection(origin, collection_id: CollectionId) -> DispatchResult {406 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);407408 Self::destroy_collection_internal(sender, collection_id)409 }410411 412 413 414 415 416 417 418 419 420 421 422 #[weight = <SelfWeightOf<T>>::add_to_allow_list()]423 pub fn add_to_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{424425 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);426 let collection = <CollectionHandle<T>>::try_get(collection_id)?;427 collection.check_is_internal()?;428429 <PalletCommon<T>>::toggle_allowlist(430 &collection,431 &sender,432 &address,433 true,434 )?;435436 Self::deposit_event(Event::<T>::AllowListAddressAdded(437 collection_id,438 address439 ));440441 Ok(())442 }443444 445 446 447 448 449 450 451 452 453 454 455 #[weight = <SelfWeightOf<T>>::remove_from_allow_list()]456 pub fn remove_from_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{457458 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);459 let collection = <CollectionHandle<T>>::try_get(collection_id)?;460 collection.check_is_internal()?;461462 <PalletCommon<T>>::toggle_allowlist(463 &collection,464 &sender,465 &address,466 false,467 )?;468469 <Pallet<T>>::deposit_event(Event::<T>::AllowListAddressRemoved(470 collection_id,471 address472 ));473474 Ok(())475 }476477 478 479 480 481 482 483 484 485 486 487 #[weight = <SelfWeightOf<T>>::change_collection_owner()]488 pub fn change_collection_owner(origin, collection_id: CollectionId, new_owner: T::AccountId) -> DispatchResult {489490 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);491492 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;493 target_collection.check_is_internal()?;494 target_collection.check_is_owner(&sender)?;495496 target_collection.owner = new_owner.clone();497 <Pallet<T>>::deposit_event(Event::<T>::CollectionOwnedChanged(498 collection_id,499 new_owner500 ));501502 target_collection.save()503 }504505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 #[weight = <SelfWeightOf<T>>::add_collection_admin()]522 pub fn add_collection_admin(origin, collection_id: CollectionId, new_admin_id: T::CrossAccountId) -> DispatchResult {523 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);524 let collection = <CollectionHandle<T>>::try_get(collection_id)?;525 collection.check_is_internal()?;526527 <Pallet<T>>::deposit_event(Event::<T>::CollectionAdminAdded(528 collection_id,529 new_admin_id.clone()530 ));531532 <PalletCommon<T>>::toggle_admin(&collection, &sender, &new_admin_id, true)533 }534535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 #[weight = <SelfWeightOf<T>>::remove_collection_admin()]550 pub fn remove_collection_admin(origin, collection_id: CollectionId, account_id: T::CrossAccountId) -> DispatchResult {551 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);552 let collection = <CollectionHandle<T>>::try_get(collection_id)?;553 collection.check_is_internal()?;554555 <Pallet<T>>::deposit_event(Event::<T>::CollectionAdminRemoved(556 collection_id,557 account_id.clone()558 ));559560 <PalletCommon<T>>::toggle_admin(&collection, &sender, &account_id, false)561 }562563 564 565 566 567 568 569 570 571 572 573 574 575 576 #[weight = <SelfWeightOf<T>>::set_collection_sponsor()]577 pub fn set_collection_sponsor(origin, collection_id: CollectionId, new_sponsor: T::AccountId) -> DispatchResult {578 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);579580 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;581 target_collection.check_is_owner_or_admin(&sender)?;582 target_collection.check_is_internal()?;583584 target_collection.set_sponsor(new_sponsor.clone())?;585586 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorSet(587 collection_id,588 new_sponsor589 ));590591 target_collection.save()592 }593594 595 596 597 598 599 600 601 602 603 604 605 606 607 #[weight = <SelfWeightOf<T>>::confirm_sponsorship()]608 pub fn confirm_sponsorship(origin, collection_id: CollectionId) -> DispatchResult {609 let sender = ensure_signed(origin)?;610611 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;612 target_collection.check_is_internal()?;613 ensure!(614 target_collection.confirm_sponsorship(&sender)?,615 Error::<T>::ConfirmUnsetSponsorFail616 );617618 <Pallet<T>>::deposit_event(Event::<T>::SponsorshipConfirmed(619 collection_id,620 sender621 ));622623 target_collection.save()624 }625626 627 628 629 630 631 632 633 634 635 #[weight = <SelfWeightOf<T>>::remove_collection_sponsor()]636 pub fn remove_collection_sponsor(origin, collection_id: CollectionId) -> DispatchResult {637 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);638639 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;640 target_collection.check_is_internal()?;641 target_collection.check_is_owner(&sender)?;642643 target_collection.sponsorship = SponsorshipState::Disabled;644645 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorRemoved(646 collection_id647 ));648 target_collection.save()649 }650651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 #[weight = T::CommonWeightInfo::create_item()]670 pub fn create_item(origin, collection_id: CollectionId, owner: T::CrossAccountId, data: CreateItemData) -> DispatchResultWithPostInfo {671 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);672 let budget = budget::Value::new(NESTING_BUDGET);673674 dispatch_tx::<T, _>(collection_id, |d| d.create_item(sender, owner, data, &budget))675 }676677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 #[weight = T::CommonWeightInfo::create_multiple_items(&items_data)]696 pub fn create_multiple_items(origin, collection_id: CollectionId, owner: T::CrossAccountId, items_data: Vec<CreateItemData>) -> DispatchResultWithPostInfo {697 ensure!(!items_data.is_empty(), Error::<T>::EmptyArgument);698 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);699 let budget = budget::Value::new(NESTING_BUDGET);700701 dispatch_tx::<T, _>(collection_id, |d| d.create_multiple_items(sender, owner, items_data, &budget))702 }703704 705 706 707 708 709 710 711 712 713 714 715 716 #[weight = T::CommonWeightInfo::set_collection_properties(properties.len() as u32)]717 pub fn set_collection_properties(718 origin,719 collection_id: CollectionId,720 properties: Vec<Property>721 ) -> DispatchResultWithPostInfo {722 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);723724 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);725726 dispatch_tx::<T, _>(collection_id, |d| d.set_collection_properties(sender, properties))727 }728729 730 731 732 733 734 735 736 737 738 739 740 741 #[weight = T::CommonWeightInfo::delete_collection_properties(property_keys.len() as u32)]742 pub fn delete_collection_properties(743 origin,744 collection_id: CollectionId,745 property_keys: Vec<PropertyKey>,746 ) -> DispatchResultWithPostInfo {747 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);748749 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);750751 dispatch_tx::<T, _>(collection_id, |d| d.delete_collection_properties(&sender, property_keys))752 }753754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 #[weight = T::CommonWeightInfo::set_token_properties(properties.len() as u32)]773 pub fn set_token_properties(774 origin,775 collection_id: CollectionId,776 token_id: TokenId,777 properties: Vec<Property>778 ) -> DispatchResultWithPostInfo {779 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);780781 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);782 let budget = budget::Value::new(NESTING_BUDGET);783784 dispatch_tx::<T, _>(collection_id, |d| d.set_token_properties(sender, token_id, properties, &budget))785 }786787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 #[weight = T::CommonWeightInfo::delete_token_properties(property_keys.len() as u32)]803 pub fn delete_token_properties(804 origin,805 collection_id: CollectionId,806 token_id: TokenId,807 property_keys: Vec<PropertyKey>808 ) -> DispatchResultWithPostInfo {809 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);810811 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);812 let budget = budget::Value::new(NESTING_BUDGET);813814 dispatch_tx::<T, _>(collection_id, |d| d.delete_token_properties(sender, token_id, property_keys, &budget))815 }816817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 #[weight = T::CommonWeightInfo::set_token_property_permissions(property_permissions.len() as u32)]833 pub fn set_token_property_permissions(834 origin,835 collection_id: CollectionId,836 property_permissions: Vec<PropertyKeyPermission>,837 ) -> DispatchResultWithPostInfo {838 ensure!(!property_permissions.is_empty(), Error::<T>::EmptyArgument);839840 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);841842 dispatch_tx::<T, _>(collection_id, |d| d.set_token_property_permissions(&sender, property_permissions))843 }844845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 #[weight = T::CommonWeightInfo::create_multiple_items_ex(&data)]861 pub fn create_multiple_items_ex(origin, collection_id: CollectionId, data: CreateItemExData<T::CrossAccountId>) -> DispatchResultWithPostInfo {862 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);863 let budget = budget::Value::new(NESTING_BUDGET);864865 dispatch_tx::<T, _>(collection_id, |d| d.create_multiple_items_ex(sender, data, &budget))866 }867868 869 870 871 872 873 874 875 876 877 878 #[weight = <SelfWeightOf<T>>::set_transfers_enabled_flag()]879 pub fn set_transfers_enabled_flag(origin, collection_id: CollectionId, value: bool) -> DispatchResult {880 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);881 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;882 target_collection.check_is_internal()?;883 target_collection.check_is_owner(&sender)?;884885 886887 target_collection.limits.transfers_enabled = Some(value);888 target_collection.save()889 }890891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 #[weight = T::CommonWeightInfo::burn_item()]908 pub fn burn_item(origin, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {909 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);910911 let post_info = dispatch_tx::<T, _>(collection_id, |d| d.burn_item(sender, item_id, value))?;912 if value == 1 {913 <NftTransferBasket<T>>::remove(collection_id, item_id);914 <NftApproveBasket<T>>::remove(collection_id, item_id);915 }916 917 918 919 Ok(post_info)920 }921922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 #[weight = T::CommonWeightInfo::burn_from()]946 pub fn burn_from(origin, collection_id: CollectionId, from: T::CrossAccountId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {947 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);948 let budget = budget::Value::new(NESTING_BUDGET);949950 dispatch_tx::<T, _>(collection_id, |d| d.burn_from(sender, from, item_id, value, &budget))951 }952953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 #[weight = T::CommonWeightInfo::transfer()]975 pub fn transfer(origin, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {976 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);977 let budget = budget::Value::new(NESTING_BUDGET);978979 dispatch_tx::<T, _>(collection_id, |d| d.transfer(sender, recipient, item_id, value, &budget))980 }981982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 #[weight = T::CommonWeightInfo::approve()]998 pub fn approve(origin, spender: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResultWithPostInfo {999 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);10001001 dispatch_tx::<T, _>(collection_id, |d| d.approve(sender, spender, item_id, amount))1002 }10031004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 #[weight = T::CommonWeightInfo::transfer_from()]1029 pub fn transfer_from(origin, from: T::CrossAccountId, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128 ) -> DispatchResultWithPostInfo {1030 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1031 let budget = budget::Value::new(NESTING_BUDGET);10321033 dispatch_tx::<T, _>(collection_id, |d| d.transfer_from(sender, from, recipient, item_id, value, &budget))1034 }10351036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 #[weight = <SelfWeightOf<T>>::set_collection_limits()]1049 pub fn set_collection_limits(1050 origin,1051 collection_id: CollectionId,1052 new_limit: CollectionLimits,1053 ) -> DispatchResult {1054 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1055 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1056 target_collection.check_is_internal()?;1057 target_collection.check_is_owner_or_admin(&sender)?;1058 let old_limit = &target_collection.limits;10591060 target_collection.limits = <PalletCommon<T>>::clamp_limits(target_collection.mode.clone(), &old_limit, new_limit)?;10611062 <Pallet<T>>::deposit_event(Event::<T>::CollectionLimitSet(1063 collection_id1064 ));10651066 target_collection.save()1067 }10681069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 #[weight = <SelfWeightOf<T>>::set_collection_limits()]1082 pub fn set_collection_permissions(1083 origin,1084 collection_id: CollectionId,1085 new_permission: CollectionPermissions,1086 ) -> DispatchResult {1087 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1088 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1089 target_collection.check_is_internal()?;1090 target_collection.check_is_owner_or_admin(&sender)?;1091 let old_limit = &target_collection.permissions;10921093 target_collection.permissions = <PalletCommon<T>>::clamp_permissions(target_collection.mode.clone(), &old_limit, new_permission)?;10941095 <Pallet<T>>::deposit_event(Event::<T>::CollectionPermissionSet(1096 collection_id1097 ));10981099 target_collection.save()1100 }11011102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 #[weight = T::RefungibleExtensionsWeightInfo::repartition()]1114 pub fn repartition(1115 origin,1116 collection_id: CollectionId,1117 token_id: TokenId,1118 amount: u128,1119 ) -> DispatchResultWithPostInfo {1120 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1121 dispatch_tx::<T, _>(collection_id, |d| {1122 if let Some(refungible_extensions) = d.refungible_extensions() {1123 refungible_extensions.repartition(&sender, token_id, amount)1124 } else {1125 fail!(<Error<T>>::RepartitionCalledOnNonRefungibleCollection)1126 }1127 })1128 }1129 }1130}11311132impl<T: Config> Pallet<T> {1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 pub fn force_set_sponsor(sponsor: T::AccountId, collection_id: CollectionId) -> DispatchResult {1143 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1144 target_collection.check_is_internal()?;1145 target_collection.set_sponsor(sponsor.clone())?;11461147 Self::deposit_event(Event::<T>::CollectionSponsorSet(1148 collection_id,1149 sponsor.clone(),1150 ));11511152 ensure!(1153 target_collection.confirm_sponsorship(&sponsor)?,1154 Error::<T>::ConfirmUnsetSponsorFail1155 );11561157 Self::deposit_event(Event::<T>::SponsorshipConfirmed(collection_id, sponsor));11581159 target_collection.save()1160 }11611162 1163 1164 1165 1166 1167 1168 1169 1170 pub fn force_remove_collection_sponsor(collection_id: CollectionId) -> DispatchResult {1171 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1172 target_collection.check_is_internal()?;1173 target_collection.sponsorship = SponsorshipState::Disabled;11741175 Self::deposit_event(Event::<T>::CollectionSponsorRemoved(collection_id));11761177 target_collection.save()1178 }11791180 #[inline(always)]1181 pub(crate) fn destroy_collection_internal(1182 sender: T::CrossAccountId,1183 collection_id: CollectionId,1184 ) -> DispatchResult {1185 let collection = <CollectionHandle<T>>::try_get(collection_id)?;1186 collection.check_is_internal()?;11871188 T::CollectionDispatch::destroy(sender, collection)?;11891190 1191 11921193 let _ = <NftTransferBasket<T>>::clear_prefix(collection_id, u32::MAX, None);1194 let _ = <FungibleTransferBasket<T>>::clear_prefix(collection_id, u32::MAX, None);1195 let _ = <ReFungibleTransferBasket<T>>::clear_prefix((collection_id,), u32::MAX, None);11961197 let _ = <NftApproveBasket<T>>::clear_prefix(collection_id, u32::MAX, None);1198 let _ = <FungibleApproveBasket<T>>::clear_prefix(collection_id, u32::MAX, None);1199 let _ = <RefungibleApproveBasket<T>>::clear_prefix((collection_id,), u32::MAX, None);12001201 Ok(())1202 }1203}