difftreelog
feat draft xcm deposit_asset
in: master
8 files changed
pallets/balances-adapter/src/common.rsdiffbeforeafterboth1use alloc::{vec, vec::Vec};2use core::marker::PhantomData;34use frame_support::{ensure, fail, weights::Weight};5use pallet_balances::{weights::SubstrateWeight as BalancesWeight, WeightInfo};6use pallet_common::{CommonCollectionOperations, CommonWeightInfo, Error as CommonError};7use up_data_structs::TokenId;89use crate::{Config, NativeFungibleHandle, Pallet};1011pub struct CommonWeights<T: Config>(PhantomData<T>);1213// All implementations with `Weight::default` used in methods that return error `UnsupportedOperation`.14impl<T: Config> CommonWeightInfo<T::CrossAccountId> for CommonWeights<T> {15 fn create_multiple_items(_amount: &[up_data_structs::CreateItemData]) -> Weight {16 Weight::default()17 }1819 fn create_multiple_items_ex(20 _cost: &up_data_structs::CreateItemExData<T::CrossAccountId>,21 ) -> Weight {22 Weight::default()23 }2425 fn burn_item() -> Weight {26 Weight::default()27 }2829 fn set_collection_properties(_amount: u32) -> Weight {30 Weight::default()31 }3233 fn set_token_properties(_amount: u32) -> Weight {34 Weight::default()35 }3637 fn set_token_property_permissions(_amount: u32) -> Weight {38 Weight::default()39 }4041 fn transfer() -> Weight {42 <BalancesWeight<T> as WeightInfo>::transfer_allow_death()43 }4445 fn approve() -> Weight {46 Weight::default()47 }4849 fn approve_from() -> Weight {50 Weight::default()51 }5253 fn transfer_from() -> Weight {54 <BalancesWeight<T> as WeightInfo>::transfer_allow_death()55 }5657 fn burn_from() -> Weight {58 Weight::default()59 }6061 fn set_allowance_for_all() -> Weight {62 Weight::default()63 }6465 fn force_repair_item() -> Weight {66 Weight::default()67 }68}6970/// Implementation of `CommonCollectionOperations` for `FungibleHandle`. It wraps FungibleHandle Pallet71/// methods and adds weight info.72impl<T: Config> CommonCollectionOperations<T> for NativeFungibleHandle<T> {73 fn create_item(74 &self,75 _sender: <T>::CrossAccountId,76 _to: <T>::CrossAccountId,77 _data: up_data_structs::CreateItemData,78 _nesting_budget: &dyn up_data_structs::budget::Budget,79 ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {80 fail!(<CommonError<T>>::UnsupportedOperation);81 }8283 fn create_multiple_items(84 &self,85 _sender: <T>::CrossAccountId,86 _to: <T>::CrossAccountId,87 _data: Vec<up_data_structs::CreateItemData>,88 _nesting_budget: &dyn up_data_structs::budget::Budget,89 ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {90 fail!(<CommonError<T>>::UnsupportedOperation);91 }9293 fn create_multiple_items_ex(94 &self,95 _sender: <T>::CrossAccountId,96 _data: up_data_structs::CreateItemExData<<T>::CrossAccountId>,97 _nesting_budget: &dyn up_data_structs::budget::Budget,98 ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {99 fail!(<CommonError<T>>::UnsupportedOperation);100 }101102 fn burn_item(103 &self,104 _sender: <T>::CrossAccountId,105 _token: TokenId,106 _amount: u128,107 ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {108 fail!(<CommonError<T>>::UnsupportedOperation);109 }110111 fn set_collection_properties(112 &self,113 _sender: <T>::CrossAccountId,114 _properties: Vec<up_data_structs::Property>,115 ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {116 fail!(<CommonError<T>>::UnsupportedOperation);117 }118119 fn delete_collection_properties(120 &self,121 _sender: &<T>::CrossAccountId,122 _property_keys: Vec<up_data_structs::PropertyKey>,123 ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {124 fail!(<CommonError<T>>::UnsupportedOperation);125 }126127 fn set_token_properties(128 &self,129 _sender: <T>::CrossAccountId,130 _token_id: TokenId,131 _properties: Vec<up_data_structs::Property>,132 _budget: &dyn up_data_structs::budget::Budget,133 ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {134 fail!(<CommonError<T>>::UnsupportedOperation);135 }136137 fn delete_token_properties(138 &self,139 _sender: <T>::CrossAccountId,140 _token_id: TokenId,141 _property_keys: Vec<up_data_structs::PropertyKey>,142 _budget: &dyn up_data_structs::budget::Budget,143 ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {144 fail!(<CommonError<T>>::UnsupportedOperation);145 }146147 fn get_token_properties_raw(148 &self,149 _token_id: TokenId,150 ) -> Option<up_data_structs::TokenProperties> {151 // No token properties are defined on fungibles152 None153 }154155 fn set_token_properties_raw(&self, _token_id: TokenId, _map: up_data_structs::TokenProperties) {156 // No token properties are defined on fungibles157 }158159 fn set_token_property_permissions(160 &self,161 _sender: &<T>::CrossAccountId,162 _property_permissions: Vec<up_data_structs::PropertyKeyPermission>,163 ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {164 fail!(<CommonError<T>>::UnsupportedOperation);165 }166167 fn transfer(168 &self,169 sender: <T>::CrossAccountId,170 to: <T>::CrossAccountId,171 token: TokenId,172 amount: u128,173 _budget: &dyn up_data_structs::budget::Budget,174 ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {175 ensure!(176 token == TokenId::default(),177 <CommonError<T>>::FungibleItemsHaveNoId178 );179180 <Pallet<T>>::transfer(&sender, &to, amount)181 }182183 fn approve(184 &self,185 _sender: <T>::CrossAccountId,186 _spender: <T>::CrossAccountId,187 _token: TokenId,188 _amount: u128,189 ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {190 fail!(<CommonError<T>>::UnsupportedOperation);191 }192193 fn approve_from(194 &self,195 _sender: <T>::CrossAccountId,196 _from: <T>::CrossAccountId,197 _to: <T>::CrossAccountId,198 _token: TokenId,199 _amount: u128,200 ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {201 fail!(<CommonError<T>>::UnsupportedOperation);202 }203204 fn transfer_from(205 &self,206 sender: <T>::CrossAccountId,207 from: <T>::CrossAccountId,208 to: <T>::CrossAccountId,209 token: TokenId,210 amount: u128,211 budget: &dyn up_data_structs::budget::Budget,212 ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {213 ensure!(214 token == TokenId::default(),215 <CommonError<T>>::FungibleItemsHaveNoId216 );217218 <Pallet<T>>::transfer_from(&sender, &from, &to, amount, budget)219 }220221 fn burn_from(222 &self,223 _sender: <T>::CrossAccountId,224 _from: <T>::CrossAccountId,225 _token: TokenId,226 _amount: u128,227 _budget: &dyn up_data_structs::budget::Budget,228 ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {229 fail!(<CommonError<T>>::UnsupportedOperation);230 }231232 fn check_nesting(233 &self,234 _sender: &<T>::CrossAccountId,235 _from: (up_data_structs::CollectionId, TokenId),236 _under: TokenId,237 _budget: &dyn up_data_structs::budget::Budget,238 ) -> frame_support::sp_runtime::DispatchResult {239 fail!(<CommonError<T>>::UnsupportedOperation);240 }241242 fn nest(&self, _under: TokenId, _to_nest: (up_data_structs::CollectionId, TokenId)) {}243244 fn unnest(&self, _under: TokenId, _to_nest: (up_data_structs::CollectionId, TokenId)) {}245246 fn account_tokens(&self, account: <T>::CrossAccountId) -> Vec<TokenId> {247 let balance = <Pallet<T>>::total_balance(&account);248 if balance != 0 {249 vec![TokenId::default()]250 } else {251 vec![]252 }253 }254255 fn collection_tokens(&self) -> Vec<TokenId> {256 vec![TokenId::default()]257 }258259 fn token_exists(&self, token: TokenId) -> bool {260 token == TokenId::default()261 }262263 fn last_token_id(&self) -> TokenId {264 TokenId::default()265 }266267 fn token_owner(268 &self,269 _token: TokenId,270 ) -> Result<<T>::CrossAccountId, up_data_structs::TokenOwnerError> {271 Err(up_data_structs::TokenOwnerError::MultipleOwners)272 }273274 fn check_token_indirect_owner(275 &self,276 _token: TokenId,277 _maybe_owner: &<T>::CrossAccountId,278 _nesting_budget: &dyn up_data_structs::budget::Budget,279 ) -> Result<bool, frame_support::sp_runtime::DispatchError> {280 Ok(false)281 }282283 fn token_owners(&self, _token: TokenId) -> Vec<<T>::CrossAccountId> {284 vec![]285 }286287 fn token_property(288 &self,289 _token_id: TokenId,290 _key: &up_data_structs::PropertyKey,291 ) -> Option<up_data_structs::PropertyValue> {292 None293 }294295 fn token_properties(296 &self,297 _token: TokenId,298 _keys: Option<Vec<up_data_structs::PropertyKey>>,299 ) -> Vec<up_data_structs::Property> {300 vec![]301 }302303 fn total_supply(&self) -> u32 {304 1305 }306307 fn account_balance(&self, account: T::CrossAccountId) -> u32 {308 let balance = <Pallet<T>>::balance_of(&account);309 (balance != 0).into()310 }311312 fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128 {313 if token != TokenId::default() {314 return 0;315 }316 <Pallet<T>>::balance_of(&account)317 }318319 fn total_pieces(&self, token: TokenId) -> Option<u128> {320 if token != TokenId::default() {321 return None;322 }323 Some(<Pallet<T>>::total_issuance())324 }325326 fn allowance(327 &self,328 _sender: <T>::CrossAccountId,329 _spender: <T>::CrossAccountId,330 _token: TokenId,331 ) -> u128 {332 0333 }334335 fn set_allowance_for_all(336 &self,337 _owner: <T>::CrossAccountId,338 _operator: <T>::CrossAccountId,339 _approve: bool,340 ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {341 fail!(<CommonError<T>>::UnsupportedOperation);342 }343344 fn allowance_for_all(345 &self,346 _owner: <T>::CrossAccountId,347 _operator: <T>::CrossAccountId,348 ) -> bool {349 false350 }351352 fn repair_item(353 &self,354 _token: TokenId,355 ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {356 fail!(<CommonError<T>>::UnsupportedOperation);357 }358}1use alloc::{vec, vec::Vec};2use core::marker::PhantomData;34use frame_support::{5 ensure, fail,6 traits::tokens::{fungible::Mutate, Fortitude, Precision},7 weights::Weight,8};9use pallet_balances::{weights::SubstrateWeight as BalancesWeight, WeightInfo};10use pallet_common::{11 erc::CrossAccountId, CommonCollectionOperations, CommonWeightInfo, Error as CommonError,12};13use up_data_structs::{budget::Budget, TokenId};1415use crate::{Config, NativeFungibleHandle, Pallet};1617pub struct CommonWeights<T: Config>(PhantomData<T>);1819// All implementations with `Weight::default` used in methods that return error `UnsupportedOperation`.20impl<T: Config> CommonWeightInfo<T::CrossAccountId> for CommonWeights<T> {21 fn create_multiple_items(_amount: &[up_data_structs::CreateItemData]) -> Weight {22 Weight::default()23 }2425 fn create_multiple_items_ex(26 _cost: &up_data_structs::CreateItemExData<T::CrossAccountId>,27 ) -> Weight {28 Weight::default()29 }3031 fn burn_item() -> Weight {32 Weight::default()33 }3435 fn set_collection_properties(_amount: u32) -> Weight {36 Weight::default()37 }3839 fn set_token_properties(_amount: u32) -> Weight {40 Weight::default()41 }4243 fn set_token_property_permissions(_amount: u32) -> Weight {44 Weight::default()45 }4647 fn transfer() -> Weight {48 <BalancesWeight<T> as WeightInfo>::transfer_allow_death()49 }5051 fn approve() -> Weight {52 Weight::default()53 }5455 fn approve_from() -> Weight {56 Weight::default()57 }5859 fn transfer_from() -> Weight {60 <BalancesWeight<T> as WeightInfo>::transfer_allow_death()61 }6263 fn burn_from() -> Weight {64 Weight::default()65 }6667 fn set_allowance_for_all() -> Weight {68 Weight::default()69 }7071 fn force_repair_item() -> Weight {72 Weight::default()73 }74}7576/// Implementation of `CommonCollectionOperations` for `FungibleHandle`. It wraps FungibleHandle Pallet77/// methods and adds weight info.78impl<T: Config> CommonCollectionOperations<T> for NativeFungibleHandle<T> {79 fn create_item(80 &self,81 _sender: <T>::CrossAccountId,82 _to: <T>::CrossAccountId,83 _data: up_data_structs::CreateItemData,84 _nesting_budget: &dyn up_data_structs::budget::Budget,85 ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {86 fail!(<CommonError<T>>::UnsupportedOperation);87 }8889 fn create_multiple_items(90 &self,91 _sender: <T>::CrossAccountId,92 _to: <T>::CrossAccountId,93 _data: Vec<up_data_structs::CreateItemData>,94 _nesting_budget: &dyn up_data_structs::budget::Budget,95 ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {96 fail!(<CommonError<T>>::UnsupportedOperation);97 }9899 fn create_multiple_items_ex(100 &self,101 _sender: <T>::CrossAccountId,102 _data: up_data_structs::CreateItemExData<<T>::CrossAccountId>,103 _nesting_budget: &dyn up_data_structs::budget::Budget,104 ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {105 fail!(<CommonError<T>>::UnsupportedOperation);106 }107108 fn burn_item(109 &self,110 _sender: <T>::CrossAccountId,111 _token: TokenId,112 _amount: u128,113 ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {114 fail!(<CommonError<T>>::UnsupportedOperation);115 }116117 fn set_collection_properties(118 &self,119 _sender: <T>::CrossAccountId,120 _properties: Vec<up_data_structs::Property>,121 ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {122 fail!(<CommonError<T>>::UnsupportedOperation);123 }124125 fn delete_collection_properties(126 &self,127 _sender: &<T>::CrossAccountId,128 _property_keys: Vec<up_data_structs::PropertyKey>,129 ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {130 fail!(<CommonError<T>>::UnsupportedOperation);131 }132133 fn set_token_properties(134 &self,135 _sender: <T>::CrossAccountId,136 _token_id: TokenId,137 _properties: Vec<up_data_structs::Property>,138 _budget: &dyn up_data_structs::budget::Budget,139 ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {140 fail!(<CommonError<T>>::UnsupportedOperation);141 }142143 fn delete_token_properties(144 &self,145 _sender: <T>::CrossAccountId,146 _token_id: TokenId,147 _property_keys: Vec<up_data_structs::PropertyKey>,148 _budget: &dyn up_data_structs::budget::Budget,149 ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {150 fail!(<CommonError<T>>::UnsupportedOperation);151 }152153 fn get_token_properties_raw(154 &self,155 _token_id: TokenId,156 ) -> Option<up_data_structs::TokenProperties> {157 // No token properties are defined on fungibles158 None159 }160161 fn set_token_properties_raw(&self, _token_id: TokenId, _map: up_data_structs::TokenProperties) {162 // No token properties are defined on fungibles163 }164165 fn set_token_property_permissions(166 &self,167 _sender: &<T>::CrossAccountId,168 _property_permissions: Vec<up_data_structs::PropertyKeyPermission>,169 ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {170 fail!(<CommonError<T>>::UnsupportedOperation);171 }172173 fn transfer(174 &self,175 sender: <T>::CrossAccountId,176 to: <T>::CrossAccountId,177 token: TokenId,178 amount: u128,179 _budget: &dyn up_data_structs::budget::Budget,180 ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {181 ensure!(182 token == TokenId::default(),183 <CommonError<T>>::FungibleItemsHaveNoId184 );185186 <Pallet<T>>::transfer(&sender, &to, amount)187 }188189 fn approve(190 &self,191 _sender: <T>::CrossAccountId,192 _spender: <T>::CrossAccountId,193 _token: TokenId,194 _amount: u128,195 ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {196 fail!(<CommonError<T>>::UnsupportedOperation);197 }198199 fn approve_from(200 &self,201 _sender: <T>::CrossAccountId,202 _from: <T>::CrossAccountId,203 _to: <T>::CrossAccountId,204 _token: TokenId,205 _amount: u128,206 ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {207 fail!(<CommonError<T>>::UnsupportedOperation);208 }209210 fn transfer_from(211 &self,212 sender: <T>::CrossAccountId,213 from: <T>::CrossAccountId,214 to: <T>::CrossAccountId,215 token: TokenId,216 amount: u128,217 budget: &dyn up_data_structs::budget::Budget,218 ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {219 ensure!(220 token == TokenId::default(),221 <CommonError<T>>::FungibleItemsHaveNoId222 );223224 <Pallet<T>>::transfer_from(&sender, &from, &to, amount, budget)225 }226227 fn burn_from(228 &self,229 _sender: <T>::CrossAccountId,230 _from: <T>::CrossAccountId,231 _token: TokenId,232 _amount: u128,233 _budget: &dyn up_data_structs::budget::Budget,234 ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {235 fail!(<CommonError<T>>::UnsupportedOperation);236 }237238 fn check_nesting(239 &self,240 _sender: &<T>::CrossAccountId,241 _from: (up_data_structs::CollectionId, TokenId),242 _under: TokenId,243 _budget: &dyn up_data_structs::budget::Budget,244 ) -> frame_support::sp_runtime::DispatchResult {245 fail!(<CommonError<T>>::UnsupportedOperation);246 }247248 fn nest(&self, _under: TokenId, _to_nest: (up_data_structs::CollectionId, TokenId)) {}249250 fn unnest(&self, _under: TokenId, _to_nest: (up_data_structs::CollectionId, TokenId)) {}251252 fn account_tokens(&self, account: <T>::CrossAccountId) -> Vec<TokenId> {253 let balance = <Pallet<T>>::total_balance(&account);254 if balance != 0 {255 vec![TokenId::default()]256 } else {257 vec![]258 }259 }260261 fn collection_tokens(&self) -> Vec<TokenId> {262 vec![TokenId::default()]263 }264265 fn token_exists(&self, token: TokenId) -> bool {266 token == TokenId::default()267 }268269 fn last_token_id(&self) -> TokenId {270 TokenId::default()271 }272273 fn token_owner(274 &self,275 _token: TokenId,276 ) -> Result<<T>::CrossAccountId, up_data_structs::TokenOwnerError> {277 Err(up_data_structs::TokenOwnerError::MultipleOwners)278 }279280 fn check_token_indirect_owner(281 &self,282 _token: TokenId,283 _maybe_owner: &<T>::CrossAccountId,284 _nesting_budget: &dyn up_data_structs::budget::Budget,285 ) -> Result<bool, frame_support::sp_runtime::DispatchError> {286 Ok(false)287 }288289 fn token_owners(&self, _token: TokenId) -> Vec<<T>::CrossAccountId> {290 vec![]291 }292293 fn token_property(294 &self,295 _token_id: TokenId,296 _key: &up_data_structs::PropertyKey,297 ) -> Option<up_data_structs::PropertyValue> {298 None299 }300301 fn token_properties(302 &self,303 _token: TokenId,304 _keys: Option<Vec<up_data_structs::PropertyKey>>,305 ) -> Vec<up_data_structs::Property> {306 vec![]307 }308309 fn total_supply(&self) -> u32 {310 1311 }312313 fn account_balance(&self, account: T::CrossAccountId) -> u32 {314 let balance = <Pallet<T>>::balance_of(&account);315 (balance != 0).into()316 }317318 fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128 {319 if token != TokenId::default() {320 return 0;321 }322 <Pallet<T>>::balance_of(&account)323 }324325 fn total_pieces(&self, token: TokenId) -> Option<u128> {326 if token != TokenId::default() {327 return None;328 }329 Some(<Pallet<T>>::total_issuance())330 }331332 fn allowance(333 &self,334 _sender: <T>::CrossAccountId,335 _spender: <T>::CrossAccountId,336 _token: TokenId,337 ) -> u128 {338 0339 }340341 fn xcm_extensions(&self) -> Option<&dyn pallet_common::XcmExtensions<T>> {342 Some(self)343 }344345 fn set_allowance_for_all(346 &self,347 _owner: <T>::CrossAccountId,348 _operator: <T>::CrossAccountId,349 _approve: bool,350 ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {351 fail!(<CommonError<T>>::UnsupportedOperation);352 }353354 fn allowance_for_all(355 &self,356 _owner: <T>::CrossAccountId,357 _operator: <T>::CrossAccountId,358 ) -> bool {359 false360 }361362 fn repair_item(363 &self,364 _token: TokenId,365 ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {366 fail!(<CommonError<T>>::UnsupportedOperation);367 }368}369370impl<T: Config> pallet_common::XcmExtensions<T> for NativeFungibleHandle<T> {371 fn is_foreign(&self) -> bool {372 false373 }374375 fn create_item_internal(376 &self,377 _depositor: &<T>::CrossAccountId,378 to: <T>::CrossAccountId,379 data: up_data_structs::CreateItemData,380 _nesting_budget: &dyn Budget,381 ) -> Result<TokenId, sp_runtime::DispatchError> {382 match &data {383 up_data_structs::CreateItemData::Fungible(fungible_data) => {384 T::Mutate::mint_into(385 to.as_sub(),386 fungible_data387 .value388 .try_into()389 .map_err(|_| sp_runtime::ArithmeticError::Overflow)?,390 )?;391392 Ok(TokenId::default())393 }394 _ => {395 fail!(<CommonError<T>>::NotFungibleDataUsedToMintFungibleCollectionToken)396 }397 }398 }399400 fn transfer_item_internal(401 &self,402 _depositor: &<T>::CrossAccountId,403 from: &<T>::CrossAccountId,404 to: &<T>::CrossAccountId,405 token: TokenId,406 amount: u128,407 _nesting_budget: &dyn Budget,408 ) -> sp_runtime::DispatchResult {409 ensure!(410 token == TokenId::default(),411 <CommonError<T>>::FungibleItemsHaveNoId412 );413414 <Pallet<T>>::transfer(from, to, amount)415 .map(|_| ())416 .map_err(|post_info| post_info.error)417 }418419 fn burn_item_internal(420 &self,421 from: T::CrossAccountId,422 token: TokenId,423 amount: u128,424 ) -> sp_runtime::DispatchResult {425 ensure!(426 token == TokenId::default(),427 <CommonError<T>>::FungibleItemsHaveNoId428 );429430 T::Mutate::burn_from(431 from.as_sub(),432 amount433 .try_into()434 .map_err(|_| sp_runtime::ArithmeticError::Overflow)?,435 Precision::Exact,436 Fortitude::Polite,437 )?;438439 Ok(())440 }441}pallets/common/src/lib.rsdiffbeforeafterboth--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -80,15 +80,16 @@
use sp_std::vec::Vec;
use sp_weights::Weight;
use up_data_structs::{
- budget::Budget, AccessMode, Collection, CollectionId, CollectionLimits, CollectionMode,
- CollectionPermissions, CollectionProperties as CollectionPropertiesT, CollectionStats,
- CreateCollectionData, CreateItemData, CreateItemExData, PhantomType, PropertiesError,
- PropertiesPermissionMap, Property, PropertyKey, PropertyKeyPermission, PropertyPermission,
- PropertyScope, PropertyValue, RpcCollection, RpcCollectionFlags, SponsoringRateLimit,
- SponsorshipState, TokenChild, TokenData, TokenId, TokenOwnerError, TokenProperties,
- TrySetProperty, COLLECTION_ADMINS_LIMIT, COLLECTION_NUMBER_LIMIT, CUSTOM_DATA_LIMIT,
- FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, MAX_SPONSOR_TIMEOUT, MAX_TOKEN_OWNERSHIP,
- MAX_TOKEN_PREFIX_LENGTH, NFT_SPONSOR_TRANSFER_TIMEOUT, REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
+ budget::Budget, mapping::TokenAddressMapping, AccessMode, Collection, CollectionId,
+ CollectionLimits, CollectionMode, CollectionPermissions,
+ CollectionProperties as CollectionPropertiesT, CollectionStats, CreateCollectionData,
+ CreateItemData, CreateItemExData, PhantomType, PropertiesError, PropertiesPermissionMap,
+ Property, PropertyKey, PropertyKeyPermission, PropertyPermission, PropertyScope, PropertyValue,
+ RpcCollection, RpcCollectionFlags, SponsoringRateLimit, SponsorshipState, TokenChild,
+ TokenData, TokenId, TokenOwnerError, TokenProperties, TrySetProperty, COLLECTION_ADMINS_LIMIT,
+ COLLECTION_NUMBER_LIMIT, CUSTOM_DATA_LIMIT, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
+ MAX_SPONSOR_TIMEOUT, MAX_TOKEN_OWNERSHIP, MAX_TOKEN_PREFIX_LENGTH,
+ NFT_SPONSOR_TRANSFER_TIMEOUT, REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
};
use up_pov_estimate_rpc::PovInfo;
@@ -786,6 +787,9 @@
/// Fungible tokens hold no ID, and the default value of TokenId for a fungible collection is 0.
FungibleItemsHaveNoId,
+
+ /// Not Fungible item data used to mint in Fungible collection.
+ NotFungibleDataUsedToMintFungibleCollectionToken,
}
/// Storage of the count of created collections. Essentially contains the last collection ID.
@@ -2347,24 +2351,77 @@
/// Is the collection a foreign one?
fn is_foreign(&self) -> bool;
- /// Create a collection's item.
+ /// Create a collection's item using a transaction.
+ ///
+ /// This function performs additional XCM-related checks before the actual creation.
+ #[transactional]
fn create_item(
&self,
+ depositor: &T::CrossAccountId,
+ to: T::CrossAccountId,
+ data: CreateItemData,
+ nesting_budget: &dyn Budget,
+ ) -> Result<TokenId, DispatchError> {
+ if T::CrossTokenAddressMapping::is_token_address(&to) {
+ return unsupported!(T);
+ }
+
+ self.create_item_internal(depositor, to, data, nesting_budget)
+ }
+
+ /// Create a collection's item.
+ fn create_item_internal(
+ &self,
+ depositor: &T::CrossAccountId,
to: T::CrossAccountId,
data: CreateItemData,
+ nesting_budget: &dyn Budget,
) -> Result<TokenId, DispatchError>;
+ /// Transfer an item from the `from` account to the `to` account using a transaction.
+ ///
+ /// This function performs additional XCM-related checks before the actual transfer.
+ #[transactional]
+ fn transfer_item(
+ &self,
+ depositor: &T::CrossAccountId,
+ from: &T::CrossAccountId,
+ to: &T::CrossAccountId,
+ token: TokenId,
+ amount: u128,
+ nesting_budget: &dyn Budget,
+ ) -> DispatchResult {
+ if T::CrossTokenAddressMapping::is_token_address(&to) {
+ return unsupported!(T);
+ }
+
+ self.transfer_item_internal(depositor, from, to, token, amount, nesting_budget)
+ }
+
/// Transfer an item from the `from` account to the `to` account.
- fn transfer(
+ fn transfer_item_internal(
&self,
- from: T::CrossAccountId,
- to: T::CrossAccountId,
+ depositor: &T::CrossAccountId,
+ from: &T::CrossAccountId,
+ to: &T::CrossAccountId,
token: TokenId,
amount: u128,
+ nesting_budget: &dyn Budget,
) -> DispatchResult;
+ /// Burn a collection's item using a transaction.
+ #[transactional]
+ fn burn_item(&self, from: T::CrossAccountId, token: TokenId, amount: u128) -> DispatchResult {
+ self.burn_item_internal(from, token, amount)
+ }
+
/// Burn a collection's item.
- fn burn(&self, from: T::CrossAccountId, token: TokenId, amount: u128) -> DispatchResult;
+ fn burn_item_internal(
+ &self,
+ from: T::CrossAccountId,
+ token: TokenId,
+ amount: u128,
+ ) -> DispatchResult;
}
/// Merge [`DispatchResult`] with [`Weight`] into [`DispatchResultWithPostInfo`].
pallets/foreign-assets/src/lib.rsdiffbeforeafterboth--- a/pallets/foreign-assets/src/lib.rs
+++ b/pallets/foreign-assets/src/lib.rs
@@ -22,13 +22,6 @@
//!
//! ## Overview
//!
-//! The foreign assests pallet provides functions for:
-//!
-//! - Local and foreign assets management. The foreign assets can be updated without runtime upgrade.
-//! - Bounds between asset and target collection for cross chain transfer and inner transfers.
-//!
-//! ## Overview
-//!
//! Under construction
#![cfg_attr(not(feature = "std"), no_std)]
@@ -37,22 +30,21 @@
use frame_support::{dispatch::DispatchResult, pallet_prelude::*, traits::EnsureOrigin, PalletId};
use frame_system::pallet_prelude::*;
use pallet_common::{
- dispatch::CollectionDispatch, erc::CrossAccountId, NATIVE_FUNGIBLE_COLLECTION_ID,
+ dispatch::CollectionDispatch, erc::CrossAccountId, XcmExtensions, NATIVE_FUNGIBLE_COLLECTION_ID,
};
use sp_runtime::traits::AccountIdConversion;
use sp_std::{vec, vec::Vec};
-// NOTE: MultiLocation is used in storages, we will need to do migration if upgrade the
-// MultiLocation to the XCM v3.
use staging_xcm::{
opaque::latest::{prelude::XcmError, Weight},
v3::{prelude::*, MultiAsset, XcmContext},
};
use staging_xcm_executor::{
- traits::{TransactAsset, WeightTrader},
+ traits::{ConvertLocation, Error as XcmExecutorError, TransactAsset, WeightTrader},
Assets,
};
use up_data_structs::{
- CollectionId, CollectionMode, CollectionName, CreateCollectionData, PropertyKey, TokenId,
+ budget::ZeroBudget, CollectionId, CollectionMode, CollectionName, CreateCollectionData,
+ CreateFungibleData, CreateItemData, CreateNftData, Property, PropertyKey, TokenId,
};
pub mod weights;
@@ -87,6 +79,12 @@
/// The ID of the foreign assets pallet.
type PalletId: Get<PalletId>;
+ /// Self-location of this parachain.
+ type SelfLocation: Get<MultiLocation>;
+
+ /// The converter from a MultiLocation to a CrossAccountId.
+ type LocationToAccountId: ConvertLocation<Self::CrossAccountId>;
+
/// Weight information for the extrinsics in this module.
type WeightInfo: WeightInfo;
}
@@ -113,6 +111,12 @@
pub type ForeignReserveLocationToCollection<T: Config> =
StorageMap<_, Twox64Concat, staging_xcm::v3::MultiLocation, CollectionId, OptionQuery>;
+ /// The corresponding reserve location of collections.
+ #[pallet::storage]
+ #[pallet::getter(fn collection_to_foreign_reserve_location)]
+ pub type CollectionToForeignReserveLocation<T: Config> =
+ StorageMap<_, Twox64Concat, CollectionId, staging_xcm::v3::MultiLocation, OptionQuery>;
+
/// The correponding NFT token id of reserve NFTs
#[pallet::storage]
#[pallet::getter(fn foreign_reserve_asset_instance_to_token_id)]
@@ -180,6 +184,7 @@
)?;
<ForeignReserveLocationToCollection<T>>::insert(reserve_location, collection_id);
+ <CollectionToForeignReserveLocation<T>>::insert(collection_id, reserve_location);
Self::deposit_event(Event::<T>::ForeignAssetRegistered {
asset_id: collection_id,
@@ -210,6 +215,132 @@
.try_into()
.expect("key length < max property key length; qed")
}
+
+ fn native_asset_location_to_collection(
+ asset_location: &MultiLocation,
+ ) -> Result<Option<CollectionId>, XcmError> {
+ let self_location = T::SelfLocation::get();
+
+ if *asset_location == Here.into() {
+ Ok(Some(NATIVE_FUNGIBLE_COLLECTION_ID))
+ } else if *asset_location == self_location {
+ Ok(Some(NATIVE_FUNGIBLE_COLLECTION_ID))
+ } else if asset_location.parents == self_location.parents {
+ match asset_location
+ .interior
+ .match_and_split(&self_location.interior)
+ {
+ Some(GeneralIndex(collection_id)) => Ok(Some(CollectionId(
+ (*collection_id)
+ .try_into()
+ .map_err(|_| XcmExecutorError::AssetIdConversionFailed)?,
+ ))),
+ _ => Ok(None),
+ }
+ } else {
+ Ok(None)
+ }
+ }
+
+ fn multiasset_to_collection(asset: &MultiAsset) -> Result<CollectionId, XcmError> {
+ let AssetId::Concrete(asset_reserve_location) = asset.id else {
+ return Err(XcmExecutorError::AssetNotHandled.into());
+ };
+
+ Self::native_asset_location_to_collection(&asset_reserve_location)?
+ .or_else(|| Self::foreign_reserve_location_to_collection(asset_reserve_location))
+ .ok_or_else(|| XcmExecutorError::AssetIdConversionFailed.into())
+ }
+
+ fn native_asset_instance_to_token_id(
+ asset_instance: &AssetInstance,
+ ) -> Result<TokenId, XcmError> {
+ match asset_instance {
+ AssetInstance::Index(token_id) => Ok(TokenId(
+ (*token_id)
+ .try_into()
+ .map_err(|_| XcmError::AssetNotFound)?,
+ )),
+ _ => Err(XcmError::AssetNotFound),
+ }
+ }
+
+ /// Obtains the token id of the `asset_instance` in the collection.
+ ///
+ /// Returns `Ok(None)` only if the `asset_instance` points to a foreign item
+ /// and it haven't been created on this blockchain yet.
+ ///
+ /// If the `asset_instance` points to a native item, it cannot return `Ok(None)`.
+ fn asset_instance_to_token_id(
+ xcm_ext: &dyn XcmExtensions<T>,
+ collection_id: CollectionId,
+ asset_instance: &AssetInstance,
+ ) -> Result<Option<TokenId>, XcmError> {
+ if xcm_ext.is_foreign() {
+ Ok(Self::foreign_reserve_asset_instance_to_token_id(
+ collection_id,
+ asset_instance,
+ ))
+ } else {
+ Self::native_asset_instance_to_token_id(asset_instance).map(Some)
+ }
+ }
+
+ fn create_foreign_asset_instance(
+ xcm_ext: &dyn XcmExtensions<T>,
+ collection_id: CollectionId,
+ asset_instance: &AssetInstance,
+ to: T::CrossAccountId,
+ ) -> XcmResult {
+ let asset_instance_encoded = asset_instance.encode();
+
+ let derivative_token_id = xcm_ext
+ .create_item(
+ &Self::pallet_account(),
+ to,
+ CreateItemData::NFT(CreateNftData {
+ properties: vec![Property {
+ key: Self::reserve_asset_instance_property_key(),
+ value: asset_instance_encoded
+ .try_into()
+ .expect("asset instance length <= 32 bytes which is less than value length limit; qed"),
+ }]
+ .try_into()
+ .expect("just one property can always be stored; qed"),
+ }),
+ &ZeroBudget,
+ )
+ .map_err(|_| XcmError::FailedToTransactAsset("non-fungible item deposit failed"))?;
+
+ <ForeignReserveAssetInstanceToTokenId<T>>::insert(
+ collection_id,
+ asset_instance,
+ derivative_token_id,
+ );
+
+ Ok(())
+ }
+
+ fn deposit_asset_instance(
+ xcm_ext: &dyn XcmExtensions<T>,
+ collection_id: CollectionId,
+ to: T::CrossAccountId,
+ asset_instance: &AssetInstance,
+ ) -> XcmResult {
+ if let Some(token_id) =
+ Self::asset_instance_to_token_id(xcm_ext, collection_id, asset_instance)?
+ {
+ let depositor = &Self::pallet_account();
+ let from = depositor;
+ let amount = 1;
+
+ xcm_ext
+ .transfer_item(depositor, from, &to, token_id, amount, &ZeroBudget)
+ .map_err(|_| XcmError::FailedToTransactAsset("non-fungible item deposit failed"))
+ } else {
+ Self::create_foreign_asset_instance(xcm_ext, collection_id, asset_instance, to)
+ }
+ }
}
impl<T: Config> TransactAsset for Pallet<T> {
@@ -234,7 +365,31 @@
fn check_out(_dest: &MultiLocation, _what: &MultiAsset, _context: &XcmContext) {}
fn deposit_asset(what: &MultiAsset, to: &MultiLocation, context: &XcmContext) -> XcmResult {
- Err(XcmError::Unimplemented)
+ let collection_id = Self::multiasset_to_collection(what)?;
+ let dispatch =
+ T::CollectionDispatch::dispatch(collection_id).map_err(|_| XcmError::AssetNotFound)?;
+
+ let collection = dispatch.as_dyn();
+ let xcm_ext = collection.xcm_extensions().ok_or(XcmError::Unimplemented)?;
+
+ let to = T::LocationToAccountId::convert_location(to)
+ .ok_or(XcmExecutorError::AccountIdConversionFailed)?;
+
+ match what.fun {
+ Fungibility::Fungible(amount) => xcm_ext
+ .create_item(
+ &Self::pallet_account(),
+ to,
+ CreateItemData::Fungible(CreateFungibleData { value: amount }),
+ &ZeroBudget,
+ )
+ .map(|_| ())
+ .map_err(|_| XcmError::FailedToTransactAsset("fungible item deposit failed")),
+
+ Fungibility::NonFungible(asset_instance) => {
+ Self::deposit_asset_instance(xcm_ext, collection_id, to, &asset_instance)
+ }
+ }
}
fn withdraw_asset(
@@ -263,20 +418,17 @@
if collection_id == NATIVE_FUNGIBLE_COLLECTION_ID {
Some(Here.into())
} else {
- // let dispatch = T::CollectionDispatch::dispatch(collection_id).ok()?;
- // let collection = dispatch.as_dyn();
- // let xcm_ext = collection.xcm_extensions()?;
+ let dispatch = T::CollectionDispatch::dispatch(collection_id).ok()?;
+ let collection = dispatch.as_dyn();
+ let xcm_ext = collection.xcm_extensions()?;
- // if xcm_ext.is_foreign() {
- // let encoded_location =
- // collection.property(&<Pallet<T>>::reserve_location_property_key())?;
- // MultiLocation::decode(&mut &encoded_location[..]).ok()
- // } else {
- // T::SelfLocation::get()
- // .pushed_with_interior(GeneralIndex(collection_id.0.into()))
- // .ok()
- // }
- todo!()
+ if xcm_ext.is_foreign() {
+ <Pallet<T>>::collection_to_foreign_reserve_location(collection_id)
+ } else {
+ T::SelfLocation::get()
+ .pushed_with_interior(GeneralIndex(collection_id.0.into()))
+ .ok()
+ }
}
}
}
pallets/fungible/src/common.rsdiffbeforeafterboth--- a/pallets/fungible/src/common.rs
+++ b/pallets/fungible/src/common.rs
@@ -19,7 +19,7 @@
use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight};
use pallet_common::{
weights::WeightInfo as _, with_weight, CommonCollectionOperations, CommonWeightInfo,
- Error as CommonError, RefungibleExtensions, SelfWeightOf as PalletCommonWeightOf,
+ Error as CommonError, SelfWeightOf as PalletCommonWeightOf, XcmExtensions,
};
use sp_runtime::{ArithmeticError, DispatchError};
use sp_std::{vec, vec::Vec};
@@ -114,7 +114,7 @@
<Pallet<T>>::create_item(self, &sender, (to, fungible_data.value), nesting_budget),
<CommonWeights<T>>::create_item(&data),
),
- _ => fail!(<Error<T>>::NotFungibleDataUsedToMintFungibleCollectionToken),
+ _ => fail!(<CommonError<T>>::NotFungibleDataUsedToMintFungibleCollectionToken),
}
}
@@ -133,7 +133,7 @@
.checked_add(data.value)
.ok_or(ArithmeticError::Overflow)?;
}
- _ => fail!(<Error<T>>::NotFungibleDataUsedToMintFungibleCollectionToken),
+ _ => fail!(<CommonError<T>>::NotFungibleDataUsedToMintFungibleCollectionToken),
}
}
@@ -152,7 +152,7 @@
let weight = <CommonWeights<T>>::create_multiple_items_ex(&data);
let data = match data {
up_data_structs::CreateItemExData::Fungible(f) => f,
- _ => fail!(<Error<T>>::NotFungibleDataUsedToMintFungibleCollectionToken),
+ _ => fail!(<CommonError<T>>::NotFungibleDataUsedToMintFungibleCollectionToken),
};
with_weight(
@@ -435,6 +435,10 @@
<TotalSupply<T>>::try_get(self.id).ok()
}
+ fn xcm_extensions(&self) -> Option<&dyn XcmExtensions<T>> {
+ Some(self)
+ }
+
fn set_allowance_for_all(
&self,
_owner: T::CrossAccountId,
@@ -453,3 +457,61 @@
fail!(<Error<T>>::FungibleTokensAreAlwaysValid)
}
}
+
+impl<T: Config> XcmExtensions<T> for FungibleHandle<T> {
+ fn is_foreign(&self) -> bool {
+ self.flags.foreign
+ }
+
+ fn create_item_internal(
+ &self,
+ depositor: &<T>::CrossAccountId,
+ to: <T>::CrossAccountId,
+ data: CreateItemData,
+ nesting_budget: &dyn Budget,
+ ) -> Result<TokenId, sp_runtime::DispatchError> {
+ match &data {
+ up_data_structs::CreateItemData::Fungible(fungible_data) => {
+ <Pallet<T>>::create_multiple_items(
+ self,
+ &depositor,
+ [(to, fungible_data.value)].into_iter().collect(),
+ nesting_budget,
+ )?
+ }
+ _ => fail!(<CommonError<T>>::NotFungibleDataUsedToMintFungibleCollectionToken),
+ }
+
+ Ok(TokenId::default())
+ }
+
+ fn transfer_item_internal(
+ &self,
+ depositor: &<T>::CrossAccountId,
+ from: &<T>::CrossAccountId,
+ to: &<T>::CrossAccountId,
+ token: TokenId,
+ amount: u128,
+ nesting_budget: &dyn Budget,
+ ) -> sp_runtime::DispatchResult {
+ ensure!(
+ token == TokenId::default(),
+ <CommonError<T>>::FungibleItemsHaveNoId
+ );
+
+ <Pallet<T>>::transfer_internal(self, &depositor, &from, &to, amount, nesting_budget)
+ .map(|_| ())
+ .map_err(|post_info| post_info.error)
+ }
+
+ fn burn_item_internal(
+ &self,
+ from: <T>::CrossAccountId,
+ token: TokenId,
+ amount: u128,
+ ) -> sp_runtime::DispatchResult {
+ <Self as CommonCollectionOperations<T>>::burn_item(&self, from, token, amount)
+ .map(|_| ())
+ .map_err(|post_info| post_info.error)
+ }
+}
pallets/fungible/src/lib.rsdiffbeforeafterboth--- a/pallets/fungible/src/lib.rs
+++ b/pallets/fungible/src/lib.rs
@@ -95,8 +95,9 @@
use sp_runtime::{ArithmeticError, DispatchError, DispatchResult};
use sp_std::{collections::btree_map::BTreeMap, vec::Vec};
use up_data_structs::{
- budget::Budget, mapping::TokenAddressMapping, AccessMode, CollectionId, CreateCollectionData,
- Property, PropertyKey, TokenId,
+ budget::{Budget, ZeroBudget},
+ mapping::TokenAddressMapping,
+ AccessMode, CollectionId, CreateCollectionData, Property, PropertyKey, TokenId,
};
use weights::WeightInfo;
@@ -121,8 +122,6 @@
#[pallet::error]
pub enum Error<T> {
- /// Not Fungible item data used to mint in Fungible collection.
- NotFungibleDataUsedToMintFungibleCollectionToken,
/// Tried to set data for fungible item.
FungibleItemsDontHaveData,
/// Fungible token does not support nesting.
@@ -275,9 +274,6 @@
let balance = <Balance<T>>::get((collection.id, owner))
.checked_sub(amount)
.ok_or(<CommonError<T>>::TokenValueTooLow)?;
-
- // Foreign collection check
- ensure!(!collection.flags.foreign, <CommonError<T>>::NoPermission);
if collection.permissions.access() == AccessMode::AllowList {
collection.check_allowlist(owner)?;
@@ -309,47 +305,7 @@
));
Ok(())
}
-
- /// Burns the specified amount of the token.
- pub fn burn_foreign(
- collection: &FungibleHandle<T>,
- owner: &T::CrossAccountId,
- amount: u128,
- ) -> DispatchResult {
- let total_supply = <TotalSupply<T>>::get(collection.id)
- .checked_sub(amount)
- .ok_or(<CommonError<T>>::TokenValueTooLow)?;
-
- let balance = <Balance<T>>::get((collection.id, owner))
- .checked_sub(amount)
- .ok_or(<CommonError<T>>::TokenValueTooLow)?;
- // =========
- if balance == 0 {
- <Balance<T>>::remove((collection.id, owner));
- <PalletStructure<T>>::unnest_if_nested(owner, collection.id, TokenId::default());
- } else {
- <Balance<T>>::insert((collection.id, owner), balance);
- }
- <TotalSupply<T>>::insert(collection.id, total_supply);
-
- <PalletEvm<T>>::deposit_log(
- ERC20Events::Transfer {
- from: *owner.as_eth(),
- to: H160::default(),
- value: amount.into(),
- }
- .to_log(collection_id_to_address(collection.id)),
- );
- <PalletCommon<T>>::deposit_event(CommonEvent::ItemDestroyed(
- collection.id,
- TokenId::default(),
- owner.clone(),
- amount,
- ));
- Ok(())
- }
-
/// Transfers the specified amount of tokens. Will check that
/// the transfer is allowed for the token.
///
@@ -450,14 +406,25 @@
}
/// Minting tokens for multiple IDs.
- /// It is a utility function used in [`create_multiple_items`][`Pallet::create_multiple_items`]
- /// and [`create_multiple_items_foreign`][`Pallet::create_multiple_items_foreign`]
- pub fn create_multiple_items_common(
+ /// See [`create_item`][`Pallet::create_item`] for more details.
+ pub fn create_multiple_items(
collection: &FungibleHandle<T>,
- sender: &T::CrossAccountId,
+ depositor: &T::CrossAccountId,
data: BTreeMap<T::CrossAccountId, u128>,
nesting_budget: &dyn Budget,
) -> DispatchResult {
+ if !collection.is_owner_or_admin(depositor) {
+ ensure!(
+ collection.permissions.mint_mode(),
+ <CommonError<T>>::PublicMintingNotAllowed
+ );
+ collection.check_allowlist(depositor)?;
+
+ for (owner, _) in data.iter() {
+ collection.check_allowlist(owner)?;
+ }
+ }
+
let total_supply = data
.values()
.copied()
@@ -468,7 +435,7 @@
for (to, _) in data.iter() {
<PalletStructure<T>>::check_nesting(
- sender,
+ depositor,
to,
collection.id,
TokenId::default(),
@@ -514,44 +481,7 @@
Ok(())
}
-
- /// Minting tokens for multiple IDs.
- /// See [`create_item`][`Pallet::create_item`] for more details.
- pub fn create_multiple_items(
- collection: &FungibleHandle<T>,
- sender: &T::CrossAccountId,
- data: BTreeMap<T::CrossAccountId, u128>,
- nesting_budget: &dyn Budget,
- ) -> DispatchResult {
- // Foreign collection check
- ensure!(!collection.flags.foreign, <CommonError<T>>::NoPermission);
-
- if !collection.is_owner_or_admin(sender) {
- ensure!(
- collection.permissions.mint_mode(),
- <CommonError<T>>::PublicMintingNotAllowed
- );
- collection.check_allowlist(sender)?;
-
- for (owner, _) in data.iter() {
- collection.check_allowlist(owner)?;
- }
- }
- Self::create_multiple_items_common(collection, sender, data, nesting_budget)
- }
-
- /// Minting tokens for multiple IDs.
- /// See [`create_item_foreign`][`Pallet::create_item_foreign`] for more details.
- pub fn create_multiple_items_foreign(
- collection: &FungibleHandle<T>,
- sender: &T::CrossAccountId,
- data: BTreeMap<T::CrossAccountId, u128>,
- nesting_budget: &dyn Budget,
- ) -> DispatchResult {
- Self::create_multiple_items_common(collection, sender, data, nesting_budget)
- }
-
fn set_allowance_unchecked(
collection: &FungibleHandle<T>,
owner: &T::CrossAccountId,
@@ -777,24 +707,6 @@
nesting_budget: &dyn Budget,
) -> DispatchResult {
Self::create_multiple_items(
- collection,
- sender,
- [(data.0, data.1)].into_iter().collect(),
- nesting_budget,
- )
- }
-
- /// Creates fungible token.
- ///
- /// - `data`: Contains user who will become the owners of the tokens and amount
- /// of tokens he will receive.
- pub fn create_item_foreign(
- collection: &FungibleHandle<T>,
- sender: &T::CrossAccountId,
- data: CreateItemData<T>,
- nesting_budget: &dyn Budget,
- ) -> DispatchResult {
- Self::create_multiple_items_foreign(
collection,
sender,
[(data.0, data.1)].into_iter().collect(),
pallets/nonfungible/src/common.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/common.rs
+++ b/pallets/nonfungible/src/common.rs
@@ -19,8 +19,8 @@
use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight};
use pallet_common::{
weights::WeightInfo as _, with_weight, write_token_properties_total_weight,
- CommonCollectionOperations, CommonWeightInfo, RefungibleExtensions,
- SelfWeightOf as PalletCommonWeightOf,
+ CommonCollectionOperations, CommonWeightInfo, SelfWeightOf as PalletCommonWeightOf,
+ XcmExtensions,
};
use pallet_structure::Pallet as PalletStructure;
use sp_runtime::DispatchError;
@@ -543,6 +543,10 @@
}
}
+ fn xcm_extensions(&self) -> Option<&dyn XcmExtensions<T>> {
+ Some(self)
+ }
+
fn set_allowance_for_all(
&self,
owner: T::CrossAccountId,
@@ -566,3 +570,53 @@
)
}
}
+
+impl<T: Config> XcmExtensions<T> for NonfungibleHandle<T> {
+ fn is_foreign(&self) -> bool {
+ self.flags.foreign
+ }
+
+ fn create_item_internal(
+ &self,
+ depositor: &<T>::CrossAccountId,
+ to: <T>::CrossAccountId,
+ data: up_data_structs::CreateItemData,
+ nesting_budget: &dyn Budget,
+ ) -> Result<TokenId, sp_runtime::DispatchError> {
+ <Pallet<T>>::create_multiple_items(
+ self,
+ &depositor,
+ vec![map_create_data::<T>(data, &to)?],
+ nesting_budget,
+ )?;
+
+ Ok(self.last_token_id())
+ }
+
+ fn transfer_item_internal(
+ &self,
+ depositor: &<T>::CrossAccountId,
+ from: &<T>::CrossAccountId,
+ to: &<T>::CrossAccountId,
+ token: TokenId,
+ amount: u128,
+ nesting_budget: &dyn Budget,
+ ) -> sp_runtime::DispatchResult {
+ ensure!(amount == 1, <Error<T>>::NonfungibleItemsHaveNoAmount);
+
+ <Pallet<T>>::transfer_internal(self, &depositor, &from, &to, token, nesting_budget)
+ .map(|_| ())
+ .map_err(|post_info| post_info.error)
+ }
+
+ fn burn_item_internal(
+ &self,
+ from: T::CrossAccountId,
+ token: TokenId,
+ amount: u128,
+ ) -> sp_runtime::DispatchResult {
+ ensure!(amount == 1, <Error<T>>::NonfungibleItemsHaveNoAmount);
+
+ <Pallet<T>>::burn(self, &from, token)
+ }
+}
primitives/data-structs/src/budget.rsdiffbeforeafterboth--- a/primitives/data-structs/src/budget.rs
+++ b/primitives/data-structs/src/budget.rs
@@ -36,3 +36,10 @@
true
}
}
+
+pub struct ZeroBudget;
+impl Budget for ZeroBudget {
+ fn consume_custom(&self, _calls: u32) -> bool {
+ 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,14 +1,43 @@
use frame_support::{parameter_types, PalletId};
+use pallet_evm::account::CrossAccountId;
+use sp_core::H160;
+use staging_xcm::prelude::*;
+use staging_xcm_builder::AccountKey20Aliases;
-use crate::{runtime_common::config::governance, Runtime, RuntimeEvent};
+use crate::{
+ runtime_common::config::{
+ ethereum::CrossAccountId as ConfigCrossAccountId,
+ governance,
+ xcm::{LocationToAccountId, SelfLocation},
+ },
+ RelayNetwork, Runtime, RuntimeEvent,
+};
parameter_types! {
pub ForeignAssetPalletId: PalletId = PalletId(*b"frgnasts");
}
+pub struct LocationToCrossAccountId;
+impl staging_xcm_executor::traits::ConvertLocation<ConfigCrossAccountId>
+ for LocationToCrossAccountId
+{
+ fn convert_location(location: &MultiLocation) -> Option<ConfigCrossAccountId> {
+ LocationToAccountId::convert_location(location)
+ .map(|sub| ConfigCrossAccountId::from_sub(sub))
+ .or_else(|| {
+ let eth_address =
+ AccountKey20Aliases::<RelayNetwork, H160>::convert_location(location)?;
+
+ Some(ConfigCrossAccountId::from_eth(eth_address))
+ })
+ }
+}
+
impl pallet_foreign_assets::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type ForceRegisterOrigin = governance::RootOrTechnicalCommitteeMember;
type PalletId = ForeignAssetPalletId;
+ type SelfLocation = SelfLocation;
+ type LocationToAccountId = LocationToCrossAccountId;
type WeightInfo = pallet_foreign_assets::weights::SubstrateWeight<Self>;
}