difftreelog
fix restore foreign flag, minor fixes
in: master
11 files changed
pallets/common/src/benchmarking.rsdiffbeforeafterboth--- a/pallets/common/src/benchmarking.rs
+++ b/pallets/common/src/benchmarking.rs
@@ -121,7 +121,7 @@
owner,
CollectionMode::NFT,
|owner: T::CrossAccountId, data| {
- <Pallet<T>>::init_collection(owner.clone(), Some(owner), data)
+ <Pallet<T>>::init_collection(owner.clone(), Some(owner), false, data)
},
|h| h,
)
pallets/common/src/dispatch.rsdiffbeforeafterboth--- a/pallets/common/src/dispatch.rs
+++ b/pallets/common/src/dispatch.rs
@@ -78,6 +78,21 @@
sender: T::CrossAccountId,
payer: Option<T::CrossAccountId>,
data: CreateCollectionData<T::CrossAccountId>,
+ ) -> Result<CollectionId, DispatchError> {
+ Self::create_internal(sender, payer, false, data)
+ }
+
+ /// Create a collection. The collection will be created according to the value of [`data.mode`](CreateCollectionData::mode).
+ ///
+ /// * `sender` - The user who will become the owner of the collection.
+ /// * `payer` - If set, the user who pays the collection creation deposit.
+ /// * `data` - Description of the created collection.
+ /// * `is_special_collection` -- Whether this collection is a system one, i.e. can have special flags set.
+ fn create_internal(
+ sender: T::CrossAccountId,
+ payer: Option<T::CrossAccountId>,
+ is_special_collection: bool,
+ data: CreateCollectionData<T::CrossAccountId>,
) -> Result<CollectionId, DispatchError>;
/// Delete the collection.
pallets/common/src/lib.rsdiffbeforeafterboth--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -1088,6 +1088,7 @@
read_only: flags.external,
flags: RpcCollectionFlags {
+ foreign: flags.foreign,
erc721metadata: flags.erc721metadata,
},
})
@@ -1129,12 +1130,16 @@
/// * `owner` - The owner of the collection.
/// * `payer` - If set, the user that will pay a deposit for the collection creation.
/// * `data` - Description of the created collection.
+ /// * `is_special_collection` -- Whether this collection is a special one, i.e. can have special flags set.
pub fn init_collection(
owner: T::CrossAccountId,
payer: Option<T::CrossAccountId>,
+ is_special_collection: bool,
data: CreateCollectionData<T::CrossAccountId>,
) -> Result<CollectionId, DispatchError> {
- ensure!(data.flags.is_allowed_for_user(), <Error<T>>::NoPermission);
+ if !is_special_collection {
+ ensure!(data.flags.is_allowed_for_user(), <Error<T>>::NoPermission);
+ }
// Take a (non-refundable) deposit of collection creation
if let Some(payer) = payer {
pallets/foreign-assets/src/lib.rsdiffbeforeafterboth1// 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//! ## Overview20//!21//! The Foreign Assets is a proxy that maps XCM operations to the Unique Network's pallets logic.2223#![cfg_attr(not(feature = "std"), no_std)]24#![allow(clippy::unused_unit)]2526use frame_support::{dispatch::DispatchResult, pallet_prelude::*, traits::EnsureOrigin, PalletId};27use frame_system::pallet_prelude::*;28use pallet_common::{29 dispatch::CollectionDispatch, erc::CrossAccountId, XcmExtensions, NATIVE_FUNGIBLE_COLLECTION_ID,30};31use sp_runtime::traits::AccountIdConversion;32use sp_std::{vec, vec::Vec};33use staging_xcm::{34 opaque::latest::{prelude::XcmError, Weight},35 v3::{prelude::*, MultiAsset, XcmContext},36};37use staging_xcm_executor::{38 traits::{ConvertLocation, Error as XcmExecutorError, TransactAsset, WeightTrader},39 Assets,40};41use up_data_structs::{42 budget::ZeroBudget, CollectionId, CollectionMode, CollectionName, CreateCollectionData,43 CreateFungibleData, CreateItemData, CreateNftData, Property, PropertyKey, TokenId,44};4546pub mod weights;4748#[cfg(feature = "runtime-benchmarks")]49mod benchmarking;5051pub use module::*;52pub use weights::WeightInfo;5354#[frame_support::pallet]55pub mod module {56 use up_data_structs::{57 CollectionDescription, Property, PropertyKeyPermission, PropertyPermission,58 };5960 use super::*;6162 #[pallet::config]63 pub trait Config:64 frame_system::Config65 + pallet_common::Config66 + pallet_fungible::Config67 + pallet_balances::Config68 {69 /// The overarching event type.70 type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;7172 /// Origin for force registering of a foreign asset.73 type ForceRegisterOrigin: EnsureOrigin<Self::RuntimeOrigin>;7475 /// The ID of the foreign assets pallet.76 type PalletId: Get<PalletId>;7778 /// Self-location of this parachain.79 type SelfLocation: Get<MultiLocation>;8081 /// The converter from a MultiLocation to a CrossAccountId.82 type LocationToAccountId: ConvertLocation<Self::CrossAccountId>;8384 /// Weight information for the extrinsics in this module.85 type WeightInfo: WeightInfo;86 }8788 #[pallet::error]89 pub enum Error<T> {90 /// The foreign asset is already registered91 ForeignAssetAlreadyRegistered,92 }9394 #[pallet::event]95 #[pallet::generate_deposit(fn deposit_event)]96 pub enum Event<T: Config> {97 /// The foreign asset registered.98 ForeignAssetRegistered {99 asset_id: CollectionId,100 reserve_location: MultiLocation,101 },102 }103104 /// The corresponding collections of reserve locations.105 #[pallet::storage]106 #[pallet::getter(fn foreign_reserve_location_to_collection)]107 pub type ForeignReserveLocationToCollection<T: Config> =108 StorageMap<_, Twox64Concat, staging_xcm::v3::MultiLocation, CollectionId, OptionQuery>;109110 /// The corresponding reserve location of collections.111 #[pallet::storage]112 #[pallet::getter(fn collection_to_foreign_reserve_location)]113 pub type CollectionToForeignReserveLocation<T: Config> =114 StorageMap<_, Twox64Concat, CollectionId, staging_xcm::v3::MultiLocation, 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 if <ForeignReserveLocationToCollection<T>>::contains_key(reserve_location) {144 return Err(<Error<T>>::ForeignAssetAlreadyRegistered.into());145 }146147 let foreign_collection_owner = Self::pallet_account();148149 let description: CollectionDescription = "Foreign Assets Collection"150 .encode_utf16()151 .collect::<Vec<_>>()152 .try_into()153 .expect("description length < max description length; qed");154155 let payer = None;156 let collection_id = T::CollectionDispatch::create(157 foreign_collection_owner,158 payer,159 CreateCollectionData {160 name,161 description,162 mode,163164 properties: vec![Property {165 key: Self::reserve_location_property_key(),166 value: reserve_location167 .encode()168 .try_into()169 .expect("multilocation is less than 32k; qed"),170 }]171 .try_into()172 .expect("just one property can always be stored; qed"),173174 token_property_permissions: vec![PropertyKeyPermission {175 key: Self::reserve_asset_instance_property_key(),176 permission: PropertyPermission {177 mutable: false,178 collection_admin: true,179 token_owner: false,180 },181 }]182 .try_into()183 .expect("just one property permission can always be stored; qed"),184 ..Default::default()185 },186 )?;187188 <ForeignReserveLocationToCollection<T>>::insert(reserve_location, collection_id);189 <CollectionToForeignReserveLocation<T>>::insert(collection_id, reserve_location);190191 Self::deposit_event(Event::<T>::ForeignAssetRegistered {192 asset_id: collection_id,193 reserve_location,194 });195196 Ok(())197 }198 }199}200201impl<T: Config> Pallet<T> {202 fn pallet_account() -> T::CrossAccountId {203 let owner: T::AccountId = T::PalletId::get().into_account_truncating();204 T::CrossAccountId::from_sub(owner)205 }206207 fn reserve_location_property_key() -> PropertyKey {208 b"reserve-location"209 .to_vec()210 .try_into()211 .expect("key length < max property key length; qed")212 }213214 fn reserve_asset_instance_property_key() -> PropertyKey {215 b"reserve-asset-instance"216 .to_vec()217 .try_into()218 .expect("key length < max property key length; qed")219 }220221 /// Converts a multilocation to the Unique Network's local collection222 /// (i.e. the collection originally created on the Unique Network's parachain).223 ///224 /// The multilocation corresponds to a Unique Network's collection if:225 /// * It is `Here` location that corresponds to the native token of this parachain.226 /// * It is `../Parachain(<Unique Network Para ID>)` that also corresponds to the native token of this parachain.227 /// * It is `../Parachain(<Unique Network Para ID>)/GeneralIndex(<Collection ID>)` that corresponds228 /// to the collection with the ID equal to `<Collection ID>`. The `<Collection ID>` must be in the valid range,229 /// otherwise the `AssetIdConversionFailed` error will be returned.230 ///231 /// If the multilocation doesn't match the patterns listed above, the function returns `Ok(None)`,232 /// identifying that the given multilocation doesn't correspond to a local collection.233 fn native_asset_location_to_collection(234 asset_location: &MultiLocation,235 ) -> Result<Option<CollectionId>, XcmError> {236 let self_location = T::SelfLocation::get();237238 if *asset_location == Here.into() {239 Ok(Some(NATIVE_FUNGIBLE_COLLECTION_ID))240 } else if *asset_location == self_location {241 Ok(Some(NATIVE_FUNGIBLE_COLLECTION_ID))242 } else if asset_location.parents == self_location.parents {243 match asset_location244 .interior245 .match_and_split(&self_location.interior)246 {247 Some(GeneralIndex(collection_id)) => Ok(Some(CollectionId(248 (*collection_id)249 .try_into()250 .map_err(|_| XcmExecutorError::AssetIdConversionFailed)?,251 ))),252 _ => Ok(None),253 }254 } else {255 Ok(None)256 }257 }258259 /// Converts a multiasset to a Unique Network's collection (either local or the foreign one).260 ///261 /// The function will try to convert the multiasset's reserve location262 /// to the Unique Network's local collection.263 ///264 /// If the multilocation doesn't correspond to a local collection,265 /// the function will check if the reserve location has the corresponding266 /// derivative Unique Network's collection, and will return the said collection ID if found.267 ///268 /// If all of the above have failed, the `AssetIdConversionFailed` error will be returned.269 fn multiasset_to_collection(asset: &MultiAsset) -> Result<CollectionId, XcmError> {270 let AssetId::Concrete(asset_reserve_location) = asset.id else {271 return Err(XcmExecutorError::AssetNotHandled.into());272 };273274 Self::native_asset_location_to_collection(&asset_reserve_location)?275 .or_else(|| Self::foreign_reserve_location_to_collection(asset_reserve_location))276 .ok_or_else(|| XcmExecutorError::AssetIdConversionFailed.into())277 }278279 /// Converts an XCM asset instance to the Unique Network's token ID.280 ///281 /// The asset instance corresponds to the Unique Network's token ID if it is in the following format:282 /// `AssetInstance::Index(<token ID>)`.283 ///284 /// If the asset instance is not in the valid format or the `<token ID>` points to a non-existent token,285 /// the `AssetNotFound` error will be returned.286 fn native_asset_instance_to_token_id(287 asset_instance: &AssetInstance,288 ) -> Result<TokenId, XcmError> {289 match asset_instance {290 AssetInstance::Index(token_id) => Ok(TokenId(291 (*token_id)292 .try_into()293 .map_err(|_| XcmError::AssetNotFound)?,294 )),295 _ => Err(XcmError::AssetNotFound),296 }297 }298299 /// Obtains the token ID of the `asset_instance` in the collection.300 ///301 /// Returns `Ok(None)` only if the `asset_instance` is a part of a foreign collection302 /// and the item hasn't yet been created on this blockchain.303 ///304 /// If the `asset_instance` exists and it is a part of a foreign collection, the function will return `Ok(Some(<token ID>))`.305 ///306 /// If the `asset_instance` is a part of a local collection,307 /// the function will return either `Ok(Some(<token ID>))` or an error if the token is not found.308 fn asset_instance_to_token_id(309 collection_id: CollectionId,310 asset_instance: &AssetInstance,311 ) -> Result<Option<TokenId>, XcmError> {312 if <CollectionToForeignReserveLocation<T>>::contains_key(collection_id) {313 Ok(Self::foreign_reserve_asset_instance_to_token_id(314 collection_id,315 asset_instance,316 ))317 } else {318 Self::native_asset_instance_to_token_id(asset_instance).map(Some)319 }320 }321322 /// Creates a foreign item in the the collection.323 fn create_foreign_asset_instance(324 xcm_ext: &dyn XcmExtensions<T>,325 collection_id: CollectionId,326 asset_instance: &AssetInstance,327 to: T::CrossAccountId,328 ) -> DispatchResult {329 let asset_instance_encoded = asset_instance.encode();330331 let derivative_token_id = xcm_ext.create_item(332 &Self::pallet_account(),333 to,334 CreateItemData::NFT(CreateNftData {335 properties: vec![Property {336 key: Self::reserve_asset_instance_property_key(),337 value: asset_instance_encoded338 .try_into()339 .expect("asset instance length <= 32 bytes which is less than value length limit; qed"),340 }]341 .try_into()342 .expect("just one property can always be stored; qed"),343 }),344 &ZeroBudget,345 )?;346347 <ForeignReserveAssetInstanceToTokenId<T>>::insert(348 collection_id,349 asset_instance,350 derivative_token_id,351 );352353 Ok(())354 }355356 /// Deposits an asset instance to the `to` account.357 ///358 /// Either transfers an existing item from the pallet's account359 /// or creates a foreign item.360 fn deposit_asset_instance(361 xcm_ext: &dyn XcmExtensions<T>,362 collection_id: CollectionId,363 asset_instance: &AssetInstance,364 to: T::CrossAccountId,365 ) -> XcmResult {366 let deposit_result = if let Some(token_id) =367 Self::asset_instance_to_token_id(collection_id, asset_instance)?368 {369 let depositor = &Self::pallet_account();370 let from = depositor;371 let amount = 1;372373 xcm_ext.transfer_item(depositor, from, &to, token_id, amount, &ZeroBudget)374 } else {375 Self::create_foreign_asset_instance(xcm_ext, collection_id, asset_instance, to)376 };377378 deposit_result379 .map_err(|_| XcmError::FailedToTransactAsset("non-fungible item deposit failed"))380 }381382 /// Withdraws an asset instance from the `from` account.383 ///384 /// Transfers the asset instance to the pallet's account.385 ///386 /// Won't withdraw the instance if it has children.387 fn withdraw_asset_instance(388 xcm_ext: &dyn XcmExtensions<T>,389 collection_id: CollectionId,390 asset_instance: &AssetInstance,391 from: T::CrossAccountId,392 ) -> XcmResult {393 let token_id = Self::asset_instance_to_token_id(collection_id, &asset_instance)?394 .ok_or(XcmError::AssetNotFound)?;395396 if xcm_ext.token_has_children(token_id) {397 return Err(XcmError::Unimplemented);398 }399400 let depositor = &from;401 let to = Self::pallet_account();402 let amount = 1;403 xcm_ext404 .transfer_item(depositor, &from, &to, token_id, amount, &ZeroBudget)405 .map_err(|_| XcmError::FailedToTransactAsset("nonfungible item withdraw failed"))?;406407 Ok(())408 }409}410411impl<T: Config> TransactAsset for Pallet<T> {412 fn can_check_in(413 _origin: &MultiLocation,414 _what: &MultiAsset,415 _context: &XcmContext,416 ) -> XcmResult {417 Err(XcmError::Unimplemented)418 }419420 fn check_in(_origin: &MultiLocation, _what: &MultiAsset, _context: &XcmContext) {}421422 fn can_check_out(423 _dest: &MultiLocation,424 _what: &MultiAsset,425 _context: &XcmContext,426 ) -> XcmResult {427 Err(XcmError::Unimplemented)428 }429430 fn check_out(_dest: &MultiLocation, _what: &MultiAsset, _context: &XcmContext) {}431432 fn deposit_asset(what: &MultiAsset, to: &MultiLocation, _context: &XcmContext) -> XcmResult {433 let to = T::LocationToAccountId::convert_location(to)434 .ok_or(XcmExecutorError::AccountIdConversionFailed)?;435436 let collection_id = Self::multiasset_to_collection(what)?;437 let dispatch =438 T::CollectionDispatch::dispatch(collection_id).map_err(|_| XcmError::AssetNotFound)?;439440 let collection = dispatch.as_dyn();441 let xcm_ext = collection.xcm_extensions().ok_or(XcmError::Unimplemented)?;442443 match what.fun {444 Fungibility::Fungible(amount) => xcm_ext445 .create_item(446 &Self::pallet_account(),447 to,448 CreateItemData::Fungible(CreateFungibleData { value: amount }),449 &ZeroBudget,450 )451 .map(|_| ())452 .map_err(|_| XcmError::FailedToTransactAsset("fungible item deposit failed")),453454 Fungibility::NonFungible(asset_instance) => {455 Self::deposit_asset_instance(xcm_ext, collection_id, &asset_instance, to)456 }457 }458 }459460 fn withdraw_asset(461 what: &MultiAsset,462 from: &MultiLocation,463 _maybe_context: Option<&XcmContext>,464 ) -> Result<staging_xcm_executor::Assets, XcmError> {465 let from = T::LocationToAccountId::convert_location(from)466 .ok_or(XcmExecutorError::AccountIdConversionFailed)?;467468 let collection_id = Self::multiasset_to_collection(what)?;469 let dispatch =470 T::CollectionDispatch::dispatch(collection_id).map_err(|_| XcmError::AssetNotFound)?;471472 let collection = dispatch.as_dyn();473 let xcm_ext = collection.xcm_extensions().ok_or(XcmError::NoPermission)?;474475 match what.fun {476 Fungibility::Fungible(amount) => xcm_ext477 .burn_item(from, TokenId::default(), amount)478 .map_err(|_| XcmError::FailedToTransactAsset("fungible item withdraw failed"))?,479480 Fungibility::NonFungible(asset_instance) => {481 Self::withdraw_asset_instance(xcm_ext, collection_id, &asset_instance, from)?;482 }483 }484485 Ok(what.clone().into())486 }487488 fn internal_transfer_asset(489 what: &MultiAsset,490 from: &MultiLocation,491 to: &MultiLocation,492 _context: &XcmContext,493 ) -> Result<staging_xcm_executor::Assets, XcmError> {494 let from = T::LocationToAccountId::convert_location(from)495 .ok_or(XcmExecutorError::AccountIdConversionFailed)?;496497 let to = T::LocationToAccountId::convert_location(to)498 .ok_or(XcmExecutorError::AccountIdConversionFailed)?;499500 let collection_id = Self::multiasset_to_collection(what)?;501502 let dispatch =503 T::CollectionDispatch::dispatch(collection_id).map_err(|_| XcmError::AssetNotFound)?;504 let collection = dispatch.as_dyn();505 let xcm_ext = collection.xcm_extensions().ok_or(XcmError::NoPermission)?;506507 let depositor = &from;508509 let token_id;510 let amount;511 let map_error: fn(DispatchError) -> XcmError;512513 match what.fun {514 Fungibility::Fungible(fungible_amount) => {515 token_id = TokenId::default();516 amount = fungible_amount;517 map_error = |_| XcmError::FailedToTransactAsset("fungible item transfer failed");518 }519520 Fungibility::NonFungible(asset_instance) => {521 token_id = Self::asset_instance_to_token_id(collection_id, &asset_instance)?522 .ok_or(XcmError::AssetNotFound)?;523524 amount = 1;525 map_error = |_| XcmError::FailedToTransactAsset("nonfungible item transfer failed")526 }527 }528529 xcm_ext530 .transfer_item(depositor, &from, &to, token_id, amount, &ZeroBudget)531 .map_err(map_error)?;532533 Ok(what.clone().into())534 }535}536537pub struct CurrencyIdConvert<T: Config>(PhantomData<T>);538impl<T: Config> sp_runtime::traits::Convert<CollectionId, Option<MultiLocation>>539 for CurrencyIdConvert<T>540{541 fn convert(collection_id: CollectionId) -> Option<MultiLocation> {542 if collection_id == NATIVE_FUNGIBLE_COLLECTION_ID {543 Some(Here.into())544 } else {545 <Pallet<T>>::collection_to_foreign_reserve_location(collection_id).or_else(|| {546 T::SelfLocation::get()547 .pushed_with_interior(GeneralIndex(collection_id.0.into()))548 .ok()549 })550 }551 }552}553554pub use frame_support::{555 traits::{556 fungibles::Balanced, tokens::currency::Currency as CurrencyT, OnUnbalanced as OnUnbalancedT,557 },558 weights::{WeightToFee, WeightToFeePolynomial},559};560561pub struct FreeForAll;562563impl WeightTrader for FreeForAll {564 fn new() -> Self {565 Self566 }567568 fn buy_weight(569 &mut self,570 weight: Weight,571 payment: Assets,572 _xcm: &XcmContext,573 ) -> Result<Assets, XcmError> {574 log::trace!(target: "fassets::weight", "buy_weight weight: {:?}, payment: {:?}", weight, payment);575 Ok(payment)576 }577}pallets/fungible/src/benchmarking.rsdiffbeforeafterboth--- a/pallets/fungible/src/benchmarking.rs
+++ b/pallets/fungible/src/benchmarking.rs
@@ -31,7 +31,7 @@
owner,
CollectionMode::Fungible(0),
|owner: T::CrossAccountId, data| {
- <PalletCommon<T>>::init_collection(owner.clone(), Some(owner), data)
+ <PalletCommon<T>>::init_collection(owner.clone(), Some(owner), false, data)
},
FungibleHandle::cast,
)
pallets/nonfungible/src/benchmarking.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/benchmarking.rs
+++ b/pallets/nonfungible/src/benchmarking.rs
@@ -58,7 +58,7 @@
owner,
CollectionMode::NFT,
|owner: T::CrossAccountId, data| {
- <PalletCommon<T>>::init_collection(owner.clone(), Some(owner), data)
+ <PalletCommon<T>>::init_collection(owner.clone(), Some(owner), false, data)
},
NonfungibleHandle::cast,
)
pallets/refungible/src/benchmarking.rsdiffbeforeafterboth--- a/pallets/refungible/src/benchmarking.rs
+++ b/pallets/refungible/src/benchmarking.rs
@@ -20,6 +20,7 @@
use pallet_common::{
bench_init,
benchmarking::{create_collection_raw, property_key, property_value},
+ Pallet as PalletCommon,
};
use sp_std::prelude::*;
use up_data_structs::{
@@ -61,7 +62,9 @@
create_collection_raw(
owner,
CollectionMode::ReFungible,
- |owner: T::CrossAccountId, data| <Pallet<T>>::init_collection(owner.clone(), owner, data),
+ |owner: T::CrossAccountId, data| {
+ <PalletCommon<T>>::init_collection(owner.clone(), Some(owner), false, data)
+ },
RefungibleHandle::cast,
)
}
pallets/refungible/src/lib.rsdiffbeforeafterboth--- a/pallets/refungible/src/lib.rs
+++ b/pallets/refungible/src/lib.rs
@@ -103,7 +103,7 @@
use sp_runtime::{ArithmeticError, DispatchError, DispatchResult, TransactionOutcome};
use sp_std::{collections::btree_map::BTreeMap, vec, vec::Vec};
use up_data_structs::{
- budget::Budget, mapping::TokenAddressMapping, AccessMode, CollectionId, CreateCollectionData,
+ budget::Budget, mapping::TokenAddressMapping, AccessMode, CollectionId,
CreateRefungibleExMultipleOwners, PropertiesPermissionMap, Property, PropertyKey,
PropertyKeyPermission, PropertyScope, PropertyValue, TokenId, TokenOwnerError,
TokenProperties as TokenPropertiesT, MAX_REFUNGIBLE_PIECES,
@@ -296,19 +296,6 @@
// unchecked calls skips any permission checks
impl<T: Config> Pallet<T> {
- /// Create RFT collection
- ///
- /// `init_collection` will take non-refundable deposit for collection creation.
- ///
- /// - `data`: Contains settings for collection limits and permissions.
- pub fn init_collection(
- owner: T::CrossAccountId,
- payer: T::CrossAccountId,
- data: CreateCollectionData<T::CrossAccountId>,
- ) -> Result<CollectionId, DispatchError> {
- <PalletCommon<T>>::init_collection(owner, Some(payer), data)
- }
-
/// Destroy RFT collection
///
/// `destroy_collection` will throw error if collection contains any tokens.
primitives/data-structs/src/lib.rsdiffbeforeafterboth--- a/primitives/data-structs/src/lib.rs
+++ b/primitives/data-structs/src/lib.rs
@@ -380,7 +380,7 @@
pub struct CollectionFlags {
/// Reserved flag
#[bondrewd(bits = "0..1")]
- pub reserved_0: bool,
+ pub foreign: bool,
/// Supports ERC721Metadata
#[bondrewd(bits = "1..2")]
pub erc721metadata: bool,
@@ -395,7 +395,7 @@
impl CollectionFlags {
pub fn is_allowed_for_user(self) -> bool {
- !self.reserved_0 && !self.external && self.reserved == 0
+ !self.foreign && !self.external && self.reserved == 0
}
}
@@ -461,6 +461,8 @@
#[derive(Debug, Encode, Decode, Clone, PartialEq, TypeInfo, Serialize, Deserialize)]
pub struct RpcCollectionFlags {
+ /// Is collection is foreign.
+ pub foreign: bool,
/// Collection supports ERC721Metadata.
pub erc721metadata: bool,
}
@@ -503,7 +505,7 @@
pub read_only: bool,
/// Extra collection flags
- #[version(2.., upper(RpcCollectionFlags {erc721metadata: false}))]
+ #[version(2.., upper(RpcCollectionFlags {foreign: false, erc721metadata: false}))]
pub flags: RpcCollectionFlags,
}
@@ -540,6 +542,7 @@
read_only: true,
flags: RpcCollectionFlags {
+ foreign: false,
erc721metadata: false,
},
}
runtime/common/config/pallets/foreign_asset.rsdiffbeforeafterboth--- a/runtime/common/config/pallets/foreign_asset.rs
+++ b/runtime/common/config/pallets/foreign_asset.rs
@@ -1,4 +1,6 @@
use frame_support::{parameter_types, PalletId};
+#[cfg(not(feature = "governance"))]
+use frame_system::EnsureRoot;
use pallet_evm::account::CrossAccountId;
use sp_core::H160;
use staging_xcm::prelude::*;
@@ -6,10 +8,6 @@
#[cfg(feature = "governance")]
use crate::runtime_common::config::governance;
-
-#[cfg(not(feature = "governance"))]
-use frame_system::EnsureRoot;
-
use crate::{
runtime_common::config::{
ethereum::CrossAccountId as ConfigCrossAccountId,
runtime/common/dispatch.rsdiffbeforeafterboth--- a/runtime/common/dispatch.rs
+++ b/runtime/common/dispatch.rs
@@ -66,9 +66,10 @@
}
}
- fn create(
+ fn create_internal(
sender: T::CrossAccountId,
payer: Option<T::CrossAccountId>,
+ is_special_collection: bool,
data: CreateCollectionData<T::CrossAccountId>,
) -> Result<CollectionId, DispatchError> {
match data.mode {
@@ -86,7 +87,7 @@
_ => {}
};
- <PalletCommon<T>>::init_collection(sender, payer, data)
+ <PalletCommon<T>>::init_collection(sender, payer, is_special_collection, data)
}
fn destroy(sender: T::CrossAccountId, collection_id: CollectionId) -> DispatchResult {