mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-31 04:01:02 +00:00
FRAME: Unity Balance Conversion for Different IDs of Native Asset (#3659)
Introduce types to define 1:1 balance conversion for different relative
asset ids/locations of native asset.
Examples:
native asset on Asset Hub presented as `VersionedLocatableAsset` type in
the context of Relay Chain is
```
{
`location`: (0, Parachain(1000)),
`asset_id`: (1, Here),
}
```
and it's balance should be converted 1:1 by implementations of
`ConversionToAssetBalance` trait.
---------
Co-authored-by: Branislav Kontur <bkontur@gmail.com>
This commit is contained in:
@@ -39,6 +39,8 @@ decl_test_relay_chains! {
|
||||
Hrmp: rococo_runtime::Hrmp,
|
||||
Identity: rococo_runtime::Identity,
|
||||
IdentityMigrator: rococo_runtime::IdentityMigrator,
|
||||
Treasury: rococo_runtime::Treasury,
|
||||
AssetRate: rococo_runtime::AssetRate,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@@ -21,15 +21,20 @@ pallet-balances = { path = "../../../../../../../substrate/frame/balances", defa
|
||||
pallet-assets = { path = "../../../../../../../substrate/frame/assets", default-features = false }
|
||||
pallet-asset-conversion = { path = "../../../../../../../substrate/frame/asset-conversion", default-features = false }
|
||||
pallet-message-queue = { path = "../../../../../../../substrate/frame/message-queue", default-features = false }
|
||||
pallet-treasury = { path = "../../../../../../../substrate/frame/treasury", default-features = false }
|
||||
pallet-utility = { path = "../../../../../../../substrate/frame/utility", default-features = false }
|
||||
|
||||
# Polkadot
|
||||
xcm = { package = "staging-xcm", path = "../../../../../../../polkadot/xcm", default-features = false }
|
||||
pallet-xcm = { path = "../../../../../../../polkadot/xcm/pallet-xcm", default-features = false }
|
||||
xcm-executor = { package = "staging-xcm-executor", path = "../../../../../../../polkadot/xcm/xcm-executor", default-features = false }
|
||||
rococo-runtime = { path = "../../../../../../../polkadot/runtime/rococo" }
|
||||
polkadot-runtime-common = { path = "../../../../../../../polkadot/runtime/common" }
|
||||
rococo-runtime-constants = { path = "../../../../../../../polkadot/runtime/rococo/constants" }
|
||||
|
||||
# Cumulus
|
||||
asset-test-utils = { path = "../../../../../runtimes/assets/test-utils" }
|
||||
cumulus-pallet-parachain-system = { path = "../../../../../../pallets/parachain-system", default-features = false }
|
||||
parachains-common = { path = "../../../../../common" }
|
||||
asset-hub-rococo-runtime = { path = "../../../../../runtimes/assets/asset-hub-rococo" }
|
||||
penpal-runtime = { path = "../../../../../runtimes/testing/penpal" }
|
||||
|
||||
+1
@@ -19,3 +19,4 @@ mod send;
|
||||
mod set_xcm_versions;
|
||||
mod swap;
|
||||
mod teleport;
|
||||
mod treasury;
|
||||
|
||||
+270
@@ -0,0 +1,270 @@
|
||||
// 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};
|
||||
use frame_support::{
|
||||
dispatch::RawOrigin,
|
||||
sp_runtime::traits::Dispatchable,
|
||||
traits::{
|
||||
fungible::Inspect,
|
||||
fungibles::{Create, Inspect as FungiblesInspect, Mutate},
|
||||
},
|
||||
};
|
||||
use parachains_common::AccountId;
|
||||
use polkadot_runtime_common::impls::VersionedLocatableAsset;
|
||||
use rococo_runtime::OriginCaller;
|
||||
use rococo_runtime_constants::currency::GRAND;
|
||||
use xcm_executor::traits::ConvertLocation;
|
||||
|
||||
// Fund Treasury account on Asset Hub from Treasury account on Relay Chain with ROCs.
|
||||
#[test]
|
||||
fn spend_roc_on_asset_hub() {
|
||||
// initial treasury balance on Asset Hub in ROCs.
|
||||
let treasury_balance = 9_000 * GRAND;
|
||||
// the balance spend on Asset Hub.
|
||||
let treasury_spend_balance = 1_000 * GRAND;
|
||||
|
||||
let init_alice_balance = AssetHubRococo::execute_with(|| {
|
||||
<<AssetHubRococo as AssetHubRococoPallet>::Balances as Inspect<_>>::balance(
|
||||
&AssetHubRococo::account_id_of(ALICE),
|
||||
)
|
||||
});
|
||||
|
||||
Rococo::execute_with(|| {
|
||||
type RuntimeEvent = <Rococo as Chain>::RuntimeEvent;
|
||||
type RuntimeCall = <Rococo as Chain>::RuntimeCall;
|
||||
type Runtime = <Rococo as Chain>::Runtime;
|
||||
type Balances = <Rococo as RococoPallet>::Balances;
|
||||
type Treasury = <Rococo as RococoPallet>::Treasury;
|
||||
|
||||
// Fund Treasury account on Asset Hub with ROCs.
|
||||
|
||||
let root = <Rococo 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,
|
||||
));
|
||||
|
||||
let native_asset = Location::here();
|
||||
let asset_hub_location: Location = [Parachain(1000)].into();
|
||||
let treasury_location: Location = (Parent, PalletInstance(18)).into();
|
||||
|
||||
let teleport_call = RuntimeCall::Utility(pallet_utility::Call::<Runtime>::dispatch_as {
|
||||
as_origin: bx!(OriginCaller::system(RawOrigin::Signed(treasury_account))),
|
||||
call: bx!(RuntimeCall::XcmPallet(pallet_xcm::Call::<Runtime>::teleport_assets {
|
||||
dest: bx!(VersionedLocation::V4(asset_hub_location.clone())),
|
||||
beneficiary: bx!(VersionedLocation::V4(treasury_location)),
|
||||
assets: bx!(VersionedAssets::V4(
|
||||
Asset { id: native_asset.clone().into(), fun: treasury_balance.into() }.into()
|
||||
)),
|
||||
fee_asset_item: 0,
|
||||
})),
|
||||
});
|
||||
|
||||
// Dispatched from Root to `despatch_as` `Signed(treasury_account)`.
|
||||
assert_ok!(teleport_call.dispatch(root));
|
||||
|
||||
assert_expected_events!(
|
||||
Rococo,
|
||||
vec![
|
||||
RuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { .. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
Rococo::execute_with(|| {
|
||||
type RuntimeEvent = <Rococo as Chain>::RuntimeEvent;
|
||||
type RuntimeCall = <Rococo as Chain>::RuntimeCall;
|
||||
type RuntimeOrigin = <Rococo as Chain>::RuntimeOrigin;
|
||||
type Runtime = <Rococo as Chain>::Runtime;
|
||||
type Treasury = <Rococo as RococoPallet>::Treasury;
|
||||
|
||||
// Fund Alice account from Rococo Treasury account on Asset Hub.
|
||||
|
||||
let treasury_origin: RuntimeOrigin =
|
||||
rococo_runtime::governance::pallet_custom_origins::Origin::Treasurer.into();
|
||||
|
||||
let alice_location: Location =
|
||||
[Junction::AccountId32 { network: None, id: Rococo::account_id_of(ALICE).into() }]
|
||||
.into();
|
||||
let asset_hub_location: Location = [Parachain(1000)].into();
|
||||
let native_asset = Location::parent();
|
||||
|
||||
let treasury_spend_call = RuntimeCall::Treasury(pallet_treasury::Call::<Runtime>::spend {
|
||||
asset_kind: bx!(VersionedLocatableAsset::V4 {
|
||||
location: asset_hub_location.clone(),
|
||||
asset_id: native_asset.into(),
|
||||
}),
|
||||
amount: treasury_spend_balance,
|
||||
beneficiary: bx!(VersionedLocation::V4(alice_location)),
|
||||
valid_from: None,
|
||||
});
|
||||
|
||||
assert_ok!(treasury_spend_call.dispatch(treasury_origin));
|
||||
|
||||
// Claim the spend.
|
||||
|
||||
let bob_signed = RuntimeOrigin::signed(Rococo::account_id_of(BOB));
|
||||
assert_ok!(Treasury::payout(bob_signed.clone(), 0));
|
||||
|
||||
assert_expected_events!(
|
||||
Rococo,
|
||||
vec![
|
||||
RuntimeEvent::Treasury(pallet_treasury::Event::AssetSpendApproved { .. }) => {},
|
||||
RuntimeEvent::Treasury(pallet_treasury::Event::Paid { .. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
AssetHubRococo::execute_with(|| {
|
||||
type RuntimeEvent = <AssetHubRococo as Chain>::RuntimeEvent;
|
||||
type Balances = <AssetHubRococo as AssetHubRococoPallet>::Balances;
|
||||
|
||||
// Ensure that the funds deposited to Alice account.
|
||||
|
||||
let alice_account = AssetHubRococo::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!(
|
||||
AssetHubRococo,
|
||||
vec![
|
||||
RuntimeEvent::Balances(pallet_balances::Event::Transfer { .. }) => {},
|
||||
RuntimeEvent::ParachainSystem(cumulus_pallet_parachain_system::Event::UpwardMessageSent { .. }) => {},
|
||||
RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true ,.. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn create_and_claim_treasury_spend_in_usdt() {
|
||||
const ASSET_ID: u32 = 1984;
|
||||
const SPEND_AMOUNT: u128 = 1_000_000;
|
||||
// treasury location from a sibling parachain.
|
||||
let treasury_location: Location = Location::new(1, PalletInstance(18));
|
||||
// treasury account on a sibling parachain.
|
||||
let treasury_account =
|
||||
asset_hub_rococo_runtime::xcm_config::LocationToAccountId::convert_location(
|
||||
&treasury_location,
|
||||
)
|
||||
.unwrap();
|
||||
let asset_hub_location =
|
||||
v3::Location::new(0, v3::Junction::Parachain(AssetHubRococo::para_id().into()));
|
||||
let root = <Rococo as Chain>::RuntimeOrigin::root();
|
||||
// asset kind to be spend from the treasury.
|
||||
let asset_kind = VersionedLocatableAsset::V3 {
|
||||
location: asset_hub_location,
|
||||
asset_id: v3::AssetId::Concrete(
|
||||
(v3::Junction::PalletInstance(50), v3::Junction::GeneralIndex(ASSET_ID.into())).into(),
|
||||
),
|
||||
};
|
||||
// treasury spend beneficiary.
|
||||
let alice: AccountId = Rococo::account_id_of(ALICE);
|
||||
let bob: AccountId = Rococo::account_id_of(BOB);
|
||||
let bob_signed = <Rococo as Chain>::RuntimeOrigin::signed(bob.clone());
|
||||
|
||||
AssetHubRococo::execute_with(|| {
|
||||
type Assets = <AssetHubRococo as AssetHubRococoPallet>::Assets;
|
||||
|
||||
// create an asset class and mint some assets to the treasury account.
|
||||
assert_ok!(<Assets as Create<_>>::create(
|
||||
ASSET_ID,
|
||||
treasury_account.clone(),
|
||||
true,
|
||||
SPEND_AMOUNT / 2
|
||||
));
|
||||
assert_ok!(<Assets as Mutate<_>>::mint_into(ASSET_ID, &treasury_account, SPEND_AMOUNT * 4));
|
||||
// beneficiary has zero balance.
|
||||
assert_eq!(<Assets as FungiblesInspect<_>>::balance(ASSET_ID, &alice,), 0u128,);
|
||||
});
|
||||
|
||||
Rococo::execute_with(|| {
|
||||
type RuntimeEvent = <Rococo as Chain>::RuntimeEvent;
|
||||
type Treasury = <Rococo as RococoPallet>::Treasury;
|
||||
type AssetRate = <Rococo as RococoPallet>::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()));
|
||||
|
||||
// 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!(
|
||||
Rococo,
|
||||
vec![
|
||||
RuntimeEvent::Treasury(pallet_treasury::Event::Paid { .. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
AssetHubRococo::execute_with(|| {
|
||||
type RuntimeEvent = <AssetHubRococo as Chain>::RuntimeEvent;
|
||||
type Assets = <AssetHubRococo as AssetHubRococoPallet>::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!(
|
||||
AssetHubRococo,
|
||||
vec![
|
||||
RuntimeEvent::Assets(pallet_assets::Event::Transferred { asset_id: id, from, to, amount }) => {
|
||||
id: id == &ASSET_ID,
|
||||
from: from == &treasury_account,
|
||||
to: to == &alice,
|
||||
amount: amount == &SPEND_AMOUNT,
|
||||
},
|
||||
RuntimeEvent::ParachainSystem(cumulus_pallet_parachain_system::Event::UpwardMessageSent { .. }) => {},
|
||||
RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true ,.. }) => {},
|
||||
]
|
||||
);
|
||||
// beneficiary received the assets from the treasury.
|
||||
assert_eq!(<Assets as FungiblesInspect<_>>::balance(ASSET_ID, &alice,), SPEND_AMOUNT,);
|
||||
});
|
||||
|
||||
Rococo::execute_with(|| {
|
||||
type RuntimeEvent = <Rococo as Chain>::RuntimeEvent;
|
||||
type Treasury = <Rococo as RococoPallet>::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!(
|
||||
Rococo,
|
||||
vec![
|
||||
RuntimeEvent::Treasury(pallet_treasury::Event::SpendProcessed { .. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
[package]
|
||||
name = "collectives-westend-integration-tests"
|
||||
version = "1.0.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license = "Apache-2.0"
|
||||
description = "Collectives Westend runtime integration tests with xcm-emulator"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
codec = { package = "parity-scale-codec", version = "3.4.0", default-features = false }
|
||||
assert_matches = "1.5.0"
|
||||
|
||||
# Substrate
|
||||
sp-runtime = { path = "../../../../../../../substrate/primitives/runtime", default-features = false }
|
||||
frame-support = { path = "../../../../../../../substrate/frame/support", default-features = false }
|
||||
pallet-balances = { path = "../../../../../../../substrate/frame/balances", default-features = false }
|
||||
pallet-asset-rate = { path = "../../../../../../../substrate/frame/asset-rate", default-features = false }
|
||||
pallet-assets = { path = "../../../../../../../substrate/frame/assets", default-features = false }
|
||||
pallet-treasury = { path = "../../../../../../../substrate/frame/treasury", default-features = false }
|
||||
pallet-message-queue = { path = "../../../../../../../substrate/frame/message-queue", default-features = false }
|
||||
pallet-utility = { path = "../../../../../../../substrate/frame/utility", default-features = false }
|
||||
|
||||
# Polkadot
|
||||
polkadot-runtime-common = { path = "../../../../../../../polkadot/runtime/common" }
|
||||
xcm = { package = "staging-xcm", path = "../../../../../../../polkadot/xcm", default-features = false }
|
||||
xcm-executor = { package = "staging-xcm-executor", path = "../../../../../../../polkadot/xcm/xcm-executor", default-features = false }
|
||||
pallet-xcm = { path = "../../../../../../../polkadot/xcm/pallet-xcm", default-features = false }
|
||||
westend-runtime = { path = "../../../../../../../polkadot/runtime/westend" }
|
||||
westend-runtime-constants = { path = "../../../../../../../polkadot/runtime/westend/constants" }
|
||||
|
||||
# Cumulus
|
||||
parachains-common = { path = "../../../../../../parachains/common" }
|
||||
testnet-parachains-constants = { path = "../../../../../runtimes/constants", features = ["westend"] }
|
||||
asset-hub-westend-runtime = { path = "../../../../../runtimes/assets/asset-hub-westend" }
|
||||
collectives-westend-runtime = { path = "../../../../../runtimes/collectives/collectives-westend" }
|
||||
cumulus-pallet-xcmp-queue = { default-features = false, path = "../../../../../../pallets/xcmp-queue" }
|
||||
cumulus-pallet-parachain-system = { default-features = false, path = "../../../../../../pallets/parachain-system" }
|
||||
emulated-integration-tests-common = { path = "../../../common", default-features = false }
|
||||
westend-system-emulated-network = { path = "../../../networks/westend-system" }
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
// 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 xcm::{prelude::*, v3};
|
||||
|
||||
pub use emulated_integration_tests_common::xcm_emulator::{
|
||||
assert_expected_events, bx, Chain, RelayChain as Relay, TestExt,
|
||||
};
|
||||
pub use westend_system_emulated_network::{
|
||||
asset_hub_westend_emulated_chain::AssetHubWestendParaPallet as AssetHubWestendPallet,
|
||||
collectives_westend_emulated_chain::CollectivesWestendParaPallet as CollectivesWestendPallet,
|
||||
westend_emulated_chain::WestendRelayPallet as WestendPallet,
|
||||
AssetHubWestendPara as AssetHubWestend, CollectivesWestendPara as CollectivesWestend,
|
||||
WestendRelay as Westend,
|
||||
};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
+236
@@ -0,0 +1,236 @@
|
||||
// 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::*;
|
||||
use asset_hub_westend_runtime::xcm_config::LocationToAccountId as AssetHubLocationToAccountId;
|
||||
use emulated_integration_tests_common::accounts::ALICE;
|
||||
use frame_support::{
|
||||
assert_ok, dispatch::RawOrigin, instances::Instance1, sp_runtime::traits::Dispatchable,
|
||||
traits::fungible::Inspect,
|
||||
};
|
||||
use polkadot_runtime_common::impls::VersionedLocatableAsset;
|
||||
use westend_runtime::OriginCaller;
|
||||
use westend_runtime_constants::currency::UNITS;
|
||||
use xcm_executor::traits::ConvertLocation;
|
||||
|
||||
// Fund Fellowship Treasury from Westend Treasury and spend from Fellowship Treasury.
|
||||
#[test]
|
||||
fn fellowship_treasury_spend() {
|
||||
// initial treasury balance on Asset Hub in WNDs.
|
||||
let treasury_balance = 20_000_000 * UNITS;
|
||||
// target fellowship balance on Asset Hub in WNDs.
|
||||
let fellowship_treasury_balance = 1_000_000 * UNITS;
|
||||
// fellowship first spend balance in WNDs.
|
||||
let fellowship_spend_balance = 10_000 * UNITS;
|
||||
|
||||
let init_alice_balance = AssetHubWestend::execute_with(|| {
|
||||
<<AssetHubWestend as AssetHubWestendPallet>::Balances as Inspect<_>>::balance(
|
||||
&AssetHubWestend::account_id_of(ALICE),
|
||||
)
|
||||
});
|
||||
|
||||
Westend::execute_with(|| {
|
||||
type RuntimeEvent = <Westend as Chain>::RuntimeEvent;
|
||||
type RuntimeCall = <Westend as Chain>::RuntimeCall;
|
||||
type Runtime = <Westend as Chain>::Runtime;
|
||||
type Balances = <Westend as WestendPallet>::Balances;
|
||||
type Treasury = <Westend as WestendPallet>::Treasury;
|
||||
|
||||
// Fund Treasury account on Asset Hub with WNDs.
|
||||
|
||||
let root = <Westend as Chain>::RuntimeOrigin::root();
|
||||
let treasury_account = Treasury::account_id();
|
||||
|
||||
// Mist assets to Treasury account on Relay Chain.
|
||||
assert_ok!(Balances::force_set_balance(
|
||||
root.clone(),
|
||||
treasury_account.clone().into(),
|
||||
treasury_balance * 2,
|
||||
));
|
||||
|
||||
let native_asset = Location::here();
|
||||
let asset_hub_location: Location = [Parachain(1000)].into();
|
||||
let treasury_location: Location = (Parent, PalletInstance(37)).into();
|
||||
|
||||
let teleport_call = RuntimeCall::Utility(pallet_utility::Call::<Runtime>::dispatch_as {
|
||||
as_origin: bx!(OriginCaller::system(RawOrigin::Signed(treasury_account))),
|
||||
call: bx!(RuntimeCall::XcmPallet(pallet_xcm::Call::<Runtime>::teleport_assets {
|
||||
dest: bx!(VersionedLocation::V4(asset_hub_location.clone())),
|
||||
beneficiary: bx!(VersionedLocation::V4(treasury_location)),
|
||||
assets: bx!(VersionedAssets::V4(
|
||||
Asset { id: native_asset.clone().into(), fun: treasury_balance.into() }.into()
|
||||
)),
|
||||
fee_asset_item: 0,
|
||||
})),
|
||||
});
|
||||
|
||||
// Dispatched from Root to `dispatch_as` `Signed(treasury_account)`.
|
||||
assert_ok!(teleport_call.dispatch(root));
|
||||
|
||||
assert_expected_events!(
|
||||
Westend,
|
||||
vec![
|
||||
RuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { .. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
Westend::execute_with(|| {
|
||||
type RuntimeEvent = <Westend as Chain>::RuntimeEvent;
|
||||
type RuntimeCall = <Westend as Chain>::RuntimeCall;
|
||||
type RuntimeOrigin = <Westend as Chain>::RuntimeOrigin;
|
||||
type Runtime = <Westend as Chain>::Runtime;
|
||||
type Treasury = <Westend as WestendPallet>::Treasury;
|
||||
|
||||
// Fund Fellowship Treasury from Westend Treasury.
|
||||
|
||||
let treasury_origin: RuntimeOrigin =
|
||||
westend_runtime::governance::pallet_custom_origins::Origin::Treasurer.into();
|
||||
let fellowship_treasury_location: Location =
|
||||
Location::new(1, [Parachain(1001), PalletInstance(65)]);
|
||||
let asset_hub_location: Location = [Parachain(1000)].into();
|
||||
let native_asset = Location::parent();
|
||||
|
||||
let treasury_spend_call = RuntimeCall::Treasury(pallet_treasury::Call::<Runtime>::spend {
|
||||
asset_kind: bx!(VersionedLocatableAsset::V4 {
|
||||
location: asset_hub_location.clone(),
|
||||
asset_id: native_asset.into(),
|
||||
}),
|
||||
amount: fellowship_treasury_balance,
|
||||
beneficiary: bx!(VersionedLocation::V4(fellowship_treasury_location)),
|
||||
valid_from: None,
|
||||
});
|
||||
|
||||
assert_ok!(treasury_spend_call.dispatch(treasury_origin));
|
||||
|
||||
// Claim the spend.
|
||||
|
||||
let alice_signed = RuntimeOrigin::signed(Westend::account_id_of(ALICE));
|
||||
assert_ok!(Treasury::payout(alice_signed.clone(), 0));
|
||||
|
||||
assert_expected_events!(
|
||||
Westend,
|
||||
vec![
|
||||
RuntimeEvent::Treasury(pallet_treasury::Event::AssetSpendApproved { .. }) => {},
|
||||
RuntimeEvent::Treasury(pallet_treasury::Event::Paid { .. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
AssetHubWestend::execute_with(|| {
|
||||
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
|
||||
type Balances = <AssetHubWestend as AssetHubWestendPallet>::Balances;
|
||||
|
||||
// Ensure that the funds deposited to the Fellowship Treasury account.
|
||||
|
||||
let fellowship_treasury_location: Location =
|
||||
Location::new(1, [Parachain(1001), PalletInstance(65)]);
|
||||
let fellowship_treasury_account =
|
||||
AssetHubLocationToAccountId::convert_location(&fellowship_treasury_location).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
<Balances as Inspect<_>>::balance(&fellowship_treasury_account),
|
||||
fellowship_treasury_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!(
|
||||
AssetHubWestend,
|
||||
vec![
|
||||
RuntimeEvent::Balances(pallet_balances::Event::Transfer { .. }) => {},
|
||||
RuntimeEvent::ParachainSystem(cumulus_pallet_parachain_system::Event::UpwardMessageSent { .. }) => {},
|
||||
RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true ,.. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
CollectivesWestend::execute_with(|| {
|
||||
type RuntimeEvent = <CollectivesWestend as Chain>::RuntimeEvent;
|
||||
type RuntimeCall = <CollectivesWestend as Chain>::RuntimeCall;
|
||||
type RuntimeOrigin = <CollectivesWestend as Chain>::RuntimeOrigin;
|
||||
type Runtime = <CollectivesWestend as Chain>::Runtime;
|
||||
type FellowshipTreasury =
|
||||
<CollectivesWestend as CollectivesWestendPallet>::FellowshipTreasury;
|
||||
|
||||
// Fund Alice account from Fellowship Treasury.
|
||||
|
||||
let fellows_origin: RuntimeOrigin =
|
||||
collectives_westend_runtime::fellowship::pallet_fellowship_origins::Origin::Fellows
|
||||
.into();
|
||||
let asset_hub_location: Location = (Parent, Parachain(1000)).into();
|
||||
let native_asset = Location::parent();
|
||||
|
||||
let alice_location: Location = [Junction::AccountId32 {
|
||||
network: None,
|
||||
id: CollectivesWestend::account_id_of(ALICE).into(),
|
||||
}]
|
||||
.into();
|
||||
|
||||
let fellowship_treasury_spend_call =
|
||||
RuntimeCall::FellowshipTreasury(pallet_treasury::Call::<Runtime, Instance1>::spend {
|
||||
asset_kind: bx!(VersionedLocatableAsset::V4 {
|
||||
location: asset_hub_location,
|
||||
asset_id: native_asset.into(),
|
||||
}),
|
||||
amount: fellowship_spend_balance,
|
||||
beneficiary: bx!(VersionedLocation::V4(alice_location)),
|
||||
valid_from: None,
|
||||
});
|
||||
|
||||
assert_ok!(fellowship_treasury_spend_call.dispatch(fellows_origin));
|
||||
|
||||
// Claim the spend.
|
||||
|
||||
let alice_signed = RuntimeOrigin::signed(CollectivesWestend::account_id_of(ALICE));
|
||||
assert_ok!(FellowshipTreasury::payout(alice_signed.clone(), 0));
|
||||
|
||||
assert_expected_events!(
|
||||
CollectivesWestend,
|
||||
vec![
|
||||
RuntimeEvent::FellowshipTreasury(pallet_treasury::Event::AssetSpendApproved { .. }) => {},
|
||||
RuntimeEvent::FellowshipTreasury(pallet_treasury::Event::Paid { .. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
AssetHubWestend::execute_with(|| {
|
||||
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
|
||||
type Balances = <AssetHubWestend as AssetHubWestendPallet>::Balances;
|
||||
|
||||
// Ensure that the funds deposited to Alice account.
|
||||
|
||||
let alice_account = AssetHubWestend::account_id_of(ALICE);
|
||||
assert_eq!(
|
||||
<Balances as Inspect<_>>::balance(&alice_account),
|
||||
fellowship_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!(
|
||||
AssetHubWestend,
|
||||
vec![
|
||||
RuntimeEvent::Balances(pallet_balances::Event::Transfer { .. }) => {},
|
||||
RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. }) => {},
|
||||
RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true ,.. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// 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 fellowship_treasury;
|
||||
Reference in New Issue
Block a user