mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-30 17:47:56 +00:00
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:
@@ -69,7 +69,6 @@ mod tests;
|
||||
|
||||
mod payment;
|
||||
use frame_support::traits::tokens::AssetId;
|
||||
use pallet_asset_conversion::MultiAssetIdConverter;
|
||||
pub use payment::*;
|
||||
|
||||
/// Type aliases used for interaction with `OnChargeTransaction`.
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
use super::*;
|
||||
use crate as pallet_asset_conversion_tx_payment;
|
||||
|
||||
use codec;
|
||||
use frame_support::{
|
||||
derive_impl,
|
||||
dispatch::DispatchClass,
|
||||
@@ -24,13 +23,19 @@ use frame_support::{
|
||||
ord_parameter_types,
|
||||
pallet_prelude::*,
|
||||
parameter_types,
|
||||
traits::{AsEnsureOriginWithArg, ConstU32, ConstU64, ConstU8, Imbalance, OnUnbalanced},
|
||||
traits::{
|
||||
tokens::{
|
||||
fungible::{NativeFromLeft, NativeOrWithId, UnionOf},
|
||||
imbalance::ResolveAssetTo,
|
||||
},
|
||||
AsEnsureOriginWithArg, ConstU32, ConstU64, ConstU8, Imbalance, OnUnbalanced,
|
||||
},
|
||||
weights::{Weight, WeightToFee as WeightToFeeT},
|
||||
PalletId,
|
||||
};
|
||||
use frame_system as system;
|
||||
use frame_system::{EnsureRoot, EnsureSignedBy};
|
||||
use pallet_asset_conversion::{NativeOrAssetId, NativeOrAssetIdConverter};
|
||||
use pallet_asset_conversion::{Ascending, Chain, WithFirstAsset};
|
||||
use pallet_transaction_payment::CurrencyAdapter;
|
||||
use sp_core::H256;
|
||||
use sp_runtime::{
|
||||
@@ -225,10 +230,9 @@ impl pallet_assets::Config<Instance2> for Runtime {
|
||||
|
||||
parameter_types! {
|
||||
pub const AssetConversionPalletId: PalletId = PalletId(*b"py/ascon");
|
||||
pub storage AllowMultiAssetPools: bool = false;
|
||||
// should be non-zero if AllowMultiAssetPools is true, otherwise can be zero
|
||||
pub storage LiquidityWithdrawalFee: Permill = Permill::from_percent(0);
|
||||
pub const MaxSwapPathLength: u32 = 4;
|
||||
pub const Native: NativeOrWithId<u32> = NativeOrWithId::Native;
|
||||
}
|
||||
|
||||
ord_parameter_types! {
|
||||
@@ -237,27 +241,26 @@ ord_parameter_types! {
|
||||
|
||||
impl pallet_asset_conversion::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type Currency = Balances;
|
||||
type AssetId = u32;
|
||||
type Balance = Balance;
|
||||
type HigherPrecisionBalance = u128;
|
||||
type AssetKind = NativeOrWithId<u32>;
|
||||
type Assets = UnionOf<Balances, Assets, NativeFromLeft, NativeOrWithId<u32>, AccountId>;
|
||||
type PoolId = (Self::AssetKind, Self::AssetKind);
|
||||
type PoolLocator = Chain<
|
||||
WithFirstAsset<Native, AccountId, NativeOrWithId<u32>>,
|
||||
Ascending<AccountId, NativeOrWithId<u32>>,
|
||||
>;
|
||||
type PoolAssetId = u32;
|
||||
type Assets = Assets;
|
||||
type PoolAssets = PoolAssets;
|
||||
type PalletId = AssetConversionPalletId;
|
||||
type WeightInfo = ();
|
||||
type LPFee = ConstU32<3>; // means 0.3%
|
||||
type PoolSetupFee = ConstU64<100>; // should be more or equal to the existential deposit
|
||||
type PoolSetupFeeReceiver = AssetConversionOrigin;
|
||||
type PoolSetupFeeAsset = Native;
|
||||
type PoolSetupFeeTarget = ResolveAssetTo<AssetConversionOrigin, Self::Assets>;
|
||||
type PalletId = AssetConversionPalletId;
|
||||
type LPFee = ConstU32<3>; // means 0.3%
|
||||
type LiquidityWithdrawalFee = LiquidityWithdrawalFee;
|
||||
type AllowMultiAssetPools = AllowMultiAssetPools;
|
||||
type MaxSwapPathLength = MaxSwapPathLength;
|
||||
type MintMinLiquidity = ConstU64<100>; // 100 is good enough when the main currency has 12 decimals.
|
||||
|
||||
type Balance = u64;
|
||||
type HigherPrecisionBalance = u128;
|
||||
|
||||
type MultiAssetId = NativeOrAssetId<u32>;
|
||||
type MultiAssetIdConverter = NativeOrAssetIdConverter<u32>;
|
||||
|
||||
type WeightInfo = ();
|
||||
pallet_asset_conversion::runtime_benchmarks_enabled! {
|
||||
type BenchmarkHelper = ();
|
||||
}
|
||||
@@ -266,5 +269,5 @@ impl pallet_asset_conversion::Config for Runtime {
|
||||
impl Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type Fungibles = Assets;
|
||||
type OnChargeAssetTransaction = AssetConversionAdapter<Balances, AssetConversion>;
|
||||
type OnChargeAssetTransaction = AssetConversionAdapter<Balances, AssetConversion, Native>;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ use frame_support::{
|
||||
};
|
||||
use pallet_asset_conversion::Swap;
|
||||
use sp_runtime::{
|
||||
traits::{DispatchInfoOf, PostDispatchInfoOf, Zero},
|
||||
traits::{DispatchInfoOf, Get, PostDispatchInfoOf, Zero},
|
||||
transaction_validity::InvalidTransaction,
|
||||
Saturating,
|
||||
};
|
||||
@@ -76,16 +76,17 @@ pub trait OnChargeAssetTransaction<T: Config> {
|
||||
/// Implements the asset transaction for a balance to asset converter (implementing [`Swap`]).
|
||||
///
|
||||
/// The converter is given the complete fee in terms of the asset used for the transaction.
|
||||
pub struct AssetConversionAdapter<C, CON>(PhantomData<(C, CON)>);
|
||||
pub struct AssetConversionAdapter<C, CON, N>(PhantomData<(C, CON, N)>);
|
||||
|
||||
/// Default implementation for a runtime instantiating this pallet, an asset to native swapper.
|
||||
impl<T, C, CON> OnChargeAssetTransaction<T> for AssetConversionAdapter<C, CON>
|
||||
impl<T, C, CON, N> OnChargeAssetTransaction<T> for AssetConversionAdapter<C, CON, N>
|
||||
where
|
||||
N: Get<CON::AssetKind>,
|
||||
T: Config,
|
||||
C: Inspect<<T as frame_system::Config>::AccountId>,
|
||||
CON: Swap<T::AccountId, Balance = BalanceOf<T>, MultiAssetId = T::MultiAssetId>,
|
||||
CON: Swap<T::AccountId, Balance = BalanceOf<T>, AssetKind = T::AssetKind>,
|
||||
BalanceOf<T>: Into<AssetBalanceOf<T>>,
|
||||
T::MultiAssetId: From<AssetIdOf<T>>,
|
||||
T::AssetKind: From<AssetIdOf<T>>,
|
||||
BalanceOf<T>: IsType<<C as Inspect<<T as frame_system::Config>::AccountId>>::Balance>,
|
||||
{
|
||||
type Balance = BalanceOf<T>;
|
||||
@@ -116,7 +117,7 @@ where
|
||||
|
||||
let asset_consumed = CON::swap_tokens_for_exact_tokens(
|
||||
who.clone(),
|
||||
vec![asset_id.into(), T::MultiAssetIdConverter::get_native()],
|
||||
vec![asset_id.into(), N::get()],
|
||||
native_asset_required,
|
||||
None,
|
||||
who.clone(),
|
||||
@@ -168,8 +169,8 @@ where
|
||||
match CON::swap_exact_tokens_for_tokens(
|
||||
who.clone(), // we already deposited the native to `who`
|
||||
vec![
|
||||
T::MultiAssetIdConverter::get_native(), // we provide the native
|
||||
asset_id.into(), // we want asset_id back
|
||||
N::get(), // we provide the native
|
||||
asset_id.into(), // we want asset_id back
|
||||
],
|
||||
swap_back, // amount of the native asset to convert to `asset_id`
|
||||
None, // no minimum amount back
|
||||
|
||||
@@ -20,14 +20,13 @@ use frame_support::{
|
||||
dispatch::{DispatchInfo, PostDispatchInfo},
|
||||
pallet_prelude::*,
|
||||
traits::{
|
||||
fungible::Inspect,
|
||||
fungible::{Inspect, NativeOrWithId},
|
||||
fungibles::{Inspect as FungiblesInspect, Mutate},
|
||||
},
|
||||
weights::Weight,
|
||||
};
|
||||
use frame_system as system;
|
||||
use mock::{ExtrinsicBaseWeight, *};
|
||||
use pallet_asset_conversion::NativeOrAssetId;
|
||||
use pallet_balances::Call as BalancesCall;
|
||||
use sp_runtime::{traits::StaticLookup, BuildStorage};
|
||||
|
||||
@@ -127,12 +126,12 @@ fn setup_lp(asset_id: u32, balance_factor: u64) {
|
||||
10_000 * balance_factor + ed_asset
|
||||
));
|
||||
|
||||
let token_1 = NativeOrAssetId::Native;
|
||||
let token_2 = NativeOrAssetId::Asset(asset_id);
|
||||
let token_1 = NativeOrWithId::Native;
|
||||
let token_2 = NativeOrWithId::WithId(asset_id);
|
||||
assert_ok!(AssetConversion::create_pool(
|
||||
RuntimeOrigin::signed(lp_provider),
|
||||
Box::new(token_1),
|
||||
Box::new(token_2)
|
||||
Box::new(token_1.clone()),
|
||||
Box::new(token_2.clone())
|
||||
));
|
||||
|
||||
assert_ok!(AssetConversion::add_liquidity(
|
||||
@@ -228,8 +227,8 @@ fn transaction_payment_in_asset_possible() {
|
||||
|
||||
let fee_in_native = base_weight + tx_weight + len as u64;
|
||||
let input_quote = AssetConversion::quote_price_tokens_for_exact_tokens(
|
||||
NativeOrAssetId::Asset(asset_id),
|
||||
NativeOrAssetId::Native,
|
||||
NativeOrWithId::WithId(asset_id),
|
||||
NativeOrWithId::Native,
|
||||
fee_in_native,
|
||||
true,
|
||||
);
|
||||
@@ -337,8 +336,8 @@ fn transaction_payment_without_fee() {
|
||||
let len = 10;
|
||||
let fee_in_native = base_weight + weight + len as u64;
|
||||
let input_quote = AssetConversion::quote_price_tokens_for_exact_tokens(
|
||||
NativeOrAssetId::Asset(asset_id),
|
||||
NativeOrAssetId::Native,
|
||||
NativeOrWithId::WithId(asset_id),
|
||||
NativeOrWithId::Native,
|
||||
fee_in_native,
|
||||
true,
|
||||
);
|
||||
@@ -355,8 +354,8 @@ fn transaction_payment_without_fee() {
|
||||
assert_eq!(Assets::balance(asset_id, caller), balance - fee_in_asset);
|
||||
|
||||
let refund = AssetConversion::quote_price_exact_tokens_for_tokens(
|
||||
NativeOrAssetId::Native,
|
||||
NativeOrAssetId::Asset(asset_id),
|
||||
NativeOrWithId::Native,
|
||||
NativeOrWithId::WithId(asset_id),
|
||||
fee_in_native,
|
||||
true,
|
||||
)
|
||||
@@ -412,8 +411,8 @@ fn asset_transaction_payment_with_tip_and_refund() {
|
||||
let len = 10;
|
||||
let fee_in_native = base_weight + weight + len as u64 + tip;
|
||||
let input_quote = AssetConversion::quote_price_tokens_for_exact_tokens(
|
||||
NativeOrAssetId::Asset(asset_id),
|
||||
NativeOrAssetId::Native,
|
||||
NativeOrWithId::WithId(asset_id),
|
||||
NativeOrWithId::Native,
|
||||
fee_in_native,
|
||||
true,
|
||||
);
|
||||
@@ -428,8 +427,8 @@ fn asset_transaction_payment_with_tip_and_refund() {
|
||||
let final_weight = 50;
|
||||
let expected_fee = fee_in_native - final_weight - tip;
|
||||
let expected_token_refund = AssetConversion::quote_price_exact_tokens_for_tokens(
|
||||
NativeOrAssetId::Native,
|
||||
NativeOrAssetId::Asset(asset_id),
|
||||
NativeOrWithId::Native,
|
||||
NativeOrWithId::WithId(asset_id),
|
||||
fee_in_native - expected_fee - tip,
|
||||
true,
|
||||
)
|
||||
@@ -493,8 +492,8 @@ fn payment_from_account_with_only_assets() {
|
||||
let fee_in_native = base_weight + weight + len as u64;
|
||||
let ed = Balances::minimum_balance();
|
||||
let fee_in_asset = AssetConversion::quote_price_tokens_for_exact_tokens(
|
||||
NativeOrAssetId::Asset(asset_id),
|
||||
NativeOrAssetId::Native,
|
||||
NativeOrWithId::WithId(asset_id),
|
||||
NativeOrWithId::Native,
|
||||
fee_in_native + ed,
|
||||
true,
|
||||
)
|
||||
@@ -509,8 +508,8 @@ fn payment_from_account_with_only_assets() {
|
||||
assert_eq!(Assets::balance(asset_id, caller), balance - fee_in_asset);
|
||||
|
||||
let refund = AssetConversion::quote_price_exact_tokens_for_tokens(
|
||||
NativeOrAssetId::Native,
|
||||
NativeOrAssetId::Asset(asset_id),
|
||||
NativeOrWithId::Native,
|
||||
NativeOrWithId::WithId(asset_id),
|
||||
ed,
|
||||
true,
|
||||
)
|
||||
@@ -585,8 +584,8 @@ fn converted_fee_is_never_zero_if_input_fee_is_not() {
|
||||
// validate even a small fee gets converted to asset.
|
||||
let fee_in_native = base_weight + weight + len as u64;
|
||||
let fee_in_asset = AssetConversion::quote_price_tokens_for_exact_tokens(
|
||||
NativeOrAssetId::Asset(asset_id),
|
||||
NativeOrAssetId::Native,
|
||||
NativeOrWithId::WithId(asset_id),
|
||||
NativeOrWithId::Native,
|
||||
fee_in_native,
|
||||
true,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user