Finally, we'll implement the most used swap
functionality. The swap
function in a decentralized exchange (DEX)
allows users to exchange one asset for another within a liquidity pool. It enables users to trade assets without the
need for a centralized order book or matching engine. Instead, the swap is facilitated by the liquidity pool, which
determines the exchange rate based on the relative reserves of the assets in the pool.
Here's a brief overview of its functionality:
Since we already have the swap
implemented in the liquidity pool, we can refer to it when defining the extrinsic call:
#[pallet::call_index(3)]#[pallet::weight(Weight::default())]pub fn swap(origin: OriginFor<T>,asset_in: AssetIdOf<T>,asset_out: AssetIdOf<T>,amount_in: AssetBalanceOf<T>,min_amount_out: AssetBalanceOf<T>,) -> DispatchResult {let sender = ensure_signed(origin)?;let trading_pair = (asset_in, asset_out);let mut liquidity_pool =LiquidityPools::<T>::get(trading_pair).ok_or(Error::<T>::LiquidityPoolNotFound)?;let amount_out = liquidity_pool.swap(asset_in, amount_in, asset_out, min_amount_out)?;Self::transfer_asset_from_user(&sender, asset_in, amount_in)?;Self::transfer_asset_to_user(&sender, asset_out, amount_out)?;LiquidityPools::<T>::insert(&trading_pair, liquidity_pool);Self::deposit_event(Event::Swapped(sender, asset_in, amount_in, asset_out, amount_out,));Ok(())}
As you can see above, we've defined the transfer_asset_from_user
and transfer_asset_to_user
methods to help us
transfer the assets:
fn transfer_asset_from_user(user: &AccountIdOf<T>,asset_id: AssetIdOf<T>,amount: AssetBalanceOf<T>,) -> DispatchResult {T::Fungibles::transfer(asset_id,user,&Self::pallet_account_id(),amount,Preservation::Expendable,)?;Ok(())}fn transfer_asset_to_user(user: &AccountIdOf<T>,asset_id: AssetIdOf<T>,amount: AssetBalanceOf<T>,) -> DispatchResult {T::Fungibles::transfer(asset_id,&Self::pallet_account_id(),user,amount,Preservation::Expendable,)?;Ok(())}
With our current implementation, what happens when we have a liquidity pool of (DOT, USDC)
and a user requests to swap
(USDC, DOT)
? They would be routed to a pool that doesn't exist, so we'll need to add some logic to make sure that
we route users to the same liquidity pool regardless of the order of assets as long as it's the same pair. See if you
implement it.