Repository: paritytech/substrate
File: frame/asset-conversion/src/lib.rs (Rust)

Code before:
			Ok(())
		}

		fn validate_swap_path(
			path: &BoundedVec<T::MultiAssetId, T::MaxSwapPathLength>,
		) -> Result<(), DispatchError> {
			ensure!(path.len() >= 2, Error::<T>::InvalidPath);

			// validate all the pools in the path are unique
			let mut pools = BoundedBTreeSet::<PoolIdOf<T>, T::MaxSwapPathLength>::new();
			for assets_pair in path.windows(2) {
				if let [asset1, asset2] = assets_pair {
					let pool_id = Self::get_pool_id(asset1.clone(), asset2.clone());
					let new_element = pools.try_insert(pool_id).expect("can't get here");
					if !new_element {
						return Err(Error::<T>::NonUniquePath.into())
					}
				}
			}
			Ok(())
		}

		/// Returns the next pool asset id for benchmark purposes only.
		#[cfg(any(test, feature = "runtime-benchmarks"))]
		pub fn get_next_pool_asset_id() -> T::PoolAssetId {
			NextPoolAssetId::<T>::get().or(T::PoolAssetId::initial_value()).unwrap()
		}
	}
}

impl<T: Config>
	frame_support::traits::tokens::fungibles::SwapForNative<
		T::RuntimeOrigin,
		T::AccountId,
		T::Balance,
		T::AssetBalance,
		T::AssetId,
	> for Pallet<T>
where
	<T as pallet::Config>::Currency:
		frame_support::traits::tokens::fungible::Inspect<<T as frame_system::Config>::AccountId>,
{
	// If successful returns the amount in.
	fn swap_tokens_for_exact_native(
		sender: T::AccountId,
		asset_id: T::AssetId,
		amount_out: T::Balance,
		amount_in_max: Option<T::AssetBalance>,
		send_to: T::AccountId,
		keep_alive: bool,
	) -> Result<T::AssetBalance, DispatchError> {

Review comment (suggestion):
Is there really a difference here? If not, I actually prefer `unwrap_or` just to reduce the chances of panicking.

Code after:
		) -> Result<T::AssetBalance, Error<T>> {
			// amount * reserve2 / reserve1
			Self::mul_div(amount, reserve2, reserve1)
		}

		pub(super) fn calc_lp_amount_for_zero_supply(
			amount1: &T::AssetBalance,
			amount2: &T::AssetBalance,
		) -> Result<T::AssetBalance, Error<T>> {
			let amount1 = T::HigherPrecisionBalance::from(*amount1);
			let amount2 = T::HigherPrecisionBalance::from(*amount2);

			let result = amount1
				.checked_mul(&amount2)
				.ok_or(Error::<T>::Overflow)?
				.integer_sqrt()
				.checked_sub(&T::MintMinLiquidity::get().into())
				.ok_or(Error::<T>::InsufficientLiquidityMinted)?;

			result.try_into().map_err(|_| Error::<T>::Overflow)
		}

		fn mul_div(
			a: &T::AssetBalance,
			b: &T::AssetBalance,
			c: &T::AssetBalance,
		) -> Result<T::AssetBalance, Error<T>> {
			let a = T::HigherPrecisionBalance::from(*a);
			let b = T::HigherPrecisionBalance::from(*b);
			let c = T::HigherPrecisionBalance::from(*c);

			let result = a
				.checked_mul(&b)
				.ok_or(Error::<T>::Overflow)?
				.checked_div(&c)
				.ok_or(Error::<T>::Overflow)?;

			result.try_into().map_err(|_| Error::<T>::Overflow)
		}

		/// Calculates amount out.
		///
		/// Given an input amount of an asset and pair reserves, returns the maximum output amount
		/// of the other asset.
		pub fn get_amount_out(
			amount_in: &T::AssetBalance,
			reserve_in: &T::AssetBalance,
			reserve_out: &T::AssetBalance,
		) -> Result<T::AssetBalance, Error<T>> {
			let amount_in = T::HigherPrecisionBalance::from(*amount_in);
			let reserve_in = T::HigherPrecisionBalance::from(*reserve_in);