Skip to content

Commit

Permalink
XCMv5: add ExecuteWithOrigin instruction (#6304)
Browse files Browse the repository at this point in the history
Added `ExecuteWithOrigin` instruction according to the old XCM RFC 38:
polkadot-fellows/xcm-format#38.

This instruction allows you to descend or clear while going back again.

- [x] Implementation
- [x] Unit tests
- [x] Integration tests
- [x] Benchmarks
- [x] PRDoc

Modify `WithComputedOrigin` barrier to allow, for example, fees to be
paid with a descendant origin using this instruction.

---------

Signed-off-by: Adrian Catangiu <[email protected]>
Co-authored-by: Adrian Catangiu <[email protected]>
Co-authored-by: Andrii <[email protected]>
Co-authored-by: Branislav Kontur <[email protected]>
Co-authored-by: Joseph Zhao <[email protected]>
Co-authored-by: Nazar Mokrynskyi <[email protected]>
Co-authored-by: Bastian Köcher <[email protected]>
Co-authored-by: Shawn Tabrizi <[email protected]>
Co-authored-by: command-bot <>
  • Loading branch information
8 people committed Nov 13, 2024
1 parent 65ee808 commit 413f900
Show file tree
Hide file tree
Showing 32 changed files with 635 additions and 144 deletions.
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 @@ -37,6 +37,7 @@ pallet-xcm = { workspace = true }
xcm-runtime-apis = { workspace = true }

# Cumulus
assets-common = { workspace = true }
parachains-common = { workspace = true, default-features = true }
asset-test-utils = { workspace = true, default-features = true }
cumulus-pallet-xcmp-queue = { workspace = true }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@

use crate::imports::*;

use assets_common::runtime_api::runtime_decl_for_fungibles_api::FungiblesApiV2;
use emulated_integration_tests_common::test_chain_can_claim_assets;
use frame_support::traits::fungible::Mutate;
use xcm_executor::traits::DropAssets;

#[test]
Expand All @@ -33,3 +35,83 @@ fn assets_can_be_claimed() {
amount
);
}

#[test]
fn chain_can_claim_assets_for_its_users() {
// Many Penpal users have assets trapped in AssetHubWestend.
let beneficiaries: Vec<(Location, Assets)> = vec![
// Some WND.
(
Location::new(1, [Parachain(2000), AccountId32 { id: [0u8; 32], network: None }]),
(Parent, 10_000_000_000_000u128).into(),
),
// Some USDT.
(
Location::new(1, [Parachain(2000), AccountId32 { id: [1u8; 32], network: None }]),
([PalletInstance(ASSETS_PALLET_ID), GeneralIndex(USDT_ID.into())], 100_000_000u128)
.into(),
),
];

// Start with those assets trapped.
AssetHubWestend::execute_with(|| {
for (location, assets) in &beneficiaries {
<AssetHubWestend as AssetHubWestendPallet>::PolkadotXcm::drop_assets(
location,
assets.clone().into(),
&XcmContext { origin: None, message_id: [0u8; 32], topic: None },
);
}
});

let penpal_to_asset_hub = PenpalA::sibling_location_of(AssetHubWestend::para_id());
let mut builder = Xcm::<()>::builder()
.withdraw_asset((Parent, 1_000_000_000_000u128))
.pay_fees((Parent, 100_000_000_000u128));

// Loop through all beneficiaries.
for (location, assets) in &beneficiaries {
builder = builder.execute_with_origin(
// We take only the last part, the `AccountId32` junction.
Some((*location.interior().last().unwrap()).into()),
Xcm::<()>::builder_unsafe()
.claim_asset(assets.clone(), Location::new(0, [GeneralIndex(5)])) // Means lost assets were version 5.
.deposit_asset(assets.clone(), location.clone())
.build(),
)
}

// Finish assembling the message.
let message = builder.build();

// Fund PenpalA's sovereign account on AssetHubWestend so it can pay for fees.
AssetHubWestend::execute_with(|| {
let penpal_as_seen_by_asset_hub = AssetHubWestend::sibling_location_of(PenpalA::para_id());
let penpal_sov_account_on_asset_hub =
AssetHubWestend::sovereign_account_id_of(penpal_as_seen_by_asset_hub);
type Balances = <AssetHubWestend as AssetHubWestendPallet>::Balances;
assert_ok!(<Balances as Mutate<_>>::mint_into(
&penpal_sov_account_on_asset_hub,
2_000_000_000_000u128,
));
});

// We can send a message from Penpal root that claims all those assets for each beneficiary.
PenpalA::execute_with(|| {
assert_ok!(<PenpalA as PenpalAPallet>::PolkadotXcm::send(
<PenpalA as Chain>::RuntimeOrigin::root(),
bx!(penpal_to_asset_hub.into()),
bx!(VersionedXcm::from(message)),
));
});

// We assert beneficiaries have received their funds.
AssetHubWestend::execute_with(|| {
for (location, expected_assets) in &beneficiaries {
let sov_account = AssetHubWestend::sovereign_account_id_of(location.clone());
let actual_assets =
<AssetHubWestend as Chain>::Runtime::query_account_balances(sov_account).unwrap();
assert_eq!(VersionedAssets::from(expected_assets.clone()), actual_assets);
}
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -253,4 +253,7 @@ impl<Call> XcmWeightInfo<Call> for AssetHubRococoXcmWeight<Call> {
fn unpaid_execution(_: &WeightLimit, _: &Option<Location>) -> Weight {
XcmGeneric::<Runtime>::unpaid_execution()
}
fn execute_with_origin(_: &Option<InteriorLocation>, _: &Xcm<Call>) -> Weight {
XcmGeneric::<Runtime>::execute_with_origin()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -373,4 +373,11 @@ impl<T: frame_system::Config> WeightInfo<T> {
// Minimum execution time: 668_000 picoseconds.
Weight::from_parts(726_000, 0)
}
pub fn execute_with_origin() -> Weight {
// Proof Size summary in bytes:
// Measured: `0`
// Estimated: `0`
// Minimum execution time: 713_000 picoseconds.
Weight::from_parts(776_000, 0)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -253,4 +253,7 @@ impl<Call> XcmWeightInfo<Call> for AssetHubWestendXcmWeight<Call> {
fn unpaid_execution(_: &WeightLimit, _: &Option<Location>) -> Weight {
XcmGeneric::<Runtime>::unpaid_execution()
}
fn execute_with_origin(_: &Option<InteriorLocation>, _: &Xcm<Call>) -> Weight {
XcmGeneric::<Runtime>::execute_with_origin()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -373,4 +373,11 @@ impl<T: frame_system::Config> WeightInfo<T> {
// Minimum execution time: 638_000 picoseconds.
Weight::from_parts(708_000, 0)
}
pub fn execute_with_origin() -> Weight {
// Proof Size summary in bytes:
// Measured: `0`
// Estimated: `0`
// Minimum execution time: 713_000 picoseconds.
Weight::from_parts(776_000, 0)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -256,4 +256,7 @@ impl<Call> XcmWeightInfo<Call> for BridgeHubRococoXcmWeight<Call> {
fn set_asset_claimer(_location: &Location) -> Weight {
XcmGeneric::<Runtime>::set_asset_claimer()
}
fn execute_with_origin(_: &Option<InteriorLocation>, _: &Xcm<Call>) -> Weight {
XcmGeneric::<Runtime>::execute_with_origin()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -380,4 +380,11 @@ impl<T: frame_system::Config> WeightInfo<T> {
// Minimum execution time: 707_000 picoseconds.
Weight::from_parts(749_000, 0)
}
pub fn execute_with_origin() -> Weight {
// Proof Size summary in bytes:
// Measured: `0`
// Estimated: `0`
// Minimum execution time: 713_000 picoseconds.
Weight::from_parts(776_000, 0)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -257,4 +257,7 @@ impl<Call> XcmWeightInfo<Call> for BridgeHubWestendXcmWeight<Call> {
fn unpaid_execution(_: &WeightLimit, _: &Option<Location>) -> Weight {
XcmGeneric::<Runtime>::unpaid_execution()
}
fn execute_with_origin(_: &Option<InteriorLocation>, _: &Xcm<Call>) -> Weight {
XcmGeneric::<Runtime>::execute_with_origin()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -380,4 +380,11 @@ impl<T: frame_system::Config> WeightInfo<T> {
// Minimum execution time: 707_000 picoseconds.
Weight::from_parts(749_000, 0)
}
pub fn execute_with_origin() -> Weight {
// Proof Size summary in bytes:
// Measured: `0`
// Estimated: `0`
// Minimum execution time: 713_000 picoseconds.
Weight::from_parts(776_000, 0)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -254,4 +254,7 @@ impl<Call> XcmWeightInfo<Call> for CoretimeRococoXcmWeight<Call> {
fn set_asset_claimer(_location: &Location) -> Weight {
XcmGeneric::<Runtime>::set_asset_claimer()
}
fn execute_with_origin(_: &Option<InteriorLocation>, _: &Xcm<Call>) -> Weight {
XcmGeneric::<Runtime>::execute_with_origin()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -338,4 +338,11 @@ impl<T: frame_system::Config> WeightInfo<T> {
// Minimum execution time: 707_000 picoseconds.
Weight::from_parts(749_000, 0)
}
pub fn execute_with_origin() -> Weight {
// Proof Size summary in bytes:
// Measured: `0`
// Estimated: `0`
// Minimum execution time: 713_000 picoseconds.
Weight::from_parts(776_000, 0)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -254,4 +254,7 @@ impl<Call> XcmWeightInfo<Call> for CoretimeWestendXcmWeight<Call> {
fn unpaid_execution(_: &WeightLimit, _: &Option<Location>) -> Weight {
XcmGeneric::<Runtime>::unpaid_execution()
}
fn execute_with_origin(_: &Option<InteriorLocation>, _: &Xcm<Call>) -> Weight {
XcmGeneric::<Runtime>::execute_with_origin()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -338,4 +338,11 @@ impl<T: frame_system::Config> WeightInfo<T> {
// Minimum execution time: 707_000 picoseconds.
Weight::from_parts(749_000, 0)
}
pub fn execute_with_origin() -> Weight {
// Proof Size summary in bytes:
// Measured: `0`
// Estimated: `0`
// Minimum execution time: 713_000 picoseconds.
Weight::from_parts(776_000, 0)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -253,4 +253,7 @@ impl<Call> XcmWeightInfo<Call> for PeopleRococoXcmWeight<Call> {
fn set_asset_claimer(_location: &Location) -> Weight {
XcmGeneric::<Runtime>::set_asset_claimer()
}
fn execute_with_origin(_: &Option<InteriorLocation>, _: &Xcm<Call>) -> Weight {
XcmGeneric::<Runtime>::execute_with_origin()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -338,4 +338,11 @@ impl<T: frame_system::Config> WeightInfo<T> {
// Minimum execution time: 707_000 picoseconds.
Weight::from_parts(749_000, 0)
}
pub fn execute_with_origin() -> Weight {
// Proof Size summary in bytes:
// Measured: `0`
// Estimated: `0`
// Minimum execution time: 713_000 picoseconds.
Weight::from_parts(776_000, 0)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -253,4 +253,7 @@ impl<Call> XcmWeightInfo<Call> for PeopleWestendXcmWeight<Call> {
fn set_asset_claimer(_location: &Location) -> Weight {
XcmGeneric::<Runtime>::set_asset_claimer()
}
fn execute_with_origin(_: &Option<InteriorLocation>, _: &Xcm<Call>) -> Weight {
XcmGeneric::<Runtime>::execute_with_origin()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -338,4 +338,11 @@ impl<T: frame_system::Config> WeightInfo<T> {
// Minimum execution time: 707_000 picoseconds.
Weight::from_parts(749_000, 0)
}
pub fn execute_with_origin() -> Weight {
// Proof Size summary in bytes:
// Measured: `0`
// Estimated: `0`
// Minimum execution time: 713_000 picoseconds.
Weight::from_parts(776_000, 0)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -344,4 +344,11 @@ impl<T: frame_system::Config> pallet_xcm_benchmarks::generic::WeightInfo for Wei
Weight::from_parts(1_354_000, 0)
.saturating_add(Weight::from_parts(0, 0))
}
fn execute_with_origin() -> Weight {
// Proof Size summary in bytes:
// Measured: `0`
// Estimated: `0`
// Minimum execution time: 713_000 picoseconds.
Weight::from_parts(776_000, 0)
}
}
3 changes: 3 additions & 0 deletions polkadot/runtime/rococo/src/weights/xcm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,9 @@ impl<RuntimeCall> XcmWeightInfo<RuntimeCall> for RococoXcmWeight<RuntimeCall> {
fn set_asset_claimer(_location: &Location) -> Weight {
XcmGeneric::<Runtime>::set_asset_claimer()
}
fn execute_with_origin(_: &Option<InteriorLocation>, _: &Xcm<RuntimeCall>) -> Weight {
XcmGeneric::<Runtime>::execute_with_origin()
}
}

#[test]
Expand Down
Loading

0 comments on commit 413f900

Please sign in to comment.