difftreelog
fix clippy
in: master
5 files changed
pallets/common/src/lib.rsdiffbeforeafterboth--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -2387,7 +2387,7 @@
amount: u128,
nesting_budget: &dyn Budget,
) -> DispatchResult {
- if T::CrossTokenAddressMapping::is_token_address(&to) {
+ if T::CrossTokenAddressMapping::is_token_address(to) {
return unsupported!(T);
}
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, CollectionTokenPrefix,43 CreateCollectionData, CreateFungibleData, CreateItemData, CreateNftData, Property, PropertyKey,44 TokenId,45};4647pub mod weights;4849#[cfg(feature = "runtime-benchmarks")]50mod benchmarking;5152pub use module::*;53pub use weights::WeightInfo;5455#[frame_support::pallet]56pub mod module {57 use up_data_structs::{58 CollectionDescription, Property, PropertyKeyPermission, PropertyPermission,59 };6061 use super::*;6263 #[pallet::config]64 pub trait Config:65 frame_system::Config66 + pallet_common::Config67 + pallet_fungible::Config68 + pallet_balances::Config69 {70 /// The overarching event type.71 type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;7273 /// Origin for force registering of a foreign asset.74 type ForceRegisterOrigin: EnsureOrigin<Self::RuntimeOrigin>;7576 /// The ID of the foreign assets pallet.77 type PalletId: Get<PalletId>;7879 /// Self-location of this parachain.80 type SelfLocation: Get<MultiLocation>;8182 /// The converter from a MultiLocation to a CrossAccountId.83 type LocationToAccountId: ConvertLocation<Self::CrossAccountId>;8485 /// Weight information for the extrinsics in this module.86 type WeightInfo: WeightInfo;87 }8889 #[pallet::error]90 pub enum Error<T> {91 /// The foreign asset is already registered.92 ForeignAssetAlreadyRegistered,93 }9495 #[pallet::event]96 #[pallet::generate_deposit(fn deposit_event)]97 pub enum Event<T: Config> {98 /// The foreign asset registered.99 ForeignAssetRegistered {100 asset_id: CollectionId,101 reserve_location: MultiLocation,102 },103 }104105 /// The corresponding collections of reserve locations.106 #[pallet::storage]107 #[pallet::getter(fn foreign_reserve_location_to_collection)]108 pub type ForeignReserveLocationToCollection<T: Config> =109 StorageMap<_, Twox64Concat, staging_xcm::v3::MultiLocation, CollectionId, OptionQuery>;110111 /// The corresponding reserve location of collections.112 #[pallet::storage]113 #[pallet::getter(fn collection_to_foreign_reserve_location)]114 pub type CollectionToForeignReserveLocation<T: Config> =115 StorageMap<_, Twox64Concat, CollectionId, staging_xcm::v3::MultiLocation, OptionQuery>;116117 /// The correponding NFT token id of reserve NFTs118 #[pallet::storage]119 #[pallet::getter(fn foreign_reserve_asset_instance_to_token_id)]120 pub type ForeignReserveAssetInstanceToTokenId<T: Config> = StorageDoubleMap<121 Hasher1 = Twox64Concat,122 Key1 = CollectionId,123 Hasher2 = Twox64Concat,124 Key2 = staging_xcm::v3::AssetInstance,125 Value = TokenId,126 QueryKind = OptionQuery,127 >;128129 #[pallet::pallet]130 pub struct Pallet<T>(_);131132 #[pallet::call]133 impl<T: Config> Pallet<T> {134 #[pallet::call_index(0)]135 #[pallet::weight(<T as Config>::WeightInfo::register_foreign_asset())]136 pub fn force_register_foreign_asset(137 origin: OriginFor<T>,138 reserve_location: MultiLocation,139 name: CollectionName,140 token_prefix: CollectionTokenPrefix,141 mode: ForeignCollectionMode,142 ) -> DispatchResult {143 T::ForceRegisterOrigin::ensure_origin(origin.clone())?;144145 if <ForeignReserveLocationToCollection<T>>::contains_key(reserve_location) {146 return Err(<Error<T>>::ForeignAssetAlreadyRegistered.into());147 }148149 let foreign_collection_owner = Self::pallet_account();150151 let description: CollectionDescription = "Foreign Assets Collection"152 .encode_utf16()153 .collect::<Vec<_>>()154 .try_into()155 .expect("description length < max description length; qed");156157 let payer = None;158 let is_special_collection = true;159 let collection_id = T::CollectionDispatch::create_internal(160 foreign_collection_owner,161 payer,162 is_special_collection,163 CreateCollectionData {164 name,165 token_prefix,166 description,167 mode: mode.into(),168169 properties: vec![Property {170 key: Self::reserve_location_property_key(),171 value: reserve_location172 .encode()173 .try_into()174 .expect("multilocation is less than 32k; qed"),175 }]176 .try_into()177 .expect("just one property can always be stored; qed"),178179 token_property_permissions: vec![PropertyKeyPermission {180 key: Self::reserve_asset_instance_property_key(),181 permission: PropertyPermission {182 mutable: false,183 collection_admin: true,184 token_owner: false,185 },186 }]187 .try_into()188 .expect("just one property permission can always be stored; qed"),189 ..Default::default()190 },191 )?;192193 <ForeignReserveLocationToCollection<T>>::insert(reserve_location, collection_id);194 <CollectionToForeignReserveLocation<T>>::insert(collection_id, reserve_location);195196 Self::deposit_event(Event::<T>::ForeignAssetRegistered {197 asset_id: collection_id,198 reserve_location,199 });200201 Ok(())202 }203 }204}205206impl<T: Config> Pallet<T> {207 fn pallet_account() -> T::CrossAccountId {208 let owner: T::AccountId = T::PalletId::get().into_account_truncating();209 T::CrossAccountId::from_sub(owner)210 }211212 fn reserve_location_property_key() -> PropertyKey {213 b"reserve-location"214 .to_vec()215 .try_into()216 .expect("key length < max property key length; qed")217 }218219 fn reserve_asset_instance_property_key() -> PropertyKey {220 b"reserve-asset-instance"221 .to_vec()222 .try_into()223 .expect("key length < max property key length; qed")224 }225226 /// Converts a multilocation to the Unique Network's local collection227 /// (i.e. the collection originally created on the Unique Network's parachain).228 ///229 /// The multilocation corresponds to a Unique Network's collection if:230 /// * It is `Here` location that corresponds to the native token of this parachain.231 /// * It is `../Parachain(<Unique Network Para ID>)` that also corresponds to the native token of this parachain.232 /// * It is `../Parachain(<Unique Network Para ID>)/GeneralIndex(<Collection ID>)` that corresponds233 /// to the collection with the ID equal to `<Collection ID>`. The `<Collection ID>` must be in the valid range,234 /// otherwise the `AssetIdConversionFailed` error will be returned.235 ///236 /// If the multilocation doesn't match the patterns listed above, the function returns `Ok(None)`,237 /// identifying that the given multilocation doesn't correspond to a local collection.238 fn native_asset_location_to_collection(239 asset_location: &MultiLocation,240 ) -> Result<Option<CollectionId>, XcmError> {241 let self_location = T::SelfLocation::get();242243 if *asset_location == Here.into() {244 Ok(Some(NATIVE_FUNGIBLE_COLLECTION_ID))245 } else if *asset_location == self_location {246 Ok(Some(NATIVE_FUNGIBLE_COLLECTION_ID))247 } else if asset_location.parents == self_location.parents {248 match asset_location249 .interior250 .match_and_split(&self_location.interior)251 {252 Some(GeneralIndex(collection_id)) => Ok(Some(CollectionId(253 (*collection_id)254 .try_into()255 .map_err(|_| XcmExecutorError::AssetIdConversionFailed)?,256 ))),257 _ => Ok(None),258 }259 } else {260 Ok(None)261 }262 }263264 /// Converts a multiasset to a Unique Network's collection (either local or the foreign one).265 ///266 /// The function will try to convert the multiasset's reserve location267 /// to the Unique Network's local collection.268 ///269 /// If the multilocation doesn't correspond to a local collection,270 /// the function will check if the reserve location has the corresponding271 /// derivative Unique Network's collection, and will return the said collection ID if found.272 ///273 /// If all of the above have failed, the `AssetIdConversionFailed` error will be returned.274 fn multiasset_to_collection(asset: &MultiAsset) -> Result<CollectionId, XcmError> {275 let AssetId::Concrete(asset_reserve_location) = asset.id else {276 return Err(XcmExecutorError::AssetNotHandled.into());277 };278279 Self::native_asset_location_to_collection(&asset_reserve_location)?280 .or_else(|| Self::foreign_reserve_location_to_collection(asset_reserve_location))281 .ok_or_else(|| XcmExecutorError::AssetIdConversionFailed.into())282 }283284 /// Converts an XCM asset instance to the Unique Network's token ID.285 ///286 /// The asset instance corresponds to the Unique Network's token ID if it is in the following format:287 /// `AssetInstance::Index(<token ID>)`.288 ///289 /// If the asset instance is not in the valid format or the `<token ID>` points to a non-existent token,290 /// the `AssetNotFound` error will be returned.291 fn native_asset_instance_to_token_id(292 asset_instance: &AssetInstance,293 ) -> Result<TokenId, XcmError> {294 match asset_instance {295 AssetInstance::Index(token_id) => Ok(TokenId(296 (*token_id)297 .try_into()298 .map_err(|_| XcmError::AssetNotFound)?,299 )),300 _ => Err(XcmError::AssetNotFound),301 }302 }303304 /// Obtains the token ID of the `asset_instance` in the collection.305 ///306 /// Returns `Ok(None)` only if the `asset_instance` is a part of a foreign collection307 /// and the item hasn't yet been created on this blockchain.308 ///309 /// If the `asset_instance` exists and it is a part of a foreign collection, the function will return `Ok(Some(<token ID>))`.310 ///311 /// If the `asset_instance` is a part of a local collection,312 /// the function will return either `Ok(Some(<token ID>))` or an error if the token is not found.313 fn asset_instance_to_token_id(314 collection_id: CollectionId,315 asset_instance: &AssetInstance,316 ) -> Result<Option<TokenId>, XcmError> {317 if <CollectionToForeignReserveLocation<T>>::contains_key(collection_id) {318 Ok(Self::foreign_reserve_asset_instance_to_token_id(319 collection_id,320 asset_instance,321 ))322 } else {323 Self::native_asset_instance_to_token_id(asset_instance).map(Some)324 }325 }326327 /// Creates a foreign item in the the collection.328 fn create_foreign_asset_instance(329 xcm_ext: &dyn XcmExtensions<T>,330 collection_id: CollectionId,331 asset_instance: &AssetInstance,332 to: T::CrossAccountId,333 ) -> DispatchResult {334 let asset_instance_encoded = asset_instance.encode();335336 let derivative_token_id = xcm_ext.create_item(337 &Self::pallet_account(),338 to,339 CreateItemData::NFT(CreateNftData {340 properties: vec![Property {341 key: Self::reserve_asset_instance_property_key(),342 value: asset_instance_encoded343 .try_into()344 .expect("asset instance length <= 32 bytes which is less than value length limit; qed"),345 }]346 .try_into()347 .expect("just one property can always be stored; qed"),348 }),349 &ZeroBudget,350 )?;351352 <ForeignReserveAssetInstanceToTokenId<T>>::insert(353 collection_id,354 asset_instance,355 derivative_token_id,356 );357358 Ok(())359 }360361 /// Deposits an asset instance to the `to` account.362 ///363 /// Either transfers an existing item from the pallet's account364 /// or creates a foreign item.365 fn deposit_asset_instance(366 xcm_ext: &dyn XcmExtensions<T>,367 collection_id: CollectionId,368 asset_instance: &AssetInstance,369 to: T::CrossAccountId,370 ) -> XcmResult {371 let deposit_result = if let Some(token_id) =372 Self::asset_instance_to_token_id(collection_id, asset_instance)?373 {374 let depositor = &Self::pallet_account();375 let from = depositor;376 let amount = 1;377378 xcm_ext.transfer_item(depositor, from, &to, token_id, amount, &ZeroBudget)379 } else {380 Self::create_foreign_asset_instance(xcm_ext, collection_id, asset_instance, to)381 };382383 deposit_result384 .map_err(|_| XcmError::FailedToTransactAsset("non-fungible item deposit failed"))385 }386387 /// Withdraws an asset instance from the `from` account.388 ///389 /// Transfers the asset instance to the pallet's account.390 ///391 /// Won't withdraw the instance if it has children.392 fn withdraw_asset_instance(393 xcm_ext: &dyn XcmExtensions<T>,394 collection_id: CollectionId,395 asset_instance: &AssetInstance,396 from: T::CrossAccountId,397 ) -> XcmResult {398 let token_id = Self::asset_instance_to_token_id(collection_id, &asset_instance)?399 .ok_or(XcmError::AssetNotFound)?;400401 if xcm_ext.token_has_children(token_id) {402 return Err(XcmError::Unimplemented);403 }404405 let depositor = &from;406 let to = Self::pallet_account();407 let amount = 1;408 xcm_ext409 .transfer_item(depositor, &from, &to, token_id, amount, &ZeroBudget)410 .map_err(|_| XcmError::FailedToTransactAsset("nonfungible item withdraw failed"))?;411412 Ok(())413 }414}415416impl<T: Config> TransactAsset for Pallet<T> {417 fn can_check_in(418 _origin: &MultiLocation,419 _what: &MultiAsset,420 _context: &XcmContext,421 ) -> XcmResult {422 Err(XcmError::Unimplemented)423 }424425 fn check_in(_origin: &MultiLocation, _what: &MultiAsset, _context: &XcmContext) {}426427 fn can_check_out(428 _dest: &MultiLocation,429 _what: &MultiAsset,430 _context: &XcmContext,431 ) -> XcmResult {432 Err(XcmError::Unimplemented)433 }434435 fn check_out(_dest: &MultiLocation, _what: &MultiAsset, _context: &XcmContext) {}436437 fn deposit_asset(what: &MultiAsset, to: &MultiLocation, _context: &XcmContext) -> XcmResult {438 let to = T::LocationToAccountId::convert_location(to)439 .ok_or(XcmExecutorError::AccountIdConversionFailed)?;440441 let collection_id = Self::multiasset_to_collection(what)?;442 let dispatch =443 T::CollectionDispatch::dispatch(collection_id).map_err(|_| XcmError::AssetNotFound)?;444445 let collection = dispatch.as_dyn();446 let xcm_ext = collection.xcm_extensions().ok_or(XcmError::Unimplemented)?;447448 match what.fun {449 Fungibility::Fungible(amount) => xcm_ext450 .create_item(451 &Self::pallet_account(),452 to,453 CreateItemData::Fungible(CreateFungibleData { value: amount }),454 &ZeroBudget,455 )456 .map(|_| ())457 .map_err(|_| XcmError::FailedToTransactAsset("fungible item deposit failed")),458459 Fungibility::NonFungible(asset_instance) => {460 Self::deposit_asset_instance(xcm_ext, collection_id, &asset_instance, to)461 }462 }463 }464465 fn withdraw_asset(466 what: &MultiAsset,467 from: &MultiLocation,468 _maybe_context: Option<&XcmContext>,469 ) -> Result<staging_xcm_executor::Assets, XcmError> {470 let from = T::LocationToAccountId::convert_location(from)471 .ok_or(XcmExecutorError::AccountIdConversionFailed)?;472473 let collection_id = Self::multiasset_to_collection(what)?;474 let dispatch =475 T::CollectionDispatch::dispatch(collection_id).map_err(|_| XcmError::AssetNotFound)?;476477 let collection = dispatch.as_dyn();478 let xcm_ext = collection.xcm_extensions().ok_or(XcmError::NoPermission)?;479480 match what.fun {481 Fungibility::Fungible(amount) => xcm_ext482 .burn_item(from, TokenId::default(), amount)483 .map_err(|_| XcmError::FailedToTransactAsset("fungible item withdraw failed"))?,484485 Fungibility::NonFungible(asset_instance) => {486 Self::withdraw_asset_instance(xcm_ext, collection_id, &asset_instance, from)?;487 }488 }489490 Ok(what.clone().into())491 }492493 fn internal_transfer_asset(494 what: &MultiAsset,495 from: &MultiLocation,496 to: &MultiLocation,497 _context: &XcmContext,498 ) -> Result<staging_xcm_executor::Assets, XcmError> {499 let from = T::LocationToAccountId::convert_location(from)500 .ok_or(XcmExecutorError::AccountIdConversionFailed)?;501502 let to = T::LocationToAccountId::convert_location(to)503 .ok_or(XcmExecutorError::AccountIdConversionFailed)?;504505 let collection_id = Self::multiasset_to_collection(what)?;506507 let dispatch =508 T::CollectionDispatch::dispatch(collection_id).map_err(|_| XcmError::AssetNotFound)?;509 let collection = dispatch.as_dyn();510 let xcm_ext = collection.xcm_extensions().ok_or(XcmError::NoPermission)?;511512 let depositor = &from;513514 let token_id;515 let amount;516 let map_error: fn(DispatchError) -> XcmError;517518 match what.fun {519 Fungibility::Fungible(fungible_amount) => {520 token_id = TokenId::default();521 amount = fungible_amount;522 map_error = |_| XcmError::FailedToTransactAsset("fungible item transfer failed");523 }524525 Fungibility::NonFungible(asset_instance) => {526 token_id = Self::asset_instance_to_token_id(collection_id, &asset_instance)?527 .ok_or(XcmError::AssetNotFound)?;528529 amount = 1;530 map_error = |_| XcmError::FailedToTransactAsset("nonfungible item transfer failed")531 }532 }533534 xcm_ext535 .transfer_item(depositor, &from, &to, token_id, amount, &ZeroBudget)536 .map_err(map_error)?;537538 Ok(what.clone().into())539 }540}541542pub struct CurrencyIdConvert<T: Config>(PhantomData<T>);543impl<T: Config> sp_runtime::traits::Convert<CollectionId, Option<MultiLocation>>544 for CurrencyIdConvert<T>545{546 fn convert(collection_id: CollectionId) -> Option<MultiLocation> {547 if collection_id == NATIVE_FUNGIBLE_COLLECTION_ID {548 Some(Here.into())549 } else {550 <Pallet<T>>::collection_to_foreign_reserve_location(collection_id).or_else(|| {551 T::SelfLocation::get()552 .pushed_with_interior(GeneralIndex(collection_id.0.into()))553 .ok()554 })555 }556 }557}558559pub use frame_support::{560 traits::{561 fungibles::Balanced, tokens::currency::Currency as CurrencyT, OnUnbalanced as OnUnbalancedT,562 },563 weights::{WeightToFee, WeightToFeePolynomial},564};565566#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]567pub enum ForeignCollectionMode {568 NFT,569 Fungible(u8),570}571572impl Into<CollectionMode> for ForeignCollectionMode {573 fn into(self) -> CollectionMode {574 match self {575 Self::NFT => CollectionMode::NFT,576 Self::Fungible(decimals) => CollectionMode::Fungible(decimals),577 }578 }579}580581pub struct FreeForAll;582583impl WeightTrader for FreeForAll {584 fn new() -> Self {585 Self586 }587588 fn buy_weight(589 &mut self,590 weight: Weight,591 payment: Assets,592 _xcm: &XcmContext,593 ) -> Result<Assets, XcmError> {594 log::trace!(target: "fassets::weight", "buy_weight weight: {:?}, payment: {:?}", weight, payment);595 Ok(payment)596 }597}pallets/fungible/src/common.rsdiffbeforeafterboth--- a/pallets/fungible/src/common.rs
+++ b/pallets/fungible/src/common.rs
@@ -470,7 +470,7 @@
up_data_structs::CreateItemData::Fungible(fungible_data) => {
<Pallet<T>>::create_multiple_items(
self,
- &depositor,
+ depositor,
[(to, fungible_data.value)].into_iter().collect(),
nesting_budget,
)?
@@ -495,7 +495,7 @@
<CommonError<T>>::FungibleItemsHaveNoId
);
- <Pallet<T>>::transfer_internal(self, &depositor, &from, &to, amount, nesting_budget)
+ <Pallet<T>>::transfer_internal(self, depositor, from, to, amount, nesting_budget)
.map(|_| ())
.map_err(|post_info| post_info.error)
}
@@ -506,7 +506,7 @@
token: TokenId,
amount: u128,
) -> sp_runtime::DispatchResult {
- <Self as CommonCollectionOperations<T>>::burn_item(&self, from, token, amount)
+ <Self as CommonCollectionOperations<T>>::burn_item(self, from, token, amount)
.map(|_| ())
.map_err(|post_info| post_info.error)
}
pallets/nonfungible/src/common.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/common.rs
+++ b/pallets/nonfungible/src/common.rs
@@ -585,7 +585,7 @@
) -> Result<TokenId, sp_runtime::DispatchError> {
<Pallet<T>>::create_multiple_items(
self,
- &depositor,
+ depositor,
vec![map_create_data::<T>(data, &to)?],
nesting_budget,
)?;
@@ -604,7 +604,7 @@
) -> sp_runtime::DispatchResult {
ensure!(amount == 1, <Error<T>>::NonfungibleItemsHaveNoAmount);
- <Pallet<T>>::transfer_internal(self, &depositor, &from, &to, token, nesting_budget)
+ <Pallet<T>>::transfer_internal(self, depositor, from, to, token, nesting_budget)
.map(|_| ())
.map_err(|post_info| post_info.error)
}
runtime/common/config/pallets/foreign_asset.rsdiffbeforeafterboth--- a/runtime/common/config/pallets/foreign_asset.rs
+++ b/runtime/common/config/pallets/foreign_asset.rs
@@ -26,7 +26,7 @@
{
fn convert_location(location: &MultiLocation) -> Option<ConfigCrossAccountId> {
LocationToAccountId::convert_location(location)
- .map(|sub| ConfigCrossAccountId::from_sub(sub))
+ .map(ConfigCrossAccountId::from_sub)
.or_else(|| {
let eth_address =
AccountKey20Aliases::<RelayNetwork, H160>::convert_location(location)?;