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 377 378379 let _ = <NftTransferBasket<T>>::clear_prefix(collection_id, u32::MAX, None);380 let _ = <FungibleTransferBasket<T>>::clear_prefix(collection_id, u32::MAX, None);381 let _ = <ReFungibleTransferBasket<T>>::clear_prefix((collection_id,), u32::MAX, None);382383 let _ = <NftApproveBasket<T>>::clear_prefix(collection_id, u32::MAX, None);384 let _ = <FungibleApproveBasket<T>>::clear_prefix(collection_id, u32::MAX, None);385 let _ = <RefungibleApproveBasket<T>>::clear_prefix((collection_id,), u32::MAX, None);386387 Ok(())388 }389390 391 392 393 394 395 396 397 398 399 400 401 #[weight = <SelfWeightOf<T>>::add_to_allow_list()]402 #[transactional]403 pub fn add_to_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{404405 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);406 let collection = <CollectionHandle<T>>::try_get(collection_id)?;407 collection.check_is_internal()?;408409 <PalletCommon<T>>::toggle_allowlist(410 &collection,411 &sender,412 &address,413 true,414 )?;415416 Self::deposit_event(Event::<T>::AllowListAddressAdded(417 collection_id,418 address419 ));420421 Ok(())422 }423424 425 426 427 428 429 430 431 432 433 434 435 #[weight = <SelfWeightOf<T>>::remove_from_allow_list()]436 #[transactional]437 pub fn remove_from_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{438439 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);440 let collection = <CollectionHandle<T>>::try_get(collection_id)?;441 collection.check_is_internal()?;442443 <PalletCommon<T>>::toggle_allowlist(444 &collection,445 &sender,446 &address,447 false,448 )?;449450 <Pallet<T>>::deposit_event(Event::<T>::AllowListAddressRemoved(451 collection_id,452 address453 ));454455 Ok(())456 }457458 459 460 461 462 463 464 465 466 467 468 #[weight = <SelfWeightOf<T>>::change_collection_owner()]469 #[transactional]470 pub fn change_collection_owner(origin, collection_id: CollectionId, new_owner: T::AccountId) -> DispatchResult {471472 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);473474 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;475 target_collection.check_is_internal()?;476 target_collection.check_is_owner(&sender)?;477478 target_collection.owner = new_owner.clone();479 <Pallet<T>>::deposit_event(Event::<T>::CollectionOwnedChanged(480 collection_id,481 new_owner482 ));483484 target_collection.save()485 }486487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 #[weight = <SelfWeightOf<T>>::add_collection_admin()]504 #[transactional]505 pub fn add_collection_admin(origin, collection_id: CollectionId, new_admin: T::CrossAccountId) -> DispatchResult {506 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);507 let collection = <CollectionHandle<T>>::try_get(collection_id)?;508 collection.check_is_internal()?;509510 <Pallet<T>>::deposit_event(Event::<T>::CollectionAdminAdded(511 collection_id,512 new_admin.clone()513 ));514515 <PalletCommon<T>>::toggle_admin(&collection, &sender, &new_admin, true)516 }517518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 #[weight = <SelfWeightOf<T>>::remove_collection_admin()]533 #[transactional]534 pub fn remove_collection_admin(origin, collection_id: CollectionId, account_id: T::CrossAccountId) -> DispatchResult {535 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);536 let collection = <CollectionHandle<T>>::try_get(collection_id)?;537 collection.check_is_internal()?;538539 <Pallet<T>>::deposit_event(Event::<T>::CollectionAdminRemoved(540 collection_id,541 account_id.clone()542 ));543544 <PalletCommon<T>>::toggle_admin(&collection, &sender, &account_id, false)545 }546547 548 549 550 551 552 553 554 555 556 557 558 559 560 #[weight = <SelfWeightOf<T>>::set_collection_sponsor()]561 #[transactional]562 pub fn set_collection_sponsor(origin, collection_id: CollectionId, new_sponsor: T::AccountId) -> DispatchResult {563 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);564565 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;566 target_collection.check_is_owner_or_admin(&sender)?;567 target_collection.check_is_internal()?;568569 target_collection.set_sponsor(new_sponsor.clone())?;570571 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorSet(572 collection_id,573 new_sponsor574 ));575576 target_collection.save()577 }578579 580 581 582 583 584 585 586 587 588 589 590 591 592 #[weight = <SelfWeightOf<T>>::confirm_sponsorship()]593 #[transactional]594 pub fn confirm_sponsorship(origin, collection_id: CollectionId) -> DispatchResult {595 let sender = ensure_signed(origin)?;596597 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;598 target_collection.check_is_internal()?;599 ensure!(600 target_collection.confirm_sponsorship(&sender)?,601 Error::<T>::ConfirmUnsetSponsorFail602 );603604 <Pallet<T>>::deposit_event(Event::<T>::SponsorshipConfirmed(605 collection_id,606 sender607 ));608609 target_collection.save()610 }611612 613 614 615 616 617 618 619 620 621 #[weight = <SelfWeightOf<T>>::remove_collection_sponsor()]622 #[transactional]623 pub fn remove_collection_sponsor(origin, collection_id: CollectionId) -> DispatchResult {624 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);625626 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;627 target_collection.check_is_internal()?;628 target_collection.check_is_owner(&sender)?;629630 target_collection.sponsorship = SponsorshipState::Disabled;631632 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorRemoved(633 collection_id634 ));635 target_collection.save()636 }637638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 #[weight = T::CommonWeightInfo::create_item()]657 #[transactional]658 pub fn create_item(origin, collection_id: CollectionId, owner: T::CrossAccountId, data: CreateItemData) -> DispatchResultWithPostInfo {659 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);660 let budget = budget::Value::new(NESTING_BUDGET);661662 dispatch_tx::<T, _>(collection_id, |d| d.create_item(sender, owner, data, &budget))663 }664665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 #[weight = T::CommonWeightInfo::create_multiple_items(&items_data)]684 #[transactional]685 pub fn create_multiple_items(origin, collection_id: CollectionId, owner: T::CrossAccountId, items_data: Vec<CreateItemData>) -> DispatchResultWithPostInfo {686 ensure!(!items_data.is_empty(), Error::<T>::EmptyArgument);687 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);688 let budget = budget::Value::new(NESTING_BUDGET);689690 dispatch_tx::<T, _>(collection_id, |d| d.create_multiple_items(sender, owner, items_data, &budget))691 }692693 694 695 696 697 698 699 700 701 702 703 704 705 #[weight = T::CommonWeightInfo::set_collection_properties(properties.len() as u32)]706 #[transactional]707 pub fn set_collection_properties(708 origin,709 collection_id: CollectionId,710 properties: Vec<Property>711 ) -> DispatchResultWithPostInfo {712 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);713714 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);715716 dispatch_tx::<T, _>(collection_id, |d| d.set_collection_properties(sender, properties))717 }718719 720 721 722 723 724 725 726 727 728 729 730 731 #[weight = T::CommonWeightInfo::delete_collection_properties(property_keys.len() as u32)]732 #[transactional]733 pub fn delete_collection_properties(734 origin,735 collection_id: CollectionId,736 property_keys: Vec<PropertyKey>,737 ) -> DispatchResultWithPostInfo {738 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);739740 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);741742 dispatch_tx::<T, _>(collection_id, |d| d.delete_collection_properties(&sender, property_keys))743 }744745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 #[weight = T::CommonWeightInfo::set_token_properties(properties.len() as u32)]764 #[transactional]765 pub fn set_token_properties(766 origin,767 collection_id: CollectionId,768 token_id: TokenId,769 properties: Vec<Property>770 ) -> DispatchResultWithPostInfo {771 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);772773 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);774 let budget = budget::Value::new(NESTING_BUDGET);775776 dispatch_tx::<T, _>(collection_id, |d| d.set_token_properties(sender, token_id, properties, &budget))777 }778779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 #[weight = T::CommonWeightInfo::delete_token_properties(property_keys.len() as u32)]795 #[transactional]796 pub fn delete_token_properties(797 origin,798 collection_id: CollectionId,799 token_id: TokenId,800 property_keys: Vec<PropertyKey>801 ) -> DispatchResultWithPostInfo {802 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);803804 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);805 let budget = budget::Value::new(NESTING_BUDGET);806807 dispatch_tx::<T, _>(collection_id, |d| d.delete_token_properties(sender, token_id, property_keys, &budget))808 }809810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 #[weight = T::CommonWeightInfo::set_token_property_permissions(property_permissions.len() as u32)]826 #[transactional]827 pub fn set_token_property_permissions(828 origin,829 collection_id: CollectionId,830 property_permissions: Vec<PropertyKeyPermission>,831 ) -> DispatchResultWithPostInfo {832 ensure!(!property_permissions.is_empty(), Error::<T>::EmptyArgument);833834 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);835836 dispatch_tx::<T, _>(collection_id, |d| d.set_token_property_permissions(&sender, property_permissions))837 }838839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 #[weight = T::CommonWeightInfo::create_multiple_items_ex(&data)]855 #[transactional]856 pub fn create_multiple_items_ex(origin, collection_id: CollectionId, data: CreateItemExData<T::CrossAccountId>) -> DispatchResultWithPostInfo {857 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);858 let budget = budget::Value::new(NESTING_BUDGET);859860 dispatch_tx::<T, _>(collection_id, |d| d.create_multiple_items_ex(sender, data, &budget))861 }862863 864 865 866 867 868 869 870 871 872 873 #[weight = <SelfWeightOf<T>>::set_transfers_enabled_flag()]874 #[transactional]875 pub fn set_transfers_enabled_flag(origin, collection_id: CollectionId, value: bool) -> DispatchResult {876 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);877 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;878 target_collection.check_is_internal()?;879 target_collection.check_is_owner(&sender)?;880881 882883 target_collection.limits.transfers_enabled = Some(value);884 target_collection.save()885 }886887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 #[weight = T::CommonWeightInfo::burn_item()]904 #[transactional]905 pub fn burn_item(origin, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {906 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);907908 let post_info = dispatch_tx::<T, _>(collection_id, |d| d.burn_item(sender, item_id, value))?;909 if value == 1 {910 <NftTransferBasket<T>>::remove(collection_id, item_id);911 <NftApproveBasket<T>>::remove(collection_id, item_id);912 }913 914 915 916 Ok(post_info)917 }918919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 #[weight = T::CommonWeightInfo::burn_from()]943 #[transactional]944 pub fn burn_from(origin, collection_id: CollectionId, from: T::CrossAccountId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {945 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);946 let budget = budget::Value::new(NESTING_BUDGET);947948 dispatch_tx::<T, _>(collection_id, |d| d.burn_from(sender, from, item_id, value, &budget))949 }950951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 #[weight = T::CommonWeightInfo::transfer()]973 #[transactional]974 pub fn transfer(origin, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {975 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);976 let budget = budget::Value::new(NESTING_BUDGET);977978 dispatch_tx::<T, _>(collection_id, |d| d.transfer(sender, recipient, item_id, value, &budget))979 }980981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 #[weight = T::CommonWeightInfo::approve()]997 #[transactional]998 pub fn approve(origin, spender: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResultWithPostInfo {999 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);10001001 dispatch_tx::<T, _>(collection_id, |d| d.approve(sender, spender, item_id, amount))1002 }10031004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 #[weight = T::CommonWeightInfo::transfer_from()]1029 #[transactional]1030 pub fn transfer_from(origin, from: T::CrossAccountId, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128 ) -> DispatchResultWithPostInfo {1031 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1032 let budget = budget::Value::new(NESTING_BUDGET);10331034 dispatch_tx::<T, _>(collection_id, |d| d.transfer_from(sender, from, recipient, item_id, value, &budget))1035 }10361037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 #[weight = <SelfWeightOf<T>>::set_collection_limits()]1050 #[transactional]1051 pub fn set_collection_limits(1052 origin,1053 collection_id: CollectionId,1054 new_limit: CollectionLimits,1055 ) -> DispatchResult {1056 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1057 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1058 target_collection.check_is_internal()?;1059 target_collection.check_is_owner_or_admin(&sender)?;1060 let old_limit = &target_collection.limits;10611062 target_collection.limits = <PalletCommon<T>>::clamp_limits(target_collection.mode.clone(), &old_limit, new_limit)?;10631064 <Pallet<T>>::deposit_event(Event::<T>::CollectionLimitSet(1065 collection_id1066 ));10671068 target_collection.save()1069 }10701071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 #[weight = <SelfWeightOf<T>>::set_collection_limits()]1084 #[transactional]1085 pub fn set_collection_permissions(1086 origin,1087 collection_id: CollectionId,1088 new_permission: CollectionPermissions,1089 ) -> DispatchResult {1090 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1091 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1092 target_collection.check_is_internal()?;1093 target_collection.check_is_owner_or_admin(&sender)?;1094 let old_limit = &target_collection.permissions;10951096 target_collection.permissions = <PalletCommon<T>>::clamp_permissions(target_collection.mode.clone(), &old_limit, new_permission)?;10971098 <Pallet<T>>::deposit_event(Event::<T>::CollectionPermissionSet(1099 collection_id1100 ));11011102 target_collection.save()1103 }11041105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 #[weight = T::RefungibleExtensionsWeightInfo::repartition()]1117 #[transactional]1118 pub fn repartition(1119 origin,1120 collection_id: CollectionId,1121 token_id: TokenId,1122 amount: u128,1123 ) -> DispatchResultWithPostInfo {1124 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1125 dispatch_tx::<T, _>(collection_id, |d| {1126 if let Some(refungible_extensions) = d.refungible_extensions() {1127 refungible_extensions.repartition(&sender, token_id, amount)1128 } else {1129 fail!(<Error<T>>::RepartitionCalledOnNonRefungibleCollection)1130 }1131 })1132 }1133 }1134}