Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement children and iterative burning #5

Merged
merged 4 commits into from
Dec 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions pallets/rmrk-core/src/functions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use super::*;

impl<T: Config> Pallet<T> {
pub fn is_x_descendent_of_y(
child_collection_id: T::CollectionId,
child_nft_id: T::NftId,
parent_collection_id: T::CollectionId,
parent_nft_id: T::NftId,
) -> bool {
let mut found_child = false;
if let Some(children) = Children::<T>::get(parent_collection_id, parent_nft_id) {
for child in children {
if child == (child_collection_id, child_nft_id) {
return true;
} else {
if Pallet::<T>::is_x_descendent_of_y(
child_collection_id,
child_nft_id,
child.0,
child.1,
) {
found_child = true;
}
}
}
}
found_child
}
}
62 changes: 57 additions & 5 deletions pallets/rmrk-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ use sp_std::{convert::TryInto, vec::Vec};

use types::{AccountIdOrCollectionNftTuple, ClassInfo, InstanceInfo};

mod functions;

#[cfg(test)]
mod mock;

Expand Down Expand Up @@ -107,6 +109,18 @@ pub mod pallet {
InstanceInfoOf<T>,
>;

#[pallet::storage]
#[pallet::getter(fn children)]
/// Stores nft info
pub type Children<T: Config> = StorageDoubleMap<
_,
Twox64Concat,
T::CollectionId,
Twox64Concat,
T::NftId,
Vec<(T::CollectionId, T::NftId)>,
>;

#[pallet::storage]
#[pallet::getter(fn resources)]
/// Stores resource info
Expand Down Expand Up @@ -163,6 +177,7 @@ pub mod pallet {
NoPermission,
NoWitness,
CollectionNotEmpty,
CannotSendToDescendent,
}

#[pallet::call]
Expand Down Expand Up @@ -270,19 +285,23 @@ pub mod pallet {
}

/// burn nft
/// TODO: If an NFT that contains other NFTs is being burnt, the owned NFTs are also burned.
#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
#[transactional]
pub fn burn_nft(
origin: OriginFor<T>,
collection_id: T::CollectionId,
nft_id: T::NftId,
) -> DispatchResult {
let sender = ensure_signed(origin)?;
let sender = ensure_signed(origin.clone())?;
pallet_uniques::Pallet::<T>::do_burn(collection_id.into(), nft_id.into(), |_, _| {
Ok(())
})?;
NFTs::<T>::remove(collection_id, nft_id);
if let Some(kids) = Children::<T>::take(collection_id, nft_id) {
for child in kids {
Pallet::<T>::burn_nft(origin.clone(), child.0, child.1)?;
}
}
Self::deposit_event(Event::NFTBurned(sender, nft_id));
Ok(())
}
Expand Down Expand Up @@ -339,15 +358,48 @@ pub mod pallet {

match new_owner.clone() {
AccountIdOrCollectionNftTuple::AccountId(account_id) => {
// Remove previous parental relationship
if let AccountIdOrCollectionNftTuple::CollectionAndNftTuple(cid, nid) =
sending_nft.owner
{
if let Some(mut kids) = Children::<T>::take(cid, nid) {
kids.retain(|&kid| kid != (collection_id, nft_id));
Children::<T>::insert(cid, nid, kids);
}
}
sending_nft.rootowner = account_id.clone();
},
}
AccountIdOrCollectionNftTuple::CollectionAndNftTuple(cid, nid) => {
let recipient_nft =
NFTs::<T>::get(cid, nid).ok_or(Error::<T>::NoAvailableNftId)?;
// Check if sending NFT is already a child of recipient NFT
ensure!(
!Pallet::<T>::is_x_descendent_of_y(cid, nid, collection_id, nft_id),
Error::<T>::CannotSendToDescendent
);

// Remove parent if exists: first we only care if the owner is a non-AccountId)
if let AccountIdOrCollectionNftTuple::CollectionAndNftTuple(cid, nid) =
sending_nft.owner
{
// second we only care if the parent has children (it should)
if let Some(mut kids) = Children::<T>::take(cid, nid) {
// third we only "retain" the other children
kids.retain(|&kid| kid != (collection_id, nft_id));
Children::<T>::insert(cid, nid, kids);
}
}
if sending_nft.rootowner != recipient_nft.rootowner {
sending_nft.rootowner = recipient_nft.rootowner
}
},
match Children::<T>::take(cid, nid) {
None => Children::<T>::insert(cid, nid, vec![(collection_id, nft_id)]),
Some(mut kids) => {
kids.push((collection_id, nft_id));
Children::<T>::insert(cid, nid, kids);
}
}
}
};
sending_nft.owner = new_owner.clone();

Expand Down Expand Up @@ -383,7 +435,7 @@ pub mod pallet {
// collection.issuer = dest.clone();
// Collections::<T>::insert(collection_id, collection);
// Ok(())
// })?;
// })?;

// Check that sender is current issuer
let mut collection =
Expand Down
Loading