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,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, ensure_root};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 CreateCollectionData, CreateItemExData, budget, Property, PropertyKey, PropertyKeyPermission,93};94use pallet_evm::account::CrossAccountId;95use pallet_common::{96 CollectionHandle, Pallet as PalletCommon, CommonWeightInfo, dispatch::dispatch_tx,97 dispatch::CollectionDispatch, RefungibleExtensionsWeightInfo,98};99pub mod eth;100101#[cfg(feature = "runtime-benchmarks")]102pub mod benchmarking;103pub mod weights;104use weights::WeightInfo;105106107pub const NESTING_BUDGET: u32 = 5;108109decl_error! {110 111 pub enum Error for Module<T: Config> {112 113 CollectionDecimalPointLimitExceeded,114 115 EmptyArgument,116 117 RepartitionCalledOnNonRefungibleCollection,118 }119}120121122pub trait Config: system::Config + pallet_common::Config + Sized + TypeInfo {123 124 type WeightInfo: WeightInfo;125126 127 type CommonWeightInfo: CommonWeightInfo<Self::CrossAccountId>;128129 130 type RefungibleExtensionsWeightInfo: RefungibleExtensionsWeightInfo;131}132133type SelfWeightOf<T> = <T as Config>::WeightInfo;134135136137138139140141142143144145146147148149150151152153154155156157decl_storage! {158 trait Store for Module<T: Config> as Unique {159160 161 162 ChainVersion: u64;163 164165 166 167 168 pub CreateItemBasket get(fn create_item_basket): map hasher(blake2_128_concat) (CollectionId, T::AccountId) => Option<T::BlockNumber>;169 170 pub NftTransferBasket get(fn nft_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;171 172 pub FungibleTransferBasket get(fn fungible_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;173 174 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>;175 176177 178 179 #[deprecated]180 pub VariableMetaDataBasket get(fn variable_meta_data_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;181 182 pub TokenPropertyBasket get(fn token_property_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;183184 185 pub NftApproveBasket get(fn nft_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;186 187 pub FungibleApproveBasket get(fn fungible_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;188 189 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>;190 }191}192193decl_module! {194 195 pub struct Module<T: Config> for enum Call196 where197 origin: T::RuntimeOrigin198 {199 type Error = Error<T>;200201 #[doc = "A maximum number of levels of depth in the token nesting tree."]202 const NESTING_BUDGET: u32 = NESTING_BUDGET;203204 #[doc = "Maximal length of a collection name."]205 const MAX_COLLECTION_NAME_LENGTH: u32 = MAX_COLLECTION_NAME_LENGTH;206207 #[doc = "Maximal length of a collection description."]208 const MAX_COLLECTION_DESCRIPTION_LENGTH: u32 = MAX_COLLECTION_DESCRIPTION_LENGTH;209210 #[doc = "Maximal length of a token prefix."]211 const MAX_TOKEN_PREFIX_LENGTH: u32 = MAX_TOKEN_PREFIX_LENGTH;212213 #[doc = "Maximum admins per collection."]214 const COLLECTION_ADMINS_LIMIT: u32 = COLLECTION_ADMINS_LIMIT;215216 #[doc = "Maximal length of a property key."]217 const MAX_PROPERTY_KEY_LENGTH: u32 = MAX_PROPERTY_KEY_LENGTH;218219 #[doc = "Maximal length of a property value."]220 const MAX_PROPERTY_VALUE_LENGTH: u32 = MAX_PROPERTY_VALUE_LENGTH;221222 #[doc = "A maximum number of token properties."]223 const MAX_PROPERTIES_PER_ITEM: u32 = MAX_PROPERTIES_PER_ITEM;224225 #[doc = "Maximum size for all collection properties."]226 const MAX_COLLECTION_PROPERTIES_SIZE: u32 = MAX_COLLECTION_PROPERTIES_SIZE;227228 #[doc = "Maximum size of all token properties."]229 const MAX_TOKEN_PROPERTIES_SIZE: u32 = MAX_TOKEN_PROPERTIES_SIZE;230231 #[doc = "Default NFT collection limit."]232 const NFT_DEFAULT_COLLECTION_LIMITS: CollectionLimits = CollectionLimits::with_default_limits(CollectionMode::NFT);233234 #[doc = "Default RFT collection limit."]235 const RFT_DEFAULT_COLLECTION_LIMITS: CollectionLimits = CollectionLimits::with_default_limits(CollectionMode::ReFungible);236237 #[doc = "Default FT collection limit."]238 const FT_DEFAULT_COLLECTION_LIMITS: CollectionLimits = CollectionLimits::with_default_limits(CollectionMode::Fungible(0));239240 fn on_initialize(_now: T::BlockNumber) -> Weight {241 Weight::zero()242 }243244 fn on_runtime_upgrade() -> Weight {245 Weight::zero()246 }247248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 #[weight = <SelfWeightOf<T>>::create_collection()]274 fn create_collection(275 origin,276 collection_name: BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>,277 collection_description: BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>,278 token_prefix: BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>,279 mode: CollectionMode280 ) -> DispatchResult {281 let data: CreateCollectionData<T::AccountId> = CreateCollectionData {282 name: collection_name,283 description: collection_description,284 token_prefix,285 mode,286 ..Default::default()287 };288 Self::create_collection_ex(origin, data)289 }290291 292 293 294 295 296 297 298 299 300 301 302 #[weight = <SelfWeightOf<T>>::create_collection()]303 pub fn create_collection_ex(origin, data: CreateCollectionData<T::AccountId>) -> DispatchResult {304 let sender = ensure_signed(origin)?;305306 307 let sender = T::CrossAccountId::from_sub(sender);308 let _id = T::CollectionDispatch::create(sender.clone(), sender, data, Default::default())?;309310 Ok(())311 }312313 314 315 316 317 318 319 320 321 322 #[weight = <SelfWeightOf<T>>::destroy_collection()]323 pub fn destroy_collection(origin, collection_id: CollectionId) -> DispatchResult {324 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);325326 Self::destroy_collection_internal(sender, collection_id)327 }328329 330 331 332 333 334 335 336 337 338 339 340 #[weight = <SelfWeightOf<T>>::add_to_allow_list()]341 pub fn add_to_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{342343 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);344 let collection = <CollectionHandle<T>>::try_get(collection_id)?;345 collection.check_is_internal()?;346347 <PalletCommon<T>>::toggle_allowlist(348 &collection,349 &sender,350 &address,351 true,352 )?;353354 Ok(())355 }356357 358 359 360 361 362 363 364 365 366 367 368 #[weight = <SelfWeightOf<T>>::remove_from_allow_list()]369 pub fn remove_from_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{370371 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);372 let collection = <CollectionHandle<T>>::try_get(collection_id)?;373 collection.check_is_internal()?;374375 <PalletCommon<T>>::toggle_allowlist(376 &collection,377 &sender,378 &address,379 false,380 )?;381382 Ok(())383 }384385 386 387 388 389 390 391 392 393 394 395 #[weight = <SelfWeightOf<T>>::change_collection_owner()]396 pub fn change_collection_owner(origin, collection_id: CollectionId, new_owner: T::AccountId) -> DispatchResult {397 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);398 let new_owner = T::CrossAccountId::from_sub(new_owner);399 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;400 target_collection.change_owner(sender, new_owner.clone())401 }402403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 #[weight = <SelfWeightOf<T>>::add_collection_admin()]420 pub fn add_collection_admin(origin, collection_id: CollectionId, new_admin_id: T::CrossAccountId) -> DispatchResult {421 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);422 let collection = <CollectionHandle<T>>::try_get(collection_id)?;423 <PalletCommon<T>>::toggle_admin(&collection, &sender, &new_admin_id, true)424 }425426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 #[weight = <SelfWeightOf<T>>::remove_collection_admin()]441 pub fn remove_collection_admin(origin, collection_id: CollectionId, account_id: T::CrossAccountId) -> DispatchResult {442 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);443 let collection = <CollectionHandle<T>>::try_get(collection_id)?;444 <PalletCommon<T>>::toggle_admin(&collection, &sender, &account_id, false)445 }446447 448 449 450 451 452 453 454 455 456 457 458 459 460 #[weight = <SelfWeightOf<T>>::set_collection_sponsor()]461 pub fn set_collection_sponsor(origin, collection_id: CollectionId, new_sponsor: T::AccountId) -> DispatchResult {462 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);463 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;464 target_collection.set_sponsor(&sender, new_sponsor.clone())465 }466467 468 469 470 471 472 473 474 475 476 477 478 479 480 #[weight = <SelfWeightOf<T>>::confirm_sponsorship()]481 pub fn confirm_sponsorship(origin, collection_id: CollectionId) -> DispatchResult {482 let sender = ensure_signed(origin)?;483 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;484 target_collection.confirm_sponsorship(&sender)485 }486487 488 489 490 491 492 493 494 495 496 #[weight = <SelfWeightOf<T>>::remove_collection_sponsor()]497 pub fn remove_collection_sponsor(origin, collection_id: CollectionId) -> DispatchResult {498 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);499 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;500 target_collection.remove_sponsor(&sender)501 }502503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 #[weight = T::CommonWeightInfo::create_item()]522 pub fn create_item(origin, collection_id: CollectionId, owner: T::CrossAccountId, data: CreateItemData) -> DispatchResultWithPostInfo {523 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);524 let budget = budget::Value::new(NESTING_BUDGET);525526 dispatch_tx::<T, _>(collection_id, |d| d.create_item(sender, owner, data, &budget))527 }528529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 #[weight = T::CommonWeightInfo::create_multiple_items(&items_data)]548 pub fn create_multiple_items(origin, collection_id: CollectionId, owner: T::CrossAccountId, items_data: Vec<CreateItemData>) -> DispatchResultWithPostInfo {549 ensure!(!items_data.is_empty(), Error::<T>::EmptyArgument);550 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);551 let budget = budget::Value::new(NESTING_BUDGET);552553 dispatch_tx::<T, _>(collection_id, |d| d.create_multiple_items(sender, owner, items_data, &budget))554 }555556 557 558 559 560 561 562 563 564 565 566 567 568 #[weight = T::CommonWeightInfo::set_collection_properties(properties.len() as u32)]569 pub fn set_collection_properties(570 origin,571 collection_id: CollectionId,572 properties: Vec<Property>573 ) -> DispatchResultWithPostInfo {574 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);575576 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);577578 dispatch_tx::<T, _>(collection_id, |d| d.set_collection_properties(sender, properties))579 }580581 582 583 584 585 586 587 588 589 590 591 592 593 #[weight = T::CommonWeightInfo::delete_collection_properties(property_keys.len() as u32)]594 pub fn delete_collection_properties(595 origin,596 collection_id: CollectionId,597 property_keys: Vec<PropertyKey>,598 ) -> DispatchResultWithPostInfo {599 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);600601 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);602603 dispatch_tx::<T, _>(collection_id, |d| d.delete_collection_properties(&sender, property_keys))604 }605606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 #[weight = T::CommonWeightInfo::set_token_properties(properties.len() as u32)]625 pub fn set_token_properties(626 origin,627 collection_id: CollectionId,628 token_id: TokenId,629 properties: Vec<Property>630 ) -> DispatchResultWithPostInfo {631 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);632633 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);634 let budget = budget::Value::new(NESTING_BUDGET);635636 dispatch_tx::<T, _>(collection_id, |d| d.set_token_properties(sender, token_id, properties, &budget))637 }638639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 #[weight = T::CommonWeightInfo::delete_token_properties(property_keys.len() as u32)]655 pub fn delete_token_properties(656 origin,657 collection_id: CollectionId,658 token_id: TokenId,659 property_keys: Vec<PropertyKey>660 ) -> DispatchResultWithPostInfo {661 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);662663 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);664 let budget = budget::Value::new(NESTING_BUDGET);665666 dispatch_tx::<T, _>(collection_id, |d| d.delete_token_properties(sender, token_id, property_keys, &budget))667 }668669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 #[weight = T::CommonWeightInfo::set_token_property_permissions(property_permissions.len() as u32)]685 pub fn set_token_property_permissions(686 origin,687 collection_id: CollectionId,688 property_permissions: Vec<PropertyKeyPermission>,689 ) -> DispatchResultWithPostInfo {690 ensure!(!property_permissions.is_empty(), Error::<T>::EmptyArgument);691692 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);693694 dispatch_tx::<T, _>(collection_id, |d| d.set_token_property_permissions(&sender, property_permissions))695 }696697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 #[weight = T::CommonWeightInfo::create_multiple_items_ex(&data)]713 pub fn create_multiple_items_ex(origin, collection_id: CollectionId, data: CreateItemExData<T::CrossAccountId>) -> DispatchResultWithPostInfo {714 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);715 let budget = budget::Value::new(NESTING_BUDGET);716717 dispatch_tx::<T, _>(collection_id, |d| d.create_multiple_items_ex(sender, data, &budget))718 }719720 721 722 723 724 725 726 727 728 729 730 #[weight = <SelfWeightOf<T>>::set_transfers_enabled_flag()]731 pub fn set_transfers_enabled_flag(origin, collection_id: CollectionId, value: bool) -> DispatchResult {732 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);733 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;734 target_collection.check_is_internal()?;735 target_collection.check_is_owner(&sender)?;736737 738739 target_collection.limits.transfers_enabled = Some(value);740 target_collection.save()741 }742743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 #[weight = T::CommonWeightInfo::burn_item()]760 pub fn burn_item(origin, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {761 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);762763 let post_info = dispatch_tx::<T, _>(collection_id, |d| d.burn_item(sender, item_id, value))?;764 if value == 1 {765 <NftTransferBasket<T>>::remove(collection_id, item_id);766 <NftApproveBasket<T>>::remove(collection_id, item_id);767 }768 769 770 771 Ok(post_info)772 }773774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 #[weight = T::CommonWeightInfo::burn_from()]798 pub fn burn_from(origin, collection_id: CollectionId, from: T::CrossAccountId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {799 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);800 let budget = budget::Value::new(NESTING_BUDGET);801802 dispatch_tx::<T, _>(collection_id, |d| d.burn_from(sender, from, item_id, value, &budget))803 }804805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 #[weight = T::CommonWeightInfo::transfer()]827 pub fn transfer(origin, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {828 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);829 let budget = budget::Value::new(NESTING_BUDGET);830831 dispatch_tx::<T, _>(collection_id, |d| d.transfer(sender, recipient, item_id, value, &budget))832 }833834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 #[weight = T::CommonWeightInfo::approve()]850 pub fn approve(origin, spender: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResultWithPostInfo {851 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);852853 dispatch_tx::<T, _>(collection_id, |d| d.approve(sender, spender, item_id, amount))854 }855856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 #[weight = T::CommonWeightInfo::approve_from()]873 pub fn approve_from(origin, from:T::CrossAccountId, to: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResultWithPostInfo {874 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);875876 dispatch_tx::<T, _>(collection_id, |d| d.approve_from(sender, from, to, item_id, amount))877 }878879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 #[weight = T::CommonWeightInfo::transfer_from()]904 pub fn transfer_from(origin, from: T::CrossAccountId, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128 ) -> DispatchResultWithPostInfo {905 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);906 let budget = budget::Value::new(NESTING_BUDGET);907908 dispatch_tx::<T, _>(collection_id, |d| d.transfer_from(sender, from, recipient, item_id, value, &budget))909 }910911 912 913 914 915 916 917 918 919 920 921 922 923 #[weight = <SelfWeightOf<T>>::set_collection_limits()]924 pub fn set_collection_limits(925 origin,926 collection_id: CollectionId,927 new_limit: CollectionLimits,928 ) -> DispatchResult {929 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);930 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;931 <PalletCommon<T>>::update_limits(&sender, &mut target_collection, new_limit)932 }933934 935 936 937 938 939 940 941 942 943 944 945 946 #[weight = <SelfWeightOf<T>>::set_collection_limits()]947 pub fn set_collection_permissions(948 origin,949 collection_id: CollectionId,950 new_permission: CollectionPermissions,951 ) -> DispatchResult {952 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);953 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;954 <PalletCommon<T>>::update_permissions(955 &sender,956 &mut target_collection,957 new_permission958 )959 }960961 962 963 964 965 966 967 968 969 970 971 972 #[weight = T::RefungibleExtensionsWeightInfo::repartition()]973 pub fn repartition(974 origin,975 collection_id: CollectionId,976 token_id: TokenId,977 amount: u128,978 ) -> DispatchResultWithPostInfo {979 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);980 dispatch_tx::<T, _>(collection_id, |d| {981 if let Some(refungible_extensions) = d.refungible_extensions() {982 refungible_extensions.repartition(&sender, token_id, amount)983 } else {984 fail!(<Error<T>>::RepartitionCalledOnNonRefungibleCollection)985 }986 })987 }988989 990 991 992 993 994 995 996 997 998 #[weight = T::CommonWeightInfo::set_allowance_for_all()]999 pub fn set_allowance_for_all(1000 origin,1001 collection_id: CollectionId,1002 operator: T::CrossAccountId,1003 approve: bool,1004 ) -> DispatchResultWithPostInfo {1005 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1006 dispatch_tx::<T, _>(collection_id, |d| {1007 d.set_allowance_for_all(sender, operator, approve)1008 })1009 }10101011 1012 1013 1014 1015 1016 #[weight = <SelfWeightOf<T>>::force_repair_collection()]1017 pub fn force_repair_collection(1018 origin,1019 collection_id: CollectionId,1020 ) -> DispatchResult {1021 ensure_root(origin)?;1022 <PalletCommon<T>>::repair_collection(collection_id)1023 }10241025 1026 1027 1028 1029 1030 1031 #[weight = T::CommonWeightInfo::force_repair_item()]1032 pub fn force_repair_item(1033 origin,1034 collection_id: CollectionId,1035 item_id: TokenId,1036 ) -> DispatchResultWithPostInfo {1037 ensure_root(origin)?;1038 dispatch_tx::<T, _>(collection_id, |d| {1039 d.repair_item(item_id)1040 })1041 }1042 }1043}10441045impl<T: Config> Pallet<T> {1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 pub fn force_set_sponsor(sponsor: T::AccountId, collection_id: CollectionId) -> DispatchResult {1056 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1057 target_collection.force_set_sponsor(sponsor.clone())1058 }10591060 1061 1062 1063 1064 1065 1066 1067 1068 pub fn force_remove_collection_sponsor(collection_id: CollectionId) -> DispatchResult {1069 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1070 target_collection.force_remove_sponsor()1071 }10721073 #[inline(always)]1074 pub(crate) fn destroy_collection_internal(1075 sender: T::CrossAccountId,1076 collection_id: CollectionId,1077 ) -> DispatchResult {1078 let collection = <CollectionHandle<T>>::try_get(collection_id)?;1079 collection.check_is_internal()?;10801081 T::CollectionDispatch::destroy(sender, collection)?;10821083 1084 10851086 let _ = <NftTransferBasket<T>>::clear_prefix(collection_id, u32::MAX, None);1087 let _ = <FungibleTransferBasket<T>>::clear_prefix(collection_id, u32::MAX, None);1088 let _ = <ReFungibleTransferBasket<T>>::clear_prefix((collection_id,), u32::MAX, None);10891090 let _ = <NftApproveBasket<T>>::clear_prefix(collection_id, u32::MAX, None);1091 let _ = <FungibleApproveBasket<T>>::clear_prefix(collection_id, u32::MAX, None);1092 let _ = <RefungibleApproveBasket<T>>::clear_prefix((collection_id,), u32::MAX, None);10931094 Ok(())1095 }1096}