diff --git a/substrate/frame/nfts/src/features/transfer.rs b/substrate/frame/nfts/src/features/transfer.rs index 0471bd67b29164358069d27c2239a2010795b7d0..ac73d283ee0e578b8b81e90697dcb5a7e3054793 100644 --- a/substrate/frame/nfts/src/features/transfer.rs +++ b/substrate/frame/nfts/src/features/transfer.rs @@ -124,10 +124,10 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> { pub(crate) fn do_transfer_ownership( origin: T::AccountId, collection: T::CollectionId, - owner: T::AccountId, + new_owner: T::AccountId, ) -> DispatchResult { // Check if the new owner is acceptable based on the collection's acceptance settings. - let acceptable_collection = OwnershipAcceptance::<T, I>::get(&owner); + let acceptable_collection = OwnershipAcceptance::<T, I>::get(&new_owner); ensure!(acceptable_collection.as_ref() == Some(&collection), Error::<T, I>::Unaccepted); // Try to retrieve and mutate the collection details. @@ -135,27 +135,28 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> { let details = maybe_details.as_mut().ok_or(Error::<T, I>::UnknownCollection)?; // Check if the `origin` is the current owner of the collection. ensure!(origin == details.owner, Error::<T, I>::NoPermission); - if details.owner == owner { + if details.owner == new_owner { return Ok(()) } // Move the deposit to the new owner. T::Currency::repatriate_reserved( &details.owner, - &owner, + &new_owner, details.owner_deposit, Reserved, )?; // Update account ownership information. CollectionAccount::<T, I>::remove(&details.owner, &collection); - CollectionAccount::<T, I>::insert(&owner, &collection, ()); + CollectionAccount::<T, I>::insert(&new_owner, &collection, ()); - details.owner = owner.clone(); - OwnershipAcceptance::<T, I>::remove(&owner); + details.owner = new_owner.clone(); + OwnershipAcceptance::<T, I>::remove(&new_owner); + frame_system::Pallet::<T>::dec_consumers(&new_owner); // Emit `OwnerChanged` event. - Self::deposit_event(Event::OwnerChanged { collection, new_owner: owner }); + Self::deposit_event(Event::OwnerChanged { collection, new_owner }); Ok(()) }) } diff --git a/substrate/frame/nfts/src/lib.rs b/substrate/frame/nfts/src/lib.rs index 92b27432ab215ced08a8dd92ddff40f3db38415f..a7d505e2e397dbca5f547ed9ed1a7c3cc4235aa5 100644 --- a/substrate/frame/nfts/src/lib.rs +++ b/substrate/frame/nfts/src/lib.rs @@ -1153,11 +1153,11 @@ pub mod pallet { pub fn transfer_ownership( origin: OriginFor<T>, collection: T::CollectionId, - owner: AccountIdLookupOf<T>, + new_owner: AccountIdLookupOf<T>, ) -> DispatchResult { let origin = ensure_signed(origin)?; - let owner = T::Lookup::lookup(owner)?; - Self::do_transfer_ownership(origin, collection, owner) + let new_owner = T::Lookup::lookup(new_owner)?; + Self::do_transfer_ownership(origin, collection, new_owner) } /// Change the Issuer, Admin and Freezer of a collection. diff --git a/substrate/frame/nfts/src/tests.rs b/substrate/frame/nfts/src/tests.rs index 0c32aea2be049e4e72c9afd1e28d045e6abb9c0a..9e521537534fab31c4626c21ecf06e3df366c01b 100644 --- a/substrate/frame/nfts/src/tests.rs +++ b/substrate/frame/nfts/src/tests.rs @@ -614,8 +614,13 @@ fn transfer_owner_should_work() { Nfts::transfer_ownership(RuntimeOrigin::signed(account(1)), 0, account(2)), Error::<Test>::Unaccepted ); + assert_eq!(System::consumers(&account(2)), 0); + assert_ok!(Nfts::set_accept_ownership(RuntimeOrigin::signed(account(2)), Some(0))); + assert_eq!(System::consumers(&account(2)), 1); + assert_ok!(Nfts::transfer_ownership(RuntimeOrigin::signed(account(1)), 0, account(2))); + assert_eq!(System::consumers(&account(2)), 1); // one consumer is added due to deposit repatriation assert_eq!(collections(), vec![(account(2), 0)]); assert_eq!(Balances::total_balance(&account(1)), 98); diff --git a/substrate/frame/uniques/src/lib.rs b/substrate/frame/uniques/src/lib.rs index 63a6e83de071990db42397cbc14932f26ad71887..253a318e474e1e415e045ca1e5603eb9289721bf 100644 --- a/substrate/frame/uniques/src/lib.rs +++ b/substrate/frame/uniques/src/lib.rs @@ -856,34 +856,37 @@ pub mod pallet { pub fn transfer_ownership( origin: OriginFor<T>, collection: T::CollectionId, - owner: AccountIdLookupOf<T>, + new_owner: AccountIdLookupOf<T>, ) -> DispatchResult { let origin = ensure_signed(origin)?; - let owner = T::Lookup::lookup(owner)?; + let new_owner = T::Lookup::lookup(new_owner)?; - let acceptable_collection = OwnershipAcceptance::<T, I>::get(&owner); + let acceptable_collection = OwnershipAcceptance::<T, I>::get(&new_owner); ensure!(acceptable_collection.as_ref() == Some(&collection), Error::<T, I>::Unaccepted); Collection::<T, I>::try_mutate(collection.clone(), |maybe_details| { let details = maybe_details.as_mut().ok_or(Error::<T, I>::UnknownCollection)?; ensure!(origin == details.owner, Error::<T, I>::NoPermission); - if details.owner == owner { + if details.owner == new_owner { return Ok(()) } // Move the deposit to the new owner. T::Currency::repatriate_reserved( &details.owner, - &owner, + &new_owner, details.total_deposit, Reserved, )?; + CollectionAccount::<T, I>::remove(&details.owner, &collection); - CollectionAccount::<T, I>::insert(&owner, &collection, ()); - details.owner = owner.clone(); - OwnershipAcceptance::<T, I>::remove(&owner); + CollectionAccount::<T, I>::insert(&new_owner, &collection, ()); + + details.owner = new_owner.clone(); + OwnershipAcceptance::<T, I>::remove(&new_owner); + frame_system::Pallet::<T>::dec_consumers(&new_owner); - Self::deposit_event(Event::OwnerChanged { collection, new_owner: owner }); + Self::deposit_event(Event::OwnerChanged { collection, new_owner }); Ok(()) }) } diff --git a/substrate/frame/uniques/src/tests.rs b/substrate/frame/uniques/src/tests.rs index 52f7df3b5efbc29796a77591ac44efd32429796a..351dac09f7f202a62df508fe71d26bb24662d5bc 100644 --- a/substrate/frame/uniques/src/tests.rs +++ b/substrate/frame/uniques/src/tests.rs @@ -254,8 +254,11 @@ fn transfer_owner_should_work() { Uniques::transfer_ownership(RuntimeOrigin::signed(1), 0, 2), Error::<Test>::Unaccepted ); + assert_eq!(System::consumers(&2), 0); assert_ok!(Uniques::set_accept_ownership(RuntimeOrigin::signed(2), Some(0))); + assert_eq!(System::consumers(&2), 1); assert_ok!(Uniques::transfer_ownership(RuntimeOrigin::signed(1), 0, 2)); + assert_eq!(System::consumers(&2), 1); assert_eq!(collections(), vec![(2, 0)]); assert_eq!(Balances::total_balance(&1), 98);