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_runtime::{sp_std::prelude::Vec};87use up_data_structs::{88 MAX_COLLECTION_NAME_LENGTH, MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_TOKEN_PREFIX_LENGTH,89 CreateItemData, CollectionLimits, CollectionPermissions, CollectionId, CollectionMode, TokenId,90 SponsorshipState, CreateCollectionData, CreateItemExData, budget, Property, PropertyKey,91 PropertyKeyPermission,92};93use pallet_evm::account::CrossAccountId;94use pallet_common::{95 CollectionHandle, Pallet as PalletCommon, CommonWeightInfo, dispatch::dispatch_tx,96 dispatch::CollectionDispatch, RefungibleExtensionsWeightInfo,97};98pub mod eth;99100#[cfg(feature = "runtime-benchmarks")]101pub mod benchmarking;102pub mod weights;103use weights::WeightInfo;104105106pub const NESTING_BUDGET: u32 = 5;107108decl_error! {109 110 pub enum Error for Module<T: Config> {111 112 CollectionDecimalPointLimitExceeded,113 114 ConfirmUnsetSponsorFail,115 116 EmptyArgument,117 118 RepartitionCalledOnNonRefungibleCollection,119 }120}121122123pub trait Config: system::Config + pallet_common::Config + Sized + TypeInfo {124 125 type Event: From<Event<Self>> + Into<<Self as frame_system::Config>::Event>;126127 128 type WeightInfo: WeightInfo;129130 131 type CommonWeightInfo: CommonWeightInfo<Self::CrossAccountId>;132133 134 type RefungibleExtensionsWeightInfo: RefungibleExtensionsWeightInfo;135}136137decl_event! {138 pub enum Event<T>139 where140 <T as frame_system::Config>::AccountId,141 <T as pallet_evm::account::Config>::CrossAccountId,142 {143 144 145 146 147 CollectionSponsorRemoved(CollectionId),148149 150 151 152 153 154 CollectionAdminAdded(CollectionId, CrossAccountId),155156 157 158 159 160 161 CollectionOwnedChanged(CollectionId, AccountId),162163 164 165 166 167 168 CollectionSponsorSet(CollectionId, AccountId),169170 171 172 173 174 175 SponsorshipConfirmed(CollectionId, AccountId),176177 178 179 180 181 182 CollectionAdminRemoved(CollectionId, CrossAccountId),183184 185 186 187 188 189 AllowListAddressRemoved(CollectionId, CrossAccountId),190191 192 193 194 195 196 AllowListAddressAdded(CollectionId, CrossAccountId),197198 199 200 201 202 CollectionLimitSet(CollectionId),203204 205 206 207 208 CollectionPermissionSet(CollectionId),209 }210}211212type SelfWeightOf<T> = <T as Config>::WeightInfo;213214215216217218219220221222223224225226227228229230231232233234235236decl_storage! {237 trait Store for Module<T: Config> as Unique {238239 240 241 ChainVersion: u64;242 243244 245 246 247 pub CreateItemBasket get(fn create_item_basket): map hasher(blake2_128_concat) (CollectionId, T::AccountId) => Option<T::BlockNumber>;248 249 pub NftTransferBasket get(fn nft_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;250 251 pub FungibleTransferBasket get(fn fungible_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;252 253 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>;254 255256 257 258 #[deprecated]259 pub VariableMetaDataBasket get(fn variable_meta_data_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;260 261 pub TokenPropertyBasket get(fn token_property_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;262263 264 pub NftApproveBasket get(fn nft_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;265 266 pub FungibleApproveBasket get(fn fungible_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;267 268 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>;269 }270}271272decl_module! {273 274 pub struct Module<T: Config> for enum Call275 where276 origin: T::Origin277 {278 type Error = Error<T>;279280 pub fn deposit_event() = default;281282 fn on_initialize(_now: T::BlockNumber) -> Weight {283 0284 }285286 fn on_runtime_upgrade() -> Weight {287 0288 }289290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 #[weight = <SelfWeightOf<T>>::create_collection()]313 #[deprecated(note = "`create_collection_ex` is more up-to-date and advanced, prefer it instead")]314 pub fn create_collection(315 origin,316 collection_name: BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>,317 collection_description: BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>,318 token_prefix: BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>,319 mode: CollectionMode320 ) -> DispatchResult {321 let data: CreateCollectionData<T::AccountId> = CreateCollectionData {322 name: collection_name,323 description: collection_description,324 token_prefix,325 mode,326 ..Default::default()327 };328 Self::create_collection_ex(origin, data)329 }330331 332 333 334 335 336 337 338 339 340 341 342 #[weight = <SelfWeightOf<T>>::create_collection()]343 pub fn create_collection_ex(origin, data: CreateCollectionData<T::AccountId>) -> DispatchResult {344 let sender = ensure_signed(origin)?;345346 347 let sender = T::CrossAccountId::from_sub(sender);348 let _id = T::CollectionDispatch::create(sender.clone(), sender, data)?;349350 Ok(())351 }352353 354 355 356 357 358 359 360 361 362 #[weight = <SelfWeightOf<T>>::destroy_collection()]363 pub fn destroy_collection(origin, collection_id: CollectionId) -> DispatchResult {364 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);365 let collection = <CollectionHandle<T>>::try_get(collection_id)?;366 collection.check_is_internal()?;367368 369370 T::CollectionDispatch::destroy(sender, collection)?;371372 373 374375 let _ = <NftTransferBasket<T>>::clear_prefix(collection_id, u32::MAX, None);376 let _ = <FungibleTransferBasket<T>>::clear_prefix(collection_id, u32::MAX, None);377 let _ = <ReFungibleTransferBasket<T>>::clear_prefix((collection_id,), u32::MAX, None);378379 let _ = <NftApproveBasket<T>>::clear_prefix(collection_id, u32::MAX, None);380 let _ = <FungibleApproveBasket<T>>::clear_prefix(collection_id, u32::MAX, None);381 let _ = <RefungibleApproveBasket<T>>::clear_prefix((collection_id,), u32::MAX, None);382383 Ok(())384 }385386 387 388 389 390 391 392 393 394 395 396 397 #[weight = <SelfWeightOf<T>>::add_to_allow_list()]398 pub fn add_to_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{399400 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);401 let collection = <CollectionHandle<T>>::try_get(collection_id)?;402 collection.check_is_internal()?;403404 <PalletCommon<T>>::toggle_allowlist(405 &collection,406 &sender,407 &address,408 true,409 )?;410411 Self::deposit_event(Event::<T>::AllowListAddressAdded(412 collection_id,413 address414 ));415416 Ok(())417 }418419 420 421 422 423 424 425 426 427 428 429 430 #[weight = <SelfWeightOf<T>>::remove_from_allow_list()]431 pub fn remove_from_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{432433 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);434 let collection = <CollectionHandle<T>>::try_get(collection_id)?;435 collection.check_is_internal()?;436437 <PalletCommon<T>>::toggle_allowlist(438 &collection,439 &sender,440 &address,441 false,442 )?;443444 <Pallet<T>>::deposit_event(Event::<T>::AllowListAddressRemoved(445 collection_id,446 address447 ));448449 Ok(())450 }451452 453 454 455 456 457 458 459 460 461 462 #[weight = <SelfWeightOf<T>>::change_collection_owner()]463 pub fn change_collection_owner(origin, collection_id: CollectionId, new_owner: T::AccountId) -> DispatchResult {464465 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);466467 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;468 target_collection.check_is_internal()?;469 target_collection.check_is_owner(&sender)?;470471 target_collection.owner = new_owner.clone();472 <Pallet<T>>::deposit_event(Event::<T>::CollectionOwnedChanged(473 collection_id,474 new_owner475 ));476477 target_collection.save()478 }479480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 #[weight = <SelfWeightOf<T>>::add_collection_admin()]497 pub fn add_collection_admin(origin, collection_id: CollectionId, new_admin_id: T::CrossAccountId) -> DispatchResult {498 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);499 let collection = <CollectionHandle<T>>::try_get(collection_id)?;500 collection.check_is_internal()?;501502 <Pallet<T>>::deposit_event(Event::<T>::CollectionAdminAdded(503 collection_id,504 new_admin_id.clone()505 ));506507 <PalletCommon<T>>::toggle_admin(&collection, &sender, &new_admin_id, true)508 }509510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 #[weight = <SelfWeightOf<T>>::remove_collection_admin()]525 pub fn remove_collection_admin(origin, collection_id: CollectionId, account_id: T::CrossAccountId) -> DispatchResult {526 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);527 let collection = <CollectionHandle<T>>::try_get(collection_id)?;528 collection.check_is_internal()?;529530 <Pallet<T>>::deposit_event(Event::<T>::CollectionAdminRemoved(531 collection_id,532 account_id.clone()533 ));534535 <PalletCommon<T>>::toggle_admin(&collection, &sender, &account_id, false)536 }537538 539 540 541 542 543 544 545 546 547 548 549 550 551 #[weight = <SelfWeightOf<T>>::set_collection_sponsor()]552 pub fn set_collection_sponsor(origin, collection_id: CollectionId, new_sponsor: T::AccountId) -> DispatchResult {553 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);554555 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;556 target_collection.check_is_owner_or_admin(&sender)?;557 target_collection.check_is_internal()?;558559 target_collection.set_sponsor(new_sponsor.clone())?;560561 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorSet(562 collection_id,563 new_sponsor564 ));565566 target_collection.save()567 }568569 570 571 572 573 574 575 576 577 578 579 580 581 582 #[weight = <SelfWeightOf<T>>::confirm_sponsorship()]583 pub fn confirm_sponsorship(origin, collection_id: CollectionId) -> DispatchResult {584 let sender = ensure_signed(origin)?;585586 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;587 target_collection.check_is_internal()?;588 ensure!(589 target_collection.confirm_sponsorship(&sender)?,590 Error::<T>::ConfirmUnsetSponsorFail591 );592593 <Pallet<T>>::deposit_event(Event::<T>::SponsorshipConfirmed(594 collection_id,595 sender596 ));597598 target_collection.save()599 }600601 602 603 604 605 606 607 608 609 610 #[weight = <SelfWeightOf<T>>::remove_collection_sponsor()]611 pub fn remove_collection_sponsor(origin, collection_id: CollectionId) -> DispatchResult {612 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);613614 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;615 target_collection.check_is_internal()?;616 target_collection.check_is_owner(&sender)?;617618 target_collection.sponsorship = SponsorshipState::Disabled;619620 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorRemoved(621 collection_id622 ));623 target_collection.save()624 }625626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 #[weight = T::CommonWeightInfo::create_item()]645 pub fn create_item(origin, collection_id: CollectionId, owner: T::CrossAccountId, data: CreateItemData) -> DispatchResultWithPostInfo {646 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);647 let budget = budget::Value::new(NESTING_BUDGET);648649 dispatch_tx::<T, _>(collection_id, |d| d.create_item(sender, owner, data, &budget))650 }651652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 #[weight = T::CommonWeightInfo::create_multiple_items(&items_data)]671 pub fn create_multiple_items(origin, collection_id: CollectionId, owner: T::CrossAccountId, items_data: Vec<CreateItemData>) -> DispatchResultWithPostInfo {672 ensure!(!items_data.is_empty(), Error::<T>::EmptyArgument);673 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);674 let budget = budget::Value::new(NESTING_BUDGET);675676 dispatch_tx::<T, _>(collection_id, |d| d.create_multiple_items(sender, owner, items_data, &budget))677 }678679 680 681 682 683 684 685 686 687 688 689 690 691 #[weight = T::CommonWeightInfo::set_collection_properties(properties.len() as u32)]692 pub fn set_collection_properties(693 origin,694 collection_id: CollectionId,695 properties: Vec<Property>696 ) -> DispatchResultWithPostInfo {697 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);698699 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);700701 dispatch_tx::<T, _>(collection_id, |d| d.set_collection_properties(sender, properties))702 }703704 705 706 707 708 709 710 711 712 713 714 715 716 #[weight = T::CommonWeightInfo::delete_collection_properties(property_keys.len() as u32)]717 pub fn delete_collection_properties(718 origin,719 collection_id: CollectionId,720 property_keys: Vec<PropertyKey>,721 ) -> DispatchResultWithPostInfo {722 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);723724 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);725726 dispatch_tx::<T, _>(collection_id, |d| d.delete_collection_properties(&sender, property_keys))727 }728729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 #[weight = T::CommonWeightInfo::set_token_properties(properties.len() as u32)]748 pub fn set_token_properties(749 origin,750 collection_id: CollectionId,751 token_id: TokenId,752 properties: Vec<Property>753 ) -> DispatchResultWithPostInfo {754 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);755756 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);757 let budget = budget::Value::new(NESTING_BUDGET);758759 dispatch_tx::<T, _>(collection_id, |d| d.set_token_properties(sender, token_id, properties, &budget))760 }761762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 #[weight = T::CommonWeightInfo::delete_token_properties(property_keys.len() as u32)]778 pub fn delete_token_properties(779 origin,780 collection_id: CollectionId,781 token_id: TokenId,782 property_keys: Vec<PropertyKey>783 ) -> DispatchResultWithPostInfo {784 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);785786 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);787 let budget = budget::Value::new(NESTING_BUDGET);788789 dispatch_tx::<T, _>(collection_id, |d| d.delete_token_properties(sender, token_id, property_keys, &budget))790 }791792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 #[weight = T::CommonWeightInfo::set_token_property_permissions(property_permissions.len() as u32)]808 pub fn set_token_property_permissions(809 origin,810 collection_id: CollectionId,811 property_permissions: Vec<PropertyKeyPermission>,812 ) -> DispatchResultWithPostInfo {813 ensure!(!property_permissions.is_empty(), Error::<T>::EmptyArgument);814815 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);816817 dispatch_tx::<T, _>(collection_id, |d| d.set_token_property_permissions(&sender, property_permissions))818 }819820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 #[weight = T::CommonWeightInfo::create_multiple_items_ex(&data)]836 pub fn create_multiple_items_ex(origin, collection_id: CollectionId, data: CreateItemExData<T::CrossAccountId>) -> DispatchResultWithPostInfo {837 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);838 let budget = budget::Value::new(NESTING_BUDGET);839840 dispatch_tx::<T, _>(collection_id, |d| d.create_multiple_items_ex(sender, data, &budget))841 }842843 844 845 846 847 848 849 850 851 852 853 #[weight = <SelfWeightOf<T>>::set_transfers_enabled_flag()]854 pub fn set_transfers_enabled_flag(origin, collection_id: CollectionId, value: bool) -> DispatchResult {855 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);856 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;857 target_collection.check_is_internal()?;858 target_collection.check_is_owner(&sender)?;859860 861862 target_collection.limits.transfers_enabled = Some(value);863 target_collection.save()864 }865866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 #[weight = T::CommonWeightInfo::burn_item()]883 pub fn burn_item(origin, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {884 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);885886 let post_info = dispatch_tx::<T, _>(collection_id, |d| d.burn_item(sender, item_id, value))?;887 if value == 1 {888 <NftTransferBasket<T>>::remove(collection_id, item_id);889 <NftApproveBasket<T>>::remove(collection_id, item_id);890 }891 892 893 894 Ok(post_info)895 }896897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 #[weight = T::CommonWeightInfo::burn_from()]921 pub fn burn_from(origin, collection_id: CollectionId, from: T::CrossAccountId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {922 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);923 let budget = budget::Value::new(NESTING_BUDGET);924925 dispatch_tx::<T, _>(collection_id, |d| d.burn_from(sender, from, item_id, value, &budget))926 }927928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 #[weight = T::CommonWeightInfo::transfer()]950 pub fn transfer(origin, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {951 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);952 let budget = budget::Value::new(NESTING_BUDGET);953954 dispatch_tx::<T, _>(collection_id, |d| d.transfer(sender, recipient, item_id, value, &budget))955 }956957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 #[weight = T::CommonWeightInfo::approve()]973 pub fn approve(origin, spender: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResultWithPostInfo {974 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);975976 dispatch_tx::<T, _>(collection_id, |d| d.approve(sender, spender, item_id, amount))977 }978979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 #[weight = T::CommonWeightInfo::transfer_from()]1004 pub fn transfer_from(origin, from: T::CrossAccountId, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128 ) -> DispatchResultWithPostInfo {1005 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1006 let budget = budget::Value::new(NESTING_BUDGET);10071008 dispatch_tx::<T, _>(collection_id, |d| d.transfer_from(sender, from, recipient, item_id, value, &budget))1009 }10101011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 #[weight = <SelfWeightOf<T>>::set_collection_limits()]1024 pub fn set_collection_limits(1025 origin,1026 collection_id: CollectionId,1027 new_limit: CollectionLimits,1028 ) -> DispatchResult {1029 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1030 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1031 target_collection.check_is_internal()?;1032 target_collection.check_is_owner_or_admin(&sender)?;1033 let old_limit = &target_collection.limits;10341035 target_collection.limits = <PalletCommon<T>>::clamp_limits(target_collection.mode.clone(), &old_limit, new_limit)?;10361037 <Pallet<T>>::deposit_event(Event::<T>::CollectionLimitSet(1038 collection_id1039 ));10401041 target_collection.save()1042 }10431044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 #[weight = <SelfWeightOf<T>>::set_collection_limits()]1057 pub fn set_collection_permissions(1058 origin,1059 collection_id: CollectionId,1060 new_permission: CollectionPermissions,1061 ) -> DispatchResult {1062 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1063 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1064 target_collection.check_is_internal()?;1065 target_collection.check_is_owner_or_admin(&sender)?;1066 let old_limit = &target_collection.permissions;10671068 target_collection.permissions = <PalletCommon<T>>::clamp_permissions(target_collection.mode.clone(), &old_limit, new_permission)?;10691070 <Pallet<T>>::deposit_event(Event::<T>::CollectionPermissionSet(1071 collection_id1072 ));10731074 target_collection.save()1075 }10761077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 #[weight = T::RefungibleExtensionsWeightInfo::repartition()]1089 pub fn repartition(1090 origin,1091 collection_id: CollectionId,1092 token_id: TokenId,1093 amount: u128,1094 ) -> DispatchResultWithPostInfo {1095 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1096 dispatch_tx::<T, _>(collection_id, |d| {1097 if let Some(refungible_extensions) = d.refungible_extensions() {1098 refungible_extensions.repartition(&sender, token_id, amount)1099 } else {1100 fail!(<Error<T>>::RepartitionCalledOnNonRefungibleCollection)1101 }1102 })1103 }1104 }1105}11061107impl<T: Config> Pallet<T> {1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 pub fn force_set_sponsor(sponsor: T::AccountId, collection_id: CollectionId) -> DispatchResult {1118 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1119 target_collection.check_is_internal()?;1120 target_collection.set_sponsor(sponsor.clone())?;11211122 Self::deposit_event(Event::<T>::CollectionSponsorSet(1123 collection_id,1124 sponsor.clone(),1125 ));11261127 ensure!(1128 target_collection.confirm_sponsorship(&sponsor)?,1129 Error::<T>::ConfirmUnsetSponsorFail1130 );11311132 Self::deposit_event(Event::<T>::SponsorshipConfirmed(collection_id, sponsor));11331134 target_collection.save()1135 }11361137 1138 1139 1140 1141 1142 1143 1144 1145 pub fn force_remove_collection_sponsor(collection_id: CollectionId) -> DispatchResult {1146 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1147 target_collection.check_is_internal()?;1148 target_collection.sponsorship = SponsorshipState::Disabled;11491150 Self::deposit_event(Event::<T>::CollectionSponsorRemoved(collection_id));11511152 target_collection.save()1153 }1154}