feat: Rebrand Polkadot/Substrate references to PezkuwiChain
This commit systematically rebrands various references from Parity Technologies' Polkadot/Substrate ecosystem to PezkuwiChain within the kurdistan-sdk. Key changes include: - Updated external repository URLs (zombienet-sdk, parity-db, parity-scale-codec, wasm-instrument) to point to pezkuwichain forks. - Modified internal documentation and code comments to reflect PezkuwiChain naming and structure. - Replaced direct references to with or specific paths within the for XCM, Pezkuwi, and other modules. - Cleaned up deprecated issue and PR references in various and files, particularly in and modules. - Adjusted image and logo URLs in documentation to point to PezkuwiChain assets. - Removed or rephrased comments related to external Polkadot/Substrate PRs and issues. This is a significant step towards fully customizing the SDK for the PezkuwiChain ecosystem.
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
# Teyrchains
|
||||
|
||||
This directory is the home of Parity-developed teyrchain runtimes. This directory is _runtime
|
||||
focused_, and does not include builds of teyrchain _nodes_.
|
||||
|
||||
The general internal structure is:
|
||||
|
||||
- `chain-specs`: Chain specs for the runtimes contained in its sibling dir `runtimes`.
|
||||
- `common`: Common configurations, `impl`s, etc. used by several teyrchain runtimes.
|
||||
- `integration-tests`: Integration tests to test teyrchain interactions via XCM.
|
||||
- `pallets`: FRAME pallets that are specific to teyrchains.
|
||||
- `runtimes`: The entry point for teyrchain runtimes.
|
||||
|
||||
## System Teyrchains
|
||||
|
||||
The `runtimes` directory includes many, but is not limited to,
|
||||
[system teyrchains](https://wiki.network.pezkuwichain.io/docs/learn-system-chains). Likewise, not all
|
||||
system teyrchains are in this repo.
|
||||
|
||||
## Releases
|
||||
|
||||
The project maintainers generally try to release a set of teyrchain runtimes for each PezkuwiChain
|
||||
Relay Chain runtime release.
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,114 @@
|
||||
[package]
|
||||
name = "teyrchains-common"
|
||||
version = "7.0.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
description = "Logic which is common to all teyrchain runtimes"
|
||||
license = "Apache-2.0"
|
||||
homepage.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
||||
[dependencies]
|
||||
codec = { features = ["derive"], workspace = true }
|
||||
scale-info = { features = ["derive"], workspace = true }
|
||||
tracing = { workspace = true }
|
||||
|
||||
# Bizinikiwi
|
||||
pezframe-support = { workspace = true }
|
||||
pezframe-system = { workspace = true }
|
||||
pezpallet-asset-tx-payment = { workspace = true }
|
||||
pezpallet-assets = { workspace = true }
|
||||
pezpallet-authorship = { workspace = true }
|
||||
pezpallet-balances = { workspace = true }
|
||||
pezpallet-message-queue = { workspace = true }
|
||||
pezpallet-treasury = { workspace = true }
|
||||
pezsp-consensus-aura = { workspace = true }
|
||||
pezsp-core = { workspace = true }
|
||||
pezsp-io = { workspace = true }
|
||||
pezsp-runtime = { workspace = true }
|
||||
|
||||
# Pezkuwi
|
||||
pezpallet-xcm = { workspace = true }
|
||||
pezkuwi-primitives = { workspace = true }
|
||||
pezkuwi-runtime-common = { workspace = true }
|
||||
xcm = { workspace = true }
|
||||
xcm-executor = { workspace = true }
|
||||
|
||||
# Pezcumulus
|
||||
pezcumulus-primitives-core = { workspace = true }
|
||||
pezcumulus-primitives-utility = { workspace = true }
|
||||
pezpallet-collator-selection = { workspace = true }
|
||||
teyrchain-info = { workspace = true }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"codec/std",
|
||||
"pezcumulus-primitives-core/std",
|
||||
"pezcumulus-primitives-utility/std",
|
||||
"pezframe-support/std",
|
||||
"pezframe-system/std",
|
||||
"pezpallet-asset-tx-payment/std",
|
||||
"pezpallet-assets/std",
|
||||
"pezpallet-authorship/std",
|
||||
"pezpallet-balances/std",
|
||||
"pezpallet-collator-selection/std",
|
||||
"pezpallet-message-queue/std",
|
||||
"pezpallet-treasury/std",
|
||||
"pezpallet-xcm/std",
|
||||
"pezkuwi-primitives/std",
|
||||
"pezkuwi-runtime-common/std",
|
||||
"scale-info/std",
|
||||
"pezsp-consensus-aura/std",
|
||||
"pezsp-core/std",
|
||||
"pezsp-io/std",
|
||||
"pezsp-runtime/std",
|
||||
"teyrchain-info/std",
|
||||
"tracing/std",
|
||||
"xcm-executor/std",
|
||||
"xcm/std",
|
||||
]
|
||||
runtime-benchmarks = [
|
||||
"pezcumulus-primitives-core/runtime-benchmarks",
|
||||
"pezcumulus-primitives-utility/runtime-benchmarks",
|
||||
"pezframe-support/runtime-benchmarks",
|
||||
"pezframe-system/runtime-benchmarks",
|
||||
"pezpallet-asset-tx-payment/runtime-benchmarks",
|
||||
"pezpallet-assets/runtime-benchmarks",
|
||||
"pezpallet-authorship/runtime-benchmarks",
|
||||
"pezpallet-balances/runtime-benchmarks",
|
||||
"pezpallet-collator-selection/runtime-benchmarks",
|
||||
"pezpallet-message-queue/runtime-benchmarks",
|
||||
"pezpallet-treasury/runtime-benchmarks",
|
||||
"pezpallet-xcm/runtime-benchmarks",
|
||||
"pezkuwi-primitives/runtime-benchmarks",
|
||||
"pezkuwi-runtime-common/runtime-benchmarks",
|
||||
"pezsp-consensus-aura/runtime-benchmarks",
|
||||
"pezsp-io/runtime-benchmarks",
|
||||
"pezsp-runtime/runtime-benchmarks",
|
||||
"teyrchain-info/runtime-benchmarks",
|
||||
"xcm-executor/runtime-benchmarks",
|
||||
"xcm/runtime-benchmarks",
|
||||
]
|
||||
|
||||
try-runtime = [
|
||||
"pezframe-support/try-runtime",
|
||||
"pezframe-system/try-runtime",
|
||||
"pezpallet-asset-tx-payment/try-runtime",
|
||||
"pezpallet-assets/try-runtime",
|
||||
"pezpallet-authorship/try-runtime",
|
||||
"pezpallet-balances/try-runtime",
|
||||
"pezpallet-collator-selection/try-runtime",
|
||||
"pezpallet-message-queue/try-runtime",
|
||||
"pezpallet-treasury/try-runtime",
|
||||
"pezpallet-xcm/try-runtime",
|
||||
"pezkuwi-runtime-common/try-runtime",
|
||||
"pezsp-runtime/try-runtime",
|
||||
"teyrchain-info/try-runtime",
|
||||
]
|
||||
@@ -0,0 +1,347 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! Auxiliary struct/enums for teyrchain runtimes.
|
||||
//! Taken from pezkuwi/runtime/common (at a21cd64) and adapted for teyrchains.
|
||||
|
||||
use alloc::boxed::Box;
|
||||
use core::marker::PhantomData;
|
||||
use pezframe_support::traits::{
|
||||
fungible, fungibles, tokens::imbalance::ResolveTo, Contains, ContainsPair, Currency, Defensive,
|
||||
Get, Imbalance, OnUnbalanced, OriginTrait,
|
||||
};
|
||||
use pezpallet_asset_tx_payment::HandleCredit;
|
||||
use pezpallet_collator_selection::StakingPotAccountId;
|
||||
use pezsp_runtime::traits::Zero;
|
||||
use xcm::latest::{
|
||||
Asset, AssetId, Fungibility, Fungibility::Fungible, Junction, Junctions::Here, Location,
|
||||
Parent, WeightLimit,
|
||||
};
|
||||
use xcm_executor::traits::ConvertLocation;
|
||||
|
||||
/// Type alias to conveniently refer to `pezframe_system`'s `Config::AccountId`.
|
||||
pub type AccountIdOf<T> = <T as pezframe_system::Config>::AccountId;
|
||||
|
||||
/// Type alias to conveniently refer to the `Currency::NegativeImbalance` associated type.
|
||||
pub type NegativeImbalance<T> = <pezpallet_balances::Pallet<T> as Currency<
|
||||
<T as pezframe_system::Config>::AccountId,
|
||||
>>::NegativeImbalance;
|
||||
|
||||
/// Implementation of `OnUnbalanced` that deposits the fees into a staking pot for later payout.
|
||||
#[deprecated(
|
||||
note = "ToStakingPot is deprecated and will be removed after March 2024. Please use pezframe_support::traits::tokens::imbalance::ResolveTo instead."
|
||||
)]
|
||||
pub struct ToStakingPot<R>(PhantomData<R>);
|
||||
#[allow(deprecated)]
|
||||
impl<R> OnUnbalanced<NegativeImbalance<R>> for ToStakingPot<R>
|
||||
where
|
||||
R: pezpallet_balances::Config + pezpallet_collator_selection::Config,
|
||||
AccountIdOf<R>: From<pezkuwi_primitives::AccountId> + Into<pezkuwi_primitives::AccountId>,
|
||||
<R as pezframe_system::Config>::RuntimeEvent: From<pezpallet_balances::Event<R>>,
|
||||
{
|
||||
fn on_nonzero_unbalanced(amount: NegativeImbalance<R>) {
|
||||
let staking_pot = <pezpallet_collator_selection::Pallet<R>>::account_id();
|
||||
// In case of error: Will drop the result triggering the `OnDrop` of the imbalance.
|
||||
<pezpallet_balances::Pallet<R>>::resolve_creating(&staking_pot, amount);
|
||||
}
|
||||
}
|
||||
|
||||
/// Fungible implementation of `OnUnbalanced` that deals with the fees by combining tip and fee and
|
||||
/// passing the result on to `ToStakingPot`.
|
||||
pub struct DealWithFees<R>(PhantomData<R>);
|
||||
impl<R> OnUnbalanced<fungible::Credit<R::AccountId, pezpallet_balances::Pallet<R>>> for DealWithFees<R>
|
||||
where
|
||||
R: pezpallet_balances::Config + pezpallet_collator_selection::Config,
|
||||
AccountIdOf<R>: From<pezkuwi_primitives::AccountId> + Into<pezkuwi_primitives::AccountId>,
|
||||
<R as pezframe_system::Config>::RuntimeEvent: From<pezpallet_balances::Event<R>>,
|
||||
{
|
||||
fn on_unbalanceds(
|
||||
mut fees_then_tips: impl Iterator<
|
||||
Item = fungible::Credit<R::AccountId, pezpallet_balances::Pallet<R>>,
|
||||
>,
|
||||
) {
|
||||
if let Some(mut fees) = fees_then_tips.next() {
|
||||
if let Some(tips) = fees_then_tips.next() {
|
||||
tips.merge_into(&mut fees);
|
||||
}
|
||||
ResolveTo::<StakingPotAccountId<R>, pezpallet_balances::Pallet<R>>::on_unbalanced(fees)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 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, I>(PhantomData<(R, I)>);
|
||||
impl<R, I> HandleCredit<AccountIdOf<R>, pezpallet_assets::Pallet<R, I>> for AssetsToBlockAuthor<R, I>
|
||||
where
|
||||
I: 'static,
|
||||
R: pezpallet_authorship::Config + pezpallet_assets::Config<I>,
|
||||
AccountIdOf<R>: From<pezkuwi_primitives::AccountId> + Into<pezkuwi_primitives::AccountId>,
|
||||
{
|
||||
fn handle_credit(credit: fungibles::Credit<AccountIdOf<R>, pezpallet_assets::Pallet<R, I>>) {
|
||||
use pezframe_support::traits::fungibles::Balanced;
|
||||
if let Some(author) = pezpallet_authorship::Pallet::<R>::author() {
|
||||
// In case of error: Will drop the result triggering the `OnDrop` of the imbalance.
|
||||
let _ = pezpallet_assets::Pallet::<R, I>::resolve(&author, credit).defensive();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Allow checking in assets that have issuance > 0.
|
||||
pub struct NonZeroIssuance<AccountId, Assets>(PhantomData<(AccountId, Assets)>);
|
||||
impl<AccountId, Assets> Contains<<Assets as fungibles::Inspect<AccountId>>::AssetId>
|
||||
for NonZeroIssuance<AccountId, Assets>
|
||||
where
|
||||
Assets: fungibles::Inspect<AccountId>,
|
||||
{
|
||||
fn contains(id: &<Assets as fungibles::Inspect<AccountId>>::AssetId) -> bool {
|
||||
!Assets::total_issuance(id.clone()).is_zero()
|
||||
}
|
||||
}
|
||||
|
||||
/// Allow checking in assets that exists.
|
||||
pub struct AssetExists<AccountId, Assets>(PhantomData<(AccountId, Assets)>);
|
||||
impl<AccountId, Assets> Contains<<Assets as fungibles::Inspect<AccountId>>::AssetId>
|
||||
for AssetExists<AccountId, Assets>
|
||||
where
|
||||
Assets: fungibles::Inspect<AccountId>,
|
||||
{
|
||||
fn contains(id: &<Assets as fungibles::Inspect<AccountId>>::AssetId) -> bool {
|
||||
Assets::asset_exists(id.clone())
|
||||
}
|
||||
}
|
||||
|
||||
/// Asset filter that allows all assets from a certain location.
|
||||
pub struct AssetsFrom<T>(PhantomData<T>);
|
||||
impl<T: Get<Location>> ContainsPair<Asset, Location> for AssetsFrom<T> {
|
||||
fn contains(asset: &Asset, origin: &Location) -> bool {
|
||||
let loc = T::get();
|
||||
&loc == origin &&
|
||||
matches!(asset, Asset { id: AssetId(asset_loc), fun: Fungible(_a) }
|
||||
if asset_loc.match_and_split(&loc).is_some())
|
||||
}
|
||||
}
|
||||
|
||||
/// Type alias to conveniently refer to the `Currency::Balance` associated type.
|
||||
pub type BalanceOf<T> =
|
||||
<pezpallet_balances::Pallet<T> as Currency<<T as pezframe_system::Config>::AccountId>>::Balance;
|
||||
|
||||
/// Implements `OnUnbalanced::on_unbalanced` to teleport slashed assets to relay chain treasury
|
||||
/// account.
|
||||
pub struct ToParentTreasury<TreasuryAccount, AccountIdConverter, T>(
|
||||
PhantomData<(TreasuryAccount, AccountIdConverter, T)>,
|
||||
);
|
||||
|
||||
impl<TreasuryAccount, AccountIdConverter, T> OnUnbalanced<NegativeImbalance<T>>
|
||||
for ToParentTreasury<TreasuryAccount, AccountIdConverter, T>
|
||||
where
|
||||
T: pezpallet_balances::Config + pezpallet_xcm::Config + pezframe_system::Config,
|
||||
<<T as pezframe_system::Config>::RuntimeOrigin as OriginTrait>::AccountId: From<AccountIdOf<T>>,
|
||||
[u8; 32]: From<<T as pezframe_system::Config>::AccountId>,
|
||||
TreasuryAccount: Get<AccountIdOf<T>>,
|
||||
AccountIdConverter: ConvertLocation<AccountIdOf<T>>,
|
||||
BalanceOf<T>: Into<Fungibility>,
|
||||
{
|
||||
fn on_unbalanced(amount: NegativeImbalance<T>) {
|
||||
let amount = match amount.drop_zero() {
|
||||
Ok(..) => return,
|
||||
Err(amount) => amount,
|
||||
};
|
||||
let imbalance = amount.peek();
|
||||
let root_location: Location = Here.into();
|
||||
let root_account: AccountIdOf<T> =
|
||||
match AccountIdConverter::convert_location(&root_location) {
|
||||
Some(a) => a,
|
||||
None => {
|
||||
tracing::warn!(target: "xcm::on_unbalanced", "Failed to convert root origin into account id");
|
||||
return;
|
||||
},
|
||||
};
|
||||
let treasury_account: AccountIdOf<T> = TreasuryAccount::get();
|
||||
|
||||
<pezpallet_balances::Pallet<T>>::resolve_creating(&root_account, amount);
|
||||
|
||||
let result = <pezpallet_xcm::Pallet<T>>::limited_teleport_assets(
|
||||
<<T as pezframe_system::Config>::RuntimeOrigin>::root(),
|
||||
Box::new(Parent.into()),
|
||||
Box::new(
|
||||
Junction::AccountId32 { network: None, id: treasury_account.into() }
|
||||
.into_location()
|
||||
.into(),
|
||||
),
|
||||
Box::new((Parent, imbalance).into()),
|
||||
Box::new(Parent.into()),
|
||||
WeightLimit::Unlimited,
|
||||
);
|
||||
|
||||
if let Err(err) = result {
|
||||
tracing::warn!(target: "xcm::on_unbalanced", error=?err, "Failed to teleport slashed assets");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use pezframe_support::{
|
||||
derive_impl, parameter_types,
|
||||
traits::{ConstU32, FindAuthor, ValidatorRegistration},
|
||||
PalletId,
|
||||
};
|
||||
use pezframe_system::{limits, EnsureRoot};
|
||||
use pezpallet_collator_selection::IdentityCollator;
|
||||
use pezkuwi_primitives::AccountId;
|
||||
use pezsp_core::H256;
|
||||
use pezsp_runtime::{
|
||||
traits::{BlakeTwo256, IdentityLookup},
|
||||
BuildStorage, Perbill,
|
||||
};
|
||||
use xcm::prelude::*;
|
||||
|
||||
type Block = pezframe_system::mocking::MockBlock<Test>;
|
||||
const TEST_ACCOUNT: AccountId = AccountId::new([1; 32]);
|
||||
|
||||
pezframe_support::construct_runtime!(
|
||||
pub enum Test
|
||||
{
|
||||
System: pezframe_system::{Pallet, Call, Config<T>, Storage, Event<T>},
|
||||
Balances: pezpallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
|
||||
CollatorSelection: pezpallet_collator_selection::{Pallet, Call, Storage, Event<T>},
|
||||
}
|
||||
);
|
||||
|
||||
parameter_types! {
|
||||
pub BlockLength: limits::BlockLength = limits::BlockLength::max(2 * 1024);
|
||||
pub const AvailableBlockRatio: Perbill = Perbill::one();
|
||||
}
|
||||
|
||||
#[derive_impl(pezframe_system::config_preludes::TestDefaultConfig)]
|
||||
impl pezframe_system::Config for Test {
|
||||
type BaseCallFilter = pezframe_support::traits::Everything;
|
||||
type RuntimeOrigin = RuntimeOrigin;
|
||||
type Nonce = u64;
|
||||
type RuntimeCall = RuntimeCall;
|
||||
type Hash = H256;
|
||||
type Hashing = BlakeTwo256;
|
||||
type AccountId = AccountId;
|
||||
type Lookup = IdentityLookup<Self::AccountId>;
|
||||
type Block = Block;
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type BlockLength = BlockLength;
|
||||
type BlockWeights = ();
|
||||
type DbWeight = ();
|
||||
type Version = ();
|
||||
type PalletInfo = PalletInfo;
|
||||
type AccountData = pezpallet_balances::AccountData<u64>;
|
||||
type OnNewAccount = ();
|
||||
type OnKilledAccount = ();
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = pezframe_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
#[derive_impl(pezpallet_balances::config_preludes::TestDefaultConfig)]
|
||||
impl pezpallet_balances::Config for Test {
|
||||
type AccountStore = System;
|
||||
}
|
||||
|
||||
pub struct OneAuthor;
|
||||
impl FindAuthor<AccountId> for OneAuthor {
|
||||
fn find_author<'a, I>(_: I) -> Option<AccountId>
|
||||
where
|
||||
I: 'a,
|
||||
{
|
||||
Some(TEST_ACCOUNT)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IsRegistered;
|
||||
impl ValidatorRegistration<AccountId> for IsRegistered {
|
||||
fn is_registered(_id: &AccountId) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const PotId: PalletId = PalletId(*b"PotStake");
|
||||
}
|
||||
|
||||
impl pezpallet_collator_selection::Config for Test {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type Currency = Balances;
|
||||
type UpdateOrigin = EnsureRoot<AccountId>;
|
||||
type PotId = PotId;
|
||||
type MaxCandidates = ConstU32<20>;
|
||||
type MinEligibleCollators = ConstU32<1>;
|
||||
type MaxInvulnerables = ConstU32<20>;
|
||||
type ValidatorId = <Self as pezframe_system::Config>::AccountId;
|
||||
type ValidatorIdOf = IdentityCollator;
|
||||
type ValidatorRegistration = IsRegistered;
|
||||
type KickThreshold = ();
|
||||
type WeightInfo = ();
|
||||
}
|
||||
|
||||
impl pezpallet_authorship::Config for Test {
|
||||
type FindAuthor = OneAuthor;
|
||||
type EventHandler = ();
|
||||
}
|
||||
|
||||
pub fn new_test_ext() -> pezsp_io::TestExternalities {
|
||||
let mut t = pezframe_system::GenesisConfig::<Test>::default().build_storage().unwrap();
|
||||
// We use default for brevity, but you can configure as desired if needed.
|
||||
pezpallet_balances::GenesisConfig::<Test>::default()
|
||||
.assimilate_storage(&mut t)
|
||||
.unwrap();
|
||||
t.into()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fees_and_tip_split() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let fee =
|
||||
<pezpallet_balances::Pallet<Test> as pezframe_support::traits::fungible::Balanced<
|
||||
AccountId,
|
||||
>>::issue(10);
|
||||
let tip =
|
||||
<pezpallet_balances::Pallet<Test> as pezframe_support::traits::fungible::Balanced<
|
||||
AccountId,
|
||||
>>::issue(20);
|
||||
|
||||
assert_eq!(Balances::free_balance(TEST_ACCOUNT), 0);
|
||||
|
||||
DealWithFees::on_unbalanceds(vec![fee, tip].into_iter());
|
||||
|
||||
// Author gets 100% of tip and 100% of fee = 30
|
||||
assert_eq!(Balances::free_balance(CollatorSelection::account_id()), 30);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn assets_from_filters_correctly() {
|
||||
parameter_types! {
|
||||
pub SomeSiblingTeyrchain: Location = (Parent, Teyrchain(1234)).into();
|
||||
}
|
||||
|
||||
let asset_location = SomeSiblingTeyrchain::get()
|
||||
.pushed_with_interior(GeneralIndex(42))
|
||||
.expect("location will only have 2 junctions; qed");
|
||||
let asset = Asset { id: AssetId(asset_location), fun: 1_000_000u128.into() };
|
||||
assert!(
|
||||
AssetsFrom::<SomeSiblingTeyrchain>::contains(&asset, &SomeSiblingTeyrchain::get()),
|
||||
"AssetsFrom should allow assets from any of its interior locations"
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
pub mod impls;
|
||||
pub mod message_queue;
|
||||
pub mod pay;
|
||||
pub mod xcm_config;
|
||||
pub use constants::*;
|
||||
pub use opaque::*;
|
||||
pub use types::*;
|
||||
|
||||
/// Common types of teyrchains.
|
||||
mod types {
|
||||
use pezsp_runtime::traits::{IdentifyAccount, Verify};
|
||||
|
||||
/// An index to a block.
|
||||
pub type BlockNumber = u32;
|
||||
|
||||
/// Alias to 512-bit hash when used in the context of a transaction signature on the chain.
|
||||
pub type Signature = pezsp_runtime::MultiSignature;
|
||||
|
||||
/// Some way of identifying an account on the chain. We intentionally make it equivalent
|
||||
/// to the public key of our transaction signing scheme.
|
||||
pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;
|
||||
|
||||
/// The type for looking up accounts. We don't expect more than 4 billion of them, but you
|
||||
/// never know...
|
||||
pub type AccountIndex = u32;
|
||||
|
||||
/// Balance of an account.
|
||||
pub type Balance = u128;
|
||||
|
||||
/// Index of a transaction in the chain.
|
||||
pub type Nonce = u32;
|
||||
|
||||
/// A hash of some data used by the chain.
|
||||
pub type Hash = pezsp_core::H256;
|
||||
|
||||
/// Digest item type.
|
||||
pub type DigestItem = pezsp_runtime::generic::DigestItem;
|
||||
|
||||
// Aura consensus authority.
|
||||
pub type AuraId = pezsp_consensus_aura::sr25519::AuthorityId;
|
||||
|
||||
// Aura consensus authority used by Asset Hub Pezkuwi.
|
||||
//
|
||||
// Because of registering the authorities with an ed25519 key before switching from Shell
|
||||
// to Asset Hub Pezkuwi, we were required to deploy a hotfix that changed Asset Hub Pezkuwi's
|
||||
// Aura keys to ed22519. In the future that may change again.
|
||||
pub type AssetHubPezkuwiAuraId = pezsp_consensus_aura::ed25519::AuthorityId;
|
||||
|
||||
// Id used for identifying assets.
|
||||
pub type AssetIdForTrustBackedAssets = u32;
|
||||
|
||||
// Id used for identifying non-fungible collections.
|
||||
pub type CollectionId = u32;
|
||||
|
||||
// Id used for identifying non-fungible items.
|
||||
pub type ItemId = u32;
|
||||
}
|
||||
|
||||
/// Common constants of teyrchains.
|
||||
mod constants {
|
||||
use super::types::BlockNumber;
|
||||
use pezframe_support::{
|
||||
weights::{constants::WEIGHT_REF_TIME_PER_SECOND, Weight},
|
||||
PalletId,
|
||||
};
|
||||
use pezsp_runtime::Perbill;
|
||||
|
||||
/// This determines the average expected block time that we are targeting. Blocks will be
|
||||
/// produced at a minimum duration defined by `SLOT_DURATION`. `SLOT_DURATION` is picked up by
|
||||
/// `pezpallet_timestamp` which is in turn picked up by `pezpallet_aura` to implement `fn
|
||||
/// slot_duration()`.
|
||||
///
|
||||
/// Change this to adjust the block time.
|
||||
pub const MILLISECS_PER_BLOCK: u64 = 12000;
|
||||
pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;
|
||||
|
||||
// Time is measured by number of blocks.
|
||||
pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);
|
||||
pub const HOURS: BlockNumber = MINUTES * 60;
|
||||
pub const DAYS: BlockNumber = HOURS * 24;
|
||||
|
||||
/// We assume that ~5% of the block weight is consumed by `on_initialize` handlers. This is
|
||||
/// used to limit the maximal weight of a single extrinsic.
|
||||
pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(5);
|
||||
/// We allow `Normal` extrinsics to fill up the block up to 75%, the rest can be used by
|
||||
/// Operational extrinsics.
|
||||
pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);
|
||||
|
||||
/// We allow for 0.5 seconds of compute with a 6 second average block time.
|
||||
pub const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts(
|
||||
WEIGHT_REF_TIME_PER_SECOND.saturating_div(2),
|
||||
pezkuwi_primitives::MAX_POV_SIZE as u64,
|
||||
);
|
||||
|
||||
/// We allow for 2 seconds of compute with a 6 second average block.
|
||||
pub const MAXIMUM_BLOCK_WEIGHT_FOR_ASYNC_BACKING: Weight = Weight::from_parts(
|
||||
WEIGHT_REF_TIME_PER_SECOND.saturating_mul(2),
|
||||
pezkuwi_primitives::MAX_POV_SIZE as u64,
|
||||
);
|
||||
|
||||
/// Treasury pallet id of the local chain, used to convert into AccountId
|
||||
pub const TREASURY_PALLET_ID: PalletId = PalletId(*b"py/trsry");
|
||||
}
|
||||
|
||||
/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
|
||||
/// the specifics of the runtime. They can then be made to be agnostic over specific formats
|
||||
/// of data like extrinsics, allowing for them to continue syncing the network through upgrades
|
||||
/// to even the core data structures.
|
||||
pub mod opaque {
|
||||
use super::*;
|
||||
use pezsp_runtime::{generic, traits::BlakeTwo256};
|
||||
|
||||
pub use pezsp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;
|
||||
/// Opaque block header type.
|
||||
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
|
||||
/// Opaque block type.
|
||||
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
|
||||
/// Opaque block identifier type.
|
||||
pub type BlockId = generic::BlockId<Block>;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// This file is part of Pezcumulus.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! Helpers to deal with configuring the message queue in the runtime.
|
||||
|
||||
use core::marker::PhantomData;
|
||||
use cumulus_primitives_core::{AggregateMessageOrigin, ParaId};
|
||||
use pezframe_support::traits::{QueueFootprint, QueuePausedQuery};
|
||||
use pezpallet_message_queue::OnQueueChanged;
|
||||
|
||||
/// Narrow the scope of the `Inner` query from `AggregateMessageOrigin` to `ParaId`.
|
||||
///
|
||||
/// All non-`Sibling` variants will be ignored.
|
||||
pub struct NarrowOriginToSibling<Inner>(PhantomData<Inner>);
|
||||
impl<Inner: QueuePausedQuery<ParaId>> QueuePausedQuery<AggregateMessageOrigin>
|
||||
for NarrowOriginToSibling<Inner>
|
||||
{
|
||||
fn is_paused(origin: &AggregateMessageOrigin) -> bool {
|
||||
match origin {
|
||||
AggregateMessageOrigin::Sibling(id) => Inner::is_paused(id),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner: OnQueueChanged<ParaId>> OnQueueChanged<AggregateMessageOrigin>
|
||||
for NarrowOriginToSibling<Inner>
|
||||
{
|
||||
fn on_queue_changed(origin: AggregateMessageOrigin, fp: QueueFootprint) {
|
||||
if let AggregateMessageOrigin::Sibling(id) = origin {
|
||||
Inner::on_queue_changed(id, fp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a sibling `ParaId` to an `AggregateMessageOrigin`.
|
||||
pub struct ParaIdToSibling;
|
||||
impl pezsp_runtime::traits::Convert<ParaId, AggregateMessageOrigin> for ParaIdToSibling {
|
||||
fn convert(para_id: ParaId) -> AggregateMessageOrigin {
|
||||
AggregateMessageOrigin::Sibling(para_id)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// This file is part of Pezcumulus.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
|
||||
use pezframe_support::traits::{
|
||||
fungibles,
|
||||
tokens::{PaymentStatus, Preservation},
|
||||
};
|
||||
use pezkuwi_runtime_common::impls::VersionedLocatableAsset;
|
||||
use pezsp_runtime::{traits::TypedGet, DispatchError, RuntimeDebug};
|
||||
use xcm::latest::prelude::*;
|
||||
use xcm_executor::traits::ConvertLocation;
|
||||
|
||||
/// Versioned locatable account type which contains both an XCM `location` and `account_id` to
|
||||
/// identify an account which exists on some chain.
|
||||
#[derive(
|
||||
Encode,
|
||||
Decode,
|
||||
Eq,
|
||||
PartialEq,
|
||||
Clone,
|
||||
RuntimeDebug,
|
||||
scale_info::TypeInfo,
|
||||
MaxEncodedLen,
|
||||
DecodeWithMemTracking,
|
||||
)]
|
||||
pub enum VersionedLocatableAccount {
|
||||
#[codec(index = 4)]
|
||||
V4 { location: xcm::v4::Location, account_id: xcm::v4::Location },
|
||||
#[codec(index = 5)]
|
||||
V5 { location: xcm::v5::Location, account_id: xcm::v5::Location },
|
||||
}
|
||||
|
||||
/// Pay on the local chain with `fungibles` implementation if the beneficiary and the asset are both
|
||||
/// local.
|
||||
pub struct LocalPay<F, A, C>(core::marker::PhantomData<(F, A, C)>);
|
||||
impl<A, F, C> pezframe_support::traits::tokens::Pay for LocalPay<F, A, C>
|
||||
where
|
||||
A: TypedGet,
|
||||
F: fungibles::Mutate<A::Type, AssetId = xcm::v5::Location> + fungibles::Create<A::Type>,
|
||||
C: ConvertLocation<A::Type>,
|
||||
A::Type: Eq + Clone,
|
||||
{
|
||||
type Balance = F::Balance;
|
||||
type Beneficiary = VersionedLocatableAccount;
|
||||
type AssetKind = VersionedLocatableAsset;
|
||||
type Id = QueryId;
|
||||
type Error = DispatchError;
|
||||
fn pay(
|
||||
who: &Self::Beneficiary,
|
||||
asset: Self::AssetKind,
|
||||
amount: Self::Balance,
|
||||
) -> Result<Self::Id, Self::Error> {
|
||||
let who = Self::match_location(who).map_err(|_| DispatchError::Unavailable)?;
|
||||
let asset = Self::match_asset(&asset).map_err(|_| DispatchError::Unavailable)?;
|
||||
<F as fungibles::Mutate<_>>::transfer(
|
||||
asset,
|
||||
&A::get(),
|
||||
&who,
|
||||
amount,
|
||||
Preservation::Expendable,
|
||||
)?;
|
||||
// We use `QueryId::MAX` as a constant identifier for these payments since they are always
|
||||
// processed immediately and successfully on the local chain. The `QueryId` type is used to
|
||||
// maintain compatibility with XCM payment implementations.
|
||||
Ok(Self::Id::MAX)
|
||||
}
|
||||
fn check_payment(_: Self::Id) -> PaymentStatus {
|
||||
PaymentStatus::Success
|
||||
}
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
fn ensure_successful(_: &Self::Beneficiary, asset: Self::AssetKind, amount: Self::Balance) {
|
||||
let asset = Self::match_asset(&asset).expect("invalid asset");
|
||||
<F as fungibles::Create<_>>::create(asset.clone(), A::get(), true, amount).unwrap();
|
||||
<F as fungibles::Mutate<_>>::mint_into(asset, &A::get(), amount).unwrap();
|
||||
}
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
fn ensure_concluded(_: Self::Id) {}
|
||||
}
|
||||
|
||||
impl<A, F, C> LocalPay<F, A, C>
|
||||
where
|
||||
A: TypedGet,
|
||||
F: fungibles::Mutate<A::Type> + fungibles::Create<A::Type>,
|
||||
C: ConvertLocation<A::Type>,
|
||||
A::Type: Eq + Clone,
|
||||
{
|
||||
fn match_location(who: &VersionedLocatableAccount) -> Result<A::Type, ()> {
|
||||
// only applicable for the local accounts
|
||||
let account_id = match who {
|
||||
VersionedLocatableAccount::V4 { location, account_id } if location.is_here() =>
|
||||
&account_id.clone().try_into().map_err(|_| ())?,
|
||||
VersionedLocatableAccount::V5 { location, account_id } if location.is_here() =>
|
||||
account_id,
|
||||
_ => return Err(()),
|
||||
};
|
||||
C::convert_location(account_id).ok_or(())
|
||||
}
|
||||
fn match_asset(asset: &VersionedLocatableAsset) -> Result<xcm::v5::Location, ()> {
|
||||
match asset {
|
||||
VersionedLocatableAsset::V4 { location, asset_id } if location.is_here() =>
|
||||
asset_id.clone().try_into().map(|a: xcm::v5::AssetId| a.0).map_err(|_| ()),
|
||||
VersionedLocatableAsset::V5 { location, asset_id } if location.is_here() =>
|
||||
Ok(asset_id.clone().0),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
pub mod benchmarks {
|
||||
use super::*;
|
||||
use core::marker::PhantomData;
|
||||
use pezframe_support::traits::Get;
|
||||
use pezpallet_treasury::ArgumentsFactory as TreasuryArgumentsFactory;
|
||||
use pezsp_core::ConstU8;
|
||||
|
||||
/// Provides factory methods for the `AssetKind` and the `Beneficiary` that are applicable for
|
||||
/// the payout made by [`LocalPay`].
|
||||
///
|
||||
/// ### Parameters:
|
||||
/// - `PalletId`: The ID of the assets registry pallet.
|
||||
/// - `AssetId`: The ID of the asset that will be created for the benchmark within `PalletId`.
|
||||
pub struct LocalPayArguments<PalletId = ConstU8<0>>(PhantomData<PalletId>);
|
||||
impl<PalletId: Get<u8>>
|
||||
TreasuryArgumentsFactory<VersionedLocatableAsset, VersionedLocatableAccount>
|
||||
for LocalPayArguments<PalletId>
|
||||
{
|
||||
fn create_asset_kind(seed: u32) -> VersionedLocatableAsset {
|
||||
VersionedLocatableAsset::V5 {
|
||||
location: Location::new(0, []),
|
||||
asset_id: Location::new(
|
||||
0,
|
||||
[PalletInstance(PalletId::get()), GeneralIndex(seed.into())],
|
||||
)
|
||||
.into(),
|
||||
}
|
||||
}
|
||||
fn create_beneficiary(seed: [u8; 32]) -> VersionedLocatableAccount {
|
||||
VersionedLocatableAccount::V5 {
|
||||
location: Location::new(0, []),
|
||||
account_id: Location::new(0, [AccountId32 { network: None, id: seed }]),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,315 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::impls::AccountIdOf;
|
||||
use core::marker::PhantomData;
|
||||
use cumulus_primitives_core::{IsSystem, ParaId};
|
||||
use pezframe_support::{
|
||||
traits::{fungibles::Inspect, tokens::ConversionToAssetBalance, Contains, ContainsPair},
|
||||
weights::Weight,
|
||||
};
|
||||
use pezsp_runtime::traits::Get;
|
||||
use xcm::latest::prelude::*;
|
||||
|
||||
/// A `ChargeFeeInFungibles` implementation that converts the output of
|
||||
/// a given WeightToFee implementation an amount charged in
|
||||
/// a particular assetId from pezpallet-assets
|
||||
pub struct AssetFeeAsExistentialDepositMultiplier<
|
||||
Runtime,
|
||||
WeightToFee,
|
||||
BalanceConverter,
|
||||
AssetInstance: 'static,
|
||||
>(PhantomData<(Runtime, WeightToFee, BalanceConverter, AssetInstance)>);
|
||||
impl<CurrencyBalance, Runtime, WeightToFee, BalanceConverter, AssetInstance>
|
||||
cumulus_primitives_utility::ChargeWeightInFungibles<
|
||||
AccountIdOf<Runtime>,
|
||||
pezpallet_assets::Pallet<Runtime, AssetInstance>,
|
||||
> for AssetFeeAsExistentialDepositMultiplier<Runtime, WeightToFee, BalanceConverter, AssetInstance>
|
||||
where
|
||||
Runtime: pezpallet_assets::Config<AssetInstance>,
|
||||
WeightToFee: pezframe_support::weights::WeightToFee<Balance = CurrencyBalance>,
|
||||
BalanceConverter: ConversionToAssetBalance<
|
||||
CurrencyBalance,
|
||||
<Runtime as pezpallet_assets::Config<AssetInstance>>::AssetId,
|
||||
<Runtime as pezpallet_assets::Config<AssetInstance>>::Balance,
|
||||
>,
|
||||
<BalanceConverter as ConversionToAssetBalance<
|
||||
CurrencyBalance,
|
||||
<Runtime as pezpallet_assets::Config<AssetInstance>>::AssetId,
|
||||
<Runtime as pezpallet_assets::Config<AssetInstance>>::Balance,
|
||||
>>::Error: core::fmt::Debug,
|
||||
{
|
||||
fn charge_weight_in_fungibles(
|
||||
asset_id: <pezpallet_assets::Pallet<Runtime, AssetInstance> as Inspect<
|
||||
AccountIdOf<Runtime>,
|
||||
>>::AssetId,
|
||||
weight: Weight,
|
||||
) -> Result<
|
||||
<pezpallet_assets::Pallet<Runtime, AssetInstance> as Inspect<AccountIdOf<Runtime>>>::Balance,
|
||||
XcmError,
|
||||
> {
|
||||
let amount = WeightToFee::weight_to_fee(&weight);
|
||||
// If the amount gotten is not at least the ED, then make it be the ED of the asset
|
||||
// This is to avoid burning assets and decreasing the supply
|
||||
let asset_amount = BalanceConverter::to_asset_balance(amount, asset_id)
|
||||
.map_err(|error| {
|
||||
tracing::debug!(target: "xcm::charge_weight_in_fungibles", ?error, "AssetFeeAsExistentialDepositMultiplier cannot convert to valid balance (possibly below ED)");
|
||||
XcmError::TooExpensive
|
||||
})?;
|
||||
Ok(asset_amount)
|
||||
}
|
||||
}
|
||||
|
||||
/// Accepts an asset if it is a native asset from a particular `Location`.
|
||||
pub struct ConcreteNativeAssetFrom<LocationValue>(PhantomData<LocationValue>);
|
||||
impl<LocationValue: Get<Location>> ContainsPair<Asset, Location>
|
||||
for ConcreteNativeAssetFrom<LocationValue>
|
||||
{
|
||||
fn contains(asset: &Asset, origin: &Location) -> bool {
|
||||
tracing::trace!(
|
||||
target: "xcm::filter_asset_location",
|
||||
?asset, ?origin, location=?LocationValue::get(),
|
||||
"ConcreteNativeAsset"
|
||||
);
|
||||
asset.id.0 == *origin && origin == &LocationValue::get()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RelayOrOtherSystemTeyrchains<
|
||||
SystemTeyrchainMatcher: Contains<Location>,
|
||||
Runtime: teyrchain_info::Config,
|
||||
> {
|
||||
_runtime: PhantomData<(SystemTeyrchainMatcher, Runtime)>,
|
||||
}
|
||||
impl<SystemTeyrchainMatcher: Contains<Location>, Runtime: teyrchain_info::Config> Contains<Location>
|
||||
for RelayOrOtherSystemTeyrchains<SystemTeyrchainMatcher, Runtime>
|
||||
{
|
||||
fn contains(l: &Location) -> bool {
|
||||
let self_para_id: u32 = teyrchain_info::Pallet::<Runtime>::get().into();
|
||||
if let (0, [Teyrchain(para_id)]) = l.unpack() {
|
||||
if *para_id == self_para_id {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
matches!(l.unpack(), (1, [])) || SystemTeyrchainMatcher::contains(l)
|
||||
}
|
||||
}
|
||||
|
||||
/// Contains all sibling system teyrchains, including the one where this matcher is used.
|
||||
///
|
||||
/// This structure can only be used at a teyrchain level. In the Relay Chain, please use
|
||||
/// the `xcm_builder::IsChildSystemTeyrchain` matcher.
|
||||
pub struct AllSiblingSystemTeyrchains;
|
||||
impl Contains<Location> for AllSiblingSystemTeyrchains {
|
||||
fn contains(l: &Location) -> bool {
|
||||
tracing::trace!(target: "xcm::contains", location=?l, "AllSiblingSystemTeyrchains");
|
||||
match l.unpack() {
|
||||
// System teyrchain
|
||||
(1, [Teyrchain(id)]) => ParaId::from(*id).is_system(),
|
||||
// Everything else
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Accepts an asset if it is a concrete asset from the system (Relay Chain or system teyrchain).
|
||||
pub struct ConcreteAssetFromSystem<AssetLocation>(PhantomData<AssetLocation>);
|
||||
impl<AssetLocation: Get<Location>> ContainsPair<Asset, Location>
|
||||
for ConcreteAssetFromSystem<AssetLocation>
|
||||
{
|
||||
fn contains(asset: &Asset, origin: &Location) -> bool {
|
||||
tracing::trace!(target: "xcm::contains", ?asset, ?origin, "ConcreteAssetFromSystem");
|
||||
let is_system = match origin.unpack() {
|
||||
// The Relay Chain
|
||||
(1, []) => true,
|
||||
// System teyrchain
|
||||
(1, [Teyrchain(id)]) => ParaId::from(*id).is_system(),
|
||||
// Others
|
||||
_ => false,
|
||||
};
|
||||
asset.id.0 == AssetLocation::get() && is_system
|
||||
}
|
||||
}
|
||||
|
||||
/// Filter to check if a given location is the parent Relay Chain or a sibling teyrchain.
|
||||
///
|
||||
/// This type should only be used within the context of a teyrchain, since it does not verify that
|
||||
/// the parent is indeed a Relay Chain.
|
||||
pub struct ParentRelayOrSiblingTeyrchains;
|
||||
impl Contains<Location> for ParentRelayOrSiblingTeyrchains {
|
||||
fn contains(location: &Location) -> bool {
|
||||
matches!(location.unpack(), (1, []) | (1, [Teyrchain(_)]))
|
||||
}
|
||||
}
|
||||
|
||||
/// Filter to check if a given `target` location represents the same AccountId32 as `origin`,
|
||||
/// but coming from another sibling system chain.
|
||||
///
|
||||
/// This type should only be used within the context of a teyrchain, to allow accounts on system
|
||||
/// chains to Alias to the same accounts on the local chain.
|
||||
pub struct AliasAccountId32FromSiblingSystemChain;
|
||||
impl ContainsPair<Location, Location> for AliasAccountId32FromSiblingSystemChain {
|
||||
fn contains(origin: &Location, target: &Location) -> bool {
|
||||
let result = match origin.unpack() {
|
||||
// `origin` is AccountId32 on sibling system teyrchain
|
||||
(1, [Teyrchain(para_id), AccountId32 { network: _, id: origin }])
|
||||
if ParaId::from(*para_id).is_system() =>
|
||||
{
|
||||
match target.unpack() {
|
||||
// `target` is local AccountId32 and matches `origin` remote account
|
||||
(0, [AccountId32 { network: _, id: target }]) => target.eq(origin),
|
||||
_ => false,
|
||||
}
|
||||
},
|
||||
_ => false,
|
||||
};
|
||||
tracing::trace!(
|
||||
target: "xcm::contains",
|
||||
?origin, ?target, ?result,
|
||||
"AliasAccountId32FromSiblingSystemChain"
|
||||
);
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use pezframe_support::{parameter_types, traits::Contains};
|
||||
|
||||
use super::{
|
||||
AliasAccountId32FromSiblingSystemChain, AllSiblingSystemTeyrchains, Asset,
|
||||
ConcreteAssetFromSystem, ContainsPair, GeneralIndex, Here, Location, PalletInstance,
|
||||
Parent, Teyrchain,
|
||||
};
|
||||
use pezkuwi_primitives::LOWEST_PUBLIC_ID;
|
||||
use xcm::latest::prelude::*;
|
||||
|
||||
parameter_types! {
|
||||
pub const RelayLocation: Location = Location::parent();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn concrete_asset_from_relay_works() {
|
||||
let expected_asset: Asset = (Parent, 1000000).into();
|
||||
let expected_origin: Location = (Parent, Here).into();
|
||||
|
||||
assert!(<ConcreteAssetFromSystem<RelayLocation>>::contains(
|
||||
&expected_asset,
|
||||
&expected_origin
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn concrete_asset_from_sibling_system_para_fails_for_wrong_asset() {
|
||||
let unexpected_assets: Vec<Asset> = vec![
|
||||
(Here, 1000000).into(),
|
||||
((PalletInstance(50), GeneralIndex(1)), 1000000).into(),
|
||||
((Parent, Teyrchain(1000), PalletInstance(50), GeneralIndex(1)), 1000000).into(),
|
||||
];
|
||||
let expected_origin: Location = (Parent, Teyrchain(1000)).into();
|
||||
|
||||
unexpected_assets.iter().for_each(|asset| {
|
||||
assert!(!<ConcreteAssetFromSystem<RelayLocation>>::contains(asset, &expected_origin));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn concrete_asset_from_sibling_system_para_works_for_correct_asset() {
|
||||
// (para_id, expected_result)
|
||||
let test_data = vec![
|
||||
(0, true),
|
||||
(1, true),
|
||||
(1000, true),
|
||||
(1999, true),
|
||||
(2000, false), // Not a System Teyrchain
|
||||
(2001, false), // Not a System Teyrchain
|
||||
];
|
||||
|
||||
let expected_asset: Asset = (Parent, 1000000).into();
|
||||
|
||||
for (para_id, expected_result) in test_data {
|
||||
let origin: Location = (Parent, Teyrchain(para_id)).into();
|
||||
assert_eq!(
|
||||
expected_result,
|
||||
<ConcreteAssetFromSystem<RelayLocation>>::contains(&expected_asset, &origin)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn all_sibling_system_teyrchains_works() {
|
||||
// system teyrchain
|
||||
assert!(AllSiblingSystemTeyrchains::contains(&Location::new(1, [Teyrchain(1)])));
|
||||
// non-system teyrchain
|
||||
assert!(!AllSiblingSystemTeyrchains::contains(&Location::new(
|
||||
1,
|
||||
[Teyrchain(LOWEST_PUBLIC_ID.into())]
|
||||
)));
|
||||
// when used at relay chain
|
||||
assert!(!AllSiblingSystemTeyrchains::contains(&Location::new(0, [Teyrchain(1)])));
|
||||
// when used with non-teyrchain
|
||||
assert!(!AllSiblingSystemTeyrchains::contains(&Location::new(1, [OnlyChild])));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn alias_accountid32_from_sibling_system_teyrchains() {
|
||||
let acc_42 = AccountId32 { network: None, id: [42u8; 32] };
|
||||
let acc_13 = AccountId32 { network: None, id: [13u8; 32] };
|
||||
// origin acc_42 on sibling system teyrchain aliases into local acc_42
|
||||
assert!(AliasAccountId32FromSiblingSystemChain::contains(
|
||||
&Location::new(1, [Teyrchain(1), acc_42]),
|
||||
&Location::new(0, [acc_42])
|
||||
));
|
||||
// if target is not local account, always fails
|
||||
assert!(!AliasAccountId32FromSiblingSystemChain::contains(
|
||||
&Location::new(1, [Teyrchain(1), acc_42]),
|
||||
&Location::new(0, [])
|
||||
));
|
||||
assert!(!AliasAccountId32FromSiblingSystemChain::contains(
|
||||
&Location::new(1, [Teyrchain(1), acc_42]),
|
||||
&Location::new(0, [Teyrchain(1)])
|
||||
));
|
||||
assert!(!AliasAccountId32FromSiblingSystemChain::contains(
|
||||
&Location::new(1, [Teyrchain(1), acc_42]),
|
||||
&Location::new(0, [GeneralIndex(42)])
|
||||
));
|
||||
assert!(!AliasAccountId32FromSiblingSystemChain::contains(
|
||||
&Location::new(1, [Teyrchain(1), acc_42]),
|
||||
&Location::new(1, [acc_42])
|
||||
));
|
||||
assert!(!AliasAccountId32FromSiblingSystemChain::contains(
|
||||
&Location::new(1, [Teyrchain(1), acc_42]),
|
||||
&Location::new(2, [acc_42])
|
||||
));
|
||||
// origin acc_13 on sibling system teyrchain CANNOT alias into local acc_42
|
||||
assert!(!AliasAccountId32FromSiblingSystemChain::contains(
|
||||
&Location::new(1, [Teyrchain(1), acc_13]),
|
||||
&Location::new(0, [acc_42])
|
||||
));
|
||||
// origin acc_42 on sibling non-system teyrchain CANNOT alias into local acc_42
|
||||
assert!(!AliasAccountId32FromSiblingSystemChain::contains(
|
||||
&Location::new(1, [Teyrchain(LOWEST_PUBLIC_ID.into()), acc_42]),
|
||||
&Location::new(0, [acc_42])
|
||||
));
|
||||
assert!(!AliasAccountId32FromSiblingSystemChain::contains(
|
||||
&Location::new(0, [acc_13]),
|
||||
&Location::new(0, [acc_13]),
|
||||
));
|
||||
assert!(!AliasAccountId32FromSiblingSystemChain::contains(
|
||||
&Location::new(0, [acc_42]),
|
||||
&Location::new(1, [Teyrchain(1), acc_42]),
|
||||
));
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
[package]
|
||||
name = "pezkuwichain-emulated-chain"
|
||||
version = "0.0.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license = "Apache-2.0"
|
||||
description = "Pezkuwichain emulated chain"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
# Bizinikiwi
|
||||
pezsc-consensus-grandpa = { workspace = true }
|
||||
pezsp-authority-discovery = { workspace = true }
|
||||
pezsp-consensus-babe = { workspace = true }
|
||||
pezsp-consensus-beefy = { workspace = true, default-features = true }
|
||||
pezsp-core = { workspace = true }
|
||||
pezsp-keyring = { workspace = true }
|
||||
|
||||
# Pezkuwi
|
||||
pezkuwi-primitives = { workspace = true }
|
||||
pezkuwichain-runtime = { workspace = true }
|
||||
pezkuwichain-runtime-constants = { workspace = true }
|
||||
|
||||
# Pezcumulus
|
||||
emulated-integration-tests-common = { workspace = true }
|
||||
teyrchains-common = { workspace = true, default-features = true }
|
||||
|
||||
[features]
|
||||
runtime-benchmarks = [
|
||||
"emulated-integration-tests-common/runtime-benchmarks",
|
||||
"pezkuwi-primitives/runtime-benchmarks",
|
||||
"pezkuwichain-runtime-constants/runtime-benchmarks",
|
||||
"pezkuwichain-runtime/runtime-benchmarks",
|
||||
"pezsc-consensus-grandpa/runtime-benchmarks",
|
||||
"pezsp-authority-discovery/runtime-benchmarks",
|
||||
"pezsp-consensus-babe/runtime-benchmarks",
|
||||
"pezsp-consensus-beefy/runtime-benchmarks",
|
||||
"pezsp-keyring/runtime-benchmarks",
|
||||
"teyrchains-common/runtime-benchmarks",
|
||||
]
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Bizinikiwi
|
||||
use pezsc_consensus_grandpa::AuthorityId as GrandpaId;
|
||||
use pezsp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
|
||||
use pezsp_consensus_babe::AuthorityId as BabeId;
|
||||
use pezsp_consensus_beefy::ecdsa_crypto::AuthorityId as BeefyId;
|
||||
use pezsp_core::storage::Storage;
|
||||
use pezsp_keyring::Sr25519Keyring as Keyring;
|
||||
|
||||
// Pezkuwi
|
||||
use pezkuwi_primitives::{AssignmentId, ValidatorId};
|
||||
|
||||
// Pezcumulus
|
||||
use emulated_integration_tests_common::{
|
||||
accounts, build_genesis_storage, get_host_config, validators,
|
||||
};
|
||||
use pezkuwichain_runtime_constants::currency::UNITS as TYR;
|
||||
use teyrchains_common::Balance;
|
||||
|
||||
pub const ED: Balance = pezkuwichain_runtime_constants::currency::EXISTENTIAL_DEPOSIT;
|
||||
const ENDOWMENT: u128 = 1_000_000 * TYR;
|
||||
|
||||
fn session_keys(
|
||||
babe: BabeId,
|
||||
grandpa: GrandpaId,
|
||||
para_validator: ValidatorId,
|
||||
para_assignment: AssignmentId,
|
||||
authority_discovery: AuthorityDiscoveryId,
|
||||
beefy: BeefyId,
|
||||
) -> pezkuwichain_runtime::SessionKeys {
|
||||
pezkuwichain_runtime::SessionKeys {
|
||||
babe,
|
||||
grandpa,
|
||||
para_validator,
|
||||
para_assignment,
|
||||
authority_discovery,
|
||||
beefy,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn genesis() -> Storage {
|
||||
let genesis_config = pezkuwichain_runtime::RuntimeGenesisConfig {
|
||||
system: pezkuwichain_runtime::SystemConfig::default(),
|
||||
balances: pezkuwichain_runtime::BalancesConfig {
|
||||
balances: accounts::init_balances().iter().map(|k| (k.clone(), ENDOWMENT)).collect(),
|
||||
..Default::default()
|
||||
},
|
||||
session: pezkuwichain_runtime::SessionConfig {
|
||||
keys: validators::initial_authorities()
|
||||
.iter()
|
||||
.map(|x| {
|
||||
(
|
||||
x.0.clone(),
|
||||
x.0.clone(),
|
||||
session_keys(
|
||||
x.2.clone(),
|
||||
x.3.clone(),
|
||||
x.4.clone(),
|
||||
x.5.clone(),
|
||||
x.6.clone(),
|
||||
x.7.clone(),
|
||||
),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
..Default::default()
|
||||
},
|
||||
babe: pezkuwichain_runtime::BabeConfig {
|
||||
authorities: Default::default(),
|
||||
epoch_config: pezkuwichain_runtime::BABE_GENESIS_EPOCH_CONFIG,
|
||||
..Default::default()
|
||||
},
|
||||
sudo: pezkuwichain_runtime::SudoConfig { key: Some(Keyring::Alice.to_account_id()) },
|
||||
configuration: pezkuwichain_runtime::ConfigurationConfig { config: get_host_config() },
|
||||
registrar: pezkuwichain_runtime::RegistrarConfig {
|
||||
next_free_para_id: pezkuwi_primitives::LOWEST_PUBLIC_ID,
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
build_genesis_storage(&genesis_config, pezkuwichain_runtime::WASM_BINARY.unwrap())
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
pub use pezkuwichain_runtime;
|
||||
|
||||
pub mod genesis;
|
||||
|
||||
// Pezcumulus
|
||||
use emulated_integration_tests_common::{
|
||||
impl_accounts_helpers_for_relay_chain, impl_assert_events_helpers_for_relay_chain,
|
||||
impl_hrmp_channels_helpers_for_relay_chain, impl_send_transact_helpers_for_relay_chain,
|
||||
xcm_emulator::decl_test_relay_chains,
|
||||
};
|
||||
|
||||
// Pezkuwichain declaration
|
||||
decl_test_relay_chains! {
|
||||
#[api_version(15)]
|
||||
pub struct Pezkuwichain {
|
||||
genesis = genesis::genesis(),
|
||||
on_init = (),
|
||||
runtime = pezkuwichain_runtime,
|
||||
core = {
|
||||
SovereignAccountOf: pezkuwichain_runtime::xcm_config::LocationConverter,
|
||||
},
|
||||
pallets = {
|
||||
XcmPallet: pezkuwichain_runtime::XcmPallet,
|
||||
Sudo: pezkuwichain_runtime::Sudo,
|
||||
Balances: pezkuwichain_runtime::Balances,
|
||||
Hrmp: pezkuwichain_runtime::Hrmp,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// Pezkuwichain implementation
|
||||
impl_accounts_helpers_for_relay_chain!(Pezkuwichain);
|
||||
impl_assert_events_helpers_for_relay_chain!(Pezkuwichain);
|
||||
impl_hrmp_channels_helpers_for_relay_chain!(Pezkuwichain);
|
||||
impl_send_transact_helpers_for_relay_chain!(Pezkuwichain);
|
||||
@@ -0,0 +1,45 @@
|
||||
[package]
|
||||
name = "zagros-emulated-chain"
|
||||
version = "0.0.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license = "Apache-2.0"
|
||||
description = "Zagros emulated chain"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
# Bizinikiwi
|
||||
pezpallet-staking = { workspace = true }
|
||||
pezsc-consensus-grandpa = { workspace = true }
|
||||
pezsp-authority-discovery = { workspace = true }
|
||||
pezsp-consensus-babe = { workspace = true }
|
||||
pezsp-consensus-beefy = { workspace = true, default-features = true }
|
||||
pezsp-core = { workspace = true }
|
||||
pezsp-runtime = { workspace = true }
|
||||
|
||||
# Pezkuwi
|
||||
pezkuwi-primitives = { workspace = true }
|
||||
zagros-runtime = { workspace = true, default-features = true }
|
||||
zagros-runtime-constants = { workspace = true }
|
||||
|
||||
# Pezcumulus
|
||||
emulated-integration-tests-common = { workspace = true }
|
||||
teyrchains-common = { workspace = true, default-features = true }
|
||||
|
||||
[features]
|
||||
runtime-benchmarks = [
|
||||
"emulated-integration-tests-common/runtime-benchmarks",
|
||||
"pezpallet-staking/runtime-benchmarks",
|
||||
"pezkuwi-primitives/runtime-benchmarks",
|
||||
"pezsc-consensus-grandpa/runtime-benchmarks",
|
||||
"pezsp-authority-discovery/runtime-benchmarks",
|
||||
"pezsp-consensus-babe/runtime-benchmarks",
|
||||
"pezsp-consensus-beefy/runtime-benchmarks",
|
||||
"pezsp-runtime/runtime-benchmarks",
|
||||
"teyrchains-common/runtime-benchmarks",
|
||||
"zagros-runtime-constants/runtime-benchmarks",
|
||||
"zagros-runtime/runtime-benchmarks",
|
||||
]
|
||||
@@ -0,0 +1,91 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Bizinikiwi
|
||||
use pezsc_consensus_grandpa::AuthorityId as GrandpaId;
|
||||
use pezsp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
|
||||
use pezsp_consensus_babe::AuthorityId as BabeId;
|
||||
use pezsp_consensus_beefy::ecdsa_crypto::AuthorityId as BeefyId;
|
||||
use pezsp_core::storage::Storage;
|
||||
|
||||
// Pezkuwi
|
||||
use pezkuwi_primitives::{AssignmentId, ValidatorId};
|
||||
|
||||
// Pezcumulus
|
||||
use emulated_integration_tests_common::{
|
||||
accounts, build_genesis_storage, get_host_config, validators,
|
||||
};
|
||||
use teyrchains_common::Balance;
|
||||
use zagros_runtime_constants::currency::UNITS as ZGR;
|
||||
|
||||
pub const ED: Balance = zagros_runtime_constants::currency::EXISTENTIAL_DEPOSIT;
|
||||
const ENDOWMENT: u128 = 1_000_000 * ZGR;
|
||||
|
||||
fn session_keys(
|
||||
babe: BabeId,
|
||||
grandpa: GrandpaId,
|
||||
para_validator: ValidatorId,
|
||||
para_assignment: AssignmentId,
|
||||
authority_discovery: AuthorityDiscoveryId,
|
||||
beefy: BeefyId,
|
||||
) -> zagros_runtime::SessionKeys {
|
||||
zagros_runtime::SessionKeys {
|
||||
babe,
|
||||
grandpa,
|
||||
para_validator,
|
||||
para_assignment,
|
||||
authority_discovery,
|
||||
beefy,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn genesis() -> Storage {
|
||||
let genesis_config = zagros_runtime::RuntimeGenesisConfig {
|
||||
system: zagros_runtime::SystemConfig::default(),
|
||||
balances: zagros_runtime::BalancesConfig {
|
||||
balances: accounts::init_balances().iter().cloned().map(|k| (k, ENDOWMENT)).collect(),
|
||||
..Default::default()
|
||||
},
|
||||
session: zagros_runtime::SessionConfig {
|
||||
keys: validators::initial_authorities()
|
||||
.iter()
|
||||
.map(|x| {
|
||||
(
|
||||
x.0.clone(),
|
||||
x.0.clone(),
|
||||
session_keys(
|
||||
x.2.clone(),
|
||||
x.3.clone(),
|
||||
x.4.clone(),
|
||||
x.5.clone(),
|
||||
x.6.clone(),
|
||||
x.7.clone(),
|
||||
),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
..Default::default()
|
||||
},
|
||||
babe: zagros_runtime::BabeConfig {
|
||||
authorities: Default::default(),
|
||||
epoch_config: zagros_runtime::BABE_GENESIS_EPOCH_CONFIG,
|
||||
..Default::default()
|
||||
},
|
||||
configuration: zagros_runtime::ConfigurationConfig { config: get_host_config() },
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
build_genesis_storage(&genesis_config, zagros_runtime::WASM_BINARY.unwrap())
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
pub use zagros_runtime;
|
||||
|
||||
pub mod genesis;
|
||||
|
||||
// Pezcumulus
|
||||
use emulated_integration_tests_common::{
|
||||
impl_accounts_helpers_for_relay_chain, impl_assert_events_helpers_for_relay_chain,
|
||||
impl_hrmp_channels_helpers_for_relay_chain, impl_send_transact_helpers_for_relay_chain,
|
||||
xcm_emulator::decl_test_relay_chains,
|
||||
};
|
||||
|
||||
// Zagros declaration
|
||||
decl_test_relay_chains! {
|
||||
#[api_version(15)]
|
||||
pub struct Zagros {
|
||||
genesis = genesis::genesis(),
|
||||
on_init = (),
|
||||
runtime = zagros_runtime,
|
||||
core = {
|
||||
SovereignAccountOf: zagros_runtime::xcm_config::LocationConverter,
|
||||
},
|
||||
pallets = {
|
||||
XcmPallet: zagros_runtime::XcmPallet,
|
||||
Sudo: zagros_runtime::Sudo,
|
||||
Balances: zagros_runtime::Balances,
|
||||
Treasury: zagros_runtime::Treasury,
|
||||
AssetRate: zagros_runtime::AssetRate,
|
||||
Hrmp: zagros_runtime::Hrmp,
|
||||
Identity: zagros_runtime::Identity,
|
||||
IdentityMigrator: zagros_runtime::IdentityMigrator,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// Zagros implementation
|
||||
impl_accounts_helpers_for_relay_chain!(Zagros);
|
||||
impl_assert_events_helpers_for_relay_chain!(Zagros);
|
||||
impl_hrmp_channels_helpers_for_relay_chain!(Zagros);
|
||||
impl_send_transact_helpers_for_relay_chain!(Zagros);
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
[package]
|
||||
name = "asset-hub-pezkuwichain-emulated-chain"
|
||||
version = "0.0.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license = "Apache-2.0"
|
||||
description = "Asset Hub Pezkuwichain emulated chain"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
# Bizinikiwi
|
||||
pezframe-support = { workspace = true }
|
||||
pezsp-core = { workspace = true }
|
||||
pezsp-keyring = { workspace = true }
|
||||
|
||||
# Pezcumulus
|
||||
asset-hub-pezkuwichain-runtime = { workspace = true, default-features = true }
|
||||
pezcumulus-primitives-core = { workspace = true }
|
||||
emulated-integration-tests-common = { workspace = true }
|
||||
pezkuwichain-emulated-chain = { workspace = true }
|
||||
testnet-teyrchains-constants = { features = [
|
||||
"pezkuwichain",
|
||||
], workspace = true, default-features = true }
|
||||
teyrchains-common = { workspace = true, default-features = true }
|
||||
|
||||
# Pezkuwi
|
||||
xcm = { workspace = true }
|
||||
xcm-builder = { workspace = true, default-features = true }
|
||||
|
||||
# Bridges
|
||||
bp-bridge-hub-pezkuwichain = { workspace = true }
|
||||
|
||||
[features]
|
||||
runtime-benchmarks = [
|
||||
"asset-hub-pezkuwichain-runtime/runtime-benchmarks",
|
||||
"bp-bridge-hub-pezkuwichain/runtime-benchmarks",
|
||||
"pezcumulus-primitives-core/runtime-benchmarks",
|
||||
"emulated-integration-tests-common/runtime-benchmarks",
|
||||
"pezframe-support/runtime-benchmarks",
|
||||
"pezkuwichain-emulated-chain/runtime-benchmarks",
|
||||
"pezsp-keyring/runtime-benchmarks",
|
||||
"testnet-teyrchains-constants/runtime-benchmarks",
|
||||
"teyrchains-common/runtime-benchmarks",
|
||||
"xcm-builder/runtime-benchmarks",
|
||||
"xcm/runtime-benchmarks",
|
||||
]
|
||||
+170
@@ -0,0 +1,170 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Bizinikiwi
|
||||
use pezframe_support::parameter_types;
|
||||
use pezsp_core::storage::Storage;
|
||||
use pezsp_keyring::Sr25519Keyring as Keyring;
|
||||
|
||||
// Pezcumulus
|
||||
use emulated_integration_tests_common::{
|
||||
accounts, build_genesis_storage, collators,
|
||||
snowbridge::{ETHER_MIN_BALANCE, WETH},
|
||||
xcm_emulator::ConvertLocation,
|
||||
PenpalALocation, PenpalASiblingSovereignAccount, PenpalATeleportableAssetLocation,
|
||||
PenpalBLocation, PenpalBSiblingSovereignAccount, PenpalBTeleportableAssetLocation,
|
||||
RESERVABLE_ASSET_ID, SAFE_XCM_VERSION, USDT_ID,
|
||||
};
|
||||
use testnet_teyrchains_constants::pezkuwichain::snowbridge::EthereumNetwork;
|
||||
use teyrchains_common::{AccountId, Balance};
|
||||
use xcm::{
|
||||
latest::prelude::*,
|
||||
opaque::latest::{PEZKUWICHAIN_GENESIS_HASH, ZAGROS_GENESIS_HASH},
|
||||
};
|
||||
use xcm_builder::ExternalConsensusLocationsConverterFor;
|
||||
|
||||
pub const PARA_ID: u32 = 1000;
|
||||
pub const ED: Balance = testnet_teyrchains_constants::pezkuwichain::currency::EXISTENTIAL_DEPOSIT;
|
||||
|
||||
parameter_types! {
|
||||
pub AssetHubPezkuwichainAssetOwner: AccountId = Keyring::Alice.to_account_id();
|
||||
pub PezkuwichainGlobalConsensusNetwork: NetworkId = NetworkId::ByGenesis(PEZKUWICHAIN_GENESIS_HASH);
|
||||
pub AssetHubPezkuwichainUniversalLocation: InteriorLocation = [GlobalConsensus(PezkuwichainGlobalConsensusNetwork::get()), Teyrchain(PARA_ID)].into();
|
||||
pub AssetHubZagrosLocation: Location = Location::new(
|
||||
2,
|
||||
[GlobalConsensus( NetworkId::ByGenesis(ZAGROS_GENESIS_HASH)), Teyrchain(PARA_ID)],
|
||||
);
|
||||
pub AssetHubZagrosSovereignAccount: AccountId = ExternalConsensusLocationsConverterFor::<
|
||||
AssetHubPezkuwichainUniversalLocation,
|
||||
AccountId,
|
||||
>::convert_location(&AssetHubZagrosLocation::get()).unwrap();
|
||||
pub EthereumLocation: Location = Location::new(2, [GlobalConsensus(EthereumNetwork::get())]);
|
||||
}
|
||||
|
||||
pub fn genesis() -> Storage {
|
||||
let genesis_config = asset_hub_pezkuwichain_runtime::RuntimeGenesisConfig {
|
||||
system: asset_hub_pezkuwichain_runtime::SystemConfig::default(),
|
||||
balances: asset_hub_pezkuwichain_runtime::BalancesConfig {
|
||||
balances: accounts::init_balances()
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|k| (k, ED * 4096 * 4096))
|
||||
.collect(),
|
||||
..Default::default()
|
||||
},
|
||||
teyrchain_info: asset_hub_pezkuwichain_runtime::TeyrchainInfoConfig {
|
||||
teyrchain_id: PARA_ID.into(),
|
||||
..Default::default()
|
||||
},
|
||||
collator_selection: asset_hub_pezkuwichain_runtime::CollatorSelectionConfig {
|
||||
invulnerables: collators::invulnerables().iter().cloned().map(|(acc, _)| acc).collect(),
|
||||
candidacy_bond: ED * 16,
|
||||
..Default::default()
|
||||
},
|
||||
session: asset_hub_pezkuwichain_runtime::SessionConfig {
|
||||
keys: collators::invulnerables()
|
||||
.into_iter()
|
||||
.map(|(acc, aura)| {
|
||||
(
|
||||
acc.clone(), // account id
|
||||
acc, // validator id
|
||||
asset_hub_pezkuwichain_runtime::SessionKeys { aura }, // session keys
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
..Default::default()
|
||||
},
|
||||
pezkuwi_xcm: asset_hub_pezkuwichain_runtime::PezkuwiXcmConfig {
|
||||
safe_xcm_version: Some(SAFE_XCM_VERSION),
|
||||
..Default::default()
|
||||
},
|
||||
assets: asset_hub_pezkuwichain_runtime::AssetsConfig {
|
||||
assets: vec![
|
||||
(RESERVABLE_ASSET_ID, AssetHubPezkuwichainAssetOwner::get(), false, ED),
|
||||
(USDT_ID, AssetHubPezkuwichainAssetOwner::get(), true, ED),
|
||||
],
|
||||
..Default::default()
|
||||
},
|
||||
foreign_assets: asset_hub_pezkuwichain_runtime::ForeignAssetsConfig {
|
||||
assets: vec![
|
||||
// PenpalA's teleportable asset representation
|
||||
(
|
||||
PenpalATeleportableAssetLocation::get(),
|
||||
PenpalASiblingSovereignAccount::get(),
|
||||
false,
|
||||
ED,
|
||||
),
|
||||
// PenpalB's teleportable asset representation
|
||||
(
|
||||
PenpalBTeleportableAssetLocation::get(),
|
||||
PenpalBSiblingSovereignAccount::get(),
|
||||
false,
|
||||
ED,
|
||||
),
|
||||
// Ether
|
||||
(
|
||||
EthereumLocation::get(),
|
||||
AssetHubZagrosSovereignAccount::get(), /* To emulate double bridging, where
|
||||
* WAH is the owner of assets from
|
||||
* Ethereum on RAH */
|
||||
true,
|
||||
ETHER_MIN_BALANCE,
|
||||
),
|
||||
// Weth
|
||||
(
|
||||
Location::new(
|
||||
2,
|
||||
[
|
||||
GlobalConsensus(EthereumNetwork::get()),
|
||||
AccountKey20 { network: None, key: WETH.into() },
|
||||
],
|
||||
),
|
||||
AssetHubZagrosSovereignAccount::get(),
|
||||
true,
|
||||
ETHER_MIN_BALANCE,
|
||||
),
|
||||
],
|
||||
reserves: vec![
|
||||
(
|
||||
PenpalATeleportableAssetLocation::get(),
|
||||
vec![(PenpalALocation::get(), true).into()],
|
||||
),
|
||||
(
|
||||
PenpalBTeleportableAssetLocation::get(),
|
||||
vec![(PenpalBLocation::get(), true).into()],
|
||||
),
|
||||
(EthereumLocation::get(), vec![(AssetHubZagrosLocation::get(), false).into()]),
|
||||
(
|
||||
Location::new(
|
||||
2,
|
||||
[
|
||||
GlobalConsensus(EthereumNetwork::get()),
|
||||
AccountKey20 { network: None, key: WETH.into() },
|
||||
],
|
||||
),
|
||||
vec![(AssetHubZagrosLocation::get(), false).into()],
|
||||
),
|
||||
],
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
build_genesis_storage(
|
||||
&genesis_config,
|
||||
asset_hub_pezkuwichain_runtime::WASM_BINARY
|
||||
.expect("WASM binary was not built, please build it!"),
|
||||
)
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
pub use asset_hub_pezkuwichain_runtime;
|
||||
|
||||
pub mod genesis;
|
||||
|
||||
// Bizinikiwi
|
||||
use pezframe_support::traits::OnInitialize;
|
||||
|
||||
// Pezcumulus
|
||||
use asset_hub_pezkuwichain_runtime::ForeignAssetReserveData;
|
||||
use emulated_integration_tests_common::{
|
||||
impl_accounts_helpers_for_teyrchain, impl_assert_events_helpers_for_teyrchain,
|
||||
impl_assets_helpers_for_system_teyrchain, impl_assets_helpers_for_teyrchain,
|
||||
impl_bridge_helpers_for_chain, impl_foreign_assets_helpers_for_teyrchain,
|
||||
impl_xcm_helpers_for_teyrchain, impls::Teyrchain, xcm_emulator::decl_test_teyrchains,
|
||||
AuraDigestProvider,
|
||||
};
|
||||
use pezkuwichain_emulated_chain::Pezkuwichain;
|
||||
|
||||
// AssetHubPezkuwichain Teyrchain declaration
|
||||
decl_test_teyrchains! {
|
||||
pub struct AssetHubPezkuwichain {
|
||||
genesis = genesis::genesis(),
|
||||
on_init = {
|
||||
asset_hub_pezkuwichain_runtime::AuraExt::on_initialize(1);
|
||||
},
|
||||
runtime = asset_hub_pezkuwichain_runtime,
|
||||
core = {
|
||||
XcmpMessageHandler: asset_hub_pezkuwichain_runtime::XcmpQueue,
|
||||
LocationToAccountId: asset_hub_pezkuwichain_runtime::xcm_config::LocationToAccountId,
|
||||
TeyrchainInfo: asset_hub_pezkuwichain_runtime::TeyrchainInfo,
|
||||
MessageOrigin: cumulus_primitives_core::AggregateMessageOrigin,
|
||||
DigestProvider: AuraDigestProvider,
|
||||
AdditionalInherentCode: (),
|
||||
},
|
||||
pallets = {
|
||||
PezkuwiXcm: asset_hub_pezkuwichain_runtime::PezkuwiXcm,
|
||||
Assets: asset_hub_pezkuwichain_runtime::Assets,
|
||||
ForeignAssets: asset_hub_pezkuwichain_runtime::ForeignAssets,
|
||||
PoolAssets: asset_hub_pezkuwichain_runtime::PoolAssets,
|
||||
AssetConversion: asset_hub_pezkuwichain_runtime::AssetConversion,
|
||||
Balances: asset_hub_pezkuwichain_runtime::Balances,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// AssetHubPezkuwichain implementation
|
||||
impl_accounts_helpers_for_teyrchain!(AssetHubPezkuwichain);
|
||||
impl_assert_events_helpers_for_teyrchain!(AssetHubPezkuwichain);
|
||||
impl_assets_helpers_for_system_teyrchain!(AssetHubPezkuwichain, Pezkuwichain);
|
||||
impl_assets_helpers_for_teyrchain!(AssetHubPezkuwichain);
|
||||
impl_foreign_assets_helpers_for_teyrchain!(
|
||||
AssetHubPezkuwichain,
|
||||
xcm::v5::Location,
|
||||
ForeignAssetReserveData
|
||||
);
|
||||
impl_xcm_helpers_for_teyrchain!(AssetHubPezkuwichain);
|
||||
impl_bridge_helpers_for_chain!(
|
||||
AssetHubPezkuwichain,
|
||||
ParaPallet,
|
||||
PezkuwiXcm,
|
||||
bp_bridge_hub_pezkuwichain::RuntimeCall::XcmOverBridgeHubZagros
|
||||
);
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
[package]
|
||||
name = "asset-hub-zagros-emulated-chain"
|
||||
version = "0.0.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license = "Apache-2.0"
|
||||
description = "Asset Hub Zagros emulated chain"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
# Bizinikiwi
|
||||
pezframe-support = { workspace = true }
|
||||
pezsp-core = { workspace = true }
|
||||
pezsp-keyring = { workspace = true }
|
||||
|
||||
# Pezcumulus
|
||||
asset-hub-zagros-runtime = { workspace = true, default-features = true }
|
||||
pezcumulus-primitives-core = { workspace = true }
|
||||
emulated-integration-tests-common = { workspace = true }
|
||||
testnet-teyrchains-constants = { features = [
|
||||
"zagros",
|
||||
], workspace = true, default-features = true }
|
||||
teyrchains-common = { workspace = true, default-features = true }
|
||||
zagros-emulated-chain = { workspace = true, default-features = true }
|
||||
|
||||
# Pezkuwi
|
||||
xcm = { workspace = true }
|
||||
xcm-builder = { workspace = true, default-features = true }
|
||||
|
||||
# Bridges
|
||||
bp-bridge-hub-zagros = { workspace = true }
|
||||
|
||||
[features]
|
||||
runtime-benchmarks = [
|
||||
"asset-hub-zagros-runtime/runtime-benchmarks",
|
||||
"bp-bridge-hub-zagros/runtime-benchmarks",
|
||||
"pezcumulus-primitives-core/runtime-benchmarks",
|
||||
"emulated-integration-tests-common/runtime-benchmarks",
|
||||
"pezframe-support/runtime-benchmarks",
|
||||
"pezsp-keyring/runtime-benchmarks",
|
||||
"testnet-teyrchains-constants/runtime-benchmarks",
|
||||
"teyrchains-common/runtime-benchmarks",
|
||||
"xcm-builder/runtime-benchmarks",
|
||||
"xcm/runtime-benchmarks",
|
||||
"zagros-emulated-chain/runtime-benchmarks",
|
||||
]
|
||||
+167
@@ -0,0 +1,167 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Bizinikiwi
|
||||
use pezframe_support::parameter_types;
|
||||
use pezsp_core::storage::Storage;
|
||||
use pezsp_keyring::Sr25519Keyring as Keyring;
|
||||
|
||||
// Pezcumulus
|
||||
use emulated_integration_tests_common::{
|
||||
accounts, build_genesis_storage, collators,
|
||||
snowbridge::{ETHER_MIN_BALANCE, WETH},
|
||||
xcm_emulator::ConvertLocation,
|
||||
PenpalALocation, PenpalASiblingSovereignAccount, PenpalATeleportableAssetLocation,
|
||||
PenpalBLocation, PenpalBSiblingSovereignAccount, PenpalBTeleportableAssetLocation,
|
||||
RESERVABLE_ASSET_ID, SAFE_XCM_VERSION, USDT_ID,
|
||||
};
|
||||
use testnet_teyrchains_constants::zagros::snowbridge::EthereumNetwork;
|
||||
use teyrchains_common::{AccountId, Balance};
|
||||
use xcm::{latest::prelude::*, opaque::latest::ZAGROS_GENESIS_HASH};
|
||||
use xcm_builder::ExternalConsensusLocationsConverterFor;
|
||||
|
||||
pub const PARA_ID: u32 = 1000;
|
||||
pub const ED: Balance = testnet_teyrchains_constants::zagros::currency::EXISTENTIAL_DEPOSIT;
|
||||
pub const USDT_ED: Balance = 70_000;
|
||||
|
||||
parameter_types! {
|
||||
pub AssetHubZagrosAssetOwner: AccountId = Keyring::Alice.to_account_id();
|
||||
pub ZagrosGlobalConsensusNetwork: NetworkId = NetworkId::ByGenesis(ZAGROS_GENESIS_HASH);
|
||||
pub AssetHubZagrosUniversalLocation: InteriorLocation = [GlobalConsensus(ZagrosGlobalConsensusNetwork::get()), Teyrchain(PARA_ID)].into();
|
||||
pub EthereumLocation: Location = Location::new(2, [GlobalConsensus(EthereumNetwork::get())]);
|
||||
pub EthereumSovereignAccount: AccountId = ExternalConsensusLocationsConverterFor::<
|
||||
AssetHubZagrosUniversalLocation,
|
||||
AccountId,
|
||||
>::convert_location(&EthereumLocation::get()).unwrap();
|
||||
}
|
||||
|
||||
pub fn genesis() -> Storage {
|
||||
let genesis_config = asset_hub_zagros_runtime::RuntimeGenesisConfig {
|
||||
system: asset_hub_zagros_runtime::SystemConfig::default(),
|
||||
balances: asset_hub_zagros_runtime::BalancesConfig {
|
||||
balances: accounts::init_balances()
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|k| (k, ED * 4096))
|
||||
// pre-fund checking account to avoid pre-funding for every test scenario
|
||||
// teleporting funds to asset hub
|
||||
.chain(std::iter::once((
|
||||
asset_hub_zagros_runtime::xcm_config::CheckingAccount::get(),
|
||||
ED * 1000,
|
||||
)))
|
||||
.collect(),
|
||||
..Default::default()
|
||||
},
|
||||
teyrchain_info: asset_hub_zagros_runtime::TeyrchainInfoConfig {
|
||||
teyrchain_id: PARA_ID.into(),
|
||||
..Default::default()
|
||||
},
|
||||
collator_selection: asset_hub_zagros_runtime::CollatorSelectionConfig {
|
||||
invulnerables: collators::invulnerables().iter().cloned().map(|(acc, _)| acc).collect(),
|
||||
candidacy_bond: ED * 16,
|
||||
..Default::default()
|
||||
},
|
||||
session: asset_hub_zagros_runtime::SessionConfig {
|
||||
keys: collators::invulnerables()
|
||||
.into_iter()
|
||||
.map(|(acc, aura)| {
|
||||
(
|
||||
acc.clone(), // account id
|
||||
acc, // validator id
|
||||
asset_hub_zagros_runtime::SessionKeys { aura }, // session keys
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
..Default::default()
|
||||
},
|
||||
pezkuwi_xcm: asset_hub_zagros_runtime::PezkuwiXcmConfig {
|
||||
safe_xcm_version: Some(SAFE_XCM_VERSION),
|
||||
..Default::default()
|
||||
},
|
||||
assets: asset_hub_zagros_runtime::AssetsConfig {
|
||||
assets: vec![
|
||||
(RESERVABLE_ASSET_ID, AssetHubZagrosAssetOwner::get(), false, ED),
|
||||
(USDT_ID, AssetHubZagrosAssetOwner::get(), true, USDT_ED),
|
||||
],
|
||||
..Default::default()
|
||||
},
|
||||
foreign_assets: asset_hub_zagros_runtime::ForeignAssetsConfig {
|
||||
assets: vec![
|
||||
// PenpalA's teleportable asset representation
|
||||
(
|
||||
PenpalATeleportableAssetLocation::get(),
|
||||
PenpalASiblingSovereignAccount::get(),
|
||||
false,
|
||||
ED,
|
||||
),
|
||||
// PenpalB's teleportable asset representation
|
||||
(
|
||||
PenpalBTeleportableAssetLocation::get(),
|
||||
PenpalBSiblingSovereignAccount::get(),
|
||||
false,
|
||||
ED,
|
||||
),
|
||||
// Ether
|
||||
(
|
||||
Location::new(2, [GlobalConsensus(EthereumNetwork::get())]),
|
||||
EthereumSovereignAccount::get(),
|
||||
true,
|
||||
ETHER_MIN_BALANCE,
|
||||
),
|
||||
// Weth
|
||||
(
|
||||
Location::new(
|
||||
2,
|
||||
[
|
||||
GlobalConsensus(EthereumNetwork::get()),
|
||||
AccountKey20 { network: None, key: WETH.into() },
|
||||
],
|
||||
),
|
||||
EthereumSovereignAccount::get(),
|
||||
true,
|
||||
ETHER_MIN_BALANCE,
|
||||
),
|
||||
],
|
||||
reserves: vec![
|
||||
(
|
||||
PenpalATeleportableAssetLocation::get(),
|
||||
vec![(PenpalALocation::get(), true).into()],
|
||||
),
|
||||
(
|
||||
PenpalBTeleportableAssetLocation::get(),
|
||||
vec![(PenpalBLocation::get(), true).into()],
|
||||
),
|
||||
(EthereumLocation::get(), vec![(EthereumLocation::get(), false).into()]),
|
||||
(
|
||||
Location::new(
|
||||
2,
|
||||
[
|
||||
GlobalConsensus(EthereumNetwork::get()),
|
||||
AccountKey20 { network: None, key: WETH.into() },
|
||||
],
|
||||
),
|
||||
vec![(EthereumLocation::get(), false).into()],
|
||||
),
|
||||
],
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
build_genesis_storage(
|
||||
&genesis_config,
|
||||
asset_hub_zagros_runtime::WASM_BINARY.expect("WASM binary was not built, please build it!"),
|
||||
)
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
pub use asset_hub_zagros_runtime;
|
||||
|
||||
pub mod genesis;
|
||||
|
||||
// Bizinikiwi
|
||||
use pezframe_support::traits::OnInitialize;
|
||||
|
||||
// Pezcumulus
|
||||
use asset_hub_zagros_runtime::ForeignAssetReserveData;
|
||||
use emulated_integration_tests_common::{
|
||||
impl_accounts_helpers_for_teyrchain, impl_assert_events_helpers_for_teyrchain,
|
||||
impl_assets_helpers_for_system_teyrchain, impl_assets_helpers_for_teyrchain,
|
||||
impl_bridge_helpers_for_chain, impl_foreign_assets_helpers_for_teyrchain,
|
||||
impl_xcm_helpers_for_teyrchain, impls::Teyrchain, xcm_emulator::decl_test_teyrchains,
|
||||
AuraDigestProvider,
|
||||
};
|
||||
use zagros_emulated_chain::Zagros;
|
||||
|
||||
// AssetHubZagros Teyrchain declaration
|
||||
decl_test_teyrchains! {
|
||||
pub struct AssetHubZagros {
|
||||
genesis = genesis::genesis(),
|
||||
on_init = {
|
||||
asset_hub_zagros_runtime::AuraExt::on_initialize(1);
|
||||
},
|
||||
runtime = asset_hub_zagros_runtime,
|
||||
core = {
|
||||
XcmpMessageHandler: asset_hub_zagros_runtime::XcmpQueue,
|
||||
LocationToAccountId: asset_hub_zagros_runtime::xcm_config::LocationToAccountId,
|
||||
TeyrchainInfo: asset_hub_zagros_runtime::TeyrchainInfo,
|
||||
MessageOrigin: cumulus_primitives_core::AggregateMessageOrigin,
|
||||
DigestProvider: AuraDigestProvider,
|
||||
AdditionalInherentCode: (),
|
||||
},
|
||||
pallets = {
|
||||
PezkuwiXcm: asset_hub_zagros_runtime::PezkuwiXcm,
|
||||
Balances: asset_hub_zagros_runtime::Balances,
|
||||
Assets: asset_hub_zagros_runtime::Assets,
|
||||
ForeignAssets: asset_hub_zagros_runtime::ForeignAssets,
|
||||
PoolAssets: asset_hub_zagros_runtime::PoolAssets,
|
||||
AssetConversion: asset_hub_zagros_runtime::AssetConversion,
|
||||
SnowbridgeSystemFrontend: asset_hub_zagros_runtime::SnowbridgeSystemFrontend,
|
||||
Revive: asset_hub_zagros_runtime::Revive,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// AssetHubZagros implementation
|
||||
impl_accounts_helpers_for_teyrchain!(AssetHubZagros);
|
||||
impl_assert_events_helpers_for_teyrchain!(AssetHubZagros);
|
||||
impl_assets_helpers_for_system_teyrchain!(AssetHubZagros, Zagros);
|
||||
impl_assets_helpers_for_teyrchain!(AssetHubZagros);
|
||||
impl_foreign_assets_helpers_for_teyrchain!(
|
||||
AssetHubZagros,
|
||||
xcm::v5::Location,
|
||||
ForeignAssetReserveData
|
||||
);
|
||||
impl_xcm_helpers_for_teyrchain!(AssetHubZagros);
|
||||
impl_bridge_helpers_for_chain!(
|
||||
AssetHubZagros,
|
||||
ParaPallet,
|
||||
PezkuwiXcm,
|
||||
bp_bridge_hub_zagros::RuntimeCall::XcmOverBridgeHubPezkuwichain
|
||||
);
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
[package]
|
||||
name = "bridge-hub-pezkuwichain-emulated-chain"
|
||||
version = "0.0.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license = "Apache-2.0"
|
||||
description = "Bridge Hub Pezkuwichain emulated chain"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
# Bizinikiwi
|
||||
pezframe-support = { workspace = true }
|
||||
pezsp-core = { workspace = true }
|
||||
pezsp-keyring = { workspace = true }
|
||||
|
||||
# Pezkuwi Dependencies
|
||||
xcm = { workspace = true }
|
||||
|
||||
# Bridge dependencies
|
||||
bp-messages = { workspace = true }
|
||||
|
||||
# Pezcumulus
|
||||
bridge-hub-common = { workspace = true }
|
||||
bridge-hub-pezkuwichain-runtime = { workspace = true, default-features = true }
|
||||
emulated-integration-tests-common = { workspace = true }
|
||||
testnet-teyrchains-constants = { features = [
|
||||
"pezkuwichain",
|
||||
], workspace = true, default-features = true }
|
||||
teyrchains-common = { workspace = true, default-features = true }
|
||||
|
||||
[features]
|
||||
runtime-benchmarks = [
|
||||
"bp-messages/runtime-benchmarks",
|
||||
"bridge-hub-common/runtime-benchmarks",
|
||||
"bridge-hub-pezkuwichain-runtime/runtime-benchmarks",
|
||||
"emulated-integration-tests-common/runtime-benchmarks",
|
||||
"pezframe-support/runtime-benchmarks",
|
||||
"pezsp-keyring/runtime-benchmarks",
|
||||
"testnet-teyrchains-constants/runtime-benchmarks",
|
||||
"teyrchains-common/runtime-benchmarks",
|
||||
"xcm/runtime-benchmarks",
|
||||
]
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Bizinikiwi
|
||||
use pezsp_core::storage::Storage;
|
||||
use pezsp_keyring::Sr25519Keyring as Keyring;
|
||||
|
||||
// Pezcumulus
|
||||
use emulated_integration_tests_common::{
|
||||
accounts, build_genesis_storage, collators, SAFE_XCM_VERSION,
|
||||
};
|
||||
use teyrchains_common::Balance;
|
||||
use xcm::latest::{prelude::*, ZAGROS_GENESIS_HASH};
|
||||
|
||||
pub const ASSETHUB_PARA_ID: u32 = 1000;
|
||||
pub const PARA_ID: u32 = 1002;
|
||||
pub const ED: Balance = testnet_teyrchains_constants::pezkuwichain::currency::EXISTENTIAL_DEPOSIT;
|
||||
|
||||
pub fn genesis() -> Storage {
|
||||
let genesis_config = bridge_hub_pezkuwichain_runtime::RuntimeGenesisConfig {
|
||||
system: bridge_hub_pezkuwichain_runtime::SystemConfig::default(),
|
||||
balances: bridge_hub_pezkuwichain_runtime::BalancesConfig {
|
||||
balances: accounts::init_balances().iter().cloned().map(|k| (k, ED * 4096)).collect(),
|
||||
..Default::default()
|
||||
},
|
||||
teyrchain_info: bridge_hub_pezkuwichain_runtime::TeyrchainInfoConfig {
|
||||
teyrchain_id: PARA_ID.into(),
|
||||
..Default::default()
|
||||
},
|
||||
collator_selection: bridge_hub_pezkuwichain_runtime::CollatorSelectionConfig {
|
||||
invulnerables: collators::invulnerables().iter().cloned().map(|(acc, _)| acc).collect(),
|
||||
candidacy_bond: ED * 16,
|
||||
..Default::default()
|
||||
},
|
||||
session: bridge_hub_pezkuwichain_runtime::SessionConfig {
|
||||
keys: collators::invulnerables()
|
||||
.into_iter()
|
||||
.map(|(acc, aura)| {
|
||||
(
|
||||
acc.clone(), // account id
|
||||
acc, // validator id
|
||||
bridge_hub_pezkuwichain_runtime::SessionKeys { aura }, // session keys
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
..Default::default()
|
||||
},
|
||||
pezkuwi_xcm: bridge_hub_pezkuwichain_runtime::PezkuwiXcmConfig {
|
||||
safe_xcm_version: Some(SAFE_XCM_VERSION),
|
||||
..Default::default()
|
||||
},
|
||||
bridge_zagros_grandpa: bridge_hub_pezkuwichain_runtime::BridgeZagrosGrandpaConfig {
|
||||
owner: Some(Keyring::Bob.to_account_id()),
|
||||
..Default::default()
|
||||
},
|
||||
bridge_zagros_messages: bridge_hub_pezkuwichain_runtime::BridgeZagrosMessagesConfig {
|
||||
owner: Some(Keyring::Bob.to_account_id()),
|
||||
..Default::default()
|
||||
},
|
||||
xcm_over_bridge_hub_zagros: bridge_hub_pezkuwichain_runtime::XcmOverBridgeHubZagrosConfig {
|
||||
opened_bridges: vec![
|
||||
// open AHR -> AHW bridge
|
||||
(
|
||||
Location::new(1, [Teyrchain(1000)]),
|
||||
Junctions::from([ByGenesis(ZAGROS_GENESIS_HASH).into(), Teyrchain(1000)]),
|
||||
Some(bp_messages::LegacyLaneId([0, 0, 0, 2])),
|
||||
),
|
||||
],
|
||||
..Default::default()
|
||||
},
|
||||
ethereum_system: bridge_hub_pezkuwichain_runtime::EthereumSystemConfig {
|
||||
para_id: PARA_ID.into(),
|
||||
asset_hub_para_id: ASSETHUB_PARA_ID.into(),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
build_genesis_storage(
|
||||
&genesis_config,
|
||||
bridge_hub_pezkuwichain_runtime::WASM_BINARY
|
||||
.expect("WASM binary was not built, please build it!"),
|
||||
)
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
pub mod genesis;
|
||||
|
||||
pub use bridge_hub_pezkuwichain_runtime::{
|
||||
self as bridge_hub_pezkuwichain_runtime,
|
||||
xcm_config::XcmConfig as BridgeHubPezkuwichainXcmConfig, EthereumBeaconClient,
|
||||
EthereumInboundQueue, ExistentialDeposit as BridgeHubPezkuwichainExistentialDeposit,
|
||||
RuntimeOrigin as BridgeHubPezkuwichainRuntimeOrigin,
|
||||
};
|
||||
|
||||
// Bizinikiwi
|
||||
use pezframe_support::traits::OnInitialize;
|
||||
|
||||
// Pezcumulus
|
||||
use emulated_integration_tests_common::{
|
||||
impl_accounts_helpers_for_teyrchain, impl_assert_events_helpers_for_teyrchain,
|
||||
impl_xcm_helpers_for_teyrchain, impls::Teyrchain, xcm_emulator::decl_test_teyrchains,
|
||||
AuraDigestProvider,
|
||||
};
|
||||
|
||||
// BridgeHubPezkuwichain Teyrchain declaration
|
||||
decl_test_teyrchains! {
|
||||
pub struct BridgeHubPezkuwichain {
|
||||
genesis = genesis::genesis(),
|
||||
on_init = {
|
||||
bridge_hub_pezkuwichain_runtime::AuraExt::on_initialize(1);
|
||||
},
|
||||
runtime = bridge_hub_pezkuwichain_runtime,
|
||||
core = {
|
||||
XcmpMessageHandler: bridge_hub_pezkuwichain_runtime::XcmpQueue,
|
||||
LocationToAccountId: bridge_hub_pezkuwichain_runtime::xcm_config::LocationToAccountId,
|
||||
TeyrchainInfo: bridge_hub_pezkuwichain_runtime::TeyrchainInfo,
|
||||
MessageOrigin: bridge_hub_common::AggregateMessageOrigin,
|
||||
DigestProvider: AuraDigestProvider,
|
||||
},
|
||||
pallets = {
|
||||
PezkuwiXcm: bridge_hub_pezkuwichain_runtime::PezkuwiXcm,
|
||||
Balances: bridge_hub_pezkuwichain_runtime::Balances,
|
||||
EthereumSystem: bridge_hub_pezkuwichain_runtime::EthereumSystem,
|
||||
EthereumInboundQueue: bridge_hub_pezkuwichain_runtime::EthereumInboundQueue,
|
||||
EthereumOutboundQueue: bridge_hub_pezkuwichain_runtime::EthereumOutboundQueue,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// BridgeHubPezkuwichain implementation
|
||||
impl_accounts_helpers_for_teyrchain!(BridgeHubPezkuwichain);
|
||||
impl_assert_events_helpers_for_teyrchain!(BridgeHubPezkuwichain);
|
||||
impl_xcm_helpers_for_teyrchain!(BridgeHubPezkuwichain);
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
[package]
|
||||
name = "bridge-hub-zagros-emulated-chain"
|
||||
version = "0.0.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license = "Apache-2.0"
|
||||
description = "Bridge Hub Zagros emulated chain"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
# Bizinikiwi
|
||||
pezframe-support = { workspace = true }
|
||||
pezsp-core = { workspace = true }
|
||||
pezsp-keyring = { workspace = true }
|
||||
|
||||
# Pezkuwi Dependencies
|
||||
xcm = { workspace = true }
|
||||
|
||||
# Bridge dependencies
|
||||
bp-messages = { workspace = true }
|
||||
|
||||
# Pezcumulus
|
||||
bridge-hub-common = { workspace = true }
|
||||
bridge-hub-zagros-runtime = { workspace = true, default-features = true }
|
||||
emulated-integration-tests-common = { workspace = true }
|
||||
testnet-teyrchains-constants = { features = [
|
||||
"zagros",
|
||||
], workspace = true, default-features = true }
|
||||
teyrchains-common = { workspace = true, default-features = true }
|
||||
|
||||
[features]
|
||||
runtime-benchmarks = [
|
||||
"bp-messages/runtime-benchmarks",
|
||||
"bridge-hub-common/runtime-benchmarks",
|
||||
"bridge-hub-zagros-runtime/runtime-benchmarks",
|
||||
"emulated-integration-tests-common/runtime-benchmarks",
|
||||
"pezframe-support/runtime-benchmarks",
|
||||
"pezsp-keyring/runtime-benchmarks",
|
||||
"testnet-teyrchains-constants/runtime-benchmarks",
|
||||
"teyrchains-common/runtime-benchmarks",
|
||||
"xcm/runtime-benchmarks",
|
||||
]
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Bizinikiwi
|
||||
use pezsp_core::storage::Storage;
|
||||
use pezsp_keyring::Sr25519Keyring as Keyring;
|
||||
|
||||
// Pezcumulus
|
||||
use emulated_integration_tests_common::{
|
||||
accounts, build_genesis_storage, collators, SAFE_XCM_VERSION,
|
||||
};
|
||||
use teyrchains_common::Balance;
|
||||
use xcm::latest::{prelude::*, PEZKUWICHAIN_GENESIS_HASH};
|
||||
|
||||
pub const PARA_ID: u32 = 1002;
|
||||
pub const ASSETHUB_PARA_ID: u32 = 1000;
|
||||
pub const ED: Balance = testnet_teyrchains_constants::zagros::currency::EXISTENTIAL_DEPOSIT;
|
||||
|
||||
pub fn genesis() -> Storage {
|
||||
let genesis_config = bridge_hub_zagros_runtime::RuntimeGenesisConfig {
|
||||
system: bridge_hub_zagros_runtime::SystemConfig::default(),
|
||||
balances: bridge_hub_zagros_runtime::BalancesConfig {
|
||||
balances: accounts::init_balances().iter().cloned().map(|k| (k, ED * 4096)).collect(),
|
||||
..Default::default()
|
||||
},
|
||||
teyrchain_info: bridge_hub_zagros_runtime::TeyrchainInfoConfig {
|
||||
teyrchain_id: PARA_ID.into(),
|
||||
..Default::default()
|
||||
},
|
||||
collator_selection: bridge_hub_zagros_runtime::CollatorSelectionConfig {
|
||||
invulnerables: collators::invulnerables().iter().cloned().map(|(acc, _)| acc).collect(),
|
||||
candidacy_bond: ED * 16,
|
||||
..Default::default()
|
||||
},
|
||||
session: bridge_hub_zagros_runtime::SessionConfig {
|
||||
keys: collators::invulnerables()
|
||||
.into_iter()
|
||||
.map(|(acc, aura)| {
|
||||
(
|
||||
acc.clone(), // account id
|
||||
acc, // validator id
|
||||
bridge_hub_zagros_runtime::SessionKeys { aura }, // session keys
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
..Default::default()
|
||||
},
|
||||
pezkuwi_xcm: bridge_hub_zagros_runtime::PezkuwiXcmConfig {
|
||||
safe_xcm_version: Some(SAFE_XCM_VERSION),
|
||||
..Default::default()
|
||||
},
|
||||
bridge_pezkuwichain_grandpa: bridge_hub_zagros_runtime::BridgePezkuwichainGrandpaConfig {
|
||||
owner: Some(Keyring::Bob.to_account_id()),
|
||||
..Default::default()
|
||||
},
|
||||
bridge_pezkuwichain_messages: bridge_hub_zagros_runtime::BridgePezkuwichainMessagesConfig {
|
||||
owner: Some(Keyring::Bob.to_account_id()),
|
||||
..Default::default()
|
||||
},
|
||||
xcm_over_bridge_hub_pezkuwichain:
|
||||
bridge_hub_zagros_runtime::XcmOverBridgeHubPezkuwichainConfig {
|
||||
opened_bridges: vec![
|
||||
// open AHW -> AHR bridge
|
||||
(
|
||||
Location::new(1, [Teyrchain(1000)]),
|
||||
Junctions::from([
|
||||
NetworkId::ByGenesis(PEZKUWICHAIN_GENESIS_HASH).into(),
|
||||
Teyrchain(1000),
|
||||
]),
|
||||
Some(bp_messages::LegacyLaneId([0, 0, 0, 2])),
|
||||
),
|
||||
],
|
||||
..Default::default()
|
||||
},
|
||||
ethereum_system: bridge_hub_zagros_runtime::EthereumSystemConfig {
|
||||
para_id: PARA_ID.into(),
|
||||
asset_hub_para_id: ASSETHUB_PARA_ID.into(),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
build_genesis_storage(
|
||||
&genesis_config,
|
||||
bridge_hub_zagros_runtime::WASM_BINARY
|
||||
.expect("WASM binary was not built, please build it!"),
|
||||
)
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
pub mod genesis;
|
||||
|
||||
pub use bridge_hub_zagros_runtime::{
|
||||
self, xcm_config::XcmConfig as BridgeHubZagrosXcmConfig,
|
||||
ExistentialDeposit as BridgeHubZagrosExistentialDeposit,
|
||||
RuntimeOrigin as BridgeHubZagrosRuntimeOrigin,
|
||||
};
|
||||
|
||||
// Bizinikiwi
|
||||
use pezframe_support::traits::OnInitialize;
|
||||
|
||||
// Pezcumulus
|
||||
use emulated_integration_tests_common::{
|
||||
impl_accounts_helpers_for_teyrchain, impl_assert_events_helpers_for_teyrchain,
|
||||
impl_xcm_helpers_for_teyrchain, impls::Teyrchain, xcm_emulator::decl_test_teyrchains,
|
||||
AuraDigestProvider,
|
||||
};
|
||||
|
||||
// BridgeHubZagros Teyrchain declaration
|
||||
decl_test_teyrchains! {
|
||||
pub struct BridgeHubZagros {
|
||||
genesis = genesis::genesis(),
|
||||
on_init = {
|
||||
bridge_hub_zagros_runtime::AuraExt::on_initialize(1);
|
||||
},
|
||||
runtime = bridge_hub_zagros_runtime,
|
||||
core = {
|
||||
XcmpMessageHandler: bridge_hub_zagros_runtime::XcmpQueue,
|
||||
LocationToAccountId: bridge_hub_zagros_runtime::xcm_config::LocationToAccountId,
|
||||
TeyrchainInfo: bridge_hub_zagros_runtime::TeyrchainInfo,
|
||||
MessageOrigin: bridge_hub_common::AggregateMessageOrigin,
|
||||
DigestProvider: AuraDigestProvider,
|
||||
},
|
||||
pallets = {
|
||||
PezkuwiXcm: bridge_hub_zagros_runtime::PezkuwiXcm,
|
||||
Balances: bridge_hub_zagros_runtime::Balances,
|
||||
EthereumSystem: bridge_hub_zagros_runtime::EthereumSystem,
|
||||
EthereumInboundQueue: bridge_hub_zagros_runtime::EthereumInboundQueue,
|
||||
EthereumOutboundQueue: bridge_hub_zagros_runtime::EthereumOutboundQueue,
|
||||
EthereumSystemV2: bridge_hub_zagros_runtime::EthereumSystemV2,
|
||||
BridgeRelayers: bridge_hub_zagros_runtime::BridgeRelayers,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// BridgeHubZagros implementation
|
||||
impl_accounts_helpers_for_teyrchain!(BridgeHubZagros);
|
||||
impl_assert_events_helpers_for_teyrchain!(BridgeHubZagros);
|
||||
impl_xcm_helpers_for_teyrchain!(BridgeHubZagros);
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
[package]
|
||||
name = "collectives-zagros-emulated-chain"
|
||||
version = "0.0.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license = "Apache-2.0"
|
||||
description = "Collectives Zagros emulated chain"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
# Bizinikiwi
|
||||
pezframe-support = { workspace = true }
|
||||
pezsp-core = { workspace = true }
|
||||
|
||||
# Pezcumulus
|
||||
collectives-zagros-runtime = { workspace = true }
|
||||
pezcumulus-primitives-core = { workspace = true }
|
||||
emulated-integration-tests-common = { workspace = true }
|
||||
testnet-teyrchains-constants = { features = [
|
||||
"zagros",
|
||||
], workspace = true, default-features = true }
|
||||
teyrchains-common = { workspace = true, default-features = true }
|
||||
|
||||
[features]
|
||||
runtime-benchmarks = [
|
||||
"collectives-zagros-runtime/runtime-benchmarks",
|
||||
"pezcumulus-primitives-core/runtime-benchmarks",
|
||||
"emulated-integration-tests-common/runtime-benchmarks",
|
||||
"pezframe-support/runtime-benchmarks",
|
||||
"testnet-teyrchains-constants/runtime-benchmarks",
|
||||
"teyrchains-common/runtime-benchmarks",
|
||||
]
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Bizinikiwi
|
||||
use pezsp_core::storage::Storage;
|
||||
|
||||
// Pezcumulus
|
||||
use emulated_integration_tests_common::{
|
||||
accounts, build_genesis_storage, collators, SAFE_XCM_VERSION,
|
||||
};
|
||||
use teyrchains_common::Balance;
|
||||
|
||||
pub const PARA_ID: u32 = 1001;
|
||||
pub const ED: Balance = testnet_teyrchains_constants::zagros::currency::EXISTENTIAL_DEPOSIT;
|
||||
|
||||
pub fn genesis() -> Storage {
|
||||
let genesis_config = collectives_zagros_runtime::RuntimeGenesisConfig {
|
||||
system: collectives_zagros_runtime::SystemConfig::default(),
|
||||
balances: collectives_zagros_runtime::BalancesConfig {
|
||||
balances: accounts::init_balances().iter().cloned().map(|k| (k, ED * 4096)).collect(),
|
||||
..Default::default()
|
||||
},
|
||||
teyrchain_info: collectives_zagros_runtime::TeyrchainInfoConfig {
|
||||
teyrchain_id: PARA_ID.into(),
|
||||
..Default::default()
|
||||
},
|
||||
collator_selection: collectives_zagros_runtime::CollatorSelectionConfig {
|
||||
invulnerables: collators::invulnerables().iter().cloned().map(|(acc, _)| acc).collect(),
|
||||
candidacy_bond: ED * 16,
|
||||
..Default::default()
|
||||
},
|
||||
session: collectives_zagros_runtime::SessionConfig {
|
||||
keys: collators::invulnerables()
|
||||
.into_iter()
|
||||
.map(|(acc, aura)| {
|
||||
(
|
||||
acc.clone(), // account id
|
||||
acc, // validator id
|
||||
collectives_zagros_runtime::SessionKeys { aura }, // session keys
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
..Default::default()
|
||||
},
|
||||
pezkuwi_xcm: collectives_zagros_runtime::PezkuwiXcmConfig {
|
||||
safe_xcm_version: Some(SAFE_XCM_VERSION),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
build_genesis_storage(
|
||||
&genesis_config,
|
||||
collectives_zagros_runtime::WASM_BINARY
|
||||
.expect("WASM binary was not built, please build it!"),
|
||||
)
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
pub use collectives_zagros_runtime;
|
||||
|
||||
pub mod genesis;
|
||||
|
||||
// Bizinikiwi
|
||||
use pezframe_support::traits::OnInitialize;
|
||||
|
||||
// Pezcumulus
|
||||
use emulated_integration_tests_common::{
|
||||
impl_accounts_helpers_for_teyrchain, impl_assert_events_helpers_for_teyrchain,
|
||||
impls::Teyrchain, xcm_emulator::decl_test_teyrchains, AuraDigestProvider,
|
||||
};
|
||||
|
||||
// CollectivesZagros Teyrchain declaration
|
||||
decl_test_teyrchains! {
|
||||
pub struct CollectivesZagros {
|
||||
genesis = genesis::genesis(),
|
||||
on_init = {
|
||||
collectives_zagros_runtime::AuraExt::on_initialize(1);
|
||||
},
|
||||
runtime = collectives_zagros_runtime,
|
||||
core = {
|
||||
XcmpMessageHandler: collectives_zagros_runtime::XcmpQueue,
|
||||
LocationToAccountId: collectives_zagros_runtime::xcm_config::LocationToAccountId,
|
||||
TeyrchainInfo: collectives_zagros_runtime::TeyrchainInfo,
|
||||
MessageOrigin: cumulus_primitives_core::AggregateMessageOrigin,
|
||||
DigestProvider: AuraDigestProvider,
|
||||
},
|
||||
pallets = {
|
||||
PezkuwiXcm: collectives_zagros_runtime::PezkuwiXcm,
|
||||
Balances: collectives_zagros_runtime::Balances,
|
||||
FellowshipTreasury: collectives_zagros_runtime::FellowshipTreasury,
|
||||
AssetRate: collectives_zagros_runtime::AssetRate,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// AssetHubZagros implementation
|
||||
impl_accounts_helpers_for_teyrchain!(CollectivesZagros);
|
||||
impl_assert_events_helpers_for_teyrchain!(CollectivesZagros);
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
[package]
|
||||
name = "coretime-pezkuwichain-emulated-chain"
|
||||
version = "0.1.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license = "Apache-2.0"
|
||||
description = "Coretime Pezkuwichain emulated chain"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
# Bizinikiwi
|
||||
pezframe-support = { workspace = true }
|
||||
pezsp-core = { workspace = true }
|
||||
|
||||
# Pezcumulus
|
||||
coretime-pezkuwichain-runtime = { workspace = true, default-features = true }
|
||||
pezcumulus-primitives-core = { workspace = true }
|
||||
emulated-integration-tests-common = { workspace = true }
|
||||
testnet-teyrchains-constants = { features = [
|
||||
"pezkuwichain",
|
||||
], workspace = true, default-features = true }
|
||||
teyrchains-common = { workspace = true, default-features = true }
|
||||
|
||||
[features]
|
||||
runtime-benchmarks = [
|
||||
"coretime-pezkuwichain-runtime/runtime-benchmarks",
|
||||
"pezcumulus-primitives-core/runtime-benchmarks",
|
||||
"emulated-integration-tests-common/runtime-benchmarks",
|
||||
"pezframe-support/runtime-benchmarks",
|
||||
"testnet-teyrchains-constants/runtime-benchmarks",
|
||||
"teyrchains-common/runtime-benchmarks",
|
||||
]
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Bizinikiwi
|
||||
use pezsp_core::storage::Storage;
|
||||
|
||||
// Pezcumulus
|
||||
use emulated_integration_tests_common::{
|
||||
accounts, build_genesis_storage, collators, SAFE_XCM_VERSION,
|
||||
};
|
||||
use teyrchains_common::Balance;
|
||||
|
||||
pub const PARA_ID: u32 = 1005;
|
||||
pub const ED: Balance = testnet_teyrchains_constants::pezkuwichain::currency::EXISTENTIAL_DEPOSIT;
|
||||
|
||||
pub fn genesis() -> Storage {
|
||||
let genesis_config = coretime_pezkuwichain_runtime::RuntimeGenesisConfig {
|
||||
system: coretime_pezkuwichain_runtime::SystemConfig::default(),
|
||||
balances: coretime_pezkuwichain_runtime::BalancesConfig {
|
||||
balances: accounts::init_balances().iter().cloned().map(|k| (k, ED * 4096)).collect(),
|
||||
..Default::default()
|
||||
},
|
||||
teyrchain_info: coretime_pezkuwichain_runtime::TeyrchainInfoConfig {
|
||||
teyrchain_id: PARA_ID.into(),
|
||||
..Default::default()
|
||||
},
|
||||
collator_selection: coretime_pezkuwichain_runtime::CollatorSelectionConfig {
|
||||
invulnerables: collators::invulnerables().iter().cloned().map(|(acc, _)| acc).collect(),
|
||||
candidacy_bond: ED * 16,
|
||||
..Default::default()
|
||||
},
|
||||
session: coretime_pezkuwichain_runtime::SessionConfig {
|
||||
keys: collators::invulnerables()
|
||||
.into_iter()
|
||||
.map(|(acc, aura)| {
|
||||
(
|
||||
acc.clone(), // account id
|
||||
acc, // validator id
|
||||
coretime_pezkuwichain_runtime::SessionKeys { aura }, // session keys
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
..Default::default()
|
||||
},
|
||||
pezkuwi_xcm: coretime_pezkuwichain_runtime::PezkuwiXcmConfig {
|
||||
safe_xcm_version: Some(SAFE_XCM_VERSION),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
build_genesis_storage(
|
||||
&genesis_config,
|
||||
coretime_pezkuwichain_runtime::WASM_BINARY
|
||||
.expect("WASM binary was not built, please build it!"),
|
||||
)
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
pub use coretime_pezkuwichain_runtime;
|
||||
|
||||
pub mod genesis;
|
||||
|
||||
// Bizinikiwi
|
||||
use pezframe_support::traits::OnInitialize;
|
||||
|
||||
// Pezcumulus
|
||||
use emulated_integration_tests_common::{
|
||||
impl_accounts_helpers_for_teyrchain, impl_assert_events_helpers_for_teyrchain,
|
||||
impls::Teyrchain, xcm_emulator::decl_test_teyrchains, AuraDigestProvider,
|
||||
};
|
||||
|
||||
// CoretimePezkuwichain Teyrchain declaration
|
||||
decl_test_teyrchains! {
|
||||
pub struct CoretimePezkuwichain {
|
||||
genesis = genesis::genesis(),
|
||||
on_init = {
|
||||
coretime_pezkuwichain_runtime::AuraExt::on_initialize(1);
|
||||
},
|
||||
runtime = coretime_pezkuwichain_runtime,
|
||||
core = {
|
||||
XcmpMessageHandler: coretime_pezkuwichain_runtime::XcmpQueue,
|
||||
LocationToAccountId: coretime_pezkuwichain_runtime::xcm_config::LocationToAccountId,
|
||||
TeyrchainInfo: coretime_pezkuwichain_runtime::TeyrchainInfo,
|
||||
MessageOrigin: cumulus_primitives_core::AggregateMessageOrigin,
|
||||
DigestProvider: AuraDigestProvider,
|
||||
},
|
||||
pallets = {
|
||||
PezkuwiXcm: coretime_pezkuwichain_runtime::PezkuwiXcm,
|
||||
Balances: coretime_pezkuwichain_runtime::Balances,
|
||||
Broker: coretime_pezkuwichain_runtime::Broker,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// CoretimePezkuwichain implementation
|
||||
impl_accounts_helpers_for_teyrchain!(CoretimePezkuwichain);
|
||||
impl_assert_events_helpers_for_teyrchain!(CoretimePezkuwichain);
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
[package]
|
||||
name = "coretime-zagros-emulated-chain"
|
||||
version = "0.1.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license = "Apache-2.0"
|
||||
description = "Coretime Zagros emulated chain"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
# Bizinikiwi
|
||||
pezframe-support = { workspace = true }
|
||||
pezsp-core = { workspace = true }
|
||||
|
||||
# Pezcumulus
|
||||
coretime-zagros-runtime = { workspace = true, default-features = true }
|
||||
pezcumulus-primitives-core = { workspace = true }
|
||||
emulated-integration-tests-common = { workspace = true }
|
||||
testnet-teyrchains-constants = { features = [
|
||||
"zagros",
|
||||
], workspace = true, default-features = true }
|
||||
teyrchains-common = { workspace = true, default-features = true }
|
||||
|
||||
[features]
|
||||
runtime-benchmarks = [
|
||||
"coretime-zagros-runtime/runtime-benchmarks",
|
||||
"pezcumulus-primitives-core/runtime-benchmarks",
|
||||
"emulated-integration-tests-common/runtime-benchmarks",
|
||||
"pezframe-support/runtime-benchmarks",
|
||||
"testnet-teyrchains-constants/runtime-benchmarks",
|
||||
"teyrchains-common/runtime-benchmarks",
|
||||
]
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Bizinikiwi
|
||||
use pezsp_core::storage::Storage;
|
||||
|
||||
// Pezcumulus
|
||||
use emulated_integration_tests_common::{
|
||||
accounts, build_genesis_storage, collators, SAFE_XCM_VERSION,
|
||||
};
|
||||
use teyrchains_common::Balance;
|
||||
|
||||
pub const PARA_ID: u32 = 1005;
|
||||
pub const ED: Balance = testnet_teyrchains_constants::zagros::currency::EXISTENTIAL_DEPOSIT;
|
||||
|
||||
pub fn genesis() -> Storage {
|
||||
let genesis_config = coretime_zagros_runtime::RuntimeGenesisConfig {
|
||||
system: coretime_zagros_runtime::SystemConfig::default(),
|
||||
balances: coretime_zagros_runtime::BalancesConfig {
|
||||
balances: accounts::init_balances().iter().cloned().map(|k| (k, ED * 4096)).collect(),
|
||||
..Default::default()
|
||||
},
|
||||
teyrchain_info: coretime_zagros_runtime::TeyrchainInfoConfig {
|
||||
teyrchain_id: PARA_ID.into(),
|
||||
..Default::default()
|
||||
},
|
||||
collator_selection: coretime_zagros_runtime::CollatorSelectionConfig {
|
||||
invulnerables: collators::invulnerables().iter().cloned().map(|(acc, _)| acc).collect(),
|
||||
candidacy_bond: ED * 16,
|
||||
..Default::default()
|
||||
},
|
||||
session: coretime_zagros_runtime::SessionConfig {
|
||||
keys: collators::invulnerables()
|
||||
.into_iter()
|
||||
.map(|(acc, aura)| {
|
||||
(
|
||||
acc.clone(), // account id
|
||||
acc, // validator id
|
||||
coretime_zagros_runtime::SessionKeys { aura }, // session keys
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
..Default::default()
|
||||
},
|
||||
pezkuwi_xcm: coretime_zagros_runtime::PezkuwiXcmConfig {
|
||||
safe_xcm_version: Some(SAFE_XCM_VERSION),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
build_genesis_storage(
|
||||
&genesis_config,
|
||||
coretime_zagros_runtime::WASM_BINARY.expect("WASM binary was not built, please build it!"),
|
||||
)
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
pub use coretime_zagros_runtime;
|
||||
|
||||
pub mod genesis;
|
||||
|
||||
// Bizinikiwi
|
||||
use pezframe_support::traits::OnInitialize;
|
||||
|
||||
// Pezcumulus
|
||||
use emulated_integration_tests_common::{
|
||||
impl_accounts_helpers_for_teyrchain, impl_assert_events_helpers_for_teyrchain,
|
||||
impls::Teyrchain, xcm_emulator::decl_test_teyrchains, AuraDigestProvider,
|
||||
};
|
||||
|
||||
// CoretimeZagros Teyrchain declaration
|
||||
decl_test_teyrchains! {
|
||||
pub struct CoretimeZagros {
|
||||
genesis = genesis::genesis(),
|
||||
on_init = {
|
||||
coretime_zagros_runtime::AuraExt::on_initialize(1);
|
||||
},
|
||||
runtime = coretime_zagros_runtime,
|
||||
core = {
|
||||
XcmpMessageHandler: coretime_zagros_runtime::XcmpQueue,
|
||||
LocationToAccountId: coretime_zagros_runtime::xcm_config::LocationToAccountId,
|
||||
TeyrchainInfo: coretime_zagros_runtime::TeyrchainInfo,
|
||||
MessageOrigin: cumulus_primitives_core::AggregateMessageOrigin,
|
||||
DigestProvider: AuraDigestProvider,
|
||||
},
|
||||
pallets = {
|
||||
PezkuwiXcm: coretime_zagros_runtime::PezkuwiXcm,
|
||||
Balances: coretime_zagros_runtime::Balances,
|
||||
Broker: coretime_zagros_runtime::Broker,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// CoretimeZagros implementation
|
||||
impl_accounts_helpers_for_teyrchain!(CoretimeZagros);
|
||||
impl_assert_events_helpers_for_teyrchain!(CoretimeZagros);
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
[package]
|
||||
name = "people-pezkuwichain-emulated-chain"
|
||||
version = "0.1.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license = "Apache-2.0"
|
||||
description = "People Pezkuwichain emulated chain"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
# Bizinikiwi
|
||||
pezframe-support = { workspace = true }
|
||||
pezsp-core = { workspace = true }
|
||||
|
||||
# Pezcumulus
|
||||
pezcumulus-primitives-core = { workspace = true }
|
||||
emulated-integration-tests-common = { workspace = true }
|
||||
people-pezkuwichain-runtime = { workspace = true }
|
||||
testnet-teyrchains-constants = { features = [
|
||||
"pezkuwichain",
|
||||
], workspace = true, default-features = true }
|
||||
teyrchains-common = { workspace = true, default-features = true }
|
||||
|
||||
[features]
|
||||
runtime-benchmarks = [
|
||||
"pezcumulus-primitives-core/runtime-benchmarks",
|
||||
"emulated-integration-tests-common/runtime-benchmarks",
|
||||
"pezframe-support/runtime-benchmarks",
|
||||
"people-pezkuwichain-runtime/runtime-benchmarks",
|
||||
"testnet-teyrchains-constants/runtime-benchmarks",
|
||||
"teyrchains-common/runtime-benchmarks",
|
||||
]
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Bizinikiwi
|
||||
use pezsp_core::storage::Storage;
|
||||
|
||||
// Pezcumulus
|
||||
use cumulus_primitives_core::ParaId;
|
||||
use emulated_integration_tests_common::{
|
||||
accounts, build_genesis_storage, collators, SAFE_XCM_VERSION,
|
||||
};
|
||||
use teyrchains_common::Balance;
|
||||
|
||||
pub const PARA_ID: u32 = 1004;
|
||||
pub const ED: Balance = testnet_teyrchains_constants::pezkuwichain::currency::EXISTENTIAL_DEPOSIT;
|
||||
|
||||
pub fn genesis() -> Storage {
|
||||
let genesis_config = people_pezkuwichain_runtime::RuntimeGenesisConfig {
|
||||
system: people_pezkuwichain_runtime::SystemConfig::default(),
|
||||
balances: people_pezkuwichain_runtime::BalancesConfig {
|
||||
balances: accounts::init_balances().iter().cloned().map(|k| (k, ED * 4096)).collect(),
|
||||
..Default::default()
|
||||
},
|
||||
teyrchain_info: people_pezkuwichain_runtime::TeyrchainInfoConfig {
|
||||
teyrchain_id: ParaId::from(PARA_ID),
|
||||
..Default::default()
|
||||
},
|
||||
collator_selection: people_pezkuwichain_runtime::CollatorSelectionConfig {
|
||||
invulnerables: collators::invulnerables().iter().cloned().map(|(acc, _)| acc).collect(),
|
||||
candidacy_bond: ED * 16,
|
||||
..Default::default()
|
||||
},
|
||||
session: people_pezkuwichain_runtime::SessionConfig {
|
||||
keys: collators::invulnerables()
|
||||
.into_iter()
|
||||
.map(|(acc, aura)| {
|
||||
(
|
||||
acc.clone(), // account id
|
||||
acc, // validator id
|
||||
people_pezkuwichain_runtime::SessionKeys { aura }, // session keys
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
..Default::default()
|
||||
},
|
||||
pezkuwi_xcm: people_pezkuwichain_runtime::PezkuwiXcmConfig {
|
||||
safe_xcm_version: Some(SAFE_XCM_VERSION),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
build_genesis_storage(
|
||||
&genesis_config,
|
||||
people_pezkuwichain_runtime::WASM_BINARY
|
||||
.expect("WASM binary was not built, please build it!"),
|
||||
)
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
pub use people_pezkuwichain_runtime;
|
||||
|
||||
pub mod genesis;
|
||||
|
||||
// Bizinikiwi
|
||||
use pezframe_support::traits::OnInitialize;
|
||||
|
||||
// Pezcumulus
|
||||
use emulated_integration_tests_common::{
|
||||
impl_accounts_helpers_for_teyrchain, impl_assert_events_helpers_for_teyrchain,
|
||||
impls::Teyrchain, xcm_emulator::decl_test_teyrchains, AuraDigestProvider,
|
||||
};
|
||||
|
||||
// PeoplePezkuwichain Teyrchain declaration
|
||||
decl_test_teyrchains! {
|
||||
pub struct PeoplePezkuwichain {
|
||||
genesis = genesis::genesis(),
|
||||
on_init = {
|
||||
people_pezkuwichain_runtime::AuraExt::on_initialize(1);
|
||||
},
|
||||
runtime = people_pezkuwichain_runtime,
|
||||
core = {
|
||||
XcmpMessageHandler: people_pezkuwichain_runtime::XcmpQueue,
|
||||
LocationToAccountId: people_pezkuwichain_runtime::xcm_config::LocationToAccountId,
|
||||
TeyrchainInfo: people_pezkuwichain_runtime::TeyrchainInfo,
|
||||
MessageOrigin: cumulus_primitives_core::AggregateMessageOrigin,
|
||||
DigestProvider: AuraDigestProvider,
|
||||
},
|
||||
pallets = {
|
||||
PezkuwiXcm: people_pezkuwichain_runtime::PezkuwiXcm,
|
||||
Balances: people_pezkuwichain_runtime::Balances,
|
||||
Identity: people_pezkuwichain_runtime::Identity,
|
||||
IdentityMigrator: people_pezkuwichain_runtime::IdentityMigrator,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// PeoplePezkuwichain implementation
|
||||
impl_accounts_helpers_for_teyrchain!(PeoplePezkuwichain);
|
||||
impl_assert_events_helpers_for_teyrchain!(PeoplePezkuwichain);
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
[package]
|
||||
name = "people-zagros-emulated-chain"
|
||||
version = "0.1.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license = "Apache-2.0"
|
||||
description = "People Zagros emulated chain"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
# Bizinikiwi
|
||||
pezframe-support = { workspace = true }
|
||||
pezsp-core = { workspace = true }
|
||||
|
||||
# Pezcumulus
|
||||
pezcumulus-primitives-core = { workspace = true }
|
||||
emulated-integration-tests-common = { workspace = true }
|
||||
people-zagros-runtime = { workspace = true }
|
||||
testnet-teyrchains-constants = { features = [
|
||||
"zagros",
|
||||
], workspace = true, default-features = true }
|
||||
teyrchains-common = { workspace = true, default-features = true }
|
||||
|
||||
[features]
|
||||
runtime-benchmarks = [
|
||||
"pezcumulus-primitives-core/runtime-benchmarks",
|
||||
"emulated-integration-tests-common/runtime-benchmarks",
|
||||
"pezframe-support/runtime-benchmarks",
|
||||
"people-zagros-runtime/runtime-benchmarks",
|
||||
"testnet-teyrchains-constants/runtime-benchmarks",
|
||||
"teyrchains-common/runtime-benchmarks",
|
||||
]
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Bizinikiwi
|
||||
use pezsp_core::storage::Storage;
|
||||
|
||||
// Pezcumulus
|
||||
use cumulus_primitives_core::ParaId;
|
||||
use emulated_integration_tests_common::{
|
||||
accounts, build_genesis_storage, collators, SAFE_XCM_VERSION,
|
||||
};
|
||||
use teyrchains_common::Balance;
|
||||
|
||||
pub const PARA_ID: u32 = 1004;
|
||||
pub const ED: Balance = testnet_teyrchains_constants::zagros::currency::EXISTENTIAL_DEPOSIT;
|
||||
|
||||
pub fn genesis() -> Storage {
|
||||
let genesis_config = people_zagros_runtime::RuntimeGenesisConfig {
|
||||
system: people_zagros_runtime::SystemConfig::default(),
|
||||
balances: people_zagros_runtime::BalancesConfig {
|
||||
balances: accounts::init_balances().iter().cloned().map(|k| (k, ED * 4096)).collect(),
|
||||
..Default::default()
|
||||
},
|
||||
teyrchain_info: people_zagros_runtime::TeyrchainInfoConfig {
|
||||
teyrchain_id: ParaId::from(PARA_ID),
|
||||
..Default::default()
|
||||
},
|
||||
collator_selection: people_zagros_runtime::CollatorSelectionConfig {
|
||||
invulnerables: collators::invulnerables().iter().cloned().map(|(acc, _)| acc).collect(),
|
||||
candidacy_bond: ED * 16,
|
||||
..Default::default()
|
||||
},
|
||||
session: people_zagros_runtime::SessionConfig {
|
||||
keys: collators::invulnerables()
|
||||
.into_iter()
|
||||
.map(|(acc, aura)| {
|
||||
(
|
||||
acc.clone(), // account id
|
||||
acc, // validator id
|
||||
people_zagros_runtime::SessionKeys { aura }, // session keys
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
..Default::default()
|
||||
},
|
||||
pezkuwi_xcm: people_zagros_runtime::PezkuwiXcmConfig {
|
||||
safe_xcm_version: Some(SAFE_XCM_VERSION),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
build_genesis_storage(
|
||||
&genesis_config,
|
||||
people_zagros_runtime::WASM_BINARY.expect("WASM binary was not built, please build it!"),
|
||||
)
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
pub use people_zagros_runtime;
|
||||
|
||||
pub mod genesis;
|
||||
|
||||
// Bizinikiwi
|
||||
use pezframe_support::traits::OnInitialize;
|
||||
|
||||
// Pezcumulus
|
||||
use emulated_integration_tests_common::{
|
||||
impl_accounts_helpers_for_teyrchain, impl_assert_events_helpers_for_teyrchain,
|
||||
impls::Teyrchain, xcm_emulator::decl_test_teyrchains, AuraDigestProvider,
|
||||
};
|
||||
|
||||
// PeopleZagros Teyrchain declaration
|
||||
decl_test_teyrchains! {
|
||||
pub struct PeopleZagros {
|
||||
genesis = genesis::genesis(),
|
||||
on_init = {
|
||||
people_zagros_runtime::AuraExt::on_initialize(1);
|
||||
},
|
||||
runtime = people_zagros_runtime,
|
||||
core = {
|
||||
XcmpMessageHandler: people_zagros_runtime::XcmpQueue,
|
||||
LocationToAccountId: people_zagros_runtime::xcm_config::LocationToAccountId,
|
||||
TeyrchainInfo: people_zagros_runtime::TeyrchainInfo,
|
||||
MessageOrigin: cumulus_primitives_core::AggregateMessageOrigin,
|
||||
DigestProvider: AuraDigestProvider,
|
||||
},
|
||||
pallets = {
|
||||
PezkuwiXcm: people_zagros_runtime::PezkuwiXcm,
|
||||
Balances: people_zagros_runtime::Balances,
|
||||
Identity: people_zagros_runtime::Identity,
|
||||
IdentityMigrator: people_zagros_runtime::IdentityMigrator,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// PeopleZagros implementation
|
||||
impl_accounts_helpers_for_teyrchain!(PeopleZagros);
|
||||
impl_assert_events_helpers_for_teyrchain!(PeopleZagros);
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
[package]
|
||||
name = "penpal-emulated-chain"
|
||||
version = "0.0.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license = "Apache-2.0"
|
||||
description = "Penpal emulated chain"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
# Bizinikiwi
|
||||
pezframe-support = { workspace = true }
|
||||
pezsp-core = { workspace = true }
|
||||
pezsp-keyring = { workspace = true }
|
||||
|
||||
# Pezkuwi
|
||||
xcm = { workspace = true }
|
||||
|
||||
# Pezcumulus
|
||||
pezcumulus-primitives-core = { workspace = true }
|
||||
emulated-integration-tests-common = { workspace = true }
|
||||
penpal-runtime = { workspace = true }
|
||||
teyrchains-common = { workspace = true, default-features = true }
|
||||
|
||||
[features]
|
||||
runtime-benchmarks = [
|
||||
"pezcumulus-primitives-core/runtime-benchmarks",
|
||||
"emulated-integration-tests-common/runtime-benchmarks",
|
||||
"pezframe-support/runtime-benchmarks",
|
||||
"penpal-runtime/runtime-benchmarks",
|
||||
"pezsp-keyring/runtime-benchmarks",
|
||||
"teyrchains-common/runtime-benchmarks",
|
||||
"xcm/runtime-benchmarks",
|
||||
]
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Bizinikiwi
|
||||
use pezframe_support::parameter_types;
|
||||
use pezsp_core::storage::Storage;
|
||||
use pezsp_keyring::Sr25519Keyring as Keyring;
|
||||
|
||||
// Pezcumulus
|
||||
use emulated_integration_tests_common::{
|
||||
accounts, build_genesis_storage, collators, SAFE_XCM_VERSION,
|
||||
};
|
||||
use penpal_runtime::xcm_config::{LocalReservableFromAssetHub, RelayLocation, UsdtFromAssetHub};
|
||||
use teyrchains_common::{AccountId, Balance};
|
||||
// Penpal
|
||||
pub const PARA_ID_A: u32 = 2000;
|
||||
pub const PARA_ID_B: u32 = 2001;
|
||||
pub const ED: Balance = penpal_runtime::EXISTENTIAL_DEPOSIT;
|
||||
pub const USDT_ED: Balance = 70_000;
|
||||
|
||||
parameter_types! {
|
||||
pub PenpalSudoAccount: AccountId = Keyring::Alice.to_account_id();
|
||||
pub PenpalAssetOwner: AccountId = PenpalSudoAccount::get();
|
||||
}
|
||||
|
||||
pub fn genesis(para_id: u32) -> Storage {
|
||||
let genesis_config = penpal_runtime::RuntimeGenesisConfig {
|
||||
system: penpal_runtime::SystemConfig::default(),
|
||||
balances: penpal_runtime::BalancesConfig {
|
||||
balances: accounts::init_balances().iter().cloned().map(|k| (k, ED * 4096)).collect(),
|
||||
..Default::default()
|
||||
},
|
||||
teyrchain_info: penpal_runtime::TeyrchainInfoConfig {
|
||||
teyrchain_id: para_id.into(),
|
||||
..Default::default()
|
||||
},
|
||||
collator_selection: penpal_runtime::CollatorSelectionConfig {
|
||||
invulnerables: collators::invulnerables().iter().cloned().map(|(acc, _)| acc).collect(),
|
||||
candidacy_bond: ED * 16,
|
||||
..Default::default()
|
||||
},
|
||||
session: penpal_runtime::SessionConfig {
|
||||
keys: collators::invulnerables()
|
||||
.into_iter()
|
||||
.map(|(acc, aura)| {
|
||||
(
|
||||
acc.clone(), // account id
|
||||
acc, // validator id
|
||||
penpal_runtime::SessionKeys { aura }, // session keys
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
..Default::default()
|
||||
},
|
||||
pezkuwi_xcm: penpal_runtime::PezkuwiXcmConfig {
|
||||
safe_xcm_version: Some(SAFE_XCM_VERSION),
|
||||
..Default::default()
|
||||
},
|
||||
sudo: penpal_runtime::SudoConfig { key: Some(PenpalSudoAccount::get()) },
|
||||
assets: penpal_runtime::AssetsConfig {
|
||||
assets: vec![(
|
||||
penpal_runtime::xcm_config::TELEPORTABLE_ASSET_ID,
|
||||
PenpalAssetOwner::get(),
|
||||
false,
|
||||
ED,
|
||||
)],
|
||||
..Default::default()
|
||||
},
|
||||
foreign_assets: penpal_runtime::ForeignAssetsConfig {
|
||||
assets: vec![
|
||||
// Relay Native asset representation
|
||||
(RelayLocation::get(), PenpalAssetOwner::get(), true, ED),
|
||||
// Sufficient AssetHub asset representation
|
||||
(LocalReservableFromAssetHub::get(), PenpalAssetOwner::get(), true, ED),
|
||||
// USDT from AssetHub
|
||||
(UsdtFromAssetHub::get(), PenpalAssetOwner::get(), true, USDT_ED),
|
||||
],
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
build_genesis_storage(
|
||||
&genesis_config,
|
||||
penpal_runtime::WASM_BINARY.expect("WASM binary was not built, please build it!"),
|
||||
)
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
pub use penpal_runtime::{
|
||||
self, xcm_config::RelayNetworkId as PenpalRelayNetworkId, ForeignAssetReserveData,
|
||||
};
|
||||
|
||||
mod genesis;
|
||||
pub use genesis::{genesis, PenpalAssetOwner, PenpalSudoAccount, ED, PARA_ID_A, PARA_ID_B};
|
||||
|
||||
// Bizinikiwi
|
||||
use pezframe_support::traits::OnInitialize;
|
||||
use pezsp_core::Encode;
|
||||
|
||||
// Pezcumulus
|
||||
use emulated_integration_tests_common::{
|
||||
impl_accounts_helpers_for_teyrchain, impl_assert_events_helpers_for_teyrchain,
|
||||
impl_assets_helpers_for_teyrchain, impl_foreign_assets_helpers_for_teyrchain,
|
||||
impl_xcm_helpers_for_teyrchain,
|
||||
impls::{NetworkId, Teyrchain},
|
||||
xcm_emulator::decl_test_teyrchains,
|
||||
AuraDigestProvider,
|
||||
};
|
||||
|
||||
// Pezkuwi
|
||||
use xcm::latest::{PEZKUWICHAIN_GENESIS_HASH, ZAGROS_GENESIS_HASH};
|
||||
|
||||
// Penpal Teyrchain declaration
|
||||
decl_test_teyrchains! {
|
||||
pub struct PenpalA {
|
||||
genesis = genesis(PARA_ID_A),
|
||||
on_init = {
|
||||
penpal_runtime::AuraExt::on_initialize(1);
|
||||
pezframe_support::assert_ok!(penpal_runtime::System::set_storage(
|
||||
penpal_runtime::RuntimeOrigin::root(),
|
||||
vec![(PenpalRelayNetworkId::key().to_vec(), NetworkId::ByGenesis(PEZKUWICHAIN_GENESIS_HASH).encode())],
|
||||
));
|
||||
},
|
||||
runtime = penpal_runtime,
|
||||
core = {
|
||||
XcmpMessageHandler: penpal_runtime::XcmpQueue,
|
||||
LocationToAccountId: penpal_runtime::xcm_config::LocationToAccountId,
|
||||
TeyrchainInfo: penpal_runtime::TeyrchainInfo,
|
||||
MessageOrigin: cumulus_primitives_core::AggregateMessageOrigin,
|
||||
DigestProvider: AuraDigestProvider,
|
||||
},
|
||||
pallets = {
|
||||
PezkuwiXcm: penpal_runtime::PezkuwiXcm,
|
||||
Assets: penpal_runtime::Assets,
|
||||
ForeignAssets: penpal_runtime::ForeignAssets,
|
||||
AssetConversion: penpal_runtime::AssetConversion,
|
||||
Balances: penpal_runtime::Balances,
|
||||
}
|
||||
},
|
||||
pub struct PenpalB {
|
||||
genesis = genesis(PARA_ID_B),
|
||||
on_init = {
|
||||
penpal_runtime::AuraExt::on_initialize(1);
|
||||
pezframe_support::assert_ok!(penpal_runtime::System::set_storage(
|
||||
penpal_runtime::RuntimeOrigin::root(),
|
||||
vec![(PenpalRelayNetworkId::key().to_vec(), NetworkId::ByGenesis(ZAGROS_GENESIS_HASH).encode())],
|
||||
));
|
||||
},
|
||||
runtime = penpal_runtime,
|
||||
core = {
|
||||
XcmpMessageHandler: penpal_runtime::XcmpQueue,
|
||||
LocationToAccountId: penpal_runtime::xcm_config::LocationToAccountId,
|
||||
TeyrchainInfo: penpal_runtime::TeyrchainInfo,
|
||||
MessageOrigin: cumulus_primitives_core::AggregateMessageOrigin,
|
||||
DigestProvider: AuraDigestProvider,
|
||||
},
|
||||
pallets = {
|
||||
PezkuwiXcm: penpal_runtime::PezkuwiXcm,
|
||||
Assets: penpal_runtime::Assets,
|
||||
ForeignAssets: penpal_runtime::ForeignAssets,
|
||||
AssetConversion: penpal_runtime::AssetConversion,
|
||||
Balances: penpal_runtime::Balances,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// Penpal implementation
|
||||
impl_accounts_helpers_for_teyrchain!(PenpalA);
|
||||
impl_accounts_helpers_for_teyrchain!(PenpalB);
|
||||
impl_assert_events_helpers_for_teyrchain!(PenpalA);
|
||||
impl_assert_events_helpers_for_teyrchain!(PenpalB);
|
||||
impl_assets_helpers_for_teyrchain!(PenpalA);
|
||||
impl_foreign_assets_helpers_for_teyrchain!(PenpalA, xcm::latest::Location, ForeignAssetReserveData);
|
||||
impl_assets_helpers_for_teyrchain!(PenpalB);
|
||||
impl_foreign_assets_helpers_for_teyrchain!(PenpalB, xcm::latest::Location, ForeignAssetReserveData);
|
||||
impl_xcm_helpers_for_teyrchain!(PenpalA);
|
||||
impl_xcm_helpers_for_teyrchain!(PenpalB);
|
||||
@@ -0,0 +1,96 @@
|
||||
[package]
|
||||
name = "emulated-integration-tests-common"
|
||||
version = "3.0.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license = "Apache-2.0"
|
||||
description = "Common resources for integration testing with xcm-emulator"
|
||||
homepage.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
codec = { workspace = true }
|
||||
hex-literal = { workspace = true }
|
||||
paste = { workspace = true, default-features = true }
|
||||
|
||||
# Bizinikiwi
|
||||
pezframe-support = { workspace = true, default-features = true }
|
||||
pezframe-system = { workspace = true, default-features = true }
|
||||
pezpallet-asset-conversion = { workspace = true, default-features = true }
|
||||
pezpallet-assets = { workspace = true, default-features = true }
|
||||
pezpallet-balances = { workspace = true, default-features = true }
|
||||
pezpallet-message-queue = { workspace = true, default-features = true }
|
||||
pezpallet-whitelist = { workspace = true, default-features = true }
|
||||
pezsc-consensus-grandpa = { workspace = true, default-features = true }
|
||||
pezsp-authority-discovery = { workspace = true, default-features = true }
|
||||
pezsp-consensus-babe = { workspace = true, default-features = true }
|
||||
pezsp-consensus-beefy = { workspace = true, default-features = true }
|
||||
pezsp-core = { workspace = true, default-features = true }
|
||||
pezsp-keyring = { workspace = true, default-features = true }
|
||||
pezsp-runtime = { workspace = true, default-features = true }
|
||||
|
||||
# Pezkuwi
|
||||
pezpallet-xcm = { features = [
|
||||
"test-utils",
|
||||
], workspace = true, default-features = true }
|
||||
pezkuwi-primitives = { workspace = true, default-features = true }
|
||||
pezkuwi-runtime-teyrchains = { workspace = true, default-features = true }
|
||||
pezkuwi-teyrchain-primitives = { workspace = true, default-features = true }
|
||||
xcm = { workspace = true, default-features = true }
|
||||
xcm-builder = { workspace = true, default-features = true }
|
||||
xcm-executor = { workspace = true, default-features = true }
|
||||
xcm-runtime-apis = { workspace = true, default-features = true }
|
||||
xcm-simulator = { workspace = true, default-features = true }
|
||||
|
||||
# Pezcumulus
|
||||
asset-test-utils = { workspace = true, default-features = true }
|
||||
pezcumulus-pezpallet-teyrchain-system = { workspace = true, default-features = true }
|
||||
pezcumulus-pezpallet-xcmp-queue = { workspace = true, default-features = true }
|
||||
pezcumulus-primitives-core = { workspace = true, default-features = true }
|
||||
teyrchains-common = { workspace = true, default-features = true }
|
||||
xcm-emulator = { workspace = true, default-features = true }
|
||||
|
||||
# Bridges
|
||||
bp-messages = { workspace = true, default-features = true }
|
||||
bp-xcm-bridge-hub = { workspace = true, default-features = true }
|
||||
pezpallet-bridge-messages = { workspace = true, default-features = true }
|
||||
pezpallet-xcm-bridge-hub = { workspace = true, default-features = true }
|
||||
|
||||
[features]
|
||||
runtime-benchmarks = [
|
||||
"asset-test-utils/runtime-benchmarks",
|
||||
"bp-messages/runtime-benchmarks",
|
||||
"bp-xcm-bridge-hub/runtime-benchmarks",
|
||||
"pezcumulus-pezpallet-teyrchain-system/runtime-benchmarks",
|
||||
"pezcumulus-pezpallet-xcmp-queue/runtime-benchmarks",
|
||||
"pezcumulus-primitives-core/runtime-benchmarks",
|
||||
"pezframe-support/runtime-benchmarks",
|
||||
"pezframe-system/runtime-benchmarks",
|
||||
"pezpallet-asset-conversion/runtime-benchmarks",
|
||||
"pezpallet-assets/runtime-benchmarks",
|
||||
"pezpallet-balances/runtime-benchmarks",
|
||||
"pezpallet-bridge-messages/runtime-benchmarks",
|
||||
"pezpallet-message-queue/runtime-benchmarks",
|
||||
"pezpallet-whitelist/runtime-benchmarks",
|
||||
"pezpallet-xcm-bridge-hub/runtime-benchmarks",
|
||||
"pezpallet-xcm/runtime-benchmarks",
|
||||
"pezkuwi-primitives/runtime-benchmarks",
|
||||
"pezkuwi-runtime-teyrchains/runtime-benchmarks",
|
||||
"pezkuwi-teyrchain-primitives/runtime-benchmarks",
|
||||
"pezsc-consensus-grandpa/runtime-benchmarks",
|
||||
"pezsp-authority-discovery/runtime-benchmarks",
|
||||
"pezsp-consensus-babe/runtime-benchmarks",
|
||||
"pezsp-consensus-beefy/runtime-benchmarks",
|
||||
"pezsp-keyring/runtime-benchmarks",
|
||||
"pezsp-runtime/runtime-benchmarks",
|
||||
"teyrchains-common/runtime-benchmarks",
|
||||
"xcm-builder/runtime-benchmarks",
|
||||
"xcm-emulator/runtime-benchmarks",
|
||||
"xcm-executor/runtime-benchmarks",
|
||||
"xcm-runtime-apis/runtime-benchmarks",
|
||||
"xcm-simulator/runtime-benchmarks",
|
||||
"xcm/runtime-benchmarks",
|
||||
]
|
||||
@@ -0,0 +1,999 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
pub use codec::{Decode, Encode};
|
||||
pub use paste;
|
||||
|
||||
pub use crate::{
|
||||
xcm_helpers::{xcm_transact_paid_execution, xcm_transact_unpaid_execution},
|
||||
PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD,
|
||||
};
|
||||
|
||||
// Bizinikiwi
|
||||
pub use pezframe_support::{
|
||||
assert_ok,
|
||||
pezsp_runtime::AccountId32,
|
||||
traits::fungibles::Inspect,
|
||||
weights::{Weight, WeightMeter},
|
||||
};
|
||||
pub use pezpallet_assets;
|
||||
pub use pezpallet_message_queue;
|
||||
pub use pezpallet_xcm;
|
||||
pub use xcm;
|
||||
|
||||
// Pezkuwi
|
||||
pub use pezkuwi_runtime_teyrchains::{
|
||||
dmp, hrmp,
|
||||
inclusion::{AggregateMessageOrigin, UmpQueueId},
|
||||
};
|
||||
pub use xcm::{
|
||||
prelude::{
|
||||
Asset, InteriorLocation, Location, OriginKind, Outcome, VersionedXcm, XcmError, XcmVersion,
|
||||
},
|
||||
DoubleEncoded,
|
||||
};
|
||||
|
||||
// Pezcumulus
|
||||
pub use cumulus_pallet_teyrchain_system;
|
||||
pub use cumulus_pallet_xcmp_queue;
|
||||
pub use cumulus_primitives_core::{
|
||||
relay_chain::HrmpChannelId, DmpMessageHandler, Junction, Junctions, NetworkId, ParaId,
|
||||
XcmpMessageHandler,
|
||||
};
|
||||
pub use teyrchains_common::{AccountId, Balance};
|
||||
pub use xcm_emulator::{
|
||||
assert_expected_events, bx, helpers::weight_within_threshold, BridgeLaneId, BridgeMessage,
|
||||
BridgeMessageDispatchError, BridgeMessageHandler, Chain, Network, RelayChain, TestExt,
|
||||
Teyrchain,
|
||||
};
|
||||
|
||||
// Bridges
|
||||
use bp_messages::{
|
||||
target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch},
|
||||
MessageKey, OutboundLaneData,
|
||||
};
|
||||
pub use bp_xcm_bridge_hub::XcmBridgeHubCall;
|
||||
use pezpallet_bridge_messages::{Config as BridgeMessagesConfig, LaneIdOf, OutboundLanes, Pallet};
|
||||
pub use pezpallet_bridge_messages::{
|
||||
Instance1 as BridgeMessagesInstance1, Instance2 as BridgeMessagesInstance2,
|
||||
Instance3 as BridgeMessagesInstance3,
|
||||
};
|
||||
use pezpallet_xcm_bridge_hub::XcmBlobMessageDispatchResult;
|
||||
|
||||
pub struct BridgeHubMessageHandler<S, SI, T, TI> {
|
||||
_marker: std::marker::PhantomData<(S, SI, T, TI)>,
|
||||
}
|
||||
|
||||
struct LaneIdWrapper<LaneId>(LaneId);
|
||||
impl<LaneId: Encode> From<LaneIdWrapper<LaneId>> for BridgeLaneId {
|
||||
fn from(lane_id: LaneIdWrapper<LaneId>) -> BridgeLaneId {
|
||||
lane_id.0.encode()
|
||||
}
|
||||
}
|
||||
impl<LaneId: Decode> From<BridgeLaneId> for LaneIdWrapper<LaneId> {
|
||||
fn from(id: BridgeLaneId) -> LaneIdWrapper<LaneId> {
|
||||
LaneIdWrapper(LaneId::decode(&mut &id[..]).expect("decodable"))
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, SI, T, TI> BridgeMessageHandler for BridgeHubMessageHandler<S, SI, T, TI>
|
||||
where
|
||||
S: BridgeMessagesConfig<SI>,
|
||||
SI: 'static,
|
||||
T: BridgeMessagesConfig<TI>,
|
||||
TI: 'static,
|
||||
<T as BridgeMessagesConfig<TI>>::InboundPayload: From<Vec<u8>>,
|
||||
<T as BridgeMessagesConfig<TI>>::MessageDispatch:
|
||||
MessageDispatch<DispatchLevelResult = XcmBlobMessageDispatchResult>,
|
||||
{
|
||||
fn get_source_outbound_messages() -> Vec<BridgeMessage> {
|
||||
// get the source active outbound lanes
|
||||
let active_outbound_lanes = OutboundLanes::<S, SI>::iter_keys();
|
||||
|
||||
let mut messages: Vec<BridgeMessage> = Default::default();
|
||||
|
||||
// collect messages from `OutboundMessages` for each active outbound lane in the source
|
||||
for lane in active_outbound_lanes {
|
||||
let latest_generated_nonce =
|
||||
OutboundLanes::<S, SI>::get(lane).unwrap().latest_generated_nonce;
|
||||
let latest_received_nonce =
|
||||
OutboundLanes::<S, SI>::get(lane).unwrap().latest_received_nonce;
|
||||
|
||||
(latest_received_nonce + 1..=latest_generated_nonce).for_each(|nonce| {
|
||||
let encoded_payload: Vec<u8> = Pallet::<S, SI>::outbound_message_data(lane, nonce)
|
||||
.expect("Bridge message does not exist")
|
||||
.into();
|
||||
let payload = Vec::<u8>::decode(&mut &encoded_payload[..])
|
||||
.expect("Decoding XCM message failed");
|
||||
let message = BridgeMessage { lane_id: LaneIdWrapper(lane).into(), nonce, payload };
|
||||
|
||||
messages.push(message);
|
||||
});
|
||||
}
|
||||
messages
|
||||
}
|
||||
|
||||
fn dispatch_target_inbound_message(
|
||||
message: BridgeMessage,
|
||||
) -> Result<(), BridgeMessageDispatchError> {
|
||||
type TargetMessageDispatch<T, I> = <T as BridgeMessagesConfig<I>>::MessageDispatch;
|
||||
type InboundPayload<T, I> = <T as BridgeMessagesConfig<I>>::InboundPayload;
|
||||
|
||||
let lane_id = LaneIdWrapper::from(message.lane_id).0;
|
||||
let nonce = message.nonce;
|
||||
let payload = Ok(From::from(message.payload));
|
||||
|
||||
// Directly dispatch outbound messages assuming everything is correct
|
||||
// and bypassing the `Relayers` and `InboundLane` logic
|
||||
let dispatch_result = TargetMessageDispatch::<T, TI>::dispatch(DispatchMessage {
|
||||
key: MessageKey { lane_id, nonce },
|
||||
data: DispatchMessageData::<InboundPayload<T, TI>> { payload },
|
||||
});
|
||||
|
||||
let result = match dispatch_result.dispatch_level_result {
|
||||
XcmBlobMessageDispatchResult::Dispatched => Ok(()),
|
||||
XcmBlobMessageDispatchResult::InvalidPayload => Err(BridgeMessageDispatchError(
|
||||
Box::new(XcmBlobMessageDispatchResult::InvalidPayload),
|
||||
)),
|
||||
XcmBlobMessageDispatchResult::NotDispatched(e) => Err(BridgeMessageDispatchError(
|
||||
Box::new(XcmBlobMessageDispatchResult::NotDispatched(e)),
|
||||
)),
|
||||
};
|
||||
result
|
||||
}
|
||||
|
||||
fn notify_source_message_delivery(lane_id: BridgeLaneId) {
|
||||
let lane_id: LaneIdOf<S, SI> = LaneIdWrapper::from(lane_id).0;
|
||||
let data = OutboundLanes::<S, SI>::get(lane_id).unwrap();
|
||||
let new_data = OutboundLaneData {
|
||||
oldest_unpruned_nonce: data.oldest_unpruned_nonce + 1,
|
||||
latest_received_nonce: data.latest_received_nonce + 1,
|
||||
..data
|
||||
};
|
||||
|
||||
OutboundLanes::<S, SI>::insert(lane_id, new_data);
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_accounts_helpers_for_relay_chain {
|
||||
( $chain:ident ) => {
|
||||
$crate::impls::paste::paste! {
|
||||
impl<N: $crate::impls::Network> $chain<N> {
|
||||
/// Fund a set of accounts with a balance
|
||||
pub fn fund_accounts(accounts: Vec<($crate::impls::AccountId, $crate::impls::Balance)>) {
|
||||
<Self as $crate::impls::TestExt>::execute_with(|| {
|
||||
for account in accounts {
|
||||
let who = account.0;
|
||||
let actual = <Self as [<$chain RelayPallet>]>::Balances::free_balance(&who);
|
||||
let actual = actual.saturating_add(<Self as [<$chain RelayPallet>]>::Balances::reserved_balance(&who));
|
||||
|
||||
$crate::impls::assert_ok!(<Self as [<$chain RelayPallet>]>::Balances::force_set_balance(
|
||||
<Self as $crate::impls::Chain>::RuntimeOrigin::root(),
|
||||
who.into(),
|
||||
actual.saturating_add(account.1),
|
||||
));
|
||||
}
|
||||
});
|
||||
}
|
||||
/// Fund a sovereign account based on its Teyrchain Id
|
||||
pub fn fund_para_sovereign(amount: $crate::impls::Balance, para_id: $crate::impls::ParaId) -> $crate::impls::AccountId32 {
|
||||
let sovereign_account = <Self as $crate::impls::RelayChain>::sovereign_account_id_of_child_para(para_id);
|
||||
Self::fund_accounts(vec![(sovereign_account.clone(), amount)]);
|
||||
sovereign_account
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_assert_events_helpers_for_relay_chain {
|
||||
( $chain:ident ) => {
|
||||
$crate::impls::paste::paste! {
|
||||
type [<$chain RuntimeEvent>]<N> = <$chain<N> as $crate::impls::Chain>::RuntimeEvent;
|
||||
|
||||
impl<N: $crate::impls::Network> $chain<N> {
|
||||
/// Asserts a dispatchable is completely executed and XCM sent
|
||||
pub fn assert_xcm_pallet_attempted_complete(expected_weight: Option<$crate::impls::Weight>) {
|
||||
$crate::impls::assert_expected_events!(
|
||||
Self,
|
||||
vec![
|
||||
[<$chain RuntimeEvent>]::<N>::XcmPallet(
|
||||
$crate::impls::pezpallet_xcm::Event::Attempted { outcome: $crate::impls::Outcome::Complete { used: weight } }
|
||||
) => {
|
||||
weight: $crate::impls::weight_within_threshold(
|
||||
($crate::impls::REF_TIME_THRESHOLD, $crate::impls::PROOF_SIZE_THRESHOLD),
|
||||
expected_weight.unwrap_or(*weight),
|
||||
*weight
|
||||
),
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/// Asserts a dispatchable is incompletely executed and XCM sent
|
||||
pub fn assert_xcm_pallet_attempted_incomplete(
|
||||
expected_weight: Option<$crate::impls::Weight>,
|
||||
expected_error: Option<$crate::impls::XcmError>,
|
||||
) {
|
||||
$crate::impls::assert_expected_events!(
|
||||
Self,
|
||||
vec![
|
||||
// Dispatchable is properly executed and XCM message sent
|
||||
[<$chain RuntimeEvent>]::<N>::XcmPallet(
|
||||
$crate::impls::pezpallet_xcm::Event::Attempted { outcome: $crate::impls::Outcome::Incomplete { used: weight, error: $crate::impls::xcm::prelude::InstructionError { error, .. } } }
|
||||
) => {
|
||||
weight: $crate::impls::weight_within_threshold(
|
||||
($crate::impls::REF_TIME_THRESHOLD, $crate::impls::PROOF_SIZE_THRESHOLD),
|
||||
expected_weight.unwrap_or(*weight),
|
||||
*weight
|
||||
),
|
||||
error: *error == expected_error.unwrap_or((*error).into()).into(),
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/// Asserts an XCM program is sent.
|
||||
pub fn assert_xcm_pallet_sent() {
|
||||
$crate::impls::assert_expected_events!(
|
||||
Self,
|
||||
vec![
|
||||
[<$chain RuntimeEvent>]::<N>::XcmPallet($crate::impls::pezpallet_xcm::Event::Sent { .. }) => {},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/// Asserts an XCM program from a System Teyrchain is successfully received and
|
||||
/// processed within expectations.
|
||||
pub fn assert_ump_queue_processed(
|
||||
expected_success: bool,
|
||||
expected_id: Option<$crate::impls::ParaId>,
|
||||
expected_weight: Option<$crate::impls::Weight>,
|
||||
) {
|
||||
$crate::impls::assert_expected_events!(
|
||||
Self,
|
||||
vec![
|
||||
// XCM is successfully received and processed
|
||||
[<$chain RuntimeEvent>]::<N>::MessageQueue($crate::impls::pezpallet_message_queue::Event::Processed {
|
||||
origin: $crate::impls::AggregateMessageOrigin::Ump($crate::impls::UmpQueueId::Para(id)),
|
||||
weight_used,
|
||||
success,
|
||||
..
|
||||
}) => {
|
||||
id: *id == expected_id.unwrap_or(*id),
|
||||
weight_used: $crate::impls::weight_within_threshold(
|
||||
($crate::impls::REF_TIME_THRESHOLD, $crate::impls::PROOF_SIZE_THRESHOLD),
|
||||
expected_weight.unwrap_or(*weight_used),
|
||||
*weight_used
|
||||
),
|
||||
success: *success == expected_success,
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_hrmp_channels_helpers_for_relay_chain {
|
||||
( $chain:ident ) => {
|
||||
$crate::impls::paste::paste! {
|
||||
impl<N: $crate::impls::Network> $chain<N> {
|
||||
/// Init open channel request with another Teyrchain
|
||||
pub fn init_open_channel_call(
|
||||
recipient_para_id: $crate::impls::ParaId,
|
||||
max_capacity: u32,
|
||||
max_message_size: u32,
|
||||
) -> $crate::impls::DoubleEncoded<()> {
|
||||
use $crate::impls::Encode;
|
||||
|
||||
<Self as $crate::impls::Chain>::RuntimeCall::Hrmp($crate::impls::hrmp::Call::<
|
||||
<Self as $crate::impls::Chain>::Runtime,
|
||||
>::hrmp_init_open_channel {
|
||||
recipient: recipient_para_id,
|
||||
proposed_max_capacity: max_capacity,
|
||||
proposed_max_message_size: max_message_size,
|
||||
})
|
||||
.encode()
|
||||
.into()
|
||||
}
|
||||
/// Recipient Teyrchain accept the open request from another Teyrchain
|
||||
pub fn accept_open_channel_call(sender_para_id: $crate::impls::ParaId) -> $crate::impls::DoubleEncoded<()> {
|
||||
use $crate::impls::Encode;
|
||||
|
||||
<Self as $crate::impls::Chain>::RuntimeCall::Hrmp($crate::impls::hrmp::Call::<
|
||||
<Self as $crate::impls::Chain>::Runtime,
|
||||
>::hrmp_accept_open_channel {
|
||||
sender: sender_para_id,
|
||||
})
|
||||
.encode()
|
||||
.into()
|
||||
}
|
||||
|
||||
/// A root origin force to open a channel between two Teyrchains
|
||||
pub fn force_process_hrmp_open(sender: $crate::impls::ParaId, recipient: $crate::impls::ParaId) {
|
||||
use $crate::impls::Chain;
|
||||
|
||||
<Self as $crate::impls::TestExt>::execute_with(|| {
|
||||
let relay_root_origin = <Self as Chain>::RuntimeOrigin::root();
|
||||
|
||||
// Force process HRMP open channel requests without waiting for the next session
|
||||
$crate::impls::assert_ok!(<Self as [<$chain RelayPallet>]>::Hrmp::force_process_hrmp_open(
|
||||
relay_root_origin,
|
||||
0
|
||||
));
|
||||
|
||||
let channel_id = $crate::impls::HrmpChannelId { sender, recipient };
|
||||
|
||||
let hrmp_channel_exist = $crate::impls::hrmp::HrmpChannels::<
|
||||
<Self as Chain>::Runtime,
|
||||
>::contains_key(&channel_id);
|
||||
|
||||
// Check the HRMP channel has been successfully registered
|
||||
assert!(hrmp_channel_exist)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_send_transact_helpers_for_relay_chain {
|
||||
( $chain:ident ) => {
|
||||
$crate::impls::paste::paste! {
|
||||
impl<N: $crate::impls::Network> $chain<N> {
|
||||
/// A root origin (as governance) sends `xcm::Transact` with `UnpaidExecution` and encoded `call` to child teyrchain.
|
||||
pub fn send_unpaid_transact_to_teyrchain_as_root(
|
||||
recipient: $crate::impls::ParaId,
|
||||
call: $crate::impls::DoubleEncoded<()>
|
||||
) {
|
||||
use $crate::impls::{bx, Chain, RelayChain};
|
||||
|
||||
<Self as $crate::impls::TestExt>::execute_with(|| {
|
||||
let root_origin = <Self as Chain>::RuntimeOrigin::root();
|
||||
let destination: $crate::impls::Location = <Self as RelayChain>::child_location_of(recipient);
|
||||
let xcm = $crate::impls::xcm_transact_unpaid_execution(call, $crate::impls::OriginKind::Superuser);
|
||||
|
||||
$crate::impls::dmp::Pallet::<<Self as $crate::impls::Chain>::Runtime>::make_teyrchain_reachable(recipient);
|
||||
|
||||
// Send XCM `Transact`
|
||||
$crate::impls::assert_ok!(<Self as [<$chain RelayPallet>]>::XcmPallet::send(
|
||||
root_origin,
|
||||
bx!(destination.into()),
|
||||
bx!(xcm),
|
||||
));
|
||||
Self::assert_xcm_pallet_sent();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_accounts_helpers_for_teyrchain {
|
||||
( $chain:ident ) => {
|
||||
$crate::impls::paste::paste! {
|
||||
impl<N: $crate::impls::Network> $chain<N> {
|
||||
/// Fund a set of accounts with a balance
|
||||
pub fn fund_accounts(accounts: Vec<($crate::impls::AccountId, $crate::impls::Balance)>) {
|
||||
<Self as $crate::impls::TestExt>::execute_with(|| {
|
||||
for account in accounts {
|
||||
let who = account.0;
|
||||
let actual = <Self as [<$chain ParaPallet>]>::Balances::free_balance(&who);
|
||||
let actual = actual.saturating_add(<Self as [<$chain ParaPallet>]>::Balances::reserved_balance(&who));
|
||||
|
||||
$crate::impls::assert_ok!(<Self as [<$chain ParaPallet>]>::Balances::force_set_balance(
|
||||
<Self as $crate::impls::Chain>::RuntimeOrigin::root(),
|
||||
who.into(),
|
||||
actual.saturating_add(account.1),
|
||||
));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Fund a sovereign account of sibling para.
|
||||
pub fn fund_para_sovereign(sibling_para_id: $crate::impls::ParaId, balance: $crate::impls::Balance) {
|
||||
let sibling_location = Self::sibling_location_of(sibling_para_id);
|
||||
let sovereign_account = Self::sovereign_account_id_of(sibling_location);
|
||||
Self::fund_accounts(vec![(sovereign_account.into(), balance)])
|
||||
}
|
||||
|
||||
/// Return local sovereign account of `para_id` on other `network_id`
|
||||
pub fn sovereign_account_of_teyrchain_on_other_global_consensus(
|
||||
network_id: $crate::impls::NetworkId,
|
||||
para_id: $crate::impls::ParaId,
|
||||
) -> $crate::impls::AccountId {
|
||||
let remote_location = $crate::impls::Location::new(
|
||||
2,
|
||||
[
|
||||
$crate::impls::Junction::GlobalConsensus(network_id),
|
||||
$crate::impls::Junction::Teyrchain(para_id.into()),
|
||||
],
|
||||
);
|
||||
<Self as $crate::impls::TestExt>::execute_with(|| {
|
||||
Self::sovereign_account_id_of(remote_location)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_assert_events_helpers_for_teyrchain {
|
||||
( $chain:ident ) => {
|
||||
$crate::impls::paste::paste! {
|
||||
type [<$chain RuntimeEvent>]<N> = <$chain<N> as $crate::impls::Chain>::RuntimeEvent;
|
||||
|
||||
impl<N: $crate::impls::Network> $chain<N> {
|
||||
/// Asserts a dispatchable is completely executed and XCM sent
|
||||
pub fn assert_xcm_pallet_attempted_complete(expected_weight: Option<$crate::impls::Weight>) {
|
||||
$crate::impls::assert_expected_events!(
|
||||
Self,
|
||||
vec![
|
||||
[<$chain RuntimeEvent>]::<N>::PezkuwiXcm(
|
||||
$crate::impls::pezpallet_xcm::Event::Attempted { outcome: $crate::impls::Outcome::Complete { used: weight } }
|
||||
) => {
|
||||
weight: $crate::impls::weight_within_threshold(
|
||||
($crate::impls::REF_TIME_THRESHOLD, $crate::impls::PROOF_SIZE_THRESHOLD),
|
||||
expected_weight.unwrap_or(*weight),
|
||||
*weight
|
||||
),
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/// Asserts a dispatchable is incompletely executed and XCM sent
|
||||
pub fn assert_xcm_pallet_attempted_incomplete(
|
||||
expected_weight: Option<$crate::impls::Weight>,
|
||||
expected_error: Option<$crate::impls::XcmError>,
|
||||
) {
|
||||
$crate::impls::assert_expected_events!(
|
||||
Self,
|
||||
vec![
|
||||
// Dispatchable is properly executed and XCM message sent
|
||||
[<$chain RuntimeEvent>]::<N>::PezkuwiXcm(
|
||||
$crate::impls::pezpallet_xcm::Event::Attempted { outcome: $crate::impls::Outcome::Incomplete { used: weight, error: $crate::impls::xcm::prelude::InstructionError { error, .. } } }
|
||||
) => {
|
||||
weight: $crate::impls::weight_within_threshold(
|
||||
($crate::impls::REF_TIME_THRESHOLD, $crate::impls::PROOF_SIZE_THRESHOLD),
|
||||
expected_weight.unwrap_or(*weight),
|
||||
*weight
|
||||
),
|
||||
error: *error == expected_error.unwrap_or((*error).into()).into(),
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/// Asserts a dispatchable throws and error when trying to be sent
|
||||
pub fn assert_xcm_pallet_attempted_error(expected_error: Option<$crate::impls::XcmError>) {
|
||||
$crate::impls::assert_expected_events!(
|
||||
Self,
|
||||
vec![
|
||||
// Execution fails in the origin with `Barrier`
|
||||
[<$chain RuntimeEvent>]::<N>::PezkuwiXcm(
|
||||
$crate::impls::pezpallet_xcm::Event::Attempted { outcome: $crate::impls::Outcome::Error($crate::impls::xcm::prelude::InstructionError { error, .. }) }
|
||||
) => {
|
||||
error: *error == expected_error.unwrap_or((*error).into()).into(),
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/// Asserts a XCM message is sent
|
||||
pub fn assert_xcm_pallet_sent() {
|
||||
$crate::impls::assert_expected_events!(
|
||||
Self,
|
||||
vec![
|
||||
[<$chain RuntimeEvent>]::<N>::PezkuwiXcm($crate::impls::pezpallet_xcm::Event::Sent { .. }) => {},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/// Asserts a XCM message is sent to Relay Chain
|
||||
pub fn assert_teyrchain_system_ump_sent() {
|
||||
$crate::impls::assert_expected_events!(
|
||||
Self,
|
||||
vec![
|
||||
[<$chain RuntimeEvent>]::<N>::TeyrchainSystem(
|
||||
$crate::impls::cumulus_pallet_teyrchain_system::Event::UpwardMessageSent { .. }
|
||||
) => {},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/// Asserts a XCM from Relay Chain is completely executed
|
||||
pub fn assert_dmp_queue_complete(expected_weight: Option<$crate::impls::Weight>) {
|
||||
$crate::impls::assert_expected_events!(
|
||||
Self,
|
||||
vec![
|
||||
[<$chain RuntimeEvent>]::<N>::MessageQueue($crate::impls::pezpallet_message_queue::Event::Processed {
|
||||
success: true, weight_used: weight, ..
|
||||
}) => {
|
||||
weight: $crate::impls::weight_within_threshold(
|
||||
($crate::impls::REF_TIME_THRESHOLD, $crate::impls::PROOF_SIZE_THRESHOLD),
|
||||
expected_weight.unwrap_or(*weight),
|
||||
*weight
|
||||
),
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/// Asserts a XCM from Relay Chain is incompletely executed
|
||||
pub fn assert_dmp_queue_incomplete(
|
||||
expected_weight: Option<$crate::impls::Weight>,
|
||||
) {
|
||||
$crate::impls::assert_expected_events!(
|
||||
Self,
|
||||
vec![
|
||||
[<$chain RuntimeEvent>]::<N>::MessageQueue($crate::impls::pezpallet_message_queue::Event::Processed {
|
||||
success: false, weight_used: weight, ..
|
||||
}) => {
|
||||
weight: $crate::impls::weight_within_threshold(
|
||||
($crate::impls::REF_TIME_THRESHOLD, $crate::impls::PROOF_SIZE_THRESHOLD),
|
||||
expected_weight.unwrap_or(*weight),
|
||||
*weight
|
||||
),
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/// Asserts a XCM from Relay Chain is executed with error
|
||||
pub fn assert_dmp_queue_error() {
|
||||
$crate::impls::assert_expected_events!(
|
||||
Self,
|
||||
vec![
|
||||
[<$chain RuntimeEvent>]::<N>::MessageQueue($crate::impls::pezpallet_message_queue::Event::ProcessingFailed {
|
||||
..
|
||||
}) => {
|
||||
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/// Asserts a XCM from another Teyrchain is completely executed
|
||||
pub fn assert_xcmp_queue_success(expected_weight: Option<$crate::impls::Weight>) {
|
||||
$crate::impls::assert_expected_events!(
|
||||
Self,
|
||||
vec![
|
||||
[<$chain RuntimeEvent>]::<N>::MessageQueue($crate::impls::pezpallet_message_queue::Event::Processed { success: true, weight_used: weight, .. }
|
||||
) => {
|
||||
weight: $crate::impls::weight_within_threshold(
|
||||
($crate::impls::REF_TIME_THRESHOLD, $crate::impls::PROOF_SIZE_THRESHOLD),
|
||||
expected_weight.unwrap_or(*weight),
|
||||
*weight
|
||||
),
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_assets_helpers_for_system_teyrchain {
|
||||
( $chain:ident, $relay_chain:ident ) => {
|
||||
$crate::impls::paste::paste! {
|
||||
impl<N: $crate::impls::Network> $chain<N> {
|
||||
/// Returns the encoded call for `force_create` from the assets pallet
|
||||
pub fn force_create_asset_call(
|
||||
asset_id: u32,
|
||||
owner: $crate::impls::AccountId,
|
||||
is_sufficient: bool,
|
||||
min_balance: $crate::impls::Balance,
|
||||
) -> $crate::impls::DoubleEncoded<()> {
|
||||
use $crate::impls::{Chain, Encode};
|
||||
|
||||
<Self as Chain>::RuntimeCall::Assets($crate::impls::pezpallet_assets::Call::<
|
||||
<Self as Chain>::Runtime,
|
||||
$crate::impls::pezpallet_assets::Instance1,
|
||||
>::force_create {
|
||||
id: asset_id.into(),
|
||||
owner: owner.into(),
|
||||
is_sufficient,
|
||||
min_balance,
|
||||
})
|
||||
.encode()
|
||||
.into()
|
||||
}
|
||||
|
||||
/// Returns a `VersionedXcm` for `force_create` from the assets pallet
|
||||
pub fn force_create_asset_xcm(
|
||||
origin_kind: $crate::impls::OriginKind,
|
||||
asset_id: u32,
|
||||
owner: $crate::impls::AccountId,
|
||||
is_sufficient: bool,
|
||||
min_balance: $crate::impls::Balance,
|
||||
) -> $crate::impls::VersionedXcm<()> {
|
||||
let call = Self::force_create_asset_call(asset_id, owner, is_sufficient, min_balance);
|
||||
$crate::impls::xcm_transact_unpaid_execution(call, origin_kind)
|
||||
}
|
||||
|
||||
/// Force create and mint assets making use of the assets pallet
|
||||
pub fn force_create_and_mint_asset(
|
||||
id: u32,
|
||||
min_balance: u128,
|
||||
is_sufficient: bool,
|
||||
asset_owner: $crate::impls::AccountId,
|
||||
dmp_weight_threshold: Option<$crate::impls::Weight>,
|
||||
amount_to_mint: u128,
|
||||
) {
|
||||
use $crate::impls::Chain;
|
||||
|
||||
// Force create asset
|
||||
Self::force_create_asset_from_relay_as_root(
|
||||
id,
|
||||
min_balance,
|
||||
is_sufficient,
|
||||
asset_owner.clone(),
|
||||
dmp_weight_threshold
|
||||
);
|
||||
|
||||
// Mint asset for System Teyrchain's sender
|
||||
let signed_origin = <Self as Chain>::RuntimeOrigin::signed(asset_owner.clone());
|
||||
Self::mint_asset(signed_origin, id, asset_owner, amount_to_mint);
|
||||
}
|
||||
|
||||
/// Relay Chain sends `Transact` instruction with `force_create_asset` to Teyrchain with `Assets` instance of `pezpallet_assets` .
|
||||
pub fn force_create_asset_from_relay_as_root(
|
||||
id: u32,
|
||||
min_balance: u128,
|
||||
is_sufficient: bool,
|
||||
asset_owner: $crate::impls::AccountId,
|
||||
dmp_weight_threshold: Option<$crate::impls::Weight>,
|
||||
) {
|
||||
use $crate::impls::{Teyrchain, Inspect, TestExt};
|
||||
|
||||
<$relay_chain<N>>::send_unpaid_transact_to_teyrchain_as_root(
|
||||
Self::para_id(),
|
||||
Self::force_create_asset_call(id, asset_owner.clone(), is_sufficient, min_balance),
|
||||
);
|
||||
|
||||
// Receive XCM message in Assets Teyrchain
|
||||
Self::execute_with(|| {
|
||||
type RuntimeEvent<N> = <$chain<N> as $crate::impls::Chain>::RuntimeEvent;
|
||||
|
||||
Self::assert_dmp_queue_complete(dmp_weight_threshold);
|
||||
|
||||
$crate::impls::assert_expected_events!(
|
||||
Self,
|
||||
vec![
|
||||
RuntimeEvent::<N>::Assets($crate::impls::pezpallet_assets::Event::ForceCreated { asset_id, owner }) => {
|
||||
asset_id: *asset_id == id,
|
||||
owner: *owner == asset_owner,
|
||||
},
|
||||
]
|
||||
);
|
||||
|
||||
assert!(<Self as [<$chain ParaPallet>]>::Assets::asset_exists(id.clone().into()));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_assets_helpers_for_teyrchain {
|
||||
($chain:ident) => {
|
||||
$crate::impls::paste::paste! {
|
||||
impl<N: $crate::impls::Network> $chain<N> {
|
||||
/// 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::pezpallet_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::pezpallet_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::pezpallet_assets::Call::<
|
||||
<Self as Chain>::Runtime,
|
||||
$crate::impls::pezpallet_assets::Instance1,
|
||||
>::create {
|
||||
id: asset_id.into(),
|
||||
min_balance,
|
||||
admin: admin.into(),
|
||||
})
|
||||
.encode()
|
||||
.into()
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_foreign_assets_helpers_for_teyrchain {
|
||||
($chain:ident, $asset_id_type:ty, $reserve_data_type:ty) => {
|
||||
$crate::impls::paste::paste! {
|
||||
impl<N: $crate::impls::Network> $chain<N> {
|
||||
/// Create foreign assets using sudo `ForeignAssets::force_create()`
|
||||
pub fn force_create_foreign_asset(
|
||||
id: $asset_id_type,
|
||||
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>]>::ForeignAssets::force_create(
|
||||
sudo_origin,
|
||||
id.clone(),
|
||||
owner.clone().into(),
|
||||
is_sufficient,
|
||||
min_balance,
|
||||
)
|
||||
);
|
||||
assert!(<Self as [<$chain ParaPallet>]>::ForeignAssets::asset_exists(id.clone()));
|
||||
type RuntimeEvent<N> = <$chain<N> as $crate::impls::Chain>::RuntimeEvent;
|
||||
$crate::impls::assert_expected_events!(
|
||||
Self,
|
||||
vec![
|
||||
RuntimeEvent::<N>::ForeignAssets(
|
||||
$crate::impls::pezpallet_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_foreign_asset(signed_origin, id.clone(), beneficiary, amount);
|
||||
}
|
||||
}
|
||||
|
||||
/// Set reserves for foreign asset using the asset's `owner` account.
|
||||
pub fn set_foreign_asset_reserves(
|
||||
id: $asset_id_type,
|
||||
owner: $crate::impls::AccountId,
|
||||
reserves: Vec<$reserve_data_type>,
|
||||
) {
|
||||
use $crate::impls::Inspect;
|
||||
let owner_origin =
|
||||
<$chain<N> as $crate::impls::Chain>::RuntimeOrigin::signed(owner.clone());
|
||||
<Self as $crate::impls::TestExt>::execute_with(|| {
|
||||
$crate::impls::assert_ok!(
|
||||
<Self as [<$chain ParaPallet>]>::ForeignAssets::set_reserves(
|
||||
owner_origin,
|
||||
id.clone(),
|
||||
reserves,
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/// Mint assets making use of the ForeignAssets pezpallet-assets instance
|
||||
pub fn mint_foreign_asset(
|
||||
signed_origin: <Self as $crate::impls::Chain>::RuntimeOrigin,
|
||||
id: $asset_id_type,
|
||||
beneficiary: $crate::impls::AccountId,
|
||||
amount_to_mint: u128,
|
||||
) {
|
||||
<Self as $crate::impls::TestExt>::execute_with(|| {
|
||||
$crate::impls::assert_ok!(<Self as [<$chain ParaPallet>]>::ForeignAssets::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>::ForeignAssets(
|
||||
$crate::impls::pezpallet_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 foreign assets pallet
|
||||
pub fn create_foreign_asset_call(
|
||||
asset_id: $asset_id_type,
|
||||
min_balance: $crate::impls::Balance,
|
||||
admin: $crate::impls::AccountId,
|
||||
) -> $crate::impls::DoubleEncoded<()> {
|
||||
use $crate::impls::{Chain, Encode};
|
||||
|
||||
<Self as Chain>::RuntimeCall::ForeignAssets($crate::impls::pezpallet_assets::Call::<
|
||||
<Self as Chain>::Runtime,
|
||||
$crate::impls::pezpallet_assets::Instance2,
|
||||
>::create {
|
||||
id: asset_id.into(),
|
||||
min_balance,
|
||||
admin: admin.into(),
|
||||
})
|
||||
.encode()
|
||||
.into()
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_xcm_helpers_for_teyrchain {
|
||||
( $chain:ident ) => {
|
||||
$crate::impls::paste::paste! {
|
||||
impl<N: $crate::impls::Network> $chain<N> {
|
||||
/// Set XCM version for destination.
|
||||
pub fn force_xcm_version(dest: $crate::impls::Location, version: $crate::impls::XcmVersion) {
|
||||
<Self as $crate::impls::TestExt>::execute_with(|| {
|
||||
$crate::impls::assert_ok!(<Self as [<$chain ParaPallet>]>::PezkuwiXcm::force_xcm_version(
|
||||
<Self as $crate::impls::Chain>::RuntimeOrigin::root(),
|
||||
$crate::impls::bx!(dest),
|
||||
version,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
/// Set default/safe XCM version for runtime.
|
||||
pub fn force_default_xcm_version(version: Option<$crate::impls::XcmVersion>) {
|
||||
<Self as $crate::impls::TestExt>::execute_with(|| {
|
||||
$crate::impls::assert_ok!(<Self as [<$chain ParaPallet>]>::PezkuwiXcm::force_default_xcm_version(
|
||||
<Self as $crate::impls::Chain>::RuntimeOrigin::root(),
|
||||
version,
|
||||
));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_bridge_helpers_for_chain {
|
||||
( $chain:ident, $pallet:ident, $pezpallet_xcm:ident, $runtime_call_wrapper:path ) => {
|
||||
$crate::impls::paste::paste! {
|
||||
impl<N: $crate::impls::Network> $chain<N> {
|
||||
/// Open bridge with `dest`.
|
||||
pub fn open_bridge(
|
||||
bridge_location: $crate::impls::Location,
|
||||
bridge_destination_universal_location: $crate::impls::InteriorLocation,
|
||||
maybe_paid: Option<($crate::impls::Asset, $crate::impls::AccountId)>
|
||||
) {
|
||||
<Self as $crate::impls::TestExt>::execute_with(|| {
|
||||
use $crate::impls::{bx, Chain};
|
||||
use $crate::impls::XcmBridgeHubCall;
|
||||
use $crate::impls::Encode;
|
||||
|
||||
// important to use `root` and `OriginKind::Xcm`
|
||||
let root_origin = <Self as Chain>::RuntimeOrigin::root();
|
||||
|
||||
// construct call
|
||||
let call: $crate::impls::DoubleEncoded<()> = $runtime_call_wrapper(XcmBridgeHubCall::open_bridge {
|
||||
bridge_destination_universal_location: bx!(
|
||||
bridge_destination_universal_location.clone().into()
|
||||
)
|
||||
}).encode().into();
|
||||
|
||||
let xcm = if let Some((fee_asset, beneficiary)) = maybe_paid {
|
||||
$crate::impls::xcm_transact_paid_execution(call, $crate::impls::OriginKind::Xcm, fee_asset, beneficiary)
|
||||
} else {
|
||||
$crate::impls::xcm_transact_unpaid_execution(call, $crate::impls::OriginKind::Xcm)
|
||||
};
|
||||
|
||||
// Send XCM `Transact` with `open_bridge` call
|
||||
$crate::impls::assert_ok!(<Self as [<$chain $pallet>]>::$pezpallet_xcm::send(
|
||||
root_origin,
|
||||
bx!(bridge_location.into()),
|
||||
bx!(xcm),
|
||||
));
|
||||
Self::assert_xcm_pallet_sent();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
pub mod impls;
|
||||
pub mod macros;
|
||||
pub mod xcm_helpers;
|
||||
|
||||
use codec::Encode;
|
||||
use cumulus_primitives_core::relay_chain::Slot;
|
||||
pub use xcm_emulator;
|
||||
pub use xcm_simulator;
|
||||
|
||||
// Bizinikiwi
|
||||
use pezframe_support::parameter_types;
|
||||
use pezsc_consensus_grandpa::AuthorityId as GrandpaId;
|
||||
use pezsp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
|
||||
use pezsp_consensus_babe::AuthorityId as BabeId;
|
||||
use pezsp_consensus_beefy::ecdsa_crypto::AuthorityId as BeefyId;
|
||||
use pezsp_core::storage::Storage;
|
||||
use pezsp_keyring::{Ed25519Keyring, Sr25519Keyring};
|
||||
use pezsp_runtime::{traits::AccountIdConversion, BuildStorage, Digest, DigestItem};
|
||||
|
||||
// Pezkuwi
|
||||
use pezkuwi_runtime_teyrchains::configuration::HostConfiguration;
|
||||
use pezkuwi_teyrchain_primitives::primitives::Sibling;
|
||||
use teyrchains_common::BlockNumber;
|
||||
|
||||
// Pezcumulus
|
||||
use pezkuwi_primitives::{AssignmentId, ValidatorId};
|
||||
use pezsp_runtime::traits::Convert;
|
||||
use teyrchains_common::{AccountId, AuraId};
|
||||
use xcm_emulator::{RelayBlockNumber, AURA_ENGINE_ID};
|
||||
|
||||
pub const XCM_V2: u32 = 2;
|
||||
pub const XCM_V3: u32 = 3;
|
||||
pub const XCM_V4: u32 = 4;
|
||||
pub const XCM_V5: u32 = 5;
|
||||
pub const REF_TIME_THRESHOLD: u64 = 33;
|
||||
pub const PROOF_SIZE_THRESHOLD: u64 = 33;
|
||||
|
||||
/// The default XCM version to set in genesis config.
|
||||
pub const SAFE_XCM_VERSION: u32 = xcm::prelude::XCM_VERSION;
|
||||
|
||||
// (trust-backed) Asset registered on AH and reserve-transferred between Teyrchain and AH
|
||||
pub const RESERVABLE_ASSET_ID: u32 = 1;
|
||||
// ForeignAsset registered on AH and teleported between Penpal and AH
|
||||
pub const TELEPORTABLE_ASSET_ID: u32 = 2;
|
||||
|
||||
// USDT registered on AH as (trust-backed) Asset and reserve-transferred between Teyrchain and AH
|
||||
pub const USDT_ID: u32 = 1984;
|
||||
|
||||
pub const PENPAL_A_ID: u32 = 2000;
|
||||
pub const PENPAL_B_ID: u32 = 2001;
|
||||
pub const ASSET_HUB_PEZKUWICHAIN_ID: u32 = 1000;
|
||||
pub const ASSET_HUB_ZAGROS_ID: u32 = 1000;
|
||||
pub const ASSETS_PALLET_ID: u8 = 50;
|
||||
|
||||
pub struct AuraDigestProvider {}
|
||||
|
||||
impl Convert<(BlockNumber, RelayBlockNumber), Digest> for AuraDigestProvider {
|
||||
fn convert((_, relay_block_number): (BlockNumber, RelayBlockNumber)) -> Digest {
|
||||
let slot: Slot = (relay_block_number as u64).into();
|
||||
let mut digest = Digest::default();
|
||||
digest.logs.push(DigestItem::PreRuntime(AURA_ENGINE_ID, slot.encode()));
|
||||
digest
|
||||
}
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub PenpalALocation: xcm::v5::Location
|
||||
= xcm::v5::Location::new(1, [xcm::v5::Junction::Teyrchain(PENPAL_A_ID)]);
|
||||
pub PenpalBLocation: xcm::v5::Location
|
||||
= xcm::v5::Location::new(1, [xcm::v5::Junction::Teyrchain(PENPAL_B_ID)]);
|
||||
pub PenpalATeleportableAssetLocation: xcm::v5::Location
|
||||
= xcm::v5::Location::new(1, [
|
||||
xcm::v5::Junction::Teyrchain(PENPAL_A_ID),
|
||||
xcm::v5::Junction::PalletInstance(ASSETS_PALLET_ID),
|
||||
xcm::v5::Junction::GeneralIndex(TELEPORTABLE_ASSET_ID.into()),
|
||||
]
|
||||
);
|
||||
pub PenpalBTeleportableAssetLocation: xcm::v5::Location
|
||||
= xcm::v5::Location::new(1, [
|
||||
xcm::v5::Junction::Teyrchain(PENPAL_B_ID),
|
||||
xcm::v5::Junction::PalletInstance(ASSETS_PALLET_ID),
|
||||
xcm::v5::Junction::GeneralIndex(TELEPORTABLE_ASSET_ID.into()),
|
||||
]
|
||||
);
|
||||
pub PenpalASiblingSovereignAccount: AccountId = Sibling::from(PENPAL_A_ID).into_account_truncating();
|
||||
pub PenpalBSiblingSovereignAccount: AccountId = Sibling::from(PENPAL_B_ID).into_account_truncating();
|
||||
}
|
||||
|
||||
pub fn get_host_config() -> HostConfiguration<BlockNumber> {
|
||||
HostConfiguration {
|
||||
max_upward_queue_count: 10,
|
||||
max_upward_queue_size: 51200,
|
||||
max_upward_message_size: 51200,
|
||||
max_upward_message_num_per_candidate: 10,
|
||||
max_downward_message_size: 51200,
|
||||
hrmp_sender_deposit: 0,
|
||||
hrmp_recipient_deposit: 0,
|
||||
hrmp_channel_max_capacity: 1000,
|
||||
hrmp_channel_max_message_size: 102400,
|
||||
hrmp_channel_max_total_size: 102400,
|
||||
hrmp_max_teyrchain_outbound_channels: 30,
|
||||
hrmp_max_teyrchain_inbound_channels: 30,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper function used in tests to build the genesis storage using given RuntimeGenesisConfig and
|
||||
/// code Used in `legacy_vs_json_check` submods to verify storage building with JSON patch against
|
||||
/// building with RuntimeGenesisConfig struct.
|
||||
pub fn build_genesis_storage(builder: &dyn BuildStorage, code: &[u8]) -> Storage {
|
||||
let mut storage = builder.build_storage().unwrap();
|
||||
storage
|
||||
.top
|
||||
.insert(pezsp_core::storage::well_known_keys::CODE.to_vec(), code.into());
|
||||
storage
|
||||
}
|
||||
|
||||
pub mod accounts {
|
||||
use super::*;
|
||||
pub const ALICE: &str = "Alice";
|
||||
pub const BOB: &str = "Bob";
|
||||
pub const DUMMY_EMPTY: &str = "JohnDoe";
|
||||
|
||||
pub fn init_balances() -> Vec<AccountId> {
|
||||
Sr25519Keyring::well_known().map(|k| k.to_account_id()).collect()
|
||||
}
|
||||
}
|
||||
|
||||
pub mod collators {
|
||||
use super::*;
|
||||
|
||||
pub fn invulnerables() -> Vec<(AccountId, AuraId)> {
|
||||
vec![
|
||||
(Sr25519Keyring::Dave.to_account_id(), Sr25519Keyring::Dave.public().into()),
|
||||
(Sr25519Keyring::Eve.to_account_id(), Sr25519Keyring::Eve.public().into()),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
pub mod validators {
|
||||
use pezsp_consensus_beefy::test_utils::Keyring;
|
||||
|
||||
use super::*;
|
||||
|
||||
pub fn initial_authorities() -> Vec<(
|
||||
AccountId,
|
||||
AccountId,
|
||||
BabeId,
|
||||
GrandpaId,
|
||||
ValidatorId,
|
||||
AssignmentId,
|
||||
AuthorityDiscoveryId,
|
||||
BeefyId,
|
||||
)> {
|
||||
vec![(
|
||||
Sr25519Keyring::AliceStash.to_account_id(),
|
||||
Sr25519Keyring::Alice.to_account_id(),
|
||||
BabeId::from(Sr25519Keyring::Alice.public()),
|
||||
GrandpaId::from(Ed25519Keyring::Alice.public()),
|
||||
ValidatorId::from(Sr25519Keyring::Alice.public()),
|
||||
AssignmentId::from(Sr25519Keyring::Alice.public()),
|
||||
AuthorityDiscoveryId::from(Sr25519Keyring::Alice.public()),
|
||||
BeefyId::from(Keyring::<BeefyId>::Alice.public()),
|
||||
)]
|
||||
}
|
||||
}
|
||||
|
||||
pub mod snowbridge {
|
||||
use hex_literal::hex;
|
||||
// Address of WETH ERC20 token contract on remote Ethereum network
|
||||
pub const WETH: [u8; 20] = hex!("fff9976782d46cc05630d1f6ebab18b2324d6b14");
|
||||
// The Ethereum network chain ID. In this case, Sepolia testnet's chain ID.
|
||||
pub const SEPOLIA_ID: u64 = 11155111;
|
||||
// The minimum balance for ether assets pre-registered in emulated tests.
|
||||
pub const ETHER_MIN_BALANCE: u128 = 1000;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,201 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Pezcumulus
|
||||
use teyrchains_common::AccountId;
|
||||
|
||||
// Pezkuwi
|
||||
use pezsp_core::H256;
|
||||
use xcm::{prelude::*, DoubleEncoded};
|
||||
use xcm_emulator::Chain;
|
||||
|
||||
use crate::impls::{bx, Encode};
|
||||
use pezframe_support::dispatch::{DispatchResultWithPostInfo, PostDispatchInfo};
|
||||
use pezsp_runtime::traits::{Dispatchable, Hash};
|
||||
use xcm::{VersionedLocation, VersionedXcm};
|
||||
|
||||
/// Helper method to build a XCM with a `Transact` instruction and paying for its execution
|
||||
pub fn xcm_transact_paid_execution(
|
||||
call: DoubleEncoded<()>,
|
||||
origin_kind: OriginKind,
|
||||
fees: Asset,
|
||||
beneficiary: AccountId,
|
||||
) -> VersionedXcm<()> {
|
||||
let weight_limit = WeightLimit::Unlimited;
|
||||
|
||||
VersionedXcm::from(Xcm(vec![
|
||||
WithdrawAsset(fees.clone().into()),
|
||||
BuyExecution { fees, weight_limit },
|
||||
Transact { origin_kind, call, fallback_max_weight: None },
|
||||
ExpectTransactStatus(MaybeErrorCode::Success),
|
||||
RefundSurplus,
|
||||
DepositAsset {
|
||||
assets: All.into(),
|
||||
beneficiary: Location {
|
||||
parents: 0,
|
||||
interior: [AccountId32 { network: None, id: beneficiary.into() }].into(),
|
||||
},
|
||||
},
|
||||
]))
|
||||
}
|
||||
|
||||
/// Helper method to build a XCM with a `Transact` instruction without paying for its execution
|
||||
pub fn xcm_transact_unpaid_execution(
|
||||
call: DoubleEncoded<()>,
|
||||
origin_kind: OriginKind,
|
||||
) -> VersionedXcm<()> {
|
||||
let weight_limit = WeightLimit::Unlimited;
|
||||
let check_origin = None;
|
||||
|
||||
VersionedXcm::from(Xcm(vec![
|
||||
UnpaidExecution { weight_limit, check_origin },
|
||||
Transact { origin_kind, call, fallback_max_weight: None },
|
||||
ExpectTransactStatus(MaybeErrorCode::Success),
|
||||
]))
|
||||
}
|
||||
|
||||
/// Helper method to get the non-fee asset used in multiple assets transfer
|
||||
pub fn non_fee_asset(assets: &Assets, fee_asset_id: &AssetId) -> Option<(Location, u128)> {
|
||||
let asset = assets.inner().into_iter().find(|a| a.id != *fee_asset_id)?;
|
||||
let asset_amount = match asset.fun {
|
||||
Fungible(amount) => amount,
|
||||
_ => return None,
|
||||
};
|
||||
Some((asset.id.0.clone(), asset_amount))
|
||||
}
|
||||
|
||||
/// Helper method to get the fee asset used in multiple assets transfer
|
||||
pub fn fee_asset(assets: &Assets, fee_asset_id: &AssetId) -> Option<(Location, u128)> {
|
||||
let asset = assets.inner().iter().find(|a| a.id == *fee_asset_id)?;
|
||||
let asset_amount = match asset.fun {
|
||||
Fungible(amount) => amount,
|
||||
_ => return None,
|
||||
};
|
||||
Some((asset.id.0.clone(), asset_amount))
|
||||
}
|
||||
|
||||
pub fn get_amount_from_versioned_assets(assets: VersionedAssets) -> u128 {
|
||||
let latest_assets: Assets = assets.try_into().unwrap();
|
||||
let Fungible(amount) = latest_assets.inner()[0].fun else {
|
||||
unreachable!("asset is non-fungible");
|
||||
};
|
||||
amount
|
||||
}
|
||||
|
||||
fn to_mq_processed_id<C: Chain>(event: C::RuntimeEvent) -> Option<H256>
|
||||
where
|
||||
<C as Chain>::Runtime: pezpallet_message_queue::Config,
|
||||
C::RuntimeEvent: TryInto<pezpallet_message_queue::Event<<C as Chain>::Runtime>>,
|
||||
{
|
||||
if let Ok(pezpallet_message_queue::Event::Processed { id, .. }) = event.try_into() {
|
||||
Some(id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper method to find all `Event::Processed` IDs from the chain's events.
|
||||
pub fn find_all_mq_processed_ids<C: Chain>() -> Vec<H256>
|
||||
where
|
||||
<C as Chain>::Runtime: pezpallet_message_queue::Config,
|
||||
C::RuntimeEvent: TryInto<pezpallet_message_queue::Event<<C as Chain>::Runtime>>,
|
||||
{
|
||||
C::events().into_iter().filter_map(to_mq_processed_id::<C>).collect()
|
||||
}
|
||||
|
||||
/// Helper method to find the ID of the first `Event::Processed` event in the chain's events.
|
||||
pub fn find_mq_processed_id<C: Chain>() -> Option<H256>
|
||||
where
|
||||
<C as Chain>::Runtime: pezpallet_message_queue::Config,
|
||||
C::RuntimeEvent: TryInto<pezpallet_message_queue::Event<<C as Chain>::Runtime>>,
|
||||
{
|
||||
C::events().into_iter().find_map(to_mq_processed_id::<C>)
|
||||
}
|
||||
|
||||
/// Helper method to find the message ID of the first `Event::Sent` event in the chain's events.
|
||||
pub fn find_xcm_sent_message_id<
|
||||
C: Chain<RuntimeEvent = <<C as Chain>::Runtime as pezpallet_xcm::Config>::RuntimeEvent>,
|
||||
>() -> Option<XcmHash>
|
||||
where
|
||||
C::Runtime: pezpallet_xcm::Config,
|
||||
C::RuntimeEvent: TryInto<pezpallet_xcm::Event<C::Runtime>>,
|
||||
{
|
||||
pezpallet_xcm::xcm_helpers::find_xcm_sent_message_id::<<C as Chain>::Runtime>(C::events())
|
||||
}
|
||||
|
||||
/// Wraps a runtime call in a whitelist preimage call and dispatches it
|
||||
pub fn dispatch_whitelisted_call_with_preimage<T>(
|
||||
call: T::RuntimeCall,
|
||||
origin: T::RuntimeOrigin,
|
||||
) -> DispatchResultWithPostInfo
|
||||
where
|
||||
T: Chain,
|
||||
T::Runtime: pezpallet_whitelist::Config,
|
||||
T::RuntimeCall: From<pezpallet_whitelist::Call<T::Runtime>>
|
||||
+ Into<<T::Runtime as pezpallet_whitelist::Config>::RuntimeCall>
|
||||
+ Dispatchable<RuntimeOrigin = T::RuntimeOrigin, PostInfo = PostDispatchInfo>,
|
||||
{
|
||||
T::execute_with(|| {
|
||||
let whitelist_call: T::RuntimeCall =
|
||||
pezpallet_whitelist::Call::<T::Runtime>::dispatch_whitelisted_call_with_preimage {
|
||||
call: Box::new(call.into()),
|
||||
}
|
||||
.into();
|
||||
whitelist_call.dispatch(origin)
|
||||
})
|
||||
}
|
||||
|
||||
/// Builds a `pezpallet_xcm::send` call to authorize an upgrade at the provided location,
|
||||
/// wrapped in an unpaid XCM `Transact` with `OriginKind::Superuser`.
|
||||
pub fn build_xcm_send_authorize_upgrade_call<T, D>(
|
||||
location: Location,
|
||||
code_hash: &H256,
|
||||
fallback_max_weight: Option<Weight>,
|
||||
) -> T::RuntimeCall
|
||||
where
|
||||
T: Chain,
|
||||
T::Runtime: pezpallet_xcm::Config,
|
||||
T::RuntimeCall: Encode + From<pezpallet_xcm::Call<T::Runtime>>,
|
||||
D: Chain,
|
||||
D::Runtime: pezframe_system::Config<Hash = H256>,
|
||||
D::RuntimeCall: Encode + From<pezframe_system::Call<D::Runtime>>,
|
||||
{
|
||||
let transact_call: D::RuntimeCall =
|
||||
pezframe_system::Call::authorize_upgrade { code_hash: *code_hash }.into();
|
||||
|
||||
let call: T::RuntimeCall = pezpallet_xcm::Call::send {
|
||||
dest: bx!(VersionedLocation::from(location)),
|
||||
message: bx!(VersionedXcm::from(Xcm(vec![
|
||||
UnpaidExecution { weight_limit: Unlimited, check_origin: None },
|
||||
Transact {
|
||||
origin_kind: OriginKind::Superuser,
|
||||
fallback_max_weight,
|
||||
call: transact_call.encode().into(),
|
||||
}
|
||||
]))),
|
||||
}
|
||||
.into();
|
||||
call
|
||||
}
|
||||
|
||||
/// Encodes a runtime call and returns its H256 hash
|
||||
pub fn call_hash_of<T>(call: &T::RuntimeCall) -> H256
|
||||
where
|
||||
T: Chain,
|
||||
T::Runtime: pezframe_system::Config<Hash = H256>,
|
||||
T::RuntimeCall: Encode,
|
||||
{
|
||||
<T::Runtime as pezframe_system::Config>::Hashing::hash_of(&call)
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
[package]
|
||||
name = "pezkuwichain-system-emulated-network"
|
||||
version = "0.0.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license = "Apache-2.0"
|
||||
description = "Pezkuwichain System emulated network"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
# Pezcumulus
|
||||
asset-hub-pezkuwichain-emulated-chain = { workspace = true }
|
||||
bridge-hub-pezkuwichain-emulated-chain = { workspace = true }
|
||||
coretime-pezkuwichain-emulated-chain = { workspace = true }
|
||||
emulated-integration-tests-common = { workspace = true }
|
||||
penpal-emulated-chain = { workspace = true }
|
||||
people-pezkuwichain-emulated-chain = { workspace = true }
|
||||
pezkuwichain-emulated-chain = { workspace = true }
|
||||
|
||||
[features]
|
||||
runtime-benchmarks = [
|
||||
"asset-hub-pezkuwichain-emulated-chain/runtime-benchmarks",
|
||||
"bridge-hub-pezkuwichain-emulated-chain/runtime-benchmarks",
|
||||
"coretime-pezkuwichain-emulated-chain/runtime-benchmarks",
|
||||
"emulated-integration-tests-common/runtime-benchmarks",
|
||||
"penpal-emulated-chain/runtime-benchmarks",
|
||||
"people-pezkuwichain-emulated-chain/runtime-benchmarks",
|
||||
"pezkuwichain-emulated-chain/runtime-benchmarks",
|
||||
]
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
pub use asset_hub_pezkuwichain_emulated_chain;
|
||||
pub use bridge_hub_pezkuwichain_emulated_chain;
|
||||
pub use coretime_pezkuwichain_emulated_chain;
|
||||
pub use penpal_emulated_chain;
|
||||
pub use people_pezkuwichain_emulated_chain;
|
||||
pub use pezkuwichain_emulated_chain;
|
||||
|
||||
use asset_hub_pezkuwichain_emulated_chain::AssetHubPezkuwichain;
|
||||
use bridge_hub_pezkuwichain_emulated_chain::BridgeHubPezkuwichain;
|
||||
use coretime_pezkuwichain_emulated_chain::CoretimePezkuwichain;
|
||||
use penpal_emulated_chain::{PenpalA, PenpalB};
|
||||
use people_pezkuwichain_emulated_chain::PeoplePezkuwichain;
|
||||
use pezkuwichain_emulated_chain::Pezkuwichain;
|
||||
|
||||
// Pezcumulus
|
||||
use emulated_integration_tests_common::{
|
||||
accounts::{ALICE, BOB},
|
||||
xcm_emulator::{decl_test_networks, decl_test_sender_receiver_accounts_parameter_types},
|
||||
};
|
||||
|
||||
decl_test_networks! {
|
||||
pub struct PezkuwichainMockNet {
|
||||
relay_chain = Pezkuwichain,
|
||||
teyrchains = vec![
|
||||
AssetHubPezkuwichain,
|
||||
BridgeHubPezkuwichain,
|
||||
CoretimePezkuwichain,
|
||||
PenpalA,
|
||||
PenpalB,
|
||||
PeoplePezkuwichain,
|
||||
],
|
||||
bridge = ()
|
||||
},
|
||||
}
|
||||
|
||||
decl_test_sender_receiver_accounts_parameter_types! {
|
||||
PezkuwichainRelay { sender: ALICE, receiver: BOB },
|
||||
AssetHubPezkuwichainPara { sender: ALICE, receiver: BOB },
|
||||
BridgeHubPezkuwichainPara { sender: ALICE, receiver: BOB },
|
||||
CoretimePezkuwichainPara { sender: ALICE, receiver: BOB },
|
||||
PenpalAPara { sender: ALICE, receiver: BOB },
|
||||
PenpalBPara { sender: ALICE, receiver: BOB },
|
||||
PeoplePezkuwichainPara { sender: ALICE, receiver: BOB }
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
[package]
|
||||
name = "pezkuwichain-zagros-system-emulated-network"
|
||||
version = "0.0.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license = "Apache-2.0"
|
||||
description = "Pezkuwichain<>Zagros emulated bridged network"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
# Pezcumulus
|
||||
asset-hub-pezkuwichain-emulated-chain = { workspace = true }
|
||||
asset-hub-zagros-emulated-chain = { workspace = true }
|
||||
bridge-hub-pezkuwichain-emulated-chain = { workspace = true }
|
||||
bridge-hub-zagros-emulated-chain = { workspace = true }
|
||||
emulated-integration-tests-common = { workspace = true }
|
||||
penpal-emulated-chain = { workspace = true }
|
||||
pezkuwichain-emulated-chain = { workspace = true }
|
||||
zagros-emulated-chain = { workspace = true, default-features = true }
|
||||
|
||||
[features]
|
||||
runtime-benchmarks = [
|
||||
"asset-hub-pezkuwichain-emulated-chain/runtime-benchmarks",
|
||||
"asset-hub-zagros-emulated-chain/runtime-benchmarks",
|
||||
"bridge-hub-pezkuwichain-emulated-chain/runtime-benchmarks",
|
||||
"bridge-hub-zagros-emulated-chain/runtime-benchmarks",
|
||||
"emulated-integration-tests-common/runtime-benchmarks",
|
||||
"penpal-emulated-chain/runtime-benchmarks",
|
||||
"pezkuwichain-emulated-chain/runtime-benchmarks",
|
||||
"zagros-emulated-chain/runtime-benchmarks",
|
||||
]
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
pub use asset_hub_pezkuwichain_emulated_chain;
|
||||
pub use asset_hub_zagros_emulated_chain;
|
||||
pub use bridge_hub_pezkuwichain_emulated_chain;
|
||||
pub use bridge_hub_zagros_emulated_chain;
|
||||
pub use penpal_emulated_chain;
|
||||
pub use pezkuwichain_emulated_chain;
|
||||
pub use zagros_emulated_chain;
|
||||
|
||||
use asset_hub_pezkuwichain_emulated_chain::AssetHubPezkuwichain;
|
||||
use asset_hub_zagros_emulated_chain::AssetHubZagros;
|
||||
use bridge_hub_pezkuwichain_emulated_chain::BridgeHubPezkuwichain;
|
||||
use bridge_hub_zagros_emulated_chain::BridgeHubZagros;
|
||||
use penpal_emulated_chain::{PenpalA, PenpalB};
|
||||
use pezkuwichain_emulated_chain::Pezkuwichain;
|
||||
use zagros_emulated_chain::Zagros;
|
||||
|
||||
// Pezcumulus
|
||||
use emulated_integration_tests_common::{
|
||||
accounts::{ALICE, BOB},
|
||||
impls::{BridgeHubMessageHandler, BridgeMessagesInstance1, BridgeMessagesInstance3},
|
||||
xcm_emulator::{
|
||||
decl_test_bridges, decl_test_networks, decl_test_sender_receiver_accounts_parameter_types,
|
||||
Chain,
|
||||
},
|
||||
};
|
||||
|
||||
decl_test_networks! {
|
||||
pub struct PezkuwichainMockNet {
|
||||
relay_chain = Pezkuwichain,
|
||||
teyrchains = vec![
|
||||
AssetHubPezkuwichain,
|
||||
BridgeHubPezkuwichain,
|
||||
PenpalA,
|
||||
],
|
||||
bridge = PezkuwichainZagrosMockBridge
|
||||
},
|
||||
pub struct ZagrosMockNet {
|
||||
relay_chain = Zagros,
|
||||
teyrchains = vec![
|
||||
AssetHubZagros,
|
||||
BridgeHubZagros,
|
||||
PenpalB,
|
||||
],
|
||||
bridge = ZagrosPezkuwichainMockBridge
|
||||
},
|
||||
}
|
||||
|
||||
decl_test_bridges! {
|
||||
pub struct PezkuwichainZagrosMockBridge {
|
||||
source = BridgeHubPezkuwichainPara,
|
||||
target = BridgeHubZagrosPara,
|
||||
handler = PezkuwichainZagrosMessageHandler
|
||||
},
|
||||
pub struct ZagrosPezkuwichainMockBridge {
|
||||
source = BridgeHubZagrosPara,
|
||||
target = BridgeHubPezkuwichainPara,
|
||||
handler = ZagrosPezkuwichainMessageHandler
|
||||
}
|
||||
}
|
||||
|
||||
type BridgeHubPezkuwichainRuntime = <BridgeHubPezkuwichainPara as Chain>::Runtime;
|
||||
type BridgeHubZagrosRuntime = <BridgeHubZagrosPara as Chain>::Runtime;
|
||||
|
||||
pub type PezkuwichainZagrosMessageHandler = BridgeHubMessageHandler<
|
||||
BridgeHubPezkuwichainRuntime,
|
||||
BridgeMessagesInstance3,
|
||||
BridgeHubZagrosRuntime,
|
||||
BridgeMessagesInstance1,
|
||||
>;
|
||||
pub type ZagrosPezkuwichainMessageHandler = BridgeHubMessageHandler<
|
||||
BridgeHubZagrosRuntime,
|
||||
BridgeMessagesInstance1,
|
||||
BridgeHubPezkuwichainRuntime,
|
||||
BridgeMessagesInstance3,
|
||||
>;
|
||||
|
||||
decl_test_sender_receiver_accounts_parameter_types! {
|
||||
PezkuwichainRelay { sender: ALICE, receiver: BOB },
|
||||
AssetHubPezkuwichainPara { sender: ALICE, receiver: BOB },
|
||||
BridgeHubPezkuwichainPara { sender: ALICE, receiver: BOB },
|
||||
ZagrosRelay { sender: ALICE, receiver: BOB },
|
||||
AssetHubZagrosPara { sender: ALICE, receiver: BOB },
|
||||
BridgeHubZagrosPara { sender: ALICE, receiver: BOB },
|
||||
PenpalAPara { sender: ALICE, receiver: BOB },
|
||||
PenpalBPara { sender: ALICE, receiver: BOB }
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
[package]
|
||||
name = "zagros-system-emulated-network"
|
||||
version = "0.0.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license = "Apache-2.0"
|
||||
description = "Zagros System emulated network"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
# Pezcumulus
|
||||
asset-hub-zagros-emulated-chain = { workspace = true }
|
||||
bridge-hub-zagros-emulated-chain = { workspace = true }
|
||||
collectives-zagros-emulated-chain = { workspace = true }
|
||||
coretime-zagros-emulated-chain = { workspace = true }
|
||||
emulated-integration-tests-common = { workspace = true }
|
||||
penpal-emulated-chain = { workspace = true }
|
||||
people-zagros-emulated-chain = { workspace = true }
|
||||
zagros-emulated-chain = { workspace = true }
|
||||
|
||||
[features]
|
||||
runtime-benchmarks = [
|
||||
"asset-hub-zagros-emulated-chain/runtime-benchmarks",
|
||||
"bridge-hub-zagros-emulated-chain/runtime-benchmarks",
|
||||
"collectives-zagros-emulated-chain/runtime-benchmarks",
|
||||
"coretime-zagros-emulated-chain/runtime-benchmarks",
|
||||
"emulated-integration-tests-common/runtime-benchmarks",
|
||||
"penpal-emulated-chain/runtime-benchmarks",
|
||||
"people-zagros-emulated-chain/runtime-benchmarks",
|
||||
"zagros-emulated-chain/runtime-benchmarks",
|
||||
]
|
||||
@@ -0,0 +1,63 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
pub use asset_hub_zagros_emulated_chain;
|
||||
pub use bridge_hub_zagros_emulated_chain;
|
||||
pub use collectives_zagros_emulated_chain;
|
||||
pub use coretime_zagros_emulated_chain;
|
||||
pub use penpal_emulated_chain;
|
||||
pub use people_zagros_emulated_chain;
|
||||
pub use zagros_emulated_chain;
|
||||
|
||||
use asset_hub_zagros_emulated_chain::AssetHubZagros;
|
||||
use bridge_hub_zagros_emulated_chain::BridgeHubZagros;
|
||||
use collectives_zagros_emulated_chain::CollectivesZagros;
|
||||
use coretime_zagros_emulated_chain::CoretimeZagros;
|
||||
use penpal_emulated_chain::{PenpalA, PenpalB};
|
||||
use people_zagros_emulated_chain::PeopleZagros;
|
||||
use zagros_emulated_chain::Zagros;
|
||||
|
||||
// Pezcumulus
|
||||
use emulated_integration_tests_common::{
|
||||
accounts::{ALICE, BOB},
|
||||
xcm_emulator::{decl_test_networks, decl_test_sender_receiver_accounts_parameter_types},
|
||||
};
|
||||
|
||||
decl_test_networks! {
|
||||
pub struct ZagrosMockNet {
|
||||
relay_chain = Zagros,
|
||||
teyrchains = vec![
|
||||
AssetHubZagros,
|
||||
BridgeHubZagros,
|
||||
CollectivesZagros,
|
||||
CoretimeZagros,
|
||||
PeopleZagros,
|
||||
PenpalA,
|
||||
PenpalB,
|
||||
],
|
||||
bridge = ()
|
||||
},
|
||||
}
|
||||
|
||||
decl_test_sender_receiver_accounts_parameter_types! {
|
||||
ZagrosRelay { sender: ALICE, receiver: BOB },
|
||||
AssetHubZagrosPara { sender: ALICE, receiver: BOB },
|
||||
BridgeHubZagrosPara { sender: ALICE, receiver: BOB },
|
||||
CollectivesZagrosPara { sender: ALICE, receiver: BOB },
|
||||
CoretimeZagrosPara { sender: ALICE, receiver: BOB },
|
||||
PeopleZagrosPara { sender: ALICE, receiver: BOB },
|
||||
PenpalAPara { sender: ALICE, receiver: BOB },
|
||||
PenpalBPara { sender: ALICE, receiver: BOB }
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
[package]
|
||||
name = "asset-hub-pezkuwichain-integration-tests"
|
||||
version = "1.0.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license = "Apache-2.0"
|
||||
description = "Asset Hub Pezkuwichain runtime integration tests with xcm-emulator"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
assert_matches = { workspace = true }
|
||||
codec = { workspace = true }
|
||||
|
||||
# Bizinikiwi
|
||||
pezframe-support = { workspace = true }
|
||||
pezframe-system = { workspace = true }
|
||||
pezpallet-asset-conversion = { workspace = true }
|
||||
pezpallet-asset-rewards = { workspace = true }
|
||||
pezpallet-assets = { workspace = true }
|
||||
pezpallet-balances = { workspace = true }
|
||||
pezpallet-message-queue = { workspace = true }
|
||||
pezpallet-treasury = { workspace = true }
|
||||
pezpallet-utility = { workspace = true }
|
||||
pezsp-core = { workspace = true }
|
||||
pezsp-runtime = { workspace = true }
|
||||
|
||||
# Pezkuwi
|
||||
pezpallet-xcm = { workspace = true }
|
||||
pezkuwi-runtime-common = { workspace = true, default-features = true }
|
||||
pezkuwichain-runtime-constants = { workspace = true, default-features = true }
|
||||
xcm = { workspace = true }
|
||||
xcm-executor = { workspace = true }
|
||||
xcm-runtime-apis = { workspace = true, default-features = true }
|
||||
|
||||
# Pezcumulus
|
||||
asset-test-utils = { workspace = true, default-features = true }
|
||||
pezcumulus-pezpallet-teyrchain-system = { workspace = true }
|
||||
emulated-integration-tests-common = { workspace = true }
|
||||
pezkuwichain-system-emulated-network = { workspace = true }
|
||||
teyrchains-common = { workspace = true, default-features = true }
|
||||
|
||||
[features]
|
||||
runtime-benchmarks = [
|
||||
"asset-test-utils/runtime-benchmarks",
|
||||
"pezcumulus-pezpallet-teyrchain-system/runtime-benchmarks",
|
||||
"emulated-integration-tests-common/runtime-benchmarks",
|
||||
"pezframe-support/runtime-benchmarks",
|
||||
"pezframe-system/runtime-benchmarks",
|
||||
"pezpallet-asset-conversion/runtime-benchmarks",
|
||||
"pezpallet-asset-rewards/runtime-benchmarks",
|
||||
"pezpallet-assets/runtime-benchmarks",
|
||||
"pezpallet-balances/runtime-benchmarks",
|
||||
"pezpallet-message-queue/runtime-benchmarks",
|
||||
"pezpallet-treasury/runtime-benchmarks",
|
||||
"pezpallet-utility/runtime-benchmarks",
|
||||
"pezpallet-xcm/runtime-benchmarks",
|
||||
"pezkuwi-runtime-common/runtime-benchmarks",
|
||||
"pezkuwichain-runtime-constants/runtime-benchmarks",
|
||||
"pezkuwichain-system-emulated-network/runtime-benchmarks",
|
||||
"pezsp-runtime/runtime-benchmarks",
|
||||
"teyrchains-common/runtime-benchmarks",
|
||||
"xcm-executor/runtime-benchmarks",
|
||||
"xcm-runtime-apis/runtime-benchmarks",
|
||||
"xcm/runtime-benchmarks",
|
||||
]
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#[cfg(test)]
|
||||
mod imports {
|
||||
pub(crate) use codec::Encode;
|
||||
|
||||
// Bizinikiwi
|
||||
pub(crate) use pezframe_support::{
|
||||
assert_err, assert_ok,
|
||||
pezpallet_prelude::Weight,
|
||||
pezsp_runtime::{DispatchError, DispatchResult, ModuleError},
|
||||
traits::fungibles::Inspect,
|
||||
};
|
||||
|
||||
// Pezkuwi
|
||||
pub(crate) use xcm::{
|
||||
latest::{PEZKUWICHAIN_GENESIS_HASH, ZAGROS_GENESIS_HASH},
|
||||
prelude::{AccountId32 as AccountId32Junction, *},
|
||||
};
|
||||
pub(crate) use xcm_executor::traits::TransferType;
|
||||
|
||||
// Pezcumulus
|
||||
pub(crate) use asset_test_utils::xcm_helpers;
|
||||
pub(crate) use emulated_integration_tests_common::{
|
||||
accounts::DUMMY_EMPTY,
|
||||
test_relay_is_trusted_teleporter, test_teyrchain_is_trusted_teleporter,
|
||||
test_teyrchain_is_trusted_teleporter_for_relay,
|
||||
test_xcm_fee_querying_apis_work_for_asset_hub,
|
||||
xcm_emulator::{
|
||||
assert_expected_events, bx, Chain, RelayChain as Relay, Test, TestArgs, TestContext,
|
||||
TestExt, Teyrchain as Para,
|
||||
},
|
||||
xcm_helpers::{
|
||||
fee_asset, get_amount_from_versioned_assets, non_fee_asset, xcm_transact_paid_execution,
|
||||
},
|
||||
PenpalATeleportableAssetLocation, ASSETS_PALLET_ID, RESERVABLE_ASSET_ID, XCM_V3,
|
||||
};
|
||||
pub(crate) use pezkuwichain_system_emulated_network::{
|
||||
asset_hub_pezkuwichain_emulated_chain::{
|
||||
asset_hub_pezkuwichain_runtime::{
|
||||
self,
|
||||
xcm_config::{
|
||||
self as ahr_xcm_config, TokenLocation as RelayLocation, TreasuryAccount,
|
||||
XcmConfig as AssetHubPezkuwichainXcmConfig,
|
||||
},
|
||||
AssetConversionOrigin as AssetHubPezkuwichainAssetConversionOrigin,
|
||||
ExistentialDeposit as AssetHubPezkuwichainExistentialDeposit,
|
||||
},
|
||||
genesis::{AssetHubPezkuwichainAssetOwner, ED as ASSET_HUB_PEZKUWICHAIN_ED},
|
||||
AssetHubPezkuwichainParaPallet as AssetHubPezkuwichainPallet,
|
||||
},
|
||||
penpal_emulated_chain::{
|
||||
penpal_runtime::xcm_config::{
|
||||
CustomizableAssetFromSystemAssetHub as PenpalCustomizableAssetFromSystemAssetHub,
|
||||
LocalReservableFromAssetHub as PenpalLocalReservableFromAssetHub,
|
||||
LocalTeleportableToAssetHub as PenpalLocalTeleportableToAssetHub,
|
||||
UsdtFromAssetHub as PenpalUsdtFromAssetHub,
|
||||
},
|
||||
PenpalAParaPallet as PenpalAPallet, PenpalAssetOwner,
|
||||
PenpalBParaPallet as PenpalBPallet, ED as PENPAL_ED,
|
||||
},
|
||||
pezkuwichain_emulated_chain::{
|
||||
genesis::ED as PEZKUWICHAIN_ED,
|
||||
pezkuwichain_runtime::{
|
||||
governance as pezkuwichain_governance,
|
||||
governance::pezpallet_custom_origins::Origin::Treasurer,
|
||||
xcm_config::UniversalLocation as PezkuwichainUniversalLocation, Dmp,
|
||||
OriginCaller as PezkuwichainOriginCaller,
|
||||
},
|
||||
PezkuwichainRelayPallet as PezkuwichainPallet,
|
||||
},
|
||||
AssetHubPezkuwichainPara as AssetHubPezkuwichain,
|
||||
AssetHubPezkuwichainParaReceiver as AssetHubPezkuwichainReceiver,
|
||||
AssetHubPezkuwichainParaSender as AssetHubPezkuwichainSender,
|
||||
BridgeHubPezkuwichainPara as BridgeHubPezkuwichain,
|
||||
BridgeHubPezkuwichainParaReceiver as BridgeHubPezkuwichainReceiver, PenpalAPara as PenpalA,
|
||||
PenpalAParaReceiver as PenpalAReceiver, PenpalAParaSender as PenpalASender,
|
||||
PenpalBPara as PenpalB, PenpalBParaReceiver as PenpalBReceiver,
|
||||
PezkuwichainRelay as Pezkuwichain, PezkuwichainRelayReceiver as PezkuwichainReceiver,
|
||||
PezkuwichainRelaySender as PezkuwichainSender,
|
||||
};
|
||||
pub(crate) use teyrchains_common::Balance;
|
||||
|
||||
pub(crate) const ASSET_ID: u32 = 3;
|
||||
pub(crate) const ASSET_MIN_BALANCE: u128 = 1000;
|
||||
|
||||
pub(crate) type RelayToParaTest = Test<Pezkuwichain, PenpalA>;
|
||||
pub(crate) type ParaToRelayTest = Test<PenpalA, Pezkuwichain>;
|
||||
pub(crate) type SystemParaToRelayTest = Test<AssetHubPezkuwichain, Pezkuwichain>;
|
||||
pub(crate) type SystemParaToParaTest = Test<AssetHubPezkuwichain, PenpalA>;
|
||||
pub(crate) type ParaToSystemParaTest = Test<PenpalA, AssetHubPezkuwichain>;
|
||||
pub(crate) type ParaToParaThroughRelayTest = Test<PenpalA, PenpalB, Pezkuwichain>;
|
||||
pub(crate) type ParaToParaThroughAHTest = Test<PenpalA, PenpalB, AssetHubPezkuwichain>;
|
||||
pub(crate) type RelayToParaThroughAHTest = Test<Pezkuwichain, PenpalA, AssetHubPezkuwichain>;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! Tests related to claiming assets trapped during XCM execution.
|
||||
|
||||
use crate::imports::*;
|
||||
|
||||
use emulated_integration_tests_common::test_chain_can_claim_assets;
|
||||
|
||||
#[test]
|
||||
fn assets_can_be_claimed() {
|
||||
let amount = AssetHubPezkuwichainExistentialDeposit::get();
|
||||
let assets: Assets = (Parent, amount).into();
|
||||
|
||||
test_chain_can_claim_assets!(
|
||||
AssetHubPezkuwichain,
|
||||
RuntimeCall,
|
||||
NetworkId::ByGenesis(PEZKUWICHAIN_GENESIS_HASH),
|
||||
assets,
|
||||
amount
|
||||
);
|
||||
}
|
||||
+868
@@ -0,0 +1,868 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use super::reserve_transfer::*;
|
||||
use crate::{
|
||||
imports::*,
|
||||
tests::teleport::do_bidirectional_teleport_foreign_assets_between_para_and_asset_hub_using_xt,
|
||||
};
|
||||
|
||||
fn para_to_para_assethub_hop_assertions(t: ParaToParaThroughAHTest) {
|
||||
type RuntimeEvent = <AssetHubPezkuwichain as Chain>::RuntimeEvent;
|
||||
let sov_penpal_a_on_ah = AssetHubPezkuwichain::sovereign_account_id_of(
|
||||
AssetHubPezkuwichain::sibling_location_of(PenpalA::para_id()),
|
||||
);
|
||||
let sov_penpal_b_on_ah = AssetHubPezkuwichain::sovereign_account_id_of(
|
||||
AssetHubPezkuwichain::sibling_location_of(PenpalB::para_id()),
|
||||
);
|
||||
|
||||
assert_expected_events!(
|
||||
AssetHubPezkuwichain,
|
||||
vec![
|
||||
// Withdrawn from sender teyrchain SA
|
||||
RuntimeEvent::Balances(
|
||||
pezpallet_balances::Event::Burned { who, amount }
|
||||
) => {
|
||||
who: *who == sov_penpal_a_on_ah,
|
||||
amount: *amount == t.args.amount,
|
||||
},
|
||||
// Deposited to receiver teyrchain SA
|
||||
RuntimeEvent::Balances(
|
||||
pezpallet_balances::Event::Minted { who, .. }
|
||||
) => {
|
||||
who: *who == sov_penpal_b_on_ah,
|
||||
},
|
||||
RuntimeEvent::MessageQueue(
|
||||
pezpallet_message_queue::Event::Processed { success: true, .. }
|
||||
) => {},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
fn ah_to_para_transfer_assets(t: SystemParaToParaTest) -> DispatchResult {
|
||||
let fee: Asset = t
|
||||
.args
|
||||
.assets
|
||||
.inner()
|
||||
.iter()
|
||||
.find(|a| a.id == t.args.fee_asset_id)
|
||||
.cloned()
|
||||
.unwrap();
|
||||
let custom_xcm_on_dest = Xcm::<()>(vec![DepositAsset {
|
||||
assets: Wild(AllCounted(t.args.assets.len() as u32)),
|
||||
beneficiary: t.args.beneficiary,
|
||||
}]);
|
||||
<AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::PezkuwiXcm::transfer_assets_using_type_and_then(
|
||||
t.signed_origin,
|
||||
bx!(t.args.dest.into()),
|
||||
bx!(t.args.assets.into()),
|
||||
bx!(TransferType::LocalReserve),
|
||||
bx!(fee.id.into()),
|
||||
bx!(TransferType::LocalReserve),
|
||||
bx!(VersionedXcm::from(custom_xcm_on_dest)),
|
||||
t.args.weight_limit,
|
||||
)
|
||||
}
|
||||
|
||||
fn para_to_ah_transfer_assets(t: ParaToSystemParaTest) -> DispatchResult {
|
||||
let fee: Asset = t
|
||||
.args
|
||||
.assets
|
||||
.inner()
|
||||
.iter()
|
||||
.find(|a| a.id == t.args.fee_asset_id)
|
||||
.cloned()
|
||||
.unwrap();
|
||||
let custom_xcm_on_dest = Xcm::<()>(vec![DepositAsset {
|
||||
assets: Wild(AllCounted(t.args.assets.len() as u32)),
|
||||
beneficiary: t.args.beneficiary,
|
||||
}]);
|
||||
<PenpalA as PenpalAPallet>::PezkuwiXcm::transfer_assets_using_type_and_then(
|
||||
t.signed_origin,
|
||||
bx!(t.args.dest.into()),
|
||||
bx!(t.args.assets.into()),
|
||||
bx!(TransferType::DestinationReserve),
|
||||
bx!(fee.id.into()),
|
||||
bx!(TransferType::DestinationReserve),
|
||||
bx!(VersionedXcm::from(custom_xcm_on_dest)),
|
||||
t.args.weight_limit,
|
||||
)
|
||||
}
|
||||
|
||||
fn para_to_para_transfer_assets_through_ah(t: ParaToParaThroughAHTest) -> DispatchResult {
|
||||
let fee: Asset = t
|
||||
.args
|
||||
.assets
|
||||
.inner()
|
||||
.iter()
|
||||
.find(|a| a.id == t.args.fee_asset_id)
|
||||
.cloned()
|
||||
.unwrap();
|
||||
let asset_hub_location: Location =
|
||||
PenpalA::sibling_location_of(AssetHubPezkuwichain::para_id());
|
||||
let custom_xcm_on_dest = Xcm::<()>(vec![DepositAsset {
|
||||
assets: Wild(AllCounted(t.args.assets.len() as u32)),
|
||||
beneficiary: t.args.beneficiary,
|
||||
}]);
|
||||
<PenpalA as PenpalAPallet>::PezkuwiXcm::transfer_assets_using_type_and_then(
|
||||
t.signed_origin,
|
||||
bx!(t.args.dest.into()),
|
||||
bx!(t.args.assets.into()),
|
||||
bx!(TransferType::RemoteReserve(asset_hub_location.clone().into())),
|
||||
bx!(fee.id.into()),
|
||||
bx!(TransferType::RemoteReserve(asset_hub_location.into())),
|
||||
bx!(VersionedXcm::from(custom_xcm_on_dest)),
|
||||
t.args.weight_limit,
|
||||
)
|
||||
}
|
||||
|
||||
fn para_to_asset_hub_teleport_foreign_assets(t: ParaToSystemParaTest) -> DispatchResult {
|
||||
let fee: Asset = t
|
||||
.args
|
||||
.assets
|
||||
.inner()
|
||||
.iter()
|
||||
.find(|a| a.id == t.args.fee_asset_id)
|
||||
.cloned()
|
||||
.unwrap();
|
||||
let custom_xcm_on_dest = Xcm::<()>(vec![DepositAsset {
|
||||
assets: Wild(AllCounted(t.args.assets.len() as u32)),
|
||||
beneficiary: t.args.beneficiary,
|
||||
}]);
|
||||
<PenpalA as PenpalAPallet>::PezkuwiXcm::transfer_assets_using_type_and_then(
|
||||
t.signed_origin,
|
||||
bx!(t.args.dest.into()),
|
||||
bx!(t.args.assets.into()),
|
||||
bx!(TransferType::Teleport),
|
||||
bx!(fee.id.into()),
|
||||
bx!(TransferType::DestinationReserve),
|
||||
bx!(VersionedXcm::from(custom_xcm_on_dest)),
|
||||
t.args.weight_limit,
|
||||
)
|
||||
}
|
||||
|
||||
fn asset_hub_to_para_teleport_foreign_assets(t: SystemParaToParaTest) -> DispatchResult {
|
||||
let fee: Asset = t
|
||||
.args
|
||||
.assets
|
||||
.inner()
|
||||
.iter()
|
||||
.find(|a| a.id == t.args.fee_asset_id)
|
||||
.cloned()
|
||||
.unwrap();
|
||||
let custom_xcm_on_dest = Xcm::<()>(vec![DepositAsset {
|
||||
assets: Wild(AllCounted(t.args.assets.len() as u32)),
|
||||
beneficiary: t.args.beneficiary,
|
||||
}]);
|
||||
<AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::PezkuwiXcm::transfer_assets_using_type_and_then(
|
||||
t.signed_origin,
|
||||
bx!(t.args.dest.into()),
|
||||
bx!(t.args.assets.into()),
|
||||
bx!(TransferType::Teleport),
|
||||
bx!(fee.id.into()),
|
||||
bx!(TransferType::LocalReserve),
|
||||
bx!(VersionedXcm::from(custom_xcm_on_dest)),
|
||||
t.args.weight_limit,
|
||||
)
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// ======= Transfer - Native + Bridged Assets - AssetHub->Teyrchain ==========
|
||||
// ===========================================================================
|
||||
/// Transfers of native asset plus bridged asset from AssetHub to some Teyrchain
|
||||
/// while paying fees using native asset.
|
||||
#[test]
|
||||
fn transfer_foreign_assets_from_asset_hub_to_para() {
|
||||
let destination = AssetHubPezkuwichain::sibling_location_of(PenpalA::para_id());
|
||||
let sender = AssetHubPezkuwichainSender::get();
|
||||
let native_amount_to_send: Balance = ASSET_HUB_PEZKUWICHAIN_ED * 10000;
|
||||
let native_asset_location = RelayLocation::get();
|
||||
let receiver = PenpalAReceiver::get();
|
||||
let assets_owner = PenpalAssetOwner::get();
|
||||
// Foreign asset used: bridged ZGR
|
||||
let foreign_amount_to_send = ASSET_HUB_PEZKUWICHAIN_ED * 10_000_000;
|
||||
let wnd_at_pezkuwichain_teyrchains =
|
||||
Location::new(2, [Junction::GlobalConsensus(NetworkId::ByGenesis(ZAGROS_GENESIS_HASH))]);
|
||||
|
||||
// Configure destination chain to trust AH as reserve of ZGR
|
||||
PenpalA::execute_with(|| {
|
||||
assert_ok!(<PenpalA as Chain>::System::set_storage(
|
||||
<PenpalA as Chain>::RuntimeOrigin::root(),
|
||||
vec![(
|
||||
PenpalCustomizableAssetFromSystemAssetHub::key().to_vec(),
|
||||
Location::new(2, [GlobalConsensus(ByGenesis(ZAGROS_GENESIS_HASH))]).encode(),
|
||||
)],
|
||||
));
|
||||
});
|
||||
PenpalA::force_create_foreign_asset(
|
||||
wnd_at_pezkuwichain_teyrchains.clone(),
|
||||
assets_owner.clone(),
|
||||
false,
|
||||
ASSET_MIN_BALANCE,
|
||||
vec![],
|
||||
);
|
||||
AssetHubPezkuwichain::force_create_foreign_asset(
|
||||
wnd_at_pezkuwichain_teyrchains.clone().try_into().unwrap(),
|
||||
assets_owner.clone(),
|
||||
false,
|
||||
ASSET_MIN_BALANCE,
|
||||
vec![],
|
||||
);
|
||||
AssetHubPezkuwichain::mint_foreign_asset(
|
||||
<AssetHubPezkuwichain as Chain>::RuntimeOrigin::signed(assets_owner),
|
||||
wnd_at_pezkuwichain_teyrchains.clone().try_into().unwrap(),
|
||||
sender.clone(),
|
||||
foreign_amount_to_send * 2,
|
||||
);
|
||||
|
||||
// Assets to send
|
||||
let assets: Vec<Asset> = vec![
|
||||
(Parent, native_amount_to_send).into(),
|
||||
(wnd_at_pezkuwichain_teyrchains.clone(), foreign_amount_to_send).into(),
|
||||
];
|
||||
let fee_asset_id = AssetId(Parent.into());
|
||||
|
||||
// Init Test
|
||||
let test_args = TestContext {
|
||||
sender: sender.clone(),
|
||||
receiver: receiver.clone(),
|
||||
args: TestArgs::new_para(
|
||||
destination.clone(),
|
||||
receiver.clone(),
|
||||
native_amount_to_send,
|
||||
assets.into(),
|
||||
None,
|
||||
fee_asset_id,
|
||||
),
|
||||
};
|
||||
let mut test = SystemParaToParaTest::new(test_args);
|
||||
|
||||
// Query initial balances
|
||||
let sender_balance_before = test.sender.balance;
|
||||
let sender_wnds_before = AssetHubPezkuwichain::execute_with(|| {
|
||||
type ForeignAssets = <AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::ForeignAssets;
|
||||
<ForeignAssets as Inspect<_>>::balance(
|
||||
wnd_at_pezkuwichain_teyrchains.clone().try_into().unwrap(),
|
||||
&sender,
|
||||
)
|
||||
});
|
||||
let receiver_assets_before = PenpalA::execute_with(|| {
|
||||
type ForeignAssets = <PenpalA as PenpalAPallet>::ForeignAssets;
|
||||
<ForeignAssets as Inspect<_>>::balance(native_asset_location.clone(), &receiver)
|
||||
});
|
||||
let receiver_wnds_before = PenpalA::execute_with(|| {
|
||||
type ForeignAssets = <PenpalA as PenpalAPallet>::ForeignAssets;
|
||||
<ForeignAssets as Inspect<_>>::balance(wnd_at_pezkuwichain_teyrchains.clone(), &receiver)
|
||||
});
|
||||
|
||||
// Set assertions and dispatchables
|
||||
test.set_assertion::<AssetHubPezkuwichain>(system_para_to_para_sender_assertions);
|
||||
test.set_assertion::<PenpalA>(system_para_to_para_receiver_assertions);
|
||||
test.set_dispatchable::<AssetHubPezkuwichain>(ah_to_para_transfer_assets);
|
||||
test.assert();
|
||||
|
||||
// Query final balances
|
||||
let sender_balance_after = test.sender.balance;
|
||||
let sender_wnds_after = AssetHubPezkuwichain::execute_with(|| {
|
||||
type ForeignAssets = <AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::ForeignAssets;
|
||||
<ForeignAssets as Inspect<_>>::balance(
|
||||
wnd_at_pezkuwichain_teyrchains.clone().try_into().unwrap(),
|
||||
&sender,
|
||||
)
|
||||
});
|
||||
let receiver_assets_after = PenpalA::execute_with(|| {
|
||||
type ForeignAssets = <PenpalA as PenpalAPallet>::ForeignAssets;
|
||||
<ForeignAssets as Inspect<_>>::balance(native_asset_location, &receiver)
|
||||
});
|
||||
let receiver_wnds_after = PenpalA::execute_with(|| {
|
||||
type ForeignAssets = <PenpalA as PenpalAPallet>::ForeignAssets;
|
||||
<ForeignAssets as Inspect<_>>::balance(wnd_at_pezkuwichain_teyrchains, &receiver)
|
||||
});
|
||||
|
||||
// Sender's balance is reduced by amount sent plus delivery fees
|
||||
assert!(sender_balance_after < sender_balance_before - native_amount_to_send);
|
||||
// Sender's balance is reduced by foreign amount sent
|
||||
assert_eq!(sender_wnds_after, sender_wnds_before - foreign_amount_to_send);
|
||||
// Receiver's assets is increased
|
||||
assert!(receiver_assets_after > receiver_assets_before);
|
||||
// Receiver's assets increased by `amount_to_send - delivery_fees - bought_execution`;
|
||||
// `delivery_fees` might be paid from transfer or JIT, also `bought_execution` is unknown but
|
||||
// should be non-zero
|
||||
assert!(receiver_assets_after < receiver_assets_before + native_amount_to_send);
|
||||
// Receiver's balance is increased by foreign amount sent
|
||||
assert_eq!(receiver_wnds_after, receiver_wnds_before + foreign_amount_to_send);
|
||||
}
|
||||
|
||||
/// Reserve Transfers of native asset from Teyrchain to System Teyrchain should work
|
||||
// ===========================================================================
|
||||
// ======= Transfer - Native + Bridged Assets - Teyrchain->AssetHub ==========
|
||||
// ===========================================================================
|
||||
/// Transfers of native asset plus bridged asset from some Teyrchain to AssetHub
|
||||
/// while paying fees using native asset.
|
||||
#[test]
|
||||
fn transfer_foreign_assets_from_para_to_asset_hub() {
|
||||
// Init values for Teyrchain
|
||||
let destination = PenpalA::sibling_location_of(AssetHubPezkuwichain::para_id());
|
||||
let sender = PenpalASender::get();
|
||||
let native_amount_to_send: Balance = ASSET_HUB_PEZKUWICHAIN_ED * 10000;
|
||||
let native_asset_location = RelayLocation::get();
|
||||
let assets_owner = PenpalAssetOwner::get();
|
||||
|
||||
// Foreign asset used: bridged ZGR
|
||||
let foreign_amount_to_send = ASSET_HUB_PEZKUWICHAIN_ED * 10_000_000;
|
||||
let wnd_at_pezkuwichain_teyrchains =
|
||||
Location::new(2, [Junction::GlobalConsensus(NetworkId::ByGenesis(ZAGROS_GENESIS_HASH))]);
|
||||
|
||||
// Configure destination chain to trust AH as reserve of ZGR
|
||||
PenpalA::execute_with(|| {
|
||||
assert_ok!(<PenpalA as Chain>::System::set_storage(
|
||||
<PenpalA as Chain>::RuntimeOrigin::root(),
|
||||
vec![(
|
||||
PenpalCustomizableAssetFromSystemAssetHub::key().to_vec(),
|
||||
Location::new(2, [GlobalConsensus(ByGenesis(ZAGROS_GENESIS_HASH))]).encode(),
|
||||
)],
|
||||
));
|
||||
});
|
||||
PenpalA::force_create_foreign_asset(
|
||||
wnd_at_pezkuwichain_teyrchains.clone(),
|
||||
assets_owner.clone(),
|
||||
false,
|
||||
ASSET_MIN_BALANCE,
|
||||
vec![],
|
||||
);
|
||||
AssetHubPezkuwichain::force_create_foreign_asset(
|
||||
wnd_at_pezkuwichain_teyrchains.clone().try_into().unwrap(),
|
||||
assets_owner.clone(),
|
||||
false,
|
||||
ASSET_MIN_BALANCE,
|
||||
vec![],
|
||||
);
|
||||
|
||||
// fund Teyrchain's sender account
|
||||
PenpalA::mint_foreign_asset(
|
||||
<PenpalA as Chain>::RuntimeOrigin::signed(assets_owner.clone()),
|
||||
native_asset_location.clone(),
|
||||
sender.clone(),
|
||||
native_amount_to_send * 2,
|
||||
);
|
||||
PenpalA::mint_foreign_asset(
|
||||
<PenpalA as Chain>::RuntimeOrigin::signed(assets_owner.clone()),
|
||||
wnd_at_pezkuwichain_teyrchains.clone(),
|
||||
sender.clone(),
|
||||
foreign_amount_to_send * 2,
|
||||
);
|
||||
|
||||
// Init values for System Teyrchain
|
||||
let receiver = AssetHubPezkuwichainReceiver::get();
|
||||
let penpal_location_as_seen_by_ahr =
|
||||
AssetHubPezkuwichain::sibling_location_of(PenpalA::para_id());
|
||||
let sov_penpal_on_ahr =
|
||||
AssetHubPezkuwichain::sovereign_account_id_of(penpal_location_as_seen_by_ahr);
|
||||
|
||||
// fund Teyrchain's SA on AssetHub with the assets held in reserve
|
||||
AssetHubPezkuwichain::fund_accounts(vec![(
|
||||
sov_penpal_on_ahr.clone().into(),
|
||||
native_amount_to_send * 2,
|
||||
)]);
|
||||
AssetHubPezkuwichain::mint_foreign_asset(
|
||||
<AssetHubPezkuwichain as Chain>::RuntimeOrigin::signed(assets_owner),
|
||||
wnd_at_pezkuwichain_teyrchains.clone().try_into().unwrap(),
|
||||
sov_penpal_on_ahr,
|
||||
foreign_amount_to_send * 2,
|
||||
);
|
||||
|
||||
// Assets to send
|
||||
let assets: Vec<Asset> = vec![
|
||||
(Parent, native_amount_to_send).into(),
|
||||
(wnd_at_pezkuwichain_teyrchains.clone(), foreign_amount_to_send).into(),
|
||||
];
|
||||
let fee_asset_id = AssetId(Parent.into());
|
||||
|
||||
// Init Test
|
||||
let test_args = TestContext {
|
||||
sender: sender.clone(),
|
||||
receiver: receiver.clone(),
|
||||
args: TestArgs::new_para(
|
||||
destination.clone(),
|
||||
receiver.clone(),
|
||||
native_amount_to_send,
|
||||
assets.into(),
|
||||
None,
|
||||
fee_asset_id,
|
||||
),
|
||||
};
|
||||
let mut test = ParaToSystemParaTest::new(test_args);
|
||||
|
||||
// Query initial balances
|
||||
let sender_native_before = PenpalA::execute_with(|| {
|
||||
type ForeignAssets = <PenpalA as PenpalAPallet>::ForeignAssets;
|
||||
<ForeignAssets as Inspect<_>>::balance(native_asset_location.clone(), &sender)
|
||||
});
|
||||
let sender_wnds_before = PenpalA::execute_with(|| {
|
||||
type ForeignAssets = <PenpalA as PenpalAPallet>::ForeignAssets;
|
||||
<ForeignAssets as Inspect<_>>::balance(wnd_at_pezkuwichain_teyrchains.clone(), &sender)
|
||||
});
|
||||
let receiver_native_before = test.receiver.balance;
|
||||
let receiver_wnds_before = AssetHubPezkuwichain::execute_with(|| {
|
||||
type ForeignAssets = <AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::ForeignAssets;
|
||||
<ForeignAssets as Inspect<_>>::balance(
|
||||
wnd_at_pezkuwichain_teyrchains.clone().try_into().unwrap(),
|
||||
&receiver,
|
||||
)
|
||||
});
|
||||
|
||||
// Set assertions and dispatchables
|
||||
test.set_assertion::<PenpalA>(para_to_system_para_sender_assertions);
|
||||
test.set_assertion::<AssetHubPezkuwichain>(para_to_system_para_receiver_assertions);
|
||||
test.set_dispatchable::<PenpalA>(para_to_ah_transfer_assets);
|
||||
test.assert();
|
||||
|
||||
// Query final balances
|
||||
let sender_native_after = PenpalA::execute_with(|| {
|
||||
type ForeignAssets = <PenpalA as PenpalAPallet>::ForeignAssets;
|
||||
<ForeignAssets as Inspect<_>>::balance(native_asset_location, &sender)
|
||||
});
|
||||
let sender_wnds_after = PenpalA::execute_with(|| {
|
||||
type ForeignAssets = <PenpalA as PenpalAPallet>::ForeignAssets;
|
||||
<ForeignAssets as Inspect<_>>::balance(wnd_at_pezkuwichain_teyrchains.clone(), &sender)
|
||||
});
|
||||
let receiver_native_after = test.receiver.balance;
|
||||
let receiver_wnds_after = AssetHubPezkuwichain::execute_with(|| {
|
||||
type ForeignAssets = <AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::ForeignAssets;
|
||||
<ForeignAssets as Inspect<_>>::balance(
|
||||
wnd_at_pezkuwichain_teyrchains.try_into().unwrap(),
|
||||
&receiver,
|
||||
)
|
||||
});
|
||||
|
||||
// Sender's balance is reduced by amount sent plus delivery fees
|
||||
assert!(sender_native_after < sender_native_before - native_amount_to_send);
|
||||
// Sender's balance is reduced by foreign amount sent
|
||||
assert_eq!(sender_wnds_after, sender_wnds_before - foreign_amount_to_send);
|
||||
// Receiver's balance is increased
|
||||
assert!(receiver_native_after > receiver_native_before);
|
||||
// Receiver's balance increased by `amount_to_send - delivery_fees - bought_execution`;
|
||||
// `delivery_fees` might be paid from transfer or JIT, also `bought_execution` is unknown but
|
||||
// should be non-zero
|
||||
assert!(receiver_native_after < receiver_native_before + native_amount_to_send);
|
||||
// Receiver's balance is increased by foreign amount sent
|
||||
assert_eq!(receiver_wnds_after, receiver_wnds_before + foreign_amount_to_send);
|
||||
}
|
||||
|
||||
// ==============================================================================
|
||||
// ===== Transfer - Native + Bridged Assets - Teyrchain->AssetHub->Teyrchain ====
|
||||
// ==============================================================================
|
||||
/// Transfers of native asset plus bridged asset from Teyrchain to Teyrchain
|
||||
/// (through AssetHub reserve) with fees paid using native asset.
|
||||
#[test]
|
||||
fn transfer_foreign_assets_from_para_to_para_through_asset_hub() {
|
||||
// Init values for Teyrchain Origin
|
||||
let destination = PenpalA::sibling_location_of(PenpalB::para_id());
|
||||
let sender = PenpalASender::get();
|
||||
let roc_to_send: Balance = PEZKUWICHAIN_ED * 10000;
|
||||
let assets_owner = PenpalAssetOwner::get();
|
||||
let roc_location = RelayLocation::get();
|
||||
let sender_as_seen_by_ah = AssetHubPezkuwichain::sibling_location_of(PenpalA::para_id());
|
||||
let sov_of_sender_on_ah = AssetHubPezkuwichain::sovereign_account_id_of(sender_as_seen_by_ah);
|
||||
let receiver_as_seen_by_ah = AssetHubPezkuwichain::sibling_location_of(PenpalB::para_id());
|
||||
let sov_of_receiver_on_ah =
|
||||
AssetHubPezkuwichain::sovereign_account_id_of(receiver_as_seen_by_ah);
|
||||
let wnd_to_send = ASSET_HUB_PEZKUWICHAIN_ED * 10_000_000;
|
||||
|
||||
// Configure source and destination chains to trust AH as reserve of ZGR
|
||||
PenpalA::execute_with(|| {
|
||||
assert_ok!(<PenpalA as Chain>::System::set_storage(
|
||||
<PenpalA as Chain>::RuntimeOrigin::root(),
|
||||
vec![(
|
||||
PenpalCustomizableAssetFromSystemAssetHub::key().to_vec(),
|
||||
Location::new(2, [GlobalConsensus(ByGenesis(ZAGROS_GENESIS_HASH))]).encode(),
|
||||
)],
|
||||
));
|
||||
});
|
||||
PenpalB::execute_with(|| {
|
||||
assert_ok!(<PenpalB as Chain>::System::set_storage(
|
||||
<PenpalB as Chain>::RuntimeOrigin::root(),
|
||||
vec![(
|
||||
PenpalCustomizableAssetFromSystemAssetHub::key().to_vec(),
|
||||
Location::new(2, [GlobalConsensus(ByGenesis(ZAGROS_GENESIS_HASH))]).encode(),
|
||||
)],
|
||||
));
|
||||
});
|
||||
|
||||
// Register ZGR as foreign asset and transfer it around the Pezkuwichain ecosystem
|
||||
let wnd_at_pezkuwichain_teyrchains =
|
||||
Location::new(2, [Junction::GlobalConsensus(NetworkId::ByGenesis(ZAGROS_GENESIS_HASH))]);
|
||||
AssetHubPezkuwichain::force_create_foreign_asset(
|
||||
wnd_at_pezkuwichain_teyrchains.clone().try_into().unwrap(),
|
||||
assets_owner.clone(),
|
||||
false,
|
||||
ASSET_MIN_BALANCE,
|
||||
vec![],
|
||||
);
|
||||
PenpalA::force_create_foreign_asset(
|
||||
wnd_at_pezkuwichain_teyrchains.clone(),
|
||||
assets_owner.clone(),
|
||||
false,
|
||||
ASSET_MIN_BALANCE,
|
||||
vec![],
|
||||
);
|
||||
PenpalB::force_create_foreign_asset(
|
||||
wnd_at_pezkuwichain_teyrchains.clone(),
|
||||
assets_owner.clone(),
|
||||
false,
|
||||
ASSET_MIN_BALANCE,
|
||||
vec![],
|
||||
);
|
||||
|
||||
// fund Teyrchain's sender account
|
||||
PenpalA::mint_foreign_asset(
|
||||
<PenpalA as Chain>::RuntimeOrigin::signed(assets_owner.clone()),
|
||||
roc_location.clone(),
|
||||
sender.clone(),
|
||||
roc_to_send * 2,
|
||||
);
|
||||
PenpalA::mint_foreign_asset(
|
||||
<PenpalA as Chain>::RuntimeOrigin::signed(assets_owner.clone()),
|
||||
wnd_at_pezkuwichain_teyrchains.clone(),
|
||||
sender.clone(),
|
||||
wnd_to_send * 2,
|
||||
);
|
||||
// fund the Teyrchain Origin's SA on Asset Hub with the assets held in reserve
|
||||
AssetHubPezkuwichain::fund_accounts(vec![(
|
||||
sov_of_sender_on_ah.clone().into(),
|
||||
roc_to_send * 2,
|
||||
)]);
|
||||
AssetHubPezkuwichain::mint_foreign_asset(
|
||||
<AssetHubPezkuwichain as Chain>::RuntimeOrigin::signed(assets_owner),
|
||||
wnd_at_pezkuwichain_teyrchains.clone().try_into().unwrap(),
|
||||
sov_of_sender_on_ah.clone(),
|
||||
wnd_to_send * 2,
|
||||
);
|
||||
|
||||
// Init values for Teyrchain Destination
|
||||
let receiver = PenpalBReceiver::get();
|
||||
|
||||
// Assets to send
|
||||
let assets: Vec<Asset> = vec![
|
||||
(roc_location.clone(), roc_to_send).into(),
|
||||
(wnd_at_pezkuwichain_teyrchains.clone(), wnd_to_send).into(),
|
||||
];
|
||||
let fee_asset_id: AssetId = roc_location.clone().into();
|
||||
|
||||
// Init Test
|
||||
let test_args = TestContext {
|
||||
sender: sender.clone(),
|
||||
receiver: receiver.clone(),
|
||||
args: TestArgs::new_para(
|
||||
destination,
|
||||
receiver.clone(),
|
||||
roc_to_send,
|
||||
assets.into(),
|
||||
None,
|
||||
fee_asset_id,
|
||||
),
|
||||
};
|
||||
let mut test = ParaToParaThroughAHTest::new(test_args);
|
||||
|
||||
// Query initial balances
|
||||
let sender_rocs_before = PenpalA::execute_with(|| {
|
||||
type ForeignAssets = <PenpalA as PenpalAPallet>::ForeignAssets;
|
||||
<ForeignAssets as Inspect<_>>::balance(roc_location.clone(), &sender)
|
||||
});
|
||||
let sender_wnds_before = PenpalA::execute_with(|| {
|
||||
type ForeignAssets = <PenpalA as PenpalAPallet>::ForeignAssets;
|
||||
<ForeignAssets as Inspect<_>>::balance(wnd_at_pezkuwichain_teyrchains.clone(), &sender)
|
||||
});
|
||||
let rocs_in_sender_reserve_on_ahr_before =
|
||||
<AssetHubPezkuwichain as Chain>::account_data_of(sov_of_sender_on_ah.clone()).free;
|
||||
let wnds_in_sender_reserve_on_ahr_before = AssetHubPezkuwichain::execute_with(|| {
|
||||
type Assets = <AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::ForeignAssets;
|
||||
<Assets as Inspect<_>>::balance(
|
||||
wnd_at_pezkuwichain_teyrchains.clone().try_into().unwrap(),
|
||||
&sov_of_sender_on_ah,
|
||||
)
|
||||
});
|
||||
let rocs_in_receiver_reserve_on_ahr_before =
|
||||
<AssetHubPezkuwichain as Chain>::account_data_of(sov_of_receiver_on_ah.clone()).free;
|
||||
let wnds_in_receiver_reserve_on_ahr_before = AssetHubPezkuwichain::execute_with(|| {
|
||||
type Assets = <AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::ForeignAssets;
|
||||
<Assets as Inspect<_>>::balance(
|
||||
wnd_at_pezkuwichain_teyrchains.clone().try_into().unwrap(),
|
||||
&sov_of_receiver_on_ah,
|
||||
)
|
||||
});
|
||||
let receiver_rocs_before = PenpalB::execute_with(|| {
|
||||
type ForeignAssets = <PenpalB as PenpalBPallet>::ForeignAssets;
|
||||
<ForeignAssets as Inspect<_>>::balance(roc_location.clone(), &receiver)
|
||||
});
|
||||
let receiver_wnds_before = PenpalB::execute_with(|| {
|
||||
type ForeignAssets = <PenpalB as PenpalBPallet>::ForeignAssets;
|
||||
<ForeignAssets as Inspect<_>>::balance(wnd_at_pezkuwichain_teyrchains.clone(), &receiver)
|
||||
});
|
||||
|
||||
// Set assertions and dispatchables
|
||||
test.set_assertion::<PenpalA>(para_to_para_through_hop_sender_assertions);
|
||||
test.set_assertion::<AssetHubPezkuwichain>(para_to_para_assethub_hop_assertions);
|
||||
test.set_assertion::<PenpalB>(para_to_para_through_hop_receiver_assertions);
|
||||
test.set_dispatchable::<PenpalA>(para_to_para_transfer_assets_through_ah);
|
||||
test.assert();
|
||||
|
||||
// Query final balances
|
||||
let sender_rocs_after = PenpalA::execute_with(|| {
|
||||
type ForeignAssets = <PenpalA as PenpalAPallet>::ForeignAssets;
|
||||
<ForeignAssets as Inspect<_>>::balance(roc_location.clone(), &sender)
|
||||
});
|
||||
let sender_wnds_after = PenpalA::execute_with(|| {
|
||||
type ForeignAssets = <PenpalA as PenpalAPallet>::ForeignAssets;
|
||||
<ForeignAssets as Inspect<_>>::balance(wnd_at_pezkuwichain_teyrchains.clone(), &sender)
|
||||
});
|
||||
let wnds_in_sender_reserve_on_ahr_after = AssetHubPezkuwichain::execute_with(|| {
|
||||
type Assets = <AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::ForeignAssets;
|
||||
<Assets as Inspect<_>>::balance(
|
||||
wnd_at_pezkuwichain_teyrchains.clone().try_into().unwrap(),
|
||||
&sov_of_sender_on_ah,
|
||||
)
|
||||
});
|
||||
let rocs_in_sender_reserve_on_ahr_after =
|
||||
<AssetHubPezkuwichain as Chain>::account_data_of(sov_of_sender_on_ah).free;
|
||||
let wnds_in_receiver_reserve_on_ahr_after = AssetHubPezkuwichain::execute_with(|| {
|
||||
type Assets = <AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::ForeignAssets;
|
||||
<Assets as Inspect<_>>::balance(
|
||||
wnd_at_pezkuwichain_teyrchains.clone().try_into().unwrap(),
|
||||
&sov_of_receiver_on_ah,
|
||||
)
|
||||
});
|
||||
let rocs_in_receiver_reserve_on_ahr_after =
|
||||
<AssetHubPezkuwichain as Chain>::account_data_of(sov_of_receiver_on_ah).free;
|
||||
let receiver_rocs_after = PenpalB::execute_with(|| {
|
||||
type ForeignAssets = <PenpalB as PenpalBPallet>::ForeignAssets;
|
||||
<ForeignAssets as Inspect<_>>::balance(roc_location, &receiver)
|
||||
});
|
||||
let receiver_wnds_after = PenpalB::execute_with(|| {
|
||||
type ForeignAssets = <PenpalB as PenpalBPallet>::ForeignAssets;
|
||||
<ForeignAssets as Inspect<_>>::balance(wnd_at_pezkuwichain_teyrchains, &receiver)
|
||||
});
|
||||
|
||||
// Sender's balance is reduced by amount sent plus delivery fees
|
||||
assert!(sender_rocs_after < sender_rocs_before - roc_to_send);
|
||||
assert_eq!(sender_wnds_after, sender_wnds_before - wnd_to_send);
|
||||
// Sovereign accounts on reserve are changed accordingly
|
||||
assert_eq!(
|
||||
rocs_in_sender_reserve_on_ahr_after,
|
||||
rocs_in_sender_reserve_on_ahr_before - roc_to_send
|
||||
);
|
||||
assert_eq!(
|
||||
wnds_in_sender_reserve_on_ahr_after,
|
||||
wnds_in_sender_reserve_on_ahr_before - wnd_to_send
|
||||
);
|
||||
assert!(rocs_in_receiver_reserve_on_ahr_after > rocs_in_receiver_reserve_on_ahr_before);
|
||||
assert_eq!(
|
||||
wnds_in_receiver_reserve_on_ahr_after,
|
||||
wnds_in_receiver_reserve_on_ahr_before + wnd_to_send
|
||||
);
|
||||
// Receiver's balance is increased
|
||||
assert!(receiver_rocs_after > receiver_rocs_before);
|
||||
assert_eq!(receiver_wnds_after, receiver_wnds_before + wnd_to_send);
|
||||
}
|
||||
|
||||
// ==============================================================================================
|
||||
// ==== Bidirectional Transfer - Native + Teleportable Foreign Assets - Teyrchain<->AssetHub ====
|
||||
// ==============================================================================================
|
||||
/// Transfers of native asset plus teleportable foreign asset from Teyrchain to AssetHub and back
|
||||
/// with fees paid using native asset.
|
||||
#[test]
|
||||
fn bidirectional_teleport_foreign_asset_between_para_and_asset_hub_using_explicit_transfer_types() {
|
||||
do_bidirectional_teleport_foreign_assets_between_para_and_asset_hub_using_xt(
|
||||
para_to_asset_hub_teleport_foreign_assets,
|
||||
asset_hub_to_para_teleport_foreign_assets,
|
||||
);
|
||||
}
|
||||
|
||||
// ===============================================================
|
||||
// ===== Transfer - Native Asset - Relay->AssetHub->Teyrchain ====
|
||||
// ===============================================================
|
||||
/// Transfers of native asset Relay to Teyrchain (using AssetHub reserve). Teyrchains want to avoid
|
||||
/// managing SAs on all system chains, thus want all their HEZ-in-reserve to be held in their
|
||||
/// Sovereign Account on Asset Hub.
|
||||
#[test]
|
||||
fn transfer_native_asset_from_relay_to_para_through_asset_hub() {
|
||||
// Init values for Relay
|
||||
let destination = Pezkuwichain::child_location_of(PenpalA::para_id());
|
||||
let sender = PezkuwichainSender::get();
|
||||
let amount_to_send: Balance = PEZKUWICHAIN_ED * 1000;
|
||||
|
||||
// Init values for Teyrchain
|
||||
let relay_native_asset_location = RelayLocation::get();
|
||||
let receiver = PenpalAReceiver::get();
|
||||
|
||||
// Init Test
|
||||
let test_args = TestContext {
|
||||
sender,
|
||||
receiver: receiver.clone(),
|
||||
args: TestArgs::new_relay(destination.clone(), receiver.clone(), amount_to_send),
|
||||
};
|
||||
let mut test = RelayToParaThroughAHTest::new(test_args);
|
||||
|
||||
let sov_penpal_on_ah = AssetHubPezkuwichain::sovereign_account_id_of(
|
||||
AssetHubPezkuwichain::sibling_location_of(PenpalA::para_id()),
|
||||
);
|
||||
// Query initial balances
|
||||
let sender_balance_before = test.sender.balance;
|
||||
let sov_penpal_on_ah_before = AssetHubPezkuwichain::execute_with(|| {
|
||||
<AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::Balances::free_balance(
|
||||
sov_penpal_on_ah.clone(),
|
||||
)
|
||||
});
|
||||
let receiver_assets_before = PenpalA::execute_with(|| {
|
||||
type ForeignAssets = <PenpalA as PenpalAPallet>::ForeignAssets;
|
||||
<ForeignAssets as Inspect<_>>::balance(relay_native_asset_location.clone(), &receiver)
|
||||
});
|
||||
|
||||
fn relay_assertions(t: RelayToParaThroughAHTest) {
|
||||
type RuntimeEvent = <Pezkuwichain as Chain>::RuntimeEvent;
|
||||
Pezkuwichain::assert_xcm_pallet_attempted_complete(None);
|
||||
assert_expected_events!(
|
||||
Pezkuwichain,
|
||||
vec![
|
||||
// Amount to teleport is withdrawn from Sender
|
||||
RuntimeEvent::Balances(pezpallet_balances::Event::Burned { who, amount }) => {
|
||||
who: *who == t.sender.account_id,
|
||||
amount: *amount == t.args.amount,
|
||||
},
|
||||
// Amount to teleport is deposited in Relay's `CheckAccount`
|
||||
RuntimeEvent::Balances(pezpallet_balances::Event::Minted { who, amount }) => {
|
||||
who: *who == <Pezkuwichain as PezkuwichainPallet>::XcmPallet::check_account(),
|
||||
amount: *amount == t.args.amount,
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
fn asset_hub_assertions(_: RelayToParaThroughAHTest) {
|
||||
type RuntimeEvent = <AssetHubPezkuwichain as Chain>::RuntimeEvent;
|
||||
let sov_penpal_on_ah = AssetHubPezkuwichain::sovereign_account_id_of(
|
||||
AssetHubPezkuwichain::sibling_location_of(PenpalA::para_id()),
|
||||
);
|
||||
assert_expected_events!(
|
||||
AssetHubPezkuwichain,
|
||||
vec![
|
||||
// Deposited to receiver teyrchain SA
|
||||
RuntimeEvent::Balances(
|
||||
pezpallet_balances::Event::Minted { who, .. }
|
||||
) => {
|
||||
who: *who == sov_penpal_on_ah,
|
||||
},
|
||||
RuntimeEvent::MessageQueue(
|
||||
pezpallet_message_queue::Event::Processed { success: true, .. }
|
||||
) => {},
|
||||
]
|
||||
);
|
||||
}
|
||||
fn penpal_assertions(t: RelayToParaThroughAHTest) {
|
||||
type RuntimeEvent = <PenpalA as Chain>::RuntimeEvent;
|
||||
// Assets in t are relative to the relay chain. The asset here should be relative to
|
||||
// Penpal, so parents: 1.
|
||||
let expected_id: Location = Location { parents: 1, interior: Here };
|
||||
|
||||
assert_expected_events!(
|
||||
PenpalA,
|
||||
vec![
|
||||
RuntimeEvent::ForeignAssets(pezpallet_assets::Event::Issued { asset_id, owner, .. }) => {
|
||||
asset_id: *asset_id == expected_id,
|
||||
owner: *owner == t.receiver.account_id,
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
fn transfer_assets_dispatchable(t: RelayToParaThroughAHTest) -> DispatchResult {
|
||||
let fee: Asset = t
|
||||
.args
|
||||
.assets
|
||||
.inner()
|
||||
.iter()
|
||||
.find(|a| a.id == t.args.fee_asset_id)
|
||||
.cloned()
|
||||
.unwrap();
|
||||
let asset_hub_location = Pezkuwichain::child_location_of(AssetHubPezkuwichain::para_id());
|
||||
let context = PezkuwichainUniversalLocation::get();
|
||||
|
||||
// reanchor fees to the view of destination (Penpal)
|
||||
let mut remote_fees = fee.clone().reanchored(&t.args.dest, &context).unwrap();
|
||||
if let Fungible(ref mut amount) = remote_fees.fun {
|
||||
// we already spent some fees along the way, just use half of what we started with
|
||||
*amount = *amount / 2;
|
||||
}
|
||||
let xcm_on_final_dest = Xcm::<()>(vec![
|
||||
BuyExecution { fees: remote_fees, weight_limit: t.args.weight_limit.clone() },
|
||||
DepositAsset {
|
||||
assets: Wild(AllCounted(t.args.assets.len() as u32)),
|
||||
beneficiary: t.args.beneficiary,
|
||||
},
|
||||
]);
|
||||
|
||||
// reanchor final dest (Penpal) to the view of hop (Asset Hub)
|
||||
let mut dest = t.args.dest.clone();
|
||||
dest.reanchor(&asset_hub_location, &context).unwrap();
|
||||
// on Asset Hub, forward assets to Penpal
|
||||
let xcm_on_hop = Xcm::<()>(vec![DepositReserveAsset {
|
||||
assets: Wild(AllCounted(t.args.assets.len() as u32)),
|
||||
dest,
|
||||
xcm: xcm_on_final_dest,
|
||||
}]);
|
||||
|
||||
Dmp::make_teyrchain_reachable(AssetHubPezkuwichain::para_id());
|
||||
|
||||
// First leg is a teleport, from there a local-reserve-transfer to final dest
|
||||
<Pezkuwichain as PezkuwichainPallet>::XcmPallet::transfer_assets_using_type_and_then(
|
||||
t.signed_origin,
|
||||
bx!(asset_hub_location.into()),
|
||||
bx!(t.args.assets.into()),
|
||||
bx!(TransferType::Teleport),
|
||||
bx!(fee.id.into()),
|
||||
bx!(TransferType::Teleport),
|
||||
bx!(VersionedXcm::from(xcm_on_hop)),
|
||||
t.args.weight_limit,
|
||||
)
|
||||
}
|
||||
|
||||
// Set assertions and dispatchables
|
||||
test.set_assertion::<Pezkuwichain>(relay_assertions);
|
||||
test.set_assertion::<AssetHubPezkuwichain>(asset_hub_assertions);
|
||||
test.set_assertion::<PenpalA>(penpal_assertions);
|
||||
test.set_dispatchable::<Pezkuwichain>(transfer_assets_dispatchable);
|
||||
test.assert();
|
||||
|
||||
// Query final balances
|
||||
let sender_balance_after = test.sender.balance;
|
||||
let sov_penpal_on_ah_after = AssetHubPezkuwichain::execute_with(|| {
|
||||
<AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::Balances::free_balance(
|
||||
sov_penpal_on_ah,
|
||||
)
|
||||
});
|
||||
let receiver_assets_after = PenpalA::execute_with(|| {
|
||||
type ForeignAssets = <PenpalA as PenpalAPallet>::ForeignAssets;
|
||||
<ForeignAssets as Inspect<_>>::balance(relay_native_asset_location, &receiver)
|
||||
});
|
||||
|
||||
// Sender's balance is reduced by amount sent plus delivery fees
|
||||
assert!(sender_balance_after < sender_balance_before - amount_to_send);
|
||||
// SA on AH balance is increased
|
||||
assert!(sov_penpal_on_ah_after > sov_penpal_on_ah_before);
|
||||
// Receiver's asset balance is increased
|
||||
assert!(receiver_assets_after > receiver_assets_before);
|
||||
// Receiver's asset balance increased by `amount_to_send - delivery_fees - bought_execution`;
|
||||
// `delivery_fees` might be paid from transfer or JIT, also `bought_execution` is unknown but
|
||||
// should be non-zero
|
||||
assert!(receiver_assets_after < receiver_assets_before + amount_to_send);
|
||||
}
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
mod claim_assets;
|
||||
mod hybrid_transfers;
|
||||
mod reserve_transfer;
|
||||
mod reward_pool;
|
||||
mod send;
|
||||
mod set_xcm_versions;
|
||||
mod swap;
|
||||
mod teleport;
|
||||
mod treasury;
|
||||
mod xcm_fee_estimation;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! create_pool_with_roc_on {
|
||||
// default amounts
|
||||
( $chain:ident, $asset_id:expr, $is_foreign:expr, $asset_owner:expr ) => {
|
||||
$crate::create_pool_with_roc_on!(
|
||||
$chain,
|
||||
$asset_id,
|
||||
$is_foreign,
|
||||
$asset_owner,
|
||||
1_000_000_000_000,
|
||||
2_000_000_000_000
|
||||
);
|
||||
};
|
||||
|
||||
// custom amounts
|
||||
( $chain:ident, $asset_id:expr, $is_foreign:expr, $asset_owner:expr, $roc_amount:expr, $asset_amount:expr ) => {
|
||||
emulated_integration_tests_common::impls::paste::paste! {
|
||||
<$chain>::execute_with(|| {
|
||||
type RuntimeEvent = <$chain as Chain>::RuntimeEvent;
|
||||
let owner = $asset_owner;
|
||||
let signed_owner = <$chain as Chain>::RuntimeOrigin::signed(owner.clone());
|
||||
let roc_location: Location = Parent.into();
|
||||
if $is_foreign {
|
||||
assert_ok!(<$chain as [<$chain Pallet>]>::ForeignAssets::mint(
|
||||
signed_owner.clone(),
|
||||
$asset_id.clone().into(),
|
||||
owner.clone().into(),
|
||||
10_000_000_000_000, // For it to have more than enough.
|
||||
));
|
||||
} else {
|
||||
let asset_id = match $asset_id.interior.last() {
|
||||
Some(GeneralIndex(id)) => *id as u32,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
assert_ok!(<$chain as [<$chain Pallet>]>::Assets::mint(
|
||||
signed_owner.clone(),
|
||||
asset_id.into(),
|
||||
owner.clone().into(),
|
||||
10_000_000_000_000, // For it to have more than enough.
|
||||
));
|
||||
}
|
||||
|
||||
assert_ok!(<$chain as [<$chain Pallet>]>::AssetConversion::create_pool(
|
||||
signed_owner.clone(),
|
||||
Box::new(roc_location.clone()),
|
||||
Box::new($asset_id.clone()),
|
||||
));
|
||||
|
||||
assert_expected_events!(
|
||||
$chain,
|
||||
vec![
|
||||
RuntimeEvent::AssetConversion(pezpallet_asset_conversion::Event::PoolCreated { .. }) => {},
|
||||
]
|
||||
);
|
||||
|
||||
assert_ok!(<$chain as [<$chain Pallet>]>::AssetConversion::add_liquidity(
|
||||
signed_owner,
|
||||
Box::new(roc_location),
|
||||
Box::new($asset_id),
|
||||
$roc_amount,
|
||||
$asset_amount,
|
||||
0,
|
||||
0,
|
||||
owner.into()
|
||||
));
|
||||
|
||||
assert_expected_events!(
|
||||
$chain,
|
||||
vec![
|
||||
RuntimeEvent::AssetConversion(pezpallet_asset_conversion::Event::LiquidityAdded { .. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
+1711
File diff suppressed because it is too large
Load Diff
+114
@@ -0,0 +1,114 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::imports::*;
|
||||
use pezframe_support::{pezsp_runtime::traits::Dispatchable, traits::schedule::DispatchTime};
|
||||
use xcm_executor::traits::ConvertLocation;
|
||||
|
||||
#[test]
|
||||
fn treasury_creates_asset_reward_pool() {
|
||||
AssetHubPezkuwichain::execute_with(|| {
|
||||
type RuntimeEvent = <AssetHubPezkuwichain as Chain>::RuntimeEvent;
|
||||
type Balances = <AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::Balances;
|
||||
|
||||
let treasurer =
|
||||
Location::new(1, [Plurality { id: BodyId::Treasury, part: BodyPart::Voice }]);
|
||||
let treasurer_account =
|
||||
ahr_xcm_config::LocationToAccountId::convert_location(&treasurer).unwrap();
|
||||
|
||||
assert_ok!(Balances::force_set_balance(
|
||||
<AssetHubPezkuwichain as Chain>::RuntimeOrigin::root(),
|
||||
treasurer_account.clone().into(),
|
||||
ASSET_HUB_PEZKUWICHAIN_ED * 100_000,
|
||||
));
|
||||
|
||||
let events = AssetHubPezkuwichain::events();
|
||||
match events.iter().last() {
|
||||
Some(RuntimeEvent::Balances(pezpallet_balances::Event::BalanceSet { who, .. })) => {
|
||||
assert_eq!(*who, treasurer_account)
|
||||
},
|
||||
_ => panic!("Expected Balances::BalanceSet event"),
|
||||
}
|
||||
});
|
||||
|
||||
Pezkuwichain::execute_with(|| {
|
||||
type AssetHubPezkuwichainRuntimeCall = <AssetHubPezkuwichain as Chain>::RuntimeCall;
|
||||
type AssetHubPezkuwichainRuntime = <AssetHubPezkuwichain as Chain>::Runtime;
|
||||
type PezkuwichainRuntimeCall = <Pezkuwichain as Chain>::RuntimeCall;
|
||||
type PezkuwichainRuntime = <Pezkuwichain as Chain>::Runtime;
|
||||
type PezkuwichainRuntimeEvent = <Pezkuwichain as Chain>::RuntimeEvent;
|
||||
type PezkuwichainRuntimeOrigin = <Pezkuwichain as Chain>::RuntimeOrigin;
|
||||
|
||||
Dmp::make_teyrchain_reachable(AssetHubPezkuwichain::para_id());
|
||||
|
||||
let staked_asset_id = bx!(RelayLocation::get());
|
||||
let reward_asset_id = bx!(RelayLocation::get());
|
||||
|
||||
let reward_rate_per_block = 1_000_000_000;
|
||||
let lifetime = 1_000_000_000;
|
||||
let admin = None;
|
||||
|
||||
let create_pool_call =
|
||||
PezkuwichainRuntimeCall::XcmPallet(pezpallet_xcm::Call::<PezkuwichainRuntime>::send {
|
||||
dest: bx!(VersionedLocation::V4(
|
||||
xcm::v4::Junction::Teyrchain(AssetHubPezkuwichain::para_id().into()).into()
|
||||
)),
|
||||
message: bx!(VersionedXcm::V5(Xcm(vec![
|
||||
UnpaidExecution { weight_limit: Unlimited, check_origin: None },
|
||||
Transact {
|
||||
origin_kind: OriginKind::SovereignAccount,
|
||||
fallback_max_weight: None,
|
||||
call: AssetHubPezkuwichainRuntimeCall::AssetRewards(
|
||||
pezpallet_asset_rewards::Call::<AssetHubPezkuwichainRuntime>::create_pool {
|
||||
staked_asset_id,
|
||||
reward_asset_id,
|
||||
reward_rate_per_block,
|
||||
expiry: DispatchTime::After(lifetime),
|
||||
admin
|
||||
}
|
||||
)
|
||||
.encode()
|
||||
.into(),
|
||||
}
|
||||
]))),
|
||||
});
|
||||
|
||||
let treasury_origin: PezkuwichainRuntimeOrigin = Treasurer.into();
|
||||
assert_ok!(create_pool_call.dispatch(treasury_origin));
|
||||
|
||||
assert_expected_events!(
|
||||
Pezkuwichain,
|
||||
vec![
|
||||
PezkuwichainRuntimeEvent::XcmPallet(pezpallet_xcm::Event::Sent { .. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
AssetHubPezkuwichain::execute_with(|| {
|
||||
type Runtime = <AssetHubPezkuwichain as Chain>::Runtime;
|
||||
type RuntimeEvent = <AssetHubPezkuwichain as Chain>::RuntimeEvent;
|
||||
|
||||
assert_eq!(1, pezpallet_asset_rewards::Pools::<Runtime>::iter().count());
|
||||
|
||||
let events = AssetHubPezkuwichain::events();
|
||||
match events.iter().last() {
|
||||
Some(RuntimeEvent::MessageQueue(pezpallet_message_queue::Event::Processed {
|
||||
success: true,
|
||||
..
|
||||
})) => (),
|
||||
_ => panic!("Expected MessageQueue::Processed event"),
|
||||
}
|
||||
});
|
||||
}
|
||||
+197
@@ -0,0 +1,197 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::{create_pool_with_roc_on, imports::*};
|
||||
|
||||
/// Relay Chain should be able to execute `Transact` instructions in System Teyrchain
|
||||
/// when `OriginKind::Superuser`.
|
||||
#[test]
|
||||
fn send_transact_as_superuser_from_relay_to_asset_hub_works() {
|
||||
AssetHubPezkuwichain::force_create_asset_from_relay_as_root(
|
||||
ASSET_ID,
|
||||
ASSET_MIN_BALANCE,
|
||||
true,
|
||||
AssetHubPezkuwichainSender::get().into(),
|
||||
Some(Weight::from_parts(144_933_000, 3675)),
|
||||
)
|
||||
}
|
||||
|
||||
/// We tests two things here:
|
||||
/// - Teyrchain should be able to send XCM paying its fee at Asset Hub using system asset
|
||||
/// - Teyrchain should be able to create a new Foreign Asset at Asset Hub
|
||||
#[test]
|
||||
fn send_xcm_from_para_to_asset_hub_paying_fee_with_system_asset() {
|
||||
let para_sovereign_account = AssetHubPezkuwichain::sovereign_account_id_of(
|
||||
AssetHubPezkuwichain::sibling_location_of(PenpalA::para_id()),
|
||||
);
|
||||
let asset_location_on_penpal = Location::new(
|
||||
0,
|
||||
[Junction::PalletInstance(ASSETS_PALLET_ID), Junction::GeneralIndex(ASSET_ID.into())],
|
||||
);
|
||||
let foreign_asset_at_asset_hub =
|
||||
Location::new(1, [Junction::Teyrchain(PenpalA::para_id().into())])
|
||||
.appended_with(asset_location_on_penpal)
|
||||
.unwrap();
|
||||
|
||||
// Encoded `create_asset` call to be executed in AssetHub
|
||||
let call = AssetHubPezkuwichain::create_foreign_asset_call(
|
||||
foreign_asset_at_asset_hub.clone(),
|
||||
ASSET_MIN_BALANCE,
|
||||
para_sovereign_account.clone(),
|
||||
);
|
||||
|
||||
let origin_kind = OriginKind::Xcm;
|
||||
let fee_amount = ASSET_HUB_PEZKUWICHAIN_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(AssetHubPezkuwichain::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
|
||||
AssetHubPezkuwichain::fund_accounts(vec![(
|
||||
para_sovereign_account.clone().into(),
|
||||
ASSET_HUB_PEZKUWICHAIN_ED * 10000000000,
|
||||
)]);
|
||||
|
||||
PenpalA::execute_with(|| {
|
||||
assert_ok!(<PenpalA as PenpalAPallet>::PezkuwiXcm::send(
|
||||
root_origin,
|
||||
bx!(system_para_destination),
|
||||
bx!(xcm),
|
||||
));
|
||||
|
||||
PenpalA::assert_xcm_pallet_sent();
|
||||
});
|
||||
|
||||
AssetHubPezkuwichain::execute_with(|| {
|
||||
type RuntimeEvent = <AssetHubPezkuwichain as Chain>::RuntimeEvent;
|
||||
AssetHubPezkuwichain::assert_xcmp_queue_success(None);
|
||||
assert_expected_events!(
|
||||
AssetHubPezkuwichain,
|
||||
vec![
|
||||
// Burned the fee
|
||||
RuntimeEvent::Balances(pezpallet_balances::Event::Burned { who, amount }) => {
|
||||
who: *who == para_sovereign_account,
|
||||
amount: *amount == fee_amount,
|
||||
},
|
||||
// Foreign Asset created
|
||||
RuntimeEvent::ForeignAssets(pezpallet_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 = <AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::ForeignAssets;
|
||||
assert!(ForeignAssets::asset_exists(foreign_asset_at_asset_hub));
|
||||
});
|
||||
}
|
||||
|
||||
/// We tests two things here:
|
||||
/// - Teyrchain should be able to send XCM paying its fee at Asset Hub using sufficient asset
|
||||
/// - Teyrchain should be able to create a new Asset at Asset Hub
|
||||
#[test]
|
||||
fn send_xcm_from_para_to_asset_hub_paying_fee_with_sufficient_asset() {
|
||||
let para_sovereign_account = AssetHubPezkuwichain::sovereign_account_id_of(
|
||||
AssetHubPezkuwichain::sibling_location_of(PenpalA::para_id()),
|
||||
);
|
||||
|
||||
// Force create and mint sufficient assets for Teyrchain's sovereign account
|
||||
AssetHubPezkuwichain::force_create_and_mint_asset(
|
||||
ASSET_ID,
|
||||
ASSET_MIN_BALANCE,
|
||||
true,
|
||||
para_sovereign_account.clone(),
|
||||
Some(Weight::from_parts(144_933_000, 3675)),
|
||||
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 = AssetHubPezkuwichain::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 asset_location =
|
||||
Location::new(0, [PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())]);
|
||||
|
||||
let root_origin = <PenpalA as Chain>::RuntimeOrigin::root();
|
||||
let system_para_destination =
|
||||
PenpalA::sibling_location_of(AssetHubPezkuwichain::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
|
||||
AssetHubPezkuwichain::fund_accounts(vec![(
|
||||
para_sovereign_account.clone().into(),
|
||||
ASSET_HUB_PEZKUWICHAIN_ED * 10000000000,
|
||||
)]);
|
||||
|
||||
create_pool_with_roc_on!(
|
||||
AssetHubPezkuwichain,
|
||||
asset_location,
|
||||
false,
|
||||
para_sovereign_account.clone(),
|
||||
9_000_000_000_000_000,
|
||||
9_000_000_000_000
|
||||
);
|
||||
|
||||
PenpalA::execute_with(|| {
|
||||
assert_ok!(<PenpalA as PenpalAPallet>::PezkuwiXcm::send(
|
||||
root_origin,
|
||||
bx!(system_para_destination),
|
||||
bx!(xcm),
|
||||
));
|
||||
|
||||
PenpalA::assert_xcm_pallet_sent();
|
||||
});
|
||||
|
||||
AssetHubPezkuwichain::execute_with(|| {
|
||||
type RuntimeEvent = <AssetHubPezkuwichain as Chain>::RuntimeEvent;
|
||||
AssetHubPezkuwichain::assert_xcmp_queue_success(None);
|
||||
assert_expected_events!(
|
||||
AssetHubPezkuwichain,
|
||||
vec![
|
||||
// Burned the fee
|
||||
RuntimeEvent::Assets(pezpallet_assets::Event::Burned { asset_id, owner, balance }) => {
|
||||
asset_id: *asset_id == ASSET_ID,
|
||||
owner: *owner == para_sovereign_account,
|
||||
balance: *balance == fee_amount,
|
||||
},
|
||||
// Asset created
|
||||
RuntimeEvent::Assets(pezpallet_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,
|
||||
},
|
||||
]
|
||||
);
|
||||
});
|
||||
}
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::imports::*;
|
||||
|
||||
#[test]
|
||||
fn relay_sets_system_para_xcm_supported_version() {
|
||||
// Init tests variables
|
||||
let sudo_origin = <Pezkuwichain as Chain>::RuntimeOrigin::root();
|
||||
let system_para_destination: Location =
|
||||
Pezkuwichain::child_location_of(AssetHubPezkuwichain::para_id());
|
||||
|
||||
// Relay Chain sets supported version for Asset Teyrchain
|
||||
Pezkuwichain::execute_with(|| {
|
||||
assert_ok!(<Pezkuwichain as PezkuwichainPallet>::XcmPallet::force_xcm_version(
|
||||
sudo_origin,
|
||||
bx!(system_para_destination.clone()),
|
||||
XCM_V3
|
||||
));
|
||||
|
||||
type RuntimeEvent = <Pezkuwichain as Chain>::RuntimeEvent;
|
||||
|
||||
assert_expected_events!(
|
||||
Pezkuwichain,
|
||||
vec![
|
||||
RuntimeEvent::XcmPallet(pezpallet_xcm::Event::SupportedVersionChanged {
|
||||
location,
|
||||
version: XCM_V3
|
||||
}) => { location: *location == system_para_destination, },
|
||||
]
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn system_para_sets_relay_xcm_supported_version() {
|
||||
// Init test variables
|
||||
let parent_location = AssetHubPezkuwichain::parent_location();
|
||||
let force_xcm_version_call =
|
||||
<AssetHubPezkuwichain as Chain>::RuntimeCall::PezkuwiXcm(pezpallet_xcm::Call::<
|
||||
<AssetHubPezkuwichain as Chain>::Runtime,
|
||||
>::force_xcm_version {
|
||||
location: bx!(parent_location.clone()),
|
||||
version: XCM_V3,
|
||||
})
|
||||
.encode()
|
||||
.into();
|
||||
|
||||
// System Teyrchain sets supported version for Relay Chain through it
|
||||
Pezkuwichain::send_unpaid_transact_to_teyrchain_as_root(
|
||||
AssetHubPezkuwichain::para_id(),
|
||||
force_xcm_version_call,
|
||||
);
|
||||
|
||||
// System Teyrchain receive the XCM message
|
||||
AssetHubPezkuwichain::execute_with(|| {
|
||||
type RuntimeEvent = <AssetHubPezkuwichain as Chain>::RuntimeEvent;
|
||||
|
||||
AssetHubPezkuwichain::assert_dmp_queue_complete(Some(Weight::from_parts(115_294_000, 0)));
|
||||
|
||||
assert_expected_events!(
|
||||
AssetHubPezkuwichain,
|
||||
vec![
|
||||
RuntimeEvent::PezkuwiXcm(pezpallet_xcm::Event::SupportedVersionChanged {
|
||||
location,
|
||||
version: XCM_V3
|
||||
}) => { location: *location == parent_location, },
|
||||
]
|
||||
);
|
||||
});
|
||||
}
|
||||
+449
@@ -0,0 +1,449 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::imports::*;
|
||||
|
||||
#[test]
|
||||
fn swap_locally_on_chain_using_local_assets() {
|
||||
let asset_native = Box::new(Location::try_from(RelayLocation::get()).unwrap());
|
||||
let asset_one = Box::new(Location::new(
|
||||
0,
|
||||
[Junction::PalletInstance(ASSETS_PALLET_ID), Junction::GeneralIndex(ASSET_ID.into())],
|
||||
));
|
||||
|
||||
AssetHubPezkuwichain::execute_with(|| {
|
||||
type RuntimeEvent = <AssetHubPezkuwichain as Chain>::RuntimeEvent;
|
||||
|
||||
assert_ok!(<AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::Assets::create(
|
||||
<AssetHubPezkuwichain as Chain>::RuntimeOrigin::signed(
|
||||
AssetHubPezkuwichainSender::get()
|
||||
),
|
||||
ASSET_ID.into(),
|
||||
AssetHubPezkuwichainSender::get().into(),
|
||||
1000,
|
||||
));
|
||||
assert!(<AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::Assets::asset_exists(
|
||||
ASSET_ID
|
||||
));
|
||||
|
||||
assert_ok!(<AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::Assets::mint(
|
||||
<AssetHubPezkuwichain as Chain>::RuntimeOrigin::signed(
|
||||
AssetHubPezkuwichainSender::get()
|
||||
),
|
||||
ASSET_ID.into(),
|
||||
AssetHubPezkuwichainSender::get().into(),
|
||||
100_000_000_000_000,
|
||||
));
|
||||
|
||||
assert_ok!(
|
||||
<AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::AssetConversion::create_pool(
|
||||
<AssetHubPezkuwichain as Chain>::RuntimeOrigin::signed(
|
||||
AssetHubPezkuwichainSender::get()
|
||||
),
|
||||
asset_native.clone(),
|
||||
asset_one.clone(),
|
||||
)
|
||||
);
|
||||
|
||||
assert_expected_events!(
|
||||
AssetHubPezkuwichain,
|
||||
vec![
|
||||
RuntimeEvent::AssetConversion(pezpallet_asset_conversion::Event::PoolCreated { .. }) => {},
|
||||
]
|
||||
);
|
||||
|
||||
assert_ok!(
|
||||
<AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::AssetConversion::add_liquidity(
|
||||
<AssetHubPezkuwichain as Chain>::RuntimeOrigin::signed(
|
||||
AssetHubPezkuwichainSender::get()
|
||||
),
|
||||
asset_native.clone(),
|
||||
asset_one.clone(),
|
||||
1_000_000_000_000,
|
||||
2_000_000_000_000,
|
||||
0,
|
||||
0,
|
||||
AssetHubPezkuwichainSender::get().into()
|
||||
)
|
||||
);
|
||||
|
||||
assert_expected_events!(
|
||||
AssetHubPezkuwichain,
|
||||
vec![
|
||||
RuntimeEvent::AssetConversion(pezpallet_asset_conversion::Event::LiquidityAdded {lp_token_minted, .. }) => { lp_token_minted: *lp_token_minted == 1414213562273, },
|
||||
]
|
||||
);
|
||||
|
||||
let path = vec![asset_native.clone(), asset_one.clone()];
|
||||
|
||||
assert_ok!(
|
||||
<AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::AssetConversion::swap_exact_tokens_for_tokens(
|
||||
<AssetHubPezkuwichain as Chain>::RuntimeOrigin::signed(AssetHubPezkuwichainSender::get()),
|
||||
path,
|
||||
100,
|
||||
1,
|
||||
AssetHubPezkuwichainSender::get().into(),
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
assert_expected_events!(
|
||||
AssetHubPezkuwichain,
|
||||
vec![
|
||||
RuntimeEvent::AssetConversion(pezpallet_asset_conversion::Event::SwapExecuted { amount_in, amount_out, .. }) => {
|
||||
amount_in: *amount_in == 100,
|
||||
amount_out: *amount_out == 199,
|
||||
},
|
||||
]
|
||||
);
|
||||
|
||||
assert_ok!(
|
||||
<AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::AssetConversion::remove_liquidity(
|
||||
<AssetHubPezkuwichain as Chain>::RuntimeOrigin::signed(
|
||||
AssetHubPezkuwichainSender::get()
|
||||
),
|
||||
asset_native,
|
||||
asset_one,
|
||||
1414213562273 - ASSET_HUB_PEZKUWICHAIN_ED * 2, /* all but the 2 EDs can't be
|
||||
* retrieved. */
|
||||
0,
|
||||
0,
|
||||
AssetHubPezkuwichainSender::get().into(),
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn swap_locally_on_chain_using_foreign_assets() {
|
||||
let asset_native = Box::new(Location::try_from(RelayLocation::get()).unwrap());
|
||||
let asset_location_on_penpal = PenpalA::execute_with(|| {
|
||||
Location::try_from(PenpalLocalTeleportableToAssetHub::get()).unwrap()
|
||||
});
|
||||
let foreign_asset_at_asset_hub_pezkuwichain =
|
||||
Location::new(1, [Junction::Teyrchain(PenpalA::para_id().into())])
|
||||
.appended_with(asset_location_on_penpal)
|
||||
.unwrap();
|
||||
|
||||
let penpal_as_seen_by_ah = AssetHubPezkuwichain::sibling_location_of(PenpalA::para_id());
|
||||
let sov_penpal_on_ahr = AssetHubPezkuwichain::sovereign_account_id_of(penpal_as_seen_by_ah);
|
||||
AssetHubPezkuwichain::fund_accounts(vec![
|
||||
// An account to swap dot for something else.
|
||||
(AssetHubPezkuwichainSender::get().into(), 5_000_000 * ASSET_HUB_PEZKUWICHAIN_ED),
|
||||
// Penpal's sovereign account in AH should have some balance
|
||||
(sov_penpal_on_ahr.clone().into(), 100_000_000 * ASSET_HUB_PEZKUWICHAIN_ED),
|
||||
]);
|
||||
|
||||
AssetHubPezkuwichain::execute_with(|| {
|
||||
// 0: No need to create foreign asset as it exists in genesis.
|
||||
//
|
||||
// 1: Mint foreign asset on asset_hub_pezkuwichain:
|
||||
//
|
||||
// (While it might be nice to use batch,
|
||||
// currently that's disabled due to safe call filters.)
|
||||
|
||||
type RuntimeEvent = <AssetHubPezkuwichain as Chain>::RuntimeEvent;
|
||||
// 1. Mint foreign asset (in reality this should be a teleport or some such)
|
||||
assert_ok!(<AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::ForeignAssets::mint(
|
||||
<AssetHubPezkuwichain as Chain>::RuntimeOrigin::signed(
|
||||
sov_penpal_on_ahr.clone().into()
|
||||
),
|
||||
foreign_asset_at_asset_hub_pezkuwichain.clone(),
|
||||
sov_penpal_on_ahr.clone().into(),
|
||||
ASSET_HUB_PEZKUWICHAIN_ED * 3_000_000_000_000,
|
||||
));
|
||||
|
||||
assert_expected_events!(
|
||||
AssetHubPezkuwichain,
|
||||
vec![
|
||||
RuntimeEvent::ForeignAssets(pezpallet_assets::Event::Issued { .. }) => {},
|
||||
]
|
||||
);
|
||||
|
||||
// 2. Create pool:
|
||||
assert_ok!(
|
||||
<AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::AssetConversion::create_pool(
|
||||
<AssetHubPezkuwichain as Chain>::RuntimeOrigin::signed(
|
||||
AssetHubPezkuwichainSender::get()
|
||||
),
|
||||
asset_native.clone(),
|
||||
Box::new(foreign_asset_at_asset_hub_pezkuwichain.clone()),
|
||||
)
|
||||
);
|
||||
|
||||
assert_expected_events!(
|
||||
AssetHubPezkuwichain,
|
||||
vec![
|
||||
RuntimeEvent::AssetConversion(pezpallet_asset_conversion::Event::PoolCreated { .. }) => {},
|
||||
]
|
||||
);
|
||||
|
||||
// 3. Add liquidity:
|
||||
assert_ok!(
|
||||
<AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::AssetConversion::add_liquidity(
|
||||
<AssetHubPezkuwichain as Chain>::RuntimeOrigin::signed(sov_penpal_on_ahr.clone()),
|
||||
asset_native.clone(),
|
||||
Box::new(foreign_asset_at_asset_hub_pezkuwichain.clone()),
|
||||
1_000_000_000_000,
|
||||
2_000_000_000_000,
|
||||
0,
|
||||
0,
|
||||
sov_penpal_on_ahr.clone().into()
|
||||
)
|
||||
);
|
||||
|
||||
assert_expected_events!(
|
||||
AssetHubPezkuwichain,
|
||||
vec![
|
||||
RuntimeEvent::AssetConversion(pezpallet_asset_conversion::Event::LiquidityAdded {lp_token_minted, .. }) => {
|
||||
lp_token_minted: *lp_token_minted == 1414213562273,
|
||||
},
|
||||
]
|
||||
);
|
||||
|
||||
// 4. Swap!
|
||||
let path =
|
||||
vec![asset_native.clone(), Box::new(foreign_asset_at_asset_hub_pezkuwichain.clone())];
|
||||
|
||||
assert_ok!(
|
||||
<AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::AssetConversion::swap_exact_tokens_for_tokens(
|
||||
<AssetHubPezkuwichain as Chain>::RuntimeOrigin::signed(AssetHubPezkuwichainSender::get()),
|
||||
path,
|
||||
100000 * ASSET_HUB_PEZKUWICHAIN_ED,
|
||||
1000 * ASSET_HUB_PEZKUWICHAIN_ED,
|
||||
AssetHubPezkuwichainSender::get().into(),
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
assert_expected_events!(
|
||||
AssetHubPezkuwichain,
|
||||
vec![
|
||||
RuntimeEvent::AssetConversion(pezpallet_asset_conversion::Event::SwapExecuted { amount_in, amount_out, .. },) => {
|
||||
amount_in: *amount_in == 333333300000,
|
||||
amount_out: *amount_out == 498874118173,
|
||||
},
|
||||
]
|
||||
);
|
||||
|
||||
// 5. Remove liquidity
|
||||
assert_ok!(
|
||||
<AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::AssetConversion::remove_liquidity(
|
||||
<AssetHubPezkuwichain as Chain>::RuntimeOrigin::signed(sov_penpal_on_ahr.clone()),
|
||||
asset_native.clone(),
|
||||
Box::new(foreign_asset_at_asset_hub_pezkuwichain.clone()),
|
||||
1414213562273 - ASSET_HUB_PEZKUWICHAIN_ED * 2, /* all but the 2 EDs can't be
|
||||
* retrieved. */
|
||||
0,
|
||||
0,
|
||||
sov_penpal_on_ahr.clone().into(),
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cannot_create_pool_from_pool_assets() {
|
||||
let asset_native = RelayLocation::get();
|
||||
let mut asset_one = ahr_xcm_config::PoolAssetsPalletLocation::get();
|
||||
asset_one.append_with(GeneralIndex(ASSET_ID.into())).expect("pool assets");
|
||||
|
||||
AssetHubPezkuwichain::execute_with(|| {
|
||||
let pool_owner_account_id = AssetHubPezkuwichainAssetConversionOrigin::get();
|
||||
|
||||
assert_ok!(<AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::PoolAssets::create(
|
||||
<AssetHubPezkuwichain as Chain>::RuntimeOrigin::signed(pool_owner_account_id.clone()),
|
||||
ASSET_ID.into(),
|
||||
pool_owner_account_id.clone().into(),
|
||||
1000,
|
||||
));
|
||||
assert!(<AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::PoolAssets::asset_exists(
|
||||
ASSET_ID
|
||||
));
|
||||
|
||||
assert_ok!(<AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::PoolAssets::mint(
|
||||
<AssetHubPezkuwichain as Chain>::RuntimeOrigin::signed(pool_owner_account_id),
|
||||
ASSET_ID.into(),
|
||||
AssetHubPezkuwichainSender::get().into(),
|
||||
3_000_000_000_000,
|
||||
));
|
||||
|
||||
assert_matches::assert_matches!(
|
||||
<AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::AssetConversion::create_pool(
|
||||
<AssetHubPezkuwichain as Chain>::RuntimeOrigin::signed(AssetHubPezkuwichainSender::get()),
|
||||
Box::new(Location::try_from(asset_native).unwrap()),
|
||||
Box::new(Location::try_from(asset_one).unwrap()),
|
||||
),
|
||||
Err(DispatchError::Module(ModuleError{index: _, error: _, message})) => assert_eq!(message, Some("Unknown"))
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pay_xcm_fee_with_some_asset_swapped_for_native() {
|
||||
let asset_native = Location::try_from(RelayLocation::get()).unwrap();
|
||||
let asset_one = Location {
|
||||
parents: 0,
|
||||
interior: [
|
||||
Junction::PalletInstance(ASSETS_PALLET_ID),
|
||||
Junction::GeneralIndex(ASSET_ID.into()),
|
||||
]
|
||||
.into(),
|
||||
};
|
||||
let penpal = AssetHubPezkuwichain::sovereign_account_id_of(
|
||||
AssetHubPezkuwichain::sibling_location_of(PenpalA::para_id()),
|
||||
);
|
||||
|
||||
AssetHubPezkuwichain::execute_with(|| {
|
||||
type RuntimeEvent = <AssetHubPezkuwichain as Chain>::RuntimeEvent;
|
||||
|
||||
// set up pool with ASSET_ID <> NATIVE pair
|
||||
assert_ok!(<AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::Assets::create(
|
||||
<AssetHubPezkuwichain as Chain>::RuntimeOrigin::signed(
|
||||
AssetHubPezkuwichainSender::get()
|
||||
),
|
||||
ASSET_ID.into(),
|
||||
AssetHubPezkuwichainSender::get().into(),
|
||||
ASSET_MIN_BALANCE,
|
||||
));
|
||||
assert!(<AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::Assets::asset_exists(
|
||||
ASSET_ID
|
||||
));
|
||||
|
||||
assert_ok!(<AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::Assets::mint(
|
||||
<AssetHubPezkuwichain as Chain>::RuntimeOrigin::signed(
|
||||
AssetHubPezkuwichainSender::get()
|
||||
),
|
||||
ASSET_ID.into(),
|
||||
AssetHubPezkuwichainSender::get().into(),
|
||||
3_000_000_000_000,
|
||||
));
|
||||
|
||||
assert_ok!(
|
||||
<AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::AssetConversion::create_pool(
|
||||
<AssetHubPezkuwichain as Chain>::RuntimeOrigin::signed(
|
||||
AssetHubPezkuwichainSender::get()
|
||||
),
|
||||
Box::new(asset_native.clone()),
|
||||
Box::new(asset_one.clone()),
|
||||
)
|
||||
);
|
||||
|
||||
assert_expected_events!(
|
||||
AssetHubPezkuwichain,
|
||||
vec![
|
||||
RuntimeEvent::AssetConversion(pezpallet_asset_conversion::Event::PoolCreated { .. }) => {},
|
||||
]
|
||||
);
|
||||
|
||||
assert_ok!(
|
||||
<AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::AssetConversion::add_liquidity(
|
||||
<AssetHubPezkuwichain as Chain>::RuntimeOrigin::signed(
|
||||
AssetHubPezkuwichainSender::get()
|
||||
),
|
||||
Box::new(asset_native),
|
||||
Box::new(asset_one),
|
||||
1_000_000_000_000,
|
||||
2_000_000_000_000,
|
||||
0,
|
||||
0,
|
||||
AssetHubPezkuwichainSender::get().into()
|
||||
)
|
||||
);
|
||||
|
||||
assert_expected_events!(
|
||||
AssetHubPezkuwichain,
|
||||
vec![
|
||||
RuntimeEvent::AssetConversion(pezpallet_asset_conversion::Event::LiquidityAdded {lp_token_minted, .. }) => { lp_token_minted: *lp_token_minted == 1414213562273, },
|
||||
]
|
||||
);
|
||||
|
||||
// ensure `penpal` sovereign account has no native tokens and mint some `ASSET_ID`
|
||||
assert_eq!(
|
||||
<AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::Balances::free_balance(
|
||||
penpal.clone()
|
||||
),
|
||||
0
|
||||
);
|
||||
|
||||
assert_ok!(<AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::Assets::touch_other(
|
||||
<AssetHubPezkuwichain as Chain>::RuntimeOrigin::signed(
|
||||
AssetHubPezkuwichainSender::get()
|
||||
),
|
||||
ASSET_ID.into(),
|
||||
penpal.clone().into(),
|
||||
));
|
||||
|
||||
assert_ok!(<AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::Assets::mint(
|
||||
<AssetHubPezkuwichain as Chain>::RuntimeOrigin::signed(
|
||||
AssetHubPezkuwichainSender::get()
|
||||
),
|
||||
ASSET_ID.into(),
|
||||
penpal.clone().into(),
|
||||
10_000_000_000_000,
|
||||
));
|
||||
});
|
||||
|
||||
PenpalA::execute_with(|| {
|
||||
// send xcm transact from `penpal` account while paying with `ASSET_ID` tokens on
|
||||
// `AssetHubPezkuwichain`
|
||||
let call = <AssetHubPezkuwichain as Chain>::RuntimeCall::System(pezframe_system::Call::<
|
||||
<AssetHubPezkuwichain as Chain>::Runtime,
|
||||
>::remark {
|
||||
remark: vec![],
|
||||
})
|
||||
.encode()
|
||||
.into();
|
||||
|
||||
let penpal_root = <PenpalA as Chain>::RuntimeOrigin::root();
|
||||
let fee_amount = 4_000_000_000_000u128;
|
||||
let asset_one =
|
||||
([PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())], fee_amount).into();
|
||||
let asset_hub_location =
|
||||
PenpalA::sibling_location_of(AssetHubPezkuwichain::para_id()).into();
|
||||
let xcm = xcm_transact_paid_execution(
|
||||
call,
|
||||
OriginKind::SovereignAccount,
|
||||
asset_one,
|
||||
penpal.clone(),
|
||||
);
|
||||
|
||||
assert_ok!(<PenpalA as PenpalAPallet>::PezkuwiXcm::send(
|
||||
penpal_root,
|
||||
bx!(asset_hub_location),
|
||||
bx!(xcm),
|
||||
));
|
||||
|
||||
PenpalA::assert_xcm_pallet_sent();
|
||||
});
|
||||
|
||||
AssetHubPezkuwichain::execute_with(|| {
|
||||
type RuntimeEvent = <AssetHubPezkuwichain as Chain>::RuntimeEvent;
|
||||
|
||||
AssetHubPezkuwichain::assert_xcmp_queue_success(None);
|
||||
assert_expected_events!(
|
||||
AssetHubPezkuwichain,
|
||||
vec![
|
||||
RuntimeEvent::AssetConversion(pezpallet_asset_conversion::Event::SwapCreditExecuted { .. },) => {},
|
||||
RuntimeEvent::MessageQueue(pezpallet_message_queue::Event::Processed { success: true,.. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn xcm_fee_querying_apis_work() {
|
||||
test_xcm_fee_querying_apis_work_for_asset_hub!(AssetHubPezkuwichain);
|
||||
}
|
||||
+643
@@ -0,0 +1,643 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::imports::*;
|
||||
|
||||
fn relay_dest_assertions_fail(_t: SystemParaToRelayTest) {
|
||||
Pezkuwichain::assert_ump_queue_processed(
|
||||
false,
|
||||
Some(AssetHubPezkuwichain::para_id()),
|
||||
Some(Weight::from_parts(157_718_000, 3_593)),
|
||||
);
|
||||
}
|
||||
|
||||
fn para_origin_assertions(t: SystemParaToRelayTest) {
|
||||
type RuntimeEvent = <AssetHubPezkuwichain as Chain>::RuntimeEvent;
|
||||
|
||||
AssetHubPezkuwichain::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(
|
||||
730_053_000,
|
||||
4_000,
|
||||
)));
|
||||
|
||||
AssetHubPezkuwichain::assert_teyrchain_system_ump_sent();
|
||||
|
||||
assert_expected_events!(
|
||||
AssetHubPezkuwichain,
|
||||
vec![
|
||||
// Amount is withdrawn from Sender's account
|
||||
RuntimeEvent::Balances(pezpallet_balances::Event::Burned { who, amount }) => {
|
||||
who: *who == t.sender.account_id,
|
||||
amount: *amount == t.args.amount,
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
fn penpal_to_ah_foreign_assets_sender_assertions(t: ParaToSystemParaTest) {
|
||||
type RuntimeEvent = <PenpalA as Chain>::RuntimeEvent;
|
||||
let system_para_native_asset_location = RelayLocation::get();
|
||||
let expected_asset_id = t.args.asset_id.unwrap();
|
||||
let (_, expected_asset_amount) = non_fee_asset(&t.args.assets, &t.args.fee_asset_id).unwrap();
|
||||
|
||||
PenpalA::assert_xcm_pallet_attempted_complete(None);
|
||||
assert_expected_events!(
|
||||
PenpalA,
|
||||
vec![
|
||||
RuntimeEvent::ForeignAssets(
|
||||
pezpallet_assets::Event::Burned { asset_id, owner, .. }
|
||||
) => {
|
||||
asset_id: *asset_id == system_para_native_asset_location,
|
||||
owner: *owner == t.sender.account_id,
|
||||
},
|
||||
RuntimeEvent::Assets(pezpallet_assets::Event::Burned { asset_id, owner, balance }) => {
|
||||
asset_id: *asset_id == expected_asset_id,
|
||||
owner: *owner == t.sender.account_id,
|
||||
balance: *balance == expected_asset_amount,
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
fn penpal_to_ah_foreign_assets_receiver_assertions(t: ParaToSystemParaTest) {
|
||||
type RuntimeEvent = <AssetHubPezkuwichain as Chain>::RuntimeEvent;
|
||||
let sov_penpal_on_ahr = AssetHubPezkuwichain::sovereign_account_id_of(
|
||||
AssetHubPezkuwichain::sibling_location_of(PenpalA::para_id()),
|
||||
);
|
||||
let (_, expected_foreign_asset_amount) =
|
||||
non_fee_asset(&t.args.assets, &t.args.fee_asset_id).unwrap();
|
||||
let (_, fee_asset_amount) = fee_asset(&t.args.assets, &t.args.fee_asset_id).unwrap();
|
||||
|
||||
AssetHubPezkuwichain::assert_xcmp_queue_success(None);
|
||||
|
||||
assert_expected_events!(
|
||||
AssetHubPezkuwichain,
|
||||
vec![
|
||||
// native asset reserve transfer for paying fees, withdrawn from Penpal's sov account
|
||||
RuntimeEvent::Balances(
|
||||
pezpallet_balances::Event::Burned { who, amount }
|
||||
) => {
|
||||
who: *who == sov_penpal_on_ahr.clone().into(),
|
||||
amount: *amount == fee_asset_amount,
|
||||
},
|
||||
RuntimeEvent::Balances(pezpallet_balances::Event::Minted { who, .. }) => {
|
||||
who: *who == t.receiver.account_id,
|
||||
},
|
||||
RuntimeEvent::ForeignAssets(pezpallet_assets::Event::Issued { asset_id, owner, amount }) => {
|
||||
asset_id: *asset_id == PenpalATeleportableAssetLocation::get(),
|
||||
owner: *owner == t.receiver.account_id,
|
||||
amount: *amount == expected_foreign_asset_amount,
|
||||
},
|
||||
RuntimeEvent::Balances(pezpallet_balances::Event::Deposit { .. }) => {},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
fn ah_to_penpal_foreign_assets_sender_assertions(t: SystemParaToParaTest) {
|
||||
type RuntimeEvent = <AssetHubPezkuwichain as Chain>::RuntimeEvent;
|
||||
AssetHubPezkuwichain::assert_xcm_pallet_attempted_complete(None);
|
||||
let (expected_foreign_asset_id, expected_foreign_asset_amount) =
|
||||
non_fee_asset(&t.args.assets, &t.args.fee_asset_id).unwrap();
|
||||
let (_, fee_asset_amount) = fee_asset(&t.args.assets, &t.args.fee_asset_id).unwrap();
|
||||
assert_expected_events!(
|
||||
AssetHubPezkuwichain,
|
||||
vec![
|
||||
// native asset used for fees is transferred to Teyrchain's Sovereign account as reserve
|
||||
RuntimeEvent::Balances(
|
||||
pezpallet_balances::Event::Transfer { from, to, amount }
|
||||
) => {
|
||||
from: *from == t.sender.account_id,
|
||||
to: *to == AssetHubPezkuwichain::sovereign_account_id_of(
|
||||
t.args.dest.clone()
|
||||
),
|
||||
amount: *amount == fee_asset_amount,
|
||||
},
|
||||
// foreign asset is burned locally as part of teleportation
|
||||
RuntimeEvent::ForeignAssets(pezpallet_assets::Event::Burned { asset_id, owner, balance }) => {
|
||||
asset_id: *asset_id == expected_foreign_asset_id,
|
||||
owner: *owner == t.sender.account_id,
|
||||
balance: *balance == expected_foreign_asset_amount,
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
fn ah_to_penpal_foreign_assets_receiver_assertions(t: SystemParaToParaTest) {
|
||||
type RuntimeEvent = <PenpalA as Chain>::RuntimeEvent;
|
||||
let expected_asset_id = t.args.asset_id.unwrap();
|
||||
let (_, expected_asset_amount) = non_fee_asset(&t.args.assets, &t.args.fee_asset_id).unwrap();
|
||||
let checking_account = <PenpalA as PenpalAPallet>::PezkuwiXcm::check_account();
|
||||
let system_para_native_asset_location = RelayLocation::get();
|
||||
|
||||
PenpalA::assert_xcmp_queue_success(None);
|
||||
|
||||
assert_expected_events!(
|
||||
PenpalA,
|
||||
vec![
|
||||
// checking account burns local asset as part of incoming teleport
|
||||
RuntimeEvent::Assets(pezpallet_assets::Event::Burned { asset_id, owner, balance }) => {
|
||||
asset_id: *asset_id == expected_asset_id,
|
||||
owner: *owner == checking_account,
|
||||
balance: *balance == expected_asset_amount,
|
||||
},
|
||||
// local asset is teleported into account of receiver
|
||||
RuntimeEvent::Assets(pezpallet_assets::Event::Issued { asset_id, owner, amount }) => {
|
||||
asset_id: *asset_id == expected_asset_id,
|
||||
owner: *owner == t.receiver.account_id,
|
||||
amount: *amount == expected_asset_amount,
|
||||
},
|
||||
// native asset for fee is deposited to receiver
|
||||
RuntimeEvent::ForeignAssets(pezpallet_assets::Event::Issued { asset_id, owner, .. }) => {
|
||||
asset_id: *asset_id == system_para_native_asset_location,
|
||||
owner: *owner == t.receiver.account_id,
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
fn system_para_limited_teleport_assets(t: SystemParaToRelayTest) -> DispatchResult {
|
||||
<AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::PezkuwiXcm::limited_teleport_assets(
|
||||
t.signed_origin,
|
||||
bx!(t.args.dest.into()),
|
||||
bx!(t.args.beneficiary.into()),
|
||||
bx!(t.args.assets.into()),
|
||||
bx!(t.args.fee_asset_id.into()),
|
||||
t.args.weight_limit,
|
||||
)
|
||||
}
|
||||
|
||||
fn para_to_system_para_transfer_assets(t: ParaToSystemParaTest) -> DispatchResult {
|
||||
<PenpalA as PenpalAPallet>::PezkuwiXcm::transfer_assets_using_type_and_then(
|
||||
t.signed_origin,
|
||||
bx!(t.args.dest.into()),
|
||||
bx!(t.args.assets.into()),
|
||||
bx!(TransferType::Teleport),
|
||||
bx!(t.args.fee_asset_id.into()),
|
||||
bx!(TransferType::DestinationReserve),
|
||||
bx!(VersionedXcm::from(
|
||||
Xcm::<()>::builder_unsafe()
|
||||
.deposit_asset(AllCounted(2), t.args.beneficiary)
|
||||
.build()
|
||||
)),
|
||||
t.args.weight_limit,
|
||||
)
|
||||
}
|
||||
|
||||
fn system_para_to_para_transfer_assets(t: SystemParaToParaTest) -> DispatchResult {
|
||||
<AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::PezkuwiXcm::transfer_assets_using_type_and_then(
|
||||
t.signed_origin,
|
||||
bx!(t.args.dest.into()),
|
||||
bx!(t.args.assets.into()),
|
||||
bx!(TransferType::Teleport),
|
||||
bx!(t.args.fee_asset_id.into()),
|
||||
bx!(TransferType::LocalReserve),
|
||||
bx!(VersionedXcm::from(
|
||||
Xcm::<()>::builder_unsafe()
|
||||
.deposit_asset(AllCounted(2), t.args.beneficiary)
|
||||
.build()
|
||||
)),
|
||||
t.args.weight_limit,
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn teleport_via_limited_teleport_assets_to_other_system_teyrchains_works() {
|
||||
let amount = ASSET_HUB_PEZKUWICHAIN_ED * 100;
|
||||
let native_asset: Assets = (Parent, amount).into();
|
||||
let fee_asset_id: AssetId = Parent.into();
|
||||
|
||||
test_teyrchain_is_trusted_teleporter!(
|
||||
AssetHubPezkuwichain, // Origin
|
||||
vec![BridgeHubPezkuwichain], // Destinations
|
||||
(native_asset, amount),
|
||||
fee_asset_id,
|
||||
limited_teleport_assets
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn teleport_via_transfer_assets_to_other_system_teyrchains_works() {
|
||||
let amount = ASSET_HUB_PEZKUWICHAIN_ED * 100;
|
||||
let native_asset: Assets = (Parent, amount).into();
|
||||
let fee_asset_id: AssetId = Parent.into();
|
||||
|
||||
test_teyrchain_is_trusted_teleporter!(
|
||||
AssetHubPezkuwichain, // Origin
|
||||
vec![BridgeHubPezkuwichain], // Destinations
|
||||
(native_asset, amount),
|
||||
fee_asset_id,
|
||||
transfer_assets
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn teleport_via_limited_teleport_assets_from_and_to_relay() {
|
||||
let amount = PEZKUWICHAIN_ED * 100;
|
||||
|
||||
test_relay_is_trusted_teleporter!(
|
||||
Pezkuwichain,
|
||||
vec![AssetHubPezkuwichain],
|
||||
amount,
|
||||
limited_teleport_assets
|
||||
);
|
||||
|
||||
test_teyrchain_is_trusted_teleporter_for_relay!(
|
||||
AssetHubPezkuwichain,
|
||||
Pezkuwichain,
|
||||
amount,
|
||||
limited_teleport_assets
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn teleport_via_transfer_assets_from_and_to_relay() {
|
||||
let amount = PEZKUWICHAIN_ED * 100;
|
||||
|
||||
test_relay_is_trusted_teleporter!(
|
||||
Pezkuwichain,
|
||||
vec![AssetHubPezkuwichain],
|
||||
amount,
|
||||
transfer_assets
|
||||
);
|
||||
|
||||
test_teyrchain_is_trusted_teleporter_for_relay!(
|
||||
AssetHubPezkuwichain,
|
||||
Pezkuwichain,
|
||||
amount,
|
||||
transfer_assets
|
||||
);
|
||||
}
|
||||
|
||||
/// Limited Teleport of native asset from System Teyrchain to Relay Chain
|
||||
/// shouldn't work when there is not enough balance in Relay Chain's `CheckAccount`
|
||||
#[test]
|
||||
fn limited_teleport_native_assets_from_system_para_to_relay_fails() {
|
||||
// Init values for Relay Chain
|
||||
let amount_to_send: Balance = ASSET_HUB_PEZKUWICHAIN_ED * 1000;
|
||||
let destination = AssetHubPezkuwichain::parent_location().into();
|
||||
let beneficiary_id = PezkuwichainReceiver::get().into();
|
||||
let assets = (Parent, amount_to_send).into();
|
||||
let fee_asset_id: AssetId = Parent.into();
|
||||
|
||||
let test_args = TestContext {
|
||||
sender: AssetHubPezkuwichainSender::get(),
|
||||
receiver: PezkuwichainReceiver::get(),
|
||||
args: TestArgs::new_para(
|
||||
destination,
|
||||
beneficiary_id,
|
||||
amount_to_send,
|
||||
assets,
|
||||
None,
|
||||
fee_asset_id.clone(),
|
||||
),
|
||||
};
|
||||
|
||||
let mut test = SystemParaToRelayTest::new(test_args);
|
||||
|
||||
let sender_balance_before = test.sender.balance;
|
||||
let receiver_balance_before = test.receiver.balance;
|
||||
|
||||
test.set_assertion::<AssetHubPezkuwichain>(para_origin_assertions);
|
||||
test.set_assertion::<Pezkuwichain>(relay_dest_assertions_fail);
|
||||
test.set_dispatchable::<AssetHubPezkuwichain>(system_para_limited_teleport_assets);
|
||||
test.assert();
|
||||
|
||||
let sender_balance_after = test.sender.balance;
|
||||
let receiver_balance_after = test.receiver.balance;
|
||||
|
||||
let delivery_fees = AssetHubPezkuwichain::execute_with(|| {
|
||||
xcm_helpers::teleport_assets_delivery_fees::<
|
||||
<AssetHubPezkuwichainXcmConfig as xcm_executor::Config>::XcmSender,
|
||||
>(
|
||||
test.args.assets.clone(),
|
||||
fee_asset_id,
|
||||
test.args.weight_limit,
|
||||
test.args.beneficiary,
|
||||
test.args.dest,
|
||||
)
|
||||
});
|
||||
|
||||
// Sender's balance is reduced
|
||||
assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after);
|
||||
// Receiver's balance does not change
|
||||
assert_eq!(receiver_balance_after, receiver_balance_before);
|
||||
}
|
||||
|
||||
/// Bidirectional teleports of local Penpal assets to Asset Hub as foreign assets while paying
|
||||
/// fees using (reserve transferred) native asset.
|
||||
pub fn do_bidirectional_teleport_foreign_assets_between_para_and_asset_hub_using_xt(
|
||||
para_to_ah_dispatchable: fn(ParaToSystemParaTest) -> DispatchResult,
|
||||
ah_to_para_dispatchable: fn(SystemParaToParaTest) -> DispatchResult,
|
||||
) {
|
||||
// Init values for Teyrchain
|
||||
let fee_amount_to_send: Balance = ASSET_HUB_PEZKUWICHAIN_ED * 10000;
|
||||
let asset_location_on_penpal =
|
||||
PenpalA::execute_with(|| PenpalLocalTeleportableToAssetHub::get());
|
||||
let asset_id_on_penpal = match asset_location_on_penpal.last() {
|
||||
Some(Junction::GeneralIndex(id)) => *id as u32,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let asset_amount_to_send = ASSET_HUB_PEZKUWICHAIN_ED * 1000;
|
||||
|
||||
let asset_owner = PenpalAssetOwner::get();
|
||||
let system_para_native_asset_location = RelayLocation::get();
|
||||
let sender = PenpalASender::get();
|
||||
let penpal_check_account = <PenpalA as PenpalAPallet>::PezkuwiXcm::check_account();
|
||||
let ah_as_seen_by_penpal = PenpalA::sibling_location_of(AssetHubPezkuwichain::para_id());
|
||||
let penpal_assets: Assets = vec![
|
||||
(Parent, fee_amount_to_send).into(),
|
||||
(asset_location_on_penpal.clone(), asset_amount_to_send).into(),
|
||||
]
|
||||
.into();
|
||||
let fee_asset_id: AssetId = Parent.into();
|
||||
|
||||
// fund Teyrchain's sender account
|
||||
PenpalA::mint_foreign_asset(
|
||||
<PenpalA as Chain>::RuntimeOrigin::signed(asset_owner.clone()),
|
||||
system_para_native_asset_location.clone(),
|
||||
sender.clone(),
|
||||
fee_amount_to_send * 2,
|
||||
);
|
||||
// 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 Teyrchain's check account to be able to teleport
|
||||
PenpalA::fund_accounts(vec![(
|
||||
penpal_check_account.clone().into(),
|
||||
ASSET_HUB_PEZKUWICHAIN_ED * 1000,
|
||||
)]);
|
||||
|
||||
// prefund SA of Penpal on AssetHub with enough native tokens to pay for fees
|
||||
let penpal_as_seen_by_ah = AssetHubPezkuwichain::sibling_location_of(PenpalA::para_id());
|
||||
let sov_penpal_on_ah = AssetHubPezkuwichain::sovereign_account_id_of(penpal_as_seen_by_ah);
|
||||
AssetHubPezkuwichain::fund_accounts(vec![(
|
||||
sov_penpal_on_ah.clone().into(),
|
||||
ASSET_HUB_PEZKUWICHAIN_ED * 100_000_000_000,
|
||||
)]);
|
||||
|
||||
// Init values for System Teyrchain
|
||||
let foreign_asset_at_asset_hub_pezkuwichain =
|
||||
Location::new(1, [Junction::Teyrchain(PenpalA::para_id().into())])
|
||||
.appended_with(asset_location_on_penpal)
|
||||
.unwrap();
|
||||
let penpal_to_ah_beneficiary_id = AssetHubPezkuwichainReceiver::get();
|
||||
|
||||
// Penpal to AH test args
|
||||
let penpal_to_ah_test_args = TestContext {
|
||||
sender: PenpalASender::get(),
|
||||
receiver: AssetHubPezkuwichainReceiver::get(),
|
||||
args: TestArgs::new_para(
|
||||
ah_as_seen_by_penpal,
|
||||
penpal_to_ah_beneficiary_id,
|
||||
asset_amount_to_send,
|
||||
penpal_assets,
|
||||
Some(asset_id_on_penpal),
|
||||
fee_asset_id,
|
||||
),
|
||||
};
|
||||
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.clone(),
|
||||
&PenpalASender::get(),
|
||||
)
|
||||
});
|
||||
|
||||
let ah_receiver_balance_before = penpal_to_ah.receiver.balance;
|
||||
|
||||
let penpal_sender_assets_before = PenpalA::execute_with(|| {
|
||||
type Assets = <PenpalA as PenpalAPallet>::Assets;
|
||||
<Assets as Inspect<_>>::balance(asset_id_on_penpal, &PenpalASender::get())
|
||||
});
|
||||
let ah_receiver_assets_before = AssetHubPezkuwichain::execute_with(|| {
|
||||
type Assets = <AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::ForeignAssets;
|
||||
<Assets as Inspect<_>>::balance(
|
||||
foreign_asset_at_asset_hub_pezkuwichain.clone().try_into().unwrap(),
|
||||
&AssetHubPezkuwichainReceiver::get(),
|
||||
)
|
||||
});
|
||||
|
||||
penpal_to_ah.set_assertion::<PenpalA>(penpal_to_ah_foreign_assets_sender_assertions);
|
||||
penpal_to_ah
|
||||
.set_assertion::<AssetHubPezkuwichain>(penpal_to_ah_foreign_assets_receiver_assertions);
|
||||
penpal_to_ah.set_dispatchable::<PenpalA>(para_to_ah_dispatchable);
|
||||
penpal_to_ah.assert();
|
||||
|
||||
let penpal_sender_balance_after = PenpalA::execute_with(|| {
|
||||
type ForeignAssets = <PenpalA as PenpalAPallet>::ForeignAssets;
|
||||
<ForeignAssets as Inspect<_>>::balance(
|
||||
system_para_native_asset_location.clone(),
|
||||
&PenpalASender::get(),
|
||||
)
|
||||
});
|
||||
|
||||
let ah_receiver_balance_after = penpal_to_ah.receiver.balance;
|
||||
|
||||
let penpal_sender_assets_after = PenpalA::execute_with(|| {
|
||||
type Assets = <PenpalA as PenpalAPallet>::Assets;
|
||||
<Assets as Inspect<_>>::balance(asset_id_on_penpal, &PenpalASender::get())
|
||||
});
|
||||
let ah_receiver_assets_after = AssetHubPezkuwichain::execute_with(|| {
|
||||
type Assets = <AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::ForeignAssets;
|
||||
<Assets as Inspect<_>>::balance(
|
||||
foreign_asset_at_asset_hub_pezkuwichain.clone().try_into().unwrap(),
|
||||
&AssetHubPezkuwichainReceiver::get(),
|
||||
)
|
||||
});
|
||||
|
||||
// Sender's balance is reduced
|
||||
assert!(penpal_sender_balance_after < penpal_sender_balance_before);
|
||||
// Receiver's balance is increased
|
||||
assert!(ah_receiver_balance_after > ah_receiver_balance_before);
|
||||
// Receiver's balance increased by `amount_to_send - delivery_fees - bought_execution`;
|
||||
// `delivery_fees` might be paid from transfer or JIT, also `bought_execution` is unknown but
|
||||
// should be non-zero
|
||||
assert!(ah_receiver_balance_after < ah_receiver_balance_before + fee_amount_to_send);
|
||||
|
||||
// Sender's balance is reduced by exact amount
|
||||
assert_eq!(penpal_sender_assets_before - asset_amount_to_send, penpal_sender_assets_after);
|
||||
// Receiver's balance is increased by exact amount
|
||||
assert_eq!(ah_receiver_assets_after, ah_receiver_assets_before + asset_amount_to_send);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Now test transferring foreign assets back from AssetHub to Penpal //
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Move funds on AH from AHReceiver to AHSender
|
||||
AssetHubPezkuwichain::execute_with(|| {
|
||||
type ForeignAssets = <AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::ForeignAssets;
|
||||
assert_ok!(ForeignAssets::transfer(
|
||||
<AssetHubPezkuwichain as Chain>::RuntimeOrigin::signed(
|
||||
AssetHubPezkuwichainReceiver::get()
|
||||
),
|
||||
foreign_asset_at_asset_hub_pezkuwichain.clone().try_into().unwrap(),
|
||||
AssetHubPezkuwichainSender::get().into(),
|
||||
asset_amount_to_send,
|
||||
));
|
||||
});
|
||||
|
||||
let ah_to_penpal_beneficiary_id = PenpalAReceiver::get();
|
||||
let penpal_as_seen_by_ah = AssetHubPezkuwichain::sibling_location_of(PenpalA::para_id());
|
||||
let ah_assets: Assets = vec![
|
||||
(Parent, fee_amount_to_send).into(),
|
||||
(foreign_asset_at_asset_hub_pezkuwichain.clone(), asset_amount_to_send).into(),
|
||||
]
|
||||
.into();
|
||||
let fee_asset_id: AssetId = Parent.into();
|
||||
|
||||
// AH to Penpal test args
|
||||
let ah_to_penpal_test_args = TestContext {
|
||||
sender: AssetHubPezkuwichainSender::get(),
|
||||
receiver: PenpalAReceiver::get(),
|
||||
args: TestArgs::new_para(
|
||||
penpal_as_seen_by_ah,
|
||||
ah_to_penpal_beneficiary_id,
|
||||
asset_amount_to_send,
|
||||
ah_assets,
|
||||
Some(asset_id_on_penpal),
|
||||
fee_asset_id,
|
||||
),
|
||||
};
|
||||
|
||||
let mut ah_to_penpal = SystemParaToParaTest::new(ah_to_penpal_test_args);
|
||||
|
||||
let ah_sender_balance_before = ah_to_penpal.sender.balance;
|
||||
let penpal_receiver_balance_before = PenpalA::execute_with(|| {
|
||||
type ForeignAssets = <PenpalA as PenpalAPallet>::ForeignAssets;
|
||||
<ForeignAssets as Inspect<_>>::balance(
|
||||
system_para_native_asset_location.clone(),
|
||||
&PenpalAReceiver::get(),
|
||||
)
|
||||
});
|
||||
|
||||
let ah_sender_assets_before = AssetHubPezkuwichain::execute_with(|| {
|
||||
type ForeignAssets = <AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::ForeignAssets;
|
||||
<ForeignAssets as Inspect<_>>::balance(
|
||||
foreign_asset_at_asset_hub_pezkuwichain.clone().try_into().unwrap(),
|
||||
&AssetHubPezkuwichainSender::get(),
|
||||
)
|
||||
});
|
||||
let penpal_receiver_assets_before = PenpalA::execute_with(|| {
|
||||
type Assets = <PenpalA as PenpalAPallet>::Assets;
|
||||
<Assets as Inspect<_>>::balance(asset_id_on_penpal, &PenpalAReceiver::get())
|
||||
});
|
||||
|
||||
ah_to_penpal
|
||||
.set_assertion::<AssetHubPezkuwichain>(ah_to_penpal_foreign_assets_sender_assertions);
|
||||
ah_to_penpal.set_assertion::<PenpalA>(ah_to_penpal_foreign_assets_receiver_assertions);
|
||||
ah_to_penpal.set_dispatchable::<AssetHubPezkuwichain>(ah_to_para_dispatchable);
|
||||
ah_to_penpal.assert();
|
||||
|
||||
let ah_sender_balance_after = ah_to_penpal.sender.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 = AssetHubPezkuwichain::execute_with(|| {
|
||||
type ForeignAssets = <AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::ForeignAssets;
|
||||
<ForeignAssets as Inspect<_>>::balance(
|
||||
foreign_asset_at_asset_hub_pezkuwichain.try_into().unwrap(),
|
||||
&AssetHubPezkuwichainSender::get(),
|
||||
)
|
||||
});
|
||||
let penpal_receiver_assets_after = PenpalA::execute_with(|| {
|
||||
type Assets = <PenpalA as PenpalAPallet>::Assets;
|
||||
<Assets as Inspect<_>>::balance(asset_id_on_penpal, &PenpalAReceiver::get())
|
||||
});
|
||||
|
||||
// Sender's balance is reduced
|
||||
assert!(ah_sender_balance_after < ah_sender_balance_before);
|
||||
// Receiver's balance is increased
|
||||
assert!(penpal_receiver_balance_after > penpal_receiver_balance_before);
|
||||
// Receiver's balance increased by `amount_to_send - delivery_fees - bought_execution`;
|
||||
// `delivery_fees` might be paid from transfer or JIT, also `bought_execution` is unknown but
|
||||
// should be non-zero
|
||||
assert!(penpal_receiver_balance_after < penpal_receiver_balance_before + fee_amount_to_send);
|
||||
|
||||
// Sender's balance is reduced by exact amount
|
||||
assert_eq!(ah_sender_assets_before - asset_amount_to_send, ah_sender_assets_after);
|
||||
// Receiver's balance is increased by exact amount
|
||||
assert_eq!(penpal_receiver_assets_after, penpal_receiver_assets_before + asset_amount_to_send);
|
||||
}
|
||||
|
||||
/// Bidirectional teleports of local Penpal assets to Asset Hub as foreign assets should work
|
||||
/// (using native reserve-based transfer for fees)
|
||||
#[test]
|
||||
fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() {
|
||||
do_bidirectional_teleport_foreign_assets_between_para_and_asset_hub_using_xt(
|
||||
para_to_system_para_transfer_assets,
|
||||
system_para_to_para_transfer_assets,
|
||||
);
|
||||
}
|
||||
|
||||
/// Teleport Native Asset from AssetHub to Teyrchain fails.
|
||||
#[test]
|
||||
fn teleport_to_untrusted_chain_fails() {
|
||||
// Init values for Teyrchain Origin
|
||||
let destination = AssetHubPezkuwichain::sibling_location_of(PenpalA::para_id());
|
||||
let signed_origin = <AssetHubPezkuwichain as Chain>::RuntimeOrigin::signed(
|
||||
AssetHubPezkuwichainSender::get().into(),
|
||||
);
|
||||
let roc_to_send: Balance = PEZKUWICHAIN_ED * 10000;
|
||||
let roc_location = RelayLocation::get();
|
||||
|
||||
// Assets to send
|
||||
let assets: Vec<Asset> = vec![(roc_location.clone(), roc_to_send).into()];
|
||||
let fee_id: AssetId = roc_location.into();
|
||||
|
||||
// this should fail
|
||||
AssetHubPezkuwichain::execute_with(|| {
|
||||
let result = <AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::PezkuwiXcm::transfer_assets_using_type_and_then(
|
||||
signed_origin.clone(),
|
||||
bx!(destination.clone().into()),
|
||||
bx!(assets.clone().into()),
|
||||
bx!(TransferType::Teleport),
|
||||
bx!(fee_id.into()),
|
||||
bx!(TransferType::Teleport),
|
||||
bx!(VersionedXcm::from(Xcm::<()>::new())),
|
||||
Unlimited,
|
||||
);
|
||||
assert_err!(
|
||||
result,
|
||||
DispatchError::Module(pezsp_runtime::ModuleError {
|
||||
index: 31,
|
||||
error: [2, 0, 0, 0],
|
||||
message: Some("Filtered")
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
// this should also fail
|
||||
AssetHubPezkuwichain::execute_with(|| {
|
||||
let xcm: Xcm<asset_hub_pezkuwichain_runtime::RuntimeCall> = Xcm(vec![
|
||||
WithdrawAsset(assets.into()),
|
||||
InitiateTeleport { assets: Wild(All), dest: destination, xcm: Xcm::<()>::new() },
|
||||
]);
|
||||
let result = <AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::PezkuwiXcm::execute(
|
||||
signed_origin,
|
||||
bx!(xcm::VersionedXcm::from(xcm)),
|
||||
Weight::MAX,
|
||||
);
|
||||
assert!(result.is_err());
|
||||
});
|
||||
}
|
||||
+264
@@ -0,0 +1,264 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::imports::*;
|
||||
use emulated_integration_tests_common::{
|
||||
accounts::{ALICE, BOB},
|
||||
USDT_ID,
|
||||
};
|
||||
use pezframe_support::{
|
||||
dispatch::RawOrigin,
|
||||
pezsp_runtime::traits::Dispatchable,
|
||||
traits::{
|
||||
fungible::Inspect,
|
||||
fungibles::{Inspect as FungiblesInspect, Mutate},
|
||||
},
|
||||
};
|
||||
use pezkuwi_runtime_common::impls::VersionedLocatableAsset;
|
||||
use pezkuwichain_runtime_constants::currency::GRAND;
|
||||
use teyrchains_common::AccountId;
|
||||
use xcm_executor::traits::ConvertLocation;
|
||||
|
||||
// Fund Treasury account on Asset Hub from Treasury account on Relay Chain with TYRs.
|
||||
#[test]
|
||||
fn spend_roc_on_asset_hub() {
|
||||
// initial treasury balance on Asset Hub in TYRs.
|
||||
let treasury_balance = 9_000 * GRAND;
|
||||
// the balance spend on Asset Hub.
|
||||
let treasury_spend_balance = 1_000 * GRAND;
|
||||
|
||||
let init_alice_balance = AssetHubPezkuwichain::execute_with(|| {
|
||||
<<AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::Balances as Inspect<_>>::balance(
|
||||
&AssetHubPezkuwichain::account_id_of(ALICE),
|
||||
)
|
||||
});
|
||||
|
||||
Pezkuwichain::execute_with(|| {
|
||||
type RuntimeEvent = <Pezkuwichain as Chain>::RuntimeEvent;
|
||||
type RuntimeCall = <Pezkuwichain as Chain>::RuntimeCall;
|
||||
type Runtime = <Pezkuwichain as Chain>::Runtime;
|
||||
type Balances = <Pezkuwichain as PezkuwichainPallet>::Balances;
|
||||
type Treasury = <Pezkuwichain as PezkuwichainPallet>::Treasury;
|
||||
|
||||
// Fund Treasury account on Asset Hub with TYRs.
|
||||
|
||||
let root = <Pezkuwichain as Chain>::RuntimeOrigin::root();
|
||||
let treasury_account = Treasury::account_id();
|
||||
|
||||
// Mint assets to Treasury account on Relay Chain.
|
||||
assert_ok!(Balances::force_set_balance(
|
||||
root.clone(),
|
||||
treasury_account.clone().into(),
|
||||
treasury_balance * 2,
|
||||
));
|
||||
|
||||
Dmp::make_teyrchain_reachable(1000);
|
||||
let native_asset = Location::here();
|
||||
let asset_hub_location: Location = [Teyrchain(1000)].into();
|
||||
let treasury_location: Location = (Parent, PalletInstance(18)).into();
|
||||
|
||||
let teleport_call = RuntimeCall::Utility(pezpallet_utility::Call::<Runtime>::dispatch_as {
|
||||
as_origin: bx!(PezkuwichainOriginCaller::system(RawOrigin::Signed(treasury_account))),
|
||||
call: bx!(RuntimeCall::XcmPallet(pezpallet_xcm::Call::<Runtime>::teleport_assets {
|
||||
dest: bx!(VersionedLocation::from(asset_hub_location.clone())),
|
||||
beneficiary: bx!(VersionedLocation::from(treasury_location)),
|
||||
assets: bx!(VersionedAssets::from(Assets::from(Asset {
|
||||
id: native_asset.clone().into(),
|
||||
fun: treasury_balance.into()
|
||||
}))),
|
||||
fee_asset_id: bx!(native_asset.into()),
|
||||
})),
|
||||
});
|
||||
|
||||
// Dispatched from Root to `dispatch_as` `Signed(treasury_account)`.
|
||||
assert_ok!(teleport_call.dispatch(root));
|
||||
|
||||
assert_expected_events!(
|
||||
Pezkuwichain,
|
||||
vec![
|
||||
RuntimeEvent::XcmPallet(pezpallet_xcm::Event::Sent { .. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
Pezkuwichain::execute_with(|| {
|
||||
type RuntimeEvent = <Pezkuwichain as Chain>::RuntimeEvent;
|
||||
type RuntimeCall = <Pezkuwichain as Chain>::RuntimeCall;
|
||||
type RuntimeOrigin = <Pezkuwichain as Chain>::RuntimeOrigin;
|
||||
type Runtime = <Pezkuwichain as Chain>::Runtime;
|
||||
type Treasury = <Pezkuwichain as PezkuwichainPallet>::Treasury;
|
||||
|
||||
// Fund Alice account from Pezkuwichain Treasury account on Asset Hub.
|
||||
|
||||
let treasury_origin: RuntimeOrigin =
|
||||
pezkuwichain_governance::pezpallet_custom_origins::Origin::Treasurer.into();
|
||||
|
||||
let alice_location: Location = [Junction::AccountId32 {
|
||||
network: None,
|
||||
id: Pezkuwichain::account_id_of(ALICE).into(),
|
||||
}]
|
||||
.into();
|
||||
let asset_hub_location: Location = [Teyrchain(1000)].into();
|
||||
let native_asset = Location::parent();
|
||||
|
||||
let treasury_spend_call = RuntimeCall::Treasury(pezpallet_treasury::Call::<Runtime>::spend {
|
||||
asset_kind: bx!(VersionedLocatableAsset::from((
|
||||
asset_hub_location.clone(),
|
||||
native_asset.into()
|
||||
))),
|
||||
amount: treasury_spend_balance,
|
||||
beneficiary: bx!(VersionedLocation::from(alice_location)),
|
||||
valid_from: None,
|
||||
});
|
||||
|
||||
assert_ok!(treasury_spend_call.dispatch(treasury_origin));
|
||||
|
||||
// Claim the spend.
|
||||
|
||||
let bob_signed = RuntimeOrigin::signed(Pezkuwichain::account_id_of(BOB));
|
||||
assert_ok!(Treasury::payout(bob_signed.clone(), 0));
|
||||
|
||||
assert_expected_events!(
|
||||
Pezkuwichain,
|
||||
vec![
|
||||
RuntimeEvent::Treasury(pezpallet_treasury::Event::AssetSpendApproved { .. }) => {},
|
||||
RuntimeEvent::Treasury(pezpallet_treasury::Event::Paid { .. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
AssetHubPezkuwichain::execute_with(|| {
|
||||
type RuntimeEvent = <AssetHubPezkuwichain as Chain>::RuntimeEvent;
|
||||
type Balances = <AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::Balances;
|
||||
|
||||
// Ensure that the funds deposited to Alice account.
|
||||
|
||||
let alice_account = AssetHubPezkuwichain::account_id_of(ALICE);
|
||||
assert_eq!(
|
||||
<Balances as Inspect<_>>::balance(&alice_account),
|
||||
treasury_spend_balance + init_alice_balance
|
||||
);
|
||||
|
||||
// Assert events triggered by xcm pay program:
|
||||
// 1. treasury asset transferred to spend beneficiary;
|
||||
// 2. response to Relay Chain Treasury pallet instance sent back;
|
||||
// 3. XCM program completed;
|
||||
assert_expected_events!(
|
||||
AssetHubPezkuwichain,
|
||||
vec![
|
||||
RuntimeEvent::Balances(pezpallet_balances::Event::Transfer { .. }) => {},
|
||||
RuntimeEvent::TeyrchainSystem(cumulus_pallet_teyrchain_system::Event::UpwardMessageSent { .. }) => {},
|
||||
RuntimeEvent::MessageQueue(pezpallet_message_queue::Event::Processed { success: true ,.. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn create_and_claim_treasury_spend_in_usdt() {
|
||||
const SPEND_AMOUNT: u128 = 10_000_000;
|
||||
// treasury location from a sibling teyrchain.
|
||||
let treasury_location: Location = Location::new(1, PalletInstance(18));
|
||||
// treasury account on a sibling teyrchain.
|
||||
let treasury_account =
|
||||
ahr_xcm_config::LocationToAccountId::convert_location(&treasury_location).unwrap();
|
||||
let asset_hub_location = Location::new(0, Teyrchain(AssetHubPezkuwichain::para_id().into()));
|
||||
let root = <Pezkuwichain as Chain>::RuntimeOrigin::root();
|
||||
// asset kind to be spent from the treasury.
|
||||
let asset_kind: VersionedLocatableAsset =
|
||||
(asset_hub_location, AssetId((PalletInstance(50), GeneralIndex(USDT_ID.into())).into()))
|
||||
.into();
|
||||
// treasury spend beneficiary.
|
||||
let alice: AccountId = Pezkuwichain::account_id_of(ALICE);
|
||||
let bob: AccountId = Pezkuwichain::account_id_of(BOB);
|
||||
let bob_signed = <Pezkuwichain as Chain>::RuntimeOrigin::signed(bob.clone());
|
||||
|
||||
AssetHubPezkuwichain::execute_with(|| {
|
||||
type Assets = <AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::Assets;
|
||||
|
||||
// USDT created at genesis, mint some assets to the treasury account.
|
||||
assert_ok!(<Assets as Mutate<_>>::mint_into(USDT_ID, &treasury_account, SPEND_AMOUNT * 4));
|
||||
// beneficiary has zero balance.
|
||||
assert_eq!(<Assets as FungiblesInspect<_>>::balance(USDT_ID, &alice,), 0u128,);
|
||||
});
|
||||
|
||||
Pezkuwichain::execute_with(|| {
|
||||
type RuntimeEvent = <Pezkuwichain as Chain>::RuntimeEvent;
|
||||
type Treasury = <Pezkuwichain as PezkuwichainPallet>::Treasury;
|
||||
type AssetRate = <Pezkuwichain as PezkuwichainPallet>::AssetRate;
|
||||
|
||||
// create a conversion rate from `asset_kind` to the native currency.
|
||||
assert_ok!(AssetRate::create(root.clone(), Box::new(asset_kind.clone()), 2.into()));
|
||||
|
||||
Dmp::make_teyrchain_reachable(1000);
|
||||
|
||||
// create and approve a treasury spend.
|
||||
assert_ok!(Treasury::spend(
|
||||
root,
|
||||
Box::new(asset_kind),
|
||||
SPEND_AMOUNT,
|
||||
Box::new(Location::new(0, Into::<[u8; 32]>::into(alice.clone())).into()),
|
||||
None,
|
||||
));
|
||||
// claim the spend.
|
||||
assert_ok!(Treasury::payout(bob_signed.clone(), 0));
|
||||
|
||||
assert_expected_events!(
|
||||
Pezkuwichain,
|
||||
vec![
|
||||
RuntimeEvent::Treasury(pezpallet_treasury::Event::Paid { .. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
AssetHubPezkuwichain::execute_with(|| {
|
||||
type RuntimeEvent = <AssetHubPezkuwichain as Chain>::RuntimeEvent;
|
||||
type Assets = <AssetHubPezkuwichain as AssetHubPezkuwichainPallet>::Assets;
|
||||
|
||||
// assert events triggered by xcm pay program
|
||||
// 1. treasury asset transferred to spend beneficiary
|
||||
// 2. response to Relay Chain treasury pallet instance sent back
|
||||
// 3. XCM program completed
|
||||
assert_expected_events!(
|
||||
AssetHubPezkuwichain,
|
||||
vec![
|
||||
RuntimeEvent::Assets(pezpallet_assets::Event::Transferred { asset_id: id, from, to, amount }) => {
|
||||
id: id == &USDT_ID,
|
||||
from: from == &treasury_account,
|
||||
to: to == &alice,
|
||||
amount: amount == &SPEND_AMOUNT,
|
||||
},
|
||||
RuntimeEvent::TeyrchainSystem(cumulus_pallet_teyrchain_system::Event::UpwardMessageSent { .. }) => {},
|
||||
RuntimeEvent::MessageQueue(pezpallet_message_queue::Event::Processed { success: true ,.. }) => {},
|
||||
]
|
||||
);
|
||||
// beneficiary received the assets from the treasury.
|
||||
assert_eq!(<Assets as FungiblesInspect<_>>::balance(USDT_ID, &alice,), SPEND_AMOUNT,);
|
||||
});
|
||||
|
||||
Pezkuwichain::execute_with(|| {
|
||||
type RuntimeEvent = <Pezkuwichain as Chain>::RuntimeEvent;
|
||||
type Treasury = <Pezkuwichain as PezkuwichainPallet>::Treasury;
|
||||
|
||||
// check the payment status to ensure the response from the AssetHub was received.
|
||||
assert_ok!(Treasury::check_status(bob_signed, 0));
|
||||
assert_expected_events!(
|
||||
Pezkuwichain,
|
||||
vec![
|
||||
RuntimeEvent::Treasury(pezpallet_treasury::Event::SpendProcessed { .. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
}
|
||||
+298
@@ -0,0 +1,298 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! Tests for XCM fee estimation in the runtime.
|
||||
|
||||
use crate::imports::*;
|
||||
use emulated_integration_tests_common::test_can_estimate_and_pay_exact_fees;
|
||||
use pezframe_support::dispatch::RawOrigin;
|
||||
use xcm_runtime_apis::{
|
||||
dry_run::runtime_decl_for_dry_run_api::DryRunApiV2,
|
||||
fees::runtime_decl_for_xcm_payment_api::XcmPaymentApiV2,
|
||||
};
|
||||
|
||||
fn sender_assertions(test: ParaToParaThroughAHTest) {
|
||||
type RuntimeEvent = <PenpalA as Chain>::RuntimeEvent;
|
||||
PenpalA::assert_xcm_pallet_attempted_complete(None);
|
||||
|
||||
assert_expected_events!(
|
||||
PenpalA,
|
||||
vec![
|
||||
RuntimeEvent::ForeignAssets(
|
||||
pezpallet_assets::Event::Burned { asset_id, owner, balance }
|
||||
) => {
|
||||
asset_id: *asset_id == Location::new(1, []),
|
||||
owner: *owner == test.sender.account_id,
|
||||
balance: *balance == test.args.amount,
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
fn hop_assertions(test: ParaToParaThroughAHTest) {
|
||||
type RuntimeEvent = <AssetHubPezkuwichain as Chain>::RuntimeEvent;
|
||||
AssetHubPezkuwichain::assert_xcmp_queue_success(None);
|
||||
|
||||
assert_expected_events!(
|
||||
AssetHubPezkuwichain,
|
||||
vec![
|
||||
RuntimeEvent::Balances(
|
||||
pezpallet_balances::Event::Burned { amount, .. }
|
||||
) => {
|
||||
amount: *amount > test.args.amount * 90/100,
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
fn receiver_assertions(test: ParaToParaThroughAHTest) {
|
||||
type RuntimeEvent = <PenpalB as Chain>::RuntimeEvent;
|
||||
PenpalB::assert_xcmp_queue_success(None);
|
||||
|
||||
assert_expected_events!(
|
||||
PenpalB,
|
||||
vec![
|
||||
RuntimeEvent::ForeignAssets(
|
||||
pezpallet_assets::Event::Issued { asset_id, owner, .. }
|
||||
) => {
|
||||
asset_id: *asset_id == Location::new(1, []),
|
||||
owner: *owner == test.receiver.account_id,
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
fn transfer_assets_para_to_para_through_ah_call(
|
||||
test: ParaToParaThroughAHTest,
|
||||
) -> <PenpalA as Chain>::RuntimeCall {
|
||||
type RuntimeCall = <PenpalA as Chain>::RuntimeCall;
|
||||
|
||||
let asset_hub_location: Location =
|
||||
PenpalB::sibling_location_of(AssetHubPezkuwichain::para_id());
|
||||
let custom_xcm_on_dest = Xcm::<()>(vec![DepositAsset {
|
||||
assets: Wild(AllCounted(test.args.assets.len() as u32)),
|
||||
beneficiary: test.args.beneficiary,
|
||||
}]);
|
||||
RuntimeCall::PezkuwiXcm(pezpallet_xcm::Call::transfer_assets_using_type_and_then {
|
||||
dest: bx!(test.args.dest.into()),
|
||||
assets: bx!(test.args.assets.clone().into()),
|
||||
assets_transfer_type: bx!(TransferType::RemoteReserve(asset_hub_location.clone().into())),
|
||||
remote_fees_id: bx!(VersionedAssetId::from(AssetId(Location::new(1, [])))),
|
||||
fees_transfer_type: bx!(TransferType::RemoteReserve(asset_hub_location.into())),
|
||||
custom_xcm_on_dest: bx!(VersionedXcm::from(custom_xcm_on_dest)),
|
||||
weight_limit: test.args.weight_limit,
|
||||
})
|
||||
}
|
||||
|
||||
/// We are able to dry-run and estimate the fees for a multi-hop XCM journey.
|
||||
/// Scenario: Alice on PenpalA has some DOTs and wants to send them to PenpalB.
|
||||
/// We want to know the fees using the `DryRunApi` and `XcmPaymentApi`.
|
||||
#[test]
|
||||
fn multi_hop_works() {
|
||||
let destination = PenpalA::sibling_location_of(PenpalB::para_id());
|
||||
let sender = PenpalASender::get();
|
||||
let amount_to_send = 1_000_000_000_000;
|
||||
let asset_owner = PenpalAssetOwner::get();
|
||||
let assets: Assets = (Parent, amount_to_send).into();
|
||||
let fee_asset_id: AssetId = Parent.into();
|
||||
let relay_native_asset_location = Location::parent();
|
||||
let sender_as_seen_by_ah = AssetHubPezkuwichain::sibling_location_of(PenpalA::para_id());
|
||||
let sov_of_sender_on_ah =
|
||||
AssetHubPezkuwichain::sovereign_account_id_of(sender_as_seen_by_ah.clone());
|
||||
|
||||
// fund Teyrchain's sender account
|
||||
PenpalA::mint_foreign_asset(
|
||||
<PenpalA as Chain>::RuntimeOrigin::signed(asset_owner.clone()),
|
||||
relay_native_asset_location.clone(),
|
||||
sender.clone(),
|
||||
amount_to_send * 2,
|
||||
);
|
||||
|
||||
// fund the Teyrchain Origin's SA on AssetHub with the native tokens held in reserve.
|
||||
AssetHubPezkuwichain::fund_accounts(vec![(sov_of_sender_on_ah.clone(), amount_to_send * 2)]);
|
||||
|
||||
// Init values for Teyrchain Destination
|
||||
let beneficiary_id = PenpalBReceiver::get();
|
||||
|
||||
let test_args = TestContext {
|
||||
sender: PenpalASender::get(), // Bob in PenpalB.
|
||||
receiver: PenpalBReceiver::get(), // Alice.
|
||||
args: TestArgs::new_para(
|
||||
destination,
|
||||
beneficiary_id.clone(),
|
||||
amount_to_send,
|
||||
assets,
|
||||
None,
|
||||
fee_asset_id,
|
||||
),
|
||||
};
|
||||
let mut test = ParaToParaThroughAHTest::new(test_args);
|
||||
|
||||
// We get them from the PenpalA closure.
|
||||
let mut delivery_fees_amount = 0;
|
||||
let mut remote_message = VersionedXcm::from(Xcm(Vec::new()));
|
||||
<PenpalA as TestExt>::execute_with(|| {
|
||||
type Runtime = <PenpalA as Chain>::Runtime;
|
||||
type OriginCaller = <PenpalA as Chain>::OriginCaller;
|
||||
|
||||
let call = transfer_assets_para_to_para_through_ah_call(test.clone());
|
||||
let origin = OriginCaller::system(RawOrigin::Signed(sender.clone()));
|
||||
let result = Runtime::dry_run_call(origin, call, xcm::prelude::XCM_VERSION).unwrap();
|
||||
// We filter the result to get only the messages we are interested in.
|
||||
let (destination_to_query, messages_to_query) = &result
|
||||
.forwarded_xcms
|
||||
.iter()
|
||||
.find(|(destination, _)| {
|
||||
*destination == VersionedLocation::from(Location::new(1, [Teyrchain(1000)]))
|
||||
})
|
||||
.unwrap();
|
||||
assert_eq!(messages_to_query.len(), 1);
|
||||
remote_message = messages_to_query[0].clone();
|
||||
let asset_id_for_delivery_fees = VersionedAssetId::from(Location::parent());
|
||||
let delivery_fees = Runtime::query_delivery_fees(
|
||||
destination_to_query.clone(),
|
||||
remote_message.clone(),
|
||||
asset_id_for_delivery_fees,
|
||||
)
|
||||
.unwrap();
|
||||
delivery_fees_amount = get_amount_from_versioned_assets(delivery_fees);
|
||||
});
|
||||
|
||||
// These are set in the AssetHub closure.
|
||||
let mut intermediate_execution_fees = 0;
|
||||
let mut intermediate_delivery_fees_amount = 0;
|
||||
let mut intermediate_remote_message = VersionedXcm::from(Xcm::<()>(Vec::new()));
|
||||
<AssetHubPezkuwichain as TestExt>::execute_with(|| {
|
||||
type Runtime = <AssetHubPezkuwichain as Chain>::Runtime;
|
||||
type RuntimeCall = <AssetHubPezkuwichain as Chain>::RuntimeCall;
|
||||
|
||||
// First we get the execution fees.
|
||||
let weight = Runtime::query_xcm_weight(remote_message.clone()).unwrap();
|
||||
intermediate_execution_fees = Runtime::query_weight_to_asset_fee(
|
||||
weight,
|
||||
VersionedAssetId::from(AssetId(Location::new(1, []))),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// We have to do this to turn `VersionedXcm<()>` into `VersionedXcm<RuntimeCall>`.
|
||||
let xcm_program = VersionedXcm::from(Xcm::<RuntimeCall>::from(
|
||||
remote_message.clone().try_into().unwrap(),
|
||||
));
|
||||
|
||||
// Now we get the delivery fees to the final destination.
|
||||
let result =
|
||||
Runtime::dry_run_xcm(sender_as_seen_by_ah.clone().into(), xcm_program).unwrap();
|
||||
let (destination_to_query, messages_to_query) = &result
|
||||
.forwarded_xcms
|
||||
.iter()
|
||||
.find(|(destination, _)| {
|
||||
*destination == VersionedLocation::from(Location::new(1, [Teyrchain(2001)]))
|
||||
})
|
||||
.unwrap();
|
||||
// There's actually two messages here.
|
||||
// One created when the message we sent from PenpalA arrived and was executed.
|
||||
// The second one when we dry-run the xcm.
|
||||
// We could've gotten the message from the queue without having to dry-run, but
|
||||
// offchain applications would have to dry-run, so we do it here as well.
|
||||
intermediate_remote_message = messages_to_query[0].clone();
|
||||
let asset_id_for_delivery_fees = VersionedAssetId::from(Location::parent());
|
||||
let delivery_fees = Runtime::query_delivery_fees(
|
||||
destination_to_query.clone(),
|
||||
intermediate_remote_message.clone(),
|
||||
asset_id_for_delivery_fees,
|
||||
)
|
||||
.unwrap();
|
||||
intermediate_delivery_fees_amount = get_amount_from_versioned_assets(delivery_fees);
|
||||
});
|
||||
|
||||
// Get the final execution fees in the destination.
|
||||
let mut final_execution_fees = 0;
|
||||
<PenpalB as TestExt>::execute_with(|| {
|
||||
type Runtime = <PenpalA as Chain>::Runtime;
|
||||
|
||||
let weight = Runtime::query_xcm_weight(intermediate_remote_message.clone()).unwrap();
|
||||
final_execution_fees = Runtime::query_weight_to_asset_fee(
|
||||
weight,
|
||||
VersionedAssetId::from(AssetId(Location::parent())),
|
||||
)
|
||||
.unwrap();
|
||||
});
|
||||
|
||||
// Dry-running is done.
|
||||
PenpalA::reset_ext();
|
||||
AssetHubPezkuwichain::reset_ext();
|
||||
PenpalB::reset_ext();
|
||||
|
||||
// Fund accounts again.
|
||||
PenpalA::mint_foreign_asset(
|
||||
<PenpalA as Chain>::RuntimeOrigin::signed(asset_owner),
|
||||
relay_native_asset_location.clone(),
|
||||
sender.clone(),
|
||||
amount_to_send * 2,
|
||||
);
|
||||
AssetHubPezkuwichain::fund_accounts(vec![(sov_of_sender_on_ah, amount_to_send * 2)]);
|
||||
|
||||
// Actually run the extrinsic.
|
||||
let sender_assets_before = PenpalA::execute_with(|| {
|
||||
type ForeignAssets = <PenpalA as PenpalAPallet>::ForeignAssets;
|
||||
<ForeignAssets as Inspect<_>>::balance(relay_native_asset_location.clone(), &sender)
|
||||
});
|
||||
let receiver_assets_before = PenpalB::execute_with(|| {
|
||||
type ForeignAssets = <PenpalB as PenpalBPallet>::ForeignAssets;
|
||||
<ForeignAssets as Inspect<_>>::balance(relay_native_asset_location.clone(), &beneficiary_id)
|
||||
});
|
||||
|
||||
test.set_assertion::<PenpalA>(sender_assertions);
|
||||
test.set_assertion::<AssetHubPezkuwichain>(hop_assertions);
|
||||
test.set_assertion::<PenpalB>(receiver_assertions);
|
||||
let call = transfer_assets_para_to_para_through_ah_call(test.clone());
|
||||
test.set_call(call);
|
||||
test.assert();
|
||||
|
||||
let sender_assets_after = PenpalA::execute_with(|| {
|
||||
type ForeignAssets = <PenpalA as PenpalAPallet>::ForeignAssets;
|
||||
<ForeignAssets as Inspect<_>>::balance(relay_native_asset_location.clone(), &sender)
|
||||
});
|
||||
let receiver_assets_after = PenpalB::execute_with(|| {
|
||||
type ForeignAssets = <PenpalB as PenpalBPallet>::ForeignAssets;
|
||||
<ForeignAssets as Inspect<_>>::balance(relay_native_asset_location, &beneficiary_id)
|
||||
});
|
||||
|
||||
// We know the exact fees on every hop.
|
||||
assert_eq!(
|
||||
sender_assets_after,
|
||||
sender_assets_before - amount_to_send - delivery_fees_amount /* This is charged directly
|
||||
* from the sender's
|
||||
* account. */
|
||||
);
|
||||
assert_eq!(
|
||||
receiver_assets_after,
|
||||
receiver_assets_before + amount_to_send -
|
||||
intermediate_execution_fees -
|
||||
intermediate_delivery_fees_amount -
|
||||
final_execution_fees
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multi_hop_pay_fees_works() {
|
||||
test_can_estimate_and_pay_exact_fees!(
|
||||
PenpalA,
|
||||
AssetHubPezkuwichain,
|
||||
PenpalB,
|
||||
(Parent, 1_000_000_000_000u128),
|
||||
Penpal
|
||||
);
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
[package]
|
||||
name = "asset-hub-zagros-integration-tests"
|
||||
version = "1.0.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license = "Apache-2.0"
|
||||
description = "Asset Hub Zagros runtime integration tests with xcm-emulator"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
assert_matches = { workspace = true }
|
||||
codec = { workspace = true }
|
||||
|
||||
# Bizinikiwi
|
||||
pezframe-support = { workspace = true }
|
||||
pezframe-system = { workspace = true }
|
||||
pezpallet-asset-conversion = { workspace = true }
|
||||
pezpallet-asset-rewards = { workspace = true }
|
||||
pezpallet-assets = { workspace = true }
|
||||
pezpallet-balances = { workspace = true }
|
||||
pezpallet-message-queue = { workspace = true }
|
||||
pezpallet-treasury = { workspace = true }
|
||||
pezsp-core = { workspace = true }
|
||||
pezsp-runtime = { workspace = true }
|
||||
|
||||
# Pezkuwi
|
||||
pezpallet-xcm = { workspace = true }
|
||||
pezkuwi-runtime-common = { workspace = true, default-features = true }
|
||||
xcm = { workspace = true }
|
||||
xcm-builder = { workspace = true }
|
||||
xcm-executor = { workspace = true }
|
||||
xcm-runtime-apis = { workspace = true }
|
||||
|
||||
# Pezcumulus
|
||||
asset-test-utils = { workspace = true, default-features = true }
|
||||
pezcumulus-pezpallet-teyrchain-system = { workspace = true }
|
||||
pezcumulus-pezpallet-xcmp-queue = { workspace = true }
|
||||
emulated-integration-tests-common = { workspace = true }
|
||||
teyrchains-common = { workspace = true, default-features = true }
|
||||
zagros-system-emulated-network = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
pezsp-tracing = { workspace = true, default-features = true }
|
||||
|
||||
[features]
|
||||
runtime-benchmarks = [
|
||||
"asset-test-utils/runtime-benchmarks",
|
||||
"pezcumulus-pezpallet-teyrchain-system/runtime-benchmarks",
|
||||
"pezcumulus-pezpallet-xcmp-queue/runtime-benchmarks",
|
||||
"emulated-integration-tests-common/runtime-benchmarks",
|
||||
"pezframe-support/runtime-benchmarks",
|
||||
"pezframe-system/runtime-benchmarks",
|
||||
"pezpallet-asset-conversion/runtime-benchmarks",
|
||||
"pezpallet-asset-rewards/runtime-benchmarks",
|
||||
"pezpallet-assets/runtime-benchmarks",
|
||||
"pezpallet-balances/runtime-benchmarks",
|
||||
"pezpallet-message-queue/runtime-benchmarks",
|
||||
"pezpallet-treasury/runtime-benchmarks",
|
||||
"pezpallet-xcm/runtime-benchmarks",
|
||||
"pezkuwi-runtime-common/runtime-benchmarks",
|
||||
"pezsp-runtime/runtime-benchmarks",
|
||||
"teyrchains-common/runtime-benchmarks",
|
||||
"xcm-builder/runtime-benchmarks",
|
||||
"xcm-executor/runtime-benchmarks",
|
||||
"xcm-runtime-apis/runtime-benchmarks",
|
||||
"xcm/runtime-benchmarks",
|
||||
"zagros-system-emulated-network/runtime-benchmarks",
|
||||
]
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#[cfg(test)]
|
||||
mod imports {
|
||||
pub(crate) use codec::Encode;
|
||||
|
||||
// Bizinikiwi
|
||||
pub(crate) use pezframe_support::{
|
||||
assert_err, assert_ok,
|
||||
pezpallet_prelude::Weight,
|
||||
pezsp_runtime::{DispatchError, DispatchResult, ModuleError},
|
||||
traits::fungibles::Inspect,
|
||||
BoundedVec,
|
||||
};
|
||||
|
||||
// Pezkuwi
|
||||
pub(crate) use xcm::{
|
||||
latest::{AssetTransferFilter, PEZKUWICHAIN_GENESIS_HASH, ZAGROS_GENESIS_HASH},
|
||||
prelude::{AccountId32 as AccountId32Junction, *},
|
||||
};
|
||||
pub(crate) use xcm_executor::traits::TransferType;
|
||||
|
||||
// Pezcumulus
|
||||
pub(crate) use asset_test_utils::xcm_helpers;
|
||||
pub(crate) use emulated_integration_tests_common::{
|
||||
accounts::DUMMY_EMPTY,
|
||||
test_relay_is_trusted_teleporter, test_teyrchain_is_trusted_teleporter,
|
||||
test_teyrchain_is_trusted_teleporter_for_relay,
|
||||
test_xcm_fee_querying_apis_work_for_asset_hub,
|
||||
xcm_emulator::{
|
||||
assert_expected_events, bx, Chain, RelayChain as Relay, Test, TestArgs, TestContext,
|
||||
TestExt, Teyrchain as Para,
|
||||
},
|
||||
xcm_helpers::{
|
||||
fee_asset, find_mq_processed_id, find_xcm_sent_message_id,
|
||||
get_amount_from_versioned_assets, non_fee_asset, xcm_transact_paid_execution,
|
||||
},
|
||||
xcm_simulator::helpers::TopicIdTracker,
|
||||
PenpalATeleportableAssetLocation, ASSETS_PALLET_ID, RESERVABLE_ASSET_ID, USDT_ID, XCM_V3,
|
||||
};
|
||||
pub(crate) use teyrchains_common::{AccountId, Balance};
|
||||
pub(crate) use zagros_system_emulated_network::{
|
||||
asset_hub_zagros_emulated_chain::{
|
||||
asset_hub_zagros_runtime::{
|
||||
self,
|
||||
governance::TreasuryAccount,
|
||||
xcm_config::{
|
||||
self as ahw_xcm_config, XcmConfig as AssetHubZagrosXcmConfig,
|
||||
ZagrosLocation as RelayLocation,
|
||||
},
|
||||
AssetConversionOrigin as AssetHubZagrosAssetConversionOrigin,
|
||||
ExistentialDeposit as AssetHubZagrosExistentialDeposit, ForeignAssetReserveData,
|
||||
},
|
||||
genesis::{AssetHubZagrosAssetOwner, ED as ASSET_HUB_ZAGROS_ED},
|
||||
AssetHubZagrosParaPallet as AssetHubZagrosPallet,
|
||||
},
|
||||
bridge_hub_zagros_emulated_chain::{
|
||||
bridge_hub_zagros_runtime::xcm_config::{self as bhw_xcm_config},
|
||||
BridgeHubZagrosParaPallet as BridgeHubZagrosPallet,
|
||||
},
|
||||
collectives_zagros_emulated_chain::CollectivesZagrosParaPallet as CollectivesZagrosPallet,
|
||||
coretime_zagros_emulated_chain::CoretimeZagrosParaPallet as CoretimeZagrosPallet,
|
||||
penpal_emulated_chain::{
|
||||
penpal_runtime::xcm_config::{
|
||||
CustomizableAssetFromSystemAssetHub as PenpalCustomizableAssetFromSystemAssetHub,
|
||||
LocalReservableFromAssetHub as PenpalLocalReservableFromAssetHub,
|
||||
LocalTeleportableToAssetHub as PenpalLocalTeleportableToAssetHub,
|
||||
UniversalLocation as PenpalUniversalLocation,
|
||||
UsdtFromAssetHub as PenpalUsdtFromAssetHub,
|
||||
},
|
||||
PenpalAParaPallet as PenpalAPallet, PenpalAssetOwner,
|
||||
PenpalBParaPallet as PenpalBPallet,
|
||||
},
|
||||
people_zagros_emulated_chain::PeopleZagrosParaPallet as PeopleZagrosPallet,
|
||||
zagros_emulated_chain::{
|
||||
genesis::ED as ZAGROS_ED,
|
||||
zagros_runtime::{
|
||||
governance::pezpallet_custom_origins::Origin::Treasurer,
|
||||
xcm_config::{
|
||||
UniversalLocation as ZagrosUniversalLocation, XcmConfig as ZagrosXcmConfig,
|
||||
},
|
||||
Dmp,
|
||||
},
|
||||
ZagrosRelayPallet as ZagrosPallet,
|
||||
},
|
||||
AssetHubZagrosPara as AssetHubZagros, AssetHubZagrosParaReceiver as AssetHubZagrosReceiver,
|
||||
AssetHubZagrosParaSender as AssetHubZagrosSender, BridgeHubZagrosPara as BridgeHubZagros,
|
||||
BridgeHubZagrosParaReceiver as BridgeHubZagrosReceiver,
|
||||
CollectivesZagrosPara as CollectivesZagros, CoretimeZagrosPara as CoretimeZagros,
|
||||
PenpalAPara as PenpalA, PenpalAParaReceiver as PenpalAReceiver,
|
||||
PenpalAParaSender as PenpalASender, PenpalBPara as PenpalB,
|
||||
PenpalBParaReceiver as PenpalBReceiver, PeopleZagrosPara as PeopleZagros,
|
||||
ZagrosRelay as Zagros, ZagrosRelayReceiver as ZagrosReceiver,
|
||||
ZagrosRelaySender as ZagrosSender,
|
||||
};
|
||||
|
||||
pub(crate) const ASSET_ID: u32 = 3;
|
||||
pub(crate) const ASSET_MIN_BALANCE: u128 = 1000;
|
||||
|
||||
pub(crate) type RelayToParaTest = Test<Zagros, PenpalA>;
|
||||
pub(crate) type ParaToRelayTest = Test<PenpalA, Zagros>;
|
||||
pub(crate) type RelayToSystemParaTest = Test<Zagros, AssetHubZagros>;
|
||||
pub(crate) type SystemParaToRelayTest = Test<AssetHubZagros, Zagros>;
|
||||
pub(crate) type SystemParaToParaTest = Test<AssetHubZagros, PenpalA>;
|
||||
pub(crate) type ParaToSystemParaTest = Test<PenpalA, AssetHubZagros>;
|
||||
pub(crate) type ParaToParaThroughRelayTest = Test<PenpalA, PenpalB, Zagros>;
|
||||
pub(crate) type ParaToParaThroughAHTest = Test<PenpalA, PenpalB, AssetHubZagros>;
|
||||
pub(crate) type RelayToParaThroughAHTest = Test<Zagros, PenpalA, AssetHubZagros>;
|
||||
pub(crate) type PenpalToRelayThroughAHTest = Test<PenpalA, Zagros, AssetHubZagros>;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
+277
@@ -0,0 +1,277 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! Tests related to XCM aliasing.
|
||||
|
||||
use crate::imports::*;
|
||||
use emulated_integration_tests_common::{macros::AccountId, test_cross_chain_alias};
|
||||
use pezframe_support::traits::ContainsPair;
|
||||
use xcm::latest::Junctions::*;
|
||||
|
||||
const ALLOWED: bool = true;
|
||||
const DENIED: bool = false;
|
||||
|
||||
const TELEPORT_FEES: bool = true;
|
||||
const RESERVE_TRANSFER_FEES: bool = false;
|
||||
|
||||
#[test]
|
||||
fn account_on_sibling_syschain_aliases_into_same_local_account() {
|
||||
// origin and target are the same account on different chains
|
||||
let origin: AccountId = [1; 32].into();
|
||||
let target = origin.clone();
|
||||
let fees = ZAGROS_ED * 10;
|
||||
|
||||
PenpalB::mint_foreign_asset(
|
||||
<PenpalB as Chain>::RuntimeOrigin::signed(PenpalAssetOwner::get()),
|
||||
Location::parent(),
|
||||
origin.clone(),
|
||||
fees * 10,
|
||||
);
|
||||
|
||||
// On Asset Hub we don't want to support aliasing from other chains:
|
||||
// - there is no real world demand for it, the direction is usually reversed, users already have
|
||||
// accounts on AH and want to use them cross-chain on other chains,
|
||||
// - without real world demand, it's better to keep AH permissions as tight as possible.
|
||||
// Aliasing same account doesn't work on AH.
|
||||
test_cross_chain_alias!(
|
||||
vec![
|
||||
// between BH and AH: denied
|
||||
(BridgeHubZagros, AssetHubZagros, TELEPORT_FEES, DENIED),
|
||||
// between Collectives and AH: denied
|
||||
(CollectivesZagros, AssetHubZagros, TELEPORT_FEES, DENIED),
|
||||
// between Coretime and AH: denied
|
||||
(CoretimeZagros, AssetHubZagros, TELEPORT_FEES, DENIED),
|
||||
// between People and AH: denied
|
||||
(PeopleZagros, AssetHubZagros, TELEPORT_FEES, DENIED),
|
||||
// between Penpal and AH: denied
|
||||
(PenpalB, AssetHubZagros, RESERVE_TRANSFER_FEES, DENIED)
|
||||
],
|
||||
origin,
|
||||
target,
|
||||
fees
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn account_on_sibling_syschain_cannot_alias_into_different_local_account() {
|
||||
// origin and target are different accounts on different chains
|
||||
let origin: AccountId = [1; 32].into();
|
||||
let target: AccountId = [2; 32].into();
|
||||
let fees = ZAGROS_ED * 10;
|
||||
|
||||
PenpalB::mint_foreign_asset(
|
||||
<PenpalB as Chain>::RuntimeOrigin::signed(PenpalAssetOwner::get()),
|
||||
Location::parent(),
|
||||
origin.clone(),
|
||||
fees * 10,
|
||||
);
|
||||
|
||||
// Aliasing different account on different chains
|
||||
test_cross_chain_alias!(
|
||||
vec![
|
||||
// between BH and AH: denied
|
||||
(BridgeHubZagros, AssetHubZagros, TELEPORT_FEES, DENIED),
|
||||
// between Collectives and AH: denied
|
||||
(CollectivesZagros, AssetHubZagros, TELEPORT_FEES, DENIED),
|
||||
// between Coretime and AH: denied
|
||||
(CoretimeZagros, AssetHubZagros, TELEPORT_FEES, DENIED),
|
||||
// between People and AH: denied
|
||||
(PeopleZagros, AssetHubZagros, TELEPORT_FEES, DENIED),
|
||||
// between Penpal and AH: denied
|
||||
(PenpalB, AssetHubZagros, RESERVE_TRANSFER_FEES, DENIED)
|
||||
],
|
||||
origin,
|
||||
target,
|
||||
fees
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn aliasing_child_locations() {
|
||||
use AssetHubZagrosXcmConfig as XcmConfig;
|
||||
AssetHubZagros::execute_with(|| {
|
||||
// Allows aliasing descendant of origin.
|
||||
let origin = Location::new(1, X1([PalletInstance(8)].into()));
|
||||
let target = Location::new(1, X2([PalletInstance(8), GeneralIndex(9)].into()));
|
||||
assert!(<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
let origin = Location::new(1, X1([Teyrchain(8)].into()));
|
||||
let target = Location::new(
|
||||
1,
|
||||
X2([Teyrchain(8), AccountId32 { network: None, id: [1u8; 32] }].into()),
|
||||
);
|
||||
assert!(<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
let origin = Location::new(1, X1([Teyrchain(8)].into()));
|
||||
let target =
|
||||
Location::new(1, X3([Teyrchain(8), PalletInstance(8), GeneralIndex(9)].into()));
|
||||
assert!(<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
|
||||
// Does not allow if not descendant.
|
||||
let origin = Location::new(1, X1([PalletInstance(8)].into()));
|
||||
let target = Location::new(0, X2([PalletInstance(8), GeneralIndex(9)].into()));
|
||||
assert!(!<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
let origin = Location::new(1, X1([Teyrchain(8)].into()));
|
||||
let target = Location::new(
|
||||
0,
|
||||
X2([Teyrchain(8), AccountId32 { network: None, id: [1u8; 32] }].into()),
|
||||
);
|
||||
assert!(!<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
let origin = Location::new(1, X1([Teyrchain(8)].into()));
|
||||
let target = Location::new(0, X1([AccountId32 { network: None, id: [1u8; 32] }].into()));
|
||||
assert!(!<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
let origin = Location::new(1, X1([AccountId32 { network: None, id: [1u8; 32] }].into()));
|
||||
let target = Location::new(0, X1([AccountId32 { network: None, id: [1u8; 32] }].into()));
|
||||
assert!(!<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn asset_hub_root_aliases_anything() {
|
||||
use AssetHubZagrosXcmConfig as XcmConfig;
|
||||
AssetHubZagros::execute_with(|| {
|
||||
// Does not allow local/AH root to alias other (non-descendant) locations.
|
||||
let origin = Location::new(0, Here);
|
||||
|
||||
let target = Location::new(1, X1([Teyrchain(2000)].into()));
|
||||
assert!(!<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
let target = Location::new(1, X1([AccountId32 { network: None, id: [1u8; 32] }].into()));
|
||||
assert!(!<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
let target = Location::new(
|
||||
1,
|
||||
X2([Teyrchain(8), AccountId32 { network: None, id: [1u8; 32] }].into()),
|
||||
);
|
||||
assert!(!<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
let target =
|
||||
Location::new(1, X3([Teyrchain(42), PalletInstance(8), GeneralIndex(9)].into()));
|
||||
assert!(!<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
let target = Location::new(2, X1([GlobalConsensus(Ethereum { chain_id: 1 })].into()));
|
||||
assert!(!<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
let target = Location::new(2, X2([GlobalConsensus(Pezkuwi), Teyrchain(1000)].into()));
|
||||
assert!(!<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
let target = Location::new(1, X2([PalletInstance(8), GeneralIndex(9)].into()));
|
||||
assert!(!<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
|
||||
// Other AH locations cannot alias anything.
|
||||
let origin = Location::new(1, X2([Teyrchain(1000), GeneralIndex(9)].into()));
|
||||
assert!(!<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
let origin = Location::new(1, X2([Teyrchain(1000), PalletInstance(9)].into()));
|
||||
assert!(!<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
let origin = Location::new(
|
||||
1,
|
||||
X2([Teyrchain(1000), AccountId32 { network: None, id: [1u8; 32] }].into()),
|
||||
);
|
||||
assert!(!<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
|
||||
// Other root locations cannot alias anything.
|
||||
let origin = Location::new(1, Here);
|
||||
let target = Location::new(2, X1([GlobalConsensus(Ethereum { chain_id: 1 })].into()));
|
||||
assert!(!<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
let target = Location::new(2, X2([GlobalConsensus(Pezkuwi), Teyrchain(1000)].into()));
|
||||
assert!(!<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
let target = Location::new(0, X2([PalletInstance(8), GeneralIndex(9)].into()));
|
||||
assert!(!<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
|
||||
let origin = Location::new(0, Here);
|
||||
let target = Location::new(1, X1([Teyrchain(2000)].into()));
|
||||
assert!(!<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
let origin = Location::new(1, X1([Teyrchain(1001)].into()));
|
||||
assert!(!<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
let origin = Location::new(1, X1([Teyrchain(1002)].into()));
|
||||
assert!(!<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn authorized_cross_chain_aliases() {
|
||||
// origin and target are different accounts on different chains
|
||||
let origin: AccountId = [100; 32].into();
|
||||
let bad_origin: AccountId = [150; 32].into();
|
||||
let target: AccountId = [200; 32].into();
|
||||
let fees = ZAGROS_ED * 10;
|
||||
|
||||
let pal_admin = <PenpalB as Chain>::RuntimeOrigin::signed(PenpalAssetOwner::get());
|
||||
PenpalB::mint_foreign_asset(pal_admin.clone(), Location::parent(), origin.clone(), fees * 10);
|
||||
PenpalB::mint_foreign_asset(pal_admin, Location::parent(), bad_origin.clone(), fees * 10);
|
||||
AssetHubZagros::fund_accounts(vec![(target.clone(), fees * 10)]);
|
||||
|
||||
// let's authorize `origin` on Penpal to alias `target` on AssetHub
|
||||
AssetHubZagros::execute_with(|| {
|
||||
let penpal_origin = Location::new(
|
||||
1,
|
||||
X2([
|
||||
Teyrchain(PenpalB::para_id().into()),
|
||||
AccountId32 {
|
||||
network: Some(ByGenesis(ZAGROS_GENESIS_HASH)),
|
||||
id: origin.clone().into(),
|
||||
},
|
||||
]
|
||||
.into()),
|
||||
);
|
||||
// `target` adds `penpal_origin` as authorized alias
|
||||
assert_ok!(<AssetHubZagros as AssetHubZagrosPallet>::PezkuwiXcm::add_authorized_alias(
|
||||
<AssetHubZagros as Chain>::RuntimeOrigin::signed(target.clone()),
|
||||
Box::new(penpal_origin.into()),
|
||||
None
|
||||
));
|
||||
});
|
||||
// Verify that unauthorized `bad_origin` cannot alias into `target`, from any chain.
|
||||
test_cross_chain_alias!(
|
||||
vec![
|
||||
// between BH and AssetHub: denied
|
||||
(BridgeHubZagros, AssetHubZagros, TELEPORT_FEES, DENIED),
|
||||
// between Collectives and AssetHub: denied
|
||||
(CollectivesZagros, AssetHubZagros, TELEPORT_FEES, DENIED),
|
||||
// between People and AssetHub: denied
|
||||
(PeopleZagros, AssetHubZagros, TELEPORT_FEES, DENIED),
|
||||
// between Penpal and AssetHub: denied
|
||||
(PenpalB, AssetHubZagros, RESERVE_TRANSFER_FEES, DENIED)
|
||||
],
|
||||
bad_origin,
|
||||
target,
|
||||
fees
|
||||
);
|
||||
// Verify that only authorized `penpal::origin` can alias into `target`, while `origin` on other
|
||||
// chains cannot.
|
||||
test_cross_chain_alias!(
|
||||
vec![
|
||||
// between BH and AssetHub: denied
|
||||
(BridgeHubZagros, AssetHubZagros, TELEPORT_FEES, DENIED),
|
||||
// between Collectives and AssetHub: denied
|
||||
(CollectivesZagros, AssetHubZagros, TELEPORT_FEES, DENIED),
|
||||
// between People and AssetHub: denied
|
||||
(PeopleZagros, AssetHubZagros, TELEPORT_FEES, DENIED),
|
||||
// between Penpal and AssetHub: allowed
|
||||
(PenpalB, AssetHubZagros, RESERVE_TRANSFER_FEES, ALLOWED)
|
||||
],
|
||||
origin,
|
||||
target,
|
||||
fees
|
||||
);
|
||||
// remove authorization for `origin` on Penpal to alias `target` on AssetHub
|
||||
AssetHubZagros::execute_with(|| {
|
||||
// `target` removes all authorized aliases
|
||||
assert_ok!(
|
||||
<AssetHubZagros as AssetHubZagrosPallet>::PezkuwiXcm::remove_all_authorized_aliases(
|
||||
<AssetHubZagros as Chain>::RuntimeOrigin::signed(target.clone())
|
||||
)
|
||||
);
|
||||
});
|
||||
// Verify `penpal::origin` can no longer alias into `target` on AssetHub.
|
||||
test_cross_chain_alias!(
|
||||
vec![(PenpalB, AssetHubZagros, RESERVE_TRANSFER_FEES, DENIED)],
|
||||
origin,
|
||||
target,
|
||||
fees
|
||||
);
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! Tests related to claiming assets trapped during XCM execution.
|
||||
|
||||
use crate::imports::*;
|
||||
|
||||
use emulated_integration_tests_common::test_chain_can_claim_assets;
|
||||
|
||||
#[test]
|
||||
fn assets_can_be_claimed() {
|
||||
let amount = AssetHubZagrosExistentialDeposit::get();
|
||||
let assets: Assets = (Parent, amount).into();
|
||||
|
||||
test_chain_can_claim_assets!(
|
||||
AssetHubZagros,
|
||||
RuntimeCall,
|
||||
NetworkId::ByGenesis(ZAGROS_GENESIS_HASH),
|
||||
assets,
|
||||
amount
|
||||
);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user