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 transactional,82 pallet_prelude::{DispatchResultWithPostInfo, ConstU32},83 BoundedVec,84};85use scale_info::TypeInfo;86use frame_system::{self as system, ensure_signed};87use sp_runtime::{sp_std::prelude::Vec};88use up_data_structs::{89 MAX_COLLECTION_NAME_LENGTH, MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_TOKEN_PREFIX_LENGTH,90 CreateItemData, CollectionLimits, CollectionPermissions, CollectionId, CollectionMode, TokenId,91 SponsorshipState, CreateCollectionData, CreateItemExData, budget, Property, PropertyKey,92 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")]102mod 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 ConfirmUnsetSponsorFail,116 117 EmptyArgument,118 119 RepartitionCalledOnNonRefungibleCollection,120 }121}122123124pub trait Config: system::Config + pallet_common::Config + Sized + TypeInfo {125 126 type Event: From<Event<Self>> + Into<<Self as frame_system::Config>::Event>;127128 129 type WeightInfo: WeightInfo;130131 132 type CommonWeightInfo: CommonWeightInfo<Self::CrossAccountId>;133134 135 type RefungibleExtensionsWeightInfo: RefungibleExtensionsWeightInfo;136}137138decl_event! {139 pub enum Event<T>140 where141 <T as frame_system::Config>::AccountId,142 <T as pallet_evm::account::Config>::CrossAccountId,143 {144 145 146 147 148 CollectionSponsorRemoved(CollectionId),149150 151 152 153 154 155 CollectionAdminAdded(CollectionId, CrossAccountId),156157 158 159 160 161 162 CollectionOwnedChanged(CollectionId, AccountId),163164 165 166 167 168 169 CollectionSponsorSet(CollectionId, AccountId),170171 172 173 174 175 176 SponsorshipConfirmed(CollectionId, AccountId),177178 179 180 181 182 183 CollectionAdminRemoved(CollectionId, CrossAccountId),184185 186 187 188 189 190 AllowListAddressRemoved(CollectionId, CrossAccountId),191192 193 194 195 196 197 AllowListAddressAdded(CollectionId, CrossAccountId),198199 200 201 202 203 CollectionLimitSet(CollectionId),204205 206 207 208 209 CollectionPermissionSet(CollectionId),210 }211}212213type SelfWeightOf<T> = <T as Config>::WeightInfo;214215216217218219220221222223224225226227228229230231232233234235236237decl_storage! {238 trait Store for Module<T: Config> as Unique {239240 241 242 ChainVersion: u64;243 244245 246 247 248 pub CreateItemBasket get(fn create_item_basket): map hasher(blake2_128_concat) (CollectionId, T::AccountId) => Option<T::BlockNumber>;249 250 pub NftTransferBasket get(fn nft_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;251 252 pub FungibleTransferBasket get(fn fungible_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;253 254 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>;255 256257 258 259 #[deprecated]260 pub VariableMetaDataBasket get(fn variable_meta_data_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;261 262 pub TokenPropertyBasket get(fn token_property_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;263264 265 pub NftApproveBasket get(fn nft_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;266 267 pub FungibleApproveBasket get(fn fungible_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;268 269 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>;270 }271}272273decl_module! {274 275 pub struct Module<T: Config> for enum Call276 where277 origin: T::Origin278 {279 type Error = Error<T>;280281 fn deposit_event() = default;282283 fn on_initialize(_now: T::BlockNumber) -> Weight {284 0285 }286287 fn on_runtime_upgrade() -> Weight {288 0289 }290291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 #[weight = <SelfWeightOf<T>>::create_collection()]314 #[transactional]315 #[deprecated(note = "`create_collection_ex` is more up-to-date and advanced, prefer it instead")]316 pub fn create_collection(317 origin,318 collection_name: BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>,319 collection_description: BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>,320 token_prefix: BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>,321 mode: CollectionMode322 ) -> DispatchResult {323 let data: CreateCollectionData<T::AccountId> = CreateCollectionData {324 name: collection_name,325 description: collection_description,326 token_prefix,327 mode,328 ..Default::default()329 };330 Self::create_collection_ex(origin, data)331 }332333 334 335 336 337 338 339 340 341 342 343 344 #[weight = <SelfWeightOf<T>>::create_collection()]345 #[transactional]346 pub fn create_collection_ex(origin, data: CreateCollectionData<T::AccountId>) -> DispatchResult {347 let sender = ensure_signed(origin)?;348349 350351 let _id = T::CollectionDispatch::create(T::CrossAccountId::from_sub(sender), data)?;352353 Ok(())354 }355356 357 358 359 360 361 362 363 364 365 #[weight = <SelfWeightOf<T>>::destroy_collection()]366 #[transactional]367 pub fn destroy_collection(origin, collection_id: CollectionId) -> DispatchResult {368 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);369 let collection = <CollectionHandle<T>>::try_get(collection_id)?;370 collection.check_is_internal()?;371372 373374 T::CollectionDispatch::destroy(sender, collection)?;375376 <NftTransferBasket<T>>::remove_prefix(collection_id, None);377 <FungibleTransferBasket<T>>::remove_prefix(collection_id, None);378 <ReFungibleTransferBasket<T>>::remove_prefix((collection_id,), None);379380 <NftApproveBasket<T>>::remove_prefix(collection_id, None);381 <FungibleApproveBasket<T>>::remove_prefix(collection_id, None);382 <RefungibleApproveBasket<T>>::remove_prefix((collection_id,), None);383384 Ok(())385 }386387 388 389 390 391 392 393 394 395 396 397 398 #[weight = <SelfWeightOf<T>>::add_to_allow_list()]399 #[transactional]400 pub fn add_to_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{401402 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);403 let collection = <CollectionHandle<T>>::try_get(collection_id)?;404 collection.check_is_internal()?;405406 <PalletCommon<T>>::toggle_allowlist(407 &collection,408 &sender,409 &address,410 true,411 )?;412413 Self::deposit_event(Event::<T>::AllowListAddressAdded(414 collection_id,415 address416 ));417418 Ok(())419 }420421 422 423 424 425 426 427 428 429 430 431 432 #[weight = <SelfWeightOf<T>>::remove_from_allow_list()]433 #[transactional]434 pub fn remove_from_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{435436 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);437 let collection = <CollectionHandle<T>>::try_get(collection_id)?;438 collection.check_is_internal()?;439440 <PalletCommon<T>>::toggle_allowlist(441 &collection,442 &sender,443 &address,444 false,445 )?;446447 <Pallet<T>>::deposit_event(Event::<T>::AllowListAddressRemoved(448 collection_id,449 address450 ));451452 Ok(())453 }454455 456 457 458 459 460 461 462 463 464 465 #[weight = <SelfWeightOf<T>>::change_collection_owner()]466 #[transactional]467 pub fn change_collection_owner(origin, collection_id: CollectionId, new_owner: T::AccountId) -> DispatchResult {468469 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);470471 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;472 target_collection.check_is_internal()?;473 target_collection.check_is_owner(&sender)?;474475 target_collection.owner = new_owner.clone();476 <Pallet<T>>::deposit_event(Event::<T>::CollectionOwnedChanged(477 collection_id,478 new_owner479 ));480481 target_collection.save()482 }483484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 #[weight = <SelfWeightOf<T>>::add_collection_admin()]501 #[transactional]502 pub fn add_collection_admin(origin, collection_id: CollectionId, new_admin: T::CrossAccountId) -> DispatchResult {503 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);504 let collection = <CollectionHandle<T>>::try_get(collection_id)?;505 collection.check_is_internal()?;506507 <Pallet<T>>::deposit_event(Event::<T>::CollectionAdminAdded(508 collection_id,509 new_admin.clone()510 ));511512 <PalletCommon<T>>::toggle_admin(&collection, &sender, &new_admin, true)513 }514515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 #[weight = <SelfWeightOf<T>>::remove_collection_admin()]530 #[transactional]531 pub fn remove_collection_admin(origin, collection_id: CollectionId, account_id: T::CrossAccountId) -> DispatchResult {532 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);533 let collection = <CollectionHandle<T>>::try_get(collection_id)?;534 collection.check_is_internal()?;535536 <Pallet<T>>::deposit_event(Event::<T>::CollectionAdminRemoved(537 collection_id,538 account_id.clone()539 ));540541 <PalletCommon<T>>::toggle_admin(&collection, &sender, &account_id, false)542 }543544 545 546 547 548 549 550 551 552 553 554 555 556 557 #[weight = <SelfWeightOf<T>>::set_collection_sponsor()]558 #[transactional]559 pub fn set_collection_sponsor(origin, collection_id: CollectionId, new_sponsor: T::AccountId) -> DispatchResult {560 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);561562 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;563 target_collection.check_is_owner_or_admin(&sender)?;564 target_collection.check_is_internal()?;565566 target_collection.set_sponsor(new_sponsor.clone())?;567568 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorSet(569 collection_id,570 new_sponsor571 ));572573 target_collection.save()574 }575576 577 578 579 580 581 582 583 584 585 586 587 588 589 #[weight = <SelfWeightOf<T>>::confirm_sponsorship()]590 #[transactional]591 pub fn confirm_sponsorship(origin, collection_id: CollectionId) -> DispatchResult {592 let sender = ensure_signed(origin)?;593594 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;595 target_collection.check_is_internal()?;596 ensure!(597 target_collection.confirm_sponsorship(&sender)?,598 Error::<T>::ConfirmUnsetSponsorFail599 );600601 <Pallet<T>>::deposit_event(Event::<T>::SponsorshipConfirmed(602 collection_id,603 sender604 ));605606 target_collection.save()607 }608609 610 611 612 613 614 615 616 617 618 #[weight = <SelfWeightOf<T>>::remove_collection_sponsor()]619 #[transactional]620 pub fn remove_collection_sponsor(origin, collection_id: CollectionId) -> DispatchResult {621 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);622623 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;624 target_collection.check_is_internal()?;625 target_collection.check_is_owner(&sender)?;626627 target_collection.sponsorship = SponsorshipState::Disabled;628629 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorRemoved(630 collection_id631 ));632 target_collection.save()633 }634635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 #[weight = T::CommonWeightInfo::create_item()]654 #[transactional]655 pub fn create_item(origin, collection_id: CollectionId, owner: T::CrossAccountId, data: CreateItemData) -> DispatchResultWithPostInfo {656 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);657 let budget = budget::Value::new(NESTING_BUDGET);658659 dispatch_tx::<T, _>(collection_id, |d| d.create_item(sender, owner, data, &budget))660 }661662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 #[weight = T::CommonWeightInfo::create_multiple_items(&items_data)]681 #[transactional]682 pub fn create_multiple_items(origin, collection_id: CollectionId, owner: T::CrossAccountId, items_data: Vec<CreateItemData>) -> DispatchResultWithPostInfo {683 ensure!(!items_data.is_empty(), Error::<T>::EmptyArgument);684 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);685 let budget = budget::Value::new(NESTING_BUDGET);686687 dispatch_tx::<T, _>(collection_id, |d| d.create_multiple_items(sender, owner, items_data, &budget))688 }689690 691 692 693 694 695 696 697 698 699 700 701 702 #[weight = T::CommonWeightInfo::set_collection_properties(properties.len() as u32)]703 #[transactional]704 pub fn set_collection_properties(705 origin,706 collection_id: CollectionId,707 properties: Vec<Property>708 ) -> DispatchResultWithPostInfo {709 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);710711 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);712713 dispatch_tx::<T, _>(collection_id, |d| d.set_collection_properties(sender, properties))714 }715716 717 718 719 720 721 722 723 724 725 726 727 728 #[weight = T::CommonWeightInfo::delete_collection_properties(property_keys.len() as u32)]729 #[transactional]730 pub fn delete_collection_properties(731 origin,732 collection_id: CollectionId,733 property_keys: Vec<PropertyKey>,734 ) -> DispatchResultWithPostInfo {735 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);736737 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);738739 dispatch_tx::<T, _>(collection_id, |d| d.delete_collection_properties(&sender, property_keys))740 }741742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 #[weight = T::CommonWeightInfo::set_token_properties(properties.len() as u32)]761 #[transactional]762 pub fn set_token_properties(763 origin,764 collection_id: CollectionId,765 token_id: TokenId,766 properties: Vec<Property>767 ) -> DispatchResultWithPostInfo {768 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);769770 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);771 let budget = budget::Value::new(NESTING_BUDGET);772773 dispatch_tx::<T, _>(collection_id, |d| d.set_token_properties(sender, token_id, properties, &budget))774 }775776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 #[weight = T::CommonWeightInfo::delete_token_properties(property_keys.len() as u32)]792 #[transactional]793 pub fn delete_token_properties(794 origin,795 collection_id: CollectionId,796 token_id: TokenId,797 property_keys: Vec<PropertyKey>798 ) -> DispatchResultWithPostInfo {799 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);800801 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);802 let budget = budget::Value::new(NESTING_BUDGET);803804 dispatch_tx::<T, _>(collection_id, |d| d.delete_token_properties(sender, token_id, property_keys, &budget))805 }806807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 #[weight = T::CommonWeightInfo::set_token_property_permissions(property_permissions.len() as u32)]823 #[transactional]824 pub fn set_token_property_permissions(825 origin,826 collection_id: CollectionId,827 property_permissions: Vec<PropertyKeyPermission>,828 ) -> DispatchResultWithPostInfo {829 ensure!(!property_permissions.is_empty(), Error::<T>::EmptyArgument);830831 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);832833 dispatch_tx::<T, _>(collection_id, |d| d.set_token_property_permissions(&sender, property_permissions))834 }835836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 #[weight = T::CommonWeightInfo::create_multiple_items_ex(&data)]852 #[transactional]853 pub fn create_multiple_items_ex(origin, collection_id: CollectionId, data: CreateItemExData<T::CrossAccountId>) -> DispatchResultWithPostInfo {854 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);855 let budget = budget::Value::new(NESTING_BUDGET);856857 dispatch_tx::<T, _>(collection_id, |d| d.create_multiple_items_ex(sender, data, &budget))858 }859860 861 862 863 864 865 866 867 868 869 870 #[weight = <SelfWeightOf<T>>::set_transfers_enabled_flag()]871 #[transactional]872 pub fn set_transfers_enabled_flag(origin, collection_id: CollectionId, value: bool) -> DispatchResult {873 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);874 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;875 target_collection.check_is_internal()?;876 target_collection.check_is_owner(&sender)?;877878 879880 target_collection.limits.transfers_enabled = Some(value);881 target_collection.save()882 }883884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 #[weight = T::CommonWeightInfo::burn_item()]901 #[transactional]902 pub fn burn_item(origin, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {903 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);904905 let post_info = dispatch_tx::<T, _>(collection_id, |d| d.burn_item(sender, item_id, value))?;906 if value == 1 {907 <NftTransferBasket<T>>::remove(collection_id, item_id);908 <NftApproveBasket<T>>::remove(collection_id, item_id);909 }910 911 912 913 Ok(post_info)914 }915916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 #[weight = T::CommonWeightInfo::burn_from()]940 #[transactional]941 pub fn burn_from(origin, collection_id: CollectionId, from: T::CrossAccountId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {942 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);943 let budget = budget::Value::new(NESTING_BUDGET);944945 dispatch_tx::<T, _>(collection_id, |d| d.burn_from(sender, from, item_id, value, &budget))946 }947948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 #[weight = T::CommonWeightInfo::transfer()]970 #[transactional]971 pub fn transfer(origin, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {972 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);973 let budget = budget::Value::new(NESTING_BUDGET);974975 dispatch_tx::<T, _>(collection_id, |d| d.transfer(sender, recipient, item_id, value, &budget))976 }977978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 #[weight = T::CommonWeightInfo::approve()]994 #[transactional]995 pub fn approve(origin, spender: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResultWithPostInfo {996 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);997998 dispatch_tx::<T, _>(collection_id, |d| d.approve(sender, spender, item_id, amount))999 }10001001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 #[weight = T::CommonWeightInfo::transfer_from()]1026 #[transactional]1027 pub fn transfer_from(origin, from: T::CrossAccountId, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128 ) -> DispatchResultWithPostInfo {1028 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1029 let budget = budget::Value::new(NESTING_BUDGET);10301031 dispatch_tx::<T, _>(collection_id, |d| d.transfer_from(sender, from, recipient, item_id, value, &budget))1032 }10331034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 #[weight = <SelfWeightOf<T>>::set_collection_limits()]1047 #[transactional]1048 pub fn set_collection_limits(1049 origin,1050 collection_id: CollectionId,1051 new_limit: CollectionLimits,1052 ) -> DispatchResult {1053 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1054 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1055 target_collection.check_is_internal()?;1056 target_collection.check_is_owner_or_admin(&sender)?;1057 let old_limit = &target_collection.limits;10581059 target_collection.limits = <PalletCommon<T>>::clamp_limits(target_collection.mode.clone(), &old_limit, new_limit)?;10601061 <Pallet<T>>::deposit_event(Event::<T>::CollectionLimitSet(1062 collection_id1063 ));10641065 target_collection.save()1066 }10671068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 #[weight = <SelfWeightOf<T>>::set_collection_limits()]1081 #[transactional]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 #[transactional]1115 pub fn repartition(1116 origin,1117 collection_id: CollectionId,1118 token_id: TokenId,1119 amount: u128,1120 ) -> DispatchResultWithPostInfo {1121 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1122 dispatch_tx::<T, _>(collection_id, |d| {1123 if let Some(refungible_extensions) = d.refungible_extensions() {1124 refungible_extensions.repartition(&sender, token_id, amount)1125 } else {1126 fail!(<Error<T>>::RepartitionCalledOnNonRefungibleCollection)1127 }1128 })1129 }1130 }1131}