Skip to content
Merged
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 CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- [AHM] Do not migrate staking era forcing info to AH ([polkadot-fellows/runtimes/pull/939](https://github.com/polkadot-fellows/runtimes/pull/939))
- [AHM] Small fixes to successfully dry-run migration tests ([polkadot-fellows/runtimes/pull/942](https://github.com/polkadot-fellows/runtimes/pull/942))
- [AHM] Fix crowdloan withdrawing and weight limit ([polkadot-fellows/runtimes/pull/943](https://github.com/polkadot-fellows/runtimes/pull/943))
- [Encointer] Fix remote treasury payout on asset hub ([polkadot-fellows/runtimes/pull/944](https://github.com/polkadot-fellows/runtimes/pull/944))

## [1.9.1] 30.09.2025

Expand Down
12 changes: 6 additions & 6 deletions Cargo.lock

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

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ encointer-balances-tx-payment = { version = "~20.1.0", default-features = false
encointer-balances-tx-payment-rpc-runtime-api = { version = "~20.1.0", default-features = false }
encointer-kusama-runtime = { path = "system-parachains/encointer" }
encointer-kusama-emulated-chain = { path = "integration-tests/emulated/chains/parachains/encointer/encointer-kusama" }
encointer-primitives = { version = "~20.5.0", default-features = false }
encointer-primitives = { version = "~20.5.1", default-features = false }
enumflags2 = { version = "0.7.7" }
frame-benchmarking = { version = "42.0.0", default-features = false }
frame-election-provider-support = { version = "42.0.0", default-features = false }
Expand Down Expand Up @@ -122,11 +122,11 @@ pallet-encointer-ceremonies = { version = "~20.1.0", default-features = false }
pallet-encointer-ceremonies-rpc-runtime-api = { version = "~20.1.0", default-features = false }
pallet-encointer-communities = { version = "~20.1.0", default-features = false }
pallet-encointer-communities-rpc-runtime-api = { version = "~20.1.0", default-features = false }
pallet-encointer-democracy = { version = "~20.6.0", default-features = false }
pallet-encointer-democracy = { version = "~20.6.1", default-features = false }
pallet-encointer-faucet = { version = "~20.2.0", default-features = false }
pallet-encointer-reputation-commitments = { version = "~20.1.0", default-features = false }
pallet-encointer-scheduler = { version = "~20.1.0", default-features = false }
pallet-encointer-treasuries = { version = "~20.7.0", default-features = false }
pallet-encointer-treasuries = { version = "~20.7.1", default-features = false }
pallet-encointer-treasuries-rpc-runtime-api = { version = "~20.3.0", default-features = false }
pallet-fast-unstake = { version = "41.0.0", default-features = false }
pallet-glutton = { version = "28.0.0", default-features = false }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@ fn remote_treasury_usdt_payout_works() {
.unwrap();
});

assert_asset_hub_kusama_tokens_received(recipient.clone());

<AssetHubKusama as TestExt>::execute_with(|| {
type Assets = <AssetHubKusama as AssetHubKusamaParaPallet>::Assets;
type Balances = <AssetHubKusama as AssetHubKusamaParaPallet>::Balances;
Expand Down Expand Up @@ -239,3 +241,20 @@ fn remote_treasury_native_payout_works() {
assert_eq!(Balances::free_balance(&recipient), SPEND_AMOUNT);
});
}

fn assert_asset_hub_kusama_tokens_received(who: AccountId) {
AssetHubKusama::execute_with(|| {
type RuntimeEvent = <AssetHubKusama as Chain>::RuntimeEvent;
assert_expected_events!(
AssetHubKusama,
vec![
RuntimeEvent::MessageQueue(
pallet_message_queue::Event::Processed { success: true, .. }
) => {},
RuntimeEvent::Assets(pallet_assets::Event::Transferred { to, .. }) => {
to: *to == who,
},
]
);
});
}
5 changes: 0 additions & 5 deletions system-parachains/encointer/src/tests/unit_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,6 @@ fn transfer_over_xcm_works() {
WithdrawAsset(fee_asset.clone().into()),
PayFees { asset: fee_asset },
SetAppendix(Xcm(vec![
ReportError(QueryResponseInfo {
destination: (Parent, Parachain(42)).into(),
query_id: 1,
max_weight: Weight::zero(),
}),
RefundSurplus,
DepositAsset {
assets: AssetFilter::Wild(WildAsset::All),
Expand Down
11 changes: 3 additions & 8 deletions system-parachains/encointer/src/treasuries_xcm_payout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use alloc::vec;
use core::marker::PhantomData;
use frame_support::traits::{tokens::PaymentStatus, Get};
use sp_runtime::traits::TryConvert;
use xcm::{latest::Error, opaque::lts::Weight, prelude::*};
use xcm::{latest::Error, prelude::*};
use xcm_builder::LocatableAssetId;
use xcm_executor::traits::{QueryHandler, QueryResponseStatus};

Expand All @@ -30,7 +30,7 @@ pub use pallet_encointer_treasuries::Transfer;
// This is the value that has been queried from the Asset Hub Kusama runtime.
// There is an integration test in `integration-tests/emulated/tests/encointer/encointer-kusama/
// That verifies that this fee is correct and will catch fee changes in Asset-Hub Kusama
pub const REMOTE_XCM_TRANSFER_REMOTE_EXECUTION_FEE: u128 = 12905733320;
pub const REMOTE_XCM_TRANSFER_REMOTE_EXECUTION_FEE: u128 = 12699199987;

pub trait GetRemoteFee {
fn get_remote_fee(xcm: Xcm<()>, asset_id: Option<AssetId>) -> Asset;
Expand Down Expand Up @@ -258,7 +258,7 @@ fn remote_transfer_xcm(
asset_id: AssetId,
amount: u128,
remote_fee: Asset,
query_id: QueryId,
_query_id: QueryId,
) -> Result<Xcm<()>, Error> {
// Transform `from` into Location::new(1, XX([Parachain(source), from.interior }])
// We need this one for the refunds.
Expand All @@ -271,11 +271,6 @@ fn remote_transfer_xcm(
WithdrawAsset(vec![remote_fee.clone()].into()),
PayFees { asset: remote_fee },
SetAppendix(Xcm(vec![
ReportError(QueryResponseInfo {
destination: destination.clone(),
query_id,
max_weight: Weight::zero(),
}),
Comment on lines -274 to -278

@clangenb clangenb Oct 4, 2025

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First, I thought that this is just a max_weight issue, so I changed this to max. However, I still got a NotHoldingFees error, although I surely withdraw enough as shown in the logs.

I have fixed the problem for now, but I guess that this might even be an XCM bug such that ReportError doesn't the appendix together with DescendOrigin yet? What do the XCM overlords think @franciscoaguirre, @bkontur, @acatangiu?

XCM Execution Logs
2025-10-04T07:13:08.321016Z TRACE xcm::process: origin=Some(Location { parents: 1, interior: X1([Parachain(1001)]) }) total_surplus=Weight { ref_time: 0, proof_size: 0 } total_refunded=Weight { ref_time: 0, proof_size: 0 } error_handler_weight=Weight { ref_time: 0, proof_size: 0 }
2025-10-04T07:13:08.321058Z TRACE xcm::process_instruction: Processing instruction instruction=DescendOrigin(X1([AccountId32 { network: None, id: [150, 141, 187, 98, 102, 33, 87, 174, 108, 105, 38, 201, 33, 252, 99, 215, 105, 11, 253, 230, 89, 13, 87, 138, 18, 41, 154, 220, 108, 179, 239, 229] }]))
2025-10-04T07:13:08.321082Z TRACE xcm::process_instruction: Processing instruction instruction=WithdrawAsset(Assets([Asset { id: AssetId(Location { parents: 1, interior: Here }), fun: Fungible(12905733320) }]))
2025-10-04T07:13:08.321096Z TRACE xcm::ensure_can_subsume_assets: Ensuring subsume assets work worst_case_holding_len=1 holding_limit=64
2025-10-04T07:13:08.321269Z TRACE xcm::fungible_adapter: withdraw_asset what=Asset { id: AssetId(Location { parents: 1, interior: Here }), fun: Fungible(12905733320) } who=Location { parents: 1, interior: X2([Parachain(1001), AccountId32 { network: None, id: [150, 141, 187, 98, 102, 33, 87, 174, 108, 105, 38, 201, 33, 252, 99, 215, 105, 11, 253, 230, 89, 13, 87, 138, 18, 41, 154, 220, 108, 179, 239, 229] }]) }
2025-10-04T07:13:08.323721Z TRACE xcm::process_instruction: Processing instruction instruction=PayFees { asset: Asset { id: AssetId(Location { parents: 1, interior: Here }), fun: Fungible(12905733320) } }
2025-10-04T07:13:08.323749Z TRACE xcm::executor::PayFees: asset_for_fees=Asset { id: AssetId(Location { parents: 1, interior: Here }), fun: Fungible(12905733320) } message_weight=Weight { ref_time: 43793552000, proof_size: 387172 }
2025-10-04T07:13:08.323939Z TRACE xcm::weight: UsingComponents::buy_weight weight=Weight { ref_time: 43793552000, proof_size: 387172 } payment=AssetsInHolding { fungible: {AssetId(Location { parents: 1, interior: Here }): 12905733320}, non_fungible: {} } context=XcmContext { origin: Some(Location { parents: 1, interior: X2([Parachain(1001), AccountId32 { network: None, id: [150, 141, 187, 98, 102, 33, 87, 174, 108, 105, 38, 201, 33, 252, 99, 215, 105, 11, 253, 230, 89, 13, 87, 138, 18, 41, 154, 220, 108, 179, 239, 229] }]) }), message_id: [207, 224, 150, 20, 104, 44, 231, 40, 113, 150, 204, 227, 199, 74, 162, 200, 138, 143, 3, 176, 227, 143, 46, 145, 94, 71, 215, 205, 7, 177, 227, 162], topic: None }
2025-10-04T07:13:08.323991Z TRACE xcm::buy_weight: Buy weight succeeded weight_trader=staging_xcm_builder::weight::UsingComponents<system_parachains_constants::kusama::fee::WeightToFee, asset_hub_kusama_runtime::xcm_config::KsmLocation, sp_core::crypto::AccountId32, pallet_balances::pallet::Pallet<asset_hub_kusama_runtime::Runtime>, frame_support::traits::tokens::imbalance::on_unbalanced::ResolveTo<asset_hub_kusama_runtime::xcm_config::StakingPot, pallet_balances::pallet::Pallet<asset_hub_kusama_runtime::Runtime>>>
2025-10-04T07:13:08.324157Z TRACE xcm::process_instruction: Processing instruction instruction=SetAppendix(Xcm([ReportError(QueryResponseInfo { destination: Location { parents: 1, interior: X1([Parachain(1001)]) }, query_id: 0, max_weight: Weight { ref_time: 18446744073709551615, proof_size: 18446744073709551615 } }), RefundSurplus, DepositAsset { assets: Wild(All), beneficiary: Location { parents: 1, interior: X2([Parachain(1001), AccountId32 { network: None, id: [150, 141, 187, 98, 102, 33, 87, 174, 108, 105, 38, 201, 33, 252, 99, 215, 105, 11, 253, 230, 89, 13, 87, 138, 18, 41, 154, 220, 108, 179, 239, 229] }]) } }]))
2025-10-04T07:13:08.324182Z TRACE xcm::weight: WeightInfoBounds Xcm([ReportError(QueryResponseInfo { destination: Location { parents: 1, interior: X1([Parachain(1001)]) }, query_id: 0, max_weight: Weight { ref_time: 18446744073709551615, proof_size: 18446744073709551615 } }), RefundSurplus, DepositAsset { assets: Wild(All), beneficiary: Location { parents: 1, interior: X2([Parachain(1001), AccountId32 { network: None, id: [150, 141, 187, 98, 102, 33, 87, 174, 108, 105, 38, 201, 33, 252, 99, 215, 105, 11, 253, 230, 89, 13, 87, 138, 18, 41, 154, 220, 108, 179, 239, 229] }]) } }])
2025-10-04T07:13:08.324225Z TRACE xcm::process_instruction: Processing instruction instruction=TransferAsset { assets: Assets([Asset { id: AssetId(Location { parents: 0, interior: X2([PalletInstance(50), GeneralIndex(1984)]) }), fun: Fungible(10000000) }]), beneficiary: Location { parents: 0, interior: X1([AccountId32 { network: None, id: [5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5] }]) } }
2025-10-04T07:13:08.324402Z TRACE xcm::fungible_adapter: internal_transfer_asset what=Asset { id: AssetId(Location { parents: 0, interior: X2([PalletInstance(50), GeneralIndex(1984)]) }), fun: Fungible(10000000) } from=Location { parents: 1, interior: X2([Parachain(1001), AccountId32 { network: None, id: [150, 141, 187, 98, 102, 33, 87, 174, 108, 105, 38, 201, 33, 252, 99, 215, 105, 11, 253, 230, 89, 13, 87, 138, 18, 41, 154, 220, 108, 179, 239, 229] }]) } to=Location { parents: 0, interior: X1([AccountId32 { network: None, id: [5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5] }]) }
2025-10-04T07:13:08.324446Z TRACE xcm::fungibles_adapter: internal_transfer_asset what=Asset { id: AssetId(Location { parents: 0, interior: X2([PalletInstance(50), GeneralIndex(1984)]) }), fun: Fungible(10000000) } from=Location { parents: 1, interior: X2([Parachain(1001), AccountId32 { network: None, id: [150, 141, 187, 98, 102, 33, 87, 174, 108, 105, 38, 201, 33, 252, 99, 215, 105, 11, 253, 230, 89, 13, 87, 138, 18, 41, 154, 220, 108, 179, 239, 229] }]) } to=Location { parents: 0, interior: X1([AccountId32 { network: None, id: [5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5] }]) }
2025-10-04T07:13:08.328370Z TRACE xcm::process_instruction: Processing instruction instruction=SetTopic([207, 224, 150, 20, 104, 44, 231, 40, 113, 150, 204, 227, 199, 74, 162, 200, 138, 143, 3, 176, 227, 143, 46, 145, 94, 71, 215, 205, 7, 177, 227, 162])
2025-10-04T07:13:08.328393Z TRACE xcm::execute: Message executed result=Ok(())
2025-10-04T07:13:08.328407Z TRACE xcm::process: origin=Some(Location { parents: 1, interior: X2([Parachain(1001), AccountId32 { network: None, id: [150, 141, 187, 98, 102, 33, 87, 174, 108, 105, 38, 201, 33, 252, 99, 215, 105, 11, 253, 230, 89, 13, 87, 138, 18, 41, 154, 220, 108, 179, 239, 229] }]) }) total_surplus=Weight { ref_time: 0, proof_size: 0 } total_refunded=Weight { ref_time: 0, proof_size: 0 } error_handler_weight=Weight { ref_time: 0, proof_size: 0 }
2025-10-04T07:13:08.328434Z TRACE xcm::process_instruction: Processing instruction instruction=ReportError(QueryResponseInfo { destination: Location { parents: 1, interior: X1([Parachain(1001)]) }, query_id: 0, max_weight: Weight { ref_time: 18446744073709551615, proof_size: 18446744073709551615 } })
2025-10-04T07:13:08.328552Z TRACE xcm::send: Sending msg msg=Xcm([QueryResponse { query_id: 0, response: ExecutionResult(None), max_weight: Weight { ref_time: 18446744073709551615, proof_size: 18446744073709551615 }, querier: Some(Location { parents: 0, interior: X1([AccountId32 { network: None, id: [150, 141, 187, 98, 102, 33, 87, 174, 108, 105, 38, 201, 33, 252, 99, 215, 105, 11, 253, 230, 89, 13, 87, 138, 18, 41, 154, 220, 108, 179, 239, 229] }]) }) }, SetTopic([207, 224, 150, 20, 104, 44, 231, 40, 113, 150, 204, 227, 199, 74, 162, 200, 138, 143, 3, 176, 227, 143, 46, 145, 94, 71, 215, 205, 7, 177, 227, 162])]) destination=Location { parents: 1, interior: X1([Parachain(1001)]) } reason=Report
2025-10-04T07:13:08.328888Z TRACE xcm::pallet_xcm::note_unknown_version: XCM version is unknown for destination dest=Location { parents: 1, interior: X1([Parachain(1001)]) }
2025-10-04T07:13:08.329239Z TRACE xcm::contains: AllSiblingSystemParachains location: Location { parents: 1, interior: X2([Parachain(1001), AccountId32 { network: None, id: [150, 141, 187, 98, 102, 33, 87, 174, 108, 105, 38, 201, 33, 252, 99, 215, 105, 11, 253, 230, 89, 13, 87, 138, 18, 41, 154, 220, 108, 179, 239, 229] }]) }
2025-10-04T07:13:08.329272Z TRACE xcm::fees: Taking fees fees=Assets([Asset { id: AssetId(Location { parents: 1, interior: Here }), fun: Fungible(1030999968) }]) origin_ref=Some(Location { parents: 1, interior: X2([Parachain(1001), AccountId32 { network: None, id: [150, 141, 187, 98, 102, 33, 87, 174, 108, 105, 38, 201, 33, 252, 99, 215, 105, 11, 253, 230, 89, 13, 87, 138, 18, 41, 154, 220, 108, 179, 239, 229] }]) }) fees_mode=FeesMode { jit_withdraw: false } reason=Report
2025-10-04T07:13:08.329308Z TRACE xcm::fees: asset_to_pay_for_fees=Asset { id: AssetId(Location { parents: 1, interior: Here }), fun: Fungible(1030999968) }
2025-10-04T07:13:08.329331Z ERROR xcm::fees: Holding doesn't hold enough for fees e=AssetUnderflow(Asset { id: AssetId(Location { parents: 1, interior: Here }), fun: Fungible(1030999968) }) asset_to_pay_for_fees=Asset { id: AssetId(Location { parents: 1, interior: Here }), fun: Fungible(1030999968) }
2025-10-04T07:13:08.329352Z DEBUG xcm::process: XCM execution failed at instruction index=0 error=NotHoldingFees
2025-10-04T07:13:08.329711Z TRACE xcm::execute: Message executed result=Err(ExecutorError { index: 0, xcm_error: NotHoldingFees, weight: Weight { ref_time: 41967000000, proof_size: 367500 } })
2025-10-04T07:13:08.329740Z TRACE xcm::refund_surplus: Refunding surplus total_surplus=Weight { ref_time: 41967000000, proof_size: 367500 } total_refunded=Weight { ref_time: 0, proof_size: 0 } current_surplus=Weight { ref_time: 41967000000, proof_size: 367500 }
2025-10-04T07:13:08.329756Z TRACE xcm::weight: UsingComponents::refund_weight weight=Weight { ref_time: 41967000000, proof_size: 367500 } context=XcmContext { origin: Some(Location { parents: 1, interior: X2([Parachain(1001), AccountId32 { network: None, id: [150, 141, 187, 98, 102, 33, 87, 174, 108, 105, 38, 201, 33, 252, 99, 215, 105, 11, 253, 230, 89, 13, 87, 138, 18, 41, 154, 220, 108, 179, 239, 229] }]) }), message_id: [207, 224, 150, 20, 104, 44, 231, 40, 113, 150, 204, 227, 199, 74, 162, 200, 138, 143, 3, 176, 227, 143, 46, 145, 94, 71, 215, 205, 7, 177, 227, 162], topic: Some([207, 224, 150, 20, 104, 44, 231, 40, 113, 150, 204, 227, 199, 74, 162, 200, 138, 143, 3, 176, 227, 143, 46, 145, 94, 71, 215, 205, 7, 177, 227, 162]) } available_weight=Weight { ref_time: 43793552000, proof_size: 387172 } available_amount=12905733320
2025-10-04T07:13:08.329802Z TRACE xcm::weight: UsingComponents::refund_weight amount=12249999988
2025-10-04T07:13:08.329816Z TRACE xcm::ensure_can_subsume_assets: Ensuring subsume assets work worst_case_holding_len=1 holding_limit=64
2025-10-04T07:13:08.329843Z TRACE xcm::refund_surplus: total_refunded=Weight { ref_time: 41967000000, proof_size: 367500 }
2025-10-04T07:13:08.332568Z TRACE xcm::post_process: Trapping assets in holding register holding_register=AssetsInHolding { fungible: {AssetId(Location { parents: 1, interior: Here }): 12249999988}, non_fungible: {} } context=XcmContext { origin: Some(Location { parents: 1, interior: X2([Parachain(1001), AccountId32 { network: None, id: [150, 141, 187, 98, 102, 33, 87, 174, 108, 105, 38, 201, 33, 252, 99, 215, 105, 11, 253, 230, 89, 13, 87, 138, 18, 41, 154, 220, 108, 179, 239, 229] }]) }), message_id: [207, 224, 150, 20, 104, 44, 231, 40, 113, 150, 204, 227, 199, 74, 162, 200, 138, 143, 3, 176, 227, 143, 46, 145, 94, 71, 215, 205, 7, 177, 227, 162], topic: Some([207, 224, 150, 20, 104, 44, 231, 40, 113, 150, 204, 227, 199, 74, 162, 200, 138, 143, 3, 176, 227, 143, 46, 145, 94, 71, 215, 205, 7, 177, 227, 162]) } original_origin=Location { parents: 1, interior: X1([Parachain(1001)]) }
2025-10-04T07:13:08.333144Z TRACE xcm::post_process: Execution failed instruction=0 error=NotHoldingFees original_origin=Location { parents: 1, interior: X1([Parachain(1001)]) }
2025-10-04T07:13:08.333167Z TRACE xcm::process-message: XCM message execution incomplete error=NotHoldingFees index=0 used=Weight { ref_time: 1826552000, proof_size: 19672 }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iiuc, are we talking about this XCM: https://github.com/polkadot-fellows/runtimes/blob/main/system-parachains/encointer/src/treasuries_xcm_payout.rs#L267-L283? Maybe just for completeness, could you add the full XCM from the logs here?

Do you have a block/transaction, that we can replay and investigate more?


From the logs above, I don't see any errored instruction after SetAppendix, which is just TransferAsset, so it passed.
But the SetAppendix(ReportError(..) is trying to send self.error register, even if the error register is None.

There are couple of issues or things to think about:

  1. ReportError sends/reports error register regardless if Some/None, which means, for every successful XCM processing, it send one everytime Xcm(ReportError(None), which is kind of "questionable":
  1. yes, I think that NotHoldingFees is correct error, because we can see WithdrawAsset(remote_fee), PayFees(remote_fee) and here I am little bit confused, because PayFees takes the whole remote_fee from the self.holding, so self.holding is now empty, and the unspent from trader should be return back to self.fees, but looks like it is not at this point

cc: @franciscoaguirre @raymondkfcheung


@clangenb Hmm, I still had it in my head that somewhere during PR reviews I came across ReportError, and I think it was exactly this XCM :D #679 (comment)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other thing is if DescendOrigin (as effective origin) should pay for ReportError or destination sovereign account (which would be Encointer parachain), but this needs more thinking, not to open possible free spamming with ReportError or something, so something like:

		SetAppendix(Xcm(vec![
			// Refund everything to `effective origin)`
			RefundSurplus,
			DepositAsset { assets: AssetFilter::Wild(WildAsset::All), beneficiary: from_at_target },
                        
			// Change origin to Encointer location
			AliasOrigin(encointer_location as Location(1/0, Parachain(1001)),
			// Encointer is waived for fees, so no fees charged for `self.send(`
			ReportError(QueryResponseInfo {
				destination: destination.clone(),
				query_id,
				max_weight: Weight::zero(),
			}),
		])),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @bkontur that AliasOrigin + reordering ReportError looks like the right fix here. We just need to make sure it can't be abused for free ReportError spam.

For tracing, I'll follow up with targeted logs around the appendix path. I need a bit more time to place these in the right spots so they're useful without being noisy.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, I am also not sure if AliasOrigin would work here, because of Aliasers:

target does not start with origin (AliasChildLocation):

origin: Location { parents: 1, interior: X2([Parachain(1001), AccountId32{..}
target: Location { parents: 1, interior: X1([Parachain(1001))

For:

pub struct AliasChildLocation;
impl ContainsPair<Location, Location> for AliasChildLocation {
	fn contains(origin: &Location, target: &Location) -> bool {
		return target.starts_with(origin)
	}
}

@clangenb clangenb Oct 6, 2025

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, thanks for looking into this.

iiuc, are we talking about this XCM: https://github.com/polkadot-fellows/runtimes/blob/main/system-parachains/encointer/src/treasuries_xcm_payout.rs#L267-L283? Maybe just for completeness, could you add the full XCM from the logs here?

You are right @bkontur, this is the xcm we are talking about.

In this setup at least, I believe that it could not be abused for free error spams because whatever is triggering the alias back into the Encointer location would need to pay XCM execution fees on AH. So they just get the spam for free, but not without paying for the enclosing XCM first, which I guess is a reasonable spam prevention mechanism.

Regardless, in order to have encointer fixed soon, I suggest that I open another issue because I think that fixing this properly might even need some design thought in XCM first. We would really like to have a working patch released.

I do not have a block to replay, but I could give you a chopsticks setup that could trigger the XCM from encointer to AH with one single extrinsic. Would this work @bkontur?

@clangenb Hmm, I still had it in my head that somewhere during PR reviews I came across ReportError, and I think it was exactly this XCM :D #679 (comment)

Haha, you are on point ;)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding your second point @bkontur, I have opened an issue for further investigation, as this might be a general XCM bug: paritytech/polkadot-sdk#10078.

RefundSurplus,
DepositAsset { assets: AssetFilter::Wild(WildAsset::All), beneficiary: from_at_target },
])),
Expand Down
Loading