difftreelog
refactor draft foreign assets as proxy to collections
in: master
18 files changed
node/cli/src/chain_spec.rsdiffbeforeafterboth167 .map(|k| (k, 1 << 100))167 .map(|k| (k, 1 << 100))168 .collect(),168 .collect(),169 },169 },170 tokens: TokensConfig { balances: vec![] },171 sudo: SudoConfig {170 sudo: SudoConfig {172 key: Some($root_key),171 key: Some($root_key),173 },172 },pallets/balances-adapter/src/common.rsdiffbeforeafterboth332 0332 0333 }333 }334335 fn refungible_extensions(&self) -> Option<&dyn pallet_common::RefungibleExtensions<T>> {336 None337 }338334339 fn set_allowance_for_all(335 fn set_allowance_for_all(340 &self,336 &self,pallets/common/src/dispatch.rsdiffbeforeafterboth72 /// Create a collection. The collection will be created according to the value of [`data.mode`](CreateCollectionData::mode).72 /// Create a collection. The collection will be created according to the value of [`data.mode`](CreateCollectionData::mode).73 ///73 ///74 /// * `sender` - The user who will become the owner of the collection.74 /// * `sender` - The user who will become the owner of the collection.75 /// * `payer` - The user who pays the collection creation fee.75 /// * `data` - Description of the created collection.76 /// * `data` - Description of the created collection.76 fn create(77 fn create(77 sender: T::CrossAccountId,78 sender: T::CrossAccountId,78 payer: T::CrossAccountId,79 payer: T::CrossAccountId,79 data: CreateCollectionData<T::CrossAccountId>,80 data: CreateCollectionData<T::CrossAccountId>,80 ) -> Result<CollectionId, DispatchError>;81 ) -> Result<CollectionId, DispatchError>;8283 /// Create a foreign collection. The collection will be created according to the value of [`data.mode`](CreateCollectionData::mode).84 ///85 /// * `sender` - The user who will become the owner of the collection.86 /// * `data` - Description of the created collection.87 fn create_foreign(88 sender: T::CrossAccountId,89 data: CreateCollectionData<T::CrossAccountId>,90 ) -> Result<CollectionId, DispatchError>;819182 /// Delete the collection.92 /// Delete the collection.83 ///93 ///pallets/common/src/lib.rsdiffbeforeafterboth1133 ) -> Result<CollectionId, DispatchError> {1133 ) -> Result<CollectionId, DispatchError> {1134 ensure!(data.flags.is_allowed_for_user(), <Error<T>>::NoPermission);1134 ensure!(data.flags.is_allowed_for_user(), <Error<T>>::NoPermission);11351136 // Take a (non-refundable) deposit of collection creation1137 {1138 let mut imbalance = <Debt<T::AccountId, <T as Config>::Currency>>::zero();1139 imbalance.subsume(<T as Config>::Currency::deposit(1140 &T::TreasuryAccountId::get(),1141 T::CollectionCreationPrice::get(),1142 Precision::Exact,1143 )?);1144 let credit =1145 <T as Config>::Currency::settle(payer.as_sub(), imbalance, Preservation::Preserve)1146 .map_err(|_| Error::<T>::NotSufficientFounds)?;11471148 debug_assert!(credit.peek().is_zero())1149 }11501135 Self::init_collection_internal(owner, payer, data)1151 Self::init_collection_internal(owner, data)1136 }1152 }113711531138 /// Initializes the collection with ForeignCollection flag. Returns [CollectionId] on success, [DispatchError] otherwise.1154 /// Initializes the collection with ForeignCollection flag. Returns [CollectionId] on success, [DispatchError] otherwise.1139 pub fn init_foreign_collection(1155 pub fn init_foreign_collection(1140 owner: T::CrossAccountId,1156 owner: T::CrossAccountId,1141 payer: T::CrossAccountId,1142 mut data: CreateCollectionData<T::CrossAccountId>,1157 mut data: CreateCollectionData<T::CrossAccountId>,1143 ) -> Result<CollectionId, DispatchError> {1158 ) -> Result<CollectionId, DispatchError> {1144 data.flags.foreign = true;1159 data.flags.foreign = true;1145 let id = Self::init_collection_internal(owner, payer, data)?;1160 let id = Self::init_collection_internal(owner, data)?;1146 Ok(id)1161 Ok(id)1147 }1162 }114811631149 fn init_collection_internal(1164 fn init_collection_internal(1150 owner: T::CrossAccountId,1165 owner: T::CrossAccountId,1151 payer: T::CrossAccountId,1152 data: CreateCollectionData<T::CrossAccountId>,1166 data: CreateCollectionData<T::CrossAccountId>,1153 ) -> Result<CollectionId, DispatchError> {1167 ) -> Result<CollectionId, DispatchError> {1154 {1168 {1225 );1239 );1226 <AdminAmount<T>>::insert(id, admin_amount);1240 <AdminAmount<T>>::insert(id, admin_amount);12271228 // Take a (non-refundable) deposit of collection creation1229 {1230 let mut imbalance = <Debt<T::AccountId, <T as Config>::Currency>>::zero();1231 imbalance.subsume(<T as Config>::Currency::deposit(1232 &T::TreasuryAccountId::get(),1233 T::CollectionCreationPrice::get(),1234 Precision::Exact,1235 )?);1236 let credit =1237 <T as Config>::Currency::settle(payer.as_sub(), imbalance, Preservation::Preserve)1238 .map_err(|_| Error::<T>::NotSufficientFounds)?;12391240 debug_assert!(credit.peek().is_zero())1241 }124212411243 <CreatedCollectionCount<T>>::put(created_count);1242 <CreatedCollectionCount<T>>::put(created_count);1244 <Pallet<T>>::deposit_event(Event::CollectionCreated(1243 <Pallet<T>>::deposit_event(Event::CollectionCreated(2293 ) -> u128;2292 ) -> u128;229422932295 /// Get extension for RFT collection.2294 /// Get extension for RFT collection.2296 fn refungible_extensions(&self) -> Option<&dyn RefungibleExtensions<T>>;2295 fn refungible_extensions(&self) -> Option<&dyn RefungibleExtensions<T>> {2296 None2297 }22982299 /// Get XCM extensions.2300 fn xcm_extensions(&self) -> Option<&dyn XcmExtensions<T>> {2301 None2302 }229723032298 /// The `operator` is allowed to transfer all tokens of the `owner` on their behalf.2304 /// The `operator` is allowed to transfer all tokens of the `owner` on their behalf.2299 /// * `owner` - Token owner2305 /// * `owner` - Token owner2333 ) -> DispatchResultWithPostInfo;2339 ) -> DispatchResultWithPostInfo;2334}2340}23412342/// XCM extensions for fungible and NFT collections2343pub trait XcmExtensions<T>2344where2345 T: Config,2346{2347 /// Is the collection a foreign one?2348 fn is_foreign(&self) -> bool;23492350 /// Create a collection's item.2351 fn create_item(2352 &self,2353 to: T::CrossAccountId,2354 data: CreateItemData,2355 ) -> Result<TokenId, DispatchError>;23562357 /// Transfer an item from the `from` account to the `to` account.2358 fn transfer(2359 &self,2360 from: T::CrossAccountId,2361 to: T::CrossAccountId,2362 token: TokenId,2363 amount: u128,2364 ) -> DispatchResult;23652366 /// Burn a collection's item.2367 fn burn(&self, from: T::CrossAccountId, token: TokenId, amount: u128) -> DispatchResult;2368}233523692336/// Merge [`DispatchResult`] with [`Weight`] into [`DispatchResultWithPostInfo`].2370/// Merge [`DispatchResult`] with [`Weight`] into [`DispatchResultWithPostInfo`].2337///2371///pallets/foreign-assets/src/impl_fungibles.rsdiffbeforeafterbothno changes
pallets/foreign-assets/src/lib.rsdiffbeforeafterboth34#![cfg_attr(not(feature = "std"), no_std)]34#![cfg_attr(not(feature = "std"), no_std)]35#![allow(clippy::unused_unit)]35#![allow(clippy::unused_unit)]363637use frame_support::{37use frame_support::{dispatch::DispatchResult, pallet_prelude::*, traits::EnsureOrigin, PalletId};38 dispatch::DispatchResult,39 ensure,40 pallet_prelude::*,41 traits::{fungible, fungibles, Currency, EnsureOrigin},42};43use frame_system::pallet_prelude::*;38use frame_system::pallet_prelude::*;44use pallet_common::erc::CrossAccountId;39use pallet_common::{45use pallet_fungible::Pallet as PalletFungible;40 dispatch::CollectionDispatch, erc::CrossAccountId, NATIVE_FUNGIBLE_COLLECTION_ID,46use scale_info::TypeInfo;47use serde::{Deserialize, Serialize};48use sp_runtime::{49 traits::{One, Zero},50 ArithmeticError,51};41};52use sp_std::{boxed::Box, vec::Vec};42use sp_runtime::traits::AccountIdConversion;53use staging_xcm::{latest::MultiLocation, VersionedMultiLocation};43use sp_std::{vec, vec::Vec};54// NOTE: MultiLocation is used in storages, we will need to do migration if upgrade the44// NOTE: MultiLocation is used in storages, we will need to do migration if upgrade the55// MultiLocation to the XCM v3.45// MultiLocation to the XCM v3.56use staging_xcm::{46use staging_xcm::{57 opaque::latest::{prelude::XcmError, Weight},47 opaque::latest::{prelude::XcmError, Weight},58 v3::XcmContext,48 v3::{prelude::*, MultiAsset, XcmContext},59};49};60use staging_xcm_executor::{traits::WeightTrader, Assets};50use staging_xcm_executor::{51 traits::{TransactAsset, WeightTrader},52 Assets,53};61use up_data_structs::{CollectionId, CollectionMode, CreateCollectionData, TokenId};54use up_data_structs::{55 CollectionId, CollectionMode, CollectionName, CreateCollectionData, PropertyKey, TokenId,56};625763// TODO: Move to primitives64// Id of native currency.65// 0 - QTZ\UNQ66// 1 - KSM\DOT67#[derive(68 Clone,69 Copy,70 Eq,71 PartialEq,72 PartialOrd,73 Ord,74 MaxEncodedLen,75 RuntimeDebug,76 Encode,77 Decode,78 TypeInfo,79 Serialize,80 Deserialize,81)]82pub enum NativeCurrency {83 Here = 0,84 Parent = 1,85}8687#[derive(88 Clone,89 Copy,90 Eq,91 PartialEq,92 PartialOrd,93 Ord,94 MaxEncodedLen,95 RuntimeDebug,96 Encode,97 Decode,98 TypeInfo,99 Serialize,100 Deserialize,101)]102pub enum AssetId {103 ForeignAssetId(ForeignAssetId),104 NativeAssetId(NativeCurrency),105}106107pub trait TryAsForeign<T, F> {108 fn try_as_foreign(asset: T) -> Option<F>;109}110111impl TryAsForeign<AssetId, ForeignAssetId> for AssetId {112 fn try_as_foreign(asset: AssetId) -> Option<ForeignAssetId> {113 match asset {114 Self::ForeignAssetId(id) => Some(id),115 _ => None,116 }117 }118}119120pub type ForeignAssetId = u32;121pub type CurrencyId = AssetId;122123mod impl_fungibles;124pub mod weights;58pub mod weights;12559126#[cfg(feature = "runtime-benchmarks")]60#[cfg(feature = "runtime-benchmarks")]129pub use module::*;63pub use module::*;130pub use weights::WeightInfo;64pub use weights::WeightInfo;13165132/// Type alias for currency balance.133pub type BalanceOf<T> =134 <<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;135136/// A mapping between ForeignAssetId and AssetMetadata.137pub trait AssetIdMapping<ForeignAssetId, MultiLocation, AssetMetadata> {138 /// Returns the AssetMetadata associated with a given ForeignAssetId.139 fn get_asset_metadata(foreign_asset_id: ForeignAssetId) -> Option<AssetMetadata>;140 /// Returns the MultiLocation associated with a given ForeignAssetId.141 fn get_multi_location(foreign_asset_id: ForeignAssetId) -> Option<MultiLocation>;142 /// Returns the CurrencyId associated with a given MultiLocation.143 fn get_currency_id(multi_location: MultiLocation) -> Option<CurrencyId>;144}145146pub struct XcmForeignAssetIdMapping<T>(sp_std::marker::PhantomData<T>);147148impl<T: Config> AssetIdMapping<ForeignAssetId, MultiLocation, AssetMetadata<BalanceOf<T>>>149 for XcmForeignAssetIdMapping<T>150{151 fn get_asset_metadata(foreign_asset_id: ForeignAssetId) -> Option<AssetMetadata<BalanceOf<T>>> {152 log::trace!(target: "fassets::asset_metadatas", "call");153 Pallet::<T>::asset_metadatas(AssetId::ForeignAssetId(foreign_asset_id))154 }155156 fn get_multi_location(foreign_asset_id: ForeignAssetId) -> Option<MultiLocation> {157 log::trace!(target: "fassets::get_multi_location", "call");158 Pallet::<T>::foreign_asset_locations(foreign_asset_id)159 }160161 fn get_currency_id(multi_location: MultiLocation) -> Option<CurrencyId> {162 log::trace!(target: "fassets::get_currency_id", "call");163 Pallet::<T>::location_to_currency_ids(multi_location).map(AssetId::ForeignAssetId)164 }165}166167#[frame_support::pallet]66#[frame_support::pallet]168pub mod module {67pub mod module {68 use up_data_structs::{69 CollectionDescription, Property, PropertyKeyPermission, PropertyPermission,70 };71169 use super::*;72 use super::*;17073171 #[pallet::config]74 #[pallet::config]172 pub trait Config:75 pub trait Config:173 frame_system::Config76 frame_system::Config174 + pallet_common::Config77 + pallet_common::Config175 + pallet_fungible::Config78 + pallet_fungible::Config176 + orml_tokens::Config177 + pallet_balances::Config79 + pallet_balances::Config178 {80 {179 /// The overarching event type.81 /// The overarching event type.180 type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;82 type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;18183182 /// Currency type for withdraw and balance storage.84 /// Origin for force registering of a foreign asset.183 type Currency: Currency<Self::AccountId>;85 type ForceRegisterOrigin: EnsureOrigin<Self::RuntimeOrigin>;18486185 /// Required origin for registering asset.87 /// The ID of the foreign assets pallet.186 type RegisterOrigin: EnsureOrigin<Self::RuntimeOrigin>;88 type PalletId: Get<PalletId>;18789188 /// Weight information for the extrinsics in this module.90 /// Weight information for the extrinsics in this module.189 type WeightInfo: WeightInfo;91 type WeightInfo: WeightInfo;190 }92 }19193192 pub type AssetName = BoundedVec<u8, ConstU32<32>>;193 pub type AssetSymbol = BoundedVec<u8, ConstU32<7>>;194195 #[derive(Clone, Eq, PartialEq, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen)]196 pub struct AssetMetadata<Balance> {197 pub name: AssetName,198 pub symbol: AssetSymbol,199 pub decimals: u8,200 pub minimal_balance: Balance,201 }202203 #[pallet::error]94 #[pallet::error]204 pub enum Error<T> {95 pub enum Error<T> {205 /// The given location could not be used (e.g. because it cannot be expressed in the96 /// The foreign asset is already registered206 /// desired version of XCM).207 BadLocation,208 /// MultiLocation existed209 MultiLocationExisted,210 /// AssetId not exists211 AssetIdNotExists,212 /// AssetId exists213 AssetIdExisted,97 ForeignAssetAlreadyRegistered,214 }98 }21599216 #[pallet::event]100 #[pallet::event]217 #[pallet::generate_deposit(fn deposit_event)]101 #[pallet::generate_deposit(fn deposit_event)]218 pub enum Event<T: Config> {102 pub enum Event<T: Config> {219 /// The foreign asset registered.103 /// The foreign asset registered.220 ForeignAssetRegistered {104 ForeignAssetRegistered {221 asset_id: ForeignAssetId,105 asset_id: CollectionId,222 asset_address: MultiLocation,106 reserve_location: MultiLocation,223 metadata: AssetMetadata<BalanceOf<T>>,224 },107 },225 /// The foreign asset updated.226 ForeignAssetUpdated {227 asset_id: ForeignAssetId,228 asset_address: MultiLocation,229 metadata: AssetMetadata<BalanceOf<T>>,230 },231 /// The asset registered.232 AssetRegistered {233 asset_id: AssetId,234 metadata: AssetMetadata<BalanceOf<T>>,235 },236 /// The asset updated.237 AssetUpdated {238 asset_id: AssetId,239 metadata: AssetMetadata<BalanceOf<T>>,240 },241 }108 }242109243 /// Next available Foreign AssetId ID.110 /// The corresponding collections of reserve locations.244 ///245 /// NextForeignAssetId: ForeignAssetId246 #[pallet::storage]111 #[pallet::storage]247 #[pallet::getter(fn next_foreign_asset_id)]112 #[pallet::getter(fn foreign_reserve_location_to_collection)]248 pub type NextForeignAssetId<T: Config> = StorageValue<_, ForeignAssetId, ValueQuery>;113 pub type ForeignReserveLocationToCollection<T: Config> =249 /// The storages for MultiLocations.114 StorageMap<_, Twox64Concat, staging_xcm::v3::MultiLocation, CollectionId, OptionQuery>;250 ///251 /// ForeignAssetLocations: map ForeignAssetId => Option<MultiLocation>252 #[pallet::storage]253 #[pallet::getter(fn foreign_asset_locations)]254 pub type ForeignAssetLocations<T: Config> =255 StorageMap<_, Twox64Concat, ForeignAssetId, staging_xcm::v3::MultiLocation, OptionQuery>;256115257 /// The storages for CurrencyIds.116 /// The correponding NFT token id of reserve NFTs258 ///259 /// LocationToCurrencyIds: map MultiLocation => Option<ForeignAssetId>260 #[pallet::storage]117 #[pallet::storage]261 #[pallet::getter(fn location_to_currency_ids)]118 #[pallet::getter(fn foreign_reserve_asset_instance_to_token_id)]262 pub type LocationToCurrencyIds<T: Config> =119 pub type ForeignReserveAssetInstanceToTokenId<T: Config> = StorageDoubleMap<263 StorageMap<_, Twox64Concat, staging_xcm::v3::MultiLocation, ForeignAssetId, OptionQuery>;120 Hasher1 = Twox64Concat,121 Key1 = CollectionId,122 Hasher2 = Twox64Concat,123 Key2 = staging_xcm::v3::AssetInstance,124 Value = TokenId,125 QueryKind = OptionQuery,126 >;264127265 /// The storages for AssetMetadatas.266 ///267 /// AssetMetadatas: map AssetIds => Option<AssetMetadata>268 #[pallet::storage]269 #[pallet::getter(fn asset_metadatas)]270 pub type AssetMetadatas<T: Config> =271 StorageMap<_, Twox64Concat, AssetId, AssetMetadata<BalanceOf<T>>, OptionQuery>;272273 /// The storages for assets to fungible collection binding274 ///275 #[pallet::storage]276 #[pallet::getter(fn asset_binding)]277 pub type AssetBinding<T: Config> =278 StorageMap<_, Twox64Concat, ForeignAssetId, CollectionId, OptionQuery>;279280 #[pallet::pallet]128 #[pallet::pallet]281 pub struct Pallet<T>(_);129 pub struct Pallet<T>(_);282130283 #[pallet::call]131 #[pallet::call]284 impl<T: Config> Pallet<T> {132 impl<T: Config> Pallet<T> {285 #[pallet::call_index(0)]133 #[pallet::call_index(0)]286 #[pallet::weight(<T as Config>::WeightInfo::register_foreign_asset())]134 #[pallet::weight(<T as Config>::WeightInfo::register_foreign_asset())]287 pub fn register_foreign_asset(135 pub fn force_register_foreign_asset(288 origin: OriginFor<T>,136 origin: OriginFor<T>,289 owner: T::AccountId,137 reserve_location: MultiLocation,290 location: Box<VersionedMultiLocation>,138 name: CollectionName,291 metadata: Box<AssetMetadata<BalanceOf<T>>>,139 mode: CollectionMode,292 ) -> DispatchResult {140 ) -> DispatchResult {293 T::RegisterOrigin::ensure_origin(origin.clone())?;141 T::ForceRegisterOrigin::ensure_origin(origin.clone())?;294142295 let location: MultiLocation = (*location)143 let foreign_collection_owner = Self::pallet_account();296 .try_into()297 .map_err(|()| Error::<T>::BadLocation)?;298144299 let md = metadata.clone();145 let description: CollectionDescription = "Foreign Assets Collection"300 let name: Vec<u16> = md.name.into_iter().map(|x| x as u16).collect::<Vec<u16>>();301 let mut description: Vec<u16> = "Foreign assets collection for "302 .encode_utf16()146 .encode_utf16()303 .collect::<Vec<u16>>();147 .collect::<Vec<_>>()304 description.append(&mut name.clone());148 .try_into()149 .expect("description length < max description length; qed");305150306 let data: CreateCollectionData<T::CrossAccountId> = CreateCollectionData {151 let collection_id = T::CollectionDispatch::create_foreign(307 name: name.try_into().unwrap(),308 description: description.try_into().unwrap(),152 foreign_collection_owner,309 mode: CollectionMode::Fungible(md.decimals),153 CreateCollectionData {310 ..Default::default()154 name,311 };312 let owner = T::CrossAccountId::from_sub(owner);155 description,313 let bounded_collection_id =314 <PalletFungible<T>>::init_foreign_collection(owner.clone(), owner, data)?;315 let foreign_asset_id =156 mode,316 Self::do_register_foreign_asset(&location, &metadata, bounded_collection_id)?;317157318 Self::deposit_event(Event::<T>::ForeignAssetRegistered {158 properties: vec![Property {319 asset_id: foreign_asset_id,159 key: Self::reserve_location_property_key(),320 asset_address: location,160 value: reserve_location321 metadata: *metadata,161 .encode()162 .try_into()163 .expect("multilocation is less than 32k; qed"),322 });164 }]323 Ok(())165 .try_into()324 }166 .expect("just one property can always be stored; qed"),325167326 #[pallet::call_index(1)]168 token_property_permissions: vec![PropertyKeyPermission {327 #[pallet::weight(<T as Config>::WeightInfo::update_foreign_asset())]169 key: Self::reserve_asset_instance_property_key(),328 pub fn update_foreign_asset(170 permission: PropertyPermission {329 origin: OriginFor<T>,171 mutable: false,330 foreign_asset_id: ForeignAssetId,172 collection_admin: true,331 location: Box<VersionedMultiLocation>,173 token_owner: false,332 metadata: Box<AssetMetadata<BalanceOf<T>>>,174 },333 ) -> DispatchResult {175 }]176 .try_into()177 .expect("just one property permission can always be stored; qed"),334 T::RegisterOrigin::ensure_origin(origin)?;178 ..Default::default()179 },180 )?;335181336 let location: MultiLocation = (*location)182 <ForeignReserveLocationToCollection<T>>::insert(reserve_location, collection_id);337 .try_into()338 .map_err(|()| Error::<T>::BadLocation)?;339 Self::do_update_foreign_asset(foreign_asset_id, &location, &metadata)?;340183341 Self::deposit_event(Event::<T>::ForeignAssetUpdated {184 Self::deposit_event(Event::<T>::ForeignAssetRegistered {342 asset_id: foreign_asset_id,185 asset_id: collection_id,343 asset_address: location,186 reserve_location,344 metadata: *metadata,345 });187 });188346 Ok(())189 Ok(())347 }190 }348 }191 }349}192}350193351impl<T: Config> Pallet<T> {194impl<T: Config> Pallet<T> {352 fn get_next_foreign_asset_id() -> Result<ForeignAssetId, DispatchError> {195 fn pallet_account() -> T::CrossAccountId {353 NextForeignAssetId::<T>::try_mutate(|current| -> Result<ForeignAssetId, DispatchError> {354 let id = *current;196 let owner: T::AccountId = T::PalletId::get().into_account_truncating();355 *current = current356 .checked_add(One::one())357 .ok_or(ArithmeticError::Overflow)?;358 Ok(id)197 T::CrossAccountId::from_sub(owner)359 })360 }198 }361199362 fn do_register_foreign_asset(200 fn reserve_location_property_key() -> PropertyKey {363 location: &MultiLocation,364 metadata: &AssetMetadata<BalanceOf<T>>,365 bounded_collection_id: CollectionId,366 ) -> Result<ForeignAssetId, DispatchError> {367 let foreign_asset_id = Self::get_next_foreign_asset_id()?;201 b"reserve-location"368 LocationToCurrencyIds::<T>::try_mutate(location, |maybe_currency_ids| -> DispatchResult {369 ensure!(202 .to_vec()370 maybe_currency_ids.is_none(),203 .try_into()371 Error::<T>::MultiLocationExisted204 .expect("key length < max property key length; qed")372 );205 }373 *maybe_currency_ids = Some(foreign_asset_id);374 // *maybe_currency_ids = Some(CurrencyId::ForeignAsset(foreign_asset_id));375206376 ForeignAssetLocations::<T>::try_mutate(207 fn reserve_asset_instance_property_key() -> PropertyKey {377 foreign_asset_id,378 |maybe_location| -> DispatchResult {379 ensure!(maybe_location.is_none(), Error::<T>::MultiLocationExisted);208 b"reserve-asset-instance"209 .to_vec()380 *maybe_location = Some(*location);210 .try_into()211 .expect("key length < max property key length; qed")212 }213}381214382 AssetMetadatas::<T>::try_mutate(215impl<T: Config> TransactAsset for Pallet<T> {383 AssetId::ForeignAssetId(foreign_asset_id),384 |maybe_asset_metadatas| -> DispatchResult {385 ensure!(maybe_asset_metadatas.is_none(), Error::<T>::AssetIdExisted);386 *maybe_asset_metadatas = Some(metadata.clone());216 fn can_check_in(387 Ok(())217 _origin: &MultiLocation,218 _what: &MultiAsset,388 },219 _context: &XcmContext,389 )220 ) -> XcmResult {390 },221 Err(XcmError::Unimplemented)391 )?;222 }392223393 AssetBinding::<T>::try_mutate(foreign_asset_id, |collection_id| -> DispatchResult {224 fn check_in(_origin: &MultiLocation, _what: &MultiAsset, _context: &XcmContext) {}394 *collection_id = Some(bounded_collection_id);395 Ok(())396 })397 })?;398225399 Ok(foreign_asset_id)226 fn can_check_out(227 _dest: &MultiLocation,228 _what: &MultiAsset,229 _context: &XcmContext,230 ) -> XcmResult {231 Err(XcmError::Unimplemented)400 }232 }401233402 fn do_update_foreign_asset(234 fn check_out(_dest: &MultiLocation, _what: &MultiAsset, _context: &XcmContext) {}403 foreign_asset_id: ForeignAssetId,404 location: &MultiLocation,405 metadata: &AssetMetadata<BalanceOf<T>>,406 ) -> DispatchResult {407 ForeignAssetLocations::<T>::try_mutate(408 foreign_asset_id,409 |maybe_multi_locations| -> DispatchResult {410 let old_multi_locations = maybe_multi_locations411 .as_mut()412 .ok_or(Error::<T>::AssetIdNotExists)?;413235414 AssetMetadatas::<T>::try_mutate(236 fn deposit_asset(what: &MultiAsset, to: &MultiLocation, context: &XcmContext) -> XcmResult {415 AssetId::ForeignAssetId(foreign_asset_id),416 |maybe_asset_metadatas| -> DispatchResult {417 ensure!(237 Err(XcmError::Unimplemented)418 maybe_asset_metadatas.is_some(),419 Error::<T>::AssetIdNotExists420 );238 }421239422 // modify location240 fn withdraw_asset(423 if location != old_multi_locations {241 what: &MultiAsset,424 LocationToCurrencyIds::<T>::remove(*old_multi_locations);242 from: &MultiLocation,425 LocationToCurrencyIds::<T>::try_mutate(243 _maybe_context: Option<&XcmContext>,426 location,427 |maybe_currency_ids| -> DispatchResult {244 ) -> Result<staging_xcm_executor::Assets, XcmError> {428 ensure!(429 maybe_currency_ids.is_none(),430 Error::<T>::MultiLocationExisted431 );432 // *maybe_currency_ids = Some(CurrencyId::ForeignAsset(foreign_asset_id));433 *maybe_currency_ids = Some(foreign_asset_id);434 Ok(())435 },436 )?;437 }438 *maybe_asset_metadatas = Some(metadata.clone());439 *old_multi_locations = *location;245 Err(XcmError::Unimplemented)440 Ok(())441 },442 )443 },444 )445 }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 }446}256}447257258pub 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}283448pub use frame_support::{284pub use frame_support::{449 traits::{285 traits::{450 fungibles::Balanced, tokens::currency::Currency as CurrencyT, OnUnbalanced as OnUnbalancedT,286 fungibles::Balanced, tokens::currency::Currency as CurrencyT, OnUnbalanced as OnUnbalancedT,451 },287 },452 weights::{WeightToFee, WeightToFeePolynomial},288 weights::{WeightToFee, WeightToFeePolynomial},453};289};454290455pub struct FreeForAll<291pub struct FreeForAll;456 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,457 AssetId: Get<MultiLocation>,458 AccountId,459 Currency: CurrencyT<AccountId>,460 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,461>(462 Weight,463 Currency::Balance,464 PhantomData<(WeightToFee, AssetId, AccountId, Currency, OnUnbalanced)>,465);466292467impl<293impl WeightTrader for FreeForAll {468 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,469 AssetId: Get<MultiLocation>,470 AccountId,471 Currency: CurrencyT<AccountId>,472 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,473 > WeightTrader for FreeForAll<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>474{475 fn new() -> Self {294 fn new() -> Self {476 Self(Weight::default(), Zero::zero(), PhantomData)295 Self477 }296 }478297479 fn buy_weight(298 fn buy_weight(484 ) -> Result<Assets, XcmError> {303 ) -> Result<Assets, XcmError> {485 log::trace!(target: "fassets::weight", "buy_weight weight: {:?}, payment: {:?}", weight, payment);304 log::trace!(target: "fassets::weight", "buy_weight weight: {:?}, payment: {:?}", weight, payment);486 Ok(payment)305 Ok(payment)487 }488}489impl<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced> Drop490 for FreeForAll<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>491where492 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,493 AssetId: Get<MultiLocation>,494 Currency: CurrencyT<AccountId>,495 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,496{497 fn drop(&mut self) {498 OnUnbalanced::on_unbalanced(Currency::issue(self.1));499 }306 }500}307}501308pallets/fungible/src/common.rsdiffbeforeafterboth428 <Allowance<T>>::get((self.id, sender, spender))428 <Allowance<T>>::get((self.id, sender, spender))429 }429 }430431 fn refungible_extensions(&self) -> Option<&dyn RefungibleExtensions<T>> {432 None433 }434430435 fn total_pieces(&self, token: TokenId) -> Option<u128> {431 fn total_pieces(&self, token: TokenId) -> Option<u128> {436 if token != TokenId::default() {432 if token != TokenId::default() {pallets/fungible/src/lib.rsdiffbeforeafterboth212212213/// Pallet implementation for fungible assets213/// Pallet implementation for fungible assets214impl<T: Config> Pallet<T> {214impl<T: Config> Pallet<T> {215 /// Initializes the collection. Returns [CollectionId] on success, [DispatchError] otherwise.216 pub fn init_collection(217 owner: T::CrossAccountId,218 payer: T::CrossAccountId,219 data: CreateCollectionData<T::CrossAccountId>,220 ) -> Result<CollectionId, DispatchError> {221 <PalletCommon<T>>::init_collection(owner, payer, data)222 }223224 /// Initializes the collection with ForeignCollection flag. Returns [CollectionId] on success, [DispatchError] otherwise.225 pub fn init_foreign_collection(226 owner: T::CrossAccountId,227 payer: T::CrossAccountId,228 data: CreateCollectionData<T::CrossAccountId>,229 ) -> Result<CollectionId, DispatchError> {230 <PalletCommon<T>>::init_foreign_collection(owner, payer, data)231 }232233 /// Destroys a collection.215 /// Destroys a collection.234 pub fn destroy_collection(216 pub fn destroy_collection(pallets/nonfungible/src/common.rsdiffbeforeafterboth535 }535 }536 }536 }537538 fn refungible_extensions(&self) -> Option<&dyn RefungibleExtensions<T>> {539 None540 }541537542 fn total_pieces(&self, token: TokenId) -> Option<u128> {538 fn total_pieces(&self, token: TokenId) -> Option<u128> {543 if <TokenData<T>>::contains_key((self.id, token)) {539 if <TokenData<T>>::contains_key((self.id, token)) {pallets/nonfungible/src/lib.rsdiffbeforeafterboth383383384// unchecked calls skips any permission checks384// unchecked calls skips any permission checks385impl<T: Config> Pallet<T> {385impl<T: Config> Pallet<T> {386 /// Create NFT collection387 ///388 /// `init_collection` will take non-refundable deposit for collection creation.389 ///390 /// - `data`: Contains settings for collection limits and permissions.391 pub fn init_collection(392 owner: T::CrossAccountId,393 payer: T::CrossAccountId,394 data: CreateCollectionData<T::CrossAccountId>,395 ) -> Result<CollectionId, DispatchError> {396 <PalletCommon<T>>::init_collection(owner, payer, data)397 }398399 /// Destroy NFT collection386 /// Destroy NFT collection400 ///387 ///runtime/common/config/orml.rsdiffbeforeafterboth161617use frame_support::{17use frame_support::{parameter_types, traits::Everything};18 parameter_types,19 traits::{Contains, Everything},20};21use frame_system::EnsureSigned;18use frame_system::EnsureSigned;22use orml_traits::{location::AbsoluteReserveProvider, parameter_type_with_key};19use orml_traits::{location::AbsoluteReserveProvider, parameter_type_with_key};23use pallet_foreign_assets::{CurrencyId, NativeCurrency};20use pallet_foreign_assets::CurrencyIdConvert;24use sp_runtime::traits::Convert;21use sp_runtime::traits::Convert;25use sp_std::{vec, vec::Vec};26use staging_xcm::latest::{Junction::*, Junctions::*, MultiLocation, Weight};22use staging_xcm::latest::{Junction::*, Junctions::*, MultiLocation, Weight};27use staging_xcm_executor::XcmExecutor;23use staging_xcm_executor::XcmExecutor;28use up_common::{24use up_common::{29 constants::*,25 constants::*,30 types::{AccountId, Balance},26 types::{AccountId, Balance},31};27};28use up_data_structs::CollectionId;322933use crate::{30use crate::{34 runtime_common::config::{31 runtime_common::config::xcm::{SelfLocation, UniversalLocation, Weigher, XcmExecutorConfig},35 pallets::TreasuryAccountId,36 substrate::{MaxLocks, MaxReserves},37 xcm::{38 xcm_assets::CurrencyIdConvert, SelfLocation, UniversalLocation, Weigher,39 XcmExecutorConfig,40 },41 },42 RelayChainBlockNumberProvider, Runtime, RuntimeEvent,32 RelayChainBlockNumberProvider, Runtime, RuntimeEvent,43};33};443459 };49 };60}50}6162parameter_type_with_key! {63 pub ExistentialDeposits: |currency_id: CurrencyId| -> Balance {64 match currency_id {65 CurrencyId::NativeAssetId(symbol) => match symbol {66 NativeCurrency::Here => 0,67 NativeCurrency::Parent=> 0,68 },69 _ => 100_00070 }71 };72}7374pub fn get_all_module_accounts() -> Vec<AccountId> {75 vec![TreasuryAccountId::get()]76}7778pub struct DustRemovalWhitelist;79impl Contains<AccountId> for DustRemovalWhitelist {80 fn contains(a: &AccountId) -> bool {81 get_all_module_accounts().contains(a)82 }83}845185pub struct AccountIdToMultiLocation;52pub struct AccountIdToMultiLocation;86impl Convert<AccountId, MultiLocation> for AccountIdToMultiLocation {53impl Convert<AccountId, MultiLocation> for AccountIdToMultiLocation {93 }60 }94}61}9596pub struct CurrencyHooks;97impl orml_traits::currency::MutationHooks<AccountId, CurrencyId, Balance> for CurrencyHooks {98 type OnDust = orml_tokens::TransferDust<Runtime, TreasuryAccountId>;99 type OnSlash = ();100 type PreTransfer = ();101 type PostTransfer = ();102 type PreDeposit = ();103 type PostDeposit = ();104 type OnNewTokenAccount = ();105 type OnKilledTokenAccount = ();106}10762108impl orml_vesting::Config for Runtime {63impl orml_vesting::Config for Runtime {109 type RuntimeEvent = RuntimeEvent;64 type RuntimeEvent = RuntimeEvent;115 type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;70 type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;116}71}117118impl orml_tokens::Config for Runtime {119 type RuntimeEvent = RuntimeEvent;120 type Balance = Balance;121 type Amount = Amount;122 type CurrencyId = CurrencyId;123 type WeightInfo = ();124 type ExistentialDeposits = ExistentialDeposits;125 type CurrencyHooks = CurrencyHooks;126 type MaxLocks = MaxLocks;127 type MaxReserves = MaxReserves;128 // TODO: Add all module accounts129 type DustRemovalWhitelist = DustRemovalWhitelist;130 /// The id type for named reserves.131 type ReserveIdentifier = ();132}13372134impl orml_xtokens::Config for Runtime {73impl orml_xtokens::Config for Runtime {135 type RuntimeEvent = RuntimeEvent;74 type RuntimeEvent = RuntimeEvent;136 type Balance = Balance;75 type Balance = Balance;137 type CurrencyId = CurrencyId;76 type CurrencyId = CollectionId;138 type CurrencyIdConvert = CurrencyIdConvert;77 type CurrencyIdConvert = CurrencyIdConvert<Self>;139 type AccountIdToMultiLocation = AccountIdToMultiLocation;78 type AccountIdToMultiLocation = AccountIdToMultiLocation;140 type SelfLocation = SelfLocation;79 type SelfLocation = SelfLocation;141 type XcmExecutor = XcmExecutor<XcmExecutorConfig<Self>>;80 type XcmExecutor = XcmExecutor<XcmExecutorConfig<Self>>;runtime/common/config/pallets/foreign_asset.rsdiffbeforeafterboth1use up_common::types::AccountId;1use frame_support::{parameter_types, PalletId};223use crate::{Balances, Runtime, RuntimeEvent};3use crate::{runtime_common::config::governance, Runtime, RuntimeEvent};45parameter_types! {6 pub ForeignAssetPalletId: PalletId = PalletId(*b"frgnasts");7}485impl pallet_foreign_assets::Config for Runtime {9impl pallet_foreign_assets::Config for Runtime {6 type RuntimeEvent = RuntimeEvent;10 type RuntimeEvent = RuntimeEvent;7 type Currency = Balances;11 type ForceRegisterOrigin = governance::RootOrTechnicalCommitteeMember;8 type RegisterOrigin = frame_system::EnsureRoot<AccountId>;12 type PalletId = ForeignAssetPalletId;9 type WeightInfo = pallet_foreign_assets::weights::SubstrateWeight<Self>;13 type WeightInfo = pallet_foreign_assets::weights::SubstrateWeight<Self>;10}14}1115runtime/common/config/xcm.rsdiffbeforeafterbothno changes
runtime/common/config/xcm/foreignassets.rsdiffbeforeafterbothno changes
runtime/common/config/xcm/mod.rsdiffbeforeafterbothno changes
runtime/common/config/xcm/nativeassets.rsdiffbeforeafterbothno changes
runtime/common/construct_runtime.rsdiffbeforeafterboth47 Vesting: orml_vesting = 37,47 Vesting: orml_vesting = 37,484849 XTokens: orml_xtokens = 38,49 XTokens: orml_xtokens = 38,50 Tokens: orml_tokens = 39,50 // [REMOVED] Tokens: orml_tokens = 39,51 // Contracts: pallet_contracts::{Pallet, Call, Storage, Event<T>} = 38,51 // Contracts: pallet_contracts::{Pallet, Call, Storage, Event<T>} = 38,525253 #[cfg(feature = "governance")]53 #[cfg(feature = "governance")]runtime/common/dispatch.rsdiffbeforeafterboth17use frame_support::{dispatch::DispatchResult, ensure, fail};17use frame_support::{dispatch::DispatchResult, ensure, fail};18use pallet_balances_adapter::NativeFungibleHandle;18use pallet_balances_adapter::NativeFungibleHandle;19pub use pallet_common::dispatch::CollectionDispatch;19pub use pallet_common::dispatch::CollectionDispatch;20#[cfg(not(feature = "refungible"))]21use pallet_common::unsupported;22use pallet_common::{20use pallet_common::{23 erc::CommonEvmHandler, eth::map_eth_to_id, CollectionById, CollectionHandle,21 erc::CommonEvmHandler, eth::map_eth_to_id, unsupported, CollectionById, CollectionHandle,24 CommonCollectionOperations,22 CommonCollectionOperations, Pallet as PalletCommon,25};23};26use pallet_evm::{PrecompileHandle, PrecompileResult};24use pallet_evm::{PrecompileHandle, PrecompileResult};27use pallet_fungible::{FungibleHandle, Pallet as PalletFungible};25use pallet_fungible::{FungibleHandle, Pallet as PalletFungible};73 payer: T::CrossAccountId,71 payer: T::CrossAccountId,74 data: CreateCollectionData<T::CrossAccountId>,72 data: CreateCollectionData<T::CrossAccountId>,75 ) -> Result<CollectionId, DispatchError> {73 ) -> Result<CollectionId, DispatchError> {76 let id = match data.mode {74 match data.mode {77 CollectionMode::NFT => <PalletNonfungible<T>>::init_collection(sender, payer, data)?,78 CollectionMode::Fungible(decimal_points) => {75 CollectionMode::Fungible(decimal_points) => {79 // check params76 // check params80 ensure!(77 ensure!(81 decimal_points <= MAX_DECIMAL_POINTS,78 decimal_points <= MAX_DECIMAL_POINTS,82 pallet_unique::Error::<T>::CollectionDecimalPointLimitExceeded79 pallet_unique::Error::<T>::CollectionDecimalPointLimitExceeded83 );80 );84 <PalletFungible<T>>::init_collection(sender, payer, data)?85 }81 }8687 #[cfg(feature = "refungible")]88 CollectionMode::ReFungible => <PalletRefungible<T>>::init_collection(sender, payer, data)?,898290 #[cfg(not(feature = "refungible"))]83 #[cfg(not(feature = "refungible"))]91 CollectionMode::ReFungible => return unsupported!(T),84 CollectionMode::ReFungible => return unsupported!(T),8586 _ => {}92 };87 };8893 Ok(id)89 <PalletCommon<T>>::init_collection(sender, payer, data)94 }90 }9192 fn create_foreign(93 sender: <T>::CrossAccountId,94 data: CreateCollectionData<<T>::CrossAccountId>,95 ) -> Result<CollectionId, DispatchError> {96 match data.mode {97 CollectionMode::Fungible(decimal_points) => {98 // check params99 ensure!(100 decimal_points <= MAX_DECIMAL_POINTS,101 pallet_unique::Error::<T>::CollectionDecimalPointLimitExceeded102 );103 }104105 CollectionMode::ReFungible => return unsupported!(T),106 _ => {}107 };108109 <PalletCommon<T>>::init_foreign_collection(sender, data)110 }9511196 fn destroy(sender: T::CrossAccountId, collection_id: CollectionId) -> DispatchResult {112 fn destroy(sender: T::CrossAccountId, collection_id: CollectionId) -> DispatchResult {97 if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {113 if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {