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

difftreelog

refactor draft foreign assets as proxy to collections

Daniel Shiposha2023-10-17parent: #bfab603.patch.diff
in: master

18 files changed

modifiednode/cli/src/chain_spec.rsdiffbeforeafterboth
167 .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 },
modifiedpallets/balances-adapter/src/common.rsdiffbeforeafterboth
332 0332 0
333 }333 }
334
335 fn refungible_extensions(&self) -> Option<&dyn pallet_common::RefungibleExtensions<T>> {
336 None
337 }
338334
339 fn set_allowance_for_all(335 fn set_allowance_for_all(
340 &self,336 &self,
modifiedpallets/common/src/dispatch.rsdiffbeforeafterboth
72 /// 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>;
82
83 /// 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>;
8191
82 /// Delete the collection.92 /// Delete the collection.
83 ///93 ///
modifiedpallets/common/src/lib.rsdiffbeforeafterboth
1133 ) -> 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);
1135
1136 // Take a (non-refundable) deposit of collection creation
1137 {
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)?;
1147
1148 debug_assert!(credit.peek().is_zero())
1149 }
1150
1135 Self::init_collection_internal(owner, payer, data)1151 Self::init_collection_internal(owner, data)
1136 }1152 }
11371153
1138 /// 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 }
11481163
1149 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);
1227
1228 // Take a (non-refundable) deposit of collection creation
1229 {
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)?;
1239
1240 debug_assert!(credit.peek().is_zero())
1241 }
12421241
1243 <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;
22942293
2295 /// 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 None
2297 }
2298
2299 /// Get XCM extensions.
2300 fn xcm_extensions(&self) -> Option<&dyn XcmExtensions<T>> {
2301 None
2302 }
22972303
2298 /// 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 owner
2333 ) -> DispatchResultWithPostInfo;2339 ) -> DispatchResultWithPostInfo;
2334}2340}
2341
2342/// XCM extensions for fungible and NFT collections
2343pub trait XcmExtensions<T>
2344where
2345 T: Config,
2346{
2347 /// Is the collection a foreign one?
2348 fn is_foreign(&self) -> bool;
2349
2350 /// Create a collection's item.
2351 fn create_item(
2352 &self,
2353 to: T::CrossAccountId,
2354 data: CreateItemData,
2355 ) -> Result<TokenId, DispatchError>;
2356
2357 /// 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;
2365
2366 /// Burn a collection's item.
2367 fn burn(&self, from: T::CrossAccountId, token: TokenId, amount: u128) -> DispatchResult;
2368}
23352369
2336/// Merge [`DispatchResult`] with [`Weight`] into [`DispatchResultWithPostInfo`].2370/// Merge [`DispatchResult`] with [`Weight`] into [`DispatchResultWithPostInfo`].
2337///2371///
deletedpallets/foreign-assets/src/impl_fungibles.rsdiffbeforeafterboth

no changes

modifiedpallets/foreign-assets/src/lib.rsdiffbeforeafterboth
34#![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)]
3636
37use 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 the
55// 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};
6257
63// TODO: Move to primitives
64// Id of native currency.
65// 0 - QTZ\UNQ
66// 1 - KSM\DOT
67#[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}
86
87#[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}
106
107pub trait TryAsForeign<T, F> {
108 fn try_as_foreign(asset: T) -> Option<F>;
109}
110
111impl 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}
119
120pub type ForeignAssetId = u32;
121pub type CurrencyId = AssetId;
122
123mod impl_fungibles;
124pub mod weights;58pub mod weights;
12559
126#[cfg(feature = "runtime-benchmarks")]60#[cfg(feature = "runtime-benchmarks")]
129pub use module::*;63pub use module::*;
130pub use weights::WeightInfo;64pub use weights::WeightInfo;
13165
132/// Type alias for currency balance.
133pub type BalanceOf<T> =
134 <<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
135
136/// 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}
145
146pub struct XcmForeignAssetIdMapping<T>(sp_std::marker::PhantomData<T>);
147
148impl<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 }
155
156 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 }
160
161 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}
166
167#[frame_support::pallet]66#[frame_support::pallet]
168pub mod module {67pub mod module {
68 use up_data_structs::{
69 CollectionDescription, Property, PropertyKeyPermission, PropertyPermission,
70 };
71
169 use super::*;72 use super::*;
17073
171 #[pallet::config]74 #[pallet::config]
172 pub trait Config:75 pub trait Config:
173 frame_system::Config76 frame_system::Config
174 + pallet_common::Config77 + pallet_common::Config
175 + pallet_fungible::Config78 + pallet_fungible::Config
176 + orml_tokens::Config
177 + pallet_balances::Config79 + pallet_balances::Config
178 {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>;
18183
182 /// 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>;
18486
185 /// Required origin for registering asset.87 /// The ID of the foreign assets pallet.
186 type RegisterOrigin: EnsureOrigin<Self::RuntimeOrigin>;88 type PalletId: Get<PalletId>;
18789
188 /// 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 }
19193
192 pub type AssetName = BoundedVec<u8, ConstU32<32>>;
193 pub type AssetSymbol = BoundedVec<u8, ConstU32<7>>;
194
195 #[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 }
202
203 #[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 registered
206 /// desired version of XCM).
207 BadLocation,
208 /// MultiLocation existed
209 MultiLocationExisted,
210 /// AssetId not exists
211 AssetIdNotExists,
212 /// AssetId exists
213 AssetIdExisted,97 ForeignAssetAlreadyRegistered,
214 }98 }
21599
216 #[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 }
242109
243 /// Next available Foreign AssetId ID.110 /// The corresponding collections of reserve locations.
244 ///
245 /// NextForeignAssetId: ForeignAssetId
246 #[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>;
256115
257 /// The storages for CurrencyIds.116 /// The correponding NFT token id of reserve NFTs
258 ///
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 >;
264127
265 /// 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>;
272
273 /// The storages for assets to fungible collection binding
274 ///
275 #[pallet::storage]
276 #[pallet::getter(fn asset_binding)]
277 pub type AssetBinding<T: Config> =
278 StorageMap<_, Twox64Concat, ForeignAssetId, CollectionId, OptionQuery>;
279
280 #[pallet::pallet]128 #[pallet::pallet]
281 pub struct Pallet<T>(_);129 pub struct Pallet<T>(_);
282130
283 #[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())?;
294142
295 let location: MultiLocation = (*location)143 let foreign_collection_owner = Self::pallet_account();
296 .try_into()
297 .map_err(|()| Error::<T>::BadLocation)?;
298144
299 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");
305150
306 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)?;
317157
318 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_location
321 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"),
325167
326 #[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 )?;
335181
336 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)?;
340183
341 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 });
188
346 Ok(())189 Ok(())
347 }190 }
348 }191 }
349}192}
350193
351impl<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 = current
356 .checked_add(One::one())
357 .ok_or(ArithmeticError::Overflow)?;
358 Ok(id)197 T::CrossAccountId::from_sub(owner)
359 })
360 }198 }
361199
362 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));
375206
376 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}
381214
382 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 }
392223
393 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 })?;
398225
399 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 }
401233
402 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_locations
411 .as_mut()
412 .ok_or(Error::<T>::AssetIdNotExists)?;
413235
414 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>::AssetIdNotExists
420 );238 }
421239
422 // 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>::MultiLocationExisted
431 );
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 }
247
248 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}
447257
258pub 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()?;
269
270 // 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}
283
448pub 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};
454290
455pub 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);
466292
467impl<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 Self
477 }296 }
478297
479 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> Drop
490 for FreeForAll<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>
491where
492 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}
501308
modifiedpallets/fungible/src/common.rsdiffbeforeafterboth
428 <Allowance<T>>::get((self.id, sender, spender))428 <Allowance<T>>::get((self.id, sender, spender))
429 }429 }
430
431 fn refungible_extensions(&self) -> Option<&dyn RefungibleExtensions<T>> {
432 None
433 }
434430
435 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() {
modifiedpallets/fungible/src/lib.rsdiffbeforeafterboth
212212
213/// Pallet implementation for fungible assets213/// Pallet implementation for fungible assets
214impl<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 }
223
224 /// 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 }
232
233 /// Destroys a collection.215 /// Destroys a collection.
234 pub fn destroy_collection(216 pub fn destroy_collection(
modifiedpallets/nonfungible/src/common.rsdiffbeforeafterboth
535 }535 }
536 }536 }
537
538 fn refungible_extensions(&self) -> Option<&dyn RefungibleExtensions<T>> {
539 None
540 }
541537
542 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)) {
modifiedpallets/nonfungible/src/lib.rsdiffbeforeafterboth
383383
384// unchecked calls skips any permission checks384// unchecked calls skips any permission checks
385impl<T: Config> Pallet<T> {385impl<T: Config> Pallet<T> {
386 /// Create NFT collection
387 ///
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 }
398
399 /// Destroy NFT collection386 /// Destroy NFT collection
400 ///387 ///
modifiedruntime/common/config/orml.rsdiffbeforeafterboth
1616
17use 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;
3229
33use 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};
4434
59 };49 };
60}50}
61
62parameter_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_000
70 }
71 };
72}
73
74pub fn get_all_module_accounts() -> Vec<AccountId> {
75 vec![TreasuryAccountId::get()]
76}
77
78pub struct DustRemovalWhitelist;
79impl Contains<AccountId> for DustRemovalWhitelist {
80 fn contains(a: &AccountId) -> bool {
81 get_all_module_accounts().contains(a)
82 }
83}
8451
85pub struct AccountIdToMultiLocation;52pub struct AccountIdToMultiLocation;
86impl Convert<AccountId, MultiLocation> for AccountIdToMultiLocation {53impl Convert<AccountId, MultiLocation> for AccountIdToMultiLocation {
93 }60 }
94}61}
95
96pub 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}
10762
108impl 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}
117
118impl 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 accounts
129 type DustRemovalWhitelist = DustRemovalWhitelist;
130 /// The id type for named reserves.
131 type ReserveIdentifier = ();
132}
13372
134impl 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>>;
modifiedruntime/common/config/pallets/foreign_asset.rsdiffbeforeafterboth
1use up_common::types::AccountId;1use frame_support::{parameter_types, PalletId};
22
3use crate::{Balances, Runtime, RuntimeEvent};3use crate::{runtime_common::config::governance, Runtime, RuntimeEvent};
4
5parameter_types! {
6 pub ForeignAssetPalletId: PalletId = PalletId(*b"frgnasts");
7}
48
5impl 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}
1115
addedruntime/common/config/xcm.rsdiffbeforeafterboth

no changes

deletedruntime/common/config/xcm/foreignassets.rsdiffbeforeafterboth

no changes

deletedruntime/common/config/xcm/mod.rsdiffbeforeafterboth

no changes

deletedruntime/common/config/xcm/nativeassets.rsdiffbeforeafterboth

no changes

modifiedruntime/common/construct_runtime.rsdiffbeforeafterboth
47 Vesting: orml_vesting = 37,47 Vesting: orml_vesting = 37,
4848
49 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,
5252
53 #[cfg(feature = "governance")]53 #[cfg(feature = "governance")]
modifiedruntime/common/dispatch.rsdiffbeforeafterboth
17use 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 params
80 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>::CollectionDecimalPointLimitExceeded
83 );80 );
84 <PalletFungible<T>>::init_collection(sender, payer, data)?
85 }81 }
86
87 #[cfg(feature = "refungible")]
88 CollectionMode::ReFungible => <PalletRefungible<T>>::init_collection(sender, payer, data)?,
8982
90 #[cfg(not(feature = "refungible"))]83 #[cfg(not(feature = "refungible"))]
91 CollectionMode::ReFungible => return unsupported!(T),84 CollectionMode::ReFungible => return unsupported!(T),
85
86 _ => {}
92 };87 };
88
93 Ok(id)89 <PalletCommon<T>>::init_collection(sender, payer, data)
94 }90 }
91
92 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 params
99 ensure!(
100 decimal_points <= MAX_DECIMAL_POINTS,
101 pallet_unique::Error::<T>::CollectionDecimalPointLimitExceeded
102 );
103 }
104
105 CollectionMode::ReFungible => return unsupported!(T),
106 _ => {}
107 };
108
109 <PalletCommon<T>>::init_foreign_collection(sender, data)
110 }
95111
96 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 {