mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-17 17:11:02 +00:00
Asset conversion get_pool_id fix (Ord does not count with is_native flag) (#14572)
* Asset conversion `get_pool_id` fix (`Ord` does not count with `is_native` flag) * Removed unnecessery clones + added `pool_account` to `PoolCreated` event * Fix bench compile * Fix bench * Improved `MultiAssetIdConverter::try_convert` * Removed `into_multiasset_id` from converter and moved to `BenchmarkHelper` * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_asset_conversion * Fixed doc * Typo * Removed `NativeOrAssetId` (test/mock) impl from types.rs to mock.rs... * Typo + 0u32 -> 0 * Update frame/asset-conversion/src/benchmarking.rs Co-authored-by: Jegor Sidorenko <5252494+jsidorenko@users.noreply.github.com> * Typo * ".git/.scripts/commands/fmt/fmt.sh" * Fix from Jegor * Try to fix the other failing benchmark * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_asset_conversion * Update frame/asset-conversion/src/lib.rs Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> * Update frame/asset-conversion/src/types.rs Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> * Update frame/transaction-payment/asset-conversion-tx-payment/src/mock.rs Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> * Update frame/asset-conversion/src/mock.rs Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> * Update bin/node/runtime/src/impls.rs Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> * Update frame/asset-conversion/src/lib.rs Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> * Update bin/node/runtime/src/impls.rs Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> * Reverted NativeOrAssetId --------- Co-authored-by: command-bot <> Co-authored-by: Jegor Sidorenko <5252494+jsidorenko@users.noreply.github.com> Co-authored-by: Jegor Sidorenko <jegor@parity.io> Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>
This commit is contained in:
@@ -55,7 +55,9 @@ where
|
|||||||
{
|
{
|
||||||
let caller: T::AccountId = whitelisted_caller();
|
let caller: T::AccountId = whitelisted_caller();
|
||||||
let caller_lookup = T::Lookup::unlookup(caller.clone());
|
let caller_lookup = T::Lookup::unlookup(caller.clone());
|
||||||
if let Ok(asset_id) = T::MultiAssetIdConverter::try_convert(asset) {
|
if let MultiAssetIdConversionResult::Converted(asset_id) =
|
||||||
|
T::MultiAssetIdConverter::try_convert(asset)
|
||||||
|
{
|
||||||
T::Currency::set_balance(&caller, BalanceOf::<T>::max_value().div(1000u32.into()));
|
T::Currency::set_balance(&caller, BalanceOf::<T>::max_value().div(1000u32.into()));
|
||||||
assert_ok!(T::Assets::create(asset_id.clone(), caller.clone(), true, 1.into()));
|
assert_ok!(T::Assets::create(asset_id.clone(), caller.clone(), true, 1.into()));
|
||||||
assert_ok!(T::Assets::mint_into(asset_id, &caller, INITIAL_ASSET_BALANCE.into()));
|
assert_ok!(T::Assets::mint_into(asset_id, &caller, INITIAL_ASSET_BALANCE.into()));
|
||||||
@@ -106,18 +108,23 @@ benchmarks! {
|
|||||||
|
|
||||||
create_pool {
|
create_pool {
|
||||||
let asset1 = T::MultiAssetIdConverter::get_native();
|
let asset1 = T::MultiAssetIdConverter::get_native();
|
||||||
let asset2 = T::MultiAssetIdConverter::into_multiasset_id(&T::BenchmarkHelper::asset_id(0_u32));
|
let asset2 = T::BenchmarkHelper::multiasset_id(0);
|
||||||
let (caller, _) = create_asset::<T>(&asset2);
|
let (caller, _) = create_asset::<T>(&asset2);
|
||||||
}: _(SystemOrigin::Signed(caller.clone()), asset1.clone(), asset2.clone())
|
}: _(SystemOrigin::Signed(caller.clone()), asset1.clone(), asset2.clone())
|
||||||
verify {
|
verify {
|
||||||
let lp_token = get_lp_token_id::<T>();
|
let lp_token = get_lp_token_id::<T>();
|
||||||
let pool_id = (asset1.clone(), asset2.clone());
|
let pool_id = (asset1.clone(), asset2.clone());
|
||||||
assert_last_event::<T>(Event::PoolCreated { creator: caller.clone(), pool_id, lp_token }.into());
|
assert_last_event::<T>(Event::PoolCreated {
|
||||||
|
creator: caller.clone(),
|
||||||
|
pool_account: AssetConversion::<T>::get_pool_account(&pool_id),
|
||||||
|
pool_id,
|
||||||
|
lp_token,
|
||||||
|
}.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
add_liquidity {
|
add_liquidity {
|
||||||
let asset1 = T::MultiAssetIdConverter::get_native();
|
let asset1 = T::MultiAssetIdConverter::get_native();
|
||||||
let asset2 = T::MultiAssetIdConverter::into_multiasset_id(&T::BenchmarkHelper::asset_id(0));
|
let asset2 = T::BenchmarkHelper::multiasset_id(0);
|
||||||
let (lp_token, caller, _) = create_asset_and_pool::<T>(&asset1, &asset2);
|
let (lp_token, caller, _) = create_asset_and_pool::<T>(&asset1, &asset2);
|
||||||
let ed: u128 = T::Currency::minimum_balance().into();
|
let ed: u128 = T::Currency::minimum_balance().into();
|
||||||
let add_amount = 1000 + ed;
|
let add_amount = 1000 + ed;
|
||||||
@@ -141,7 +148,7 @@ benchmarks! {
|
|||||||
|
|
||||||
remove_liquidity {
|
remove_liquidity {
|
||||||
let asset1 = T::MultiAssetIdConverter::get_native();
|
let asset1 = T::MultiAssetIdConverter::get_native();
|
||||||
let asset2 = T::MultiAssetIdConverter::into_multiasset_id(&T::BenchmarkHelper::asset_id(0));
|
let asset2 = T::BenchmarkHelper::multiasset_id(0);
|
||||||
let (lp_token, caller, _) = create_asset_and_pool::<T>(&asset1, &asset2);
|
let (lp_token, caller, _) = create_asset_and_pool::<T>(&asset1, &asset2);
|
||||||
let ed: u128 = T::Currency::minimum_balance().into();
|
let ed: u128 = T::Currency::minimum_balance().into();
|
||||||
let add_amount = 100 * ed;
|
let add_amount = 100 * ed;
|
||||||
@@ -170,8 +177,8 @@ benchmarks! {
|
|||||||
|
|
||||||
swap_exact_tokens_for_tokens {
|
swap_exact_tokens_for_tokens {
|
||||||
let native = T::MultiAssetIdConverter::get_native();
|
let native = T::MultiAssetIdConverter::get_native();
|
||||||
let asset1 = T::MultiAssetIdConverter::into_multiasset_id(&T::BenchmarkHelper::asset_id(1));
|
let asset1 = T::BenchmarkHelper::multiasset_id(1);
|
||||||
let asset2 = T::MultiAssetIdConverter::into_multiasset_id(&T::BenchmarkHelper::asset_id(2));
|
let asset2 = T::BenchmarkHelper::multiasset_id(2);
|
||||||
let (_, caller, _) = create_asset_and_pool::<T>(&native, &asset1);
|
let (_, caller, _) = create_asset_and_pool::<T>(&native, &asset1);
|
||||||
let (_, _) = create_asset::<T>(&asset2);
|
let (_, _) = create_asset::<T>(&asset2);
|
||||||
let ed: u128 = T::Currency::minimum_balance().into();
|
let ed: u128 = T::Currency::minimum_balance().into();
|
||||||
@@ -187,6 +194,87 @@ benchmarks! {
|
|||||||
caller.clone(),
|
caller.clone(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
let path;
|
||||||
|
let swap_amount;
|
||||||
|
// 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>::add_liquidity(
|
||||||
|
SystemOrigin::Signed(caller.clone()).into(),
|
||||||
|
native.clone(),
|
||||||
|
asset2.clone(),
|
||||||
|
(500 * ed).into(),
|
||||||
|
1000.into(),
|
||||||
|
0.into(),
|
||||||
|
0.into(),
|
||||||
|
caller.clone(),
|
||||||
|
)?;
|
||||||
|
path = vec![asset1.clone(), native.clone(), 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())?;
|
||||||
|
let (_, _) = create_asset::<T>(&asset3);
|
||||||
|
AssetConversion::<T>::create_pool(SystemOrigin::Signed(caller.clone()).into(), asset2.clone(), asset3.clone())?;
|
||||||
|
|
||||||
|
AssetConversion::<T>::add_liquidity(
|
||||||
|
SystemOrigin::Signed(caller.clone()).into(),
|
||||||
|
asset1.clone(),
|
||||||
|
asset2.clone(),
|
||||||
|
200.into(),
|
||||||
|
2000.into(),
|
||||||
|
0.into(),
|
||||||
|
0.into(),
|
||||||
|
caller.clone(),
|
||||||
|
)?;
|
||||||
|
AssetConversion::<T>::add_liquidity(
|
||||||
|
SystemOrigin::Signed(caller.clone()).into(),
|
||||||
|
asset2.clone(),
|
||||||
|
asset3.clone(),
|
||||||
|
2000.into(),
|
||||||
|
2000.into(),
|
||||||
|
0.into(),
|
||||||
|
0.into(),
|
||||||
|
caller.clone(),
|
||||||
|
)?;
|
||||||
|
path = vec![native.clone(), asset1.clone(), asset2.clone(), 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)
|
||||||
|
verify {
|
||||||
|
if !T::AllowMultiAssetPools::get() {
|
||||||
|
let new_asset1_balance = T::Assets::balance(T::BenchmarkHelper::asset_id(1), &caller);
|
||||||
|
assert_eq!(new_asset1_balance, asset1_balance - 100.into());
|
||||||
|
} else {
|
||||||
|
let new_native_balance = T::Currency::balance(&caller);
|
||||||
|
assert_eq!(new_native_balance, native_balance - ed.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
swap_tokens_for_exact_tokens {
|
||||||
|
let native = T::MultiAssetIdConverter::get_native();
|
||||||
|
let asset1 = T::BenchmarkHelper::multiasset_id(1);
|
||||||
|
let asset2 = T::BenchmarkHelper::multiasset_id(2);
|
||||||
|
let (_, caller, _) = create_asset_and_pool::<T>(&native, &asset1);
|
||||||
|
let (_, _) = create_asset::<T>(&asset2);
|
||||||
|
let ed: u128 = T::Currency::minimum_balance().into();
|
||||||
|
|
||||||
|
AssetConversion::<T>::add_liquidity(
|
||||||
|
SystemOrigin::Signed(caller.clone()).into(),
|
||||||
|
native.clone(),
|
||||||
|
asset1.clone(),
|
||||||
|
(1000 * ed).into(),
|
||||||
|
500.into(),
|
||||||
|
0.into(),
|
||||||
|
0.into(),
|
||||||
|
caller.clone(),
|
||||||
|
)?;
|
||||||
|
|
||||||
let path;
|
let path;
|
||||||
// if we only allow the native-asset pools, then the worst case scenario would be to swap
|
// if we only allow the native-asset pools, then the worst case scenario would be to swap
|
||||||
// asset1-native-asset2
|
// asset1-native-asset2
|
||||||
@@ -204,8 +292,8 @@ benchmarks! {
|
|||||||
)?;
|
)?;
|
||||||
path = vec![asset1.clone(), native.clone(), asset2.clone()];
|
path = vec![asset1.clone(), native.clone(), asset2.clone()];
|
||||||
} else {
|
} else {
|
||||||
let asset3 = T::MultiAssetIdConverter::into_multiasset_id(&T::BenchmarkHelper::asset_id(3));
|
|
||||||
AssetConversion::<T>::create_pool(SystemOrigin::Signed(caller.clone()).into(), asset1.clone(), asset2.clone())?;
|
AssetConversion::<T>::create_pool(SystemOrigin::Signed(caller.clone()).into(), asset1.clone(), asset2.clone())?;
|
||||||
|
let asset3 = T::BenchmarkHelper::multiasset_id(3);
|
||||||
let (_, _) = create_asset::<T>(&asset3);
|
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(), asset2.clone(), asset3.clone())?;
|
||||||
|
|
||||||
@@ -213,86 +301,7 @@ benchmarks! {
|
|||||||
SystemOrigin::Signed(caller.clone()).into(),
|
SystemOrigin::Signed(caller.clone()).into(),
|
||||||
asset1.clone(),
|
asset1.clone(),
|
||||||
asset2.clone(),
|
asset2.clone(),
|
||||||
200.into(),
|
|
||||||
2000.into(),
|
2000.into(),
|
||||||
0.into(),
|
|
||||||
0.into(),
|
|
||||||
caller.clone(),
|
|
||||||
)?;
|
|
||||||
AssetConversion::<T>::add_liquidity(
|
|
||||||
SystemOrigin::Signed(caller.clone()).into(),
|
|
||||||
asset2.clone(),
|
|
||||||
asset3.clone(),
|
|
||||||
2000.into(),
|
|
||||||
2000.into(),
|
|
||||||
0.into(),
|
|
||||||
0.into(),
|
|
||||||
caller.clone(),
|
|
||||||
)?;
|
|
||||||
path = vec![native.clone(), asset1.clone(), asset2.clone(), asset3.clone()];
|
|
||||||
}
|
|
||||||
|
|
||||||
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, ed.into(), 1.into(), caller.clone(), false)
|
|
||||||
verify {
|
|
||||||
if !T::AllowMultiAssetPools::get() {
|
|
||||||
let new_asset1_balance = T::Assets::balance(T::BenchmarkHelper::asset_id(1), &caller);
|
|
||||||
assert_eq!(new_asset1_balance, asset1_balance - 100.into());
|
|
||||||
} else {
|
|
||||||
let new_native_balance = T::Currency::balance(&caller);
|
|
||||||
assert_eq!(new_native_balance, native_balance - ed.into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
swap_tokens_for_exact_tokens {
|
|
||||||
let native = T::MultiAssetIdConverter::get_native();
|
|
||||||
let asset1 = T::MultiAssetIdConverter::into_multiasset_id(&T::BenchmarkHelper::asset_id(1));
|
|
||||||
let asset2 = T::MultiAssetIdConverter::into_multiasset_id(&T::BenchmarkHelper::asset_id(2));
|
|
||||||
let (_, caller, _) = create_asset_and_pool::<T>(&native, &asset1);
|
|
||||||
let (_, _) = create_asset::<T>(&asset2);
|
|
||||||
let ed: u128 = T::Currency::minimum_balance().into();
|
|
||||||
let add_native = 1000 + ed;
|
|
||||||
|
|
||||||
AssetConversion::<T>::add_liquidity(
|
|
||||||
SystemOrigin::Signed(caller.clone()).into(),
|
|
||||||
native.clone(),
|
|
||||||
asset1.clone(),
|
|
||||||
add_native.into(),
|
|
||||||
200.into(),
|
|
||||||
0.into(),
|
|
||||||
0.into(),
|
|
||||||
caller.clone(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let path;
|
|
||||||
// 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>::add_liquidity(
|
|
||||||
SystemOrigin::Signed(caller.clone()).into(),
|
|
||||||
native.clone(),
|
|
||||||
asset2.clone(),
|
|
||||||
(500 + ed).into(),
|
|
||||||
1000.into(),
|
|
||||||
0.into(),
|
|
||||||
0.into(),
|
|
||||||
caller.clone(),
|
|
||||||
)?;
|
|
||||||
path = vec![asset1.clone(), native.clone(), asset2.clone()];
|
|
||||||
} else {
|
|
||||||
AssetConversion::<T>::create_pool(SystemOrigin::Signed(caller.clone()).into(), asset1.clone(), asset2.clone())?;
|
|
||||||
let asset3 = T::MultiAssetIdConverter::into_multiasset_id(&T::BenchmarkHelper::asset_id(3));
|
|
||||||
let (_, _) = create_asset::<T>(&asset3);
|
|
||||||
AssetConversion::<T>::create_pool(SystemOrigin::Signed(caller.clone()).into(), asset2.clone(), asset3.clone())?;
|
|
||||||
|
|
||||||
AssetConversion::<T>::add_liquidity(
|
|
||||||
SystemOrigin::Signed(caller.clone()).into(),
|
|
||||||
asset1.clone(),
|
|
||||||
asset2.clone(),
|
|
||||||
200.into(),
|
|
||||||
2000.into(),
|
2000.into(),
|
||||||
0.into(),
|
0.into(),
|
||||||
0.into(),
|
0.into(),
|
||||||
@@ -314,7 +323,7 @@ benchmarks! {
|
|||||||
let path: BoundedVec<_, T::MaxSwapPathLength> = BoundedVec::try_from(path).unwrap();
|
let path: BoundedVec<_, T::MaxSwapPathLength> = BoundedVec::try_from(path).unwrap();
|
||||||
let asset2_balance = T::Assets::balance(T::BenchmarkHelper::asset_id(2), &caller);
|
let asset2_balance = T::Assets::balance(T::BenchmarkHelper::asset_id(2), &caller);
|
||||||
let asset3_balance = T::Assets::balance(T::BenchmarkHelper::asset_id(3), &caller);
|
let asset3_balance = T::Assets::balance(T::BenchmarkHelper::asset_id(3), &caller);
|
||||||
}: _(SystemOrigin::Signed(caller.clone()), path.clone(), 100.into(), add_native.into(), caller.clone(), false)
|
}: _(SystemOrigin::Signed(caller.clone()), path.clone(), 100.into(), (1000 * ed).into(), caller.clone(), false)
|
||||||
verify {
|
verify {
|
||||||
if !T::AllowMultiAssetPools::get() {
|
if !T::AllowMultiAssetPools::get() {
|
||||||
let new_asset2_balance = T::Assets::balance(T::BenchmarkHelper::asset_id(2), &caller);
|
let new_asset2_balance = T::Assets::balance(T::BenchmarkHelper::asset_id(2), &caller);
|
||||||
|
|||||||
@@ -143,9 +143,10 @@ pub mod pallet {
|
|||||||
/// Identifier for the class of non-native asset.
|
/// Identifier for the class of non-native asset.
|
||||||
/// Note: A `From<u32>` bound here would prevent `MultiLocation` from being used as an
|
/// Note: A `From<u32>` bound here would prevent `MultiLocation` from being used as an
|
||||||
/// `AssetId`.
|
/// `AssetId`.
|
||||||
type AssetId: AssetId + PartialOrd;
|
type AssetId: AssetId;
|
||||||
|
|
||||||
/// Type that identifies either the native currency or a token class from `Assets`.
|
/// Type that identifies either the native currency or a token class from `Assets`.
|
||||||
|
/// `Ord` is added because of `get_pool_id`.
|
||||||
type MultiAssetId: AssetId + Ord + From<Self::AssetId>;
|
type MultiAssetId: AssetId + Ord + From<Self::AssetId>;
|
||||||
|
|
||||||
/// Type to convert an `AssetId` into `MultiAssetId`.
|
/// Type to convert an `AssetId` into `MultiAssetId`.
|
||||||
@@ -203,7 +204,7 @@ pub mod pallet {
|
|||||||
|
|
||||||
/// The benchmarks need a way to create asset ids from u32s.
|
/// The benchmarks need a way to create asset ids from u32s.
|
||||||
#[cfg(feature = "runtime-benchmarks")]
|
#[cfg(feature = "runtime-benchmarks")]
|
||||||
type BenchmarkHelper: BenchmarkHelper<Self::AssetId>;
|
type BenchmarkHelper: BenchmarkHelper<Self::AssetId, Self::MultiAssetId>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Map from `PoolAssetId` to `PoolInfo`. This establishes whether a pool has been officially
|
/// Map from `PoolAssetId` to `PoolInfo`. This establishes whether a pool has been officially
|
||||||
@@ -228,6 +229,8 @@ pub mod pallet {
|
|||||||
/// The pool id associated with the pool. Note that the order of the assets may not be
|
/// The pool id associated with the pool. Note that the order of the assets may not be
|
||||||
/// the same as the order specified in the create pool extrinsic.
|
/// the same as the order specified in the create pool extrinsic.
|
||||||
pool_id: PoolIdOf<T>,
|
pool_id: PoolIdOf<T>,
|
||||||
|
/// The account ID of the pool.
|
||||||
|
pool_account: T::AccountId,
|
||||||
/// The id of the liquidity tokens that will be minted when assets are added to this
|
/// The id of the liquidity tokens that will be minted when assets are added to this
|
||||||
/// pool.
|
/// pool.
|
||||||
lp_token: T::PoolAssetId,
|
lp_token: T::PoolAssetId,
|
||||||
@@ -302,6 +305,8 @@ pub mod pallet {
|
|||||||
pub enum Error<T> {
|
pub enum Error<T> {
|
||||||
/// Provided assets are equal.
|
/// Provided assets are equal.
|
||||||
EqualAssets,
|
EqualAssets,
|
||||||
|
/// Provided asset is not supported for pool.
|
||||||
|
UnsupportedAsset,
|
||||||
/// Pool already exists.
|
/// Pool already exists.
|
||||||
PoolExists,
|
PoolExists,
|
||||||
/// Desired amount can't be zero.
|
/// Desired amount can't be zero.
|
||||||
@@ -384,15 +389,14 @@ pub mod pallet {
|
|||||||
let sender = ensure_signed(origin)?;
|
let sender = ensure_signed(origin)?;
|
||||||
ensure!(asset1 != asset2, Error::<T>::EqualAssets);
|
ensure!(asset1 != asset2, Error::<T>::EqualAssets);
|
||||||
|
|
||||||
let pool_id = Self::get_pool_id(asset1.clone(), asset2.clone());
|
// prepare pool_id
|
||||||
let (asset1, asset2) = pool_id.clone();
|
let pool_id = Self::get_pool_id(asset1, asset2);
|
||||||
|
ensure!(!Pools::<T>::contains_key(&pool_id), Error::<T>::PoolExists);
|
||||||
if !T::AllowMultiAssetPools::get() && !T::MultiAssetIdConverter::is_native(&asset1) {
|
let (asset1, asset2) = &pool_id;
|
||||||
|
if !T::AllowMultiAssetPools::get() && !T::MultiAssetIdConverter::is_native(asset1) {
|
||||||
Err(Error::<T>::PoolMustContainNativeCurrency)?;
|
Err(Error::<T>::PoolMustContainNativeCurrency)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
ensure!(!Pools::<T>::contains_key(&pool_id), Error::<T>::PoolExists);
|
|
||||||
|
|
||||||
let pool_account = Self::get_pool_account(&pool_id);
|
let pool_account = Self::get_pool_account(&pool_id);
|
||||||
frame_system::Pallet::<T>::inc_providers(&pool_account);
|
frame_system::Pallet::<T>::inc_providers(&pool_account);
|
||||||
|
|
||||||
@@ -404,15 +408,22 @@ pub mod pallet {
|
|||||||
Preserve,
|
Preserve,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
if let Ok(asset) = T::MultiAssetIdConverter::try_convert(&asset1) {
|
// try to convert both assets
|
||||||
if !T::Assets::contains(&asset, &pool_account) {
|
match T::MultiAssetIdConverter::try_convert(asset1) {
|
||||||
T::Assets::touch(asset, pool_account.clone(), sender.clone())?;
|
MultiAssetIdConversionResult::Converted(asset) =>
|
||||||
}
|
if !T::Assets::contains(&asset, &pool_account) {
|
||||||
|
T::Assets::touch(asset, pool_account.clone(), sender.clone())?
|
||||||
|
},
|
||||||
|
MultiAssetIdConversionResult::Unsupported(_) => Err(Error::<T>::UnsupportedAsset)?,
|
||||||
|
MultiAssetIdConversionResult::Native => (),
|
||||||
}
|
}
|
||||||
if let Ok(asset) = T::MultiAssetIdConverter::try_convert(&asset2) {
|
match T::MultiAssetIdConverter::try_convert(asset2) {
|
||||||
if !T::Assets::contains(&asset, &pool_account) {
|
MultiAssetIdConversionResult::Converted(asset) =>
|
||||||
T::Assets::touch(asset, pool_account.clone(), sender.clone())?;
|
if !T::Assets::contains(&asset, &pool_account) {
|
||||||
}
|
T::Assets::touch(asset, pool_account.clone(), sender.clone())?
|
||||||
|
},
|
||||||
|
MultiAssetIdConversionResult::Unsupported(_) => Err(Error::<T>::UnsupportedAsset)?,
|
||||||
|
MultiAssetIdConversionResult::Native => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
let lp_token = NextPoolAssetId::<T>::get().unwrap_or(T::PoolAssetId::initial_value());
|
let lp_token = NextPoolAssetId::<T>::get().unwrap_or(T::PoolAssetId::initial_value());
|
||||||
@@ -425,7 +436,12 @@ pub mod pallet {
|
|||||||
let pool_info = PoolInfo { lp_token: lp_token.clone() };
|
let pool_info = PoolInfo { lp_token: lp_token.clone() };
|
||||||
Pools::<T>::insert(pool_id.clone(), pool_info);
|
Pools::<T>::insert(pool_id.clone(), pool_info);
|
||||||
|
|
||||||
Self::deposit_event(Event::PoolCreated { creator: sender, pool_id, lp_token });
|
Self::deposit_event(Event::PoolCreated {
|
||||||
|
creator: sender,
|
||||||
|
pool_id,
|
||||||
|
pool_account,
|
||||||
|
lp_token,
|
||||||
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -767,34 +783,35 @@ pub mod pallet {
|
|||||||
amount: T::AssetBalance,
|
amount: T::AssetBalance,
|
||||||
keep_alive: bool,
|
keep_alive: bool,
|
||||||
) -> Result<T::AssetBalance, DispatchError> {
|
) -> Result<T::AssetBalance, DispatchError> {
|
||||||
Self::deposit_event(Event::Transfer {
|
let result = match T::MultiAssetIdConverter::try_convert(asset_id) {
|
||||||
from: from.clone(),
|
MultiAssetIdConversionResult::Converted(asset_id) =>
|
||||||
to: to.clone(),
|
T::Assets::transfer(asset_id, from, to, amount, Expendable),
|
||||||
asset: (*asset_id).clone(),
|
MultiAssetIdConversionResult::Native => {
|
||||||
amount,
|
let preservation = match keep_alive {
|
||||||
});
|
true => Preserve,
|
||||||
if T::MultiAssetIdConverter::is_native(asset_id) {
|
false => Expendable,
|
||||||
let preservation = match keep_alive {
|
};
|
||||||
true => Preserve,
|
let amount = Self::convert_asset_balance_to_native_balance(amount)?;
|
||||||
false => Expendable,
|
Ok(Self::convert_native_balance_to_asset_balance(T::Currency::transfer(
|
||||||
};
|
from,
|
||||||
let amount = Self::convert_asset_balance_to_native_balance(amount)?;
|
to,
|
||||||
Ok(Self::convert_native_balance_to_asset_balance(T::Currency::transfer(
|
amount,
|
||||||
from,
|
preservation,
|
||||||
to,
|
)?)?)
|
||||||
|
},
|
||||||
|
MultiAssetIdConversionResult::Unsupported(_) =>
|
||||||
|
Err(Error::<T>::UnsupportedAsset.into()),
|
||||||
|
};
|
||||||
|
|
||||||
|
if result.is_ok() {
|
||||||
|
Self::deposit_event(Event::Transfer {
|
||||||
|
from: from.clone(),
|
||||||
|
to: to.clone(),
|
||||||
|
asset: (*asset_id).clone(),
|
||||||
amount,
|
amount,
|
||||||
preservation,
|
});
|
||||||
)?)?)
|
|
||||||
} else {
|
|
||||||
T::Assets::transfer(
|
|
||||||
T::MultiAssetIdConverter::try_convert(&asset_id)
|
|
||||||
.map_err(|_| Error::<T>::Overflow)?,
|
|
||||||
from,
|
|
||||||
to,
|
|
||||||
amount,
|
|
||||||
Expendable,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert a `Balance` type to an `AssetBalance`.
|
/// Convert a `Balance` type to an `AssetBalance`.
|
||||||
@@ -898,28 +915,40 @@ pub mod pallet {
|
|||||||
owner: &T::AccountId,
|
owner: &T::AccountId,
|
||||||
asset: &T::MultiAssetId,
|
asset: &T::MultiAssetId,
|
||||||
) -> Result<T::AssetBalance, Error<T>> {
|
) -> Result<T::AssetBalance, Error<T>> {
|
||||||
if T::MultiAssetIdConverter::is_native(asset) {
|
match T::MultiAssetIdConverter::try_convert(asset) {
|
||||||
Self::convert_native_balance_to_asset_balance(
|
MultiAssetIdConversionResult::Converted(asset_id) => Ok(
|
||||||
<<T as Config>::Currency>::reducible_balance(owner, Expendable, Polite),
|
<<T as Config>::Assets>::reducible_balance(asset_id, owner, Expendable, Polite),
|
||||||
)
|
),
|
||||||
} else {
|
MultiAssetIdConversionResult::Native =>
|
||||||
Ok(<<T as Config>::Assets>::reducible_balance(
|
Self::convert_native_balance_to_asset_balance(
|
||||||
T::MultiAssetIdConverter::try_convert(asset)
|
<<T as Config>::Currency>::reducible_balance(owner, Expendable, Polite),
|
||||||
.map_err(|_| Error::<T>::Overflow)?,
|
),
|
||||||
owner,
|
MultiAssetIdConversionResult::Unsupported(_) =>
|
||||||
Expendable,
|
Err(Error::<T>::UnsupportedAsset.into()),
|
||||||
Polite,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a pool id constructed from 2 sorted assets.
|
/// Returns a pool id constructed from 2 assets.
|
||||||
/// Native asset should be lower than the other asset ids.
|
/// 1. Native asset should be lower than the other asset ids.
|
||||||
|
/// 2. Two native or two non-native assets are compared by their `Ord` implementation.
|
||||||
|
///
|
||||||
|
/// We expect deterministic order, so (asset1, asset2) or (asset2, asset1) returns the same
|
||||||
|
/// result.
|
||||||
pub fn get_pool_id(asset1: T::MultiAssetId, asset2: T::MultiAssetId) -> PoolIdOf<T> {
|
pub fn get_pool_id(asset1: T::MultiAssetId, asset2: T::MultiAssetId) -> PoolIdOf<T> {
|
||||||
if asset1 <= asset2 {
|
match (
|
||||||
(asset1, asset2)
|
T::MultiAssetIdConverter::is_native(&asset1),
|
||||||
} else {
|
T::MultiAssetIdConverter::is_native(&asset2),
|
||||||
(asset2, asset1)
|
) {
|
||||||
|
(true, false) => return (asset1, asset2),
|
||||||
|
(false, true) => return (asset2, asset1),
|
||||||
|
_ => {
|
||||||
|
// else we want to be deterministic based on `Ord` implementation
|
||||||
|
if asset1 <= asset2 {
|
||||||
|
(asset1, asset2)
|
||||||
|
} else {
|
||||||
|
(asset2, asset1)
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1161,7 +1190,9 @@ pub mod pallet {
|
|||||||
()
|
()
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
let asset_id = T::MultiAssetIdConverter::try_convert(asset).map_err(|_| ())?;
|
let MultiAssetIdConversionResult::Converted(asset_id) = T::MultiAssetIdConverter::try_convert(asset) else {
|
||||||
|
return Err(())
|
||||||
|
};
|
||||||
let minimal = T::Assets::minimum_balance(asset_id);
|
let minimal = T::Assets::minimum_balance(asset_id);
|
||||||
ensure!(value >= minimal, ());
|
ensure!(value >= minimal, ());
|
||||||
}
|
}
|
||||||
@@ -1179,7 +1210,8 @@ pub mod pallet {
|
|||||||
for assets_pair in path.windows(2) {
|
for assets_pair in path.windows(2) {
|
||||||
if let [asset1, asset2] = assets_pair {
|
if let [asset1, asset2] = assets_pair {
|
||||||
let pool_id = Self::get_pool_id(asset1.clone(), asset2.clone());
|
let pool_id = Self::get_pool_id(asset1.clone(), asset2.clone());
|
||||||
let new_element = pools.try_insert(pool_id).expect("can't get here");
|
let new_element =
|
||||||
|
pools.try_insert(pool_id).map_err(|_| Error::<T>::Overflow)?;
|
||||||
if !new_element {
|
if !new_element {
|
||||||
return Err(Error::<T>::NonUniquePath.into())
|
return Err(Error::<T>::NonUniquePath.into())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ use sp_runtime::{
|
|||||||
traits::{AccountIdConversion, BlakeTwo256, IdentityLookup},
|
traits::{AccountIdConversion, BlakeTwo256, IdentityLookup},
|
||||||
BuildStorage,
|
BuildStorage,
|
||||||
};
|
};
|
||||||
|
|
||||||
type Block = frame_system::mocking::MockBlock<Test>;
|
type Block = frame_system::mocking::MockBlock<Test>;
|
||||||
|
|
||||||
construct_runtime!(
|
construct_runtime!(
|
||||||
|
|||||||
@@ -66,13 +66,8 @@ fn pool_assets() -> Vec<u32> {
|
|||||||
|
|
||||||
fn create_tokens(owner: u128, tokens: Vec<NativeOrAssetId<u32>>) {
|
fn create_tokens(owner: u128, tokens: Vec<NativeOrAssetId<u32>>) {
|
||||||
for token_id in tokens {
|
for token_id in tokens {
|
||||||
assert_ok!(Assets::force_create(
|
let MultiAssetIdConversionResult::Converted(asset_id) = NativeOrAssetIdConverter::try_convert(&token_id) else { unreachable!("invalid token") };
|
||||||
RuntimeOrigin::root(),
|
assert_ok!(Assets::force_create(RuntimeOrigin::root(), asset_id, owner, false, 1));
|
||||||
NativeOrAssetIdConverter::try_convert(&token_id).unwrap(),
|
|
||||||
owner,
|
|
||||||
false,
|
|
||||||
1
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,7 +152,15 @@ fn can_create_pool() {
|
|||||||
assert_eq!(balance(pool_account, NativeOrAssetId::Native), setup_fee);
|
assert_eq!(balance(pool_account, NativeOrAssetId::Native), setup_fee);
|
||||||
assert_eq!(lp_token + 1, AssetConversion::get_next_pool_asset_id());
|
assert_eq!(lp_token + 1, AssetConversion::get_next_pool_asset_id());
|
||||||
|
|
||||||
assert_eq!(events(), [Event::<Test>::PoolCreated { creator: user, pool_id, lp_token }]);
|
assert_eq!(
|
||||||
|
events(),
|
||||||
|
[Event::<Test>::PoolCreated {
|
||||||
|
creator: user,
|
||||||
|
pool_id,
|
||||||
|
pool_account: AssetConversion::get_pool_account(&pool_id),
|
||||||
|
lp_token
|
||||||
|
}]
|
||||||
|
);
|
||||||
assert_eq!(pools(), vec![pool_id]);
|
assert_eq!(pools(), vec![pool_id]);
|
||||||
assert_eq!(assets(), vec![token_2]);
|
assert_eq!(assets(), vec![token_2]);
|
||||||
assert_eq!(pool_assets(), vec![lp_token]);
|
assert_eq!(pool_assets(), vec![lp_token]);
|
||||||
@@ -236,6 +239,7 @@ fn different_pools_should_have_different_lp_tokens() {
|
|||||||
[Event::<Test>::PoolCreated {
|
[Event::<Test>::PoolCreated {
|
||||||
creator: user,
|
creator: user,
|
||||||
pool_id: pool_id_1_2,
|
pool_id: pool_id_1_2,
|
||||||
|
pool_account: AssetConversion::get_pool_account(&pool_id_1_2),
|
||||||
lp_token: lp_token2_1
|
lp_token: lp_token2_1
|
||||||
}]
|
}]
|
||||||
);
|
);
|
||||||
@@ -246,6 +250,7 @@ fn different_pools_should_have_different_lp_tokens() {
|
|||||||
[Event::<Test>::PoolCreated {
|
[Event::<Test>::PoolCreated {
|
||||||
creator: user,
|
creator: user,
|
||||||
pool_id: pool_id_1_3,
|
pool_id: pool_id_1_3,
|
||||||
|
pool_account: AssetConversion::get_pool_account(&pool_id_1_3),
|
||||||
lp_token: lp_token3_1,
|
lp_token: lp_token3_1,
|
||||||
}]
|
}]
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -16,11 +16,10 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use core::marker::PhantomData;
|
|
||||||
use sp_std::cmp::Ordering;
|
|
||||||
|
|
||||||
use codec::{Decode, Encode, MaxEncodedLen};
|
use codec::{Decode, Encode, MaxEncodedLen};
|
||||||
use scale_info::TypeInfo;
|
use scale_info::TypeInfo;
|
||||||
|
use sp_std::{cmp::Ordering, marker::PhantomData};
|
||||||
|
|
||||||
pub(super) type PoolIdOf<T> = (<T as Config>::MultiAssetId, <T as Config>::MultiAssetId);
|
pub(super) type PoolIdOf<T> = (<T as Config>::MultiAssetId, <T as Config>::MultiAssetId);
|
||||||
|
|
||||||
@@ -40,96 +39,43 @@ pub trait MultiAssetIdConverter<MultiAssetId, AssetId> {
|
|||||||
fn is_native(asset: &MultiAssetId) -> bool;
|
fn is_native(asset: &MultiAssetId) -> bool;
|
||||||
|
|
||||||
/// If it's not native, returns the AssetId for the given MultiAssetId.
|
/// If it's not native, returns the AssetId for the given MultiAssetId.
|
||||||
fn try_convert(asset: &MultiAssetId) -> Result<AssetId, ()>;
|
fn try_convert(asset: &MultiAssetId) -> MultiAssetIdConversionResult<MultiAssetId, AssetId>;
|
||||||
|
}
|
||||||
|
|
||||||
/// Wraps an AssetId as a MultiAssetId.
|
/// Result of `MultiAssetIdConverter::try_convert`.
|
||||||
fn into_multiasset_id(asset: &AssetId) -> MultiAssetId;
|
#[cfg_attr(feature = "std", derive(PartialEq, Debug))]
|
||||||
|
pub enum MultiAssetIdConversionResult<MultiAssetId, AssetId> {
|
||||||
|
/// Input asset is successfully converted. Means that converted asset is supported.
|
||||||
|
Converted(AssetId),
|
||||||
|
/// Means that input asset is the chain's native asset, if it has one, so no conversion (see
|
||||||
|
/// `MultiAssetIdConverter::get_native`).
|
||||||
|
Native,
|
||||||
|
/// Means input asset is not supported for pool.
|
||||||
|
Unsupported(MultiAssetId),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Benchmark Helper
|
/// Benchmark Helper
|
||||||
#[cfg(feature = "runtime-benchmarks")]
|
#[cfg(feature = "runtime-benchmarks")]
|
||||||
pub trait BenchmarkHelper<AssetId> {
|
pub trait BenchmarkHelper<AssetId, MultiAssetId> {
|
||||||
/// Returns an asset id from a given integer.
|
/// Returns an `AssetId` from a given integer.
|
||||||
fn asset_id(asset_id: u32) -> AssetId;
|
fn asset_id(asset_id: u32) -> AssetId;
|
||||||
|
|
||||||
|
/// Returns a `MultiAssetId` from a given integer.
|
||||||
|
fn multiasset_id(asset_id: u32) -> MultiAssetId;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "runtime-benchmarks")]
|
#[cfg(feature = "runtime-benchmarks")]
|
||||||
impl<AssetId> BenchmarkHelper<AssetId> for ()
|
impl<AssetId, MultiAssetId> BenchmarkHelper<AssetId, MultiAssetId> for ()
|
||||||
where
|
where
|
||||||
AssetId: From<u32>,
|
AssetId: From<u32>,
|
||||||
|
MultiAssetId: From<u32>,
|
||||||
{
|
{
|
||||||
fn asset_id(asset_id: u32) -> AssetId {
|
fn asset_id(asset_id: u32) -> AssetId {
|
||||||
asset_id.into()
|
asset_id.into()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// An implementation of MultiAssetId that can be either Native or an asset.
|
fn multiasset_id(asset_id: u32) -> MultiAssetId {
|
||||||
#[derive(Decode, Encode, Default, MaxEncodedLen, TypeInfo, Clone, Copy, Debug)]
|
asset_id.into()
|
||||||
pub enum NativeOrAssetId<AssetId>
|
|
||||||
where
|
|
||||||
AssetId: Ord,
|
|
||||||
{
|
|
||||||
/// Native asset. For example, on statemint this would be dot.
|
|
||||||
#[default]
|
|
||||||
Native,
|
|
||||||
/// A non-native asset id.
|
|
||||||
Asset(AssetId),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<AssetId: Ord> From<AssetId> for NativeOrAssetId<AssetId> {
|
|
||||||
fn from(asset: AssetId) -> Self {
|
|
||||||
Self::Asset(asset)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<AssetId: Ord> Ord for NativeOrAssetId<AssetId> {
|
|
||||||
fn cmp(&self, other: &Self) -> Ordering {
|
|
||||||
match (self, other) {
|
|
||||||
(Self::Native, Self::Native) => Ordering::Equal,
|
|
||||||
(Self::Native, Self::Asset(_)) => Ordering::Less,
|
|
||||||
(Self::Asset(_), Self::Native) => Ordering::Greater,
|
|
||||||
(Self::Asset(id1), Self::Asset(id2)) => <AssetId as Ord>::cmp(id1, id2),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<AssetId: Ord> PartialOrd for NativeOrAssetId<AssetId> {
|
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
|
||||||
Some(<Self as Ord>::cmp(self, other))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<AssetId: Ord> PartialEq for NativeOrAssetId<AssetId> {
|
|
||||||
fn eq(&self, other: &Self) -> bool {
|
|
||||||
self.cmp(other) == Ordering::Equal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<AssetId: Ord> Eq for NativeOrAssetId<AssetId> {}
|
|
||||||
|
|
||||||
/// Converts between a MultiAssetId and an AssetId
|
|
||||||
/// (or the native currency).
|
|
||||||
pub struct NativeOrAssetIdConverter<AssetId> {
|
|
||||||
_phantom: PhantomData<AssetId>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<AssetId: Ord + Clone> MultiAssetIdConverter<NativeOrAssetId<AssetId>, AssetId>
|
|
||||||
for NativeOrAssetIdConverter<AssetId>
|
|
||||||
{
|
|
||||||
fn get_native() -> NativeOrAssetId<AssetId> {
|
|
||||||
NativeOrAssetId::Native
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_native(asset: &NativeOrAssetId<AssetId>) -> bool {
|
|
||||||
*asset == Self::get_native()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn try_convert(asset: &NativeOrAssetId<AssetId>) -> Result<AssetId, ()> {
|
|
||||||
match asset {
|
|
||||||
NativeOrAssetId::Asset(asset) => Ok(asset.clone()),
|
|
||||||
NativeOrAssetId::Native => Err(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn into_multiasset_id(asset: &AssetId) -> NativeOrAssetId<AssetId> {
|
|
||||||
NativeOrAssetId::Asset((*asset).clone())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,3 +115,70 @@ pub trait Swap<AccountId, Balance, MultiAssetId> {
|
|||||||
keep_alive: bool,
|
keep_alive: bool,
|
||||||
) -> Result<Balance, DispatchError>;
|
) -> Result<Balance, DispatchError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An implementation of MultiAssetId that can be either Native or an asset.
|
||||||
|
#[derive(Decode, Encode, Default, MaxEncodedLen, TypeInfo, Clone, Copy, Debug)]
|
||||||
|
pub enum NativeOrAssetId<AssetId>
|
||||||
|
where
|
||||||
|
AssetId: Ord,
|
||||||
|
{
|
||||||
|
/// Native asset. For example, on the Polkadot Asset Hub this would be DOT.
|
||||||
|
#[default]
|
||||||
|
Native,
|
||||||
|
/// A non-native asset id.
|
||||||
|
Asset(AssetId),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<AssetId: Ord> From<AssetId> for NativeOrAssetId<AssetId> {
|
||||||
|
fn from(asset: AssetId) -> Self {
|
||||||
|
Self::Asset(asset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<AssetId: Ord> Ord for NativeOrAssetId<AssetId> {
|
||||||
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
|
match (self, other) {
|
||||||
|
(Self::Native, Self::Native) => Ordering::Equal,
|
||||||
|
(Self::Native, Self::Asset(_)) => Ordering::Less,
|
||||||
|
(Self::Asset(_), Self::Native) => Ordering::Greater,
|
||||||
|
(Self::Asset(id1), Self::Asset(id2)) => <AssetId as Ord>::cmp(id1, id2),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<AssetId: Ord> PartialOrd for NativeOrAssetId<AssetId> {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
Some(<Self as Ord>::cmp(self, other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<AssetId: Ord> PartialEq for NativeOrAssetId<AssetId> {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.cmp(other) == Ordering::Equal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<AssetId: Ord> Eq for NativeOrAssetId<AssetId> {}
|
||||||
|
|
||||||
|
/// Converts between a MultiAssetId and an AssetId (or the native currency).
|
||||||
|
pub struct NativeOrAssetIdConverter<AssetId> {
|
||||||
|
_phantom: PhantomData<AssetId>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<AssetId: Ord + Clone> MultiAssetIdConverter<NativeOrAssetId<AssetId>, AssetId>
|
||||||
|
for NativeOrAssetIdConverter<AssetId>
|
||||||
|
{
|
||||||
|
fn get_native() -> NativeOrAssetId<AssetId> {
|
||||||
|
NativeOrAssetId::Native
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_native(asset: &NativeOrAssetId<AssetId>) -> bool {
|
||||||
|
*asset == Self::get_native()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_convert(
|
||||||
|
asset: &NativeOrAssetId<AssetId>,
|
||||||
|
) -> MultiAssetIdConversionResult<NativeOrAssetId<AssetId>, AssetId> {
|
||||||
|
match asset {
|
||||||
|
NativeOrAssetId::Asset(asset) => MultiAssetIdConversionResult::Converted(asset.clone()),
|
||||||
|
NativeOrAssetId::Native => MultiAssetIdConversionResult::Native,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+21
-21
@@ -18,7 +18,7 @@
|
|||||||
//! Autogenerated weights for pallet_asset_conversion
|
//! Autogenerated weights for pallet_asset_conversion
|
||||||
//!
|
//!
|
||||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
|
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
|
||||||
//! DATE: 2023-07-17, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
//! DATE: 2023-07-18, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||||
//! WORST CASE MAP SIZE: `1000000`
|
//! WORST CASE MAP SIZE: `1000000`
|
||||||
//! HOSTNAME: `runner-gghbxkbs-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
|
//! HOSTNAME: `runner-gghbxkbs-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
|
||||||
//! EXECUTION: ``, WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024`
|
//! EXECUTION: ``, WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024`
|
||||||
@@ -77,8 +77,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
|||||||
// Proof Size summary in bytes:
|
// Proof Size summary in bytes:
|
||||||
// Measured: `729`
|
// Measured: `729`
|
||||||
// Estimated: `6196`
|
// Estimated: `6196`
|
||||||
// Minimum execution time: 131_549_000 picoseconds.
|
// Minimum execution time: 131_688_000 picoseconds.
|
||||||
Weight::from_parts(134_287_000, 6196)
|
Weight::from_parts(134_092_000, 6196)
|
||||||
.saturating_add(T::DbWeight::get().reads(8_u64))
|
.saturating_add(T::DbWeight::get().reads(8_u64))
|
||||||
.saturating_add(T::DbWeight::get().writes(8_u64))
|
.saturating_add(T::DbWeight::get().writes(8_u64))
|
||||||
}
|
}
|
||||||
@@ -98,8 +98,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
|||||||
// Proof Size summary in bytes:
|
// Proof Size summary in bytes:
|
||||||
// Measured: `1382`
|
// Measured: `1382`
|
||||||
// Estimated: `6208`
|
// Estimated: `6208`
|
||||||
// Minimum execution time: 156_395_000 picoseconds.
|
// Minimum execution time: 157_310_000 picoseconds.
|
||||||
Weight::from_parts(157_952_000, 6208)
|
Weight::from_parts(161_547_000, 6208)
|
||||||
.saturating_add(T::DbWeight::get().reads(8_u64))
|
.saturating_add(T::DbWeight::get().reads(8_u64))
|
||||||
.saturating_add(T::DbWeight::get().writes(7_u64))
|
.saturating_add(T::DbWeight::get().writes(7_u64))
|
||||||
}
|
}
|
||||||
@@ -119,8 +119,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
|||||||
// Proof Size summary in bytes:
|
// Proof Size summary in bytes:
|
||||||
// Measured: `1371`
|
// Measured: `1371`
|
||||||
// Estimated: `6208`
|
// Estimated: `6208`
|
||||||
// Minimum execution time: 140_295_000 picoseconds.
|
// Minimum execution time: 142_769_000 picoseconds.
|
||||||
Weight::from_parts(143_452_000, 6208)
|
Weight::from_parts(145_139_000, 6208)
|
||||||
.saturating_add(T::DbWeight::get().reads(7_u64))
|
.saturating_add(T::DbWeight::get().reads(7_u64))
|
||||||
.saturating_add(T::DbWeight::get().writes(6_u64))
|
.saturating_add(T::DbWeight::get().writes(6_u64))
|
||||||
}
|
}
|
||||||
@@ -134,8 +134,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
|||||||
// Proof Size summary in bytes:
|
// Proof Size summary in bytes:
|
||||||
// Measured: `1738`
|
// Measured: `1738`
|
||||||
// Estimated: `16644`
|
// Estimated: `16644`
|
||||||
// Minimum execution time: 214_657_000 picoseconds.
|
// Minimum execution time: 213_186_000 picoseconds.
|
||||||
Weight::from_parts(217_657_000, 16644)
|
Weight::from_parts(217_471_000, 16644)
|
||||||
.saturating_add(T::DbWeight::get().reads(10_u64))
|
.saturating_add(T::DbWeight::get().reads(10_u64))
|
||||||
.saturating_add(T::DbWeight::get().writes(10_u64))
|
.saturating_add(T::DbWeight::get().writes(10_u64))
|
||||||
}
|
}
|
||||||
@@ -149,8 +149,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
|||||||
// Proof Size summary in bytes:
|
// Proof Size summary in bytes:
|
||||||
// Measured: `1738`
|
// Measured: `1738`
|
||||||
// Estimated: `16644`
|
// Estimated: `16644`
|
||||||
// Minimum execution time: 215_319_000 picoseconds.
|
// Minimum execution time: 213_793_000 picoseconds.
|
||||||
Weight::from_parts(218_299_000, 16644)
|
Weight::from_parts(218_584_000, 16644)
|
||||||
.saturating_add(T::DbWeight::get().reads(10_u64))
|
.saturating_add(T::DbWeight::get().reads(10_u64))
|
||||||
.saturating_add(T::DbWeight::get().writes(10_u64))
|
.saturating_add(T::DbWeight::get().writes(10_u64))
|
||||||
}
|
}
|
||||||
@@ -176,8 +176,8 @@ impl WeightInfo for () {
|
|||||||
// Proof Size summary in bytes:
|
// Proof Size summary in bytes:
|
||||||
// Measured: `729`
|
// Measured: `729`
|
||||||
// Estimated: `6196`
|
// Estimated: `6196`
|
||||||
// Minimum execution time: 131_549_000 picoseconds.
|
// Minimum execution time: 131_688_000 picoseconds.
|
||||||
Weight::from_parts(134_287_000, 6196)
|
Weight::from_parts(134_092_000, 6196)
|
||||||
.saturating_add(RocksDbWeight::get().reads(8_u64))
|
.saturating_add(RocksDbWeight::get().reads(8_u64))
|
||||||
.saturating_add(RocksDbWeight::get().writes(8_u64))
|
.saturating_add(RocksDbWeight::get().writes(8_u64))
|
||||||
}
|
}
|
||||||
@@ -197,8 +197,8 @@ impl WeightInfo for () {
|
|||||||
// Proof Size summary in bytes:
|
// Proof Size summary in bytes:
|
||||||
// Measured: `1382`
|
// Measured: `1382`
|
||||||
// Estimated: `6208`
|
// Estimated: `6208`
|
||||||
// Minimum execution time: 156_395_000 picoseconds.
|
// Minimum execution time: 157_310_000 picoseconds.
|
||||||
Weight::from_parts(157_952_000, 6208)
|
Weight::from_parts(161_547_000, 6208)
|
||||||
.saturating_add(RocksDbWeight::get().reads(8_u64))
|
.saturating_add(RocksDbWeight::get().reads(8_u64))
|
||||||
.saturating_add(RocksDbWeight::get().writes(7_u64))
|
.saturating_add(RocksDbWeight::get().writes(7_u64))
|
||||||
}
|
}
|
||||||
@@ -218,8 +218,8 @@ impl WeightInfo for () {
|
|||||||
// Proof Size summary in bytes:
|
// Proof Size summary in bytes:
|
||||||
// Measured: `1371`
|
// Measured: `1371`
|
||||||
// Estimated: `6208`
|
// Estimated: `6208`
|
||||||
// Minimum execution time: 140_295_000 picoseconds.
|
// Minimum execution time: 142_769_000 picoseconds.
|
||||||
Weight::from_parts(143_452_000, 6208)
|
Weight::from_parts(145_139_000, 6208)
|
||||||
.saturating_add(RocksDbWeight::get().reads(7_u64))
|
.saturating_add(RocksDbWeight::get().reads(7_u64))
|
||||||
.saturating_add(RocksDbWeight::get().writes(6_u64))
|
.saturating_add(RocksDbWeight::get().writes(6_u64))
|
||||||
}
|
}
|
||||||
@@ -233,8 +233,8 @@ impl WeightInfo for () {
|
|||||||
// Proof Size summary in bytes:
|
// Proof Size summary in bytes:
|
||||||
// Measured: `1738`
|
// Measured: `1738`
|
||||||
// Estimated: `16644`
|
// Estimated: `16644`
|
||||||
// Minimum execution time: 214_657_000 picoseconds.
|
// Minimum execution time: 213_186_000 picoseconds.
|
||||||
Weight::from_parts(217_657_000, 16644)
|
Weight::from_parts(217_471_000, 16644)
|
||||||
.saturating_add(RocksDbWeight::get().reads(10_u64))
|
.saturating_add(RocksDbWeight::get().reads(10_u64))
|
||||||
.saturating_add(RocksDbWeight::get().writes(10_u64))
|
.saturating_add(RocksDbWeight::get().writes(10_u64))
|
||||||
}
|
}
|
||||||
@@ -248,8 +248,8 @@ impl WeightInfo for () {
|
|||||||
// Proof Size summary in bytes:
|
// Proof Size summary in bytes:
|
||||||
// Measured: `1738`
|
// Measured: `1738`
|
||||||
// Estimated: `16644`
|
// Estimated: `16644`
|
||||||
// Minimum execution time: 215_319_000 picoseconds.
|
// Minimum execution time: 213_793_000 picoseconds.
|
||||||
Weight::from_parts(218_299_000, 16644)
|
Weight::from_parts(218_584_000, 16644)
|
||||||
.saturating_add(RocksDbWeight::get().reads(10_u64))
|
.saturating_add(RocksDbWeight::get().reads(10_u64))
|
||||||
.saturating_add(RocksDbWeight::get().writes(10_u64))
|
.saturating_add(RocksDbWeight::get().writes(10_u64))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -257,6 +257,7 @@ impl<T: Config<I>, I: 'static> fungibles::approvals::Inspect<<T as SystemConfig>
|
|||||||
impl<T: Config<I>, I: 'static> fungibles::approvals::Mutate<<T as SystemConfig>::AccountId>
|
impl<T: Config<I>, I: 'static> fungibles::approvals::Mutate<<T as SystemConfig>::AccountId>
|
||||||
for Pallet<T, I>
|
for Pallet<T, I>
|
||||||
{
|
{
|
||||||
|
// Approve spending tokens from a given account
|
||||||
fn approve(
|
fn approve(
|
||||||
asset: T::AssetId,
|
asset: T::AssetId,
|
||||||
owner: &<T as SystemConfig>::AccountId,
|
owner: &<T as SystemConfig>::AccountId,
|
||||||
@@ -266,7 +267,6 @@ impl<T: Config<I>, I: 'static> fungibles::approvals::Mutate<<T as SystemConfig>:
|
|||||||
Self::do_approve_transfer(asset, owner, delegate, amount)
|
Self::do_approve_transfer(asset, owner, delegate, amount)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Aprove spending tokens from a given account
|
|
||||||
fn transfer_from(
|
fn transfer_from(
|
||||||
asset: T::AssetId,
|
asset: T::AssetId,
|
||||||
owner: &<T as SystemConfig>::AccountId,
|
owner: &<T as SystemConfig>::AccountId,
|
||||||
|
|||||||
@@ -62,7 +62,8 @@ pub trait Inspect<AccountId>: Sized {
|
|||||||
/// The minimum balance any single account may have.
|
/// The minimum balance any single account may have.
|
||||||
fn minimum_balance(asset: Self::AssetId) -> Self::Balance;
|
fn minimum_balance(asset: Self::AssetId) -> Self::Balance;
|
||||||
|
|
||||||
/// Get the total amount of funds whose ultimate bneficial ownership can be determined as `who`.
|
/// Get the total amount of funds whose ultimate beneficial ownership can be determined as
|
||||||
|
/// `who`.
|
||||||
///
|
///
|
||||||
/// This may include funds which are wholly inaccessible to `who`, either temporarily or even
|
/// This may include funds which are wholly inaccessible to `who`, either temporarily or even
|
||||||
/// indefinitely.
|
/// indefinitely.
|
||||||
|
|||||||
Reference in New Issue
Block a user