git.delta.rocks / unique-network / refs/commits / c652c1eecc65

difftreelog

source

pallets/foreign-assets/src/lib.rs8.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//! # Foreign assets18//!19//! - [`Config`]20//! - [`Call`]21//! - [`Pallet`]22//!23//! ## Overview24//!25//! The foreign assests pallet provides functions for:26//!27//! - Local and foreign assets management. The foreign assets can be updated without runtime upgrade.28//! - Bounds between asset and target collection for cross chain transfer and inner transfers.29//!30//! ## Overview31//!32//! Under construction3334#![cfg_attr(not(feature = "std"), no_std)]35#![allow(clippy::unused_unit)]3637use frame_support::{dispatch::DispatchResult, pallet_prelude::*, traits::EnsureOrigin, PalletId};38use frame_system::pallet_prelude::*;39use pallet_common::{40	dispatch::CollectionDispatch, erc::CrossAccountId, NATIVE_FUNGIBLE_COLLECTION_ID,41};42use sp_runtime::traits::AccountIdConversion;43use sp_std::{vec, vec::Vec};44// NOTE: MultiLocation is used in storages, we will need to do migration if upgrade the45// MultiLocation to the XCM v3.46use staging_xcm::{47	opaque::latest::{prelude::XcmError, Weight},48	v3::{prelude::*, MultiAsset, XcmContext},49};50use staging_xcm_executor::{51	traits::{TransactAsset, WeightTrader},52	Assets,53};54use up_data_structs::{55	CollectionId, CollectionMode, CollectionName, CreateCollectionData, PropertyKey, TokenId,56};5758pub mod weights;5960#[cfg(feature = "runtime-benchmarks")]61mod benchmarking;6263pub use module::*;64pub use weights::WeightInfo;6566#[frame_support::pallet]67pub mod module {68	use up_data_structs::{69		CollectionDescription, Property, PropertyKeyPermission, PropertyPermission,70	};7172	use super::*;7374	#[pallet::config]75	pub trait Config:76		frame_system::Config77		+ pallet_common::Config78		+ pallet_fungible::Config79		+ pallet_balances::Config80	{81		/// The overarching event type.82		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;8384		/// Origin for force registering of a foreign asset.85		type ForceRegisterOrigin: EnsureOrigin<Self::RuntimeOrigin>;8687		/// The ID of the foreign assets pallet.88		type PalletId: Get<PalletId>;8990		/// Weight information for the extrinsics in this module.91		type WeightInfo: WeightInfo;92	}9394	#[pallet::error]95	pub enum Error<T> {96		/// The foreign asset is already registered97		ForeignAssetAlreadyRegistered,98	}99100	#[pallet::event]101	#[pallet::generate_deposit(fn deposit_event)]102	pub enum Event<T: Config> {103		/// The foreign asset registered.104		ForeignAssetRegistered {105			asset_id: CollectionId,106			reserve_location: MultiLocation,107		},108	}109110	/// The corresponding collections of reserve locations.111	#[pallet::storage]112	#[pallet::getter(fn foreign_reserve_location_to_collection)]113	pub type ForeignReserveLocationToCollection<T: Config> =114		StorageMap<_, Twox64Concat, staging_xcm::v3::MultiLocation, CollectionId, OptionQuery>;115116	/// The correponding NFT token id of reserve NFTs117	#[pallet::storage]118	#[pallet::getter(fn foreign_reserve_asset_instance_to_token_id)]119	pub type ForeignReserveAssetInstanceToTokenId<T: Config> = StorageDoubleMap<120		Hasher1 = Twox64Concat,121		Key1 = CollectionId,122		Hasher2 = Twox64Concat,123		Key2 = staging_xcm::v3::AssetInstance,124		Value = TokenId,125		QueryKind = OptionQuery,126	>;127128	#[pallet::pallet]129	pub struct Pallet<T>(_);130131	#[pallet::call]132	impl<T: Config> Pallet<T> {133		#[pallet::call_index(0)]134		#[pallet::weight(<T as Config>::WeightInfo::register_foreign_asset())]135		pub fn force_register_foreign_asset(136			origin: OriginFor<T>,137			reserve_location: MultiLocation,138			name: CollectionName,139			mode: CollectionMode,140		) -> DispatchResult {141			T::ForceRegisterOrigin::ensure_origin(origin.clone())?;142143			let foreign_collection_owner = Self::pallet_account();144145			let description: CollectionDescription = "Foreign Assets Collection"146				.encode_utf16()147				.collect::<Vec<_>>()148				.try_into()149				.expect("description length < max description length; qed");150151			let collection_id = T::CollectionDispatch::create_foreign(152				foreign_collection_owner,153				CreateCollectionData {154					name,155					description,156					mode,157158					properties: vec![Property {159						key: Self::reserve_location_property_key(),160						value: reserve_location161							.encode()162							.try_into()163							.expect("multilocation is less than 32k; qed"),164					}]165					.try_into()166					.expect("just one property can always be stored; qed"),167168					token_property_permissions: vec![PropertyKeyPermission {169						key: Self::reserve_asset_instance_property_key(),170						permission: PropertyPermission {171							mutable: false,172							collection_admin: true,173							token_owner: false,174						},175					}]176					.try_into()177					.expect("just one property permission can always be stored; qed"),178					..Default::default()179				},180			)?;181182			<ForeignReserveLocationToCollection<T>>::insert(reserve_location, collection_id);183184			Self::deposit_event(Event::<T>::ForeignAssetRegistered {185				asset_id: collection_id,186				reserve_location,187			});188189			Ok(())190		}191	}192}193194impl<T: Config> Pallet<T> {195	fn pallet_account() -> T::CrossAccountId {196		let owner: T::AccountId = T::PalletId::get().into_account_truncating();197		T::CrossAccountId::from_sub(owner)198	}199200	fn reserve_location_property_key() -> PropertyKey {201		b"reserve-location"202			.to_vec()203			.try_into()204			.expect("key length < max property key length; qed")205	}206207	fn reserve_asset_instance_property_key() -> PropertyKey {208		b"reserve-asset-instance"209			.to_vec()210			.try_into()211			.expect("key length < max property key length; qed")212	}213}214215impl<T: Config> TransactAsset for Pallet<T> {216	fn can_check_in(217		_origin: &MultiLocation,218		_what: &MultiAsset,219		_context: &XcmContext,220	) -> XcmResult {221		Err(XcmError::Unimplemented)222	}223224	fn check_in(_origin: &MultiLocation, _what: &MultiAsset, _context: &XcmContext) {}225226	fn can_check_out(227		_dest: &MultiLocation,228		_what: &MultiAsset,229		_context: &XcmContext,230	) -> XcmResult {231		Err(XcmError::Unimplemented)232	}233234	fn check_out(_dest: &MultiLocation, _what: &MultiAsset, _context: &XcmContext) {}235236	fn deposit_asset(what: &MultiAsset, to: &MultiLocation, context: &XcmContext) -> XcmResult {237		Err(XcmError::Unimplemented)238	}239240	fn withdraw_asset(241		what: &MultiAsset,242		from: &MultiLocation,243		_maybe_context: Option<&XcmContext>,244	) -> Result<staging_xcm_executor::Assets, XcmError> {245		Err(XcmError::Unimplemented)246	}247248	fn internal_transfer_asset(249		what: &MultiAsset,250		from: &MultiLocation,251		to: &MultiLocation,252		_context: &XcmContext,253	) -> Result<staging_xcm_executor::Assets, XcmError> {254		Err(XcmError::Unimplemented)255	}256}257258pub struct CurrencyIdConvert<T: Config>(PhantomData<T>);259impl<T: Config> sp_runtime::traits::Convert<CollectionId, Option<MultiLocation>>260	for CurrencyIdConvert<T>261{262	fn convert(collection_id: CollectionId) -> Option<MultiLocation> {263		if collection_id == NATIVE_FUNGIBLE_COLLECTION_ID {264			Some(Here.into())265		} else {266			// let dispatch = T::CollectionDispatch::dispatch(collection_id).ok()?;267			// let collection = dispatch.as_dyn();268			// let xcm_ext = collection.xcm_extensions()?;269270			// if xcm_ext.is_foreign() {271			// 	let encoded_location =272			// 		collection.property(&<Pallet<T>>::reserve_location_property_key())?;273			// 	MultiLocation::decode(&mut &encoded_location[..]).ok()274			// } else {275			// 	T::SelfLocation::get()276			// 		.pushed_with_interior(GeneralIndex(collection_id.0.into()))277			// 		.ok()278			// }279			todo!()280		}281	}282}283284pub use frame_support::{285	traits::{286		fungibles::Balanced, tokens::currency::Currency as CurrencyT, OnUnbalanced as OnUnbalancedT,287	},288	weights::{WeightToFee, WeightToFeePolynomial},289};290291pub struct FreeForAll;292293impl WeightTrader for FreeForAll {294	fn new() -> Self {295		Self296	}297298	fn buy_weight(299		&mut self,300		weight: Weight,301		payment: Assets,302		_xcm: &XcmContext,303	) -> Result<Assets, XcmError> {304		log::trace!(target: "fassets::weight", "buy_weight weight: {:?}, payment: {:?}", weight, payment);305		Ok(payment)306	}307}