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 317 #[weight = <SelfWeightOf<T>>::create_collection()]318 #[transactional]319 #[deprecated(note = "`create_collection_ex` is more up-to-date and advanced, prefer it instead")]320 pub fn create_collection(321 origin,322 collection_name: BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>,323 collection_description: BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>,324 token_prefix: BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>,325 mode: CollectionMode326 ) -> DispatchResult {327 let data: CreateCollectionData<T::AccountId> = CreateCollectionData {328 name: collection_name,329 description: collection_description,330 token_prefix,331 mode,332 ..Default::default()333 };334 Self::create_collection_ex(origin, data)335 }336337 338 339 340 341 342 343 344 345 346 347 348 #[weight = <SelfWeightOf<T>>::create_collection()]349 #[transactional]350 pub fn create_collection_ex(origin, data: CreateCollectionData<T::AccountId>) -> DispatchResult {351 let sender = ensure_signed(origin)?;352353 354355 T::CollectionDispatch::create(T::CrossAccountId::from_sub(sender), data)?;356357 Ok(())358 }359360 361 362 363 364 365 366 367 368 369 #[weight = <SelfWeightOf<T>>::destroy_collection()]370 #[transactional]371 pub fn destroy_collection(origin, collection_id: CollectionId) -> DispatchResult {372 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);373 let collection = <CollectionHandle<T>>::try_get(collection_id)?;374 collection.check_is_internal()?;375376 377378 T::CollectionDispatch::destroy(sender, collection)?;379380 <NftTransferBasket<T>>::remove_prefix(collection_id, None);381 <FungibleTransferBasket<T>>::remove_prefix(collection_id, None);382 <ReFungibleTransferBasket<T>>::remove_prefix((collection_id,), None);383384 <NftApproveBasket<T>>::remove_prefix(collection_id, None);385 <FungibleApproveBasket<T>>::remove_prefix(collection_id, None);386 <RefungibleApproveBasket<T>>::remove_prefix((collection_id,), None);387388 Ok(())389 }390391 392 393 394 395 396 397 398 399 400 401 402 #[weight = <SelfWeightOf<T>>::add_to_allow_list()]403 #[transactional]404 pub fn add_to_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{405406 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);407 let collection = <CollectionHandle<T>>::try_get(collection_id)?;408 collection.check_is_internal()?;409410 <PalletCommon<T>>::toggle_allowlist(411 &collection,412 &sender,413 &address,414 true,415 )?;416417 Self::deposit_event(Event::<T>::AllowListAddressAdded(418 collection_id,419 address420 ));421422 Ok(())423 }424425 426 427 428 429 430 431 432 433 434 435 436 #[weight = <SelfWeightOf<T>>::remove_from_allow_list()]437 #[transactional]438 pub fn remove_from_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{439440 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);441 let collection = <CollectionHandle<T>>::try_get(collection_id)?;442 collection.check_is_internal()?;443444 <PalletCommon<T>>::toggle_allowlist(445 &collection,446 &sender,447 &address,448 false,449 )?;450451 <Pallet<T>>::deposit_event(Event::<T>::AllowListAddressRemoved(452 collection_id,453 address454 ));455456 Ok(())457 }458459 460 461 462 463 464 465 466 467 468 469 #[weight = <SelfWeightOf<T>>::change_collection_owner()]470 #[transactional]471 pub fn change_collection_owner(origin, collection_id: CollectionId, new_owner: T::AccountId) -> DispatchResult {472473 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);474475 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;476 target_collection.check_is_internal()?;477 target_collection.check_is_owner(&sender)?;478479 target_collection.owner = new_owner.clone();480 <Pallet<T>>::deposit_event(Event::<T>::CollectionOwnedChanged(481 collection_id,482 new_owner483 ));484485 target_collection.save()486 }487488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 #[weight = <SelfWeightOf<T>>::add_collection_admin()]505 #[transactional]506 pub fn add_collection_admin(origin, collection_id: CollectionId, new_admin: T::CrossAccountId) -> DispatchResult {507 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);508 let collection = <CollectionHandle<T>>::try_get(collection_id)?;509 collection.check_is_internal()?;510511 <Pallet<T>>::deposit_event(Event::<T>::CollectionAdminAdded(512 collection_id,513 new_admin.clone()514 ));515516 <PalletCommon<T>>::toggle_admin(&collection, &sender, &new_admin, true)517 }518519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 #[weight = <SelfWeightOf<T>>::remove_collection_admin()]534 #[transactional]535 pub fn remove_collection_admin(origin, collection_id: CollectionId, account_id: T::CrossAccountId) -> DispatchResult {536 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);537 let collection = <CollectionHandle<T>>::try_get(collection_id)?;538 collection.check_is_internal()?;539540 <Pallet<T>>::deposit_event(Event::<T>::CollectionAdminRemoved(541 collection_id,542 account_id.clone()543 ));544545 <PalletCommon<T>>::toggle_admin(&collection, &sender, &account_id, false)546 }547548 549 550 551 552 553 554 555 556 557 558 559 560 561 #[weight = <SelfWeightOf<T>>::set_collection_sponsor()]562 #[transactional]563 pub fn set_collection_sponsor(origin, collection_id: CollectionId, new_sponsor: T::AccountId) -> DispatchResult {564 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);565566 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;567 target_collection.check_is_owner_or_admin(&sender)?;568 target_collection.check_is_internal()?;569570 target_collection.set_sponsor(new_sponsor.clone())?;571572 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorSet(573 collection_id,574 new_sponsor575 ));576577 target_collection.save()578 }579580 581 582 583 584 585 586 587 588 589 590 591 592 593 #[weight = <SelfWeightOf<T>>::confirm_sponsorship()]594 #[transactional]595 pub fn confirm_sponsorship(origin, collection_id: CollectionId) -> DispatchResult {596 let sender = ensure_signed(origin)?;597598 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;599 target_collection.check_is_internal()?;600 ensure!(601 target_collection.confirm_sponsorship(&sender)?,602 Error::<T>::ConfirmUnsetSponsorFail603 );604605 <Pallet<T>>::deposit_event(Event::<T>::SponsorshipConfirmed(606 collection_id,607 sender608 ));609610 target_collection.save()611 }612613 614 615 616 617 618 619 620 621 622 #[weight = <SelfWeightOf<T>>::remove_collection_sponsor()]623 #[transactional]624 pub fn remove_collection_sponsor(origin, collection_id: CollectionId) -> DispatchResult {625 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);626627 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;628 target_collection.check_is_internal()?;629 target_collection.check_is_owner(&sender)?;630631 target_collection.sponsorship = SponsorshipState::Disabled;632633 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorRemoved(634 collection_id635 ));636 target_collection.save()637 }638639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 #[weight = T::CommonWeightInfo::create_item()]658 #[transactional]659 pub fn create_item(origin, collection_id: CollectionId, owner: T::CrossAccountId, data: CreateItemData) -> DispatchResultWithPostInfo {660 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);661 let budget = budget::Value::new(NESTING_BUDGET);662663 dispatch_tx::<T, _>(collection_id, |d| d.create_item(sender, owner, data, &budget))664 }665666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 #[weight = T::CommonWeightInfo::create_multiple_items(&items_data)]685 #[transactional]686 pub fn create_multiple_items(origin, collection_id: CollectionId, owner: T::CrossAccountId, items_data: Vec<CreateItemData>) -> DispatchResultWithPostInfo {687 ensure!(!items_data.is_empty(), Error::<T>::EmptyArgument);688 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);689 let budget = budget::Value::new(NESTING_BUDGET);690691 dispatch_tx::<T, _>(collection_id, |d| d.create_multiple_items(sender, owner, items_data, &budget))692 }693694 695 696 697 698 699 700 701 702 703 704 705 706 #[weight = T::CommonWeightInfo::set_collection_properties(properties.len() as u32)]707 #[transactional]708 pub fn set_collection_properties(709 origin,710 collection_id: CollectionId,711 properties: Vec<Property>712 ) -> DispatchResultWithPostInfo {713 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);714715 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);716717 dispatch_tx::<T, _>(collection_id, |d| d.set_collection_properties(sender, properties))718 }719720 721 722 723 724 725 726 727 728 729 730 731 732 #[weight = T::CommonWeightInfo::delete_collection_properties(property_keys.len() as u32)]733 #[transactional]734 pub fn delete_collection_properties(735 origin,736 collection_id: CollectionId,737 property_keys: Vec<PropertyKey>,738 ) -> DispatchResultWithPostInfo {739 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);740741 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);742743 dispatch_tx::<T, _>(collection_id, |d| d.delete_collection_properties(&sender, property_keys))744 }745746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 #[weight = T::CommonWeightInfo::set_token_properties(properties.len() as u32)]765 #[transactional]766 pub fn set_token_properties(767 origin,768 collection_id: CollectionId,769 token_id: TokenId,770 properties: Vec<Property>771 ) -> DispatchResultWithPostInfo {772 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);773774 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);775 let budget = budget::Value::new(NESTING_BUDGET);776777 dispatch_tx::<T, _>(collection_id, |d| d.set_token_properties(sender, token_id, properties, &budget))778 }779780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 #[weight = T::CommonWeightInfo::delete_token_properties(property_keys.len() as u32)]796 #[transactional]797 pub fn delete_token_properties(798 origin,799 collection_id: CollectionId,800 token_id: TokenId,801 property_keys: Vec<PropertyKey>802 ) -> DispatchResultWithPostInfo {803 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);804805 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);806 let budget = budget::Value::new(NESTING_BUDGET);807808 dispatch_tx::<T, _>(collection_id, |d| d.delete_token_properties(sender, token_id, property_keys, &budget))809 }810811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 #[weight = T::CommonWeightInfo::set_token_property_permissions(property_permissions.len() as u32)]827 #[transactional]828 pub fn set_token_property_permissions(829 origin,830 collection_id: CollectionId,831 property_permissions: Vec<PropertyKeyPermission>,832 ) -> DispatchResultWithPostInfo {833 ensure!(!property_permissions.is_empty(), Error::<T>::EmptyArgument);834835 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);836837 dispatch_tx::<T, _>(collection_id, |d| d.set_token_property_permissions(&sender, property_permissions))838 }839840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 #[weight = T::CommonWeightInfo::create_multiple_items_ex(&data)]856 #[transactional]857 pub fn create_multiple_items_ex(origin, collection_id: CollectionId, data: CreateItemExData<T::CrossAccountId>) -> DispatchResultWithPostInfo {858 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);859 let budget = budget::Value::new(NESTING_BUDGET);860861 dispatch_tx::<T, _>(collection_id, |d| d.create_multiple_items_ex(sender, data, &budget))862 }863864 865 866 867 868 869 870 871 872 873 874 #[weight = <SelfWeightOf<T>>::set_transfers_enabled_flag()]875 #[transactional]876 pub fn set_transfers_enabled_flag(origin, collection_id: CollectionId, value: bool) -> DispatchResult {877 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);878 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;879 target_collection.check_is_internal()?;880 target_collection.check_is_owner(&sender)?;881882 883884 target_collection.limits.transfers_enabled = Some(value);885 target_collection.save()886 }887888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 #[weight = T::CommonWeightInfo::burn_item()]905 #[transactional]906 pub fn burn_item(origin, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {907 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);908909 let post_info = dispatch_tx::<T, _>(collection_id, |d| d.burn_item(sender, item_id, value))?;910 if value == 1 {911 <NftTransferBasket<T>>::remove(collection_id, item_id);912 <NftApproveBasket<T>>::remove(collection_id, item_id);913 }914 915 916 917 Ok(post_info)918 }919920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 #[weight = T::CommonWeightInfo::burn_from()]944 #[transactional]945 pub fn burn_from(origin, collection_id: CollectionId, from: T::CrossAccountId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {946 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);947 let budget = budget::Value::new(NESTING_BUDGET);948949 dispatch_tx::<T, _>(collection_id, |d| d.burn_from(sender, from, item_id, value, &budget))950 }951952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 #[weight = T::CommonWeightInfo::transfer()]974 #[transactional]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 #[transactional]999 pub fn approve(origin, spender: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResultWithPostInfo {1000 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);10011002 dispatch_tx::<T, _>(collection_id, |d| d.approve(sender, spender, item_id, amount))1003 }10041005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 #[weight = T::CommonWeightInfo::transfer_from()]1030 #[transactional]1031 pub fn transfer_from(origin, from: T::CrossAccountId, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128 ) -> DispatchResultWithPostInfo {1032 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1033 let budget = budget::Value::new(NESTING_BUDGET);10341035 dispatch_tx::<T, _>(collection_id, |d| d.transfer_from(sender, from, recipient, item_id, value, &budget))1036 }10371038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 #[weight = <SelfWeightOf<T>>::set_collection_limits()]1051 #[transactional]1052 pub fn set_collection_limits(1053 origin,1054 collection_id: CollectionId,1055 new_limit: CollectionLimits,1056 ) -> DispatchResult {1057 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1058 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1059 target_collection.check_is_internal()?;1060 target_collection.check_is_owner_or_admin(&sender)?;1061 let old_limit = &target_collection.limits;10621063 target_collection.limits = <PalletCommon<T>>::clamp_limits(target_collection.mode.clone(), &old_limit, new_limit)?;10641065 <Pallet<T>>::deposit_event(Event::<T>::CollectionLimitSet(1066 collection_id1067 ));10681069 target_collection.save()1070 }10711072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 #[weight = <SelfWeightOf<T>>::set_collection_limits()]1085 #[transactional]1086 pub fn set_collection_permissions(1087 origin,1088 collection_id: CollectionId,1089 new_permission: CollectionPermissions,1090 ) -> DispatchResult {1091 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1092 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1093 target_collection.check_is_internal()?;1094 target_collection.check_is_owner_or_admin(&sender)?;1095 let old_limit = &target_collection.permissions;10961097 target_collection.permissions = <PalletCommon<T>>::clamp_permissions(target_collection.mode.clone(), &old_limit, new_permission)?;10981099 <Pallet<T>>::deposit_event(Event::<T>::CollectionPermissionSet(1100 collection_id1101 ));11021103 target_collection.save()1104 }11051106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 #[weight = T::RefungibleExtensionsWeightInfo::repartition()]1118 #[transactional]1119 pub fn repartition(1120 origin,1121 collection_id: CollectionId,1122 token_id: TokenId,1123 amount: u128,1124 ) -> DispatchResultWithPostInfo {1125 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1126 dispatch_tx::<T, _>(collection_id, |d| {1127 if let Some(refungible_extensions) = d.refungible_extensions() {1128 refungible_extensions.repartition(&sender, token_id, amount)1129 } else {1130 fail!(<Error<T>>::RepartitionCalledOnNonRefungibleCollection)1131 }1132 })1133 }1134 }1135}