git.delta.rocks / unique-network / refs/commits / 4e0b740f5ec1

difftreelog

source

pallets/rmrk-proxy/src/lib.rs7.3 KiBsourcehistory
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617#![cfg_attr(not(feature = "std"), no_std)]1819use frame_support::{pallet_prelude::*, transactional, BoundedVec, traits::ConstU32, dispatch::DispatchResult};20use frame_system::{pallet_prelude::*, ensure_signed};21use sp_runtime::DispatchError;22use up_data_structs::*;23use pallet_common::{Pallet as PalletCommon, Error as CommonError, CollectionHandle, CommonCollectionOperations};24use pallet_nonfungible::{Pallet as PalletNft, NonfungibleHandle};25use pallet_evm::account::CrossAccountId;2627pub use pallet::*;2829pub mod misc;3031use misc::*;3233#[frame_support::pallet]34pub mod pallet {35    use super::*;36    use pallet_evm::account;3738	#[pallet::config]39	pub trait Config: frame_system::Config40                    + pallet_common::Config41                    + pallet_nonfungible::Config42                    + account::Config {43		type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;44	}4546	#[pallet::pallet]47	#[pallet::generate_store(pub(super) trait Store)]48	pub struct Pallet<T>(_);4950	#[pallet::event]51	#[pallet::generate_deposit(pub(super) fn deposit_event)]52	pub enum Event<T: Config> {53        CollectionCreated {54			issuer: T::AccountId,55			collection_id: CollectionId,56		},57        CollectionDestroyed {58			issuer: T::AccountId,59			collection_id: CollectionId,60		},61        CollectionLocked {62			issuer: T::AccountId,63			collection_id: CollectionId,64		},65	}6667	#[pallet::error]68	pub enum Error<T> {69        /* Unique-specific events */70        CorruptedCollectionType,71        NotRmrkCollection,7273        /* RMRK compatible events */74        CollectionNotEmpty,75        NoAvailableCollectionId,76        CollectionUnknown,77	}7879	#[pallet::call]80	impl<T: Config> Pallet<T> {81        #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]82		#[transactional]83		pub fn create_collection(84			origin: OriginFor<T>,85			metadata: PropertyValue,86			max: Option<u32>,87			symbol: BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>,88		) -> DispatchResult {89            let sender = ensure_signed(origin)?;9091            let limits = max.map(|max| CollectionLimits {92                token_limit: Some(max),93                ..Default::default()94            });9596            let data = CreateCollectionData {97                limits,98                token_prefix: symbol,99                ..Default::default()100            };101102            let collection_id_res = <PalletNft<T>>::init_collection(sender.clone(), data);103104            if let Err(DispatchError::Arithmetic(_)) = &collection_id_res {105                return Err(<Error<T>>::NoAvailableCollectionId.into());106            }107108            let collection_id = collection_id_res?;109110            let collection = Self::get_nft_collection(collection_id)?.into_inner();111112            <PalletCommon<T>>::set_scoped_collection_properties(113                &collection,114                PropertyScope::Rmrk,115                [116                    rmrk_property!(Metadata, metadata),117                    rmrk_property!(CollectionType, CollectionType::Regular),118                ].into_iter()119            )?;120121            Self::deposit_event(Event::CollectionCreated { issuer: sender, collection_id });122123            Ok(())124        }125126        #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]127		#[transactional]128		pub fn destroy_collection(129			origin: OriginFor<T>,130			collection_id: CollectionId,131		) -> DispatchResult {132            let sender = ensure_signed(origin)?;133            let cross_sender = T::CrossAccountId::from_sub(sender.clone());134135            let collection = Self::get_nft_collection(collection_id)?;136137            Self::check_collection_type(collection_id, CollectionType::Regular)?;138139            ensure!(collection.total_supply() == 0, <Error<T>>::CollectionNotEmpty);140141            <PalletNft<T>>::destroy_collection(collection, &cross_sender)?;142143            Self::deposit_event(Event::CollectionDestroyed { issuer: sender, collection_id });144145            Ok(())146        }147148        #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]149		#[transactional]150		pub fn change_collection_issuer(151			origin: OriginFor<T>,152			collection_id: CollectionId,153			new_issuer: T::AccountId,154		) -> DispatchResult {155            let sender = ensure_signed(origin)?;156157            Self::change_collection_owner(158                collection_id,159                CollectionType::Regular,160                sender,161                new_issuer162            )?;163164            Ok(())165        }166167        #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]168		#[transactional]169		pub fn lock_collection(170			origin: OriginFor<T>,171			collection_id: CollectionId,172		) -> DispatchResult {173            let sender = ensure_signed(origin)?;174            let cross_sender = T::CrossAccountId::from_sub(sender.clone());175176            let collection = Self::get_nft_collection(collection_id)?;177            collection.check_is_owner(&cross_sender)?;178179            let token_count = collection.total_supply();180181            let mut collection = collection.into_inner();182            collection.limits.token_limit = Some(token_count);183            collection.save()?;184185			Self::deposit_event(Event::CollectionLocked { issuer: sender, collection_id });186187            Ok(())188        }189	}190}191192impl<T: Config> Pallet<T> {193    fn change_collection_owner(194        collection_id: CollectionId,195        collection_type: CollectionType,196        sender: T::AccountId,197        new_owner: T::AccountId,198    ) -> DispatchResult {199        let mut collection = Self::get_nft_collection(collection_id)?.into_inner();200        collection.check_is_owner(&T::CrossAccountId::from_sub(sender))?;201202        Self::check_collection_type(collection_id, collection_type)?;203204        collection.owner = new_owner;205        collection.save()206    }207208    fn get_nft_collection(collection_id: CollectionId) -> Result<NonfungibleHandle<T>, DispatchError> {209        let collection = <CollectionHandle<T>>::try_get(collection_id)210            .map_err(|_| <Error<T>>::CollectionUnknown)?211            .into_nft_collection()?;212213        Ok(collection)214    }215216    fn get_collection_type(collection_id: CollectionId) -> Result<CollectionType, DispatchError> {217        let collection_type: CollectionType = <PalletCommon<T>>::collection_properties(collection_id)218            .get(&rmrk_property!(CollectionType))219            .ok_or(<Error<T>>::NotRmrkCollection)?220            .try_into()221            .map_err(<Error<T>>::from)?;222223        Ok(collection_type)224    }225226    fn check_collection_type(collection_id: CollectionId, collection_type: CollectionType) -> DispatchResult {227        let actual_type = Self::get_collection_type(collection_id)?;228        ensure!(actual_type == collection_type, <CommonError<T>>::NoPermission);229230        Ok(())231    }232}