Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Commit

Permalink
Asset conversion nits (#2860)
Browse files Browse the repository at this point in the history
* [asset-conv] Unused Balances type

* [asset-conv] native asset change

* Dedicated `AssetBalance` type for `pallet_assets` instances

* Improved local vs foreign asset handling + test for not allowing pool_assets in pool

* Removed `into_multiasset_id`

* Fix

* Refactor

* Fixed create_pool for benchmark with LocalAndForeignAssets (finally found it)

* ".git/.scripts/commands/fmt/fmt.sh"

* Revert

* fmt

* Migrates pools with `MultiLocation { parents: 0, interior: Here }` to `MultiLocation { parents: 1, interior: Here }`

* Allow `set_storage` for `AllowMultiAssetPools` / `LiquidityWithdrawalFee`

* Benchmarks work

* Removed comment + more defensive migration

* `T::Currency::transfer` -> `Balances::transfer_all` in migration

* Change pool_id in migration

* Update parachains/runtimes/assets/asset-hub-westend/src/lib.rs

* Bump substrate (manually)

* Bump polkadot

* Fixes from polkadot + clippy

* Fix for xcm-emulator tests (thank you Nacho)

---------

Co-authored-by: command-bot <>
Co-authored-by: Jegor Sidorenko <[email protected]>
  • Loading branch information
bkontur and jsidorenko authored Jul 21, 2023
1 parent 66db07b commit 1ac85ed
Show file tree
Hide file tree
Showing 25 changed files with 1,055 additions and 481 deletions.
529 changes: 266 additions & 263 deletions Cargo.lock

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ fn reserve_transfer_native_asset_from_relay_to_assets() {
Kusama,
vec![
RuntimeEvent::XcmPallet(pallet_xcm::Event::Attempted { outcome: Outcome::Complete(weight) }) => {
weight: weight_within_threshold((REF_TIME_THRESHOLD, PROOF_SIZE_THRESHOLD), Weight::from_parts(754_244_000, 0), *weight),
weight: weight_within_threshold((REF_TIME_THRESHOLD, PROOF_SIZE_THRESHOLD), Weight::from_parts(630_092_000, 6196), *weight),
},
]
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ fn reserve_transfer_native_asset_from_relay_to_assets() {
Polkadot,
vec![
RuntimeEvent::XcmPallet(pallet_xcm::Event::Attempted { outcome: Outcome::Complete(weight) }) => {
weight: weight_within_threshold((REF_TIME_THRESHOLD, PROOF_SIZE_THRESHOLD), Weight::from_parts(2_000_000_000, 0), *weight),
weight: weight_within_threshold((REF_TIME_THRESHOLD, PROOF_SIZE_THRESHOLD), Weight::from_parts(686_043_000, 6196), *weight),
},
]
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ description = "Asset Hub Westend runtime integration tests with xcm-emulator"

[dependencies]
codec = { package = "parity-scale-codec", version = "3.4.0", default-features = false }
assert_matches = "1.5.0"

# Substrate
sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ fn reserve_transfer_native_asset_from_relay_to_assets() {
Westend,
vec![
RuntimeEvent::XcmPallet(pallet_xcm::Event::Attempted { outcome: Outcome::Complete(weight) }) => {
weight: weight_within_threshold((REF_TIME_THRESHOLD, PROOF_SIZE_THRESHOLD), Weight::from_parts(731_495_000, 0), *weight),
weight: weight_within_threshold((REF_TIME_THRESHOLD, PROOF_SIZE_THRESHOLD), Weight::from_parts(629_384_000, 6196), *weight),
},
]
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use crate::*;
use frame_support::{instances::Instance2, BoundedVec};
use sp_runtime::{DispatchError, ModuleError};
use xcm_emulator::Parachain;

#[test]
fn swap_locally_on_chain_using_local_assets() {
const ASSET_ID: u32 = 1;

let asset_native = Box::new(MultiLocation { parents: 0, interior: Here });
let asset_native = Box::new(asset_hub_westend_runtime::xcm_config::WestendLocation::get());
let asset_one = Box::new(MultiLocation {
parents: 0,
interior: X2(PalletInstance(50), GeneralIndex(ASSET_ID.into())),
Expand Down Expand Up @@ -99,7 +100,7 @@ fn swap_locally_on_chain_using_foreign_assets() {
use frame_support::weights::WeightToFee;

const ASSET_ID: u32 = 1;
let asset_native = Box::new(MultiLocation { parents: 0, interior: Here });
let asset_native = Box::new(asset_hub_westend_runtime::xcm_config::WestendLocation::get());

let foreign_asset1_at_asset_hub_westend = Box::new(MultiLocation {
parents: 1,
Expand Down Expand Up @@ -305,3 +306,40 @@ fn swap_locally_on_chain_using_foreign_assets() {
));
});
}

#[test]
fn cannot_create_pool_from_pool_assets() {
const ASSET_ID: u32 = 1;

let asset_native = Box::new(asset_hub_westend_runtime::xcm_config::WestendLocation::get());
let mut asset_one = asset_hub_westend_runtime::xcm_config::PoolAssetsPalletLocation::get();
asset_one.append_with(GeneralIndex(ASSET_ID.into())).expect("pool assets");

AssetHubWestend::execute_with(|| {
let pool_owner_account_id = asset_hub_westend_runtime::AssetConversionOrigin::get();

assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::PoolAssets::create(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(pool_owner_account_id.clone()),
ASSET_ID.into(),
pool_owner_account_id.clone().into(),
1000,
));
assert!(<AssetHubWestend as AssetHubWestendPallet>::PoolAssets::asset_exists(ASSET_ID));

assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::PoolAssets::mint(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(pool_owner_account_id),
ASSET_ID.into(),
AssetHubWestendSender::get().into(),
3_000_000_000_000,
));

assert_matches::assert_matches!(
<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::create_pool(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
asset_native.clone(),
Box::new(asset_one),
),
Err(DispatchError::Module(ModuleError{index: _, error: _, message})) => assert_eq!(message, Some("UnsupportedAsset"))
);
});
}
1 change: 1 addition & 0 deletions parachains/integration-tests/emulated/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ decl_test_parachains! {
PolkadotXcm: asset_hub_westend_runtime::PolkadotXcm,
Assets: asset_hub_westend_runtime::Assets,
ForeignAssets: asset_hub_westend_runtime::ForeignAssets,
PoolAssets: asset_hub_westend_runtime::PoolAssets,
AssetConversion: asset_hub_westend_runtime::AssetConversion,
}
},
Expand Down
3 changes: 2 additions & 1 deletion parachains/runtimes/assets/asset-hub-kusama/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1139,14 +1139,15 @@ impl_runtime_apis! {
MultiAsset { fun: Fungible(UNITS), id: Concrete(KsmLocation::get()) },
));
pub const CheckedAccount: Option<(AccountId, xcm_builder::MintLocation)> = None;

pub const TrustedReserve: Option<(MultiLocation, MultiAsset)> = None;
}

impl pallet_xcm_benchmarks::fungible::Config for Runtime {
type TransactAsset = Balances;

type CheckedAccount = CheckedAccount;
type TrustedTeleporter = TrustedTeleporter;
type TrustedReserve = TrustedReserve;

fn get_multi_asset() -> MultiAsset {
MultiAsset {
Expand Down
2 changes: 2 additions & 0 deletions parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1121,13 +1121,15 @@ impl_runtime_apis! {
MultiAsset { fun: Fungible(UNITS), id: Concrete(DotLocation::get()) },
));
pub const CheckedAccount: Option<(AccountId, xcm_builder::MintLocation)> = None;
pub const TrustedReserve: Option<(MultiLocation, MultiAsset)> = None;
}

impl pallet_xcm_benchmarks::fungible::Config for Runtime {
type TransactAsset = Balances;

type CheckedAccount = CheckedAccount;
type TrustedTeleporter = TrustedTeleporter;
type TrustedReserve = TrustedReserve;

fn get_multi_asset() -> MultiAsset {
MultiAsset {
Expand Down
150 changes: 142 additions & 8 deletions parachains/runtimes/assets/asset-hub-westend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,13 @@ pub mod constants;
mod weights;
pub mod xcm_config;

use crate::xcm_config::{TrustBackedAssetsPalletLocation, UniversalLocation};
use assets_common::local_and_foreign_assets::{LocalAndForeignAssets, MultiLocationConverter};
use crate::xcm_config::{
LocalAndForeignAssetsMultiLocationMatcher, TrustBackedAssetsPalletLocation,
};
use assets_common::{
local_and_foreign_assets::{LocalAndForeignAssets, MultiLocationConverter},
AssetIdForTrustBackedAssetsConvert,
};
use codec::{Decode, Encode, MaxEncodedLen};
use constants::{currency::*, fee::WeightToFee};
use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases;
Expand Down Expand Up @@ -300,9 +305,13 @@ impl pallet_asset_conversion::Config for Runtime {
type Balance = Balance;
type HigherPrecisionBalance = sp_core::U256;
type Currency = Balances;
type AssetBalance = <Self as pallet_balances::Config>::Balance;
type AssetBalance = Balance;
type AssetId = MultiLocation;
type Assets = LocalAndForeignAssets<Assets, ForeignAssets, TrustBackedAssetsPalletLocation>;
type Assets = LocalAndForeignAssets<
Assets,
AssetIdForTrustBackedAssetsConvert<TrustBackedAssetsPalletLocation>,
ForeignAssets,
>;
type PoolAssets = PoolAssets;
type PoolAssetId = u32;
type PoolSetupFee = ConstU128<0>; // Asset class deposit fees are sufficient to prevent spam
Expand All @@ -314,11 +323,12 @@ impl pallet_asset_conversion::Config for Runtime {
type MaxSwapPathLength = ConstU32<4>;

type MultiAssetId = Box<MultiLocation>;
type MultiAssetIdConverter = MultiLocationConverter<Balances, UniversalLocation>;
type MultiAssetIdConverter =
MultiLocationConverter<WestendLocation, LocalAndForeignAssetsMultiLocationMatcher>;

type MintMinLiquidity = ConstU128<100>;

type WeightInfo = ();
type WeightInfo = weights::pallet_asset_conversion::WeightInfo<Runtime>;

#[cfg(feature = "runtime-benchmarks")]
type BenchmarkHelper =
Expand Down Expand Up @@ -659,7 +669,11 @@ impl pallet_collator_selection::Config for Runtime {

impl pallet_asset_conversion_tx_payment::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Fungibles = LocalAndForeignAssets<Assets, ForeignAssets, TrustBackedAssetsPalletLocation>;
type Fungibles = LocalAndForeignAssets<
Assets,
AssetIdForTrustBackedAssetsConvert<TrustBackedAssetsPalletLocation>,
ForeignAssets,
>;
type OnChargeAssetTransaction = AssetConversionAdapter<Balances, AssetConversion>;
}

Expand Down Expand Up @@ -835,6 +849,8 @@ pub type Migrations = (
pallet_nfts::migration::v1::MigrateToV1<Runtime>,
// unreleased
pallet_collator_selection::migration::v1::MigrateToV1<Runtime>,
// unreleased
migrations::NativeAssetParents0ToParents1Migration<Runtime>,
);

/// Executive: handles dispatch to the various modules.
Expand Down Expand Up @@ -1240,14 +1256,15 @@ impl_runtime_apis! {
MultiAsset { fun: Fungible(UNITS), id: Concrete(WestendLocation::get()) },
));
pub const CheckedAccount: Option<(AccountId, xcm_builder::MintLocation)> = None;

pub const TrustedReserve: Option<(MultiLocation, MultiAsset)> = None;
}

impl pallet_xcm_benchmarks::fungible::Config for Runtime {
type TransactAsset = Balances;

type CheckedAccount = CheckedAccount;
type TrustedTeleporter = TrustedTeleporter;
type TrustedReserve = TrustedReserve;

fn get_multi_asset() -> MultiAsset {
MultiAsset {
Expand Down Expand Up @@ -1360,3 +1377,120 @@ cumulus_pallet_parachain_system::register_validate_block! {
BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::<Runtime, Executive>,
CheckInherents = CheckInherents,
}

pub mod migrations {
use super::*;
use frame_support::{
pallet_prelude::Get,
traits::{
fungibles::{Inspect, Mutate},
tokens::Preservation,
OnRuntimeUpgrade, OriginTrait,
},
};
use parachains_common::impls::AccountIdOf;
use sp_runtime::{traits::StaticLookup, Saturating};
use xcm::latest::prelude::*;

/// Temporary migration because of bug with native asset, it can be removed once applied on `AssetHubWestend`.
/// Migrates pools with `MultiLocation { parents: 0, interior: Here }` to `MultiLocation { parents: 1, interior: Here }`
pub struct NativeAssetParents0ToParents1Migration<T>(sp_std::marker::PhantomData<T>);
impl<
T: pallet_asset_conversion::Config<
MultiAssetId = Box<MultiLocation>,
AssetId = MultiLocation,
>,
> OnRuntimeUpgrade for NativeAssetParents0ToParents1Migration<T>
where
<T as pallet_asset_conversion::Config>::PoolAssetId: Into<u32>,
AccountIdOf<Runtime>: Into<[u8; 32]>,
<T as frame_system::Config>::AccountId:
Into<<<T as frame_system::Config>::RuntimeOrigin as OriginTrait>::AccountId>,
<<T as frame_system::Config>::Lookup as StaticLookup>::Source:
From<<T as frame_system::Config>::AccountId>,
sp_runtime::AccountId32: From<<T as frame_system::Config>::AccountId>,
{
fn on_runtime_upgrade() -> Weight {
let invalid_native_asset = MultiLocation { parents: 0, interior: Here };
let valid_native_asset = WestendLocation::get();

let mut reads: u64 = 1;
let mut writes: u64 = 0;

// migrate pools with invalid native asset
let pools = pallet_asset_conversion::Pools::<T>::iter().collect::<Vec<_>>();
reads.saturating_accrue(1);
for (old_pool_id, pool_info) in pools {
let old_pool_account =
pallet_asset_conversion::Pallet::<T>::get_pool_account(&old_pool_id);
reads.saturating_accrue(1);
let pool_asset_id = pool_info.lp_token.clone();
if old_pool_id.0.as_ref() != &invalid_native_asset {
// skip, if ok
continue
}

// fix new account
let new_pool_id = pallet_asset_conversion::Pallet::<T>::get_pool_id(
Box::new(valid_native_asset),
old_pool_id.1.clone(),
);
let new_pool_account =
pallet_asset_conversion::Pallet::<T>::get_pool_account(&new_pool_id);
frame_system::Pallet::<T>::inc_providers(&new_pool_account);
reads.saturating_accrue(2);
writes.saturating_accrue(1);

// move currency
let _ = Balances::transfer_all(
RuntimeOrigin::signed(sp_runtime::AccountId32::from(old_pool_account.clone())),
sp_runtime::AccountId32::from(new_pool_account.clone()).into(),
false,
);
reads.saturating_accrue(2);
writes.saturating_accrue(2);

// move LP token
let _ = T::PoolAssets::transfer(
pool_asset_id.clone(),
&old_pool_account,
&new_pool_account,
T::PoolAssets::balance(pool_asset_id.clone(), &old_pool_account),
Preservation::Expendable,
);
reads.saturating_accrue(1);
writes.saturating_accrue(2);

// change the ownership of LP token
let _ = pallet_assets::Pallet::<Runtime, PoolAssetsInstance>::transfer_ownership(
RuntimeOrigin::signed(sp_runtime::AccountId32::from(old_pool_account.clone())),
pool_asset_id.into(),
sp_runtime::AccountId32::from(new_pool_account.clone()).into(),
);
reads.saturating_accrue(1);
writes.saturating_accrue(2);

// move LocalOrForeignAssets
let _ = T::Assets::transfer(
*old_pool_id.1.as_ref(),
&old_pool_account,
&new_pool_account,
T::Assets::balance(*old_pool_id.1.as_ref(), &old_pool_account),
Preservation::Expendable,
);
reads.saturating_accrue(1);
writes.saturating_accrue(2);

// dec providers for old account
let _ = frame_system::Pallet::<T>::dec_providers(&old_pool_account);
writes.saturating_accrue(1);

// change pool key
pallet_asset_conversion::Pools::<T>::insert(new_pool_id, pool_info);
pallet_asset_conversion::Pools::<T>::remove(old_pool_id);
}

T::DbWeight::get().reads_writes(reads, writes)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub mod block_weights;
pub mod cumulus_pallet_xcmp_queue;
pub mod extrinsic_weights;
pub mod frame_system;
pub mod pallet_asset_conversion;
pub mod pallet_assets_foreign;
pub mod pallet_assets_local;
pub mod pallet_assets_pool;
Expand Down
Loading

0 comments on commit 1ac85ed

Please sign in to comment.