[Feature] XCM-Emulator (#2447)

* [Feature] XCM-Emulator

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

* rename

* readme

* more rename

* rename directory

* implement AssetTransactor

* Update xcm/xcm-emulator/README.md

Co-authored-by: Muharem Ismailov <ismailov.m.h@gmail.com>

* address review comments (#2502)

* Update xcm/xcm-emulator/example/src/lib.rs

Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Update xcm/xcm-emulator/README.md

* Use 2d weights.

* Point out nearer the failure why it should fail

* Move test-runtime to under examples

* Walk through how to use it

* proof needs to be non-zero

* Apply suggestions from code review

* Update xcm/xcm-emulator/README.md

Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Improve xcm emulator (#2593)

* folder restructutre

* common created

* make macros repetitions

* messenger traits for relay and para

* default Messenger impls

* messenger traits refactor

* declared two networks

* init network approach works

* queues use HashMap but relay block number

* init and reset refactor

* messengers trait name changed

* relay block number suboptimal

* fix reset hashmap keys

* genesis added

* test ext added for parachains

* genesis added relay chains

* genesis to storage

* new_ext replaced by on_init

* new relay block number approach

* ext_wrapper added

* added types to Parachain trait

* relay chain with types

* restructure

* para_ids working

* replace para_id getter

* replace para_id getter 2

* tests restructure + common variables

* added sovereign and balances helpers

* more helpers + tess pass

* expected events macro added

* added events trait method

* expect_events macro improve

* expect_events macro done

* network traits added

* reserve_transfer test added

* para & relay macro inputs redefined

* added collectives & BH paras

* test restructure

* statemine removed

* nitpick

* rename test folder + events logs

* clean

* weight threshold helper

* update readme

* remove cumulus-test-service dependancy

* fmt

* comment docs

* update e2e tests to xcm v3

* clippy + runtime-benchmark + clean docs

---------

Co-authored-by: command-bot <>
Co-authored-by: Muharem Ismailov <ismailov.m.h@gmail.com>
Co-authored-by: Squirrel <gilescope@gmail.com>
Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>
Co-authored-by: Ignacio Palacios <ignacio.palacios.santos@gmail.com>
This commit is contained in:
Roman Useinov
2023-05-19 19:53:41 +02:00
committed by GitHub
parent 8425e2a5c0
commit 944ab483d5
40 changed files with 3848 additions and 1859 deletions
@@ -0,0 +1,36 @@
[package]
name = "statemint-it"
version = "1.0.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"
description = "Statemint parachain runtime integration tests with xcm-emulator"
[dependencies]
codec = { package = "parity-scale-codec", version = "3.4.0", default-features = false }
# Substrate
sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
sp-weights = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-balances = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-assets = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
# Polkadot
polkadot-core-primitives = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-parachain = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-runtime = { git = "https://github.com/paritytech/polkadot", branch = "master" }
xcm = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "master" }
xcm-executor = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "master" }
pallet-xcm = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "master" }
# Cumulus
parachains-common = { path = "../../../../common" }
penpal-runtime = { path = "../../../../runtimes/testing/penpal" }
statemint-runtime = { path = "../../../../runtimes/assets/statemint" }
# Local
xcm-emulator = { default-features = false, path = "../../../../../xcm/xcm-emulator" }
integration-tests-common = { default-features = false, path = "../../common" }
@@ -0,0 +1,33 @@
pub use codec::Encode;
pub use frame_support::{
assert_ok, instances::Instance1, pallet_prelude::Weight, traits::fungibles::Inspect,
};
pub use integration_tests_common::{
constants::{
accounts::{ALICE, BOB},
polkadot::ED as POLKADOT_ED,
PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3,
},
AccountId, BHKusama, BHKusamaPallet, BHKusamaReceiver, BHKusamaSender, BHPolkadot,
BHPolkadotPallet, BHPolkadotReceiver, BHPolkadotSender, Collectives, CollectivesPallet,
CollectivesReceiver, CollectivesSender, Kusama, KusamaMockNet, KusamaPallet, KusamaReceiver,
KusamaSender, PenpalKusama, PenpalKusamaReceiver, PenpalKusamaSender, PenpalPolkadot,
PenpalPolkadotReceiver, PenpalPolkadotSender, Polkadot, PolkadotMockNet, PolkadotPallet,
PolkadotReceiver, PolkadotSender, Statemine, StateminePallet, StatemineReceiver,
StatemineSender, Statemint, StatemintPallet, StatemintReceiver, StatemintSender,
};
pub use polkadot_core_primitives::InboundDownwardMessage;
pub use xcm::{
prelude::*,
v3::{
Error,
NetworkId::{Kusama as KusamaId, Polkadot as PolkadotId},
},
};
pub use xcm_emulator::{
assert_expected_events, bx, cumulus_pallet_dmp_queue, helpers::weight_within_threshold,
Parachain as Para, RelayChain as Relay, TestExt,
};
#[cfg(test)]
mod tests;
@@ -0,0 +1,3 @@
mod reserve_transfer;
mod teleport;
mod transact;
@@ -0,0 +1,63 @@
use crate::*;
#[test]
fn reserve_transfer_native_asset_from_relay_to_assets() {
// Init tests variables
let amount = POLKADOT_ED * 1000;
let relay_sender_balance_before = Polkadot::account_data_of(PolkadotSender::get()).free;
let para_receiver_balance_before = Statemint::account_data_of(StatemintReceiver::get()).free;
let origin = <Polkadot as Relay>::RuntimeOrigin::signed(PolkadotSender::get());
let assets_para_destination: VersionedMultiLocation =
Polkadot::child_location_of(Statemint::para_id()).into();
let beneficiary: VersionedMultiLocation =
AccountId32 { network: None, id: StatemintReceiver::get().into() }.into();
let native_assets: VersionedMultiAssets = (Here, amount).into();
let fee_asset_item = 0;
let weight_limit = WeightLimit::Unlimited;
// Send XCM message from Relay Chain
Polkadot::execute_with(|| {
assert_ok!(<Polkadot as PolkadotPallet>::XcmPallet::limited_reserve_transfer_assets(
origin,
bx!(assets_para_destination),
bx!(beneficiary),
bx!(native_assets),
fee_asset_item,
weight_limit,
));
type RuntimeEvent = <Polkadot as Relay>::RuntimeEvent;
assert_expected_events!(
Polkadot,
vec![
RuntimeEvent::XcmPallet(pallet_xcm::Event::Attempted(Outcome::Complete(weight))) => {
weight: weight_within_threshold((REF_TIME_THRESHOLD, PROOF_SIZE_THRESHOLD), Weight::from_parts(2_000_000_000, 0), *weight),
},
]
);
});
// Receive XCM message in Assets Parachain
Statemint::execute_with(|| {
type RuntimeEvent = <Statemint as Para>::RuntimeEvent;
assert_expected_events!(
Statemint,
vec![
RuntimeEvent::DmpQueue(cumulus_pallet_dmp_queue::Event::ExecutedDownward {
outcome: Outcome::Incomplete(_, Error::UntrustedReserveLocation),
..
}) => {},
]
);
});
// Check if balances are updated accordingly in Relay Chain and Assets Parachain
let relay_sender_balance_after = Polkadot::account_data_of(PolkadotSender::get()).free;
let para_sender_balance_after = Statemint::account_data_of(StatemintReceiver::get()).free;
assert_eq!(relay_sender_balance_before - amount, relay_sender_balance_after);
assert_eq!(para_sender_balance_after, para_receiver_balance_before);
}
@@ -0,0 +1,60 @@
use crate::*;
#[test]
fn teleport_native_assets_from_relay_to_assets_para() {
// Init tests variables
let amount = POLKADOT_ED * 1000;
let relay_sender_balance_before = Polkadot::account_data_of(PolkadotSender::get()).free;
let para_receiver_balance_before = Statemint::account_data_of(StatemintReceiver::get()).free;
let origin = <Polkadot as Relay>::RuntimeOrigin::signed(PolkadotSender::get());
let assets_para_destination: VersionedMultiLocation =
Polkadot::child_location_of(Statemint::para_id()).into();
let beneficiary: VersionedMultiLocation =
AccountId32 { network: None, id: StatemintReceiver::get().into() }.into();
let native_assets: VersionedMultiAssets = (Here, amount).into();
let fee_asset_item = 0;
let weight_limit = WeightLimit::Unlimited;
// Send XCM message from Relay Chain
Polkadot::execute_with(|| {
assert_ok!(<Polkadot as PolkadotPallet>::XcmPallet::limited_teleport_assets(
origin,
bx!(assets_para_destination),
bx!(beneficiary),
bx!(native_assets),
fee_asset_item,
weight_limit,
));
type RuntimeEvent = <Polkadot as Relay>::RuntimeEvent;
assert_expected_events!(
Polkadot,
vec![
RuntimeEvent::XcmPallet(pallet_xcm::Event::Attempted(Outcome::Complete { .. })) => {},
]
);
});
// Receive XCM message in Assets Parachain
Statemint::execute_with(|| {
type RuntimeEvent = <Statemint as Para>::RuntimeEvent;
assert_expected_events!(
Statemint,
vec![
RuntimeEvent::Balances(pallet_balances::Event::Deposit { who, .. }) => {
who: *who == StatemineReceiver::get().into(),
},
]
);
});
// Check if balances are updated accordingly in Relay Chain and Assets Parachain
let relay_sender_balance_after = Polkadot::account_data_of(PolkadotSender::get()).free;
let para_sender_balance_after = Statemint::account_data_of(StatemintReceiver::get()).free;
assert_eq!(relay_sender_balance_before - amount, relay_sender_balance_after);
assert!(para_sender_balance_after > para_receiver_balance_before);
}
@@ -0,0 +1,58 @@
use crate::*;
#[test]
fn transact_sudo_from_relay_to_assets_para() {
// Init tests variables
// Call to be executed in Assets Parachain
const ASSET_ID: u32 = 1;
let call = <Statemint as Para>::RuntimeCall::Assets(pallet_assets::Call::<
<Statemint as Para>::Runtime,
Instance1,
>::force_create {
id: ASSET_ID.into(),
is_sufficient: true,
min_balance: 1000,
owner: StatemintSender::get().into(),
})
.encode()
.into();
// XcmPallet send arguments
let sudo_origin = <Polkadot as Relay>::RuntimeOrigin::root();
let assets_para_destination: VersionedMultiLocation =
Polkadot::child_location_of(Statemint::para_id()).into();
let weight_limit = WeightLimit::Unlimited;
let require_weight_at_most = Weight::from_parts(1000000000, 200000);
let origin_kind = OriginKind::Superuser;
let check_origin = None;
let xcm = VersionedXcm::from(Xcm(vec![
UnpaidExecution { weight_limit, check_origin },
Transact { require_weight_at_most, origin_kind, call },
]));
// Send XCM message from Relay Chain
Polkadot::execute_with(|| {
assert_ok!(<Polkadot as PolkadotPallet>::XcmPallet::send(
sudo_origin,
bx!(assets_para_destination),
bx!(xcm),
));
type RuntimeEvent = <Polkadot as Relay>::RuntimeEvent;
assert_expected_events!(
Polkadot,
vec![
RuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { .. }) => {},
]
);
});
// Receive XCM message in Assets Parachain
Statemint::execute_with(|| {
assert!(<Statemint as StatemintPallet>::Assets::asset_exists(ASSET_ID));
});
}