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

difftreelog

fix(rmrk) sending nft

Daniel Shiposha2022-06-05parent: #7e808da.patch.diff
in: master

5 files changed

modifiedpallets/proxy-rmrk-core/src/lib.rsdiffbeforeafterboth
25 Pallet as PalletCommon, Error as CommonError, CollectionHandle, CommonCollectionOperations,25 Pallet as PalletCommon, Error as CommonError, CollectionHandle, CommonCollectionOperations,
26};26};
27use pallet_nonfungible::{Pallet as PalletNft, NonfungibleHandle, TokenData};27use pallet_nonfungible::{Pallet as PalletNft, NonfungibleHandle, TokenData};
28use pallet_structure::Pallet as PalletStructure;28use pallet_structure::{Pallet as PalletStructure, Error as StructureError};
29use pallet_evm::account::CrossAccountId;29use pallet_evm::account::CrossAccountId;
30use core::convert::AsRef;30use core::convert::AsRef;
3131
128 NoAvailableNftId,128 NoAvailableNftId,
129 CollectionUnknown,129 CollectionUnknown,
130 NoPermission,130 NoPermission,
131 NonTransferable,
131 CollectionFullOrLocked,132 CollectionFullOrLocked,
132 ResourceDoesntExist,133 ResourceDoesntExist,
134 CannotSendToDescendentOrSelf,
133 }135 }
134136
135 #[pallet::call]137 #[pallet::call]
207 );209 );
208210
209 <PalletNft<T>>::destroy_collection(collection, &cross_sender)211 <PalletNft<T>>::destroy_collection(collection, &cross_sender)
210 .map_err(Self::map_common_err_to_proxy)?;212 .map_err(Self::map_unique_err_to_proxy)?;
211213
212 Self::deposit_event(Event::CollectionDestroyed {214 Self::deposit_event(Event::CollectionDestroyed {
213 issuer: sender,215 issuer: sender,
283 recipient: Option<T::AccountId>,285 recipient: Option<T::AccountId>,
284 royalty_amount: Option<Permill>,286 royalty_amount: Option<Permill>,
285 metadata: RmrkString,287 metadata: RmrkString,
288 transferable: bool,
286 ) -> DispatchResult {289 ) -> DispatchResult {
287 let sender = ensure_signed(origin)?;290 let sender = ensure_signed(origin)?;
288 let sender = T::CrossAccountId::from_sub(sender);291 let sender = T::CrossAccountId::from_sub(sender);
304 &collection,307 &collection,
305 [308 [
306 Self::rmrk_property(TokenType, &NftType::Regular)?,309 Self::rmrk_property(TokenType, &NftType::Regular)?,
310 Self::rmrk_property(Transferable, &transferable)?,
311 Self::rmrk_property(PendingNftAccept, &false)?,
307 Self::rmrk_property(RoyaltyInfo, &royalty_info)?,312 Self::rmrk_property(RoyaltyInfo, &royalty_info)?,
308 Self::rmrk_property(Metadata, &metadata)?,313 Self::rmrk_property(Metadata, &metadata)?,
309 Self::rmrk_property(Equipped, &false)?,314 Self::rmrk_property(Equipped, &false)?,
327 )332 )
328 .map_err(|err| match err {333 .map_err(|err| match err {
329 DispatchError::Arithmetic(_) => <Error<T>>::NoAvailableNftId.into(),334 DispatchError::Arithmetic(_) => <Error<T>>::NoAvailableNftId.into(),
330 err => Self::map_common_err_to_proxy(err),335 err => Self::map_unique_err_to_proxy(err),
331 })?;336 })?;
332337
333 Self::deposit_event(Event::NftMinted {338 Self::deposit_event(Event::NftMinted {
373 new_owner: RmrkAccountIdOrCollectionNftTuple<T::AccountId>,378 new_owner: RmrkAccountIdOrCollectionNftTuple<T::AccountId>,
374 ) -> DispatchResult {379 ) -> DispatchResult {
375 let sender = ensure_signed(origin.clone())?;380 let sender = ensure_signed(origin.clone())?;
376 let cross_sender = T::CrossAccountId::from_sub(sender.clone());381 let cross_sender = T::CrossAccountId::from_sub(sender);
377382
378 let collection_id = Self::unique_collection_id(rmrk_collection_id)?;383 let collection_id = Self::unique_collection_id(rmrk_collection_id)?;
379 let nft_id = rmrk_nft_id.into();384 let nft_id = rmrk_nft_id.into();
388 misc::CollectionType::Regular,393 misc::CollectionType::Regular,
389 )?;394 )?;
395
396 if !Self::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::Transferable)? {
397 return Err(<Error<T>>::NonTransferable.into());
398 }
390399
391 let budget = budget::Value::new(NESTING_BUDGET);400 if Self::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::PendingNftAccept)? {
401 return Err(<Error<T>>::NoPermission.into());
402 }
392403
393 let target_owner;404 let target_owner;
394405
399 RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(target_collection_id, target_nft_id) => {410 RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(target_collection_id, target_nft_id) => {
400 let target_collection_id = Self::unique_collection_id(target_collection_id)?;411 let target_collection_id = Self::unique_collection_id(target_collection_id)?;
401412
402 target_owner = T::CrossTokenAddressMapping::token_to_address(413 let target_nft_budget = budget::Value::new(NESTING_BUDGET);
403 target_collection_id,
404 target_nft_id.into(),
405 );
406414
407 let spender = <PalletStructure<T>>::get_indirect_owner(415 let target_nft_owner = <PalletStructure<T>>::get_checked_indirect_owner(
408 target_collection_id,416 target_collection_id,
409 target_nft_id.into(),417 target_nft_id.into(),
410 Some((collection_id, nft_id)),418 Some((collection_id, nft_id)),
411 &budget,419 &target_nft_budget,
412 )?;420 ).map_err(Self::map_unique_err_to_proxy)?;
413421
414 let is_approval_required = cross_sender != spender;422 let is_approval_required = cross_sender != target_nft_owner;
415423
416 if is_approval_required {424 if is_approval_required {
417 // FIXME425 target_owner = target_nft_owner;
418 // <PalletNft<T>>::set_allowance(426
419 // &collection,427 <PalletNft<T>>::set_scoped_token_property(
420 // &cross_sender,428 collection.id,
421 // nft_id,429 nft_id,
422 // Some(&spender),430 PropertyScope::Rmrk,
423 // &budget431 Self::rmrk_property(PendingNftAccept, &is_approval_required)?,
424 // ).map_err(Self::map_common_err_to_proxy)?;432 )?;
425433 } else {
426 return Ok(());434 target_owner = T::CrossTokenAddressMapping::token_to_address(
435 target_collection_id,
436 target_nft_id.into(),
437 );
427 }438 }
428 }439 }
429 }440 }
441
442 let src_nft_budget = budget::Value::new(NESTING_BUDGET);
430443
431 <PalletNft<T>>::transfer_from(444 <PalletNft<T>>::transfer_from(
432 &collection,445 &collection,
433 &cross_sender,446 &cross_sender,
434 &from,447 &from,
435 &target_owner,448 &target_owner,
436 nft_id,449 nft_id,
437 &budget450 &src_nft_budget
438 ).map_err(Self::map_common_err_to_proxy)?;451 ).map_err(Self::map_unique_err_to_proxy)?;
439452
440 Ok(())453 Ok(())
441 }454 }
719 let collection = Self::get_typed_nft_collection(collection_id, collection_type)?;732 let collection = Self::get_typed_nft_collection(collection_id, collection_type)?;
720733
721 <PalletNft<T>>::burn(&collection, &sender, token_id)734 <PalletNft<T>>::burn(&collection, &sender, token_id)
722 .map_err(Self::map_common_err_to_proxy)?;735 .map_err(Self::map_unique_err_to_proxy)?;
723736
724 Ok(())737 Ok(())
725 }738 }
762 )775 )
763 .map_err(|err| match err {776 .map_err(|err| match err {
764 DispatchError::Arithmetic(_) => <Error<T>>::NoAvailableNftId.into(),777 DispatchError::Arithmetic(_) => <Error<T>>::NoAvailableNftId.into(),
765 err => Self::map_common_err_to_proxy(err),778 err => Self::map_unique_err_to_proxy(err),
766 })?;779 })?;
767780
768 Ok(resource_id.0)781 Ok(resource_id.0)
794 let sender = T::CrossAccountId::from_sub(sender);807 let sender = T::CrossAccountId::from_sub(sender);
795 if topmost_owner == sender {808 if topmost_owner == sender {
796 <PalletNft<T>>::burn(&resource_collection, &sender, resource_id)809 <PalletNft<T>>::burn(&resource_collection, &sender, resource_id)
797 .map_err(Self::map_common_err_to_proxy)?;810 .map_err(Self::map_unique_err_to_proxy)?;
798 } else {811 } else {
799 <PalletNft<T>>::set_scoped_token_property(812 <PalletNft<T>>::set_scoped_token_property(
800 resource_collection_id,813 resource_collection_id,
828 ) -> DispatchResult {841 ) -> DispatchResult {
829 collection842 collection
830 .check_is_owner(account)843 .check_is_owner(account)
831 .map_err(Self::map_common_err_to_proxy)844 .map_err(Self::map_unique_err_to_proxy)
832 }845 }
833846
834 pub fn last_collection_idx() -> RmrkCollectionId {847 pub fn last_collection_idx() -> RmrkCollectionId {
1064 Ok(properties)1077 Ok(properties)
1065 }1078 }
10661079
1067 fn map_common_err_to_proxy(err: DispatchError) -> DispatchError {1080 fn map_unique_err_to_proxy(err: DispatchError) -> DispatchError {
1068 map_common_err_to_proxy! {1081 map_unique_err_to_proxy! {
1069 match err {1082 match err {
1070 NoPermission => NoPermission,1083 CommonError::NoPermission => NoPermission,
1071 CollectionTokenLimitExceeded => CollectionFullOrLocked,1084 CommonError::CollectionTokenLimitExceeded => CollectionFullOrLocked,
1072 PublicMintingNotAllowed => NoPermission,1085 CommonError::PublicMintingNotAllowed => NoPermission,
1073 TokenNotFound => NoAvailableNftId,1086 CommonError::TokenNotFound => NoAvailableNftId,
1074 ApprovedValueTooLow => NoPermission1087 CommonError::ApprovedValueTooLow => NoPermission,
1088 StructureError::TokenNotFound => NoAvailableNftId,
1089 StructureError::OuroborosDetected => CannotSendToDescendentOrSelf
1075 }1090 }
1076 }1091 }
1077 }1092 }
modifiedpallets/proxy-rmrk-core/src/misc.rsdiffbeforeafterboth
2use codec::{Encode, Decode, Error};2use codec::{Encode, Decode, Error};
33
4#[macro_export]4#[macro_export]
5macro_rules! map_common_err_to_proxy {5macro_rules! map_unique_err_to_proxy {
6 (match $err:ident { $($common_err:ident => $proxy_err:ident),+ }) => {6 (match $err:ident { $($unique_err_ty:ident :: $unique_err:ident => $proxy_err:ident),+ }) => {
7 $(7 $(
8 if $err == <CommonError<T>>::$common_err.into() {8 if $err == <$unique_err_ty<T>>::$unique_err.into() {
9 return <Error<T>>::$proxy_err.into()9 return <Error<T>>::$proxy_err.into()
10 } else10 } else
11 )+ {11 )+ {
modifiedpallets/proxy-rmrk-core/src/property.rsdiffbeforeafterboth
5 Metadata,5 Metadata,
6 CollectionType,6 CollectionType,
7 TokenType,7 TokenType,
8 Transferable,
8 RoyaltyInfo,9 RoyaltyInfo,
9 Equipped,10 Equipped,
10 ResourceCollection,11 ResourceCollection,
11 ResourcePriorities,12 ResourcePriorities,
12 ResourceType,13 ResourceType,
14 PendingNftAccept,
13 PendingResourceAccept,15 PendingResourceAccept,
14 PendingResourceRemoval,16 PendingResourceRemoval,
15 Parts,17 Parts,
49 Self::Metadata => key!("metadata"),51 Self::Metadata => key!("metadata"),
50 Self::CollectionType => key!("collection-type"),52 Self::CollectionType => key!("collection-type"),
51 Self::TokenType => key!("token-type"),53 Self::TokenType => key!("token-type"),
54 Self::Transferable => key!("transferable"),
52 Self::RoyaltyInfo => key!("royalty-info"),55 Self::RoyaltyInfo => key!("royalty-info"),
53 Self::Equipped => key!("equipped"),56 Self::Equipped => key!("equipped"),
54 Self::ResourceCollection => key!("resource-collection"),57 Self::ResourceCollection => key!("resource-collection"),
55 Self::ResourcePriorities => key!("resource-priorities"),58 Self::ResourcePriorities => key!("resource-priorities"),
56 Self::ResourceType => key!("resource-type"),59 Self::ResourceType => key!("resource-type"),
60 Self::PendingNftAccept => key!("pending-nft-accept"),
57 Self::PendingResourceAccept => key!("pending-accept"),61 Self::PendingResourceAccept => key!("pending-resource-accept"),
58 Self::PendingResourceRemoval => key!("pending-removal"),62 Self::PendingResourceRemoval => key!("pending-resource-removal"),
59 Self::Parts => key!("parts"),63 Self::Parts => key!("parts"),
60 Self::Base => key!("base"),64 Self::Base => key!("base"),
61 Self::Src => key!("src"),65 Self::Src => key!("src"),
modifiedpallets/structure/src/lib.rsdiffbeforeafterboth
149 })149 })
150 }150 }
151151
152 pub fn get_indirect_owner(152 pub fn get_checked_indirect_owner(
153 collection: CollectionId,153 collection: CollectionId,
154 token: TokenId,154 token: TokenId,
155 for_nest: Option<(CollectionId, TokenId)>,155 for_nest: Option<(CollectionId, TokenId)>,
203 None => user,203 None => user,
204 };204 };
205205
206 Self::get_indirect_owner(206 Self::get_checked_indirect_owner(
207 collection,207 collection,
208 token,208 token,
209 for_nest,209 for_nest,
modifiedruntime/common/src/runtime_apis.rsdiffbeforeafterboth
188 None => return Ok(None)188 None => return Ok(None)
189 };189 };
190
191 let allowance = pallet_nonfungible::Allowance::<Runtime>::get((collection_id, nft_id));
192190
193 Ok(Some(RmrkInstanceInfo {191 Ok(Some(RmrkInstanceInfo {
194 owner: owner,192 owner: owner,
195 royalty: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::RoyaltyInfo)?,193 royalty: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::RoyaltyInfo)?,
196 metadata: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::Metadata)?,194 metadata: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::Metadata)?,
197 equipped: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::Equipped)?,195 equipped: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::Equipped)?,
198 pending: allowance.is_some(),196 pending: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::PendingNftAccept)?,
199 }))197 }))
200 }198 }
201199
202 fn account_tokens(account_id: AccountId, collection_id: RmrkCollectionId) -> Result<Vec<RmrkNftId>, DispatchError> {200 fn account_tokens(account_id: AccountId, collection_id: RmrkCollectionId) -> Result<Vec<RmrkNftId>, DispatchError> {
203 use pallet_proxy_rmrk_core::misc::CollectionType;201 use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType};
204 use pallet_common::CommonCollectionOperations;202 use pallet_common::CommonCollectionOperations;
205203
206 let cross_account_id = CrossAccountId::from_sub(account_id);204 let cross_account_id = CrossAccountId::from_sub(account_id);
210 Err(_) => return Ok(Vec::new()),208 Err(_) => return Ok(Vec::new()),
211 };209 };
212210
213 Ok(
214 collection.account_tokens(cross_account_id)211 let tokens = collection.account_tokens(cross_account_id)
215 .into_iter()212 .into_iter()
213 .filter(|token| {
214 let is_pending = RmrkCore::get_nft_property_decoded(
215 collection_id,
216 *token,
217 RmrkProperty::PendingNftAccept
218 ).unwrap_or(true);
219
220 !is_pending
221 })
216 .map(|token| token.0)222 .map(|token| token.0)
217 .collect()223 .collect();
218 )224
225 Ok(tokens)
219 }226 }
220227
221 fn nft_children(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkNftChild>, DispatchError> {228 fn nft_children(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkNftChild>, DispatchError> {
229 use pallet_proxy_rmrk_core::RmrkProperty;
230
222 let collection_id = match RmrkCore::unique_collection_id(collection_id) {231 let collection_id = match RmrkCore::unique_collection_id(collection_id) {
223 Ok(id) => id,232 Ok(id) => id,
229 Ok(238 Ok(
230 pallet_nonfungible::TokenChildren::<Runtime>::iter_prefix((collection_id, nft_id))239 pallet_nonfungible::TokenChildren::<Runtime>::iter_prefix((collection_id, nft_id))
231 .filter_map(|((child_collection, child_token), _)| {240 .filter_map(|((child_collection, child_token), _)| {
241 let is_pending = RmrkCore::get_nft_property_decoded(
242 child_collection,
243 child_token,
244 RmrkProperty::PendingNftAccept
245 ).ok()?;
246
247 if is_pending {
248 return None;
249 }
250
232 let rmrk_child_collection = RmrkCore::rmrk_collection_id(251 let rmrk_child_collection = RmrkCore::rmrk_collection_id(
233 child_collection252 child_collection