123456#![recursion_limit = "1024"]7#![cfg_attr(not(feature = "std"), no_std)]8#![allow(9 clippy::too_many_arguments,10 clippy::unnecessary_mut_passed,11 clippy::unused_unit12)]1314extern crate alloc;1516pub use serde::{Serialize, Deserialize};1718pub use frame_support::{19 construct_runtime, decl_module, decl_storage, decl_error, decl_event,20 dispatch::DispatchResult,21 ensure, fail, parameter_types,22 traits::{23 ExistenceRequirement, Get, Imbalance, KeyOwnerProofSystem, OnUnbalanced, Randomness,24 IsSubType, WithdrawReasons,25 },26 weights::{27 constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},28 DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,29 WeightToFeePolynomial, DispatchClass,30 },31 StorageValue, transactional,32 pallet_prelude::DispatchResultWithPostInfo,33};34use scale_info::TypeInfo;35use frame_system::{self as system, ensure_signed};36use sp_runtime::{sp_std::prelude::Vec};37use up_data_structs::{38 MAX_DECIMAL_POINTS, MAX_SPONSOR_TIMEOUT, MAX_TOKEN_OWNERSHIP, CUSTOM_DATA_LIMIT,39 VARIABLE_ON_CHAIN_SCHEMA_LIMIT, CONST_ON_CHAIN_SCHEMA_LIMIT, OFFCHAIN_SCHEMA_LIMIT,40 FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,41 NFT_SPONSOR_TRANSFER_TIMEOUT, AccessMode, Collection, CreateItemData, CollectionLimits,42 CollectionId, CollectionMode, TokenId, SchemaVersion, SponsorshipState, MetaUpdatePermission,43};44use pallet_common::{45 account::CrossAccountId, CollectionHandle, Pallet as PalletCommon, Error as CommonError,46 CommonWeightInfo,47};48use pallet_refungible::{Pallet as PalletRefungible, RefungibleHandle};49use pallet_fungible::{Pallet as PalletFungible, FungibleHandle};50use pallet_nonfungible::{Pallet as PalletNonfungible, NonfungibleHandle};5152#[cfg(test)]53mod mock;5455#[cfg(test)]56mod tests;5758mod eth;59mod sponsorship;60pub use sponsorship::UniqueSponsorshipHandler;61pub use eth::sponsoring::UniqueEthSponsorshipHandler;6263pub use eth::UniqueErcSupport;6465pub mod common;66use common::CommonWeights;67pub mod dispatch;68use dispatch::dispatch_call;6970#[cfg(feature = "runtime-benchmarks")]71mod benchmarking;72pub mod weights;73use weights::WeightInfo;7475decl_error! {76 77 pub enum Error for Module<T: Config> {78 79 CollectionDecimalPointLimitExceeded,80 81 ConfirmUnsetSponsorFail,82 83 EmptyArgument,84 85 CollectionLimitBoundsExceeded,86 87 OwnerPermissionsCantBeReverted,88 }89}9091pub trait Config:92 system::Config93 + pallet_evm_coder_substrate::Config94 + pallet_common::Config95 + pallet_nonfungible::Config96 + pallet_refungible::Config97 + pallet_fungible::Config98 + Sized99 + TypeInfo100{101 type Event: From<Event<Self>> + Into<<Self as frame_system::Config>::Event>;102103 104 type WeightInfo: WeightInfo;105}106107decl_event! {108 pub enum Event<T>109 where110 <T as frame_system::Config>::AccountId,111 <T as pallet_common::Config>::CrossAccountId,112 {113 114 115 116 117 118 CollectionSponsorRemoved(CollectionId),119120 121 122 123 124 125 126 127 CollectionAdminAdded(CollectionId, CrossAccountId),128129 130 131 132 133 134 135 136 CollectionOwnedChanged(CollectionId, AccountId),137138 139 140 141 142 143 144 145 CollectionSponsorSet(CollectionId, AccountId),146147 148 149 150 151 152 ConstOnChainSchemaSet(CollectionId),153154 155 156 157 158 159 160 161 SponsorshipConfirmed(CollectionId, AccountId),162163 164 165 166 167 168 169 170 CollectionAdminRemoved(CollectionId, CrossAccountId),171172 173 174 175 176 177 178 179 AllowListAddressRemoved(CollectionId, CrossAccountId),180181 182 183 184 185 186 187 188 AllowListAddressAdded(CollectionId, CrossAccountId),189190 191 192 193 194 195 CollectionLimitSet(CollectionId),196197 198 199 200 201 202 MintPermissionSet(CollectionId),203204 205 206 207 208 209 OffchainSchemaSet(CollectionId),210211 212 213 214 215 216 217 218 PublicAccessModeSet(CollectionId, AccessMode),219220 221 222 223 224 225 SchemaVersionSet(CollectionId),226227 228 229 230 231 232 VariableOnChainSchemaSet(CollectionId),233 }234}235236type SelfWeightOf<T> = <T as Config>::WeightInfo;237238239240241242243244245246247248249250251252253254255256257258259260decl_storage! {261 trait Store for Module<T: Config> as Unique {262263 264 265 ChainVersion: u64;266 267268 269 270 271 pub CreateItemBasket get(fn create_item_basket): map hasher(blake2_128_concat) (CollectionId, T::AccountId) => Option<T::BlockNumber>;272 273 pub NftTransferBasket get(fn nft_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;274 275 pub FungibleTransferBasket get(fn fungible_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;276 277 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>;278 279280 281 282 pub VariableMetaDataBasket get(fn variable_meta_data_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;283 284 pub NftApproveBasket get(fn nft_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;285 pub FungibleApproveBasket get(fn fungible_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;286 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>;287 }288}289290decl_module! {291 pub struct Module<T: Config> for enum Call292 where293 origin: T::Origin294 {295 type Error = Error<T>;296297 fn deposit_event() = default;298299 fn on_initialize(_now: T::BlockNumber) -> Weight {300 0301 }302303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 #[weight = <SelfWeightOf<T>>::create_collection()]320 #[transactional]321 pub fn create_collection(origin,322 collection_name: Vec<u16>,323 collection_description: Vec<u16>,324 token_prefix: Vec<u8>,325 mode: CollectionMode) -> DispatchResult {326327 328 let who = ensure_signed(origin)?;329330 331 let new_collection = Collection {332 owner: who,333 name: collection_name,334 mode: mode.clone(),335 mint_mode: false,336 access: AccessMode::Normal,337 description: collection_description,338 token_prefix,339 offchain_schema: Vec::new(),340 schema_version: SchemaVersion::ImageURL,341 sponsorship: SponsorshipState::Disabled,342 variable_on_chain_schema: Vec::new(),343 const_on_chain_schema: Vec::new(),344 limits: Default::default(),345 meta_update_permission: Default::default(),346 };347348 let _id = match mode {349 CollectionMode::NFT => {<PalletNonfungible<T>>::init_collection(new_collection)?},350 CollectionMode::Fungible(decimal_points) => {351 352 ensure!(decimal_points <= MAX_DECIMAL_POINTS, Error::<T>::CollectionDecimalPointLimitExceeded);353 <PalletFungible<T>>::init_collection(new_collection)?354 }355 CollectionMode::ReFungible => {356 <PalletRefungible<T>>::init_collection(new_collection)?357 }358 };359360 Ok(())361 }362363 364 365 366 367 368 369 370 371 372 #[weight = <SelfWeightOf<T>>::destroy_collection()]373 #[transactional]374 pub fn destroy_collection(origin, collection_id: CollectionId) -> DispatchResult {375 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);376377 let collection = <CollectionHandle<T>>::try_get(collection_id)?;378 collection.check_is_owner(&sender)?;379380 381382 match collection.mode {383 CollectionMode::ReFungible => PalletRefungible::destroy_collection(RefungibleHandle::cast(collection), &sender)?,384 CollectionMode::Fungible(_) => PalletFungible::destroy_collection(FungibleHandle::cast(collection), &sender)?,385 CollectionMode::NFT => PalletNonfungible::destroy_collection(NonfungibleHandle::cast(collection), &sender)?,386 }387388 <NftTransferBasket<T>>::remove_prefix(collection_id, None);389 <FungibleTransferBasket<T>>::remove_prefix(collection_id, None);390 <ReFungibleTransferBasket<T>>::remove_prefix((collection_id,), None);391392 <VariableMetaDataBasket<T>>::remove_prefix(collection_id, None);393 <NftApproveBasket<T>>::remove_prefix(collection_id, None);394 <FungibleApproveBasket<T>>::remove_prefix(collection_id, None);395 <RefungibleApproveBasket<T>>::remove_prefix((collection_id,), None);396397 Ok(())398 }399400 401 402 403 404 405 406 407 408 409 410 411 412 #[weight = <SelfWeightOf<T>>::add_to_allow_list()]413 #[transactional]414 pub fn add_to_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{415416 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);417 let collection = <CollectionHandle<T>>::try_get(collection_id)?;418419 <PalletCommon<T>>::toggle_allowlist(420 &collection,421 &sender,422 &address,423 true,424 )?;425426 Self::deposit_event(Event::<T>::AllowListAddressAdded(427 collection_id,428 address429 ));430431 Ok(())432 }433434 435 436 437 438 439 440 441 442 443 444 445 446 #[weight = <SelfWeightOf<T>>::remove_from_allow_list()]447 #[transactional]448 pub fn remove_from_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{449450 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);451 let collection = <CollectionHandle<T>>::try_get(collection_id)?;452453 <PalletCommon<T>>::toggle_allowlist(454 &collection,455 &sender,456 &address,457 false,458 )?;459460 <Pallet<T>>::deposit_event(Event::<T>::AllowListAddressRemoved(461 collection_id,462 address463 ));464465 Ok(())466 }467468 469 470 471 472 473 474 475 476 477 478 479 #[weight = <SelfWeightOf<T>>::set_public_access_mode()]480 #[transactional]481 pub fn set_public_access_mode(origin, collection_id: CollectionId, mode: AccessMode) -> DispatchResult482 {483 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);484485 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;486 target_collection.check_is_owner(&sender)?;487488 target_collection.access = mode.clone();489490 <Pallet<T>>::deposit_event(Event::<T>::PublicAccessModeSet(491 collection_id,492 mode493 ));494495 target_collection.save()496 }497498 499 500 501 502 503 504 505 506 507 508 509 510 511 #[weight = <SelfWeightOf<T>>::set_mint_permission()]512 #[transactional]513 pub fn set_mint_permission(origin, collection_id: CollectionId, mint_permission: bool) -> DispatchResult514 {515 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);516517 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;518 target_collection.check_is_owner(&sender)?;519520 target_collection.mint_mode = mint_permission;521522 <Pallet<T>>::deposit_event(Event::<T>::MintPermissionSet(523 collection_id524 ));525526 target_collection.save()527 }528529 530 531 532 533 534 535 536 537 538 539 540 #[weight = <SelfWeightOf<T>>::change_collection_owner()]541 #[transactional]542 pub fn change_collection_owner(origin, collection_id: CollectionId, new_owner: T::AccountId) -> DispatchResult {543544 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);545546 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;547 target_collection.check_is_owner(&sender)?;548549 target_collection.owner = new_owner.clone();550 <Pallet<T>>::deposit_event(Event::<T>::CollectionOwnedChanged(551 collection_id,552 new_owner553 ));554555 target_collection.save()556 }557558 559 560 561 562 563 564 565 566 567 568 569 570 571 #[weight = <SelfWeightOf<T>>::add_collection_admin()]572 #[transactional]573 pub fn add_collection_admin(origin, collection_id: CollectionId, new_admin_id: T::CrossAccountId) -> DispatchResult {574 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);575 let collection = <CollectionHandle<T>>::try_get(collection_id)?;576577 <Pallet<T>>::deposit_event(Event::<T>::CollectionAdminAdded(578 collection_id,579 new_admin_id.clone()580 ));581582 <PalletCommon<T>>::toggle_admin(&collection, &sender, &new_admin_id, true)583 }584585 586 587 588 589 590 591 592 593 594 595 596 597 #[weight = <SelfWeightOf<T>>::remove_collection_admin()]598 #[transactional]599 pub fn remove_collection_admin(origin, collection_id: CollectionId, account_id: T::CrossAccountId) -> DispatchResult {600 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);601 let collection = <CollectionHandle<T>>::try_get(collection_id)?;602603 <Pallet<T>>::deposit_event(Event::<T>::CollectionAdminRemoved(604 collection_id,605 account_id.clone()606 ));607608 <PalletCommon<T>>::toggle_admin(&collection, &sender, &account_id, false)609 }610611 612 613 614 615 616 617 618 619 620 #[weight = <SelfWeightOf<T>>::set_collection_sponsor()]621 #[transactional]622 pub fn set_collection_sponsor(origin, collection_id: CollectionId, new_sponsor: T::AccountId) -> DispatchResult {623 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);624625 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;626 target_collection.check_is_owner(&sender)?;627628 target_collection.sponsorship = SponsorshipState::Unconfirmed(new_sponsor.clone());629630 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorSet(631 collection_id,632 new_sponsor633 ));634635 target_collection.save()636 }637638 639 640 641 642 643 644 645 #[weight = <SelfWeightOf<T>>::confirm_sponsorship()]646 #[transactional]647 pub fn confirm_sponsorship(origin, collection_id: CollectionId) -> DispatchResult {648 let sender = ensure_signed(origin)?;649650 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;651 ensure!(652 target_collection.sponsorship.pending_sponsor() == Some(&sender),653 Error::<T>::ConfirmUnsetSponsorFail654 );655656 target_collection.sponsorship = SponsorshipState::Confirmed(sender.clone());657658 <Pallet<T>>::deposit_event(Event::<T>::SponsorshipConfirmed(659 collection_id,660 sender661 ));662663 target_collection.save()664 }665666 667 668 669 670 671 672 673 674 675 #[weight = <SelfWeightOf<T>>::remove_collection_sponsor()]676 #[transactional]677 pub fn remove_collection_sponsor(origin, collection_id: CollectionId) -> DispatchResult {678 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);679680 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;681 target_collection.check_is_owner(&sender)?;682683 target_collection.sponsorship = SponsorshipState::Disabled;684685 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorRemoved(686 collection_id687 ));688 target_collection.save()689 }690691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 #[weight = <CommonWeights<T>>::create_item()]710 #[transactional]711 pub fn create_item(origin, collection_id: CollectionId, owner: T::CrossAccountId, data: CreateItemData) -> DispatchResultWithPostInfo {712 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);713714 dispatch_call::<T, _>(collection_id, |d| d.create_item(sender, owner, data))715 }716717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 #[weight = <CommonWeights<T>>::create_multiple_items(items_data.len() as u32)]736 #[transactional]737 pub fn create_multiple_items(origin, collection_id: CollectionId, owner: T::CrossAccountId, items_data: Vec<CreateItemData>) -> DispatchResultWithPostInfo {738 ensure!(!items_data.is_empty(), Error::<T>::EmptyArgument);739 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);740741 dispatch_call::<T, _>(collection_id, |d| d.create_multiple_items(sender, owner, items_data))742 }743744 745746 747 748 749 750 751 752 753 754 755 756 757 #[weight = <SelfWeightOf<T>>::set_transfers_enabled_flag()]758 #[transactional]759 pub fn set_transfers_enabled_flag(origin, collection_id: CollectionId, value: bool) -> DispatchResult {760 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);761 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;762 target_collection.check_is_owner(&sender)?;763764 765766 target_collection.limits.transfers_enabled = Some(value);767 target_collection.save()768 }769770 771 772 773 774 775 776 777 778 779 780 781 782 783 #[weight = <CommonWeights<T>>::burn_item()]784 #[transactional]785 pub fn burn_item(origin, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {786 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);787788 let post_info = dispatch_call::<T, _>(collection_id, |d| d.burn_item(sender, item_id, value))?;789 if value == 1 {790 <NftTransferBasket<T>>::remove(collection_id, item_id);791 <NftApproveBasket<T>>::remove(collection_id, item_id);792 }793 794 795 796 Ok(post_info)797 }798799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 #[weight = <CommonWeights<T>>::burn_from()]816 #[transactional]817 pub fn burn_from(origin, collection_id: CollectionId, from: T::CrossAccountId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {818 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);819820 dispatch_call::<T, _>(collection_id, |d| d.burn_from(sender, from, item_id, value))821 }822823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 #[weight = <CommonWeights<T>>::transfer()]847 #[transactional]848 pub fn transfer(origin, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {849 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);850851 dispatch_call::<T, _>(collection_id, |d| d.transfer(sender, recipient, item_id, value))852 }853854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 #[weight = <CommonWeights<T>>::approve()]870 #[transactional]871 pub fn approve(origin, spender: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResultWithPostInfo {872 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);873874 dispatch_call::<T, _>(collection_id, |d| d.approve(sender, spender, item_id, amount))875 }876877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 #[weight = <CommonWeights<T>>::transfer_from()]897 #[transactional]898 pub fn transfer_from(origin, from: T::CrossAccountId, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128 ) -> DispatchResultWithPostInfo {899 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);900901 dispatch_call::<T, _>(collection_id, |d| d.transfer_from(sender, from, recipient, item_id, value))902 }903904 905 906 907 908 909 910 911 912 913 914 915 916 #[weight = <CommonWeights<T>>::set_variable_metadata(data.len() as u32)]917 #[transactional]918 pub fn set_variable_meta_data (919 origin,920 collection_id: CollectionId,921 item_id: TokenId,922 data: Vec<u8>923 ) -> DispatchResultWithPostInfo {924 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);925926 dispatch_call::<T, _>(collection_id, |d| d.set_variable_metadata(sender, item_id, data))927 }928929 930 931 932 933 934 935 936 937 938 939 940 #[weight = <SelfWeightOf<T>>::set_meta_update_permission_flag()]941 #[transactional]942 pub fn set_meta_update_permission_flag(origin, collection_id: CollectionId, value: MetaUpdatePermission) -> DispatchResult {943 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);944 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;945946 ensure!(947 target_collection.meta_update_permission != MetaUpdatePermission::None,948 <CommonError<T>>::MetadataFlagFrozen,949 );950 target_collection.check_is_owner(&sender)?;951952 target_collection.meta_update_permission = value;953954 target_collection.save()955 }956957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 #[weight = <SelfWeightOf<T>>::set_schema_version()]972 #[transactional]973 pub fn set_schema_version(974 origin,975 collection_id: CollectionId,976 version: SchemaVersion977 ) -> DispatchResult {978 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);979 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;980 target_collection.check_is_owner_or_admin(&sender)?;981 target_collection.schema_version = version;982983 <Pallet<T>>::deposit_event(Event::<T>::SchemaVersionSet(984 collection_id985 ));986987 target_collection.save()988 }989990 991 992 993 994 995 996 997 998 999 1000 1001 1002 #[weight = <SelfWeightOf<T>>::set_offchain_schema(schema.len() as u32)]1003 #[transactional]1004 pub fn set_offchain_schema(1005 origin,1006 collection_id: CollectionId,1007 schema: Vec<u8>1008 ) -> DispatchResult {1009 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1010 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1011 target_collection.check_is_owner_or_admin(&sender)?;10121013 1014 ensure!(schema.len() as u32 <= OFFCHAIN_SCHEMA_LIMIT, "");10151016 target_collection.offchain_schema = schema;10171018 <Pallet<T>>::deposit_event(Event::<T>::OffchainSchemaSet(1019 collection_id1020 ));10211022 target_collection.save()1023 }10241025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 #[weight = <SelfWeightOf<T>>::set_const_on_chain_schema(schema.len() as u32)]1038 #[transactional]1039 pub fn set_const_on_chain_schema (1040 origin,1041 collection_id: CollectionId,1042 schema: Vec<u8>1043 ) -> DispatchResult {1044 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1045 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1046 target_collection.check_is_owner_or_admin(&sender)?;10471048 1049 ensure!(schema.len() as u32 <= CONST_ON_CHAIN_SCHEMA_LIMIT, "");10501051 target_collection.const_on_chain_schema = schema;10521053 <Pallet<T>>::deposit_event(Event::<T>::ConstOnChainSchemaSet(1054 collection_id1055 ));10561057 target_collection.save()1058 }10591060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 #[weight = <SelfWeightOf<T>>::set_const_on_chain_schema(schema.len() as u32)]1073 #[transactional]1074 pub fn set_variable_on_chain_schema (1075 origin,1076 collection_id: CollectionId,1077 schema: Vec<u8>1078 ) -> DispatchResult {1079 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1080 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1081 target_collection.check_is_owner_or_admin(&sender)?;10821083 1084 ensure!(schema.len() as u32 <= VARIABLE_ON_CHAIN_SCHEMA_LIMIT, "");10851086 target_collection.variable_on_chain_schema = schema;10871088 <Pallet<T>>::deposit_event(Event::<T>::VariableOnChainSchemaSet(1089 collection_id1090 ));10911092 target_collection.save()1093 }10941095 #[weight = <SelfWeightOf<T>>::set_collection_limits()]1096 #[transactional]1097 pub fn set_collection_limits(1098 origin,1099 collection_id: CollectionId,1100 new_limit: CollectionLimits,1101 ) -> DispatchResult {1102 let mut new_limit = new_limit;1103 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1104 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1105 target_collection.check_is_owner(&sender)?;1106 let old_limit = &target_collection.limits;11071108 macro_rules! limit_default {1109 ($old:ident, $new:ident, $($field:ident $(($arg:expr))? => $check:expr),* $(,)?) => {{1110 $(1111 if let Some($new) = $new.$field {1112 let $old = $old.$field($($arg)?);1113 let _ = $new;1114 let _ = $old;1115 $check1116 } else {1117 $new.$field = $old.$field1118 }1119 )*1120 }};1121 }11221123 limit_default!(old_limit, new_limit,1124 account_token_ownership_limit => ensure!(1125 new_limit <= MAX_TOKEN_OWNERSHIP,1126 <Error<T>>::CollectionLimitBoundsExceeded,1127 ),1128 sponsor_transfer_timeout(match target_collection.mode {1129 CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,1130 CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,1131 CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,1132 }) => ensure!(1133 new_limit <= MAX_SPONSOR_TIMEOUT,1134 <Error<T>>::CollectionLimitBoundsExceeded,1135 ),1136 sponsored_data_size => ensure!(1137 new_limit <= CUSTOM_DATA_LIMIT,1138 <Error<T>>::CollectionLimitBoundsExceeded,1139 ),1140 token_limit => ensure!(1141 old_limit >= new_limit && new_limit > 0,1142 <CommonError<T>>::CollectionTokenLimitExceeded1143 ),1144 owner_can_transfer => ensure!(1145 old_limit || !new_limit,1146 <Error<T>>::OwnerPermissionsCantBeReverted,1147 ),1148 owner_can_destroy => ensure!(1149 old_limit || !new_limit,1150 <Error<T>>::OwnerPermissionsCantBeReverted,1151 ),1152 sponsored_data_rate_limit => {},1153 transfers_enabled => {},1154 );11551156 target_collection.limits = new_limit;11571158 <Pallet<T>>::deposit_event(Event::<T>::CollectionLimitSet(1159 collection_id1160 ));11611162 target_collection.save()1163 }1164 }1165}