Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pallet-xcm: add extrinsic to allow withdrawal of reserve-based assets #1430

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ impl<T: frame_system::Config> pallet_xcm::WeightInfo for WeightInfo<T> {
.saturating_add(Weight::from_parts(0, 1489))
.saturating_add(T::DbWeight::get().reads(1))
}
fn reserve_withdraw_assets() -> Weight {
Weight::from_parts(23_000_000, 0)
.saturating_add(Weight::from_parts(0, 0))
}
/// Storage: `Benchmark::Override` (r:0 w:0)
/// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn execute() -> Weight {
Expand Down
64 changes: 62 additions & 2 deletions cumulus/parachains/runtimes/assets/asset-hub-kusama/tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@
//! Tests for the Statemine (Kusama Assets Hub) chain.

use asset_hub_kusama_runtime::xcm_config::{
AssetFeeAsExistentialDepositMultiplierFeeCharger, KsmLocation, TrustBackedAssetsPalletLocation,
AssetFeeAsExistentialDepositMultiplierFeeCharger, KsmLocation, LocationToAccountId,
TrustBackedAssetsPalletLocation,
};
pub use asset_hub_kusama_runtime::{
xcm_config::{CheckingAccount, ForeignCreatorsSovereignAccountOf, XcmConfig},
AllPalletsWithoutSystem, AssetDeposit, Assets, Balances, ExistentialDeposit, ForeignAssets,
ForeignAssetsInstance, MetadataDepositBase, MetadataDepositPerByte, ParachainSystem, Runtime,
RuntimeCall, RuntimeEvent, SessionKeys, System, TrustBackedAssetsInstance,
RuntimeCall, RuntimeEvent, SessionKeys, System, TrustBackedAssetsInstance, XcmpQueue,
};
use asset_test_utils::{CollatorSessionKeys, ExtBuilder};
use codec::{Decode, Encode};
Expand Down Expand Up @@ -632,3 +633,62 @@ asset_test_utils::include_create_and_manage_foreign_assets_for_local_consensus_p
assert_eq!(ForeignAssets::asset_ids().collect::<Vec<_>>().len(), 1);
})
);

#[test]
fn reserve_transfer_native_asset_works() {
asset_test_utils::test_cases::reserve_transfer_native_asset_works::<
Runtime,
AllPalletsWithoutSystem,
XcmConfig,
ParachainSystem,
XcmpQueue,
LocationToAccountId,
>(
collator_session_keys(),
ExistentialDeposit::get(),
AccountId::from(ALICE),
Box::new(|runtime_event_encoded: Vec<u8>| {
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
Ok(RuntimeEvent::PolkadotXcm(event)) => Some(event),
_ => None,
}
}),
Box::new(|runtime_event_encoded: Vec<u8>| {
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
Ok(RuntimeEvent::XcmpQueue(event)) => Some(event),
_ => None,
}
}),
WeightLimit::Unlimited,
);
}

#[test]
fn reserve_withdraw_foreign_asset_works() {
asset_test_utils::test_cases::reserve_withdraw_foreign_asset_works::<
Runtime,
AllPalletsWithoutSystem,
XcmConfig,
ForeignAssetsInstance,
ParachainSystem,
XcmpQueue,
LocationToAccountId,
>(
collator_session_keys(),
ExistentialDeposit::get(),
AccountId::from(ALICE),
Box::new(|runtime_event_encoded: Vec<u8>| {
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
Ok(RuntimeEvent::PolkadotXcm(event)) => Some(event),
_ => None,
}
}),
Box::new(|runtime_event_encoded: Vec<u8>| {
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
Ok(RuntimeEvent::XcmpQueue(event)) => Some(event),
_ => None,
}
}),
WeightLimit::Unlimited,
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ impl<T: frame_system::Config> pallet_xcm::WeightInfo for WeightInfo<T> {
.saturating_add(Weight::from_parts(0, 1489))
.saturating_add(T::DbWeight::get().reads(1))
}
fn reserve_withdraw_assets() -> Weight {
Weight::from_parts(23_000_000, 0)
.saturating_add(Weight::from_parts(0, 0))
}
/// Storage: `Benchmark::Override` (r:0 w:0)
/// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn execute() -> Weight {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@

use asset_hub_polkadot_runtime::xcm_config::{
AssetFeeAsExistentialDepositMultiplierFeeCharger, CheckingAccount, DotLocation,
ForeignCreatorsSovereignAccountOf, TrustBackedAssetsPalletLocation, XcmConfig,
ForeignCreatorsSovereignAccountOf, LocationToAccountId, TrustBackedAssetsPalletLocation,
XcmConfig,
};
pub use asset_hub_polkadot_runtime::{
AllPalletsWithoutSystem, AssetDeposit, Assets, Balances, ExistentialDeposit, ForeignAssets,
ForeignAssetsInstance, MetadataDepositBase, MetadataDepositPerByte, ParachainSystem, Runtime,
RuntimeCall, RuntimeEvent, SessionKeys, System, TrustBackedAssetsInstance,
RuntimeCall, RuntimeEvent, SessionKeys, System, TrustBackedAssetsInstance, XcmpQueue,
};
use asset_test_utils::{CollatorSessionKeys, ExtBuilder};
use codec::{Decode, Encode};
Expand Down Expand Up @@ -657,3 +658,62 @@ asset_test_utils::include_create_and_manage_foreign_assets_for_local_consensus_p
assert_eq!(ForeignAssets::asset_ids().collect::<Vec<_>>().len(), 1);
})
);

#[test]
fn reserve_transfer_native_asset_works() {
asset_test_utils::test_cases::reserve_transfer_native_asset_works::<
Runtime,
AllPalletsWithoutSystem,
XcmConfig,
ParachainSystem,
XcmpQueue,
LocationToAccountId,
>(
collator_session_keys(),
ExistentialDeposit::get(),
AccountId::from(ALICE),
Box::new(|runtime_event_encoded: Vec<u8>| {
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
Ok(RuntimeEvent::PolkadotXcm(event)) => Some(event),
_ => None,
}
}),
Box::new(|runtime_event_encoded: Vec<u8>| {
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
Ok(RuntimeEvent::XcmpQueue(event)) => Some(event),
_ => None,
}
}),
WeightLimit::Unlimited,
);
}

#[test]
fn reserve_withdraw_foreign_asset_works() {
asset_test_utils::test_cases::reserve_withdraw_foreign_asset_works::<
Runtime,
AllPalletsWithoutSystem,
XcmConfig,
ForeignAssetsInstance,
ParachainSystem,
XcmpQueue,
LocationToAccountId,
>(
collator_session_keys(),
ExistentialDeposit::get(),
AccountId::from(ALICE),
Box::new(|runtime_event_encoded: Vec<u8>| {
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
Ok(RuntimeEvent::PolkadotXcm(event)) => Some(event),
_ => None,
}
}),
Box::new(|runtime_event_encoded: Vec<u8>| {
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
Ok(RuntimeEvent::XcmpQueue(event)) => Some(event),
_ => None,
}
}),
WeightLimit::Unlimited,
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ impl<T: frame_system::Config> pallet_xcm::WeightInfo for WeightInfo<T> {
.saturating_add(Weight::from_parts(0, 1489))
.saturating_add(T::DbWeight::get().reads(1))
}
fn reserve_withdraw_assets() -> Weight {
Weight::from_parts(23_000_000, 0)
.saturating_add(Weight::from_parts(0, 0))
}
fn execute() -> Weight {
// Proof Size summary in bytes:
// Measured: `0`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@
use asset_hub_westend_runtime::{
xcm_config::{
AssetFeeAsExistentialDepositMultiplierFeeCharger, ForeignCreatorsSovereignAccountOf,
WestendLocation,
LocationToAccountId, WestendLocation,
},
AllPalletsWithoutSystem, MetadataDepositBase, MetadataDepositPerByte, RuntimeCall,
RuntimeEvent,
RuntimeEvent, XcmpQueue,
};
pub use asset_hub_westend_runtime::{
xcm_config::{CheckingAccount, TrustBackedAssetsPalletLocation, XcmConfig},
Expand Down Expand Up @@ -666,3 +666,62 @@ fn plain_receive_teleported_asset_works() {
assert_eq!(outcome.ensure_complete(), Ok(()));
})
}

#[test]
fn reserve_transfer_native_asset_works() {
asset_test_utils::test_cases::reserve_transfer_native_asset_works::<
Runtime,
AllPalletsWithoutSystem,
XcmConfig,
ParachainSystem,
XcmpQueue,
LocationToAccountId,
>(
collator_session_keys(),
ExistentialDeposit::get(),
AccountId::from(ALICE),
Box::new(|runtime_event_encoded: Vec<u8>| {
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
Ok(RuntimeEvent::PolkadotXcm(event)) => Some(event),
_ => None,
}
}),
Box::new(|runtime_event_encoded: Vec<u8>| {
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
Ok(RuntimeEvent::XcmpQueue(event)) => Some(event),
_ => None,
}
}),
WeightLimit::Unlimited,
);
}

#[test]
fn reserve_withdraw_foreign_asset_works() {
asset_test_utils::test_cases::reserve_withdraw_foreign_asset_works::<
Runtime,
AllPalletsWithoutSystem,
XcmConfig,
ForeignAssetsInstance,
ParachainSystem,
XcmpQueue,
LocationToAccountId,
>(
collator_session_keys(),
ExistentialDeposit::get(),
AccountId::from(ALICE),
Box::new(|runtime_event_encoded: Vec<u8>| {
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
Ok(RuntimeEvent::PolkadotXcm(event)) => Some(event),
_ => None,
}
}),
Box::new(|runtime_event_encoded: Vec<u8>| {
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
Ok(RuntimeEvent::XcmpQueue(event)) => Some(event),
_ => None,
}
}),
WeightLimit::Unlimited,
);
}
2 changes: 2 additions & 0 deletions cumulus/parachains/runtimes/assets/test-utils/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ parachains-runtimes-test-utils = { path = "../../test-utils", default-features =

# Polkadot
xcm = { package = "staging-xcm", path = "../../../../../polkadot/xcm", default-features = false}
xcm-builder = { package = "staging-xcm-builder", path = "../../../../../polkadot/xcm/xcm-builder", 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}
polkadot-parachain-primitives = { path = "../../../../../polkadot/parachain", default-features = false}
Expand Down Expand Up @@ -72,6 +73,7 @@ std = [
"sp-io/std",
"sp-runtime/std",
"sp-std/std",
"xcm-builder/std",
"xcm-executor/std",
"xcm/std",
]
75 changes: 75 additions & 0 deletions cumulus/parachains/runtimes/assets/test-utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,79 @@
//! Module contains predefined test-case scenarios for `Runtime` with various assets.

pub mod test_cases;

use frame_support::traits::ProcessMessageError;
pub use parachains_runtimes_test_utils::*;

use xcm::latest::prelude::*;
use xcm_builder::{CreateMatcher, MatchXcm};

/// Helper function to verify `xcm` contains all relevant instructions expected on destination
/// chain as part of a reserve-asset-transfer.
pub(crate) fn assert_matches_reserve_asset_deposited_instructions<RuntimeCall>(
xcm: &mut Xcm<RuntimeCall>,
expected_reserve_assets_deposited: &MultiAssets,
expected_beneficiary: &MultiLocation,
) {
let _ = xcm
.0
.matcher()
.skip_inst_while(|inst| !matches!(inst, ReserveAssetDeposited(..)))
.expect("no instruction ReserveAssetDeposited?")
.match_next_inst(|instr| match instr {
ReserveAssetDeposited(reserve_assets)
if reserve_assets == expected_reserve_assets_deposited =>
Ok(()),
_ => Err(ProcessMessageError::BadFormat),
})
.expect("expected instruction ReserveAssetDeposited")
.match_next_inst(|instr| match instr {
ClearOrigin => Ok(()),
_ => Err(ProcessMessageError::BadFormat),
})
.expect("expected instruction ClearOrigin")
.match_next_inst(|instr| match instr {
BuyExecution { .. } => Ok(()),
_ => Err(ProcessMessageError::BadFormat),
})
.expect("expected instruction BuyExecution")
.match_next_inst(|instr| match instr {
DepositAsset { assets: _, beneficiary } if beneficiary == expected_beneficiary =>
Ok(()),
_ => Err(ProcessMessageError::BadFormat),
})
.expect("expected instruction DepositAsset");
}

/// Helper function to verify `xcm` contains all relevant instructions expected on destination
/// chain as part of a reserve-asset-withdrawal.
pub(crate) fn assert_matches_reserve_assets_withdrawal_instructions<RuntimeCall>(
xcm: &mut Xcm<RuntimeCall>,
expected_reserve_assets: &MultiAssets,
expected_beneficiary: &MultiLocation,
) {
let _ = xcm
.0
.matcher()
.match_next_inst(|instr| match instr {
WithdrawAsset(reserve_assets) if reserve_assets == expected_reserve_assets => Ok(()),
_ => Err(ProcessMessageError::BadFormat),
})
.expect("expected instruction WithdrawAsset for reserve asset")
.match_next_inst(|instr| match instr {
ClearOrigin => Ok(()),
_ => Err(ProcessMessageError::BadFormat),
})
.expect("expected instruction ClearOrigin")
.match_next_inst(|instr| match instr {
BuyExecution { .. } => Ok(()),
_ => Err(ProcessMessageError::BadFormat),
})
.expect("expected instruction BuyExecution")
.match_next_inst(|instr| match instr {
DepositAsset { assets: _, beneficiary } if beneficiary == expected_beneficiary =>
Ok(()),
_ => Err(ProcessMessageError::BadFormat),
})
.expect("expected instruction DepositAsset");
}
Loading
Loading