pallet-asset-conversion: Decoupling Native Currency Dependancy (#2031)

closes https://github.com/paritytech/polkadot-sdk/issues/1842

Decoupling Pallet from the Concept of Native Currency

Currently, the pallet is intrinsically linked with the concept of native
currency, requiring users to provide implementations of the
`fungible::*` and `fungibles::*` traits to interact with native and non
native assets. This incapsulates some non-related to the pallet
complexity and makes it less adaptable in contexts where the native
currency concept is absent.

With this PR, the dependence on `fungible::*` for liquidity-supplying
assets has been removed. Instead, the native and non-native currencies'
handling is now overseen by a single type that implements the
`fungibles::*` traits. To simplify this integration, types have been
introduced to facilitate the creation of a union between `fungible::*`
and `fungibles::*` implementations, producing a unified `fungibles::*`
type.

One of the reasons driving these changes is the ambition to create a
more user-friendly API for the `SwapCredit` implementation. Given that
it interacts with two distinct credit types from `fungible` and
`fungibles`, a unified type was introduced. Clients now manage potential
conversion failures for those credit types. In certain contexts, it's
vital to guarantee that operations are fail-safe, like in this impl -
[PR](https://github.com/paritytech/polkadot-sdk/pull/1845), place in
[code](https://github.com/paritytech/polkadot-sdk/blob/20b85a5fada8f55c98ba831964f5866ffeadf4da/cumulus/primitives/utility/src/lib.rs#L429).

Additional Updates:
- abstracted the pool ID and its account derivation logic via trait
bounds, along with common implementation offerings;
- removed `inc_providers` on a pool creation for the pool account;
- benchmarks:
-- swap complexity is N, not const;
-- removed `From<u128> + Into<u128>` bound from `T::Balance`;
-- removed swap/liquidity/.. amount constants, resolve them dynamically
based on pallet configuration;
-- migrated to v2 API;
- `OnUnbalanced` handler for the pool creation fee, replacing direct
transfers to a specified account ID;
- renamed `MultiAssetId` to `AssetKind` aligning with naming across
frame crates;

related PRs:
- (depends) https://github.com/paritytech/polkadot-sdk/pull/1677
- (caused) https://github.com/paritytech/polkadot-sdk/pull/2033
- (caused) https://github.com/paritytech/polkadot-sdk/pull/1876

---------

Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>
Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>
This commit is contained in:
Muharem
2023-12-20 13:57:26 +01:00
committed by GitHub
parent d32f66fb8f
commit 4f832ea865
26 changed files with 1750 additions and 4571 deletions
+19 -17
View File
@@ -24,7 +24,7 @@ pub trait Swap<AccountId> {
/// Measure units of the asset classes for swapping.
type Balance: Balance;
/// Kind of assets that are going to be swapped.
type MultiAssetId;
type AssetKind;
/// Returns the upper limit on the length of the swap path.
fn max_path_len() -> u32;
@@ -41,7 +41,7 @@ pub trait Swap<AccountId> {
/// This operation is expected to be atomic.
fn swap_exact_tokens_for_tokens(
sender: AccountId,
path: Vec<Self::MultiAssetId>,
path: Vec<Self::AssetKind>,
amount_in: Self::Balance,
amount_out_min: Option<Self::Balance>,
send_to: AccountId,
@@ -60,7 +60,7 @@ pub trait Swap<AccountId> {
/// This operation is expected to be atomic.
fn swap_tokens_for_exact_tokens(
sender: AccountId,
path: Vec<Self::MultiAssetId>,
path: Vec<Self::AssetKind>,
amount_out: Self::Balance,
amount_in_max: Option<Self::Balance>,
send_to: AccountId,
@@ -73,7 +73,7 @@ pub trait SwapCredit<AccountId> {
/// Measure units of the asset classes for swapping.
type Balance: Balance;
/// Kind of assets that are going to be swapped.
type MultiAssetId;
type AssetKind;
/// Credit implying a negative imbalance in the system that can be placed into an account or
/// alter the total supply.
type Credit;
@@ -90,7 +90,7 @@ pub trait SwapCredit<AccountId> {
///
/// This operation is expected to be atomic.
fn swap_exact_tokens_for_tokens(
path: Vec<Self::MultiAssetId>,
path: Vec<Self::AssetKind>,
credit_in: Self::Credit,
amount_out_min: Option<Self::Balance>,
) -> Result<Self::Credit, (Self::Credit, DispatchError)>;
@@ -106,7 +106,7 @@ pub trait SwapCredit<AccountId> {
///
/// This operation is expected to be atomic.
fn swap_tokens_for_exact_tokens(
path: Vec<Self::MultiAssetId>,
path: Vec<Self::AssetKind>,
credit_in: Self::Credit,
amount_out: Self::Balance,
) -> Result<(Self::Credit, Self::Credit), (Self::Credit, DispatchError)>;
@@ -114,7 +114,7 @@ pub trait SwapCredit<AccountId> {
impl<T: Config> Swap<T::AccountId> for Pallet<T> {
type Balance = T::Balance;
type MultiAssetId = T::MultiAssetId;
type AssetKind = T::AssetKind;
fn max_path_len() -> u32 {
T::MaxSwapPathLength::get()
@@ -122,7 +122,7 @@ impl<T: Config> Swap<T::AccountId> for Pallet<T> {
fn swap_exact_tokens_for_tokens(
sender: T::AccountId,
path: Vec<Self::MultiAssetId>,
path: Vec<Self::AssetKind>,
amount_in: Self::Balance,
amount_out_min: Option<Self::Balance>,
send_to: T::AccountId,
@@ -138,12 +138,12 @@ impl<T: Config> Swap<T::AccountId> for Pallet<T> {
keep_alive,
)
})?;
Ok(amount_out.into())
Ok(amount_out)
}
fn swap_tokens_for_exact_tokens(
sender: T::AccountId,
path: Vec<Self::MultiAssetId>,
path: Vec<Self::AssetKind>,
amount_out: Self::Balance,
amount_in_max: Option<Self::Balance>,
send_to: T::AccountId,
@@ -159,24 +159,25 @@ impl<T: Config> Swap<T::AccountId> for Pallet<T> {
keep_alive,
)
})?;
Ok(amount_in.into())
Ok(amount_in)
}
}
impl<T: Config> SwapCredit<T::AccountId> for Pallet<T> {
type Balance = T::Balance;
type MultiAssetId = T::MultiAssetId;
type Credit = Credit<T>;
type AssetKind = T::AssetKind;
type Credit = CreditOf<T>;
fn max_path_len() -> u32 {
T::MaxSwapPathLength::get()
}
fn swap_exact_tokens_for_tokens(
path: Vec<Self::MultiAssetId>,
path: Vec<Self::AssetKind>,
credit_in: Self::Credit,
amount_out_min: Option<Self::Balance>,
) -> Result<Self::Credit, (Self::Credit, DispatchError)> {
let credit_asset = credit_in.asset();
with_transaction(|| -> TransactionOutcome<Result<_, DispatchError>> {
let res = Self::do_swap_exact_credit_tokens_for_tokens(path, credit_in, amount_out_min);
match &res {
@@ -187,14 +188,15 @@ impl<T: Config> SwapCredit<T::AccountId> for Pallet<T> {
}
})
// should never map an error since `with_transaction` above never returns it.
.map_err(|_| (Self::Credit::native_zero(), DispatchError::Corruption))?
.map_err(|_| (Self::Credit::zero(credit_asset), DispatchError::Corruption))?
}
fn swap_tokens_for_exact_tokens(
path: Vec<Self::MultiAssetId>,
path: Vec<Self::AssetKind>,
credit_in: Self::Credit,
amount_out: Self::Balance,
) -> Result<(Self::Credit, Self::Credit), (Self::Credit, DispatchError)> {
let credit_asset = credit_in.asset();
with_transaction(|| -> TransactionOutcome<Result<_, DispatchError>> {
let res = Self::do_swap_credit_tokens_for_exact_tokens(path, credit_in, amount_out);
match &res {
@@ -205,6 +207,6 @@ impl<T: Config> SwapCredit<T::AccountId> for Pallet<T> {
}
})
// should never map an error since `with_transaction` above never returns it.
.map_err(|_| (Self::Credit::native_zero(), DispatchError::Corruption))?
.map_err(|_| (Self::Credit::zero(credit_asset), DispatchError::Corruption))?
}
}