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

Code before:
	///   (dust) value should be burned, rather than credited.
	///
	/// On success, the amount which should be credited (this will always be at least `amount`)
	/// together with an optional value indicating the value which should be burned. The latter
	/// will always be `None` as long as `burn_dust` is `false` or `debit` is no greater than
	/// `amount`.
	///
	/// If no valid credit can be made then return an `Err`.
	pub(super) fn prep_credit(
		id: T::AssetId,
		dest: &T::AccountId,
		amount: T::Balance,
		debit: T::Balance,
		burn_dust: bool,
	) -> Result<(T::Balance, Option<T::Balance>), DispatchError> {
		let (credit, maybe_burn) = match (burn_dust, debit.checked_sub(&amount)) {
			(true, Some(dust)) => (amount, Some(dust)),
			_ => (debit, None),
		};
		Self::can_increase(id, dest, credit, false).into_result()?;
		Ok((credit, maybe_burn))
	}

	/// Creates an account for `who` to hold asset `id` with a zero balance and takes a deposit.
	pub(super) fn do_touch(
		id: T::AssetId,
		who: T::AccountId,
		depositor: T::AccountId,
	) -> DispatchResult {
		ensure!(!Account::<T, I>::contains_key(id, &who), Error::<T, I>::AlreadyExists);
		let deposit = T::AssetAccountDeposit::get();
		let mut details = Asset::<T, I>::get(&id).ok_or(Error::<T, I>::Unknown)?;
		ensure!(details.status == AssetStatus::Live, Error::<T, I>::AssetNotLive);
		ensure!(
			&depositor == &who || &depositor == &details.admin || &depositor == &details.freezer,
			Error::<T, I>::NoPermission
		);
		let reason = Self::new_account(&who, &mut details, Some((&depositor, deposit)))?;
		T::Currency::reserve(&depositor, deposit)?;
		Asset::<T, I>::insert(&id, details);
		Account::<T, I>::insert(
			id,
			&who,
			AssetAccountOf::<T, I> {
				balance: Zero::zero(),
				is_frozen: false,
				reason,
				extra: T::Extra::default(),
			},
		);
		Self::deposit_event(Event::Touched { asset_id: id, who, depositor });

Review comment (security):
```suggestion
	/// If invoked `permissionless = true`, then a depositor can be anyone. If `permissionless = false`,
```

Code after:
	///   (dust) value should be burned, rather than credited.
	///
	/// On success, the amount which should be credited (this will always be at least `amount`)
	/// together with an optional value indicating the value which should be burned. The latter
	/// will always be `None` as long as `burn_dust` is `false` or `debit` is no greater than
	/// `amount`.
	///
	/// If no valid credit can be made then return an `Err`.
	pub(super) fn prep_credit(
		id: T::AssetId,
		dest: &T::AccountId,
		amount: T::Balance,
		debit: T::Balance,
		burn_dust: bool,
	) -> Result<(T::Balance, Option<T::Balance>), DispatchError> {
		let (credit, maybe_burn) = match (burn_dust, debit.checked_sub(&amount)) {
			(true, Some(dust)) => (amount, Some(dust)),
			_ => (debit, None),
		};
		Self::can_increase(id, dest, credit, false).into_result()?;
		Ok((credit, maybe_burn))
	}

	/// Creates an account for `who` to hold asset `id` with a zero balance and takes a deposit.
	///
	/// If invoked `permissionless = true`, then a depositor can be anyone. If `permissioned = false`,
	/// then the depositor must be the asset's `Admin` or `Freezer`.
	pub(super) fn do_touch(
		id: T::AssetId,
		who: T::AccountId,
		depositor: T::AccountId,
		permissionless: bool,
	) -> DispatchResult {
		ensure!(!Account::<T, I>::contains_key(id, &who), Error::<T, I>::AlreadyExists);
		let deposit = T::AssetAccountDeposit::get();
		let mut details = Asset::<T, I>::get(&id).ok_or(Error::<T, I>::Unknown)?;
		ensure!(details.status == AssetStatus::Live, Error::<T, I>::AssetNotLive);
		ensure!(
			permissionless || &depositor == &details.admin || &depositor == &details.freezer,
			Error::<T, I>::NoPermission
		);
		let reason = Self::new_account(&who, &mut details, Some((&depositor, deposit)))?;
		T::Currency::reserve(&depositor, deposit)?;
		Asset::<T, I>::insert(&id, details);
		Account::<T, I>::insert(
			id,
			&who,
			AssetAccountOf::<T, I> {
				balance: Zero::zero(),
				is_frozen: false,
				reason,