Improve Penpal runtime + emulated tests (#3543)

Issues addressed in this PR:
- Improve *Penpal* runtime:
- Properly handled received assets. Previously, it treated `(1, Here)`
as the local native currency, whereas it should be treated as a
`ForeignAsset`. This wasn't a great example of standard Parachain
behaviour, as no Parachain treats the system asset as the local
currency.
- Remove `AllowExplicitUnpaidExecutionFrom` the system. Again, this
wasn't a great example of standard Parachain behaviour.
- Move duplicated
`ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger` to
`assets_common` crate.
- Improve emulated tests:
  - Update *Penpal* tests to new runtime.
- To simplify tests, register the reserve transferred, teleported, and
system assets in *Penpal* and *AssetHub* genesis. This saves us from
having to create the assets repeatedly for each test
- Add missing test case:
`reserve_transfer_assets_from_para_to_system_para`.
  - Cleanup.
- Prevent integration tests crates imports from being re-exported, as
they were polluting the `polkadot-sdk` docs.

There is still a test case missing for reserve transfers:
- Reserve transfer of system asset from *Parachain* to *Parachain*
trough *AssetHub*.
- This is not yet possible with `pallet-xcm` due to the reasons
explained in https://github.com/paritytech/polkadot-sdk/pull/3339

---------

Co-authored-by: command-bot <>
This commit is contained in:
Ignacio Palacios
2024-03-14 11:29:24 +01:00
committed by GitHub
parent 606664e1bd
commit cfc4050d6b
47 changed files with 2581 additions and 1200 deletions
Generated
+4 -2
View File
@@ -841,6 +841,7 @@ dependencies = [
"pallet-xcm",
"parachains-common",
"parity-scale-codec",
"penpal-runtime",
"rococo-runtime",
"rococo-system-emulated-network",
"sp-runtime",
@@ -962,6 +963,7 @@ dependencies = [
"pallet-xcm",
"parachains-common",
"parity-scale-codec",
"penpal-runtime",
"polkadot-runtime-common",
"sp-runtime",
"staging-xcm",
@@ -4931,6 +4933,7 @@ dependencies = [
"parachains-common",
"parity-scale-codec",
"paste",
"polkadot-parachain-primitives",
"polkadot-primitives",
"polkadot-runtime-parachains",
"sc-consensus-grandpa",
@@ -11645,9 +11648,8 @@ dependencies = [
"frame-support",
"parachains-common",
"penpal-runtime",
"rococo-emulated-chain",
"sp-core",
"westend-emulated-chain",
"staging-xcm",
]
[[package]]
@@ -14,17 +14,24 @@
// limitations under the License.
// Substrate
use sp_core::storage::Storage;
use frame_support::parameter_types;
use sp_core::{sr25519, storage::Storage};
// Cumulus
use emulated_integration_tests_common::{
accounts, build_genesis_storage, collators, SAFE_XCM_VERSION,
accounts, build_genesis_storage, collators, get_account_id_from_seed,
PenpalSiblingSovereigAccount, PenpalTeleportableAssetLocation, RESERVABLE_ASSET_ID,
SAFE_XCM_VERSION,
};
use parachains_common::Balance;
use parachains_common::{AccountId, Balance};
pub const PARA_ID: u32 = 1000;
pub const ED: Balance = testnet_parachains_constants::rococo::currency::EXISTENTIAL_DEPOSIT;
parameter_types! {
pub AssetHubRococoAssetOwner: AccountId = get_account_id_from_seed::<sr25519::Public>("Alice");
}
pub fn genesis() -> Storage {
let genesis_config = asset_hub_rococo_runtime::RuntimeGenesisConfig {
system: asset_hub_rococo_runtime::SystemConfig::default(),
@@ -60,6 +67,22 @@ pub fn genesis() -> Storage {
safe_xcm_version: Some(SAFE_XCM_VERSION),
..Default::default()
},
assets: asset_hub_rococo_runtime::AssetsConfig {
assets: vec![(RESERVABLE_ASSET_ID, AssetHubRococoAssetOwner::get(), true, ED)],
..Default::default()
},
foreign_assets: asset_hub_rococo_runtime::ForeignAssetsConfig {
assets: vec![
// Penpal's teleportable asset representation
(
PenpalTeleportableAssetLocation::get(),
PenpalSiblingSovereigAccount::get(),
true,
ED,
),
],
..Default::default()
},
..Default::default()
};
@@ -21,7 +21,7 @@ use frame_support::traits::OnInitialize;
// Cumulus
use emulated_integration_tests_common::{
impl_accounts_helpers_for_parachain, impl_assert_events_helpers_for_parachain,
impl_assets_helpers_for_parachain, impl_foreign_assets_helpers_for_parachain,
impl_assets_helpers_for_parachain, impl_assets_helpers_for_system_parachain,
impl_xcm_helpers_for_parachain, impls::Parachain, xcm_emulator::decl_test_parachains,
};
use rococo_emulated_chain::Rococo;
@@ -54,6 +54,6 @@ decl_test_parachains! {
// AssetHubRococo implementation
impl_accounts_helpers_for_parachain!(AssetHubRococo);
impl_assert_events_helpers_for_parachain!(AssetHubRococo);
impl_assets_helpers_for_parachain!(AssetHubRococo, Rococo);
impl_foreign_assets_helpers_for_parachain!(AssetHubRococo, Rococo);
impl_assets_helpers_for_system_parachain!(AssetHubRococo, Rococo);
impl_assets_helpers_for_parachain!(AssetHubRococo);
impl_xcm_helpers_for_parachain!(AssetHubRococo);
@@ -14,17 +14,24 @@
// limitations under the License.
// Substrate
use sp_core::storage::Storage;
use frame_support::parameter_types;
use sp_core::{sr25519, storage::Storage};
// Cumulus
use emulated_integration_tests_common::{
accounts, build_genesis_storage, collators, SAFE_XCM_VERSION,
accounts, build_genesis_storage, collators, get_account_id_from_seed,
PenpalSiblingSovereigAccount, PenpalTeleportableAssetLocation, RESERVABLE_ASSET_ID,
SAFE_XCM_VERSION,
};
use parachains_common::Balance;
use parachains_common::{AccountId, Balance};
pub const PARA_ID: u32 = 1000;
pub const ED: Balance = testnet_parachains_constants::westend::currency::EXISTENTIAL_DEPOSIT;
parameter_types! {
pub AssetHubWestendAssetOwner: AccountId = get_account_id_from_seed::<sr25519::Public>("Alice");
}
pub fn genesis() -> Storage {
let genesis_config = asset_hub_westend_runtime::RuntimeGenesisConfig {
system: asset_hub_westend_runtime::SystemConfig::default(),
@@ -56,6 +63,22 @@ pub fn genesis() -> Storage {
safe_xcm_version: Some(SAFE_XCM_VERSION),
..Default::default()
},
assets: asset_hub_westend_runtime::AssetsConfig {
assets: vec![(RESERVABLE_ASSET_ID, AssetHubWestendAssetOwner::get(), true, ED)],
..Default::default()
},
foreign_assets: asset_hub_westend_runtime::ForeignAssetsConfig {
assets: vec![
// Penpal's teleportable asset representation
(
PenpalTeleportableAssetLocation::get(),
PenpalSiblingSovereigAccount::get(),
true,
ED,
),
],
..Default::default()
},
..Default::default()
};
@@ -21,7 +21,7 @@ use frame_support::traits::OnInitialize;
// Cumulus
use emulated_integration_tests_common::{
impl_accounts_helpers_for_parachain, impl_assert_events_helpers_for_parachain,
impl_assets_helpers_for_parachain, impl_foreign_assets_helpers_for_parachain,
impl_assets_helpers_for_parachain, impl_assets_helpers_for_system_parachain,
impl_xcm_helpers_for_parachain, impls::Parachain, xcm_emulator::decl_test_parachains,
};
use westend_emulated_chain::Westend;
@@ -54,6 +54,6 @@ decl_test_parachains! {
// AssetHubWestend implementation
impl_accounts_helpers_for_parachain!(AssetHubWestend);
impl_assert_events_helpers_for_parachain!(AssetHubWestend);
impl_assets_helpers_for_parachain!(AssetHubWestend, Westend);
impl_foreign_assets_helpers_for_parachain!(AssetHubWestend, Westend);
impl_assets_helpers_for_system_parachain!(AssetHubWestend, Westend);
impl_assets_helpers_for_parachain!(AssetHubWestend);
impl_xcm_helpers_for_parachain!(AssetHubWestend);
@@ -16,10 +16,11 @@ workspace = true
sp-core = { path = "../../../../../../../../substrate/primitives/core", default-features = false }
frame-support = { path = "../../../../../../../../substrate/frame/support", default-features = false }
# Polkadot
xcm = { package = "staging-xcm", path = "../../../../../../../../polkadot/xcm", default-features = false }
# Cumulus
parachains-common = { path = "../../../../../../../parachains/common" }
cumulus-primitives-core = { path = "../../../../../../../primitives/core", default-features = false }
emulated-integration-tests-common = { path = "../../../../common", default-features = false }
penpal-runtime = { path = "../../../../../../runtimes/testing/penpal" }
rococo-emulated-chain = { path = "../../../relays/rococo" }
westend-emulated-chain = { path = "../../../relays/westend" }
@@ -14,19 +14,27 @@
// limitations under the License.
// Substrate
use frame_support::parameter_types;
use sp_core::{sr25519, storage::Storage};
// Polkadot
use xcm::v3::Location;
// Cumulus
use emulated_integration_tests_common::{
accounts, build_genesis_storage, collators, get_account_id_from_seed, SAFE_XCM_VERSION,
};
use parachains_common::Balance;
use parachains_common::{AccountId, Balance};
use penpal_runtime::xcm_config::{LocalReservableFromAssetHub, RelayLocation};
// Penpal
pub const PARA_ID_A: u32 = 2000;
pub const PARA_ID_B: u32 = 2001;
pub const ED: Balance = penpal_runtime::EXISTENTIAL_DEPOSIT;
parameter_types! {
pub PenpalSudoAcccount: AccountId = get_account_id_from_seed::<sr25519::Public>("Alice");
pub PenpalAssetOwner: AccountId = PenpalSudoAcccount::get();
}
pub fn genesis(para_id: u32) -> Storage {
let genesis_config = penpal_runtime::RuntimeGenesisConfig {
system: penpal_runtime::SystemConfig::default(),
@@ -58,8 +66,35 @@ pub fn genesis(para_id: u32) -> Storage {
safe_xcm_version: Some(SAFE_XCM_VERSION),
..Default::default()
},
sudo: penpal_runtime::SudoConfig {
key: Some(get_account_id_from_seed::<sr25519::Public>("Alice")),
sudo: penpal_runtime::SudoConfig { key: Some(PenpalSudoAcccount::get()) },
assets: penpal_runtime::AssetsConfig {
assets: vec![(
penpal_runtime::xcm_config::TELEPORTABLE_ASSET_ID,
PenpalAssetOwner::get(),
false,
ED,
)],
..Default::default()
},
foreign_assets: penpal_runtime::ForeignAssetsConfig {
assets: vec![
// Relay Native asset representation
(
Location::try_from(RelayLocation::get()).expect("conversion works"),
PenpalAssetOwner::get(),
true,
ED,
),
// Sufficient AssetHub asset representation
(
Location::try_from(LocalReservableFromAssetHub::get())
.expect("conversion works"),
PenpalAssetOwner::get(),
true,
ED,
),
],
..Default::default()
},
..Default::default()
};
@@ -14,10 +14,9 @@
// limitations under the License.
mod genesis;
pub use genesis::{genesis, ED, PARA_ID_A, PARA_ID_B};
pub use genesis::{genesis, PenpalAssetOwner, PenpalSudoAcccount, ED, PARA_ID_A, PARA_ID_B};
pub use penpal_runtime::xcm_config::{
CustomizableAssetFromSystemAssetHub, LocalTeleportableToAssetHub,
LocalTeleportableToAssetHubV3, XcmConfig,
CustomizableAssetFromSystemAssetHub, LocalTeleportableToAssetHub, XcmConfig,
};
// Substrate
@@ -28,8 +27,6 @@ use emulated_integration_tests_common::{
impl_accounts_helpers_for_parachain, impl_assert_events_helpers_for_parachain,
impl_assets_helpers_for_parachain, impls::Parachain, xcm_emulator::decl_test_parachains,
};
use rococo_emulated_chain::Rococo;
use westend_emulated_chain::Westend;
// Penpal Parachain declaration
decl_test_parachains! {
@@ -76,7 +73,7 @@ decl_test_parachains! {
// Penpal implementation
impl_accounts_helpers_for_parachain!(PenpalA);
impl_accounts_helpers_for_parachain!(PenpalB);
impl_assets_helpers_for_parachain!(PenpalA, Rococo);
impl_assets_helpers_for_parachain!(PenpalB, Westend);
impl_assert_events_helpers_for_parachain!(PenpalA);
impl_assert_events_helpers_for_parachain!(PenpalB);
impl_assets_helpers_for_parachain!(PenpalA);
impl_assets_helpers_for_parachain!(PenpalB);
@@ -27,6 +27,7 @@ pallet-message-queue = { path = "../../../../../substrate/frame/message-queue" }
# Polkadot
polkadot-primitives = { path = "../../../../../polkadot/primitives" }
polkadot-parachain-primitives = { path = "../../../../../polkadot/parachain" }
polkadot-runtime-parachains = { path = "../../../../../polkadot/runtime/parachains" }
xcm = { package = "staging-xcm", path = "../../../../../polkadot/xcm" }
pallet-xcm = { path = "../../../../../polkadot/xcm/pallet-xcm" }
@@ -592,7 +592,7 @@ macro_rules! impl_assert_events_helpers_for_parachain {
}
#[macro_export]
macro_rules! impl_assets_helpers_for_parachain {
macro_rules! impl_assets_helpers_for_system_parachain {
( $chain:ident, $relay_chain:ident ) => {
$crate::impls::paste::paste! {
impl<N: $crate::impls::Network> $chain<N> {
@@ -630,38 +630,6 @@ macro_rules! impl_assets_helpers_for_parachain {
$crate::impls::xcm_transact_unpaid_execution(call, origin_kind)
}
/// Mint assets making use of the assets pallet
pub fn mint_asset(
signed_origin: <Self as $crate::impls::Chain>::RuntimeOrigin,
id: u32,
beneficiary: $crate::impls::AccountId,
amount_to_mint: u128,
) {
<Self as $crate::impls::TestExt>::execute_with(|| {
$crate::impls::assert_ok!(<Self as [<$chain ParaPallet>]>::Assets::mint(
signed_origin,
id.clone().into(),
beneficiary.clone().into(),
amount_to_mint
));
type RuntimeEvent<N> = <$chain<N> as $crate::impls::Chain>::RuntimeEvent;
$crate::impls::assert_expected_events!(
Self,
vec![
RuntimeEvent::<N>::Assets(
$crate::impls::pallet_assets::Event::Issued { asset_id, owner, amount }
) => {
asset_id: *asset_id == id,
owner: *owner == beneficiary.clone().into(),
amount: *amount == amount_to_mint,
},
]
);
});
}
/// Force create and mint assets making use of the assets pallet
pub fn force_create_and_mint_asset(
id: u32,
@@ -727,8 +695,8 @@ macro_rules! impl_assets_helpers_for_parachain {
}
#[macro_export]
macro_rules! impl_foreign_assets_helpers_for_parachain {
( $chain:ident, $relay_chain:ident ) => {
macro_rules! impl_assets_helpers_for_parachain {
( $chain:ident) => {
$crate::impls::paste::paste! {
impl<N: $crate::impls::Network> $chain<N> {
/// Create foreign assets using sudo `ForeignAssets::force_create()`
@@ -803,6 +771,118 @@ macro_rules! impl_foreign_assets_helpers_for_parachain {
);
});
}
/// Create assets using sudo `Assets::force_create()`
pub fn force_create_asset(
id: u32,
owner: $crate::impls::AccountId,
is_sufficient: bool,
min_balance: u128,
prefund_accounts: Vec<($crate::impls::AccountId, u128)>,
) {
use $crate::impls::Inspect;
let sudo_origin = <$chain<N> as $crate::impls::Chain>::RuntimeOrigin::root();
<Self as $crate::impls::TestExt>::execute_with(|| {
$crate::impls::assert_ok!(
<Self as [<$chain ParaPallet>]>::Assets::force_create(
sudo_origin,
id.clone().into(),
owner.clone().into(),
is_sufficient,
min_balance,
)
);
assert!(<Self as [<$chain ParaPallet>]>::Assets::asset_exists(id.clone()));
type RuntimeEvent<N> = <$chain<N> as $crate::impls::Chain>::RuntimeEvent;
$crate::impls::assert_expected_events!(
Self,
vec![
RuntimeEvent::<N>::Assets(
$crate::impls::pallet_assets::Event::ForceCreated {
asset_id,
..
}
) => { asset_id: *asset_id == id, },
]
);
});
for (beneficiary, amount) in prefund_accounts.into_iter() {
let signed_origin =
<$chain<N> as $crate::impls::Chain>::RuntimeOrigin::signed(owner.clone());
Self::mint_asset(signed_origin, id.clone(), beneficiary, amount);
}
}
/// Mint assets making use of the assets pallet
pub fn mint_asset(
signed_origin: <Self as $crate::impls::Chain>::RuntimeOrigin,
id: u32,
beneficiary: $crate::impls::AccountId,
amount_to_mint: u128,
) {
<Self as $crate::impls::TestExt>::execute_with(|| {
$crate::impls::assert_ok!(<Self as [<$chain ParaPallet>]>::Assets::mint(
signed_origin,
id.clone().into(),
beneficiary.clone().into(),
amount_to_mint
));
type RuntimeEvent<N> = <$chain<N> as $crate::impls::Chain>::RuntimeEvent;
$crate::impls::assert_expected_events!(
Self,
vec![
RuntimeEvent::<N>::Assets(
$crate::impls::pallet_assets::Event::Issued { asset_id, owner, amount }
) => {
asset_id: *asset_id == id,
owner: *owner == beneficiary.clone().into(),
amount: *amount == amount_to_mint,
},
]
);
});
}
/// Returns the encoded call for `create` from the assets pallet
pub fn create_asset_call(
asset_id: u32,
min_balance: $crate::impls::Balance,
admin: $crate::impls::AccountId,
) -> $crate::impls::DoubleEncoded<()> {
use $crate::impls::{Chain, Encode};
<Self as Chain>::RuntimeCall::Assets($crate::impls::pallet_assets::Call::<
<Self as Chain>::Runtime,
$crate::impls::pallet_assets::Instance1,
>::create {
id: asset_id.into(),
min_balance,
admin: admin.into(),
})
.encode()
.into()
}
/// Returns the encoded call for `create` from the foreign assets pallet
pub fn create_foreign_asset_call(
asset_id: $crate::impls::v3::Location,
min_balance: $crate::impls::Balance,
admin: $crate::impls::AccountId,
) -> $crate::impls::DoubleEncoded<()> {
use $crate::impls::{Chain, Encode};
<Self as Chain>::RuntimeCall::ForeignAssets($crate::impls::pallet_assets::Call::<
<Self as Chain>::Runtime,
$crate::impls::pallet_assets::Instance2,
>::create {
id: asset_id.into(),
min_balance,
admin: admin.into(),
})
.encode()
.into()
}
}
}
};
@@ -21,17 +21,19 @@ pub use xcm_emulator;
// Substrate
use beefy_primitives::ecdsa_crypto::AuthorityId as BeefyId;
use frame_support::parameter_types;
use grandpa::AuthorityId as GrandpaId;
use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
use sp_consensus_babe::AuthorityId as BabeId;
use sp_core::{sr25519, storage::Storage, Pair, Public};
use sp_runtime::{
traits::{IdentifyAccount, Verify},
traits::{AccountIdConversion, IdentifyAccount, Verify},
BuildStorage, MultiSignature,
};
// Polakdot
use parachains_common::BlockNumber;
use polkadot_parachain_primitives::primitives::Sibling;
use polkadot_runtime_parachains::configuration::HostConfiguration;
// Cumulus
@@ -49,6 +51,25 @@ pub const SAFE_XCM_VERSION: u32 = xcm::prelude::XCM_VERSION;
type AccountPublic = <MultiSignature as Verify>::Signer;
// This asset is added to AH as Asset and reserved transfer between Parachain and AH
pub const RESERVABLE_ASSET_ID: u32 = 1;
// This asset is added to AH as ForeignAsset and teleported between Penpal and AH
pub const TELEPORTABLE_ASSET_ID: u32 = 2;
pub const PENPAL_ID: u32 = 2000;
pub const ASSETS_PALLET_ID: u8 = 50;
parameter_types! {
pub PenpalTeleportableAssetLocation: xcm::v3::Location
= xcm::v3::Location::new(1, [
xcm::v3::Junction::Parachain(PENPAL_ID),
xcm::v3::Junction::PalletInstance(ASSETS_PALLET_ID),
xcm::v3::Junction::GeneralIndex(TELEPORTABLE_ASSET_ID.into()),
]
);
pub PenpalSiblingSovereigAccount: AccountId = Sibling::from(PENPAL_ID).into_account_truncating();
}
/// Helper function to generate a crypto pair from seed
pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {
TPublic::Pair::from_string(&format!("//{}", seed), None)
@@ -16,16 +16,26 @@
pub use paste;
// Substrate
pub use frame_support::{pallet_prelude::Weight, weights::WeightToFee};
pub use pallet_assets;
pub use pallet_balances;
pub use pallet_message_queue;
pub use pallet_xcm;
// Polkadot
pub use xcm::prelude::{AccountId32, WeightLimit};
pub use xcm::{
prelude::{
AccountId32, All, Asset, AssetId, BuyExecution, DepositAsset, ExpectTransactStatus,
Fungible, Here, Location, MaybeErrorCode, OriginKind, RefundSurplus, Transact, Unlimited,
VersionedXcm, WeightLimit, WithdrawAsset, Xcm,
},
v3::Location as V3Location,
};
// Cumulus
pub use asset_test_utils;
pub use cumulus_pallet_xcmp_queue;
pub use parachains_common::AccountId;
pub use xcm_emulator::Chain;
#[macro_export]
@@ -120,102 +130,3 @@ macro_rules! test_parachain_is_trusted_teleporter {
}
};
}
#[macro_export]
macro_rules! include_penpal_create_foreign_asset_on_asset_hub {
( $penpal:ident, $asset_hub:ident, $relay_ed:expr, $weight_to_fee:expr) => {
$crate::impls::paste::paste! {
pub fn penpal_create_foreign_asset_on_asset_hub(
asset_id_on_penpal: u32,
foreign_asset_at_asset_hub: v3::Location,
ah_as_seen_by_penpal: Location,
is_sufficient: bool,
asset_owner: AccountId,
prefund_amount: u128,
) {
use frame_support::weights::WeightToFee;
let ah_check_account = $asset_hub::execute_with(|| {
<$asset_hub as [<$asset_hub Pallet>]>::PolkadotXcm::check_account()
});
let penpal_check_account =
$penpal::execute_with(|| <$penpal as [<$penpal Pallet>]>::PolkadotXcm::check_account());
let penpal_as_seen_by_ah = $asset_hub::sibling_location_of($penpal::para_id());
// prefund SA of Penpal on AssetHub with enough native tokens to pay for creating
// new foreign asset, also prefund CheckingAccount with ED, because teleported asset
// itself might not be sufficient and CheckingAccount cannot be created otherwise
let sov_penpal_on_ah = $asset_hub::sovereign_account_id_of(penpal_as_seen_by_ah.clone());
$asset_hub::fund_accounts(vec![
(sov_penpal_on_ah.clone().into(), $relay_ed * 100_000_000_000),
(ah_check_account.clone().into(), $relay_ed * 1000),
]);
// prefund SA of AssetHub on Penpal with native asset
let sov_ah_on_penpal = $penpal::sovereign_account_id_of(ah_as_seen_by_penpal.clone());
$penpal::fund_accounts(vec![
(sov_ah_on_penpal.into(), $relay_ed * 1_000_000_000),
(penpal_check_account.clone().into(), $relay_ed * 1000),
]);
// Force create asset on $penpal and prefund [<$penpal Sender>]
$penpal::force_create_and_mint_asset(
asset_id_on_penpal,
ASSET_MIN_BALANCE,
is_sufficient,
asset_owner,
None,
prefund_amount,
);
let require_weight_at_most = Weight::from_parts(1_100_000_000_000, 30_000);
// `OriginKind::Xcm` required by ForeignCreators pallet-assets origin filter
let origin_kind = OriginKind::Xcm;
let call_create_foreign_assets =
<$asset_hub as Chain>::RuntimeCall::ForeignAssets(pallet_assets::Call::<
<$asset_hub as Chain>::Runtime,
pallet_assets::Instance2,
>::create {
id: foreign_asset_at_asset_hub,
min_balance: ASSET_MIN_BALANCE,
admin: sov_penpal_on_ah.into(),
})
.encode();
let buy_execution_fee_amount = $weight_to_fee::weight_to_fee(
&Weight::from_parts(10_100_000_000_000, 300_000),
);
let buy_execution_fee = Asset {
id: AssetId(Location { parents: 1, interior: Here }),
fun: Fungible(buy_execution_fee_amount),
};
let xcm = VersionedXcm::from(Xcm(vec![
WithdrawAsset { 0: vec![buy_execution_fee.clone()].into() },
BuyExecution { fees: buy_execution_fee.clone(), weight_limit: Unlimited },
Transact { require_weight_at_most, origin_kind, call: call_create_foreign_assets.into() },
ExpectTransactStatus(MaybeErrorCode::Success),
RefundSurplus,
DepositAsset { assets: All.into(), beneficiary: penpal_as_seen_by_ah },
]));
// Send XCM message from penpal => asset_hub
let sudo_penpal_origin = <$penpal as Chain>::RuntimeOrigin::root();
$penpal::execute_with(|| {
assert_ok!(<$penpal as [<$penpal Pallet>]>::PolkadotXcm::send(
sudo_penpal_origin.clone(),
bx!(ah_as_seen_by_penpal.into()),
bx!(xcm),
));
type RuntimeEvent = <$penpal as Chain>::RuntimeEvent;
assert_expected_events!(
$penpal,
vec![
RuntimeEvent::PolkadotXcm(pallet_xcm::Event::Sent { .. }) => {},
]
);
});
$asset_hub::execute_with(|| {
type ForeignAssets = <$asset_hub as [<$asset_hub Pallet>]>::ForeignAssets;
assert!(ForeignAssets::asset_exists(foreign_asset_at_asset_hub));
});
}
}
};
}
@@ -34,5 +34,6 @@ parachains-common = { path = "../../../../../../parachains/common" }
cumulus-pallet-parachain-system = { path = "../../../../../../pallets/parachain-system", default-features = false }
testnet-parachains-constants = { path = "../../../../../runtimes/constants", features = ["rococo"] }
asset-hub-rococo-runtime = { path = "../../../../../runtimes/assets/asset-hub-rococo" }
penpal-runtime = { path = "../../../../../runtimes/testing/penpal" }
emulated-integration-tests-common = { path = "../../../common", default-features = false }
rococo-system-emulated-network = { path = "../../../networks/rococo-system" }
@@ -13,59 +13,79 @@
// See the License for the specific language governing permissions and
// limitations under the License.
pub use codec::Encode;
#[cfg(test)]
mod imports {
pub use codec::Encode;
// Substrate
pub use frame_support::{
assert_err, assert_ok,
pallet_prelude::Weight,
sp_runtime::{AccountId32, DispatchError, DispatchResult},
traits::fungibles::Inspect,
};
// Substrate
pub use frame_support::{
assert_err, assert_ok,
pallet_prelude::Weight,
sp_runtime::{DispatchError, DispatchResult, ModuleError},
traits::fungibles::Inspect,
};
// Polkadot
pub use xcm::{
prelude::{AccountId32 as AccountId32Junction, *},
v3::{self, Error, NetworkId::Rococo as RococoId},
};
// Polkadot
pub use xcm::{
prelude::{AccountId32 as AccountId32Junction, *},
v3,
};
// Cumulus
pub use asset_test_utils::xcm_helpers;
pub use emulated_integration_tests_common::{
test_parachain_is_trusted_teleporter,
xcm_emulator::{
assert_expected_events, bx, helpers::weight_within_threshold, Chain, Parachain as Para,
RelayChain as Relay, Test, TestArgs, TestContext, TestExt,
},
xcm_helpers::{xcm_transact_paid_execution, xcm_transact_unpaid_execution},
PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3,
};
pub use parachains_common::{AccountId, Balance};
pub use rococo_system_emulated_network::{
asset_hub_rococo_emulated_chain::{
genesis::ED as ASSET_HUB_ROCOCO_ED, AssetHubRococoParaPallet as AssetHubRococoPallet,
},
penpal_emulated_chain::PenpalAParaPallet as PenpalAPallet,
rococo_emulated_chain::{genesis::ED as ROCOCO_ED, RococoRelayPallet as RococoPallet},
AssetHubRococoPara as AssetHubRococo, AssetHubRococoParaReceiver as AssetHubRococoReceiver,
AssetHubRococoParaSender as AssetHubRococoSender, BridgeHubRococoPara as BridgeHubRococo,
BridgeHubRococoParaReceiver as BridgeHubRococoReceiver, PenpalAPara as PenpalA,
PenpalAParaReceiver as PenpalAReceiver, PenpalAParaSender as PenpalASender,
PenpalBPara as PenpalB, PenpalBParaReceiver as PenpalBReceiver, RococoRelay as Rococo,
RococoRelayReceiver as RococoReceiver, RococoRelaySender as RococoSender,
};
// Cumulus
pub use asset_test_utils::xcm_helpers;
pub use emulated_integration_tests_common::{
test_parachain_is_trusted_teleporter,
xcm_emulator::{
assert_expected_events, bx, Chain, Parachain as Para, RelayChain as Relay, Test,
TestArgs, TestContext, TestExt,
},
xcm_helpers::{non_fee_asset, xcm_transact_paid_execution},
ASSETS_PALLET_ID, RESERVABLE_ASSET_ID, XCM_V3,
};
pub use parachains_common::Balance;
pub use rococo_system_emulated_network::{
asset_hub_rococo_emulated_chain::{
genesis::{AssetHubRococoAssetOwner, ED as ASSET_HUB_ROCOCO_ED},
AssetHubRococoParaPallet as AssetHubRococoPallet,
},
penpal_emulated_chain::{
PenpalAParaPallet as PenpalAPallet, PenpalAssetOwner,
PenpalBParaPallet as PenpalBPallet, ED as PENPAL_ED,
},
rococo_emulated_chain::{genesis::ED as ROCOCO_ED, RococoRelayPallet as RococoPallet},
AssetHubRococoPara as AssetHubRococo, AssetHubRococoParaReceiver as AssetHubRococoReceiver,
AssetHubRococoParaSender as AssetHubRococoSender, BridgeHubRococoPara as BridgeHubRococo,
BridgeHubRococoParaReceiver as BridgeHubRococoReceiver, PenpalAPara as PenpalA,
PenpalAParaReceiver as PenpalAReceiver, PenpalAParaSender as PenpalASender,
PenpalBPara as PenpalB, PenpalBParaReceiver as PenpalBReceiver, RococoRelay as Rococo,
RococoRelayReceiver as RococoReceiver, RococoRelaySender as RococoSender,
};
pub const ASSET_ID: u32 = 1;
pub const ASSET_MIN_BALANCE: u128 = 1000;
// `Assets` pallet index
pub const ASSETS_PALLET_ID: u8 = 50;
// Runtimes
pub use asset_hub_rococo_runtime::xcm_config::{
TokenLocation as RelayLocation, UniversalLocation as AssetHubRococoUniversalLocation,
XcmConfig as AssetHubRococoXcmConfig,
};
pub use penpal_runtime::xcm_config::{
LocalReservableFromAssetHub as PenpalLocalReservableFromAssetHub,
LocalTeleportableToAssetHub as PenpalLocalTeleportableToAssetHub,
UniversalLocation as PenpalUniversalLocation, XcmConfig as PenpalRococoXcmConfig,
};
pub use rococo_runtime::xcm_config::{
UniversalLocation as RococoUniversalLocation, XcmConfig as RococoXcmConfig,
};
pub type RelayToSystemParaTest = Test<Rococo, AssetHubRococo>;
pub type RelayToParaTest = Test<Rococo, PenpalA>;
pub type SystemParaToRelayTest = Test<AssetHubRococo, Rococo>;
pub type SystemParaToParaTest = Test<AssetHubRococo, PenpalA>;
pub type ParaToSystemParaTest = Test<PenpalA, AssetHubRococo>;
pub type ParaToParaTest = Test<PenpalA, PenpalB, Rococo>;
pub const ASSET_ID: u32 = 3;
pub const ASSET_MIN_BALANCE: u128 = 1000;
pub type RelayToSystemParaTest = Test<Rococo, AssetHubRococo>;
pub type RelayToParaTest = Test<Rococo, PenpalA>;
pub type ParaToRelayTest = Test<PenpalA, Rococo>;
pub type SystemParaToRelayTest = Test<AssetHubRococo, Rococo>;
pub type SystemParaToParaTest = Test<AssetHubRococo, PenpalA>;
pub type ParaToSystemParaTest = Test<PenpalA, AssetHubRococo>;
pub type ParaToParaThroughRelayTest = Test<PenpalA, PenpalB, Rococo>;
}
#[cfg(test)]
mod tests;
@@ -18,11 +18,3 @@ mod send;
mod set_xcm_versions;
mod swap;
mod teleport;
use crate::*;
emulated_integration_tests_common::include_penpal_create_foreign_asset_on_asset_hub!(
PenpalA,
AssetHubRococo,
ROCOCO_ED,
testnet_parachains_constants::rococo::fee::WeightToFee
);
@@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::*;
use crate::imports::*;
/// Relay Chain should be able to execute `Transact` instructions in System Parachain
/// when `OriginKind::Superuser`.
@@ -28,47 +28,52 @@ fn send_transact_as_superuser_from_relay_to_system_para_works() {
)
}
/// Parachain should be able to send XCM paying its fee with sufficient asset
/// in the System Parachain
/// We tests two things here:
/// - Parachain should be able to send XCM paying its fee with system asset in the System Parachain
/// - Parachain should be able to create a new Foreign Asset in the System Parachain
#[test]
fn send_xcm_from_para_to_system_para_paying_fee_with_assets_works() {
fn send_xcm_from_para_to_system_para_paying_fee_with_system_assets_works() {
let para_sovereign_account = AssetHubRococo::sovereign_account_id_of(
AssetHubRococo::sibling_location_of(PenpalA::para_id()),
);
let asset_location_on_penpal = v3::Location::new(
0,
[
v3::Junction::PalletInstance(ASSETS_PALLET_ID),
v3::Junction::GeneralIndex(ASSET_ID.into()),
],
);
let foreign_asset_at_asset_hub =
v3::Location::new(1, [v3::Junction::Parachain(PenpalA::para_id().into())])
.appended_with(asset_location_on_penpal)
.unwrap();
// Force create and mint assets for Parachain's sovereign account
AssetHubRococo::force_create_and_mint_asset(
ASSET_ID,
// Encoded `create_asset` call to be executed in AssetHub
let call = AssetHubRococo::create_foreign_asset_call(
foreign_asset_at_asset_hub,
ASSET_MIN_BALANCE,
true,
para_sovereign_account.clone(),
Some(Weight::from_parts(1_019_445_000, 200_000)),
ASSET_MIN_BALANCE * 1000000000,
);
// We just need a call that can pass the `SafeCallFilter`
// Call values are not relevant
let call = AssetHubRococo::force_create_asset_call(
ASSET_ID,
para_sovereign_account.clone(),
true,
ASSET_MIN_BALANCE,
);
let origin_kind = OriginKind::SovereignAccount;
let fee_amount = ASSET_MIN_BALANCE * 1000000;
let native_asset =
([PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())], fee_amount).into();
let origin_kind = OriginKind::Xcm;
let fee_amount = ASSET_HUB_ROCOCO_ED * 1000000;
let system_asset = (Parent, fee_amount).into();
let root_origin = <PenpalA as Chain>::RuntimeOrigin::root();
let system_para_destination = PenpalA::sibling_location_of(AssetHubRococo::para_id()).into();
let xcm = xcm_transact_paid_execution(
call,
origin_kind,
native_asset,
system_asset,
para_sovereign_account.clone(),
);
// SA-of-Penpal-on-AHR needs to have balance to pay for fees and asset creation deposit
AssetHubRococo::fund_accounts(vec![(
para_sovereign_account.clone().into(),
ASSET_HUB_ROCOCO_ED * 10000000000,
)]);
PenpalA::execute_with(|| {
assert_ok!(<PenpalA as PenpalAPallet>::PolkadotXcm::send(
root_origin,
@@ -90,13 +95,101 @@ fn send_xcm_from_para_to_system_para_paying_fee_with_assets_works() {
assert_expected_events!(
AssetHubRococo,
vec![
// Burned the fee
RuntimeEvent::Balances(pallet_balances::Event::Burned { who, amount }) => {
who: *who == para_sovereign_account,
amount: *amount == fee_amount,
},
// Foreign Asset created
RuntimeEvent::ForeignAssets(pallet_assets::Event::Created { asset_id, creator, owner }) => {
asset_id: *asset_id == foreign_asset_at_asset_hub,
creator: *creator == para_sovereign_account.clone(),
owner: *owner == para_sovereign_account,
},
]
);
type ForeignAssets = <AssetHubRococo as AssetHubRococoPallet>::ForeignAssets;
assert!(ForeignAssets::asset_exists(foreign_asset_at_asset_hub));
});
}
/// We tests two things here:
/// - Parachain should be able to send XCM paying its fee with system assets in the System Parachain
/// - Parachain should be able to create a new Asset in the System Parachain
#[test]
fn send_xcm_from_para_to_system_para_paying_fee_with_assets_works() {
let para_sovereign_account = AssetHubRococo::sovereign_account_id_of(
AssetHubRococo::sibling_location_of(PenpalA::para_id()),
);
// Force create and mint assets for Parachain's sovereign account
AssetHubRococo::force_create_and_mint_asset(
ASSET_ID,
ASSET_MIN_BALANCE,
true,
para_sovereign_account.clone(),
Some(Weight::from_parts(1_019_445_000, 200_000)),
ASSET_MIN_BALANCE * 1000000000,
);
// Just a different `asset_id`` that does not exist yet
let new_asset_id = ASSET_ID + 1;
// Encoded `create_asset` call to be executed in AssetHub
let call = AssetHubRococo::create_asset_call(
new_asset_id,
ASSET_MIN_BALANCE,
para_sovereign_account.clone(),
);
let origin_kind = OriginKind::SovereignAccount;
let fee_amount = ASSET_MIN_BALANCE * 1000000;
let asset =
([PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())], fee_amount).into();
let root_origin = <PenpalA as Chain>::RuntimeOrigin::root();
let system_para_destination = PenpalA::sibling_location_of(AssetHubRococo::para_id()).into();
let xcm = xcm_transact_paid_execution(call, origin_kind, asset, para_sovereign_account.clone());
// SA-of-Penpal-on-AHR needs to have balance to pay for asset creation deposit
AssetHubRococo::fund_accounts(vec![(
para_sovereign_account.clone().into(),
ASSET_HUB_ROCOCO_ED * 10000000000,
)]);
PenpalA::execute_with(|| {
assert_ok!(<PenpalA as PenpalAPallet>::PolkadotXcm::send(
root_origin,
bx!(system_para_destination),
bx!(xcm),
));
PenpalA::assert_xcm_pallet_sent();
});
AssetHubRococo::execute_with(|| {
type RuntimeEvent = <AssetHubRococo as Chain>::RuntimeEvent;
AssetHubRococo::assert_xcmp_queue_success(Some(Weight::from_parts(
15_594_564_000,
562_893,
)));
assert_expected_events!(
AssetHubRococo,
vec![
// Burned the fee
RuntimeEvent::Assets(pallet_assets::Event::Burned { asset_id, owner, balance }) => {
asset_id: *asset_id == ASSET_ID,
owner: *owner == para_sovereign_account,
balance: *balance == fee_amount,
},
RuntimeEvent::Assets(pallet_assets::Event::Issued { asset_id, .. }) => {
asset_id: *asset_id == ASSET_ID,
// Asset created
RuntimeEvent::Assets(pallet_assets::Event::Created { asset_id, creator, owner }) => {
asset_id: *asset_id == new_asset_id,
creator: *creator == para_sovereign_account.clone(),
owner: *owner == para_sovereign_account,
},
]
);
@@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::*;
use crate::imports::*;
#[test]
fn relay_sets_system_para_xcm_supported_version() {
@@ -13,9 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::*;
use rococo_system_emulated_network::penpal_emulated_chain::LocalTeleportableToAssetHubV3 as PenpalLocalTeleportableToAssetHubV3;
use sp_runtime::ModuleError;
use crate::imports::*;
#[test]
fn swap_locally_on_chain_using_local_assets() {
@@ -114,49 +112,39 @@ fn swap_locally_on_chain_using_local_assets() {
#[test]
fn swap_locally_on_chain_using_foreign_assets() {
let asset_native = Box::new(asset_hub_rococo_runtime::xcm_config::TokenLocationV3::get());
let ah_as_seen_by_penpal = PenpalA::sibling_location_of(AssetHubRococo::para_id());
let asset_location_on_penpal = PenpalLocalTeleportableToAssetHubV3::get();
let asset_id_on_penpal = match asset_location_on_penpal.last() {
Some(v3::Junction::GeneralIndex(id)) => *id as u32,
_ => unreachable!(),
};
let asset_owner_on_penpal = PenpalASender::get();
let asset_native =
Box::new(v3::Location::try_from(RelayLocation::get()).expect("conversion works"));
let asset_location_on_penpal =
v3::Location::try_from(PenpalLocalTeleportableToAssetHub::get()).expect("conversion works");
let foreign_asset_at_asset_hub_rococo =
v3::Location::new(1, [v3::Junction::Parachain(PenpalA::para_id().into())])
.appended_with(asset_location_on_penpal)
.unwrap();
// 1. Create asset on penpal and, 2. Create foreign asset on asset_hub_rococo
super::penpal_create_foreign_asset_on_asset_hub(
asset_id_on_penpal,
foreign_asset_at_asset_hub_rococo,
ah_as_seen_by_penpal,
true,
asset_owner_on_penpal,
ASSET_MIN_BALANCE * 1_000_000,
);
let penpal_as_seen_by_ah = AssetHubRococo::sibling_location_of(PenpalA::para_id());
let sov_penpal_on_ahr = AssetHubRococo::sovereign_account_id_of(penpal_as_seen_by_ah);
AssetHubRococo::fund_accounts(vec![
(AssetHubRococoSender::get().into(), 5_000_000 * ROCOCO_ED), /* An account to swap dot
* for something else. */
// An account to swap dot for something else.
(AssetHubRococoSender::get().into(), 5_000_000 * ASSET_HUB_ROCOCO_ED),
// Penpal's sovereign account in AH should have some balance
(sov_penpal_on_ahr.clone().into(), 100_000_000 * ASSET_HUB_ROCOCO_ED),
]);
AssetHubRococo::execute_with(|| {
// 3: Mint foreign asset on asset_hub_rococo:
// 0: No need to create foreign asset as it exists in genesis.
//
// 1: Mint foreign asset on asset_hub_rococo:
//
// (While it might be nice to use batch,
// currently that's disabled due to safe call filters.)
type RuntimeEvent = <AssetHubRococo as Chain>::RuntimeEvent;
// 3. Mint foreign asset (in reality this should be a teleport or some such)
// 1. Mint foreign asset (in reality this should be a teleport or some such)
assert_ok!(<AssetHubRococo as AssetHubRococoPallet>::ForeignAssets::mint(
<AssetHubRococo as Chain>::RuntimeOrigin::signed(sov_penpal_on_ahr.clone().into()),
foreign_asset_at_asset_hub_rococo,
sov_penpal_on_ahr.clone().into(),
3_000_000_000_000,
ASSET_HUB_ROCOCO_ED * 3_000_000_000_000,
));
assert_expected_events!(
@@ -166,7 +154,7 @@ fn swap_locally_on_chain_using_foreign_assets() {
]
);
// 4. Create pool:
// 2. Create pool:
assert_ok!(<AssetHubRococo as AssetHubRococoPallet>::AssetConversion::create_pool(
<AssetHubRococo as Chain>::RuntimeOrigin::signed(AssetHubRococoSender::get()),
asset_native.clone(),
@@ -180,7 +168,7 @@ fn swap_locally_on_chain_using_foreign_assets() {
]
);
// 5. Add liquidity:
// 3. Add liquidity:
assert_ok!(<AssetHubRococo as AssetHubRococoPallet>::AssetConversion::add_liquidity(
<AssetHubRococo as Chain>::RuntimeOrigin::signed(sov_penpal_on_ahr.clone()),
asset_native.clone(),
@@ -201,15 +189,15 @@ fn swap_locally_on_chain_using_foreign_assets() {
]
);
// 6. Swap!
// 4. Swap!
let path = vec![asset_native.clone(), Box::new(foreign_asset_at_asset_hub_rococo)];
assert_ok!(
<AssetHubRococo as AssetHubRococoPallet>::AssetConversion::swap_exact_tokens_for_tokens(
<AssetHubRococo as Chain>::RuntimeOrigin::signed(AssetHubRococoSender::get()),
path,
100000,
1000,
100000 * ASSET_HUB_ROCOCO_ED,
1000 * ASSET_HUB_ROCOCO_ED,
AssetHubRococoSender::get().into(),
true
)
@@ -219,18 +207,18 @@ fn swap_locally_on_chain_using_foreign_assets() {
AssetHubRococo,
vec![
RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::SwapExecuted { amount_in, amount_out, .. },) => {
amount_in: *amount_in == 100000,
amount_out: *amount_out == 199399,
amount_in: *amount_in == 333333300000,
amount_out: *amount_out == 498874118173,
},
]
);
// 7. Remove liquidity
// 5. Remove liquidity
assert_ok!(<AssetHubRococo as AssetHubRococoPallet>::AssetConversion::remove_liquidity(
<AssetHubRococo as Chain>::RuntimeOrigin::signed(sov_penpal_on_ahr.clone()),
asset_native.clone(),
Box::new(foreign_asset_at_asset_hub_rococo),
1414213562273 - 2_000_000_000, // all but the 2 EDs can't be retrieved.
1414213562273 - ASSET_HUB_ROCOCO_ED * 2, // all but the 2 EDs can't be retrieved.
0,
0,
sov_penpal_on_ahr.clone().into(),
@@ -13,11 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::*;
use asset_hub_rococo_runtime::xcm_config::XcmConfig as AssetHubRococoXcmConfig;
use emulated_integration_tests_common::xcm_helpers::non_fee_asset;
use rococo_runtime::xcm_config::XcmConfig as RococoXcmConfig;
use rococo_system_emulated_network::penpal_emulated_chain::LocalTeleportableToAssetHubV3 as PenpalLocalTeleportableToAssetHubV3;
use crate::imports::*;
fn relay_origin_assertions(t: RelayToSystemParaTest) {
type RuntimeEvent = <Rococo as Chain>::RuntimeEvent;
@@ -114,18 +110,21 @@ fn para_dest_assertions(t: RelayToSystemParaTest) {
fn penpal_to_ah_foreign_assets_sender_assertions(t: ParaToSystemParaTest) {
type RuntimeEvent = <PenpalA as Chain>::RuntimeEvent;
PenpalA::assert_xcm_pallet_attempted_complete(None);
let system_para_native_asset_location =
v3::Location::try_from(RelayLocation::get()).expect("conversion works");
let expected_asset_id = t.args.asset_id.unwrap();
let (_, expected_asset_amount) =
non_fee_asset(&t.args.assets, t.args.fee_asset_item as usize).unwrap();
PenpalA::assert_xcm_pallet_attempted_complete(None);
assert_expected_events!(
PenpalA,
vec![
RuntimeEvent::Balances(
pallet_balances::Event::Burned { who, amount }
RuntimeEvent::ForeignAssets(
pallet_assets::Event::Burned { asset_id, owner, .. }
) => {
who: *who == t.sender.account_id,
amount: *amount == t.args.amount,
asset_id: *asset_id == system_para_native_asset_location,
owner: *owner == t.sender.account_id,
},
RuntimeEvent::Assets(pallet_assets::Event::Burned { asset_id, owner, balance }) => {
asset_id: *asset_id == expected_asset_id,
@@ -144,6 +143,9 @@ fn penpal_to_ah_foreign_assets_receiver_assertions(t: ParaToSystemParaTest) {
let (expected_foreign_asset_id, expected_foreign_asset_amount) =
non_fee_asset(&t.args.assets, t.args.fee_asset_item as usize).unwrap();
let expected_foreign_asset_id_v3: v3::Location = expected_foreign_asset_id.try_into().unwrap();
AssetHubRococo::assert_xcmp_queue_success(None);
assert_expected_events!(
AssetHubRococo,
vec![
@@ -163,9 +165,6 @@ fn penpal_to_ah_foreign_assets_receiver_assertions(t: ParaToSystemParaTest) {
amount: *amount == expected_foreign_asset_amount,
},
RuntimeEvent::Balances(pallet_balances::Event::Deposit { .. }) => {},
RuntimeEvent::MessageQueue(
pallet_message_queue::Event::Processed { success: true, .. }
) => {},
]
);
}
@@ -205,6 +204,11 @@ fn ah_to_penpal_foreign_assets_receiver_assertions(t: SystemParaToParaTest) {
let (_, expected_asset_amount) =
non_fee_asset(&t.args.assets, t.args.fee_asset_item as usize).unwrap();
let checking_account = <PenpalA as PenpalAPallet>::PolkadotXcm::check_account();
let system_para_native_asset_location =
v3::Location::try_from(RelayLocation::get()).expect("conversion works");
PenpalA::assert_xcmp_queue_success(None);
assert_expected_events!(
PenpalA,
vec![
@@ -221,12 +225,11 @@ fn ah_to_penpal_foreign_assets_receiver_assertions(t: SystemParaToParaTest) {
amount: *amount == expected_asset_amount,
},
// native asset for fee is deposited to receiver
RuntimeEvent::Balances(pallet_balances::Event::Minted { who, .. }) => {
who: *who == t.receiver.account_id,
RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { asset_id, owner, amount }) => {
asset_id: *asset_id == system_para_native_asset_location,
owner: *owner == t.receiver.account_id,
amount: *amount == expected_asset_amount,
},
RuntimeEvent::MessageQueue(
pallet_message_queue::Event::Processed { success: true, .. }
) => {},
]
);
}
@@ -558,30 +561,21 @@ fn teleport_to_other_system_parachains_works() {
/// (using native reserve-based transfer for fees)
#[test]
fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() {
let ah_as_seen_by_penpal = PenpalA::sibling_location_of(AssetHubRococo::para_id());
let asset_location_on_penpal = PenpalLocalTeleportableToAssetHubV3::get();
// Init values for Parachain
let fee_amount_to_send: Balance = ASSET_HUB_ROCOCO_ED * 10000;
let asset_location_on_penpal =
v3::Location::try_from(PenpalLocalTeleportableToAssetHub::get()).expect("conversion works");
let asset_id_on_penpal = match asset_location_on_penpal.last() {
Some(v3::Junction::GeneralIndex(id)) => *id as u32,
_ => unreachable!(),
};
let asset_owner_on_penpal = PenpalASender::get();
let foreign_asset_at_asset_hub_rococo =
v3::Location::new(1, [v3::Junction::Parachain(PenpalA::para_id().into())])
.appended_with(asset_location_on_penpal)
.unwrap();
super::penpal_create_foreign_asset_on_asset_hub(
asset_id_on_penpal,
foreign_asset_at_asset_hub_rococo,
ah_as_seen_by_penpal.clone(),
false,
asset_owner_on_penpal,
ASSET_MIN_BALANCE * 1_000_000,
);
let penpal_to_ah_beneficiary_id = AssetHubRococoReceiver::get();
let fee_amount_to_send = ASSET_HUB_ROCOCO_ED * 10_000;
let asset_amount_to_send = ASSET_MIN_BALANCE * 1000;
let asset_amount_to_send = ASSET_HUB_ROCOCO_ED * 1000;
let asset_owner = PenpalAssetOwner::get();
let system_para_native_asset_location =
v3::Location::try_from(RelayLocation::get()).expect("conversion works");
let sender = PenpalASender::get();
let penpal_check_account = <PenpalA as PenpalAPallet>::PolkadotXcm::check_account();
let ah_as_seen_by_penpal = PenpalA::sibling_location_of(AssetHubRococo::para_id());
let asset_location_on_penpal_latest: Location = asset_location_on_penpal.try_into().unwrap();
let penpal_assets: Assets = vec![
(Parent, fee_amount_to_send).into(),
@@ -594,6 +588,38 @@ fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() {
.position(|r| r == &(Parent, fee_amount_to_send).into())
.unwrap() as u32;
// fund Parachain's sender account
PenpalA::mint_foreign_asset(
<PenpalA as Chain>::RuntimeOrigin::signed(asset_owner.clone()),
system_para_native_asset_location,
sender.clone(),
fee_amount_to_send,
);
// No need to create the asset (only mint) as it exists in genesis.
PenpalA::mint_asset(
<PenpalA as Chain>::RuntimeOrigin::signed(asset_owner.clone()),
asset_id_on_penpal,
sender.clone(),
asset_amount_to_send,
);
// fund Parachain's check account to be able to teleport
PenpalA::fund_accounts(vec![(penpal_check_account.clone().into(), ASSET_HUB_ROCOCO_ED * 1000)]);
// prefund SA of Penpal on AssetHub with enough native tokens to pay for fees
let penpal_as_seen_by_ah = AssetHubRococo::sibling_location_of(PenpalA::para_id());
let sov_penpal_on_ah = AssetHubRococo::sovereign_account_id_of(penpal_as_seen_by_ah);
AssetHubRococo::fund_accounts(vec![(
sov_penpal_on_ah.clone().into(),
ASSET_HUB_ROCOCO_ED * 100_000_000_000,
)]);
// Init values for System Parachain
let foreign_asset_at_asset_hub_rococo =
v3::Location::new(1, [v3::Junction::Parachain(PenpalA::para_id().into())])
.appended_with(asset_location_on_penpal)
.unwrap();
let penpal_to_ah_beneficiary_id = AssetHubRococoReceiver::get();
// Penpal to AH test args
let penpal_to_ah_test_args = TestContext {
sender: PenpalASender::get(),
@@ -608,8 +634,14 @@ fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() {
),
};
let mut penpal_to_ah = ParaToSystemParaTest::new(penpal_to_ah_test_args);
let penpal_sender_balance_before = PenpalA::execute_with(|| {
type ForeignAssets = <PenpalA as PenpalAPallet>::ForeignAssets;
<ForeignAssets as Inspect<_>>::balance(
system_para_native_asset_location,
&PenpalASender::get(),
)
});
let penpal_sender_balance_before = penpal_to_ah.sender.balance;
let ah_receiver_balance_before = penpal_to_ah.receiver.balance;
let penpal_sender_assets_before = PenpalA::execute_with(|| {
@@ -629,7 +661,14 @@ fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() {
penpal_to_ah.set_dispatchable::<PenpalA>(para_to_system_para_transfer_assets);
penpal_to_ah.assert();
let penpal_sender_balance_after = penpal_to_ah.sender.balance;
let penpal_sender_balance_after = PenpalA::execute_with(|| {
type ForeignAssets = <PenpalA as PenpalAPallet>::ForeignAssets;
<ForeignAssets as Inspect<_>>::balance(
system_para_native_asset_location,
&PenpalASender::get(),
)
});
let ah_receiver_balance_after = penpal_to_ah.receiver.balance;
let penpal_sender_assets_after = PenpalA::execute_with(|| {
@@ -704,7 +743,13 @@ fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() {
let mut ah_to_penpal = SystemParaToParaTest::new(ah_to_penpal_test_args);
let ah_sender_balance_before = ah_to_penpal.sender.balance;
let penpal_receiver_balance_before = ah_to_penpal.receiver.balance;
let penpal_receiver_balance_before = PenpalA::execute_with(|| {
type ForeignAssets = <PenpalA as PenpalAPallet>::ForeignAssets;
<ForeignAssets as Inspect<_>>::balance(
system_para_native_asset_location,
&PenpalAReceiver::get(),
)
});
let ah_sender_assets_before = AssetHubRococo::execute_with(|| {
type ForeignAssets = <AssetHubRococo as AssetHubRococoPallet>::ForeignAssets;
@@ -724,7 +769,13 @@ fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() {
ah_to_penpal.assert();
let ah_sender_balance_after = ah_to_penpal.sender.balance;
let penpal_receiver_balance_after = ah_to_penpal.receiver.balance;
let penpal_receiver_balance_after = PenpalA::execute_with(|| {
type ForeignAssets = <PenpalA as PenpalAPallet>::ForeignAssets;
<ForeignAssets as Inspect<_>>::balance(
system_para_native_asset_location,
&PenpalAReceiver::get(),
)
});
let ah_sender_assets_after = AssetHubRococo::execute_with(|| {
type ForeignAssets = <AssetHubRococo as AssetHubRococoPallet>::ForeignAssets;
@@ -33,6 +33,7 @@ westend-runtime = { path = "../../../../../../../polkadot/runtime/westend" }
# Cumulus
parachains-common = { path = "../../../../../../parachains/common" }
testnet-parachains-constants = { path = "../../../../../runtimes/constants", features = ["westend"] }
penpal-runtime = { path = "../../../../../runtimes/testing/penpal" }
asset-hub-westend-runtime = { path = "../../../../../runtimes/assets/asset-hub-westend" }
asset-test-utils = { path = "../../../../../runtimes/assets/test-utils" }
cumulus-pallet-xcmp-queue = { default-features = false, path = "../../../../../../pallets/xcmp-queue" }
@@ -13,67 +13,83 @@
// See the License for the specific language governing permissions and
// limitations under the License.
pub use codec::Encode;
#[cfg(test)]
mod imports {
pub use codec::Encode;
// Substrate
pub use frame_support::{
assert_err, assert_ok,
instances::Instance2,
pallet_prelude::Weight,
sp_runtime::{AccountId32, DispatchError, DispatchResult, ModuleError},
traits::fungibles::Inspect,
BoundedVec,
};
// Substrate
pub use frame_support::{
assert_err, assert_ok,
pallet_prelude::Weight,
sp_runtime::{DispatchError, DispatchResult, ModuleError},
traits::fungibles::Inspect,
};
// Polkadot
pub use xcm::{
prelude::{AccountId32 as AccountId32Junction, *},
v3::{self, Error, NetworkId::Westend as WestendId},
};
// Polkadot
pub use xcm::{
prelude::{AccountId32 as AccountId32Junction, *},
v3,
};
// Cumulus
pub use asset_test_utils::xcm_helpers;
pub use emulated_integration_tests_common::{
test_parachain_is_trusted_teleporter,
xcm_emulator::{
assert_expected_events, bx, helpers::weight_within_threshold, Chain, Parachain as Para,
RelayChain as Relay, Test, TestArgs, TestContext, TestExt,
},
xcm_helpers::{xcm_transact_paid_execution, xcm_transact_unpaid_execution},
PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3,
};
pub use parachains_common::{AccountId, Balance};
pub use westend_system_emulated_network::{
asset_hub_westend_emulated_chain::{
genesis::ED as ASSET_HUB_WESTEND_ED, AssetHubWestendParaPallet as AssetHubWestendPallet,
},
collectives_westend_emulated_chain::{
genesis::ED as COLLECTIVES_WESTEND_ED,
CollectivesWestendParaPallet as CollectivesWestendPallet,
},
penpal_emulated_chain::PenpalBParaPallet as PenpalBPallet,
westend_emulated_chain::{genesis::ED as WESTEND_ED, WestendRelayPallet as WestendPallet},
AssetHubWestendPara as AssetHubWestend, AssetHubWestendParaReceiver as AssetHubWestendReceiver,
AssetHubWestendParaSender as AssetHubWestendSender, BridgeHubWestendPara as BridgeHubWestend,
BridgeHubWestendParaReceiver as BridgeHubWestendReceiver,
CollectivesWestendPara as CollectivesWestend, PenpalAPara as PenpalA,
PenpalAParaReceiver as PenpalAReceiver, PenpalBPara as PenpalB,
PenpalBParaReceiver as PenpalBReceiver, PenpalBParaSender as PenpalBSender,
WestendRelay as Westend, WestendRelayReceiver as WestendReceiver,
WestendRelaySender as WestendSender,
};
// Cumulus
pub use asset_test_utils::xcm_helpers;
pub use emulated_integration_tests_common::{
test_parachain_is_trusted_teleporter,
xcm_emulator::{
assert_expected_events, bx, Chain, Parachain as Para, RelayChain as Relay, Test,
TestArgs, TestContext, TestExt,
},
xcm_helpers::{non_fee_asset, xcm_transact_paid_execution},
ASSETS_PALLET_ID, RESERVABLE_ASSET_ID, XCM_V3,
};
pub use parachains_common::{AccountId, Balance};
pub use westend_system_emulated_network::{
asset_hub_westend_emulated_chain::{
genesis::{AssetHubWestendAssetOwner, ED as ASSET_HUB_WESTEND_ED},
AssetHubWestendParaPallet as AssetHubWestendPallet,
},
collectives_westend_emulated_chain::CollectivesWestendParaPallet as CollectivesWestendPallet,
penpal_emulated_chain::{
PenpalAParaPallet as PenpalAPallet, PenpalAssetOwner,
PenpalBParaPallet as PenpalBPallet,
},
westend_emulated_chain::{genesis::ED as WESTEND_ED, WestendRelayPallet as WestendPallet},
AssetHubWestendPara as AssetHubWestend,
AssetHubWestendParaReceiver as AssetHubWestendReceiver,
AssetHubWestendParaSender as AssetHubWestendSender,
BridgeHubWestendPara as BridgeHubWestend,
BridgeHubWestendParaReceiver as BridgeHubWestendReceiver,
CollectivesWestendPara as CollectivesWestend, PenpalAPara as PenpalA,
PenpalAParaReceiver as PenpalAReceiver, PenpalAParaSender as PenpalASender,
PenpalBPara as PenpalB, PenpalBParaReceiver as PenpalBReceiver, WestendRelay as Westend,
WestendRelayReceiver as WestendReceiver, WestendRelaySender as WestendSender,
};
pub const ASSET_ID: u32 = 1;
pub const ASSET_MIN_BALANCE: u128 = 1000;
// `Assets` pallet index
pub const ASSETS_PALLET_ID: u8 = 50;
// Runtimes
pub use asset_hub_westend_runtime::xcm_config::{
UniversalLocation as AssetHubWestendUniversalLocation, WestendLocation as RelayLocation,
XcmConfig as AssetHubWestendXcmConfig,
};
pub use penpal_runtime::xcm_config::{
LocalReservableFromAssetHub as PenpalLocalReservableFromAssetHub,
LocalTeleportableToAssetHub as PenpalLocalTeleportableToAssetHub,
UniversalLocation as PenpalUniversalLocation, XcmConfig as PenpalWestendXcmConfig,
};
pub use westend_runtime::xcm_config::{
UniversalLocation as WestendUniversalLocation, XcmConfig as WestendXcmConfig,
};
pub type RelayToSystemParaTest = Test<Westend, AssetHubWestend>;
pub type RelayToParaTest = Test<Westend, PenpalB>;
pub type SystemParaToRelayTest = Test<AssetHubWestend, Westend>;
pub type SystemParaToParaTest = Test<AssetHubWestend, PenpalB>;
pub type ParaToSystemParaTest = Test<PenpalB, AssetHubWestend>;
pub type ParaToParaTest = Test<PenpalB, PenpalA, Westend>;
pub const ASSET_ID: u32 = 3;
pub const ASSET_MIN_BALANCE: u128 = 1000;
pub type RelayToSystemParaTest = Test<Westend, AssetHubWestend>;
pub type RelayToParaTest = Test<Westend, PenpalA>;
pub type ParaToRelayTest = Test<PenpalA, Westend>;
pub type SystemParaToRelayTest = Test<AssetHubWestend, Westend>;
pub type SystemParaToParaTest = Test<AssetHubWestend, PenpalA>;
pub type ParaToSystemParaTest = Test<PenpalA, AssetHubWestend>;
pub type ParaToParaThroughRelayTest = Test<PenpalA, PenpalB, Westend>;
}
#[cfg(test)]
mod tests;
@@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::*;
use crate::imports::*;
use emulated_integration_tests_common::accounts::{ALICE, BOB};
use frame_support::traits::fungibles::{Create, Inspect, Mutate};
use polkadot_runtime_common::impls::VersionedLocatableAsset;
@@ -20,11 +20,3 @@ mod set_xcm_versions;
mod swap;
mod teleport;
mod treasury;
use crate::*;
emulated_integration_tests_common::include_penpal_create_foreign_asset_on_asset_hub!(
PenpalB,
AssetHubWestend,
WESTEND_ED,
testnet_parachains_constants::westend::fee::WeightToFee
);
@@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::*;
use crate::imports::*;
/// Relay Chain should be able to execute `Transact` instructions in System Parachain
/// when `OriginKind::Superuser`.
@@ -28,12 +28,99 @@ fn send_transact_as_superuser_from_relay_to_system_para_works() {
)
}
/// Parachain should be able to send XCM paying its fee with sufficient asset
/// in the System Parachain
/// We tests two things here:
/// - Parachain should be able to send XCM paying its fee with system asset in the System Parachain
/// - Parachain should be able to create a new Foreign Asset in the System Parachain
#[test]
fn send_xcm_from_para_to_system_para_paying_fee_with_system_assets_works() {
let para_sovereign_account = AssetHubWestend::sovereign_account_id_of(
AssetHubWestend::sibling_location_of(PenpalA::para_id()),
);
let asset_location_on_penpal = v3::Location::new(
0,
[
v3::Junction::PalletInstance(ASSETS_PALLET_ID),
v3::Junction::GeneralIndex(ASSET_ID.into()),
],
);
let foreign_asset_at_asset_hub =
v3::Location::new(1, [v3::Junction::Parachain(PenpalA::para_id().into())])
.appended_with(asset_location_on_penpal)
.unwrap();
// Encoded `create_asset` call to be executed in AssetHub
let call = AssetHubWestend::create_foreign_asset_call(
foreign_asset_at_asset_hub,
ASSET_MIN_BALANCE,
para_sovereign_account.clone(),
);
let origin_kind = OriginKind::Xcm;
let fee_amount = ASSET_HUB_WESTEND_ED * 1000000;
let system_asset = (Parent, fee_amount).into();
let root_origin = <PenpalA as Chain>::RuntimeOrigin::root();
let system_para_destination = PenpalA::sibling_location_of(AssetHubWestend::para_id()).into();
let xcm = xcm_transact_paid_execution(
call,
origin_kind,
system_asset,
para_sovereign_account.clone(),
);
// SA-of-Penpal-on-AHR needs to have balance to pay for fees and asset creation deposit
AssetHubWestend::fund_accounts(vec![(
para_sovereign_account.clone().into(),
ASSET_HUB_WESTEND_ED * 10000000000,
)]);
PenpalA::execute_with(|| {
assert_ok!(<PenpalA as PenpalAPallet>::PolkadotXcm::send(
root_origin,
bx!(system_para_destination),
bx!(xcm),
));
PenpalA::assert_xcm_pallet_sent();
});
AssetHubWestend::execute_with(|| {
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
AssetHubWestend::assert_xcmp_queue_success(Some(Weight::from_parts(
15_594_564_000,
562_893,
)));
assert_expected_events!(
AssetHubWestend,
vec![
// Burned the fee
RuntimeEvent::Balances(pallet_balances::Event::Burned { who, amount }) => {
who: *who == para_sovereign_account,
amount: *amount == fee_amount,
},
// Foreign Asset created
RuntimeEvent::ForeignAssets(pallet_assets::Event::Created { asset_id, creator, owner }) => {
asset_id: *asset_id == foreign_asset_at_asset_hub,
creator: *creator == para_sovereign_account.clone(),
owner: *owner == para_sovereign_account,
},
]
);
type ForeignAssets = <AssetHubWestend as AssetHubWestendPallet>::ForeignAssets;
assert!(ForeignAssets::asset_exists(foreign_asset_at_asset_hub));
});
}
/// We tests two things here:
/// - Parachain should be able to send XCM paying its fee with system assets in the System Parachain
/// - Parachain should be able to create a new Asset in the System Parachain
#[test]
fn send_xcm_from_para_to_system_para_paying_fee_with_assets_works() {
let para_sovereign_account = AssetHubWestend::sovereign_account_id_of(
AssetHubWestend::sibling_location_of(PenpalB::para_id()),
AssetHubWestend::sibling_location_of(PenpalA::para_id()),
);
// Force create and mint assets for Parachain's sovereign account
@@ -46,57 +133,63 @@ fn send_xcm_from_para_to_system_para_paying_fee_with_assets_works() {
ASSET_MIN_BALANCE * 1000000000,
);
// We just need a call that can pass the `SafeCallFilter`
// Call values are not relevant
let call = AssetHubWestend::force_create_asset_call(
ASSET_ID,
para_sovereign_account.clone(),
true,
// Just a different `asset_id`` that does not exist yet
let new_asset_id = ASSET_ID + 1;
// Encoded `create_asset` call to be executed in AssetHub
let call = AssetHubWestend::create_asset_call(
new_asset_id,
ASSET_MIN_BALANCE,
para_sovereign_account.clone(),
);
let origin_kind = OriginKind::SovereignAccount;
let fee_amount = ASSET_MIN_BALANCE * 1000000;
let native_asset =
let asset =
([PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())], fee_amount).into();
let root_origin = <PenpalB as Chain>::RuntimeOrigin::root();
let system_para_destination = PenpalB::sibling_location_of(AssetHubWestend::para_id()).into();
let xcm = xcm_transact_paid_execution(
call,
origin_kind,
native_asset,
para_sovereign_account.clone(),
);
let root_origin = <PenpalA as Chain>::RuntimeOrigin::root();
let system_para_destination = PenpalA::sibling_location_of(AssetHubWestend::para_id()).into();
let xcm = xcm_transact_paid_execution(call, origin_kind, asset, para_sovereign_account.clone());
PenpalB::execute_with(|| {
assert_ok!(<PenpalB as PenpalBPallet>::PolkadotXcm::send(
// SA-of-Penpal-on-AHR needs to have balance to pay for asset creation deposit
AssetHubWestend::fund_accounts(vec![(
para_sovereign_account.clone().into(),
ASSET_HUB_WESTEND_ED * 10000000000,
)]);
PenpalA::execute_with(|| {
assert_ok!(<PenpalA as PenpalAPallet>::PolkadotXcm::send(
root_origin,
bx!(system_para_destination),
bx!(xcm),
));
PenpalB::assert_xcm_pallet_sent();
PenpalA::assert_xcm_pallet_sent();
});
AssetHubWestend::execute_with(|| {
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
AssetHubWestend::assert_xcmp_queue_success(Some(Weight::from_parts(
16_290_336_000,
15_594_564_000,
562_893,
)));
assert_expected_events!(
AssetHubWestend,
vec![
// Burned the fee
RuntimeEvent::Assets(pallet_assets::Event::Burned { asset_id, owner, balance }) => {
asset_id: *asset_id == ASSET_ID,
owner: *owner == para_sovereign_account,
balance: *balance == fee_amount,
},
RuntimeEvent::Assets(pallet_assets::Event::Issued { asset_id, .. }) => {
asset_id: *asset_id == ASSET_ID,
// Asset created
RuntimeEvent::Assets(pallet_assets::Event::Created { asset_id, creator, owner }) => {
asset_id: *asset_id == new_asset_id,
creator: *creator == para_sovereign_account.clone(),
owner: *owner == para_sovereign_account,
},
]
);
@@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::*;
use crate::imports::*;
#[test]
fn relay_sets_system_para_xcm_supported_version() {
@@ -13,8 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::*;
use westend_system_emulated_network::penpal_emulated_chain::LocalTeleportableToAssetHubV3 as PenpalLocalTeleportableToAssetHubV3;
use crate::imports::*;
#[test]
fn swap_locally_on_chain_using_local_assets() {
@@ -112,49 +111,39 @@ fn swap_locally_on_chain_using_local_assets() {
#[test]
fn swap_locally_on_chain_using_foreign_assets() {
let asset_native = Box::new(asset_hub_westend_runtime::xcm_config::WestendLocationV3::get());
let ah_as_seen_by_penpal = PenpalB::sibling_location_of(AssetHubWestend::para_id());
let asset_location_on_penpal = PenpalLocalTeleportableToAssetHubV3::get();
let asset_id_on_penpal = match asset_location_on_penpal.last() {
Some(v3::Junction::GeneralIndex(id)) => *id as u32,
_ => unreachable!(),
};
let asset_owner_on_penpal = PenpalBSender::get();
let asset_native =
Box::new(v3::Location::try_from(RelayLocation::get()).expect("conversion works"));
let asset_location_on_penpal =
v3::Location::try_from(PenpalLocalTeleportableToAssetHub::get()).expect("conversion_works");
let foreign_asset_at_asset_hub_westend =
v3::Location::new(1, [v3::Junction::Parachain(PenpalB::para_id().into())])
v3::Location::new(1, [v3::Junction::Parachain(PenpalA::para_id().into())])
.appended_with(asset_location_on_penpal)
.unwrap();
// 1. Create asset on penpal and, 2. Create foreign asset on asset_hub_westend
super::penpal_create_foreign_asset_on_asset_hub(
asset_id_on_penpal,
foreign_asset_at_asset_hub_westend,
ah_as_seen_by_penpal,
true,
asset_owner_on_penpal,
ASSET_MIN_BALANCE * 1_000_000,
);
let penpal_as_seen_by_ah = AssetHubWestend::sibling_location_of(PenpalB::para_id());
let sov_penpal_on_ahw = AssetHubWestend::sovereign_account_id_of(penpal_as_seen_by_ah);
let penpal_as_seen_by_ah = AssetHubWestend::sibling_location_of(PenpalA::para_id());
let sov_penpal_on_ahr = AssetHubWestend::sovereign_account_id_of(penpal_as_seen_by_ah);
AssetHubWestend::fund_accounts(vec![
(AssetHubWestendSender::get().into(), 5_000_000 * WESTEND_ED), /* An account to swap dot
* for something else. */
// An account to swap dot for something else.
(AssetHubWestendSender::get().into(), 5_000_000 * ASSET_HUB_WESTEND_ED),
// Penpal's sovereign account in AH should have some balance
(sov_penpal_on_ahr.clone().into(), 100_000_000 * ASSET_HUB_WESTEND_ED),
]);
AssetHubWestend::execute_with(|| {
// 3: Mint foreign asset on asset_hub_westend:
// 0: No need to create foreign asset as it exists in genesis.
//
// 1: Mint foreign asset on asset_hub_westend:
//
// (While it might be nice to use batch,
// currently that's disabled due to safe call filters.)
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
// 3. Mint foreign asset (in reality this should be a teleport or some such)
// 1. Mint foreign asset (in reality this should be a teleport or some such)
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::ForeignAssets::mint(
<AssetHubWestend as Chain>::RuntimeOrigin::signed(sov_penpal_on_ahw.clone().into()),
<AssetHubWestend as Chain>::RuntimeOrigin::signed(sov_penpal_on_ahr.clone().into()),
foreign_asset_at_asset_hub_westend,
sov_penpal_on_ahw.clone().into(),
3_000_000_000_000,
sov_penpal_on_ahr.clone().into(),
ASSET_HUB_WESTEND_ED * 3_000_000_000_000,
));
assert_expected_events!(
@@ -164,7 +153,7 @@ fn swap_locally_on_chain_using_foreign_assets() {
]
);
// 4. Create pool:
// 2. Create pool:
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::create_pool(
<AssetHubWestend as Chain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
asset_native.clone(),
@@ -178,58 +167,60 @@ fn swap_locally_on_chain_using_foreign_assets() {
]
);
// 5. Add liquidity:
// 3. Add liquidity:
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::add_liquidity(
<AssetHubWestend as Chain>::RuntimeOrigin::signed(sov_penpal_on_ahw.clone()),
<AssetHubWestend as Chain>::RuntimeOrigin::signed(sov_penpal_on_ahr.clone()),
asset_native.clone(),
Box::new(foreign_asset_at_asset_hub_westend),
1_000_000_000_000,
2_000_000_000_000,
1_000_000_000_000_000,
2_000_000_000_000_000,
0,
0,
sov_penpal_on_ahw.clone().into()
sov_penpal_on_ahr.clone().into()
));
assert_expected_events!(
AssetHubWestend,
vec![
RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::LiquidityAdded {lp_token_minted, .. }) => {
lp_token_minted: *lp_token_minted == 1414213562273,
lp_token_minted: *lp_token_minted == 1414213562372995,
},
]
);
// 6. Swap!
// 4. Swap!
let path = vec![asset_native.clone(), Box::new(foreign_asset_at_asset_hub_westend)];
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::swap_exact_tokens_for_tokens(
<AssetHubWestend as Chain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
path,
100000,
1000,
AssetHubWestendSender::get().into(),
true
));
assert_ok!(
<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::swap_exact_tokens_for_tokens(
<AssetHubWestend as Chain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
path,
100000 * ASSET_HUB_WESTEND_ED,
1000 * ASSET_HUB_WESTEND_ED,
AssetHubWestendSender::get().into(),
true
)
);
assert_expected_events!(
AssetHubWestend,
vec![
RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::SwapExecuted { amount_in, amount_out, .. },) => {
amount_in: *amount_in == 100000,
amount_out: *amount_out == 199399,
amount_in: *amount_in == 100000000000000,
amount_out: *amount_out == 181322178776029,
},
]
);
// 7. Remove liquidity
// 5. Remove liquidity
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::remove_liquidity(
<AssetHubWestend as Chain>::RuntimeOrigin::signed(sov_penpal_on_ahw.clone()),
<AssetHubWestend as Chain>::RuntimeOrigin::signed(sov_penpal_on_ahr.clone()),
asset_native.clone(),
Box::new(foreign_asset_at_asset_hub_westend),
1414213562273 - 2_000_000_000, // all but the 2 EDs can't be retrieved.
1414213562372995 - ASSET_HUB_WESTEND_ED * 2, // all but the 2 EDs can't be retrieved.
0,
0,
sov_penpal_on_ahw.into(),
sov_penpal_on_ahr.clone().into(),
));
});
}
@@ -283,7 +274,7 @@ fn pay_xcm_fee_with_some_asset_swapped_for_native() {
.into(),
};
let penpal = AssetHubWestend::sovereign_account_id_of(AssetHubWestend::sibling_location_of(
PenpalB::para_id(),
PenpalA::para_id(),
));
AssetHubWestend::execute_with(|| {
@@ -356,7 +347,7 @@ fn pay_xcm_fee_with_some_asset_swapped_for_native() {
));
});
PenpalB::execute_with(|| {
PenpalA::execute_with(|| {
// send xcm transact from `penpal` account which as only `ASSET_ID` tokens on
// `AssetHubWestend`
let call = AssetHubWestend::force_create_asset_call(
@@ -366,11 +357,11 @@ fn pay_xcm_fee_with_some_asset_swapped_for_native() {
ASSET_MIN_BALANCE,
);
let penpal_root = <PenpalB as Chain>::RuntimeOrigin::root();
let penpal_root = <PenpalA as Chain>::RuntimeOrigin::root();
let fee_amount = 4_000_000_000_000u128;
let asset_one =
([PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())], fee_amount).into();
let asset_hub_location = PenpalB::sibling_location_of(AssetHubWestend::para_id()).into();
let asset_hub_location = PenpalA::sibling_location_of(AssetHubWestend::para_id()).into();
let xcm = xcm_transact_paid_execution(
call,
OriginKind::SovereignAccount,
@@ -378,13 +369,13 @@ fn pay_xcm_fee_with_some_asset_swapped_for_native() {
penpal.clone(),
);
assert_ok!(<PenpalB as PenpalBPallet>::PolkadotXcm::send(
assert_ok!(<PenpalA as PenpalAPallet>::PolkadotXcm::send(
penpal_root,
bx!(asset_hub_location),
bx!(xcm),
));
PenpalB::assert_xcm_pallet_sent();
PenpalA::assert_xcm_pallet_sent();
});
AssetHubWestend::execute_with(|| {
@@ -13,16 +13,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::*;
use asset_hub_westend_runtime::xcm_config::XcmConfig as AssetHubWestendXcmConfig;
use emulated_integration_tests_common::xcm_helpers::non_fee_asset;
use westend_runtime::xcm_config::XcmConfig as WestendXcmConfig;
use westend_system_emulated_network::penpal_emulated_chain::LocalTeleportableToAssetHubV3 as PenpalLocalTeleportableToAssetHubV3;
use crate::imports::*;
fn relay_origin_assertions(t: RelayToSystemParaTest) {
type RuntimeEvent = <Westend as Chain>::RuntimeEvent;
Westend::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(632_207_000, 7_186)));
Westend::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(631_531_000, 7_186)));
assert_expected_events!(
Westend,
@@ -47,7 +43,7 @@ fn relay_dest_assertions(t: SystemParaToRelayTest) {
Westend::assert_ump_queue_processed(
true,
Some(AssetHubWestend::para_id()),
Some(Weight::from_parts(308_222_000, 7_186)),
Some(Weight::from_parts(307_225_000, 7_186)),
);
assert_expected_events!(
@@ -70,7 +66,7 @@ fn relay_dest_assertions_fail(_t: SystemParaToRelayTest) {
Westend::assert_ump_queue_processed(
false,
Some(AssetHubWestend::para_id()),
Some(Weight::from_parts(148_705_000, 3_593)),
Some(Weight::from_parts(157_718_000, 3_593)),
);
}
@@ -78,8 +74,8 @@ fn para_origin_assertions(t: SystemParaToRelayTest) {
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
AssetHubWestend::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(
533_910_000,
7167,
720_053_000,
7_203,
)));
AssetHubWestend::assert_parachain_system_ump_sent();
@@ -99,7 +95,7 @@ fn para_origin_assertions(t: SystemParaToRelayTest) {
fn para_dest_assertions(t: RelayToSystemParaTest) {
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
AssetHubWestend::assert_dmp_queue_complete(Some(Weight::from_parts(164_793_000, 3593)));
AssetHubWestend::assert_dmp_queue_complete(Some(Weight::from_parts(157_718_000, 3593)));
assert_expected_events!(
AssetHubWestend,
@@ -113,19 +109,22 @@ fn para_dest_assertions(t: RelayToSystemParaTest) {
}
fn penpal_to_ah_foreign_assets_sender_assertions(t: ParaToSystemParaTest) {
type RuntimeEvent = <PenpalB as Chain>::RuntimeEvent;
PenpalB::assert_xcm_pallet_attempted_complete(None);
type RuntimeEvent = <PenpalA as Chain>::RuntimeEvent;
let system_para_native_asset_location =
v3::Location::try_from(RelayLocation::get()).expect("conversion works");
let expected_asset_id = t.args.asset_id.unwrap();
let (_, expected_asset_amount) =
non_fee_asset(&t.args.assets, t.args.fee_asset_item as usize).unwrap();
PenpalA::assert_xcm_pallet_attempted_complete(None);
assert_expected_events!(
PenpalB,
PenpalA,
vec![
RuntimeEvent::Balances(
pallet_balances::Event::Burned { who, amount }
RuntimeEvent::ForeignAssets(
pallet_assets::Event::Burned { asset_id, owner, .. }
) => {
who: *who == t.sender.account_id,
amount: *amount == t.args.amount,
asset_id: *asset_id == system_para_native_asset_location,
owner: *owner == t.sender.account_id,
},
RuntimeEvent::Assets(pallet_assets::Event::Burned { asset_id, owner, balance }) => {
asset_id: *asset_id == expected_asset_id,
@@ -139,11 +138,14 @@ fn penpal_to_ah_foreign_assets_sender_assertions(t: ParaToSystemParaTest) {
fn penpal_to_ah_foreign_assets_receiver_assertions(t: ParaToSystemParaTest) {
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
let sov_penpal_on_ahr = AssetHubWestend::sovereign_account_id_of(
AssetHubWestend::sibling_location_of(PenpalB::para_id()),
AssetHubWestend::sibling_location_of(PenpalA::para_id()),
);
let (expected_foreign_asset_id, expected_foreign_asset_amount) =
non_fee_asset(&t.args.assets, t.args.fee_asset_item as usize).unwrap();
let expected_foreign_asset_id_v3: v3::Location = expected_foreign_asset_id.try_into().unwrap();
AssetHubWestend::assert_xcmp_queue_success(None);
assert_expected_events!(
AssetHubWestend,
vec![
@@ -163,9 +165,6 @@ fn penpal_to_ah_foreign_assets_receiver_assertions(t: ParaToSystemParaTest) {
amount: *amount == expected_foreign_asset_amount,
},
RuntimeEvent::Balances(pallet_balances::Event::Deposit { .. }) => {},
RuntimeEvent::MessageQueue(
pallet_message_queue::Event::Processed { success: true, .. }
) => {},
]
);
}
@@ -200,13 +199,18 @@ fn ah_to_penpal_foreign_assets_sender_assertions(t: SystemParaToParaTest) {
}
fn ah_to_penpal_foreign_assets_receiver_assertions(t: SystemParaToParaTest) {
type RuntimeEvent = <PenpalB as Chain>::RuntimeEvent;
type RuntimeEvent = <PenpalA as Chain>::RuntimeEvent;
let expected_asset_id = t.args.asset_id.unwrap();
let (_, expected_asset_amount) =
non_fee_asset(&t.args.assets, t.args.fee_asset_item as usize).unwrap();
let checking_account = <PenpalB as PenpalBPallet>::PolkadotXcm::check_account();
let checking_account = <PenpalA as PenpalAPallet>::PolkadotXcm::check_account();
let system_para_native_asset_location =
v3::Location::try_from(RelayLocation::get()).expect("conversion works");
PenpalA::assert_xcmp_queue_success(None);
assert_expected_events!(
PenpalB,
PenpalA,
vec![
// checking account burns local asset as part of incoming teleport
RuntimeEvent::Assets(pallet_assets::Event::Burned { asset_id, owner, balance }) => {
@@ -221,12 +225,11 @@ fn ah_to_penpal_foreign_assets_receiver_assertions(t: SystemParaToParaTest) {
amount: *amount == expected_asset_amount,
},
// native asset for fee is deposited to receiver
RuntimeEvent::Balances(pallet_balances::Event::Minted { who, .. }) => {
who: *who == t.receiver.account_id,
RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { asset_id, owner, amount }) => {
asset_id: *asset_id == system_para_native_asset_location,
owner: *owner == t.receiver.account_id,
amount: *amount == expected_asset_amount,
},
RuntimeEvent::MessageQueue(
pallet_message_queue::Event::Processed { success: true, .. }
) => {},
]
);
}
@@ -273,8 +276,8 @@ fn system_para_teleport_assets(t: SystemParaToRelayTest) -> DispatchResult {
)
}
fn system_para_to_para_transfer_assets(t: SystemParaToParaTest) -> DispatchResult {
<AssetHubWestend as AssetHubWestendPallet>::PolkadotXcm::transfer_assets(
fn para_to_system_para_transfer_assets(t: ParaToSystemParaTest) -> DispatchResult {
<PenpalA as PenpalAPallet>::PolkadotXcm::transfer_assets(
t.signed_origin,
bx!(t.args.dest.into()),
bx!(t.args.beneficiary.into()),
@@ -284,8 +287,8 @@ fn system_para_to_para_transfer_assets(t: SystemParaToParaTest) -> DispatchResul
)
}
fn para_to_system_para_transfer_assets(t: ParaToSystemParaTest) -> DispatchResult {
<PenpalB as PenpalBPallet>::PolkadotXcm::transfer_assets(
fn system_para_to_para_transfer_assets(t: SystemParaToParaTest) -> DispatchResult {
<AssetHubWestend as AssetHubWestendPallet>::PolkadotXcm::transfer_assets(
t.signed_origin,
bx!(t.args.dest.into()),
bx!(t.args.beneficiary.into()),
@@ -301,11 +304,11 @@ fn limited_teleport_native_assets_from_relay_to_system_para_works() {
// Init values for Relay Chain
let amount_to_send: Balance = WESTEND_ED * 1000;
let dest = Westend::child_location_of(AssetHubWestend::para_id());
let beneficiary = AssetHubWestendReceiver::get();
let beneficiary_id = AssetHubWestendReceiver::get();
let test_args = TestContext {
sender: WestendSender::get(),
receiver: beneficiary.clone(),
args: TestArgs::new_relay(dest, beneficiary, amount_to_send),
receiver: AssetHubWestendReceiver::get(),
args: TestArgs::new_relay(dest, beneficiary_id, amount_to_send),
};
let mut test = RelayToSystemParaTest::new(test_args);
@@ -424,11 +427,11 @@ fn teleport_native_assets_from_relay_to_system_para_works() {
// Init values for Relay Chain
let amount_to_send: Balance = WESTEND_ED * 1000;
let dest = Westend::child_location_of(AssetHubWestend::para_id());
let beneficiary = AssetHubWestendReceiver::get();
let beneficiary_id = AssetHubWestendReceiver::get();
let test_args = TestContext {
sender: WestendSender::get(),
receiver: beneficiary.clone(),
args: TestArgs::new_relay(dest, beneficiary, amount_to_send),
receiver: AssetHubWestendReceiver::get(),
args: TestArgs::new_relay(dest, beneficiary_id, amount_to_send),
};
let mut test = RelayToSystemParaTest::new(test_args);
@@ -485,15 +488,15 @@ fn teleport_native_assets_back_from_system_para_to_relay_works() {
test.set_dispatchable::<AssetHubWestend>(system_para_teleport_assets);
test.assert();
let sender_balance_after = test.sender.balance;
let receiver_balance_after = test.receiver.balance;
let delivery_fees = AssetHubWestend::execute_with(|| {
xcm_helpers::transfer_assets_delivery_fees::<
<AssetHubWestendXcmConfig as xcm_executor::Config>::XcmSender,
>(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest)
});
let sender_balance_after = test.sender.balance;
let receiver_balance_after = test.receiver.balance;
// Sender's balance is reduced
assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after);
// Receiver's balance is increased
@@ -558,30 +561,21 @@ fn teleport_to_other_system_parachains_works() {
/// (using native reserve-based transfer for fees)
#[test]
fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() {
let ah_as_seen_by_penpal = PenpalB::sibling_location_of(AssetHubWestend::para_id());
let asset_location_on_penpal = PenpalLocalTeleportableToAssetHubV3::get();
// Init values for Parachain
let fee_amount_to_send: Balance = ASSET_HUB_WESTEND_ED * 100;
let asset_location_on_penpal =
v3::Location::try_from(PenpalLocalTeleportableToAssetHub::get()).expect("conversion works");
let asset_id_on_penpal = match asset_location_on_penpal.last() {
Some(v3::Junction::GeneralIndex(id)) => *id as u32,
_ => unreachable!(),
};
let asset_owner_on_penpal = PenpalBSender::get();
let foreign_asset_at_asset_hub_westend =
v3::Location::new(1, [v3::Junction::Parachain(PenpalB::para_id().into())])
.appended_with(asset_location_on_penpal)
.unwrap();
super::penpal_create_foreign_asset_on_asset_hub(
asset_id_on_penpal,
foreign_asset_at_asset_hub_westend,
ah_as_seen_by_penpal.clone(),
false,
asset_owner_on_penpal,
ASSET_MIN_BALANCE * 1_000_000,
);
let penpal_to_ah_beneficiary_id = AssetHubWestendReceiver::get();
let fee_amount_to_send = ASSET_HUB_WESTEND_ED * 1000;
let asset_amount_to_send = ASSET_MIN_BALANCE * 1000;
let asset_amount_to_send = ASSET_HUB_WESTEND_ED * 100;
let asset_owner = PenpalAssetOwner::get();
let system_para_native_asset_location =
v3::Location::try_from(RelayLocation::get()).expect("conversion works");
let sender = PenpalASender::get();
let penpal_check_account = <PenpalA as PenpalAPallet>::PolkadotXcm::check_account();
let ah_as_seen_by_penpal = PenpalA::sibling_location_of(AssetHubWestend::para_id());
let asset_location_on_penpal_latest: Location = asset_location_on_penpal.try_into().unwrap();
let penpal_assets: Assets = vec![
(Parent, fee_amount_to_send).into(),
@@ -594,9 +588,44 @@ fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() {
.position(|r| r == &(Parent, fee_amount_to_send).into())
.unwrap() as u32;
// fund Parachain's sender account
PenpalA::mint_foreign_asset(
<PenpalA as Chain>::RuntimeOrigin::signed(asset_owner.clone()),
system_para_native_asset_location,
sender.clone(),
fee_amount_to_send,
);
// No need to create the asset (only mint) as it exists in genesis.
PenpalA::mint_asset(
<PenpalA as Chain>::RuntimeOrigin::signed(asset_owner.clone()),
asset_id_on_penpal,
sender.clone(),
asset_amount_to_send,
);
// fund Parachain's check account to be able to teleport
PenpalA::fund_accounts(vec![(
penpal_check_account.clone().into(),
ASSET_HUB_WESTEND_ED * 1000,
)]);
// prefund SA of Penpal on AssetHub with enough native tokens to pay for fees
let penpal_as_seen_by_ah = AssetHubWestend::sibling_location_of(PenpalA::para_id());
let sov_penpal_on_ah = AssetHubWestend::sovereign_account_id_of(penpal_as_seen_by_ah);
AssetHubWestend::fund_accounts(vec![(
sov_penpal_on_ah.clone().into(),
ASSET_HUB_WESTEND_ED * 100_000_000_000,
)]);
// Init values for System Parachain
let foreign_asset_at_asset_hub_westend =
v3::Location::new(1, [v3::Junction::Parachain(PenpalA::para_id().into())])
.appended_with(asset_location_on_penpal)
.unwrap();
let penpal_to_ah_beneficiary_id = AssetHubWestendReceiver::get();
// Penpal to AH test args
let penpal_to_ah_test_args = TestContext {
sender: PenpalBSender::get(),
sender: PenpalASender::get(),
receiver: AssetHubWestendReceiver::get(),
args: TestArgs::new_para(
ah_as_seen_by_penpal,
@@ -608,13 +637,19 @@ fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() {
),
};
let mut penpal_to_ah = ParaToSystemParaTest::new(penpal_to_ah_test_args);
let penpal_sender_balance_before = PenpalA::execute_with(|| {
type ForeignAssets = <PenpalA as PenpalAPallet>::ForeignAssets;
<ForeignAssets as Inspect<_>>::balance(
system_para_native_asset_location,
&PenpalASender::get(),
)
});
let penpal_sender_balance_before = penpal_to_ah.sender.balance;
let ah_receiver_balance_before = penpal_to_ah.receiver.balance;
let penpal_sender_assets_before = PenpalB::execute_with(|| {
type Assets = <PenpalB as PenpalBPallet>::Assets;
<Assets as Inspect<_>>::balance(asset_id_on_penpal, &PenpalBSender::get())
let penpal_sender_assets_before = PenpalA::execute_with(|| {
type Assets = <PenpalA as PenpalAPallet>::Assets;
<Assets as Inspect<_>>::balance(asset_id_on_penpal, &PenpalASender::get())
});
let ah_receiver_assets_before = AssetHubWestend::execute_with(|| {
type Assets = <AssetHubWestend as AssetHubWestendPallet>::ForeignAssets;
@@ -624,17 +659,24 @@ fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() {
)
});
penpal_to_ah.set_assertion::<PenpalB>(penpal_to_ah_foreign_assets_sender_assertions);
penpal_to_ah.set_assertion::<PenpalA>(penpal_to_ah_foreign_assets_sender_assertions);
penpal_to_ah.set_assertion::<AssetHubWestend>(penpal_to_ah_foreign_assets_receiver_assertions);
penpal_to_ah.set_dispatchable::<PenpalB>(para_to_system_para_transfer_assets);
penpal_to_ah.set_dispatchable::<PenpalA>(para_to_system_para_transfer_assets);
penpal_to_ah.assert();
let penpal_sender_balance_after = penpal_to_ah.sender.balance;
let penpal_sender_balance_after = PenpalA::execute_with(|| {
type ForeignAssets = <PenpalA as PenpalAPallet>::ForeignAssets;
<ForeignAssets as Inspect<_>>::balance(
system_para_native_asset_location,
&PenpalASender::get(),
)
});
let ah_receiver_balance_after = penpal_to_ah.receiver.balance;
let penpal_sender_assets_after = PenpalB::execute_with(|| {
type Assets = <PenpalB as PenpalBPallet>::Assets;
<Assets as Inspect<_>>::balance(asset_id_on_penpal, &PenpalBSender::get())
let penpal_sender_assets_after = PenpalA::execute_with(|| {
type Assets = <PenpalA as PenpalAPallet>::Assets;
<Assets as Inspect<_>>::balance(asset_id_on_penpal, &PenpalASender::get())
});
let ah_receiver_assets_after = AssetHubWestend::execute_with(|| {
type Assets = <AssetHubWestend as AssetHubWestendPallet>::ForeignAssets;
@@ -675,8 +717,8 @@ fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() {
let foreign_asset_at_asset_hub_westend_latest: Location =
foreign_asset_at_asset_hub_westend.try_into().unwrap();
let ah_to_penpal_beneficiary_id = PenpalBReceiver::get();
let penpal_as_seen_by_ah = AssetHubWestend::sibling_location_of(PenpalB::para_id());
let ah_to_penpal_beneficiary_id = PenpalAReceiver::get();
let penpal_as_seen_by_ah = AssetHubWestend::sibling_location_of(PenpalA::para_id());
let ah_assets: Assets = vec![
(Parent, fee_amount_to_send).into(),
(foreign_asset_at_asset_hub_westend_latest, asset_amount_to_send).into(),
@@ -691,7 +733,7 @@ fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() {
// AH to Penpal test args
let ah_to_penpal_test_args = TestContext {
sender: AssetHubWestendSender::get(),
receiver: PenpalBReceiver::get(),
receiver: PenpalAReceiver::get(),
args: TestArgs::new_para(
penpal_as_seen_by_ah,
ah_to_penpal_beneficiary_id,
@@ -704,7 +746,13 @@ fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() {
let mut ah_to_penpal = SystemParaToParaTest::new(ah_to_penpal_test_args);
let ah_sender_balance_before = ah_to_penpal.sender.balance;
let penpal_receiver_balance_before = ah_to_penpal.receiver.balance;
let penpal_receiver_balance_before = PenpalA::execute_with(|| {
type ForeignAssets = <PenpalA as PenpalAPallet>::ForeignAssets;
<ForeignAssets as Inspect<_>>::balance(
system_para_native_asset_location,
&PenpalAReceiver::get(),
)
});
let ah_sender_assets_before = AssetHubWestend::execute_with(|| {
type ForeignAssets = <AssetHubWestend as AssetHubWestendPallet>::ForeignAssets;
@@ -713,18 +761,24 @@ fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() {
&AssetHubWestendSender::get(),
)
});
let penpal_receiver_assets_before = PenpalB::execute_with(|| {
type Assets = <PenpalB as PenpalBPallet>::Assets;
<Assets as Inspect<_>>::balance(asset_id_on_penpal, &PenpalBReceiver::get())
let penpal_receiver_assets_before = PenpalA::execute_with(|| {
type Assets = <PenpalA as PenpalAPallet>::Assets;
<Assets as Inspect<_>>::balance(asset_id_on_penpal, &PenpalAReceiver::get())
});
ah_to_penpal.set_assertion::<AssetHubWestend>(ah_to_penpal_foreign_assets_sender_assertions);
ah_to_penpal.set_assertion::<PenpalB>(ah_to_penpal_foreign_assets_receiver_assertions);
ah_to_penpal.set_assertion::<PenpalA>(ah_to_penpal_foreign_assets_receiver_assertions);
ah_to_penpal.set_dispatchable::<AssetHubWestend>(system_para_to_para_transfer_assets);
ah_to_penpal.assert();
let ah_sender_balance_after = ah_to_penpal.sender.balance;
let penpal_receiver_balance_after = ah_to_penpal.receiver.balance;
let penpal_receiver_balance_after = PenpalA::execute_with(|| {
type ForeignAssets = <PenpalA as PenpalAPallet>::ForeignAssets;
<ForeignAssets as Inspect<_>>::balance(
system_para_native_asset_location,
&PenpalAReceiver::get(),
)
});
let ah_sender_assets_after = AssetHubWestend::execute_with(|| {
type ForeignAssets = <AssetHubWestend as AssetHubWestendPallet>::ForeignAssets;
@@ -733,9 +787,9 @@ fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() {
&AssetHubWestendSender::get(),
)
});
let penpal_receiver_assets_after = PenpalB::execute_with(|| {
type Assets = <PenpalB as PenpalBPallet>::Assets;
<Assets as Inspect<_>>::balance(asset_id_on_penpal, &PenpalBReceiver::get())
let penpal_receiver_assets_after = PenpalA::execute_with(|| {
type Assets = <PenpalA as PenpalAPallet>::Assets;
<Assets as Inspect<_>>::balance(asset_id_on_penpal, &PenpalAReceiver::get())
});
// Sender's balance is reduced
@@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::*;
use crate::imports::*;
use emulated_integration_tests_common::accounts::{ALICE, BOB};
use frame_support::traits::fungibles::{Create, Inspect, Mutate};
use polkadot_runtime_common::impls::VersionedLocatableAsset;
@@ -13,62 +13,53 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// Substrate
pub use frame_support::{assert_err, assert_ok, pallet_prelude::DispatchResult};
pub use sp_runtime::DispatchError;
#[cfg(test)]
mod imports {
// Substrate
pub use frame_support::{assert_err, assert_ok, pallet_prelude::DispatchResult};
pub use sp_runtime::DispatchError;
// Polkadot
pub use xcm::{
latest::ParentThen,
prelude::{AccountId32 as AccountId32Junction, *},
v3::{
self, Error,
NetworkId::{Rococo as RococoId, Westend as WestendId},
},
};
// Polkadot
pub use xcm::{
latest::ParentThen,
prelude::{AccountId32 as AccountId32Junction, *},
v3::{self, NetworkId::Westend as WestendId},
};
// Bridges
pub use bp_messages::LaneId;
// Cumulus
pub use emulated_integration_tests_common::{
accounts::ALICE,
impls::Inspect,
test_parachain_is_trusted_teleporter,
xcm_emulator::{
assert_expected_events, bx, Chain, Parachain as Para, RelayChain as Relay, TestExt,
},
};
pub use parachains_common::AccountId;
pub use rococo_westend_system_emulated_network::{
asset_hub_rococo_emulated_chain::{
genesis::ED as ASSET_HUB_ROCOCO_ED, AssetHubRococoParaPallet as AssetHubRococoPallet,
},
asset_hub_westend_emulated_chain::{
genesis::ED as ASSET_HUB_WESTEND_ED, AssetHubWestendParaPallet as AssetHubWestendPallet,
},
bridge_hub_rococo_emulated_chain::{
genesis::ED as BRIDGE_HUB_ROCOCO_ED, BridgeHubRococoParaPallet as BridgeHubRococoPallet,
},
penpal_emulated_chain::PenpalAParaPallet as PenpalAPallet,
rococo_emulated_chain::{genesis::ED as ROCOCO_ED, RococoRelayPallet as RococoPallet},
AssetHubRococoPara as AssetHubRococo, AssetHubRococoParaReceiver as AssetHubRococoReceiver,
AssetHubRococoParaSender as AssetHubRococoSender, AssetHubWestendPara as AssetHubWestend,
AssetHubWestendParaReceiver as AssetHubWestendReceiver,
AssetHubWestendParaSender as AssetHubWestendSender, BridgeHubRococoPara as BridgeHubRococo,
BridgeHubRococoParaSender as BridgeHubRococoSender,
BridgeHubWestendPara as BridgeHubWestend, PenpalAPara as PenpalA,
PenpalAParaReceiver as PenpalAReceiver, PenpalAParaSender as PenpalASender,
RococoRelay as Rococo,
};
// Cumulus
pub use emulated_integration_tests_common::{
accounts::ALICE,
impls::Inspect,
test_parachain_is_trusted_teleporter,
xcm_emulator::{
assert_expected_events, bx, helpers::weight_within_threshold, Chain, Parachain as Para,
RelayChain as Relay, Test, TestArgs, TestContext, TestExt,
},
xcm_helpers::{xcm_transact_paid_execution, xcm_transact_unpaid_execution},
PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3,
};
pub use parachains_common::{AccountId, Balance};
pub use rococo_westend_system_emulated_network::{
asset_hub_rococo_emulated_chain::{
genesis::ED as ASSET_HUB_ROCOCO_ED, AssetHubRococoParaPallet as AssetHubRococoPallet,
},
asset_hub_westend_emulated_chain::{
genesis::ED as ASSET_HUB_WESTEND_ED, AssetHubWestendParaPallet as AssetHubWestendPallet,
},
bridge_hub_rococo_emulated_chain::{
genesis::ED as BRIDGE_HUB_ROCOCO_ED, BridgeHubRococoParaPallet as BridgeHubRococoPallet,
},
penpal_emulated_chain::PenpalAParaPallet as PenpalAPallet,
rococo_emulated_chain::{genesis::ED as ROCOCO_ED, RococoRelayPallet as RococoPallet},
AssetHubRococoPara as AssetHubRococo, AssetHubRococoParaReceiver as AssetHubRococoReceiver,
AssetHubRococoParaSender as AssetHubRococoSender, AssetHubWestendPara as AssetHubWestend,
AssetHubWestendParaReceiver as AssetHubWestendReceiver,
AssetHubWestendParaSender as AssetHubWestendSender, BridgeHubRococoPara as BridgeHubRococo,
BridgeHubRococoParaReceiver as BridgeHubRococoReceiver,
BridgeHubRococoParaSender as BridgeHubRococoSender, BridgeHubWestendPara as BridgeHubWestend,
PenpalAPara as PenpalA, PenpalAParaReceiver as PenpalAReceiver,
PenpalAParaSender as PenpalASender, RococoRelay as Rococo,
RococoRelayReceiver as RococoReceiver, RococoRelaySender as RococoSender,
};
pub const ASSET_ID: u32 = 1;
pub const ASSET_MIN_BALANCE: u128 = 1000;
pub const ASSETS_PALLET_ID: u8 = 50;
pub const ASSET_MIN_BALANCE: u128 = 1000;
}
#[cfg(test)]
mod tests;
@@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::*;
use crate::imports::*;
mod asset_transfers;
mod send_xcm;
@@ -12,7 +12,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::*;
use crate::imports::*;
use bridge_hub_rococo_runtime::{EthereumBeaconClient, EthereumInboundQueue, RuntimeOrigin};
use codec::{Decode, Encode};
use emulated_integration_tests_common::xcm_emulator::ConvertLocation;
@@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::*;
use crate::tests::*;
use bridge_hub_rococo_runtime::xcm_config::XcmConfig;
#[test]
@@ -13,59 +13,52 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// Substrate
pub use frame_support::{assert_err, assert_ok, pallet_prelude::DispatchResult};
pub use sp_runtime::DispatchError;
#[cfg(test)]
mod imports {
// Substrate
pub use frame_support::{assert_err, assert_ok, pallet_prelude::DispatchResult};
pub use sp_runtime::DispatchError;
// Polkadot
pub use xcm::{
latest::ParentThen,
prelude::{AccountId32 as AccountId32Junction, *},
v3,
v4::{
Error,
NetworkId::{Rococo as RococoId, Westend as WestendId},
},
};
// Polkadot
pub use xcm::{
latest::ParentThen,
prelude::{AccountId32 as AccountId32Junction, *},
v3,
v4::NetworkId::Rococo as RococoId,
};
// Bridges
pub use bp_messages::LaneId;
// Cumulus
pub use emulated_integration_tests_common::{
accounts::ALICE,
impls::Inspect,
test_parachain_is_trusted_teleporter,
xcm_emulator::{
assert_expected_events, bx, Chain, Parachain as Para, RelayChain as Relay, TestExt,
},
};
pub use parachains_common::AccountId;
pub use rococo_westend_system_emulated_network::{
asset_hub_rococo_emulated_chain::{
genesis::ED as ASSET_HUB_ROCOCO_ED, AssetHubRococoParaPallet as AssetHubRococoPallet,
},
asset_hub_westend_emulated_chain::{
genesis::ED as ASSET_HUB_WESTEND_ED, AssetHubWestendParaPallet as AssetHubWestendPallet,
},
bridge_hub_westend_emulated_chain::{
genesis::ED as BRIDGE_HUB_WESTEND_ED,
BridgeHubWestendParaPallet as BridgeHubWestendPallet,
},
westend_emulated_chain::WestendRelayPallet as WestendPallet,
AssetHubRococoPara as AssetHubRococo, AssetHubRococoParaReceiver as AssetHubRococoReceiver,
AssetHubRococoParaSender as AssetHubRococoSender, AssetHubWestendPara as AssetHubWestend,
AssetHubWestendParaReceiver as AssetHubWestendReceiver,
AssetHubWestendParaSender as AssetHubWestendSender, BridgeHubRococoPara as BridgeHubRococo,
BridgeHubWestendPara as BridgeHubWestend,
BridgeHubWestendParaSender as BridgeHubWestendSender, WestendRelay as Westend,
};
// Cumulus
pub use emulated_integration_tests_common::{
accounts::ALICE,
impls::Inspect,
test_parachain_is_trusted_teleporter,
xcm_emulator::{
assert_expected_events, bx, helpers::weight_within_threshold, Chain, Parachain as Para,
RelayChain as Relay, Test, TestArgs, TestContext, TestExt,
},
xcm_helpers::{xcm_transact_paid_execution, xcm_transact_unpaid_execution},
PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3,
};
pub use parachains_common::{AccountId, Balance};
pub use rococo_westend_system_emulated_network::{
asset_hub_rococo_emulated_chain::{
genesis::ED as ASSET_HUB_ROCOCO_ED, AssetHubRococoParaPallet as AssetHubRococoPallet,
},
asset_hub_westend_emulated_chain::{
genesis::ED as ASSET_HUB_WESTEND_ED, AssetHubWestendParaPallet as AssetHubWestendPallet,
},
bridge_hub_westend_emulated_chain::{
genesis::ED as BRIDGE_HUB_WESTEND_ED, BridgeHubWestendParaPallet as BridgeHubWestendPallet,
},
westend_emulated_chain::WestendRelayPallet as WestendPallet,
AssetHubRococoPara as AssetHubRococo, AssetHubRococoParaReceiver as AssetHubRococoReceiver,
AssetHubRococoParaSender as AssetHubRococoSender, AssetHubWestendPara as AssetHubWestend,
AssetHubWestendParaReceiver as AssetHubWestendReceiver,
AssetHubWestendParaSender as AssetHubWestendSender, BridgeHubRococoPara as BridgeHubRococo,
BridgeHubWestendPara as BridgeHubWestend, BridgeHubWestendParaSender as BridgeHubWestendSender,
WestendRelay as Westend,
};
pub const ASSET_ID: u32 = 1;
pub const ASSET_MIN_BALANCE: u128 = 1000;
pub const ASSETS_PALLET_ID: u8 = 50;
pub const ASSET_MIN_BALANCE: u128 = 1000;
}
#[cfg(test)]
mod tests;
@@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::*;
use crate::imports::*;
mod asset_transfers;
mod send_xcm;
@@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::*;
use crate::tests::*;
use bridge_hub_westend_runtime::xcm_config::XcmConfig;
#[test]
@@ -13,52 +13,41 @@
// See the License for the specific language governing permissions and
// limitations under the License.
pub use codec::Encode;
#[cfg(test)]
mod imports {
pub use codec::Encode;
// Substrate
pub use frame_support::{
assert_err, assert_ok,
pallet_prelude::Weight,
sp_runtime::{AccountId32, DispatchError, DispatchResult},
traits::fungibles::Inspect,
};
// Substrate
pub use frame_support::{
assert_ok,
pallet_prelude::Weight,
sp_runtime::{AccountId32, DispatchResult},
traits::fungibles::Inspect,
};
// Polkadot
pub use xcm::{
prelude::{AccountId32 as AccountId32Junction, *},
v3::{Error, NetworkId::Rococo as RococoId},
};
// Polkadot
pub use xcm::prelude::*;
// Cumulus
pub use asset_test_utils::xcm_helpers;
pub use emulated_integration_tests_common::{
test_parachain_is_trusted_teleporter,
xcm_emulator::{
assert_expected_events, bx, helpers::weight_within_threshold, Chain, Parachain as Para,
RelayChain as Relay, Test, TestArgs, TestContext, TestExt,
},
xcm_helpers::{xcm_transact_paid_execution, xcm_transact_unpaid_execution},
PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3,
};
pub use parachains_common::{AccountId, Balance};
pub use rococo_system_emulated_network::{
people_rococo_emulated_chain::{
genesis::ED as PEOPLE_ROCOCO_ED, PeopleRococoParaPallet as PeopleRococoPallet,
},
rococo_emulated_chain::{genesis::ED as ROCOCO_ED, RococoRelayPallet as RococoPallet},
PenpalAPara as PenpalA, PeopleRococoPara as PeopleRococo,
PeopleRococoParaReceiver as PeopleRococoReceiver, PeopleRococoParaSender as PeopleRococoSender,
RococoRelay as Rococo, RococoRelayReceiver as RococoReceiver,
RococoRelaySender as RococoSender,
};
// Cumulus
pub use asset_test_utils::xcm_helpers;
pub use emulated_integration_tests_common::xcm_emulator::{
assert_expected_events, bx, Chain, Parachain as Para, RelayChain as Relay, Test, TestArgs,
TestContext, TestExt,
};
pub use parachains_common::Balance;
pub use rococo_system_emulated_network::{
people_rococo_emulated_chain::{
genesis::ED as PEOPLE_ROCOCO_ED, PeopleRococoParaPallet as PeopleRococoPallet,
},
rococo_emulated_chain::{genesis::ED as ROCOCO_ED, RococoRelayPallet as RococoPallet},
PeopleRococoPara as PeopleRococo, PeopleRococoParaReceiver as PeopleRococoReceiver,
PeopleRococoParaSender as PeopleRococoSender, RococoRelay as Rococo,
RococoRelayReceiver as RococoReceiver, RococoRelaySender as RococoSender,
};
// pub const ASSET_ID: u32 = 1;
// pub const ASSET_MIN_BALANCE: u128 = 1000;
pub type RelayToSystemParaTest = Test<Rococo, PeopleRococo>;
pub type RelayToParaTest = Test<Rococo, PenpalA>;
pub type SystemParaToRelayTest = Test<PeopleRococo, Rococo>;
pub type SystemParaToParaTest = Test<PeopleRococo, PenpalA>;
pub type ParaToSystemParaTest = Test<PenpalA, PeopleRococo>;
pub type RelayToSystemParaTest = Test<Rococo, PeopleRococo>;
pub type SystemParaToRelayTest = Test<PeopleRococo, Rococo>;
}
#[cfg(test)]
mod tests;
@@ -38,7 +38,7 @@
//! - The freed deposit from the Relay Chain is sufficient for the parachain deposit; and
//! - The account will exist on the parachain.
use crate::*;
use crate::imports::*;
use frame_support::BoundedVec;
use pallet_balances::Event as BalancesEvent;
use pallet_identity::{legacy::IdentityInfo, Data, Event as IdentityEvent};
@@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::*;
use crate::imports::*;
use people_rococo_runtime::xcm_config::XcmConfig as PeopleRococoXcmConfig;
use rococo_runtime::xcm_config::XcmConfig as RococoXcmConfig;
@@ -13,52 +13,40 @@
// See the License for the specific language governing permissions and
// limitations under the License.
pub use codec::Encode;
#[cfg(test)]
mod imports {
pub use codec::Encode;
// Substrate
pub use frame_support::{
assert_ok,
pallet_prelude::Weight,
sp_runtime::{AccountId32, DispatchResult},
traits::fungibles::Inspect,
};
// Substrate
pub use frame_support::{
assert_err, assert_ok,
pallet_prelude::Weight,
sp_runtime::{AccountId32, DispatchError, DispatchResult},
traits::fungibles::Inspect,
};
// Polkadot
pub use xcm::prelude::*;
// Polkadot
pub use xcm::{
prelude::{AccountId32 as AccountId32Junction, *},
v3::{Error, NetworkId::Westend as WestendId},
};
// Cumulus
pub use asset_test_utils::xcm_helpers;
pub use emulated_integration_tests_common::xcm_emulator::{
assert_expected_events, bx, Chain, Parachain as Para, RelayChain as Relay, Test, TestArgs,
TestContext, TestExt,
};
pub use parachains_common::Balance;
pub use westend_system_emulated_network::{
people_westend_emulated_chain::{
genesis::ED as PEOPLE_WESTEND_ED, PeopleWestendParaPallet as PeopleWestendPallet,
},
westend_emulated_chain::{genesis::ED as WESTEND_ED, WestendRelayPallet as WestendPallet},
PeopleWestendPara as PeopleWestend, PeopleWestendParaReceiver as PeopleWestendReceiver,
PeopleWestendParaSender as PeopleWestendSender, WestendRelay as Westend,
WestendRelayReceiver as WestendReceiver, WestendRelaySender as WestendSender,
};
// Cumulus
pub use asset_test_utils::xcm_helpers;
pub use emulated_integration_tests_common::{
test_parachain_is_trusted_teleporter,
xcm_emulator::{
assert_expected_events, bx, helpers::weight_within_threshold, Chain, Parachain as Para,
RelayChain as Relay, Test, TestArgs, TestContext, TestExt,
},
xcm_helpers::{xcm_transact_paid_execution, xcm_transact_unpaid_execution},
PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3,
};
pub use parachains_common::{AccountId, Balance};
pub use westend_system_emulated_network::{
people_westend_emulated_chain::{
genesis::ED as PEOPLE_WESTEND_ED, PeopleWestendParaPallet as PeopleWestendPallet,
},
westend_emulated_chain::{genesis::ED as WESTEND_ED, WestendRelayPallet as WestendPallet},
PenpalAPara as PenpalA, PeopleWestendPara as PeopleWestend,
PeopleWestendParaReceiver as PeopleWestendReceiver,
PeopleWestendParaSender as PeopleWestendSender, WestendRelay as Westend,
WestendRelayReceiver as WestendReceiver, WestendRelaySender as WestendSender,
};
// pub const ASSET_ID: u32 = 1;
// pub const ASSET_MIN_BALANCE: u128 = 1000;
pub type RelayToSystemParaTest = Test<Westend, PeopleWestend>;
pub type RelayToParaTest = Test<Westend, PenpalA>;
pub type SystemParaToRelayTest = Test<PeopleWestend, Westend>;
pub type SystemParaToParaTest = Test<PeopleWestend, PenpalA>;
pub type ParaToSystemParaTest = Test<PenpalA, PeopleWestend>;
pub type RelayToSystemParaTest = Test<Westend, PeopleWestend>;
pub type SystemParaToRelayTest = Test<PeopleWestend, Westend>;
}
#[cfg(test)]
mod tests;
@@ -38,7 +38,7 @@
//! - The freed deposit from the Relay Chain is sufficient for the parachain deposit; and
//! - The account will exist on the parachain.
use crate::*;
use crate::imports::*;
use frame_support::BoundedVec;
use pallet_balances::Event as BalancesEvent;
use pallet_identity::{legacy::IdentityInfo, Data, Event as IdentityEvent};
@@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::*;
use crate::imports::*;
use people_westend_runtime::xcm_config::XcmConfig as PeopleWestendXcmConfig;
use westend_runtime::xcm_config::XcmConfig as WestendXcmConfig;
@@ -527,12 +527,12 @@ fn test_foreign_asset_xcm_take_first_trader() {
let bought = Weight::from_parts(4_000_000_000u64, 0);
// Lets calculate amount needed
let asset_amount_needed =
ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger::charge_weight_in_fungibles(
let asset_amount_needed
= ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger::charge_weight_in_fungibles(
foreign_location,
bought,
bought
)
.expect("failed to compute");
.expect("failed to compute");
// Lets pay with: asset_amount_needed + asset_amount_extra
let asset_amount_extra = 100_u128;
@@ -527,12 +527,8 @@ fn test_foreign_asset_xcm_take_first_trader() {
let bought = Weight::from_parts(4_000_000_000u64, 0);
// Lets calculate amount needed
let asset_amount_needed =
ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger::charge_weight_in_fungibles(
foreign_location,
bought,
)
.expect("failed to compute");
let asset_amount_needed = ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger::charge_weight_in_fungibles(foreign_location, bought)
.expect("failed to compute");
// Lets pay with: asset_amount_needed + asset_amount_extra
let asset_amount_extra = 100_u128;
@@ -53,7 +53,10 @@ use frame_system::{
limits::{BlockLength, BlockWeights},
EnsureRoot, EnsureSigned,
};
use parachains_common::message_queue::{NarrowOriginToSibling, ParaIdToSibling};
use parachains_common::{
impls::{AssetsToBlockAuthor, NonZeroIssuance},
message_queue::{NarrowOriginToSibling, ParaIdToSibling},
};
use polkadot_runtime_common::xcm_sender::NoPriceForMessageDelivery;
use smallvec::smallvec;
use sp_api::impl_runtime_apis;
@@ -70,7 +73,7 @@ use sp_std::prelude::*;
#[cfg(feature = "std")]
use sp_version::NativeVersion;
use sp_version::RuntimeVersion;
use xcm_config::{AssetsToBlockAuthor, XcmOriginToTransactDispatchOrigin};
use xcm_config::XcmOriginToTransactDispatchOrigin;
#[cfg(any(feature = "std", test))]
pub use sp_runtime::BuildStorage;
@@ -618,7 +621,7 @@ impl pallet_asset_tx_payment::Config for Runtime {
ConvertInto,
pallet_assets::Instance1,
>,
AssetsToBlockAuthor<Runtime>,
AssetsToBlockAuthor<Runtime, pallet_assets::Instance1>,
>;
}
@@ -23,41 +23,39 @@
//! `ReserveAssetTransferDeposited` message but that will but the intension will be to support this
//! soon.
use super::{
AccountId, AllPalletsWithSystem, AssetId as AssetIdPalletAssets, Assets, Balance, Balances,
ForeignAssets, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent,
RuntimeOrigin, WeightToFee, XcmpQueue,
AccountId, AllPalletsWithSystem, AssetId as AssetIdPalletAssets, Assets, Authorship, Balance,
Balances, ForeignAssets, ForeignAssetsInstance, NonZeroIssuance, ParachainInfo,
ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee,
XcmpQueue,
};
use core::marker::PhantomData;
use frame_support::{
parameter_types,
traits::{
fungibles::{self, Balanced, Credit},
ConstU32, Contains, ContainsPair, Everything, Get, Nothing,
},
traits::{ConstU32, Contains, ContainsPair, Everything, EverythingBut, Get, Nothing},
weights::Weight,
};
use frame_system::EnsureRoot;
use pallet_asset_tx_payment::HandleCredit;
use pallet_assets::Instance1;
use pallet_xcm::XcmPassthrough;
use parachains_common::xcm_config::AssetFeeAsExistentialDepositMultiplier;
use polkadot_parachain_primitives::primitives::Sibling;
use polkadot_runtime_common::impls::ToAuthor;
use sp_runtime::traits::Zero;
use sp_runtime::traits::ConvertInto;
use xcm::latest::prelude::*;
use xcm_builder::{
AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses,
AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex,
ConvertedConcreteId, EnsureXcmOrigin, FixedWeightBounds, FrameTransactionalProcessor,
FungibleAdapter, FungiblesAdapter, IsConcrete, LocalMint, NativeAsset, NoChecking,
ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative,
SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32,
SovereignSignedViaLocation, StartsWith, TakeWeightCredit, TrailingSetTopicAsId,
UsingComponents, WithComputedOrigin, WithUniqueTopic,
AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom,
AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex, ConvertedConcreteId, EnsureXcmOrigin,
FixedWeightBounds, FrameTransactionalProcessor, FungibleAdapter, FungiblesAdapter, IsConcrete,
LocalMint, NativeAsset, NoChecking, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative,
SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative,
SignedToAccountId32, SovereignSignedViaLocation, StartsWith, TakeWeightCredit,
TrailingSetTopicAsId, UsingComponents, WithComputedOrigin, WithUniqueTopic,
};
use xcm_executor::{traits::JustTry, XcmExecutor};
parameter_types! {
pub const RelayLocation: Location = Location::parent();
// Local native currency which is stored in `pallet_balances``
pub const PenpalNativeCurrency: Location = Location::here();
pub const RelayNetwork: Option<NetworkId> = None;
pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into();
pub UniversalLocation: InteriorLocation = [Parachain(ParachainInfo::parachain_id().into())].into();
@@ -80,7 +78,7 @@ pub type CurrencyTransactor = FungibleAdapter<
// Use this currency:
Balances,
// Use this currency when it is a fungible asset matching the given location or name:
IsConcrete<RelayLocation>,
IsConcrete<PenpalNativeCurrency>,
// Do a simple punn to convert an AccountId32 Location into a native chain account ID:
LocationToAccountId,
// Our chain's account ID type (we can't get away without mentioning it explicitly):
@@ -123,9 +121,16 @@ pub type FungiblesTransactor = FungiblesAdapter<
CheckingAccount,
>;
/// `AssetId/Balance` converter for `TrustBackedAssets`
pub type ForeignAssetsConvertedConcreteId =
assets_common::ForeignAssetsConvertedConcreteId<StartsWith<RelayLocation>, Balance>;
pub type ForeignAssetsConvertedConcreteId = assets_common::LocationConvertedConcreteId<
EverythingBut<(
// Here we rely on fact that something like this works:
// assert!(Location::new(1,
// [Parachain(100)]).starts_with(&Location::parent()));
// assert!([Parachain(100)].into().starts_with(&Here));
StartsWith<assets_common::matching::LocalLocationPattern>,
)>,
Balance,
>;
/// Means for transacting foreign assets from different global consensus.
pub type ForeignFungiblesTransactor = FungiblesAdapter<
@@ -175,6 +180,7 @@ parameter_types! {
pub UnitWeightCost: Weight = Weight::from_parts(1_000_000_000, 64 * 1024);
pub const MaxInstructions: u32 = 100;
pub const MaxAssetsIntoHolding: u32 = 64;
pub XcmAssetFeesReceiver: Option<AccountId> = Authorship::author();
}
pub struct ParentOrParentsExecutivePlurality;
@@ -184,13 +190,6 @@ impl Contains<Location> for ParentOrParentsExecutivePlurality {
}
}
pub struct CommonGoodAssetsParachain;
impl Contains<Location> for CommonGoodAssetsParachain {
fn contains(location: &Location) -> bool {
matches!(location.unpack(), (1, [Parachain(1000)]))
}
}
pub type Barrier = TrailingSetTopicAsId<(
TakeWeightCredit,
// Expected responses are OK.
@@ -201,12 +200,6 @@ pub type Barrier = TrailingSetTopicAsId<(
// If the message is one that immediately attempts to pay for execution, then
// allow it.
AllowTopLevelPaidExecutionFrom<Everything>,
// System Assets parachain, parent and its exec plurality get free
// execution
AllowExplicitUnpaidExecutionFrom<(
CommonGoodAssetsParachain,
ParentOrParentsExecutivePlurality,
)>,
// Subscriptions for version tracking are OK.
AllowSubscriptionsFrom<Everything>,
),
@@ -246,53 +239,30 @@ impl<T: Get<Location>> ContainsPair<Asset, Location> for NativeAssetFrom<T> {
}
}
/// Allow checking in assets that have issuance > 0.
pub struct NonZeroIssuance<AccountId, Assets>(PhantomData<(AccountId, Assets)>);
impl<AccountId, Assets> Contains<<Assets as fungibles::Inspect<AccountId>>::AssetId>
for NonZeroIssuance<AccountId, Assets>
where
Assets: fungibles::Inspect<AccountId>,
{
fn contains(id: &<Assets as fungibles::Inspect<AccountId>>::AssetId) -> bool {
!Assets::total_issuance(id.clone()).is_zero()
}
}
/// A `HandleCredit` implementation that naively transfers the fees to the block author.
/// Will drop and burn the assets in case the transfer fails.
pub struct AssetsToBlockAuthor<R>(PhantomData<R>);
impl<R> HandleCredit<AccountIdOf<R>, pallet_assets::Pallet<R, Instance1>> for AssetsToBlockAuthor<R>
where
R: pallet_authorship::Config + pallet_assets::Config<Instance1>,
AccountIdOf<R>: From<polkadot_primitives::AccountId> + Into<polkadot_primitives::AccountId>,
{
fn handle_credit(credit: Credit<AccountIdOf<R>, pallet_assets::Pallet<R, Instance1>>) {
if let Some(author) = pallet_authorship::Pallet::<R>::author() {
// In case of error: Will drop the result triggering the `OnDrop` of the imbalance.
let _ = pallet_assets::Pallet::<R, Instance1>::resolve(&author, credit);
}
}
}
// This asset can be added to AH as Asset and reserved transfer between Penpal and AH
pub const RESERVABLE_ASSET_ID: u32 = 1;
// This asset can be added to AH as ForeignAsset and teleported between Penpal and AH
pub const TELEPORTABLE_ASSET_ID: u32 = 2;
pub const ASSETS_PALLET_ID: u8 = 50;
pub const ASSET_HUB_ID: u32 = 1000;
parameter_types! {
/// The location that this chain recognizes as the Relay network's Asset Hub.
pub SystemAssetHubLocation: Location = Location::new(1, [Parachain(1000)]);
// ALWAYS ensure that the index in PalletInstance stays up-to-date with
pub SystemAssetHubLocation: Location = Location::new(1, [Parachain(ASSET_HUB_ID)]);
// the Relay Chain's Asset Hub's Assets pallet index
pub SystemAssetHubAssetsPalletLocation: Location =
Location::new(1, [Parachain(1000), PalletInstance(50)]);
Location::new(1, [Parachain(ASSET_HUB_ID), PalletInstance(ASSETS_PALLET_ID)]);
pub AssetsPalletLocation: Location =
Location::new(0, [PalletInstance(50)]);
Location::new(0, [PalletInstance(ASSETS_PALLET_ID)]);
pub CheckingAccount: AccountId = PolkadotXcm::check_account();
pub LocalTeleportableToAssetHub: Location = Location::new(
0,
[PalletInstance(50), GeneralIndex(TELEPORTABLE_ASSET_ID.into())]
[PalletInstance(ASSETS_PALLET_ID), GeneralIndex(TELEPORTABLE_ASSET_ID.into())]
);
pub LocalTeleportableToAssetHubV3: xcm::v3::Location = xcm::v3::Location::new(
0,
[xcm::v3::Junction::PalletInstance(50), xcm::v3::Junction::GeneralIndex(TELEPORTABLE_ASSET_ID.into())]
pub LocalReservableFromAssetHub: Location = Location::new(
1,
[Parachain(ASSET_HUB_ID), PalletInstance(ASSETS_PALLET_ID), GeneralIndex(RESERVABLE_ASSET_ID.into())]
);
/// The Penpal runtime is utilized for testing with various environment setups.
@@ -337,8 +307,22 @@ impl xcm_executor::Config for XcmConfig {
type UniversalLocation = UniversalLocation;
type Barrier = Barrier;
type Weigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
type Trader =
UsingComponents<WeightToFee, RelayLocation, AccountId, Balances, ToAuthor<Runtime>>;
type Trader = (
UsingComponents<WeightToFee, RelayLocation, AccountId, Balances, ToAuthor<Runtime>>,
// This trader allows to pay with `is_sufficient=true` "Foreign" assets from dedicated
// `pallet_assets` instance - `ForeignAssets`.
cumulus_primitives_utility::TakeFirstAssetTrader<
AccountId,
ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger,
ForeignAssetsConvertedConcreteId,
ForeignAssets,
cumulus_primitives_utility::XcmFeesTo32ByteAccount<
ForeignFungiblesTransactor,
AccountId,
XcmAssetFeesReceiver,
>,
>,
);
type ResponseHandler = PolkadotXcm;
type AssetTrap = PolkadotXcm;
type AssetClaims = PolkadotXcm;
@@ -356,6 +340,15 @@ impl xcm_executor::Config for XcmConfig {
type TransactionalProcessor = FrameTransactionalProcessor;
}
/// Multiplier used for dedicated `TakeFirstAssetTrader` with `ForeignAssets` instance.
pub type ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger =
AssetFeeAsExistentialDepositMultiplier<
Runtime,
WeightToFee,
pallet_assets::BalanceToAssetBalance<Balances, Runtime, ConvertInto, ForeignAssetsInstance>,
ForeignAssetsInstance,
>;
/// No local origins on this chain are allowed to dispatch XCM sends/executions.
pub type LocalOriginToLocation = SignedToAccountId32<RuntimeOrigin, AccountId, RelayNetwork>;