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", "pallet-xcm",
"parachains-common", "parachains-common",
"parity-scale-codec", "parity-scale-codec",
"penpal-runtime",
"rococo-runtime", "rococo-runtime",
"rococo-system-emulated-network", "rococo-system-emulated-network",
"sp-runtime", "sp-runtime",
@@ -962,6 +963,7 @@ dependencies = [
"pallet-xcm", "pallet-xcm",
"parachains-common", "parachains-common",
"parity-scale-codec", "parity-scale-codec",
"penpal-runtime",
"polkadot-runtime-common", "polkadot-runtime-common",
"sp-runtime", "sp-runtime",
"staging-xcm", "staging-xcm",
@@ -4931,6 +4933,7 @@ dependencies = [
"parachains-common", "parachains-common",
"parity-scale-codec", "parity-scale-codec",
"paste", "paste",
"polkadot-parachain-primitives",
"polkadot-primitives", "polkadot-primitives",
"polkadot-runtime-parachains", "polkadot-runtime-parachains",
"sc-consensus-grandpa", "sc-consensus-grandpa",
@@ -11645,9 +11648,8 @@ dependencies = [
"frame-support", "frame-support",
"parachains-common", "parachains-common",
"penpal-runtime", "penpal-runtime",
"rococo-emulated-chain",
"sp-core", "sp-core",
"westend-emulated-chain", "staging-xcm",
] ]
[[package]] [[package]]
@@ -14,17 +14,24 @@
// limitations under the License. // limitations under the License.
// Substrate // Substrate
use sp_core::storage::Storage; use frame_support::parameter_types;
use sp_core::{sr25519, storage::Storage};
// Cumulus // Cumulus
use emulated_integration_tests_common::{ 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 PARA_ID: u32 = 1000;
pub const ED: Balance = testnet_parachains_constants::rococo::currency::EXISTENTIAL_DEPOSIT; 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 { pub fn genesis() -> Storage {
let genesis_config = asset_hub_rococo_runtime::RuntimeGenesisConfig { let genesis_config = asset_hub_rococo_runtime::RuntimeGenesisConfig {
system: asset_hub_rococo_runtime::SystemConfig::default(), system: asset_hub_rococo_runtime::SystemConfig::default(),
@@ -60,6 +67,22 @@ pub fn genesis() -> Storage {
safe_xcm_version: Some(SAFE_XCM_VERSION), safe_xcm_version: Some(SAFE_XCM_VERSION),
..Default::default() ..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() ..Default::default()
}; };
@@ -21,7 +21,7 @@ use frame_support::traits::OnInitialize;
// Cumulus // Cumulus
use emulated_integration_tests_common::{ use emulated_integration_tests_common::{
impl_accounts_helpers_for_parachain, impl_assert_events_helpers_for_parachain, 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, impl_xcm_helpers_for_parachain, impls::Parachain, xcm_emulator::decl_test_parachains,
}; };
use rococo_emulated_chain::Rococo; use rococo_emulated_chain::Rococo;
@@ -54,6 +54,6 @@ decl_test_parachains! {
// AssetHubRococo implementation // AssetHubRococo implementation
impl_accounts_helpers_for_parachain!(AssetHubRococo); impl_accounts_helpers_for_parachain!(AssetHubRococo);
impl_assert_events_helpers_for_parachain!(AssetHubRococo); impl_assert_events_helpers_for_parachain!(AssetHubRococo);
impl_assets_helpers_for_parachain!(AssetHubRococo, Rococo); impl_assets_helpers_for_system_parachain!(AssetHubRococo, Rococo);
impl_foreign_assets_helpers_for_parachain!(AssetHubRococo, Rococo); impl_assets_helpers_for_parachain!(AssetHubRococo);
impl_xcm_helpers_for_parachain!(AssetHubRococo); impl_xcm_helpers_for_parachain!(AssetHubRococo);
@@ -14,17 +14,24 @@
// limitations under the License. // limitations under the License.
// Substrate // Substrate
use sp_core::storage::Storage; use frame_support::parameter_types;
use sp_core::{sr25519, storage::Storage};
// Cumulus // Cumulus
use emulated_integration_tests_common::{ 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 PARA_ID: u32 = 1000;
pub const ED: Balance = testnet_parachains_constants::westend::currency::EXISTENTIAL_DEPOSIT; 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 { pub fn genesis() -> Storage {
let genesis_config = asset_hub_westend_runtime::RuntimeGenesisConfig { let genesis_config = asset_hub_westend_runtime::RuntimeGenesisConfig {
system: asset_hub_westend_runtime::SystemConfig::default(), system: asset_hub_westend_runtime::SystemConfig::default(),
@@ -56,6 +63,22 @@ pub fn genesis() -> Storage {
safe_xcm_version: Some(SAFE_XCM_VERSION), safe_xcm_version: Some(SAFE_XCM_VERSION),
..Default::default() ..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() ..Default::default()
}; };
@@ -21,7 +21,7 @@ use frame_support::traits::OnInitialize;
// Cumulus // Cumulus
use emulated_integration_tests_common::{ use emulated_integration_tests_common::{
impl_accounts_helpers_for_parachain, impl_assert_events_helpers_for_parachain, 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, impl_xcm_helpers_for_parachain, impls::Parachain, xcm_emulator::decl_test_parachains,
}; };
use westend_emulated_chain::Westend; use westend_emulated_chain::Westend;
@@ -54,6 +54,6 @@ decl_test_parachains! {
// AssetHubWestend implementation // AssetHubWestend implementation
impl_accounts_helpers_for_parachain!(AssetHubWestend); impl_accounts_helpers_for_parachain!(AssetHubWestend);
impl_assert_events_helpers_for_parachain!(AssetHubWestend); impl_assert_events_helpers_for_parachain!(AssetHubWestend);
impl_assets_helpers_for_parachain!(AssetHubWestend, Westend); impl_assets_helpers_for_system_parachain!(AssetHubWestend, Westend);
impl_foreign_assets_helpers_for_parachain!(AssetHubWestend, Westend); impl_assets_helpers_for_parachain!(AssetHubWestend);
impl_xcm_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 } sp-core = { path = "../../../../../../../../substrate/primitives/core", default-features = false }
frame-support = { path = "../../../../../../../../substrate/frame/support", default-features = false } frame-support = { path = "../../../../../../../../substrate/frame/support", default-features = false }
# Polkadot
xcm = { package = "staging-xcm", path = "../../../../../../../../polkadot/xcm", default-features = false }
# Cumulus # Cumulus
parachains-common = { path = "../../../../../../../parachains/common" } parachains-common = { path = "../../../../../../../parachains/common" }
cumulus-primitives-core = { path = "../../../../../../../primitives/core", default-features = false } cumulus-primitives-core = { path = "../../../../../../../primitives/core", default-features = false }
emulated-integration-tests-common = { path = "../../../../common", default-features = false } emulated-integration-tests-common = { path = "../../../../common", default-features = false }
penpal-runtime = { path = "../../../../../../runtimes/testing/penpal" } 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. // limitations under the License.
// Substrate // Substrate
use frame_support::parameter_types;
use sp_core::{sr25519, storage::Storage}; use sp_core::{sr25519, storage::Storage};
// Polkadot
use xcm::v3::Location;
// Cumulus // Cumulus
use emulated_integration_tests_common::{ use emulated_integration_tests_common::{
accounts, build_genesis_storage, collators, get_account_id_from_seed, SAFE_XCM_VERSION, 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 // Penpal
pub const PARA_ID_A: u32 = 2000; pub const PARA_ID_A: u32 = 2000;
pub const PARA_ID_B: u32 = 2001; pub const PARA_ID_B: u32 = 2001;
pub const ED: Balance = penpal_runtime::EXISTENTIAL_DEPOSIT; 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 { pub fn genesis(para_id: u32) -> Storage {
let genesis_config = penpal_runtime::RuntimeGenesisConfig { let genesis_config = penpal_runtime::RuntimeGenesisConfig {
system: penpal_runtime::SystemConfig::default(), system: penpal_runtime::SystemConfig::default(),
@@ -58,8 +66,35 @@ pub fn genesis(para_id: u32) -> Storage {
safe_xcm_version: Some(SAFE_XCM_VERSION), safe_xcm_version: Some(SAFE_XCM_VERSION),
..Default::default() ..Default::default()
}, },
sudo: penpal_runtime::SudoConfig { sudo: penpal_runtime::SudoConfig { key: Some(PenpalSudoAcccount::get()) },
key: Some(get_account_id_from_seed::<sr25519::Public>("Alice")), 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() ..Default::default()
}; };
@@ -14,10 +14,9 @@
// limitations under the License. // limitations under the License.
mod genesis; 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::{ pub use penpal_runtime::xcm_config::{
CustomizableAssetFromSystemAssetHub, LocalTeleportableToAssetHub, CustomizableAssetFromSystemAssetHub, LocalTeleportableToAssetHub, XcmConfig,
LocalTeleportableToAssetHubV3, XcmConfig,
}; };
// Substrate // Substrate
@@ -28,8 +27,6 @@ use emulated_integration_tests_common::{
impl_accounts_helpers_for_parachain, impl_assert_events_helpers_for_parachain, impl_accounts_helpers_for_parachain, impl_assert_events_helpers_for_parachain,
impl_assets_helpers_for_parachain, impls::Parachain, xcm_emulator::decl_test_parachains, 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 // Penpal Parachain declaration
decl_test_parachains! { decl_test_parachains! {
@@ -76,7 +73,7 @@ decl_test_parachains! {
// Penpal implementation // Penpal implementation
impl_accounts_helpers_for_parachain!(PenpalA); impl_accounts_helpers_for_parachain!(PenpalA);
impl_accounts_helpers_for_parachain!(PenpalB); 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!(PenpalA);
impl_assert_events_helpers_for_parachain!(PenpalB); 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
polkadot-primitives = { path = "../../../../../polkadot/primitives" } polkadot-primitives = { path = "../../../../../polkadot/primitives" }
polkadot-parachain-primitives = { path = "../../../../../polkadot/parachain" }
polkadot-runtime-parachains = { path = "../../../../../polkadot/runtime/parachains" } polkadot-runtime-parachains = { path = "../../../../../polkadot/runtime/parachains" }
xcm = { package = "staging-xcm", path = "../../../../../polkadot/xcm" } xcm = { package = "staging-xcm", path = "../../../../../polkadot/xcm" }
pallet-xcm = { path = "../../../../../polkadot/xcm/pallet-xcm" } pallet-xcm = { path = "../../../../../polkadot/xcm/pallet-xcm" }
@@ -592,7 +592,7 @@ macro_rules! impl_assert_events_helpers_for_parachain {
} }
#[macro_export] #[macro_export]
macro_rules! impl_assets_helpers_for_parachain { macro_rules! impl_assets_helpers_for_system_parachain {
( $chain:ident, $relay_chain:ident ) => { ( $chain:ident, $relay_chain:ident ) => {
$crate::impls::paste::paste! { $crate::impls::paste::paste! {
impl<N: $crate::impls::Network> $chain<N> { 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) $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 /// Force create and mint assets making use of the assets pallet
pub fn force_create_and_mint_asset( pub fn force_create_and_mint_asset(
id: u32, id: u32,
@@ -727,8 +695,8 @@ macro_rules! impl_assets_helpers_for_parachain {
} }
#[macro_export] #[macro_export]
macro_rules! impl_foreign_assets_helpers_for_parachain { macro_rules! impl_assets_helpers_for_parachain {
( $chain:ident, $relay_chain:ident ) => { ( $chain:ident) => {
$crate::impls::paste::paste! { $crate::impls::paste::paste! {
impl<N: $crate::impls::Network> $chain<N> { impl<N: $crate::impls::Network> $chain<N> {
/// Create foreign assets using sudo `ForeignAssets::force_create()` /// 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 // Substrate
use beefy_primitives::ecdsa_crypto::AuthorityId as BeefyId; use beefy_primitives::ecdsa_crypto::AuthorityId as BeefyId;
use frame_support::parameter_types;
use grandpa::AuthorityId as GrandpaId; use grandpa::AuthorityId as GrandpaId;
use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
use sp_consensus_babe::AuthorityId as BabeId; use sp_consensus_babe::AuthorityId as BabeId;
use sp_core::{sr25519, storage::Storage, Pair, Public}; use sp_core::{sr25519, storage::Storage, Pair, Public};
use sp_runtime::{ use sp_runtime::{
traits::{IdentifyAccount, Verify}, traits::{AccountIdConversion, IdentifyAccount, Verify},
BuildStorage, MultiSignature, BuildStorage, MultiSignature,
}; };
// Polakdot // Polakdot
use parachains_common::BlockNumber; use parachains_common::BlockNumber;
use polkadot_parachain_primitives::primitives::Sibling;
use polkadot_runtime_parachains::configuration::HostConfiguration; use polkadot_runtime_parachains::configuration::HostConfiguration;
// Cumulus // Cumulus
@@ -49,6 +51,25 @@ pub const SAFE_XCM_VERSION: u32 = xcm::prelude::XCM_VERSION;
type AccountPublic = <MultiSignature as Verify>::Signer; 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 /// Helper function to generate a crypto pair from seed
pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public { pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {
TPublic::Pair::from_string(&format!("//{}", seed), None) TPublic::Pair::from_string(&format!("//{}", seed), None)
@@ -16,16 +16,26 @@
pub use paste; pub use paste;
// Substrate // Substrate
pub use frame_support::{pallet_prelude::Weight, weights::WeightToFee};
pub use pallet_assets;
pub use pallet_balances; pub use pallet_balances;
pub use pallet_message_queue; pub use pallet_message_queue;
pub use pallet_xcm; pub use pallet_xcm;
// Polkadot // 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 // Cumulus
pub use asset_test_utils; pub use asset_test_utils;
pub use cumulus_pallet_xcmp_queue; pub use cumulus_pallet_xcmp_queue;
pub use parachains_common::AccountId;
pub use xcm_emulator::Chain; pub use xcm_emulator::Chain;
#[macro_export] #[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 } cumulus-pallet-parachain-system = { path = "../../../../../../pallets/parachain-system", default-features = false }
testnet-parachains-constants = { path = "../../../../../runtimes/constants", features = ["rococo"] } testnet-parachains-constants = { path = "../../../../../runtimes/constants", features = ["rococo"] }
asset-hub-rococo-runtime = { path = "../../../../../runtimes/assets/asset-hub-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 } emulated-integration-tests-common = { path = "../../../common", default-features = false }
rococo-system-emulated-network = { path = "../../../networks/rococo-system" } rococo-system-emulated-network = { path = "../../../networks/rococo-system" }
@@ -13,20 +13,22 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#[cfg(test)]
mod imports {
pub use codec::Encode; pub use codec::Encode;
// Substrate // Substrate
pub use frame_support::{ pub use frame_support::{
assert_err, assert_ok, assert_err, assert_ok,
pallet_prelude::Weight, pallet_prelude::Weight,
sp_runtime::{AccountId32, DispatchError, DispatchResult}, sp_runtime::{DispatchError, DispatchResult, ModuleError},
traits::fungibles::Inspect, traits::fungibles::Inspect,
}; };
// Polkadot // Polkadot
pub use xcm::{ pub use xcm::{
prelude::{AccountId32 as AccountId32Junction, *}, prelude::{AccountId32 as AccountId32Junction, *},
v3::{self, Error, NetworkId::Rococo as RococoId}, v3,
}; };
// Cumulus // Cumulus
@@ -34,18 +36,22 @@ pub use asset_test_utils::xcm_helpers;
pub use emulated_integration_tests_common::{ pub use emulated_integration_tests_common::{
test_parachain_is_trusted_teleporter, test_parachain_is_trusted_teleporter,
xcm_emulator::{ xcm_emulator::{
assert_expected_events, bx, helpers::weight_within_threshold, Chain, Parachain as Para, assert_expected_events, bx, Chain, Parachain as Para, RelayChain as Relay, Test,
RelayChain as Relay, Test, TestArgs, TestContext, TestExt, TestArgs, TestContext, TestExt,
}, },
xcm_helpers::{xcm_transact_paid_execution, xcm_transact_unpaid_execution}, xcm_helpers::{non_fee_asset, xcm_transact_paid_execution},
PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3, ASSETS_PALLET_ID, RESERVABLE_ASSET_ID, XCM_V3,
}; };
pub use parachains_common::{AccountId, Balance}; pub use parachains_common::Balance;
pub use rococo_system_emulated_network::{ pub use rococo_system_emulated_network::{
asset_hub_rococo_emulated_chain::{ asset_hub_rococo_emulated_chain::{
genesis::ED as ASSET_HUB_ROCOCO_ED, AssetHubRococoParaPallet as AssetHubRococoPallet, 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,
}, },
penpal_emulated_chain::PenpalAParaPallet as PenpalAPallet,
rococo_emulated_chain::{genesis::ED as ROCOCO_ED, RococoRelayPallet as RococoPallet}, rococo_emulated_chain::{genesis::ED as ROCOCO_ED, RococoRelayPallet as RococoPallet},
AssetHubRococoPara as AssetHubRococo, AssetHubRococoParaReceiver as AssetHubRococoReceiver, AssetHubRococoPara as AssetHubRococo, AssetHubRococoParaReceiver as AssetHubRococoReceiver,
AssetHubRococoParaSender as AssetHubRococoSender, BridgeHubRococoPara as BridgeHubRococo, AssetHubRococoParaSender as AssetHubRococoSender, BridgeHubRococoPara as BridgeHubRococo,
@@ -55,17 +61,31 @@ pub use rococo_system_emulated_network::{
RococoRelayReceiver as RococoReceiver, RococoRelaySender as RococoSender, RococoRelayReceiver as RococoReceiver, RococoRelaySender as RococoSender,
}; };
pub const ASSET_ID: u32 = 1; // 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 const ASSET_ID: u32 = 3;
pub const ASSET_MIN_BALANCE: u128 = 1000; pub const ASSET_MIN_BALANCE: u128 = 1000;
// `Assets` pallet index
pub const ASSETS_PALLET_ID: u8 = 50;
pub type RelayToSystemParaTest = Test<Rococo, AssetHubRococo>; pub type RelayToSystemParaTest = Test<Rococo, AssetHubRococo>;
pub type RelayToParaTest = Test<Rococo, PenpalA>; pub type RelayToParaTest = Test<Rococo, PenpalA>;
pub type ParaToRelayTest = Test<PenpalA, Rococo>;
pub type SystemParaToRelayTest = Test<AssetHubRococo, Rococo>; pub type SystemParaToRelayTest = Test<AssetHubRococo, Rococo>;
pub type SystemParaToParaTest = Test<AssetHubRococo, PenpalA>; pub type SystemParaToParaTest = Test<AssetHubRococo, PenpalA>;
pub type ParaToSystemParaTest = Test<PenpalA, AssetHubRococo>; pub type ParaToSystemParaTest = Test<PenpalA, AssetHubRococo>;
pub type ParaToParaTest = Test<PenpalA, PenpalB, Rococo>; pub type ParaToParaThroughRelayTest = Test<PenpalA, PenpalB, Rococo>;
}
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
@@ -18,11 +18,3 @@ mod send;
mod set_xcm_versions; mod set_xcm_versions;
mod swap; mod swap;
mod teleport; 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 // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::*; use crate::imports::*;
/// Relay Chain should be able to execute `Transact` instructions in System Parachain /// Relay Chain should be able to execute `Transact` instructions in System Parachain
/// when `OriginKind::Superuser`. /// 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 /// We tests two things here:
/// in the System Parachain /// - 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] #[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( let para_sovereign_account = AssetHubRococo::sovereign_account_id_of(
AssetHubRococo::sibling_location_of(PenpalA::para_id()), 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 // Encoded `create_asset` call to be executed in AssetHub
AssetHubRococo::force_create_and_mint_asset( let call = AssetHubRococo::create_foreign_asset_call(
ASSET_ID, foreign_asset_at_asset_hub,
ASSET_MIN_BALANCE, ASSET_MIN_BALANCE,
true,
para_sovereign_account.clone(), 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` let origin_kind = OriginKind::Xcm;
// Call values are not relevant let fee_amount = ASSET_HUB_ROCOCO_ED * 1000000;
let call = AssetHubRococo::force_create_asset_call( let system_asset = (Parent, fee_amount).into();
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 root_origin = <PenpalA as Chain>::RuntimeOrigin::root(); let root_origin = <PenpalA as Chain>::RuntimeOrigin::root();
let system_para_destination = PenpalA::sibling_location_of(AssetHubRococo::para_id()).into(); let system_para_destination = PenpalA::sibling_location_of(AssetHubRococo::para_id()).into();
let xcm = xcm_transact_paid_execution( let xcm = xcm_transact_paid_execution(
call, call,
origin_kind, origin_kind,
native_asset, system_asset,
para_sovereign_account.clone(), 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(|| { PenpalA::execute_with(|| {
assert_ok!(<PenpalA as PenpalAPallet>::PolkadotXcm::send( assert_ok!(<PenpalA as PenpalAPallet>::PolkadotXcm::send(
root_origin, root_origin,
@@ -90,13 +95,101 @@ fn send_xcm_from_para_to_system_para_paying_fee_with_assets_works() {
assert_expected_events!( assert_expected_events!(
AssetHubRococo, AssetHubRococo,
vec![ 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 }) => { RuntimeEvent::Assets(pallet_assets::Event::Burned { asset_id, owner, balance }) => {
asset_id: *asset_id == ASSET_ID, asset_id: *asset_id == ASSET_ID,
owner: *owner == para_sovereign_account, owner: *owner == para_sovereign_account,
balance: *balance == fee_amount, balance: *balance == fee_amount,
}, },
RuntimeEvent::Assets(pallet_assets::Event::Issued { asset_id, .. }) => { // Asset created
asset_id: *asset_id == ASSET_ID, 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 // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::*; use crate::imports::*;
#[test] #[test]
fn relay_sets_system_para_xcm_supported_version() { fn relay_sets_system_para_xcm_supported_version() {
@@ -13,9 +13,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::*; use crate::imports::*;
use rococo_system_emulated_network::penpal_emulated_chain::LocalTeleportableToAssetHubV3 as PenpalLocalTeleportableToAssetHubV3;
use sp_runtime::ModuleError;
#[test] #[test]
fn swap_locally_on_chain_using_local_assets() { fn swap_locally_on_chain_using_local_assets() {
@@ -114,49 +112,39 @@ fn swap_locally_on_chain_using_local_assets() {
#[test] #[test]
fn swap_locally_on_chain_using_foreign_assets() { fn swap_locally_on_chain_using_foreign_assets() {
let asset_native = Box::new(asset_hub_rococo_runtime::xcm_config::TokenLocationV3::get()); let asset_native =
let ah_as_seen_by_penpal = PenpalA::sibling_location_of(AssetHubRococo::para_id()); Box::new(v3::Location::try_from(RelayLocation::get()).expect("conversion works"));
let asset_location_on_penpal = PenpalLocalTeleportableToAssetHubV3::get(); let asset_location_on_penpal =
let asset_id_on_penpal = match asset_location_on_penpal.last() { v3::Location::try_from(PenpalLocalTeleportableToAssetHub::get()).expect("conversion works");
Some(v3::Junction::GeneralIndex(id)) => *id as u32,
_ => unreachable!(),
};
let asset_owner_on_penpal = PenpalASender::get();
let foreign_asset_at_asset_hub_rococo = let foreign_asset_at_asset_hub_rococo =
v3::Location::new(1, [v3::Junction::Parachain(PenpalA::para_id().into())]) v3::Location::new(1, [v3::Junction::Parachain(PenpalA::para_id().into())])
.appended_with(asset_location_on_penpal) .appended_with(asset_location_on_penpal)
.unwrap(); .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 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); let sov_penpal_on_ahr = AssetHubRococo::sovereign_account_id_of(penpal_as_seen_by_ah);
AssetHubRococo::fund_accounts(vec![ AssetHubRococo::fund_accounts(vec![
(AssetHubRococoSender::get().into(), 5_000_000 * ROCOCO_ED), /* An account to swap dot // An account to swap dot for something else.
* 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(|| { 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, // (While it might be nice to use batch,
// currently that's disabled due to safe call filters.) // currently that's disabled due to safe call filters.)
type RuntimeEvent = <AssetHubRococo as Chain>::RuntimeEvent; 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( assert_ok!(<AssetHubRococo as AssetHubRococoPallet>::ForeignAssets::mint(
<AssetHubRococo as Chain>::RuntimeOrigin::signed(sov_penpal_on_ahr.clone().into()), <AssetHubRococo as Chain>::RuntimeOrigin::signed(sov_penpal_on_ahr.clone().into()),
foreign_asset_at_asset_hub_rococo, foreign_asset_at_asset_hub_rococo,
sov_penpal_on_ahr.clone().into(), sov_penpal_on_ahr.clone().into(),
3_000_000_000_000, ASSET_HUB_ROCOCO_ED * 3_000_000_000_000,
)); ));
assert_expected_events!( 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( assert_ok!(<AssetHubRococo as AssetHubRococoPallet>::AssetConversion::create_pool(
<AssetHubRococo as Chain>::RuntimeOrigin::signed(AssetHubRococoSender::get()), <AssetHubRococo as Chain>::RuntimeOrigin::signed(AssetHubRococoSender::get()),
asset_native.clone(), 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( assert_ok!(<AssetHubRococo as AssetHubRococoPallet>::AssetConversion::add_liquidity(
<AssetHubRococo as Chain>::RuntimeOrigin::signed(sov_penpal_on_ahr.clone()), <AssetHubRococo as Chain>::RuntimeOrigin::signed(sov_penpal_on_ahr.clone()),
asset_native.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)]; let path = vec![asset_native.clone(), Box::new(foreign_asset_at_asset_hub_rococo)];
assert_ok!( assert_ok!(
<AssetHubRococo as AssetHubRococoPallet>::AssetConversion::swap_exact_tokens_for_tokens( <AssetHubRococo as AssetHubRococoPallet>::AssetConversion::swap_exact_tokens_for_tokens(
<AssetHubRococo as Chain>::RuntimeOrigin::signed(AssetHubRococoSender::get()), <AssetHubRococo as Chain>::RuntimeOrigin::signed(AssetHubRococoSender::get()),
path, path,
100000, 100000 * ASSET_HUB_ROCOCO_ED,
1000, 1000 * ASSET_HUB_ROCOCO_ED,
AssetHubRococoSender::get().into(), AssetHubRococoSender::get().into(),
true true
) )
@@ -219,18 +207,18 @@ fn swap_locally_on_chain_using_foreign_assets() {
AssetHubRococo, AssetHubRococo,
vec![ vec![
RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::SwapExecuted { amount_in, amount_out, .. },) => { RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::SwapExecuted { amount_in, amount_out, .. },) => {
amount_in: *amount_in == 100000, amount_in: *amount_in == 333333300000,
amount_out: *amount_out == 199399, amount_out: *amount_out == 498874118173,
}, },
] ]
); );
// 7. Remove liquidity // 5. Remove liquidity
assert_ok!(<AssetHubRococo as AssetHubRococoPallet>::AssetConversion::remove_liquidity( assert_ok!(<AssetHubRococo as AssetHubRococoPallet>::AssetConversion::remove_liquidity(
<AssetHubRococo as Chain>::RuntimeOrigin::signed(sov_penpal_on_ahr.clone()), <AssetHubRococo as Chain>::RuntimeOrigin::signed(sov_penpal_on_ahr.clone()),
asset_native.clone(), asset_native.clone(),
Box::new(foreign_asset_at_asset_hub_rococo), 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,
0, 0,
sov_penpal_on_ahr.clone().into(), sov_penpal_on_ahr.clone().into(),
@@ -13,11 +13,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::*; use crate::imports::*;
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;
fn relay_origin_assertions(t: RelayToSystemParaTest) { fn relay_origin_assertions(t: RelayToSystemParaTest) {
type RuntimeEvent = <Rococo as Chain>::RuntimeEvent; 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) { fn penpal_to_ah_foreign_assets_sender_assertions(t: ParaToSystemParaTest) {
type RuntimeEvent = <PenpalA as Chain>::RuntimeEvent; 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_id = t.args.asset_id.unwrap();
let (_, expected_asset_amount) = let (_, expected_asset_amount) =
non_fee_asset(&t.args.assets, t.args.fee_asset_item as usize).unwrap(); non_fee_asset(&t.args.assets, t.args.fee_asset_item as usize).unwrap();
PenpalA::assert_xcm_pallet_attempted_complete(None);
assert_expected_events!( assert_expected_events!(
PenpalA, PenpalA,
vec![ vec![
RuntimeEvent::Balances( RuntimeEvent::ForeignAssets(
pallet_balances::Event::Burned { who, amount } pallet_assets::Event::Burned { asset_id, owner, .. }
) => { ) => {
who: *who == t.sender.account_id, asset_id: *asset_id == system_para_native_asset_location,
amount: *amount == t.args.amount, owner: *owner == t.sender.account_id,
}, },
RuntimeEvent::Assets(pallet_assets::Event::Burned { asset_id, owner, balance }) => { RuntimeEvent::Assets(pallet_assets::Event::Burned { asset_id, owner, balance }) => {
asset_id: *asset_id == expected_asset_id, 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) = let (expected_foreign_asset_id, expected_foreign_asset_amount) =
non_fee_asset(&t.args.assets, t.args.fee_asset_item as usize).unwrap(); 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(); let expected_foreign_asset_id_v3: v3::Location = expected_foreign_asset_id.try_into().unwrap();
AssetHubRococo::assert_xcmp_queue_success(None);
assert_expected_events!( assert_expected_events!(
AssetHubRococo, AssetHubRococo,
vec![ vec![
@@ -163,9 +165,6 @@ fn penpal_to_ah_foreign_assets_receiver_assertions(t: ParaToSystemParaTest) {
amount: *amount == expected_foreign_asset_amount, amount: *amount == expected_foreign_asset_amount,
}, },
RuntimeEvent::Balances(pallet_balances::Event::Deposit { .. }) => {}, 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) = let (_, expected_asset_amount) =
non_fee_asset(&t.args.assets, t.args.fee_asset_item as usize).unwrap(); non_fee_asset(&t.args.assets, t.args.fee_asset_item as usize).unwrap();
let checking_account = <PenpalA as PenpalAPallet>::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!( assert_expected_events!(
PenpalA, PenpalA,
vec![ vec![
@@ -221,12 +225,11 @@ fn ah_to_penpal_foreign_assets_receiver_assertions(t: SystemParaToParaTest) {
amount: *amount == expected_asset_amount, amount: *amount == expected_asset_amount,
}, },
// native asset for fee is deposited to receiver // native asset for fee is deposited to receiver
RuntimeEvent::Balances(pallet_balances::Event::Minted { who, .. }) => { RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { asset_id, owner, amount }) => {
who: *who == t.receiver.account_id, 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) /// (using native reserve-based transfer for fees)
#[test] #[test]
fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() { fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() {
let ah_as_seen_by_penpal = PenpalA::sibling_location_of(AssetHubRococo::para_id()); // Init values for Parachain
let asset_location_on_penpal = PenpalLocalTeleportableToAssetHubV3::get(); 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() { let asset_id_on_penpal = match asset_location_on_penpal.last() {
Some(v3::Junction::GeneralIndex(id)) => *id as u32, Some(v3::Junction::GeneralIndex(id)) => *id as u32,
_ => unreachable!(), _ => unreachable!(),
}; };
let asset_owner_on_penpal = PenpalASender::get(); let asset_amount_to_send = ASSET_HUB_ROCOCO_ED * 1000;
let foreign_asset_at_asset_hub_rococo = let asset_owner = PenpalAssetOwner::get();
v3::Location::new(1, [v3::Junction::Parachain(PenpalA::para_id().into())]) let system_para_native_asset_location =
.appended_with(asset_location_on_penpal) v3::Location::try_from(RelayLocation::get()).expect("conversion works");
.unwrap(); let sender = PenpalASender::get();
super::penpal_create_foreign_asset_on_asset_hub( let penpal_check_account = <PenpalA as PenpalAPallet>::PolkadotXcm::check_account();
asset_id_on_penpal, let ah_as_seen_by_penpal = PenpalA::sibling_location_of(AssetHubRococo::para_id());
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_location_on_penpal_latest: Location = asset_location_on_penpal.try_into().unwrap(); let asset_location_on_penpal_latest: Location = asset_location_on_penpal.try_into().unwrap();
let penpal_assets: Assets = vec![ let penpal_assets: Assets = vec![
(Parent, fee_amount_to_send).into(), (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()) .position(|r| r == &(Parent, fee_amount_to_send).into())
.unwrap() as u32; .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 // Penpal to AH test args
let penpal_to_ah_test_args = TestContext { let penpal_to_ah_test_args = TestContext {
sender: PenpalASender::get(), 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 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 ah_receiver_balance_before = penpal_to_ah.receiver.balance;
let penpal_sender_assets_before = PenpalA::execute_with(|| { 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.set_dispatchable::<PenpalA>(para_to_system_para_transfer_assets);
penpal_to_ah.assert(); 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 ah_receiver_balance_after = penpal_to_ah.receiver.balance;
let penpal_sender_assets_after = PenpalA::execute_with(|| { 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 mut ah_to_penpal = SystemParaToParaTest::new(ah_to_penpal_test_args);
let ah_sender_balance_before = ah_to_penpal.sender.balance; 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(|| { let ah_sender_assets_before = AssetHubRococo::execute_with(|| {
type ForeignAssets = <AssetHubRococo as AssetHubRococoPallet>::ForeignAssets; type ForeignAssets = <AssetHubRococo as AssetHubRococoPallet>::ForeignAssets;
@@ -724,7 +769,13 @@ fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() {
ah_to_penpal.assert(); ah_to_penpal.assert();
let ah_sender_balance_after = ah_to_penpal.sender.balance; 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(|| { let ah_sender_assets_after = AssetHubRococo::execute_with(|| {
type ForeignAssets = <AssetHubRococo as AssetHubRococoPallet>::ForeignAssets; type ForeignAssets = <AssetHubRococo as AssetHubRococoPallet>::ForeignAssets;
@@ -33,6 +33,7 @@ westend-runtime = { path = "../../../../../../../polkadot/runtime/westend" }
# Cumulus # Cumulus
parachains-common = { path = "../../../../../../parachains/common" } parachains-common = { path = "../../../../../../parachains/common" }
testnet-parachains-constants = { path = "../../../../../runtimes/constants", features = ["westend"] } 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-hub-westend-runtime = { path = "../../../../../runtimes/assets/asset-hub-westend" }
asset-test-utils = { path = "../../../../../runtimes/assets/test-utils" } asset-test-utils = { path = "../../../../../runtimes/assets/test-utils" }
cumulus-pallet-xcmp-queue = { default-features = false, path = "../../../../../../pallets/xcmp-queue" } cumulus-pallet-xcmp-queue = { default-features = false, path = "../../../../../../pallets/xcmp-queue" }
@@ -13,22 +13,22 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#[cfg(test)]
mod imports {
pub use codec::Encode; pub use codec::Encode;
// Substrate // Substrate
pub use frame_support::{ pub use frame_support::{
assert_err, assert_ok, assert_err, assert_ok,
instances::Instance2,
pallet_prelude::Weight, pallet_prelude::Weight,
sp_runtime::{AccountId32, DispatchError, DispatchResult, ModuleError}, sp_runtime::{DispatchError, DispatchResult, ModuleError},
traits::fungibles::Inspect, traits::fungibles::Inspect,
BoundedVec,
}; };
// Polkadot // Polkadot
pub use xcm::{ pub use xcm::{
prelude::{AccountId32 as AccountId32Junction, *}, prelude::{AccountId32 as AccountId32Junction, *},
v3::{self, Error, NetworkId::Westend as WestendId}, v3,
}; };
// Cumulus // Cumulus
@@ -36,44 +36,60 @@ pub use asset_test_utils::xcm_helpers;
pub use emulated_integration_tests_common::{ pub use emulated_integration_tests_common::{
test_parachain_is_trusted_teleporter, test_parachain_is_trusted_teleporter,
xcm_emulator::{ xcm_emulator::{
assert_expected_events, bx, helpers::weight_within_threshold, Chain, Parachain as Para, assert_expected_events, bx, Chain, Parachain as Para, RelayChain as Relay, Test,
RelayChain as Relay, Test, TestArgs, TestContext, TestExt, TestArgs, TestContext, TestExt,
}, },
xcm_helpers::{xcm_transact_paid_execution, xcm_transact_unpaid_execution}, xcm_helpers::{non_fee_asset, xcm_transact_paid_execution},
PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3, ASSETS_PALLET_ID, RESERVABLE_ASSET_ID, XCM_V3,
}; };
pub use parachains_common::{AccountId, Balance}; pub use parachains_common::{AccountId, Balance};
pub use westend_system_emulated_network::{ pub use westend_system_emulated_network::{
asset_hub_westend_emulated_chain::{ asset_hub_westend_emulated_chain::{
genesis::ED as ASSET_HUB_WESTEND_ED, AssetHubWestendParaPallet as AssetHubWestendPallet, genesis::{AssetHubWestendAssetOwner, ED as ASSET_HUB_WESTEND_ED},
AssetHubWestendParaPallet as AssetHubWestendPallet,
}, },
collectives_westend_emulated_chain::{ collectives_westend_emulated_chain::CollectivesWestendParaPallet as CollectivesWestendPallet,
genesis::ED as COLLECTIVES_WESTEND_ED, penpal_emulated_chain::{
CollectivesWestendParaPallet as CollectivesWestendPallet, PenpalAParaPallet as PenpalAPallet, PenpalAssetOwner,
PenpalBParaPallet as PenpalBPallet,
}, },
penpal_emulated_chain::PenpalBParaPallet as PenpalBPallet,
westend_emulated_chain::{genesis::ED as WESTEND_ED, WestendRelayPallet as WestendPallet}, westend_emulated_chain::{genesis::ED as WESTEND_ED, WestendRelayPallet as WestendPallet},
AssetHubWestendPara as AssetHubWestend, AssetHubWestendParaReceiver as AssetHubWestendReceiver, AssetHubWestendPara as AssetHubWestend,
AssetHubWestendParaSender as AssetHubWestendSender, BridgeHubWestendPara as BridgeHubWestend, AssetHubWestendParaReceiver as AssetHubWestendReceiver,
AssetHubWestendParaSender as AssetHubWestendSender,
BridgeHubWestendPara as BridgeHubWestend,
BridgeHubWestendParaReceiver as BridgeHubWestendReceiver, BridgeHubWestendParaReceiver as BridgeHubWestendReceiver,
CollectivesWestendPara as CollectivesWestend, PenpalAPara as PenpalA, CollectivesWestendPara as CollectivesWestend, PenpalAPara as PenpalA,
PenpalAParaReceiver as PenpalAReceiver, PenpalBPara as PenpalB, PenpalAParaReceiver as PenpalAReceiver, PenpalAParaSender as PenpalASender,
PenpalBParaReceiver as PenpalBReceiver, PenpalBParaSender as PenpalBSender, PenpalBPara as PenpalB, PenpalBParaReceiver as PenpalBReceiver, WestendRelay as Westend,
WestendRelay as Westend, WestendRelayReceiver as WestendReceiver, WestendRelayReceiver as WestendReceiver, WestendRelaySender as WestendSender,
WestendRelaySender as WestendSender,
}; };
pub const ASSET_ID: u32 = 1; // 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 const ASSET_ID: u32 = 3;
pub const ASSET_MIN_BALANCE: u128 = 1000; pub const ASSET_MIN_BALANCE: u128 = 1000;
// `Assets` pallet index
pub const ASSETS_PALLET_ID: u8 = 50;
pub type RelayToSystemParaTest = Test<Westend, AssetHubWestend>; pub type RelayToSystemParaTest = Test<Westend, AssetHubWestend>;
pub type RelayToParaTest = Test<Westend, PenpalB>; pub type RelayToParaTest = Test<Westend, PenpalA>;
pub type ParaToRelayTest = Test<PenpalA, Westend>;
pub type SystemParaToRelayTest = Test<AssetHubWestend, Westend>; pub type SystemParaToRelayTest = Test<AssetHubWestend, Westend>;
pub type SystemParaToParaTest = Test<AssetHubWestend, PenpalB>; pub type SystemParaToParaTest = Test<AssetHubWestend, PenpalA>;
pub type ParaToSystemParaTest = Test<PenpalB, AssetHubWestend>; pub type ParaToSystemParaTest = Test<PenpalA, AssetHubWestend>;
pub type ParaToParaTest = Test<PenpalB, PenpalA, Westend>; pub type ParaToParaThroughRelayTest = Test<PenpalA, PenpalB, Westend>;
}
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
@@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::*; use crate::imports::*;
use emulated_integration_tests_common::accounts::{ALICE, BOB}; use emulated_integration_tests_common::accounts::{ALICE, BOB};
use frame_support::traits::fungibles::{Create, Inspect, Mutate}; use frame_support::traits::fungibles::{Create, Inspect, Mutate};
use polkadot_runtime_common::impls::VersionedLocatableAsset; use polkadot_runtime_common::impls::VersionedLocatableAsset;
@@ -20,11 +20,3 @@ mod set_xcm_versions;
mod swap; mod swap;
mod teleport; mod teleport;
mod treasury; 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 // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::*; use crate::imports::*;
/// Relay Chain should be able to execute `Transact` instructions in System Parachain /// Relay Chain should be able to execute `Transact` instructions in System Parachain
/// when `OriginKind::Superuser`. /// 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 /// We tests two things here:
/// in the System Parachain /// - 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] #[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_assets_works() {
let para_sovereign_account = AssetHubWestend::sovereign_account_id_of( 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 // 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, ASSET_MIN_BALANCE * 1000000000,
); );
// We just need a call that can pass the `SafeCallFilter` // Just a different `asset_id`` that does not exist yet
// Call values are not relevant let new_asset_id = ASSET_ID + 1;
let call = AssetHubWestend::force_create_asset_call(
ASSET_ID, // Encoded `create_asset` call to be executed in AssetHub
para_sovereign_account.clone(), let call = AssetHubWestend::create_asset_call(
true, new_asset_id,
ASSET_MIN_BALANCE, ASSET_MIN_BALANCE,
para_sovereign_account.clone(),
); );
let origin_kind = OriginKind::SovereignAccount; let origin_kind = OriginKind::SovereignAccount;
let fee_amount = ASSET_MIN_BALANCE * 1000000; let fee_amount = ASSET_MIN_BALANCE * 1000000;
let native_asset = let asset =
([PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())], fee_amount).into(); ([PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())], fee_amount).into();
let root_origin = <PenpalB as Chain>::RuntimeOrigin::root(); let root_origin = <PenpalA as Chain>::RuntimeOrigin::root();
let system_para_destination = PenpalB::sibling_location_of(AssetHubWestend::para_id()).into(); let system_para_destination = PenpalA::sibling_location_of(AssetHubWestend::para_id()).into();
let xcm = xcm_transact_paid_execution( let xcm = xcm_transact_paid_execution(call, origin_kind, asset, para_sovereign_account.clone());
call,
origin_kind,
native_asset,
para_sovereign_account.clone(),
);
PenpalB::execute_with(|| { // SA-of-Penpal-on-AHR needs to have balance to pay for asset creation deposit
assert_ok!(<PenpalB as PenpalBPallet>::PolkadotXcm::send( 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, root_origin,
bx!(system_para_destination), bx!(system_para_destination),
bx!(xcm), bx!(xcm),
)); ));
PenpalB::assert_xcm_pallet_sent(); PenpalA::assert_xcm_pallet_sent();
}); });
AssetHubWestend::execute_with(|| { AssetHubWestend::execute_with(|| {
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent; type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
AssetHubWestend::assert_xcmp_queue_success(Some(Weight::from_parts( AssetHubWestend::assert_xcmp_queue_success(Some(Weight::from_parts(
16_290_336_000, 15_594_564_000,
562_893, 562_893,
))); )));
assert_expected_events!( assert_expected_events!(
AssetHubWestend, AssetHubWestend,
vec![ vec![
// Burned the fee
RuntimeEvent::Assets(pallet_assets::Event::Burned { asset_id, owner, balance }) => { RuntimeEvent::Assets(pallet_assets::Event::Burned { asset_id, owner, balance }) => {
asset_id: *asset_id == ASSET_ID, asset_id: *asset_id == ASSET_ID,
owner: *owner == para_sovereign_account, owner: *owner == para_sovereign_account,
balance: *balance == fee_amount, balance: *balance == fee_amount,
}, },
RuntimeEvent::Assets(pallet_assets::Event::Issued { asset_id, .. }) => { // Asset created
asset_id: *asset_id == ASSET_ID, 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 // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::*; use crate::imports::*;
#[test] #[test]
fn relay_sets_system_para_xcm_supported_version() { fn relay_sets_system_para_xcm_supported_version() {
@@ -13,8 +13,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::*; use crate::imports::*;
use westend_system_emulated_network::penpal_emulated_chain::LocalTeleportableToAssetHubV3 as PenpalLocalTeleportableToAssetHubV3;
#[test] #[test]
fn swap_locally_on_chain_using_local_assets() { fn swap_locally_on_chain_using_local_assets() {
@@ -112,49 +111,39 @@ fn swap_locally_on_chain_using_local_assets() {
#[test] #[test]
fn swap_locally_on_chain_using_foreign_assets() { fn swap_locally_on_chain_using_foreign_assets() {
let asset_native = Box::new(asset_hub_westend_runtime::xcm_config::WestendLocationV3::get()); let asset_native =
let ah_as_seen_by_penpal = PenpalB::sibling_location_of(AssetHubWestend::para_id()); Box::new(v3::Location::try_from(RelayLocation::get()).expect("conversion works"));
let asset_location_on_penpal = PenpalLocalTeleportableToAssetHubV3::get(); let asset_location_on_penpal =
let asset_id_on_penpal = match asset_location_on_penpal.last() { v3::Location::try_from(PenpalLocalTeleportableToAssetHub::get()).expect("conversion_works");
Some(v3::Junction::GeneralIndex(id)) => *id as u32,
_ => unreachable!(),
};
let asset_owner_on_penpal = PenpalBSender::get();
let foreign_asset_at_asset_hub_westend = 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) .appended_with(asset_location_on_penpal)
.unwrap(); .unwrap();
// 1. Create asset on penpal and, 2. Create foreign asset on asset_hub_westend let penpal_as_seen_by_ah = AssetHubWestend::sibling_location_of(PenpalA::para_id());
super::penpal_create_foreign_asset_on_asset_hub( let sov_penpal_on_ahr = AssetHubWestend::sovereign_account_id_of(penpal_as_seen_by_ah);
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);
AssetHubWestend::fund_accounts(vec![ AssetHubWestend::fund_accounts(vec![
(AssetHubWestendSender::get().into(), 5_000_000 * WESTEND_ED), /* An account to swap dot // An account to swap dot for something else.
* 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(|| { 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, // (While it might be nice to use batch,
// currently that's disabled due to safe call filters.) // currently that's disabled due to safe call filters.)
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent; 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( 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, foreign_asset_at_asset_hub_westend,
sov_penpal_on_ahw.clone().into(), sov_penpal_on_ahr.clone().into(),
3_000_000_000_000, ASSET_HUB_WESTEND_ED * 3_000_000_000_000,
)); ));
assert_expected_events!( 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( assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::create_pool(
<AssetHubWestend as Chain>::RuntimeOrigin::signed(AssetHubWestendSender::get()), <AssetHubWestend as Chain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
asset_native.clone(), 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( 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(), asset_native.clone(),
Box::new(foreign_asset_at_asset_hub_westend), Box::new(foreign_asset_at_asset_hub_westend),
1_000_000_000_000, 1_000_000_000_000_000,
2_000_000_000_000, 2_000_000_000_000_000,
0, 0,
0, 0,
sov_penpal_on_ahw.clone().into() sov_penpal_on_ahr.clone().into()
)); ));
assert_expected_events!( assert_expected_events!(
AssetHubWestend, AssetHubWestend,
vec![ vec![
RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::LiquidityAdded {lp_token_minted, .. }) => { 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)]; 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( assert_ok!(
<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::swap_exact_tokens_for_tokens(
<AssetHubWestend as Chain>::RuntimeOrigin::signed(AssetHubWestendSender::get()), <AssetHubWestend as Chain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
path, path,
100000, 100000 * ASSET_HUB_WESTEND_ED,
1000, 1000 * ASSET_HUB_WESTEND_ED,
AssetHubWestendSender::get().into(), AssetHubWestendSender::get().into(),
true true
)); )
);
assert_expected_events!( assert_expected_events!(
AssetHubWestend, AssetHubWestend,
vec![ vec![
RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::SwapExecuted { amount_in, amount_out, .. },) => { RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::SwapExecuted { amount_in, amount_out, .. },) => {
amount_in: *amount_in == 100000, amount_in: *amount_in == 100000000000000,
amount_out: *amount_out == 199399, amount_out: *amount_out == 181322178776029,
}, },
] ]
); );
// 7. Remove liquidity // 5. Remove liquidity
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::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(), asset_native.clone(),
Box::new(foreign_asset_at_asset_hub_westend), 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,
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(), .into(),
}; };
let penpal = AssetHubWestend::sovereign_account_id_of(AssetHubWestend::sibling_location_of( let penpal = AssetHubWestend::sovereign_account_id_of(AssetHubWestend::sibling_location_of(
PenpalB::para_id(), PenpalA::para_id(),
)); ));
AssetHubWestend::execute_with(|| { 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 // send xcm transact from `penpal` account which as only `ASSET_ID` tokens on
// `AssetHubWestend` // `AssetHubWestend`
let call = AssetHubWestend::force_create_asset_call( let call = AssetHubWestend::force_create_asset_call(
@@ -366,11 +357,11 @@ fn pay_xcm_fee_with_some_asset_swapped_for_native() {
ASSET_MIN_BALANCE, 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 fee_amount = 4_000_000_000_000u128;
let asset_one = let asset_one =
([PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())], fee_amount).into(); ([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( let xcm = xcm_transact_paid_execution(
call, call,
OriginKind::SovereignAccount, OriginKind::SovereignAccount,
@@ -378,13 +369,13 @@ fn pay_xcm_fee_with_some_asset_swapped_for_native() {
penpal.clone(), penpal.clone(),
); );
assert_ok!(<PenpalB as PenpalBPallet>::PolkadotXcm::send( assert_ok!(<PenpalA as PenpalAPallet>::PolkadotXcm::send(
penpal_root, penpal_root,
bx!(asset_hub_location), bx!(asset_hub_location),
bx!(xcm), bx!(xcm),
)); ));
PenpalB::assert_xcm_pallet_sent(); PenpalA::assert_xcm_pallet_sent();
}); });
AssetHubWestend::execute_with(|| { AssetHubWestend::execute_with(|| {
@@ -13,16 +13,12 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::*; use crate::imports::*;
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;
fn relay_origin_assertions(t: RelayToSystemParaTest) { fn relay_origin_assertions(t: RelayToSystemParaTest) {
type RuntimeEvent = <Westend as Chain>::RuntimeEvent; 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!( assert_expected_events!(
Westend, Westend,
@@ -47,7 +43,7 @@ fn relay_dest_assertions(t: SystemParaToRelayTest) {
Westend::assert_ump_queue_processed( Westend::assert_ump_queue_processed(
true, true,
Some(AssetHubWestend::para_id()), 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!( assert_expected_events!(
@@ -70,7 +66,7 @@ fn relay_dest_assertions_fail(_t: SystemParaToRelayTest) {
Westend::assert_ump_queue_processed( Westend::assert_ump_queue_processed(
false, false,
Some(AssetHubWestend::para_id()), 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; type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
AssetHubWestend::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts( AssetHubWestend::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(
533_910_000, 720_053_000,
7167, 7_203,
))); )));
AssetHubWestend::assert_parachain_system_ump_sent(); AssetHubWestend::assert_parachain_system_ump_sent();
@@ -99,7 +95,7 @@ fn para_origin_assertions(t: SystemParaToRelayTest) {
fn para_dest_assertions(t: RelayToSystemParaTest) { fn para_dest_assertions(t: RelayToSystemParaTest) {
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent; 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!( assert_expected_events!(
AssetHubWestend, AssetHubWestend,
@@ -113,19 +109,22 @@ fn para_dest_assertions(t: RelayToSystemParaTest) {
} }
fn penpal_to_ah_foreign_assets_sender_assertions(t: ParaToSystemParaTest) { fn penpal_to_ah_foreign_assets_sender_assertions(t: ParaToSystemParaTest) {
type RuntimeEvent = <PenpalB as Chain>::RuntimeEvent; type RuntimeEvent = <PenpalA as Chain>::RuntimeEvent;
PenpalB::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_id = t.args.asset_id.unwrap();
let (_, expected_asset_amount) = let (_, expected_asset_amount) =
non_fee_asset(&t.args.assets, t.args.fee_asset_item as usize).unwrap(); non_fee_asset(&t.args.assets, t.args.fee_asset_item as usize).unwrap();
PenpalA::assert_xcm_pallet_attempted_complete(None);
assert_expected_events!( assert_expected_events!(
PenpalB, PenpalA,
vec![ vec![
RuntimeEvent::Balances( RuntimeEvent::ForeignAssets(
pallet_balances::Event::Burned { who, amount } pallet_assets::Event::Burned { asset_id, owner, .. }
) => { ) => {
who: *who == t.sender.account_id, asset_id: *asset_id == system_para_native_asset_location,
amount: *amount == t.args.amount, owner: *owner == t.sender.account_id,
}, },
RuntimeEvent::Assets(pallet_assets::Event::Burned { asset_id, owner, balance }) => { RuntimeEvent::Assets(pallet_assets::Event::Burned { asset_id, owner, balance }) => {
asset_id: *asset_id == expected_asset_id, 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) { fn penpal_to_ah_foreign_assets_receiver_assertions(t: ParaToSystemParaTest) {
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent; type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
let sov_penpal_on_ahr = AssetHubWestend::sovereign_account_id_of( 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) = let (expected_foreign_asset_id, expected_foreign_asset_amount) =
non_fee_asset(&t.args.assets, t.args.fee_asset_item as usize).unwrap(); 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(); let expected_foreign_asset_id_v3: v3::Location = expected_foreign_asset_id.try_into().unwrap();
AssetHubWestend::assert_xcmp_queue_success(None);
assert_expected_events!( assert_expected_events!(
AssetHubWestend, AssetHubWestend,
vec![ vec![
@@ -163,9 +165,6 @@ fn penpal_to_ah_foreign_assets_receiver_assertions(t: ParaToSystemParaTest) {
amount: *amount == expected_foreign_asset_amount, amount: *amount == expected_foreign_asset_amount,
}, },
RuntimeEvent::Balances(pallet_balances::Event::Deposit { .. }) => {}, 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) { 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_id = t.args.asset_id.unwrap();
let (_, expected_asset_amount) = let (_, expected_asset_amount) =
non_fee_asset(&t.args.assets, t.args.fee_asset_item as usize).unwrap(); 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!( assert_expected_events!(
PenpalB, PenpalA,
vec![ vec![
// checking account burns local asset as part of incoming teleport // checking account burns local asset as part of incoming teleport
RuntimeEvent::Assets(pallet_assets::Event::Burned { asset_id, owner, balance }) => { 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, amount: *amount == expected_asset_amount,
}, },
// native asset for fee is deposited to receiver // native asset for fee is deposited to receiver
RuntimeEvent::Balances(pallet_balances::Event::Minted { who, .. }) => { RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { asset_id, owner, amount }) => {
who: *who == t.receiver.account_id, 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 { fn para_to_system_para_transfer_assets(t: ParaToSystemParaTest) -> DispatchResult {
<AssetHubWestend as AssetHubWestendPallet>::PolkadotXcm::transfer_assets( <PenpalA as PenpalAPallet>::PolkadotXcm::transfer_assets(
t.signed_origin, t.signed_origin,
bx!(t.args.dest.into()), bx!(t.args.dest.into()),
bx!(t.args.beneficiary.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 { fn system_para_to_para_transfer_assets(t: SystemParaToParaTest) -> DispatchResult {
<PenpalB as PenpalBPallet>::PolkadotXcm::transfer_assets( <AssetHubWestend as AssetHubWestendPallet>::PolkadotXcm::transfer_assets(
t.signed_origin, t.signed_origin,
bx!(t.args.dest.into()), bx!(t.args.dest.into()),
bx!(t.args.beneficiary.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 // Init values for Relay Chain
let amount_to_send: Balance = WESTEND_ED * 1000; let amount_to_send: Balance = WESTEND_ED * 1000;
let dest = Westend::child_location_of(AssetHubWestend::para_id()); let dest = Westend::child_location_of(AssetHubWestend::para_id());
let beneficiary = AssetHubWestendReceiver::get(); let beneficiary_id = AssetHubWestendReceiver::get();
let test_args = TestContext { let test_args = TestContext {
sender: WestendSender::get(), sender: WestendSender::get(),
receiver: beneficiary.clone(), receiver: AssetHubWestendReceiver::get(),
args: TestArgs::new_relay(dest, beneficiary, amount_to_send), args: TestArgs::new_relay(dest, beneficiary_id, amount_to_send),
}; };
let mut test = RelayToSystemParaTest::new(test_args); 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 // Init values for Relay Chain
let amount_to_send: Balance = WESTEND_ED * 1000; let amount_to_send: Balance = WESTEND_ED * 1000;
let dest = Westend::child_location_of(AssetHubWestend::para_id()); let dest = Westend::child_location_of(AssetHubWestend::para_id());
let beneficiary = AssetHubWestendReceiver::get(); let beneficiary_id = AssetHubWestendReceiver::get();
let test_args = TestContext { let test_args = TestContext {
sender: WestendSender::get(), sender: WestendSender::get(),
receiver: beneficiary.clone(), receiver: AssetHubWestendReceiver::get(),
args: TestArgs::new_relay(dest, beneficiary, amount_to_send), args: TestArgs::new_relay(dest, beneficiary_id, amount_to_send),
}; };
let mut test = RelayToSystemParaTest::new(test_args); 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.set_dispatchable::<AssetHubWestend>(system_para_teleport_assets);
test.assert(); test.assert();
let sender_balance_after = test.sender.balance;
let receiver_balance_after = test.receiver.balance;
let delivery_fees = AssetHubWestend::execute_with(|| { let delivery_fees = AssetHubWestend::execute_with(|| {
xcm_helpers::transfer_assets_delivery_fees::< xcm_helpers::transfer_assets_delivery_fees::<
<AssetHubWestendXcmConfig as xcm_executor::Config>::XcmSender, <AssetHubWestendXcmConfig as xcm_executor::Config>::XcmSender,
>(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) >(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 // Sender's balance is reduced
assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after); assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after);
// Receiver's balance is increased // Receiver's balance is increased
@@ -558,30 +561,21 @@ fn teleport_to_other_system_parachains_works() {
/// (using native reserve-based transfer for fees) /// (using native reserve-based transfer for fees)
#[test] #[test]
fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() { fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() {
let ah_as_seen_by_penpal = PenpalB::sibling_location_of(AssetHubWestend::para_id()); // Init values for Parachain
let asset_location_on_penpal = PenpalLocalTeleportableToAssetHubV3::get(); 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() { let asset_id_on_penpal = match asset_location_on_penpal.last() {
Some(v3::Junction::GeneralIndex(id)) => *id as u32, Some(v3::Junction::GeneralIndex(id)) => *id as u32,
_ => unreachable!(), _ => unreachable!(),
}; };
let asset_owner_on_penpal = PenpalBSender::get(); let asset_amount_to_send = ASSET_HUB_WESTEND_ED * 100;
let foreign_asset_at_asset_hub_westend = let asset_owner = PenpalAssetOwner::get();
v3::Location::new(1, [v3::Junction::Parachain(PenpalB::para_id().into())]) let system_para_native_asset_location =
.appended_with(asset_location_on_penpal) v3::Location::try_from(RelayLocation::get()).expect("conversion works");
.unwrap(); let sender = PenpalASender::get();
super::penpal_create_foreign_asset_on_asset_hub( let penpal_check_account = <PenpalA as PenpalAPallet>::PolkadotXcm::check_account();
asset_id_on_penpal, let ah_as_seen_by_penpal = PenpalA::sibling_location_of(AssetHubWestend::para_id());
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_location_on_penpal_latest: Location = asset_location_on_penpal.try_into().unwrap(); let asset_location_on_penpal_latest: Location = asset_location_on_penpal.try_into().unwrap();
let penpal_assets: Assets = vec![ let penpal_assets: Assets = vec![
(Parent, fee_amount_to_send).into(), (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()) .position(|r| r == &(Parent, fee_amount_to_send).into())
.unwrap() as u32; .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 // Penpal to AH test args
let penpal_to_ah_test_args = TestContext { let penpal_to_ah_test_args = TestContext {
sender: PenpalBSender::get(), sender: PenpalASender::get(),
receiver: AssetHubWestendReceiver::get(), receiver: AssetHubWestendReceiver::get(),
args: TestArgs::new_para( args: TestArgs::new_para(
ah_as_seen_by_penpal, 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 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 ah_receiver_balance_before = penpal_to_ah.receiver.balance;
let penpal_sender_assets_before = PenpalB::execute_with(|| { let penpal_sender_assets_before = PenpalA::execute_with(|| {
type Assets = <PenpalB as PenpalBPallet>::Assets; type Assets = <PenpalA as PenpalAPallet>::Assets;
<Assets as Inspect<_>>::balance(asset_id_on_penpal, &PenpalBSender::get()) <Assets as Inspect<_>>::balance(asset_id_on_penpal, &PenpalASender::get())
}); });
let ah_receiver_assets_before = AssetHubWestend::execute_with(|| { let ah_receiver_assets_before = AssetHubWestend::execute_with(|| {
type Assets = <AssetHubWestend as AssetHubWestendPallet>::ForeignAssets; 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_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(); 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 ah_receiver_balance_after = penpal_to_ah.receiver.balance;
let penpal_sender_assets_after = PenpalB::execute_with(|| { let penpal_sender_assets_after = PenpalA::execute_with(|| {
type Assets = <PenpalB as PenpalBPallet>::Assets; type Assets = <PenpalA as PenpalAPallet>::Assets;
<Assets as Inspect<_>>::balance(asset_id_on_penpal, &PenpalBSender::get()) <Assets as Inspect<_>>::balance(asset_id_on_penpal, &PenpalASender::get())
}); });
let ah_receiver_assets_after = AssetHubWestend::execute_with(|| { let ah_receiver_assets_after = AssetHubWestend::execute_with(|| {
type Assets = <AssetHubWestend as AssetHubWestendPallet>::ForeignAssets; 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 = let foreign_asset_at_asset_hub_westend_latest: Location =
foreign_asset_at_asset_hub_westend.try_into().unwrap(); foreign_asset_at_asset_hub_westend.try_into().unwrap();
let ah_to_penpal_beneficiary_id = PenpalBReceiver::get(); let ah_to_penpal_beneficiary_id = PenpalAReceiver::get();
let penpal_as_seen_by_ah = AssetHubWestend::sibling_location_of(PenpalB::para_id()); let penpal_as_seen_by_ah = AssetHubWestend::sibling_location_of(PenpalA::para_id());
let ah_assets: Assets = vec![ let ah_assets: Assets = vec![
(Parent, fee_amount_to_send).into(), (Parent, fee_amount_to_send).into(),
(foreign_asset_at_asset_hub_westend_latest, asset_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 // AH to Penpal test args
let ah_to_penpal_test_args = TestContext { let ah_to_penpal_test_args = TestContext {
sender: AssetHubWestendSender::get(), sender: AssetHubWestendSender::get(),
receiver: PenpalBReceiver::get(), receiver: PenpalAReceiver::get(),
args: TestArgs::new_para( args: TestArgs::new_para(
penpal_as_seen_by_ah, penpal_as_seen_by_ah,
ah_to_penpal_beneficiary_id, 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 mut ah_to_penpal = SystemParaToParaTest::new(ah_to_penpal_test_args);
let ah_sender_balance_before = ah_to_penpal.sender.balance; 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(|| { let ah_sender_assets_before = AssetHubWestend::execute_with(|| {
type ForeignAssets = <AssetHubWestend as AssetHubWestendPallet>::ForeignAssets; type ForeignAssets = <AssetHubWestend as AssetHubWestendPallet>::ForeignAssets;
@@ -713,18 +761,24 @@ fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() {
&AssetHubWestendSender::get(), &AssetHubWestendSender::get(),
) )
}); });
let penpal_receiver_assets_before = PenpalB::execute_with(|| { let penpal_receiver_assets_before = PenpalA::execute_with(|| {
type Assets = <PenpalB as PenpalBPallet>::Assets; type Assets = <PenpalA as PenpalAPallet>::Assets;
<Assets as Inspect<_>>::balance(asset_id_on_penpal, &PenpalBReceiver::get()) <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::<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.set_dispatchable::<AssetHubWestend>(system_para_to_para_transfer_assets);
ah_to_penpal.assert(); ah_to_penpal.assert();
let ah_sender_balance_after = ah_to_penpal.sender.balance; 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(|| { let ah_sender_assets_after = AssetHubWestend::execute_with(|| {
type ForeignAssets = <AssetHubWestend as AssetHubWestendPallet>::ForeignAssets; type ForeignAssets = <AssetHubWestend as AssetHubWestendPallet>::ForeignAssets;
@@ -733,9 +787,9 @@ fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() {
&AssetHubWestendSender::get(), &AssetHubWestendSender::get(),
) )
}); });
let penpal_receiver_assets_after = PenpalB::execute_with(|| { let penpal_receiver_assets_after = PenpalA::execute_with(|| {
type Assets = <PenpalB as PenpalBPallet>::Assets; type Assets = <PenpalA as PenpalAPallet>::Assets;
<Assets as Inspect<_>>::balance(asset_id_on_penpal, &PenpalBReceiver::get()) <Assets as Inspect<_>>::balance(asset_id_on_penpal, &PenpalAReceiver::get())
}); });
// Sender's balance is reduced // Sender's balance is reduced
@@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::*; use crate::imports::*;
use emulated_integration_tests_common::accounts::{ALICE, BOB}; use emulated_integration_tests_common::accounts::{ALICE, BOB};
use frame_support::traits::fungibles::{Create, Inspect, Mutate}; use frame_support::traits::fungibles::{Create, Inspect, Mutate};
use polkadot_runtime_common::impls::VersionedLocatableAsset; use polkadot_runtime_common::impls::VersionedLocatableAsset;
@@ -13,6 +13,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#[cfg(test)]
mod imports {
// Substrate // Substrate
pub use frame_support::{assert_err, assert_ok, pallet_prelude::DispatchResult}; pub use frame_support::{assert_err, assert_ok, pallet_prelude::DispatchResult};
pub use sp_runtime::DispatchError; pub use sp_runtime::DispatchError;
@@ -21,28 +23,19 @@ pub use sp_runtime::DispatchError;
pub use xcm::{ pub use xcm::{
latest::ParentThen, latest::ParentThen,
prelude::{AccountId32 as AccountId32Junction, *}, prelude::{AccountId32 as AccountId32Junction, *},
v3::{ v3::{self, NetworkId::Westend as WestendId},
self, Error,
NetworkId::{Rococo as RococoId, Westend as WestendId},
},
}; };
// Bridges
pub use bp_messages::LaneId;
// Cumulus // Cumulus
pub use emulated_integration_tests_common::{ pub use emulated_integration_tests_common::{
accounts::ALICE, accounts::ALICE,
impls::Inspect, impls::Inspect,
test_parachain_is_trusted_teleporter, test_parachain_is_trusted_teleporter,
xcm_emulator::{ xcm_emulator::{
assert_expected_events, bx, helpers::weight_within_threshold, Chain, Parachain as Para, assert_expected_events, bx, Chain, Parachain as Para, RelayChain as Relay, TestExt,
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 parachains_common::AccountId;
pub use rococo_westend_system_emulated_network::{ pub use rococo_westend_system_emulated_network::{
asset_hub_rococo_emulated_chain::{ asset_hub_rococo_emulated_chain::{
genesis::ED as ASSET_HUB_ROCOCO_ED, AssetHubRococoParaPallet as AssetHubRococoPallet, genesis::ED as ASSET_HUB_ROCOCO_ED, AssetHubRococoParaPallet as AssetHubRococoPallet,
@@ -59,16 +52,14 @@ pub use rococo_westend_system_emulated_network::{
AssetHubRococoParaSender as AssetHubRococoSender, AssetHubWestendPara as AssetHubWestend, AssetHubRococoParaSender as AssetHubRococoSender, AssetHubWestendPara as AssetHubWestend,
AssetHubWestendParaReceiver as AssetHubWestendReceiver, AssetHubWestendParaReceiver as AssetHubWestendReceiver,
AssetHubWestendParaSender as AssetHubWestendSender, BridgeHubRococoPara as BridgeHubRococo, AssetHubWestendParaSender as AssetHubWestendSender, BridgeHubRococoPara as BridgeHubRococo,
BridgeHubRococoParaReceiver as BridgeHubRococoReceiver, BridgeHubRococoParaSender as BridgeHubRococoSender,
BridgeHubRococoParaSender as BridgeHubRococoSender, BridgeHubWestendPara as BridgeHubWestend, BridgeHubWestendPara as BridgeHubWestend, PenpalAPara as PenpalA,
PenpalAPara as PenpalA, PenpalAParaReceiver as PenpalAReceiver, PenpalAParaReceiver as PenpalAReceiver, PenpalAParaSender as PenpalASender,
PenpalAParaSender as PenpalASender, RococoRelay as Rococo, RococoRelay as Rococo,
RococoRelayReceiver as RococoReceiver, RococoRelaySender as RococoSender,
}; };
pub const ASSET_ID: u32 = 1;
pub const ASSET_MIN_BALANCE: u128 = 1000; pub const ASSET_MIN_BALANCE: u128 = 1000;
pub const ASSETS_PALLET_ID: u8 = 50; }
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
@@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::*; use crate::imports::*;
mod asset_transfers; mod asset_transfers;
mod send_xcm; mod send_xcm;
@@ -12,7 +12,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::*; use crate::imports::*;
use bridge_hub_rococo_runtime::{EthereumBeaconClient, EthereumInboundQueue, RuntimeOrigin}; use bridge_hub_rococo_runtime::{EthereumBeaconClient, EthereumInboundQueue, RuntimeOrigin};
use codec::{Decode, Encode}; use codec::{Decode, Encode};
use emulated_integration_tests_common::xcm_emulator::ConvertLocation; use emulated_integration_tests_common::xcm_emulator::ConvertLocation;
@@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::*; use crate::tests::*;
use bridge_hub_rococo_runtime::xcm_config::XcmConfig; use bridge_hub_rococo_runtime::xcm_config::XcmConfig;
#[test] #[test]
@@ -13,6 +13,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#[cfg(test)]
mod imports {
// Substrate // Substrate
pub use frame_support::{assert_err, assert_ok, pallet_prelude::DispatchResult}; pub use frame_support::{assert_err, assert_ok, pallet_prelude::DispatchResult};
pub use sp_runtime::DispatchError; pub use sp_runtime::DispatchError;
@@ -22,28 +24,19 @@ pub use xcm::{
latest::ParentThen, latest::ParentThen,
prelude::{AccountId32 as AccountId32Junction, *}, prelude::{AccountId32 as AccountId32Junction, *},
v3, v3,
v4::{ v4::NetworkId::Rococo as RococoId,
Error,
NetworkId::{Rococo as RococoId, Westend as WestendId},
},
}; };
// Bridges
pub use bp_messages::LaneId;
// Cumulus // Cumulus
pub use emulated_integration_tests_common::{ pub use emulated_integration_tests_common::{
accounts::ALICE, accounts::ALICE,
impls::Inspect, impls::Inspect,
test_parachain_is_trusted_teleporter, test_parachain_is_trusted_teleporter,
xcm_emulator::{ xcm_emulator::{
assert_expected_events, bx, helpers::weight_within_threshold, Chain, Parachain as Para, assert_expected_events, bx, Chain, Parachain as Para, RelayChain as Relay, TestExt,
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 parachains_common::AccountId;
pub use rococo_westend_system_emulated_network::{ pub use rococo_westend_system_emulated_network::{
asset_hub_rococo_emulated_chain::{ asset_hub_rococo_emulated_chain::{
genesis::ED as ASSET_HUB_ROCOCO_ED, AssetHubRococoParaPallet as AssetHubRococoPallet, genesis::ED as ASSET_HUB_ROCOCO_ED, AssetHubRococoParaPallet as AssetHubRococoPallet,
@@ -52,20 +45,20 @@ pub use rococo_westend_system_emulated_network::{
genesis::ED as ASSET_HUB_WESTEND_ED, AssetHubWestendParaPallet as AssetHubWestendPallet, genesis::ED as ASSET_HUB_WESTEND_ED, AssetHubWestendParaPallet as AssetHubWestendPallet,
}, },
bridge_hub_westend_emulated_chain::{ bridge_hub_westend_emulated_chain::{
genesis::ED as BRIDGE_HUB_WESTEND_ED, BridgeHubWestendParaPallet as BridgeHubWestendPallet, genesis::ED as BRIDGE_HUB_WESTEND_ED,
BridgeHubWestendParaPallet as BridgeHubWestendPallet,
}, },
westend_emulated_chain::WestendRelayPallet as WestendPallet, westend_emulated_chain::WestendRelayPallet as WestendPallet,
AssetHubRococoPara as AssetHubRococo, AssetHubRococoParaReceiver as AssetHubRococoReceiver, AssetHubRococoPara as AssetHubRococo, AssetHubRococoParaReceiver as AssetHubRococoReceiver,
AssetHubRococoParaSender as AssetHubRococoSender, AssetHubWestendPara as AssetHubWestend, AssetHubRococoParaSender as AssetHubRococoSender, AssetHubWestendPara as AssetHubWestend,
AssetHubWestendParaReceiver as AssetHubWestendReceiver, AssetHubWestendParaReceiver as AssetHubWestendReceiver,
AssetHubWestendParaSender as AssetHubWestendSender, BridgeHubRococoPara as BridgeHubRococo, AssetHubWestendParaSender as AssetHubWestendSender, BridgeHubRococoPara as BridgeHubRococo,
BridgeHubWestendPara as BridgeHubWestend, BridgeHubWestendParaSender as BridgeHubWestendSender, BridgeHubWestendPara as BridgeHubWestend,
WestendRelay as Westend, BridgeHubWestendParaSender as BridgeHubWestendSender, WestendRelay as Westend,
}; };
pub const ASSET_ID: u32 = 1;
pub const ASSET_MIN_BALANCE: u128 = 1000; pub const ASSET_MIN_BALANCE: u128 = 1000;
pub const ASSETS_PALLET_ID: u8 = 50; }
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
@@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::*; use crate::imports::*;
mod asset_transfers; mod asset_transfers;
mod send_xcm; mod send_xcm;
@@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::*; use crate::tests::*;
use bridge_hub_westend_runtime::xcm_config::XcmConfig; use bridge_hub_westend_runtime::xcm_config::XcmConfig;
#[test] #[test]
@@ -13,52 +13,41 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#[cfg(test)]
mod imports {
pub use codec::Encode; pub use codec::Encode;
// Substrate // Substrate
pub use frame_support::{ pub use frame_support::{
assert_err, assert_ok, assert_ok,
pallet_prelude::Weight, pallet_prelude::Weight,
sp_runtime::{AccountId32, DispatchError, DispatchResult}, sp_runtime::{AccountId32, DispatchResult},
traits::fungibles::Inspect, traits::fungibles::Inspect,
}; };
// Polkadot // Polkadot
pub use xcm::{ pub use xcm::prelude::*;
prelude::{AccountId32 as AccountId32Junction, *},
v3::{Error, NetworkId::Rococo as RococoId},
};
// Cumulus // Cumulus
pub use asset_test_utils::xcm_helpers; pub use asset_test_utils::xcm_helpers;
pub use emulated_integration_tests_common::{ pub use emulated_integration_tests_common::xcm_emulator::{
test_parachain_is_trusted_teleporter, assert_expected_events, bx, Chain, Parachain as Para, RelayChain as Relay, Test, TestArgs,
xcm_emulator::{ TestContext, TestExt,
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 parachains_common::Balance;
pub use rococo_system_emulated_network::{ pub use rococo_system_emulated_network::{
people_rococo_emulated_chain::{ people_rococo_emulated_chain::{
genesis::ED as PEOPLE_ROCOCO_ED, PeopleRococoParaPallet as PeopleRococoPallet, genesis::ED as PEOPLE_ROCOCO_ED, PeopleRococoParaPallet as PeopleRococoPallet,
}, },
rococo_emulated_chain::{genesis::ED as ROCOCO_ED, RococoRelayPallet as RococoPallet}, rococo_emulated_chain::{genesis::ED as ROCOCO_ED, RococoRelayPallet as RococoPallet},
PenpalAPara as PenpalA, PeopleRococoPara as PeopleRococo, PeopleRococoPara as PeopleRococo, PeopleRococoParaReceiver as PeopleRococoReceiver,
PeopleRococoParaReceiver as PeopleRococoReceiver, PeopleRococoParaSender as PeopleRococoSender, PeopleRococoParaSender as PeopleRococoSender, RococoRelay as Rococo,
RococoRelay as Rococo, RococoRelayReceiver as RococoReceiver, RococoRelayReceiver as RococoReceiver, RococoRelaySender as RococoSender,
RococoRelaySender as RococoSender,
}; };
// pub const ASSET_ID: u32 = 1;
// pub const ASSET_MIN_BALANCE: u128 = 1000;
pub type RelayToSystemParaTest = Test<Rococo, PeopleRococo>; pub type RelayToSystemParaTest = Test<Rococo, PeopleRococo>;
pub type RelayToParaTest = Test<Rococo, PenpalA>;
pub type SystemParaToRelayTest = Test<PeopleRococo, Rococo>; pub type SystemParaToRelayTest = Test<PeopleRococo, Rococo>;
pub type SystemParaToParaTest = Test<PeopleRococo, PenpalA>; }
pub type ParaToSystemParaTest = Test<PenpalA, PeopleRococo>;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
@@ -38,7 +38,7 @@
//! - The freed deposit from the Relay Chain is sufficient for the parachain deposit; and //! - The freed deposit from the Relay Chain is sufficient for the parachain deposit; and
//! - The account will exist on the parachain. //! - The account will exist on the parachain.
use crate::*; use crate::imports::*;
use frame_support::BoundedVec; use frame_support::BoundedVec;
use pallet_balances::Event as BalancesEvent; use pallet_balances::Event as BalancesEvent;
use pallet_identity::{legacy::IdentityInfo, Data, Event as IdentityEvent}; use pallet_identity::{legacy::IdentityInfo, Data, Event as IdentityEvent};
@@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::*; use crate::imports::*;
use people_rococo_runtime::xcm_config::XcmConfig as PeopleRococoXcmConfig; use people_rococo_runtime::xcm_config::XcmConfig as PeopleRococoXcmConfig;
use rococo_runtime::xcm_config::XcmConfig as RococoXcmConfig; use rococo_runtime::xcm_config::XcmConfig as RococoXcmConfig;
@@ -13,52 +13,40 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#[cfg(test)]
mod imports {
pub use codec::Encode; pub use codec::Encode;
// Substrate // Substrate
pub use frame_support::{ pub use frame_support::{
assert_err, assert_ok, assert_ok,
pallet_prelude::Weight, pallet_prelude::Weight,
sp_runtime::{AccountId32, DispatchError, DispatchResult}, sp_runtime::{AccountId32, DispatchResult},
traits::fungibles::Inspect, traits::fungibles::Inspect,
}; };
// Polkadot // Polkadot
pub use xcm::{ pub use xcm::prelude::*;
prelude::{AccountId32 as AccountId32Junction, *},
v3::{Error, NetworkId::Westend as WestendId},
};
// Cumulus // Cumulus
pub use asset_test_utils::xcm_helpers; pub use asset_test_utils::xcm_helpers;
pub use emulated_integration_tests_common::{ pub use emulated_integration_tests_common::xcm_emulator::{
test_parachain_is_trusted_teleporter, assert_expected_events, bx, Chain, Parachain as Para, RelayChain as Relay, Test, TestArgs,
xcm_emulator::{ TestContext, TestExt,
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 parachains_common::Balance;
pub use westend_system_emulated_network::{ pub use westend_system_emulated_network::{
people_westend_emulated_chain::{ people_westend_emulated_chain::{
genesis::ED as PEOPLE_WESTEND_ED, PeopleWestendParaPallet as PeopleWestendPallet, genesis::ED as PEOPLE_WESTEND_ED, PeopleWestendParaPallet as PeopleWestendPallet,
}, },
westend_emulated_chain::{genesis::ED as WESTEND_ED, WestendRelayPallet as WestendPallet}, westend_emulated_chain::{genesis::ED as WESTEND_ED, WestendRelayPallet as WestendPallet},
PenpalAPara as PenpalA, PeopleWestendPara as PeopleWestend, PeopleWestendPara as PeopleWestend, PeopleWestendParaReceiver as PeopleWestendReceiver,
PeopleWestendParaReceiver as PeopleWestendReceiver,
PeopleWestendParaSender as PeopleWestendSender, WestendRelay as Westend, PeopleWestendParaSender as PeopleWestendSender, WestendRelay as Westend,
WestendRelayReceiver as WestendReceiver, WestendRelaySender as WestendSender, 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 RelayToSystemParaTest = Test<Westend, PeopleWestend>;
pub type RelayToParaTest = Test<Westend, PenpalA>;
pub type SystemParaToRelayTest = Test<PeopleWestend, Westend>; pub type SystemParaToRelayTest = Test<PeopleWestend, Westend>;
pub type SystemParaToParaTest = Test<PeopleWestend, PenpalA>; }
pub type ParaToSystemParaTest = Test<PenpalA, PeopleWestend>;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
@@ -38,7 +38,7 @@
//! - The freed deposit from the Relay Chain is sufficient for the parachain deposit; and //! - The freed deposit from the Relay Chain is sufficient for the parachain deposit; and
//! - The account will exist on the parachain. //! - The account will exist on the parachain.
use crate::*; use crate::imports::*;
use frame_support::BoundedVec; use frame_support::BoundedVec;
use pallet_balances::Event as BalancesEvent; use pallet_balances::Event as BalancesEvent;
use pallet_identity::{legacy::IdentityInfo, Data, Event as IdentityEvent}; use pallet_identity::{legacy::IdentityInfo, Data, Event as IdentityEvent};
@@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::*; use crate::imports::*;
use people_westend_runtime::xcm_config::XcmConfig as PeopleWestendXcmConfig; use people_westend_runtime::xcm_config::XcmConfig as PeopleWestendXcmConfig;
use westend_runtime::xcm_config::XcmConfig as WestendXcmConfig; use westend_runtime::xcm_config::XcmConfig as WestendXcmConfig;
@@ -527,10 +527,10 @@ fn test_foreign_asset_xcm_take_first_trader() {
let bought = Weight::from_parts(4_000_000_000u64, 0); let bought = Weight::from_parts(4_000_000_000u64, 0);
// Lets calculate amount needed // Lets calculate amount needed
let asset_amount_needed = let asset_amount_needed
ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger::charge_weight_in_fungibles( = ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger::charge_weight_in_fungibles(
foreign_location, foreign_location,
bought, bought
) )
.expect("failed to compute"); .expect("failed to compute");
@@ -527,11 +527,7 @@ fn test_foreign_asset_xcm_take_first_trader() {
let bought = Weight::from_parts(4_000_000_000u64, 0); let bought = Weight::from_parts(4_000_000_000u64, 0);
// Lets calculate amount needed // Lets calculate amount needed
let asset_amount_needed = let asset_amount_needed = ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger::charge_weight_in_fungibles(foreign_location, bought)
ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger::charge_weight_in_fungibles(
foreign_location,
bought,
)
.expect("failed to compute"); .expect("failed to compute");
// Lets pay with: asset_amount_needed + asset_amount_extra // Lets pay with: asset_amount_needed + asset_amount_extra
@@ -53,7 +53,10 @@ use frame_system::{
limits::{BlockLength, BlockWeights}, limits::{BlockLength, BlockWeights},
EnsureRoot, EnsureSigned, 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 polkadot_runtime_common::xcm_sender::NoPriceForMessageDelivery;
use smallvec::smallvec; use smallvec::smallvec;
use sp_api::impl_runtime_apis; use sp_api::impl_runtime_apis;
@@ -70,7 +73,7 @@ use sp_std::prelude::*;
#[cfg(feature = "std")] #[cfg(feature = "std")]
use sp_version::NativeVersion; use sp_version::NativeVersion;
use sp_version::RuntimeVersion; use sp_version::RuntimeVersion;
use xcm_config::{AssetsToBlockAuthor, XcmOriginToTransactDispatchOrigin}; use xcm_config::XcmOriginToTransactDispatchOrigin;
#[cfg(any(feature = "std", test))] #[cfg(any(feature = "std", test))]
pub use sp_runtime::BuildStorage; pub use sp_runtime::BuildStorage;
@@ -618,7 +621,7 @@ impl pallet_asset_tx_payment::Config for Runtime {
ConvertInto, ConvertInto,
pallet_assets::Instance1, 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 //! `ReserveAssetTransferDeposited` message but that will but the intension will be to support this
//! soon. //! soon.
use super::{ use super::{
AccountId, AllPalletsWithSystem, AssetId as AssetIdPalletAssets, Assets, Balance, Balances, AccountId, AllPalletsWithSystem, AssetId as AssetIdPalletAssets, Assets, Authorship, Balance,
ForeignAssets, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, Balances, ForeignAssets, ForeignAssetsInstance, NonZeroIssuance, ParachainInfo,
RuntimeOrigin, WeightToFee, XcmpQueue, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee,
XcmpQueue,
}; };
use core::marker::PhantomData; use core::marker::PhantomData;
use frame_support::{ use frame_support::{
parameter_types, parameter_types,
traits::{ traits::{ConstU32, Contains, ContainsPair, Everything, EverythingBut, Get, Nothing},
fungibles::{self, Balanced, Credit},
ConstU32, Contains, ContainsPair, Everything, Get, Nothing,
},
weights::Weight, weights::Weight,
}; };
use frame_system::EnsureRoot; use frame_system::EnsureRoot;
use pallet_asset_tx_payment::HandleCredit;
use pallet_assets::Instance1;
use pallet_xcm::XcmPassthrough; use pallet_xcm::XcmPassthrough;
use parachains_common::xcm_config::AssetFeeAsExistentialDepositMultiplier;
use polkadot_parachain_primitives::primitives::Sibling; use polkadot_parachain_primitives::primitives::Sibling;
use polkadot_runtime_common::impls::ToAuthor; use polkadot_runtime_common::impls::ToAuthor;
use sp_runtime::traits::Zero; use sp_runtime::traits::ConvertInto;
use xcm::latest::prelude::*; use xcm::latest::prelude::*;
use xcm_builder::{ use xcm_builder::{
AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom,
AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex, AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex, ConvertedConcreteId, EnsureXcmOrigin,
ConvertedConcreteId, EnsureXcmOrigin, FixedWeightBounds, FrameTransactionalProcessor, FixedWeightBounds, FrameTransactionalProcessor, FungibleAdapter, FungiblesAdapter, IsConcrete,
FungibleAdapter, FungiblesAdapter, IsConcrete, LocalMint, NativeAsset, NoChecking, LocalMint, NativeAsset, NoChecking, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative,
ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative,
SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, SignedToAccountId32, SovereignSignedViaLocation, StartsWith, TakeWeightCredit,
SovereignSignedViaLocation, StartsWith, TakeWeightCredit, TrailingSetTopicAsId, TrailingSetTopicAsId, UsingComponents, WithComputedOrigin, WithUniqueTopic,
UsingComponents, WithComputedOrigin, WithUniqueTopic,
}; };
use xcm_executor::{traits::JustTry, XcmExecutor}; use xcm_executor::{traits::JustTry, XcmExecutor};
parameter_types! { parameter_types! {
pub const RelayLocation: Location = Location::parent(); 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 const RelayNetwork: Option<NetworkId> = None;
pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into();
pub UniversalLocation: InteriorLocation = [Parachain(ParachainInfo::parachain_id().into())].into(); pub UniversalLocation: InteriorLocation = [Parachain(ParachainInfo::parachain_id().into())].into();
@@ -80,7 +78,7 @@ pub type CurrencyTransactor = FungibleAdapter<
// Use this currency: // Use this currency:
Balances, Balances,
// Use this currency when it is a fungible asset matching the given location or name: // 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: // Do a simple punn to convert an AccountId32 Location into a native chain account ID:
LocationToAccountId, LocationToAccountId,
// Our chain's account ID type (we can't get away without mentioning it explicitly): // Our chain's account ID type (we can't get away without mentioning it explicitly):
@@ -123,9 +121,16 @@ pub type FungiblesTransactor = FungiblesAdapter<
CheckingAccount, CheckingAccount,
>; >;
/// `AssetId/Balance` converter for `TrustBackedAssets` pub type ForeignAssetsConvertedConcreteId = assets_common::LocationConvertedConcreteId<
pub type ForeignAssetsConvertedConcreteId = EverythingBut<(
assets_common::ForeignAssetsConvertedConcreteId<StartsWith<RelayLocation>, Balance>; // 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. /// Means for transacting foreign assets from different global consensus.
pub type ForeignFungiblesTransactor = FungiblesAdapter< pub type ForeignFungiblesTransactor = FungiblesAdapter<
@@ -175,6 +180,7 @@ parameter_types! {
pub UnitWeightCost: Weight = Weight::from_parts(1_000_000_000, 64 * 1024); pub UnitWeightCost: Weight = Weight::from_parts(1_000_000_000, 64 * 1024);
pub const MaxInstructions: u32 = 100; pub const MaxInstructions: u32 = 100;
pub const MaxAssetsIntoHolding: u32 = 64; pub const MaxAssetsIntoHolding: u32 = 64;
pub XcmAssetFeesReceiver: Option<AccountId> = Authorship::author();
} }
pub struct ParentOrParentsExecutivePlurality; 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<( pub type Barrier = TrailingSetTopicAsId<(
TakeWeightCredit, TakeWeightCredit,
// Expected responses are OK. // 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 // If the message is one that immediately attempts to pay for execution, then
// allow it. // allow it.
AllowTopLevelPaidExecutionFrom<Everything>, AllowTopLevelPaidExecutionFrom<Everything>,
// System Assets parachain, parent and its exec plurality get free
// execution
AllowExplicitUnpaidExecutionFrom<(
CommonGoodAssetsParachain,
ParentOrParentsExecutivePlurality,
)>,
// Subscriptions for version tracking are OK. // Subscriptions for version tracking are OK.
AllowSubscriptionsFrom<Everything>, AllowSubscriptionsFrom<Everything>,
), ),
@@ -246,53 +239,30 @@ impl<T: Get<Location>> ContainsPair<Asset, Location> for NativeAssetFrom<T> {
} }
} }
/// Allow checking in assets that have issuance > 0. // This asset can be added to AH as Asset and reserved transfer between Penpal and AH
pub struct NonZeroIssuance<AccountId, Assets>(PhantomData<(AccountId, Assets)>); pub const RESERVABLE_ASSET_ID: u32 = 1;
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 ForeignAsset and teleported between Penpal and AH // This asset can be added to AH as ForeignAsset and teleported between Penpal and AH
pub const TELEPORTABLE_ASSET_ID: u32 = 2; pub const TELEPORTABLE_ASSET_ID: u32 = 2;
pub const ASSETS_PALLET_ID: u8 = 50;
pub const ASSET_HUB_ID: u32 = 1000;
parameter_types! { parameter_types! {
/// The location that this chain recognizes as the Relay network's Asset Hub. /// The location that this chain recognizes as the Relay network's Asset Hub.
pub SystemAssetHubLocation: Location = Location::new(1, [Parachain(1000)]); pub SystemAssetHubLocation: Location = Location::new(1, [Parachain(ASSET_HUB_ID)]);
// ALWAYS ensure that the index in PalletInstance stays up-to-date with
// the Relay Chain's Asset Hub's Assets pallet index // the Relay Chain's Asset Hub's Assets pallet index
pub SystemAssetHubAssetsPalletLocation: Location = pub SystemAssetHubAssetsPalletLocation: Location =
Location::new(1, [Parachain(1000), PalletInstance(50)]); Location::new(1, [Parachain(ASSET_HUB_ID), PalletInstance(ASSETS_PALLET_ID)]);
pub AssetsPalletLocation: Location = pub AssetsPalletLocation: Location =
Location::new(0, [PalletInstance(50)]); Location::new(0, [PalletInstance(ASSETS_PALLET_ID)]);
pub CheckingAccount: AccountId = PolkadotXcm::check_account(); pub CheckingAccount: AccountId = PolkadotXcm::check_account();
pub LocalTeleportableToAssetHub: Location = Location::new( pub LocalTeleportableToAssetHub: Location = Location::new(
0, 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( pub LocalReservableFromAssetHub: Location = Location::new(
0, 1,
[xcm::v3::Junction::PalletInstance(50), xcm::v3::Junction::GeneralIndex(TELEPORTABLE_ASSET_ID.into())] [Parachain(ASSET_HUB_ID), PalletInstance(ASSETS_PALLET_ID), GeneralIndex(RESERVABLE_ASSET_ID.into())]
); );
/// The Penpal runtime is utilized for testing with various environment setups. /// 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 UniversalLocation = UniversalLocation;
type Barrier = Barrier; type Barrier = Barrier;
type Weigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>; type Weigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
type Trader = type Trader = (
UsingComponents<WeightToFee, RelayLocation, AccountId, Balances, ToAuthor<Runtime>>; 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 ResponseHandler = PolkadotXcm;
type AssetTrap = PolkadotXcm; type AssetTrap = PolkadotXcm;
type AssetClaims = PolkadotXcm; type AssetClaims = PolkadotXcm;
@@ -356,6 +340,15 @@ impl xcm_executor::Config for XcmConfig {
type TransactionalProcessor = FrameTransactionalProcessor; 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. /// No local origins on this chain are allowed to dispatch XCM sends/executions.
pub type LocalOriginToLocation = SignedToAccountId32<RuntimeOrigin, AccountId, RelayNetwork>; pub type LocalOriginToLocation = SignedToAccountId32<RuntimeOrigin, AccountId, RelayNetwork>;