mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-07-15 04:25:43 +00:00
pallet-asset-conversion: Swap Credit (#1677)
Introduces a swap implementation that allows the exchange of a credit (aka Negative Imbalance) of one asset for a credit of another asset. This is particularly useful when a credit swap is required but may not have sufficient value to meet the ED constraint, hence cannot be deposited to temp account before. An example use case is when XCM fees are paid using an asset held in the XCM executor registry and has to be swapped for native currency. Additional Updates: - encapsulates the existing `Swap` trait impl within a transactional context, since partial storage mutation is possible when an error occurs; - supplied `Currency` and `Assets` impls must be implemented over the same `Balance` type, the `AssetBalance` generic type is dropped. This helps to avoid numerous type conversion and overflow cases. If those types are different it should be handled outside of the pallet; - `Box` asset kind on a pallet level, unbox on a runtime level - here [why](https://substrate.stackexchange.com/questions/10039/boxed-argument-of-a-dispatchable/10103#10103); - `path` uses `Vec` now, instead of `BoundedVec` since it is never used in PoV; - removes the `Transfer` event due to it's redundancy with the events emitted by `fungible/s` implementations; - modifies the `SwapExecuted` event type; related issue: - https://github.com/paritytech/polkadot-sdk/issues/105 related PRs: - (required for) https://github.com/paritytech/polkadot-sdk/pull/1845 - (caused) https://github.com/paritytech/polkadot-sdk/pull/1717 // DONE make the pallet work only with `fungibles` trait and make it free from the concept of a `native` asset - https://github.com/paritytech/polkadot-sdk/issues/1842 --------- Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>
This commit is contained in:
@@ -21,7 +21,6 @@ use super::*;
|
||||
use frame_benchmarking::{benchmarks, whitelisted_caller};
|
||||
use frame_support::{
|
||||
assert_ok,
|
||||
storage::bounded_vec::BoundedVec,
|
||||
traits::{
|
||||
fungible::{Inspect as InspectFungible, Mutate as MutateFungible, Unbalanced},
|
||||
fungibles::{Create, Inspect, Mutate},
|
||||
@@ -49,7 +48,7 @@ where
|
||||
|
||||
fn create_asset<T: Config>(asset: &T::MultiAssetId) -> (T::AccountId, AccountIdLookupOf<T>)
|
||||
where
|
||||
T::AssetBalance: From<u128>,
|
||||
T::Balance: From<u128>,
|
||||
T::Currency: Unbalanced<T::AccountId>,
|
||||
T::Assets: Create<T::AccountId> + Mutate<T::AccountId>,
|
||||
{
|
||||
@@ -70,7 +69,7 @@ fn create_asset_and_pool<T: Config>(
|
||||
asset2: &T::MultiAssetId,
|
||||
) -> (T::PoolAssetId, T::AccountId, AccountIdLookupOf<T>)
|
||||
where
|
||||
T::AssetBalance: From<u128>,
|
||||
T::Balance: From<u128>,
|
||||
T::Currency: Unbalanced<T::AccountId>,
|
||||
T::Assets: Create<T::AccountId> + Mutate<T::AccountId>,
|
||||
T::PoolAssetId: Into<u32>,
|
||||
@@ -80,8 +79,8 @@ where
|
||||
|
||||
assert_ok!(AssetConversion::<T>::create_pool(
|
||||
SystemOrigin::Signed(caller.clone()).into(),
|
||||
asset1.clone(),
|
||||
asset2.clone()
|
||||
Box::new(asset1.clone()),
|
||||
Box::new(asset2.clone())
|
||||
));
|
||||
let lp_token = get_lp_token_id::<T>();
|
||||
|
||||
@@ -99,7 +98,6 @@ fn assert_last_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) {
|
||||
benchmarks! {
|
||||
where_clause {
|
||||
where
|
||||
T::AssetBalance: From<u128> + Into<u128>,
|
||||
T::Currency: Unbalanced<T::AccountId>,
|
||||
T::Balance: From<u128> + Into<u128>,
|
||||
T::Assets: Create<T::AccountId> + Mutate<T::AccountId>,
|
||||
@@ -110,7 +108,7 @@ benchmarks! {
|
||||
let asset1 = T::MultiAssetIdConverter::get_native();
|
||||
let asset2 = T::BenchmarkHelper::multiasset_id(0);
|
||||
let (caller, _) = create_asset::<T>(&asset2);
|
||||
}: _(SystemOrigin::Signed(caller.clone()), asset1.clone(), asset2.clone())
|
||||
}: _(SystemOrigin::Signed(caller.clone()), Box::new(asset1.clone()), Box::new(asset2.clone()))
|
||||
verify {
|
||||
let lp_token = get_lp_token_id::<T>();
|
||||
let pool_id = (asset1.clone(), asset2.clone());
|
||||
@@ -128,7 +126,7 @@ benchmarks! {
|
||||
let (lp_token, caller, _) = create_asset_and_pool::<T>(&asset1, &asset2);
|
||||
let ed: u128 = T::Currency::minimum_balance().into();
|
||||
let add_amount = 1000 + ed;
|
||||
}: _(SystemOrigin::Signed(caller.clone()), asset1.clone(), asset2.clone(), add_amount.into(), 1000.into(), 0.into(), 0.into(), caller.clone())
|
||||
}: _(SystemOrigin::Signed(caller.clone()), Box::new(asset1.clone()), Box::new(asset2.clone()), add_amount.into(), 1000.into(), 0.into(), 0.into(), caller.clone())
|
||||
verify {
|
||||
let pool_id = (asset1.clone(), asset2.clone());
|
||||
let lp_minted = AssetConversion::<T>::calc_lp_amount_for_zero_supply(&add_amount.into(), &1000.into()).unwrap().into();
|
||||
@@ -157,8 +155,8 @@ benchmarks! {
|
||||
|
||||
AssetConversion::<T>::add_liquidity(
|
||||
SystemOrigin::Signed(caller.clone()).into(),
|
||||
asset1.clone(),
|
||||
asset2.clone(),
|
||||
Box::new(asset1.clone()),
|
||||
Box::new(asset2.clone()),
|
||||
add_amount.into(),
|
||||
1000.into(),
|
||||
0.into(),
|
||||
@@ -166,7 +164,7 @@ benchmarks! {
|
||||
caller.clone(),
|
||||
)?;
|
||||
let total_supply = <T::PoolAssets as Inspect<T::AccountId>>::total_issuance(lp_token.clone());
|
||||
}: _(SystemOrigin::Signed(caller.clone()), asset1, asset2, remove_lp_amount.into(), 0.into(), 0.into(), caller.clone())
|
||||
}: _(SystemOrigin::Signed(caller.clone()), Box::new(asset1), Box::new(asset2), remove_lp_amount.into(), 0.into(), 0.into(), caller.clone())
|
||||
verify {
|
||||
let new_total_supply = <T::PoolAssets as Inspect<T::AccountId>>::total_issuance(lp_token.clone());
|
||||
assert_eq!(
|
||||
@@ -185,8 +183,8 @@ benchmarks! {
|
||||
|
||||
AssetConversion::<T>::add_liquidity(
|
||||
SystemOrigin::Signed(caller.clone()).into(),
|
||||
native.clone(),
|
||||
asset1.clone(),
|
||||
Box::new(native.clone()),
|
||||
Box::new(asset1.clone()),
|
||||
(100 * ed).into(),
|
||||
200.into(),
|
||||
0.into(),
|
||||
@@ -199,29 +197,45 @@ benchmarks! {
|
||||
// if we only allow the native-asset pools, then the worst case scenario would be to swap
|
||||
// asset1-native-asset2
|
||||
if !T::AllowMultiAssetPools::get() {
|
||||
AssetConversion::<T>::create_pool(SystemOrigin::Signed(caller.clone()).into(), native.clone(), asset2.clone())?;
|
||||
AssetConversion::<T>::create_pool(
|
||||
SystemOrigin::Signed(caller.clone()).into(),
|
||||
Box::new(native.clone()),
|
||||
Box::new(asset2.clone())
|
||||
)?;
|
||||
AssetConversion::<T>::add_liquidity(
|
||||
SystemOrigin::Signed(caller.clone()).into(),
|
||||
native.clone(),
|
||||
asset2.clone(),
|
||||
Box::new(native.clone()),
|
||||
Box::new(asset2.clone()),
|
||||
(500 * ed).into(),
|
||||
1000.into(),
|
||||
0.into(),
|
||||
0.into(),
|
||||
caller.clone(),
|
||||
)?;
|
||||
path = vec![asset1.clone(), native.clone(), asset2.clone()];
|
||||
path = vec![
|
||||
Box::new(asset1.clone()),
|
||||
Box::new(native.clone()),
|
||||
Box::new(asset2.clone())
|
||||
];
|
||||
swap_amount = 100.into();
|
||||
} else {
|
||||
let asset3 = T::BenchmarkHelper::multiasset_id(3);
|
||||
AssetConversion::<T>::create_pool(SystemOrigin::Signed(caller.clone()).into(), asset1.clone(), asset2.clone())?;
|
||||
AssetConversion::<T>::create_pool(
|
||||
SystemOrigin::Signed(caller.clone()).into(),
|
||||
Box::new(asset1.clone()),
|
||||
Box::new(asset2.clone())
|
||||
)?;
|
||||
let (_, _) = create_asset::<T>(&asset3);
|
||||
AssetConversion::<T>::create_pool(SystemOrigin::Signed(caller.clone()).into(), asset2.clone(), asset3.clone())?;
|
||||
AssetConversion::<T>::create_pool(
|
||||
SystemOrigin::Signed(caller.clone()).into(),
|
||||
Box::new(asset2.clone()),
|
||||
Box::new(asset3.clone())
|
||||
)?;
|
||||
|
||||
AssetConversion::<T>::add_liquidity(
|
||||
SystemOrigin::Signed(caller.clone()).into(),
|
||||
asset1.clone(),
|
||||
asset2.clone(),
|
||||
Box::new(asset1.clone()),
|
||||
Box::new(asset2.clone()),
|
||||
200.into(),
|
||||
2000.into(),
|
||||
0.into(),
|
||||
@@ -230,19 +244,22 @@ benchmarks! {
|
||||
)?;
|
||||
AssetConversion::<T>::add_liquidity(
|
||||
SystemOrigin::Signed(caller.clone()).into(),
|
||||
asset2.clone(),
|
||||
asset3.clone(),
|
||||
Box::new(asset2.clone()),
|
||||
Box::new(asset3.clone()),
|
||||
2000.into(),
|
||||
2000.into(),
|
||||
0.into(),
|
||||
0.into(),
|
||||
caller.clone(),
|
||||
)?;
|
||||
path = vec![native.clone(), asset1.clone(), asset2.clone(), asset3.clone()];
|
||||
path = vec![
|
||||
Box::new(native.clone()),
|
||||
Box::new(asset1.clone()),
|
||||
Box::new(asset2.clone()),
|
||||
Box::new(asset3.clone())
|
||||
];
|
||||
swap_amount = ed.into();
|
||||
}
|
||||
|
||||
let path: BoundedVec<_, T::MaxSwapPathLength> = BoundedVec::try_from(path).unwrap();
|
||||
let native_balance = T::Currency::balance(&caller);
|
||||
let asset1_balance = T::Assets::balance(T::BenchmarkHelper::asset_id(1), &caller);
|
||||
}: _(SystemOrigin::Signed(caller.clone()), path, swap_amount, 1.into(), caller.clone(), false)
|
||||
@@ -266,8 +283,8 @@ benchmarks! {
|
||||
|
||||
AssetConversion::<T>::add_liquidity(
|
||||
SystemOrigin::Signed(caller.clone()).into(),
|
||||
native.clone(),
|
||||
asset1.clone(),
|
||||
Box::new(native.clone()),
|
||||
Box::new(asset1.clone()),
|
||||
(1000 * ed).into(),
|
||||
500.into(),
|
||||
0.into(),
|
||||
@@ -279,28 +296,44 @@ benchmarks! {
|
||||
// if we only allow the native-asset pools, then the worst case scenario would be to swap
|
||||
// asset1-native-asset2
|
||||
if !T::AllowMultiAssetPools::get() {
|
||||
AssetConversion::<T>::create_pool(SystemOrigin::Signed(caller.clone()).into(), native.clone(), asset2.clone())?;
|
||||
AssetConversion::<T>::create_pool(
|
||||
SystemOrigin::Signed(caller.clone()).into(),
|
||||
Box::new(native.clone()),
|
||||
Box::new(asset2.clone())
|
||||
)?;
|
||||
AssetConversion::<T>::add_liquidity(
|
||||
SystemOrigin::Signed(caller.clone()).into(),
|
||||
native.clone(),
|
||||
asset2.clone(),
|
||||
Box::new(native.clone()),
|
||||
Box::new(asset2.clone()),
|
||||
(500 * ed).into(),
|
||||
1000.into(),
|
||||
0.into(),
|
||||
0.into(),
|
||||
caller.clone(),
|
||||
)?;
|
||||
path = vec![asset1.clone(), native.clone(), asset2.clone()];
|
||||
path = vec![
|
||||
Box::new(asset1.clone()),
|
||||
Box::new(native.clone()),
|
||||
Box::new(asset2.clone())
|
||||
];
|
||||
} else {
|
||||
AssetConversion::<T>::create_pool(SystemOrigin::Signed(caller.clone()).into(), asset1.clone(), asset2.clone())?;
|
||||
AssetConversion::<T>::create_pool(
|
||||
SystemOrigin::Signed(caller.clone()).into(),
|
||||
Box::new(asset1.clone()),
|
||||
Box::new(asset2.clone())
|
||||
)?;
|
||||
let asset3 = T::BenchmarkHelper::multiasset_id(3);
|
||||
let (_, _) = create_asset::<T>(&asset3);
|
||||
AssetConversion::<T>::create_pool(SystemOrigin::Signed(caller.clone()).into(), asset2.clone(), asset3.clone())?;
|
||||
AssetConversion::<T>::create_pool(
|
||||
SystemOrigin::Signed(caller.clone()).into(),
|
||||
Box::new(asset2.clone()),
|
||||
Box::new(asset3.clone())
|
||||
)?;
|
||||
|
||||
AssetConversion::<T>::add_liquidity(
|
||||
SystemOrigin::Signed(caller.clone()).into(),
|
||||
asset1.clone(),
|
||||
asset2.clone(),
|
||||
Box::new(asset1.clone()),
|
||||
Box::new(asset2.clone()),
|
||||
2000.into(),
|
||||
2000.into(),
|
||||
0.into(),
|
||||
@@ -309,18 +342,22 @@ benchmarks! {
|
||||
)?;
|
||||
AssetConversion::<T>::add_liquidity(
|
||||
SystemOrigin::Signed(caller.clone()).into(),
|
||||
asset2.clone(),
|
||||
asset3.clone(),
|
||||
Box::new(asset2.clone()),
|
||||
Box::new(asset3.clone()),
|
||||
2000.into(),
|
||||
2000.into(),
|
||||
0.into(),
|
||||
0.into(),
|
||||
caller.clone(),
|
||||
)?;
|
||||
path = vec![native.clone(), asset1.clone(), asset2.clone(), asset3.clone()];
|
||||
path = vec![
|
||||
Box::new(native.clone()),
|
||||
Box::new(asset1.clone()),
|
||||
Box::new(asset2.clone()),
|
||||
Box::new(asset3.clone())
|
||||
];
|
||||
}
|
||||
|
||||
let path: BoundedVec<_, T::MaxSwapPathLength> = BoundedVec::try_from(path).unwrap();
|
||||
let asset2_balance = T::Assets::balance(T::BenchmarkHelper::asset_id(2), &caller);
|
||||
let asset3_balance = T::Assets::balance(T::BenchmarkHelper::asset_id(3), &caller);
|
||||
}: _(SystemOrigin::Signed(caller.clone()), path.clone(), 100.into(), (1000 * ed).into(), caller.clone(), false)
|
||||
|
||||
Reference in New Issue
Block a user