Repository: paritytech/substrate
File: frame/assets/src/functions.rs (Rust)

Code before:
		let _ = Asset::<T, I>::try_mutate_exists(
			id.clone(),
			|maybe_details| -> Result<(), DispatchError> {
				let details = maybe_details.as_mut().ok_or(Error::<T, I>::Unknown)?;

				// Should only destroy accounts while the asset is in a destroying state.
				ensure!(details.status == AssetStatus::Destroying, Error::<T, I>::IncorrectStatus);

				for ((owner, _), approval) in Approvals::<T, I>::drain_prefix((id.clone(),)) {
					T::Currency::unreserve(&owner, approval.deposit);
					removed_approvals = removed_approvals.saturating_add(1);
					details.approvals = details.approvals.saturating_sub(1);
					if removed_approvals >= max_items {
						break
					}
				}
				Self::deposit_event(Event::ApprovalsDestroyed {
					asset_id: id,
					approvals_destroyed: removed_approvals as u32,
					approvals_remaining: details.approvals as u32,
				});
				Ok(())
			},
		)?;
		Ok(removed_approvals)
	}

	/// Complete destroying an asset and unreserve the deposit.
	///
	/// On success, the `Event::Destroyed` event is emitted.
	pub(super) fn do_finish_destroy(id: T::AssetId) -> DispatchResult {
		Asset::<T, I>::try_mutate_exists(id.clone(), |maybe_details| -> Result<(), DispatchError> {
			let details = maybe_details.take().ok_or(Error::<T, I>::Unknown)?;
			ensure!(details.status == AssetStatus::Destroying, Error::<T, I>::IncorrectStatus);
			ensure!(details.accounts == 0, Error::<T, I>::InUse);
			ensure!(details.approvals == 0, Error::<T, I>::InUse);
			ensure!(T::CallbackHandle::destroyed(&id).is_ok(), Error::<T, I>::CallbackFailed);

			let metadata = Metadata::<T, I>::take(&id);
			T::Currency::unreserve(
				&details.owner,
				details.deposit.saturating_add(metadata.deposit),
			);
			Self::deposit_event(Event::Destroyed { asset_id: id });

			Ok(())
		})
	}

	/// Creates an approval from `owner` to spend `amount` of asset `id` tokens by 'delegate'
	/// while reserving `T::ApprovalDeposit` from owner

Review comment (suggestion):
```suggestion
		Asset::<T, I>::try_mutate_exists(&id, |maybe_details| -> Result<(), DispatchError> {
```

Code after:
				ensure!(details.status == AssetStatus::Destroying, Error::<T, I>::IncorrectStatus);

				for ((owner, _), approval) in Approvals::<T, I>::drain_prefix((id.clone(),)) {
					T::Currency::unreserve(&owner, approval.deposit);
					removed_approvals = removed_approvals.saturating_add(1);
					details.approvals = details.approvals.saturating_sub(1);
					if removed_approvals >= max_items {
						break
					}
				}
				Self::deposit_event(Event::ApprovalsDestroyed {
					asset_id: id,
					approvals_destroyed: removed_approvals as u32,
					approvals_remaining: details.approvals as u32,
				});
				Ok(())
			},
		)?;
		Ok(removed_approvals)
	}

	/// Complete destroying an asset and unreserve the deposit.
	///
	/// On success, the `Event::Destroyed` event is emitted.
	pub(super) fn do_finish_destroy(id: T::AssetId) -> DispatchResult {
		Asset::<T, I>::try_mutate_exists(id.clone(), |maybe_details| -> Result<(), DispatchError> {
			let details = maybe_details.take().ok_or(Error::<T, I>::Unknown)?;
			ensure!(details.status == AssetStatus::Destroying, Error::<T, I>::IncorrectStatus);
			ensure!(details.accounts == 0, Error::<T, I>::InUse);
			ensure!(details.approvals == 0, Error::<T, I>::InUse);
			ensure!(T::CallbackHandle::destroyed(&id).is_ok(), Error::<T, I>::CallbackFailed);

			let metadata = Metadata::<T, I>::take(&id);
			T::Currency::unreserve(
				&details.owner,
				details.deposit.saturating_add(metadata.deposit),
			);
			Self::deposit_event(Event::Destroyed { asset_id: id });

			Ok(())
		})
	}

	/// Creates an approval from `owner` to spend `amount` of asset `id` tokens by 'delegate'
	/// while reserving `T::ApprovalDeposit` from owner
	///
	/// If an approval already exists, the new amount is added to such existing approval
	pub(super) fn do_approve_transfer(
		id: T::AssetId,
		owner: &T::AccountId,
		delegate: &T::AccountId,