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 let limit = None;289290 <VariableMetaDataBasket<T>>::remove_all(limit);291292 0293 }294295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 #[weight = <SelfWeightOf<T>>::create_collection()]317 #[transactional]318 #[deprecated]319 pub fn create_collection(320 origin,321 collection_name: BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>,322 collection_description: BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>,323 token_prefix: BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>,324 mode: CollectionMode325 ) -> DispatchResult {326 let data: CreateCollectionData<T::AccountId> = CreateCollectionData {327 name: collection_name,328 description: collection_description,329 token_prefix,330 mode,331 ..Default::default()332 };333 Self::create_collection_ex(origin, data)334 }335336 337 338 339 340 341 342 343 344 345 346 #[weight = <SelfWeightOf<T>>::create_collection()]347 #[transactional]348 pub fn create_collection_ex(origin, data: CreateCollectionData<T::AccountId>) -> DispatchResult {349 let sender = ensure_signed(origin)?;350351 352353 T::CollectionDispatch::create(T::CrossAccountId::from_sub(sender), data)?;354355 Ok(())356 }357358 359 360 361 362 363 364 365 366 367 #[weight = <SelfWeightOf<T>>::destroy_collection()]368 #[transactional]369 pub fn destroy_collection(origin, collection_id: CollectionId) -> DispatchResult {370 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);371 let collection = <CollectionHandle<T>>::try_get(collection_id)?;372 collection.check_is_internal()?;373374 375376 T::CollectionDispatch::destroy(sender, collection)?;377378 <NftTransferBasket<T>>::remove_prefix(collection_id, None);379 <FungibleTransferBasket<T>>::remove_prefix(collection_id, None);380 <ReFungibleTransferBasket<T>>::remove_prefix((collection_id,), None);381382 <NftApproveBasket<T>>::remove_prefix(collection_id, None);383 <FungibleApproveBasket<T>>::remove_prefix(collection_id, None);384 <RefungibleApproveBasket<T>>::remove_prefix((collection_id,), None);385386 Ok(())387 }388389 390 391 392 393 394 395 396 397 398 399 400 #[weight = <SelfWeightOf<T>>::add_to_allow_list()]401 #[transactional]402 pub fn add_to_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{403404 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);405 let collection = <CollectionHandle<T>>::try_get(collection_id)?;406 collection.check_is_internal()?;407408 <PalletCommon<T>>::toggle_allowlist(409 &collection,410 &sender,411 &address,412 true,413 )?;414415 Self::deposit_event(Event::<T>::AllowListAddressAdded(416 collection_id,417 address418 ));419420 Ok(())421 }422423 424 425 426 427 428 429 430 431 432 433 434 #[weight = <SelfWeightOf<T>>::remove_from_allow_list()]435 #[transactional]436 pub fn remove_from_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{437438 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);439 let collection = <CollectionHandle<T>>::try_get(collection_id)?;440 collection.check_is_internal()?;441442 <PalletCommon<T>>::toggle_allowlist(443 &collection,444 &sender,445 &address,446 false,447 )?;448449 <Pallet<T>>::deposit_event(Event::<T>::AllowListAddressRemoved(450 collection_id,451 address452 ));453454 Ok(())455 }456457 458 459 460 461 462 463 464 465 466 467 #[weight = <SelfWeightOf<T>>::change_collection_owner()]468 #[transactional]469 pub fn change_collection_owner(origin, collection_id: CollectionId, new_owner: T::AccountId) -> DispatchResult {470471 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);472473 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;474 target_collection.check_is_internal()?;475 target_collection.check_is_owner(&sender)?;476477 target_collection.owner = new_owner.clone();478 <Pallet<T>>::deposit_event(Event::<T>::CollectionOwnedChanged(479 collection_id,480 new_owner481 ));482483 target_collection.save()484 }485486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 #[weight = <SelfWeightOf<T>>::add_collection_admin()]503 #[transactional]504 pub fn add_collection_admin(origin, collection_id: CollectionId, new_admin: T::CrossAccountId) -> DispatchResult {505 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);506 let collection = <CollectionHandle<T>>::try_get(collection_id)?;507 collection.check_is_internal()?;508509 <Pallet<T>>::deposit_event(Event::<T>::CollectionAdminAdded(510 collection_id,511 new_admin.clone()512 ));513514 <PalletCommon<T>>::toggle_admin(&collection, &sender, &new_admin, true)515 }516517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 #[weight = <SelfWeightOf<T>>::remove_collection_admin()]532 #[transactional]533 pub fn remove_collection_admin(origin, collection_id: CollectionId, account_id: T::CrossAccountId) -> DispatchResult {534 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);535 let collection = <CollectionHandle<T>>::try_get(collection_id)?;536 collection.check_is_internal()?;537538 <Pallet<T>>::deposit_event(Event::<T>::CollectionAdminRemoved(539 collection_id,540 account_id.clone()541 ));542543 <PalletCommon<T>>::toggle_admin(&collection, &sender, &account_id, false)544 }545546 547 548 549 550 551 552 553 554 555 556 557 558 #[weight = <SelfWeightOf<T>>::set_collection_sponsor()]559 #[transactional]560 pub fn set_collection_sponsor(origin, collection_id: CollectionId, new_sponsor: T::AccountId) -> DispatchResult {561 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);562563 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;564 target_collection.check_is_owner_or_admin(&sender)?;565 target_collection.check_is_internal()?;566567 target_collection.set_sponsor(new_sponsor.clone())?;568569 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorSet(570 collection_id,571 new_sponsor572 ));573574 target_collection.save()575 }576577 578 579 580 581 582 583 584 585 586 587 588 589 590 #[weight = <SelfWeightOf<T>>::confirm_sponsorship()]591 #[transactional]592 pub fn confirm_sponsorship(origin, collection_id: CollectionId) -> DispatchResult {593 let sender = ensure_signed(origin)?;594595 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;596 target_collection.check_is_internal()?;597 ensure!(598 target_collection.confirm_sponsorship(&sender)?,599 Error::<T>::ConfirmUnsetSponsorFail600 );601602 <Pallet<T>>::deposit_event(Event::<T>::SponsorshipConfirmed(603 collection_id,604 sender605 ));606607 target_collection.save()608 }609610 611 612 613 614 615 616 617 618 619 #[weight = <SelfWeightOf<T>>::remove_collection_sponsor()]620 #[transactional]621 pub fn remove_collection_sponsor(origin, collection_id: CollectionId) -> DispatchResult {622 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);623624 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;625 target_collection.check_is_internal()?;626 target_collection.check_is_owner(&sender)?;627628 target_collection.sponsorship = SponsorshipState::Disabled;629630 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorRemoved(631 collection_id632 ));633 target_collection.save()634 }635636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 #[weight = T::CommonWeightInfo::create_item()]655 #[transactional]656 pub fn create_item(origin, collection_id: CollectionId, owner: T::CrossAccountId, data: CreateItemData) -> DispatchResultWithPostInfo {657 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);658 let budget = budget::Value::new(NESTING_BUDGET);659660 dispatch_tx::<T, _>(collection_id, |d| d.create_item(sender, owner, data, &budget))661 }662663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 #[weight = T::CommonWeightInfo::create_multiple_items(&items_data)]682 #[transactional]683 pub fn create_multiple_items(origin, collection_id: CollectionId, owner: T::CrossAccountId, items_data: Vec<CreateItemData>) -> DispatchResultWithPostInfo {684 ensure!(!items_data.is_empty(), Error::<T>::EmptyArgument);685 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);686 let budget = budget::Value::new(NESTING_BUDGET);687688 dispatch_tx::<T, _>(collection_id, |d| d.create_multiple_items(sender, owner, items_data, &budget))689 }690691 692 693 694 695 696 697 698 699 700 701 702 703 #[weight = T::CommonWeightInfo::set_collection_properties(properties.len() as u32)]704 #[transactional]705 pub fn set_collection_properties(706 origin,707 collection_id: CollectionId,708 properties: Vec<Property>709 ) -> DispatchResultWithPostInfo {710 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);711712 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);713714 dispatch_tx::<T, _>(collection_id, |d| d.set_collection_properties(sender, properties))715 }716717 718 719 720 721 722 723 724 725 726 727 728 729 #[weight = T::CommonWeightInfo::delete_collection_properties(property_keys.len() as u32)]730 #[transactional]731 pub fn delete_collection_properties(732 origin,733 collection_id: CollectionId,734 property_keys: Vec<PropertyKey>,735 ) -> DispatchResultWithPostInfo {736 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);737738 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);739740 dispatch_tx::<T, _>(collection_id, |d| d.delete_collection_properties(&sender, property_keys))741 }742743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 #[weight = T::CommonWeightInfo::set_token_properties(properties.len() as u32)]762 #[transactional]763 pub fn set_token_properties(764 origin,765 collection_id: CollectionId,766 token_id: TokenId,767 properties: Vec<Property>768 ) -> DispatchResultWithPostInfo {769 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);770771 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);772 let budget = budget::Value::new(NESTING_BUDGET);773774 dispatch_tx::<T, _>(collection_id, |d| d.set_token_properties(sender, token_id, properties, &budget))775 }776777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 #[weight = T::CommonWeightInfo::delete_token_properties(property_keys.len() as u32)]793 #[transactional]794 pub fn delete_token_properties(795 origin,796 collection_id: CollectionId,797 token_id: TokenId,798 property_keys: Vec<PropertyKey>799 ) -> DispatchResultWithPostInfo {800 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);801802 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);803 let budget = budget::Value::new(NESTING_BUDGET);804805 dispatch_tx::<T, _>(collection_id, |d| d.delete_token_properties(sender, token_id, property_keys, &budget))806 }807808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 #[weight = T::CommonWeightInfo::set_token_property_permissions(property_permissions.len() as u32)]824 #[transactional]825 pub fn set_token_property_permissions(826 origin,827 collection_id: CollectionId,828 property_permissions: Vec<PropertyKeyPermission>,829 ) -> DispatchResultWithPostInfo {830 ensure!(!property_permissions.is_empty(), Error::<T>::EmptyArgument);831832 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);833834 dispatch_tx::<T, _>(collection_id, |d| d.set_token_property_permissions(&sender, property_permissions))835 }836837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 #[weight = T::CommonWeightInfo::create_multiple_items_ex(&data)]853 #[transactional]854 pub fn create_multiple_items_ex(origin, collection_id: CollectionId, data: CreateItemExData<T::CrossAccountId>) -> DispatchResultWithPostInfo {855 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);856 let budget = budget::Value::new(NESTING_BUDGET);857858 dispatch_tx::<T, _>(collection_id, |d| d.create_multiple_items_ex(sender, data, &budget))859 }860861 862 863 864 865 866 867 868 869 870 871 #[weight = <SelfWeightOf<T>>::set_transfers_enabled_flag()]872 #[transactional]873 pub fn set_transfers_enabled_flag(origin, collection_id: CollectionId, value: bool) -> DispatchResult {874 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);875 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;876 target_collection.check_is_internal()?;877 target_collection.check_is_owner(&sender)?;878879 880881 target_collection.limits.transfers_enabled = Some(value);882 target_collection.save()883 }884885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 #[weight = T::CommonWeightInfo::burn_item()]902 #[transactional]903 pub fn burn_item(origin, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {904 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);905906 let post_info = dispatch_tx::<T, _>(collection_id, |d| d.burn_item(sender, item_id, value))?;907 if value == 1 {908 <NftTransferBasket<T>>::remove(collection_id, item_id);909 <NftApproveBasket<T>>::remove(collection_id, item_id);910 }911 912 913 914 Ok(post_info)915 }916917 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 #[weight = T::CommonWeightInfo::transfer_from()]1025 #[transactional]1026 pub fn transfer_from(origin, from: T::CrossAccountId, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128 ) -> DispatchResultWithPostInfo {1027 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1028 let budget = budget::Value::new(NESTING_BUDGET);10291030 dispatch_tx::<T, _>(collection_id, |d| d.transfer_from(sender, from, recipient, item_id, value, &budget))1031 }10321033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 #[weight = <SelfWeightOf<T>>::set_collection_limits()]1045 #[transactional]1046 pub fn set_collection_limits(1047 origin,1048 collection_id: CollectionId,1049 new_limit: CollectionLimits,1050 ) -> DispatchResult {1051 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1052 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1053 target_collection.check_is_internal()?;1054 target_collection.check_is_owner_or_admin(&sender)?;1055 let old_limit = &target_collection.limits;10561057 target_collection.limits = <PalletCommon<T>>::clamp_limits(target_collection.mode.clone(), &old_limit, new_limit)?;10581059 <Pallet<T>>::deposit_event(Event::<T>::CollectionLimitSet(1060 collection_id1061 ));10621063 target_collection.save()1064 }10651066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 #[weight = <SelfWeightOf<T>>::set_collection_limits()]1078 #[transactional]1079 pub fn set_collection_permissions(1080 origin,1081 collection_id: CollectionId,1082 new_permission: CollectionPermissions,1083 ) -> DispatchResult {1084 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1085 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1086 target_collection.check_is_internal()?;1087 target_collection.check_is_owner_or_admin(&sender)?;1088 let old_limit = &target_collection.permissions;10891090 target_collection.permissions = <PalletCommon<T>>::clamp_permissions(target_collection.mode.clone(), &old_limit, new_permission)?;10911092 <Pallet<T>>::deposit_event(Event::<T>::CollectionPermissionSet(1093 collection_id1094 ));10951096 target_collection.save()1097 }10981099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 #[weight = T::RefungibleExtensionsWeightInfo::repartition()]1111 #[transactional]1112 pub fn repartition(1113 origin,1114 collection_id: CollectionId,1115 token_id: TokenId,1116 amount: u128,1117 ) -> DispatchResultWithPostInfo {1118 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1119 dispatch_tx::<T, _>(collection_id, |d| {1120 if let Some(refungible_extensions) = d.refungible_extensions() {1121 refungible_extensions.repartition(&sender, token_id, amount)1122 } else {1123 fail!(<Error<T>>::RepartitionCalledOnNonRefungibleCollection)1124 }1125 })1126 }1127 }1128}