diff --git a/bridges/snowbridge/runtime/test-common/src/lib.rs b/bridges/snowbridge/runtime/test-common/src/lib.rs index 5441dd822caca..fa14131cf3a73 100644 --- a/bridges/snowbridge/runtime/test-common/src/lib.rs +++ b/bridges/snowbridge/runtime/test-common/src/lib.rs @@ -371,7 +371,7 @@ pub fn send_unpaid_transfer_token_message( Weight::zero(), ); // check error is barrier - assert_err!(outcome.ensure_complete(), XcmError::Barrier); + assert_err!(outcome.ensure_complete(), (0, XcmError::Barrier)); }); } @@ -423,7 +423,7 @@ pub fn send_transfer_token_message_failure( destination_address, fee_amount, ); - assert_err!(outcome.ensure_complete(), expected_error); + assert_err!(outcome.ensure_complete(), (0, expected_error)); }); } diff --git a/cumulus/parachains/integration-tests/emulated/common/src/impls.rs b/cumulus/parachains/integration-tests/emulated/common/src/impls.rs index 9dad323aa19c7..61ec9410dab09 100644 --- a/cumulus/parachains/integration-tests/emulated/common/src/impls.rs +++ b/cumulus/parachains/integration-tests/emulated/common/src/impls.rs @@ -233,7 +233,7 @@ macro_rules! impl_assert_events_helpers_for_relay_chain { vec![ // Dispatchable is properly executed and XCM message sent [<$chain RuntimeEvent>]::::XcmPallet( - $crate::impls::pallet_xcm::Event::Attempted { outcome: $crate::impls::Outcome::Incomplete { used: weight, error } } + $crate::impls::pallet_xcm::Event::Attempted { outcome: $crate::impls::Outcome::Incomplete { used: weight, error, .. } } ) => { weight: $crate::impls::weight_within_threshold( ($crate::impls::REF_TIME_THRESHOLD, $crate::impls::PROOF_SIZE_THRESHOLD), @@ -471,7 +471,7 @@ macro_rules! impl_assert_events_helpers_for_parachain { vec![ // Dispatchable is properly executed and XCM message sent [<$chain RuntimeEvent>]::::PolkadotXcm( - $crate::impls::pallet_xcm::Event::Attempted { outcome: $crate::impls::Outcome::Incomplete { used: weight, error } } + $crate::impls::pallet_xcm::Event::Attempted { outcome: $crate::impls::Outcome::Incomplete { used: weight, error, .. } } ) => { weight: $crate::impls::weight_within_threshold( ($crate::impls::REF_TIME_THRESHOLD, $crate::impls::PROOF_SIZE_THRESHOLD), @@ -491,7 +491,7 @@ macro_rules! impl_assert_events_helpers_for_parachain { vec![ // Execution fails in the origin with `Barrier` [<$chain RuntimeEvent>]::::PolkadotXcm( - $crate::impls::pallet_xcm::Event::Attempted { outcome: $crate::impls::Outcome::Error { error } } + $crate::impls::pallet_xcm::Event::Attempted { outcome: $crate::impls::Outcome::Error { error, .. } } ) => { error: *error == expected_error.unwrap_or((*error).into()).into(), }, diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge_v2_outbound.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge_v2_outbound.rs index 28705c59a281f..064663effb155 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge_v2_outbound.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge_v2_outbound.rs @@ -883,7 +883,10 @@ fn export_message_from_asset_hub_to_ethereum_is_banned_when_set_operating_mode() bx!(xcm), Weight::from(EXECUTION_WEIGHT), ), - pallet_xcm::Error::::LocalExecutionIncompleteWithError + pallet_xcm::Error::::LocalExecutionIncompleteWithError { + error: XcmError::NoDeal.into(), + index: 0 + } ); }); } diff --git a/cumulus/parachains/runtimes/test-utils/src/lib.rs b/cumulus/parachains/runtimes/test-utils/src/lib.rs index 073d1f669a4f2..258a5598dc5b9 100644 --- a/cumulus/parachains/runtimes/test-utils/src/lib.rs +++ b/cumulus/parachains/runtimes/test-utils/src/lib.rs @@ -475,7 +475,7 @@ impl< pub fn execute_as_governance_call( call: Call, governance_origin: GovernanceOrigin, - ) -> Result<(), Either> { + ) -> Result<(), Either> { // execute xcm as governance would send let execute_xcm = |call: Call, governance_location, descend_origin| { // prepare xcm diff --git a/cumulus/parachains/runtimes/test-utils/src/test_cases.rs b/cumulus/parachains/runtimes/test-utils/src/test_cases.rs index afad2a80d4e48..48e4f7956917e 100644 --- a/cumulus/parachains/runtimes/test-utils/src/test_cases.rs +++ b/cumulus/parachains/runtimes/test-utils/src/test_cases.rs @@ -226,7 +226,7 @@ where /// `frame_system::Call::authorize_upgrade` from governance system. pub fn can_governance_authorize_upgrade( governance_origin: GovernanceOrigin, -) -> Result<(), Either> +) -> Result<(), Either> where Runtime: BasicParachainRuntime + frame_system::Config, diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index e7c9d8936ff98..f08f27462f54e 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -365,13 +365,12 @@ pub mod pallet { Self::deposit_event(Event::Attempted { outcome: outcome.clone() }); let weight_used = outcome.weight_used(); - outcome.ensure_complete().map_err(|error| { + outcome.ensure_complete().map_err(|(index, error)| { tracing::error!(target: "xcm::pallet_xcm::execute", ?error, "XCM execution failed with error"); - Error::::LocalExecutionIncompleteWithError(error.into()).with_weight( - weight_used.saturating_add( + Error::::LocalExecutionIncompleteWithError { error: error.into(), index } + .with_weight(weight_used.saturating_add( ::execute(), - ), - ) + )) })?; Ok(weight_used) } @@ -686,10 +685,7 @@ pub mod pallet { AliasNotFound, /// Local XCM execution incomplete with error. #[codec(index = 28)] - LocalExecutionIncompleteWithError { - error: ExecutionError, - index: u8, - }, + LocalExecutionIncompleteWithError { error: ExecutionError, index: u8 }, } impl From for Error { @@ -1455,9 +1451,9 @@ pub mod pallet { weight, weight, ); - outcome.ensure_complete().map_err(|error| { + outcome.ensure_complete().map_err(|(index, error)| { tracing::error!(target: "xcm::pallet_xcm::claim_assets", ?error, "XCM execution failed with error"); - Error::::LocalExecutionIncompleteWithError(error.into()) + Error::::LocalExecutionIncompleteWithError {index, error: error.into()} })?; Ok(()) } @@ -2087,12 +2083,12 @@ impl Pallet { weight, ); Self::deposit_event(Event::Attempted { outcome: outcome.clone() }); - outcome.clone().ensure_complete().map_err(|error| { + outcome.clone().ensure_complete().map_err(|(index, error)| { tracing::error!( target: "xcm::pallet_xcm::execute_xcm_transfer", ?error, "XCM execution failed with error with outcome: {:?}", outcome ); - Error::::LocalExecutionIncompleteWithError(error.into()) + Error::::LocalExecutionIncompleteWithError { error: error.into(), index } })?; if let Some(remote_xcm) = remote_xcm { diff --git a/polkadot/xcm/pallet-xcm/src/tests/mod.rs b/polkadot/xcm/pallet-xcm/src/tests/mod.rs index b439be100d49e..010708ee6123a 100644 --- a/polkadot/xcm/pallet-xcm/src/tests/mod.rs +++ b/polkadot/xcm/pallet-xcm/src/tests/mod.rs @@ -656,7 +656,10 @@ fn trapped_assets_can_be_claimed() { ]))), weight ), - Error::::LocalExecutionIncompleteWithError(XcmError::UnknownClaim.into()) + Error::::LocalExecutionIncompleteWithError { + index: 0, + error: XcmError::UnknownClaim.into() + } ); }); } @@ -753,9 +756,10 @@ fn incomplete_execute_reverts_side_effects() { pays_fee: frame_support::dispatch::Pays::Yes, }, error: sp_runtime::DispatchError::from( - Error::::LocalExecutionIncompleteWithError( - XcmError::FailedToTransactAsset("").into() - ) + Error::::LocalExecutionIncompleteWithError { + index: 3, + error: XcmError::FailedToTransactAsset("").into() + } ) }) ); diff --git a/polkadot/xcm/src/v5/traits.rs b/polkadot/xcm/src/v5/traits.rs index 0294663a85515..5322967e7169e 100644 --- a/polkadot/xcm/src/v5/traits.rs +++ b/polkadot/xcm/src/v5/traits.rs @@ -252,11 +252,11 @@ pub enum Outcome { } impl Outcome { - pub fn ensure_complete(self) -> Result<(), (u8, Error)> { + pub fn ensure_complete(self) -> result::Result<(), (u8, Error)> { match self { Outcome::Complete { .. } => Ok(()), - Outcome::Incomplete { error, index, .. } => Err(error), - Outcome::Error { error, index, .. } => Err(error), + Outcome::Incomplete { error, index, .. } => Err((index, error)), + Outcome::Error { error, index, .. } => Err((index, error)), } } pub fn ensure_execution(self) -> result::Result { @@ -278,7 +278,7 @@ impl Outcome { impl From for Outcome { fn from(error: Error) -> Self { - Self::Error { error } + Self::Error { error, index: 0 } } } @@ -305,11 +305,11 @@ pub trait ExecuteXcm { ) -> Outcome { let pre = match Self::prepare(message) { Ok(x) => x, - Err(_) => return Outcome::Error { error: Error::WeightNotComputable }, + Err(_) => return Outcome::Error { error: Error::WeightNotComputable, index: 0 }, }; let xcm_weight = pre.weight_of(); if xcm_weight.any_gt(weight_limit) { - return Outcome::Error { error: Error::WeightLimitReached(xcm_weight) } + return Outcome::Error { error: Error::WeightLimitReached(xcm_weight), index: 0 } } Self::execute(origin, pre, id, weight_credit) } diff --git a/polkadot/xcm/xcm-builder/src/process_xcm_message.rs b/polkadot/xcm/xcm-builder/src/process_xcm_message.rs index d195217a52241..30589a7a5e5d0 100644 --- a/polkadot/xcm/xcm-builder/src/process_xcm_message.rs +++ b/polkadot/xcm/xcm-builder/src/process_xcm_message.rs @@ -97,18 +97,23 @@ impl< ); (used, Ok(true)) }, - Outcome::Incomplete { used, error } => { + Outcome::Incomplete { used, error, index } => { tracing::trace!( target: LOG_TARGET, - "XCM message execution incomplete, used weight: {used}, error: {error:?}", + ?error, + ?index, + ?used, + "XCM message execution incomplete, used weight", ); (used, Ok(false)) }, // In the error-case we assume the worst case and consume all possible weight. - Outcome::Error { error } => { + Outcome::Error { error, index } => { tracing::trace!( target: LOG_TARGET, - "XCM message execution error: {error:?}", + ?error, + ?index, + "XCM message execution error", ); let error = match error { xcm::latest::Error::ExceedsStackLimit => ProcessMessageError::StackLimitReached, diff --git a/polkadot/xcm/xcm-builder/src/tests/aliases.rs b/polkadot/xcm/xcm-builder/src/tests/aliases.rs index dc8b016a6aa40..b9dfb5a20d778 100644 --- a/polkadot/xcm/xcm-builder/src/tests/aliases.rs +++ b/polkadot/xcm/xcm-builder/src/tests/aliases.rs @@ -76,7 +76,11 @@ fn alias_origin_should_work() { ); assert_eq!( r, - Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::NoPermission } + Outcome::Incomplete { + used: Weight::from_parts(10, 10), + error: XcmError::NoPermission, + index: 0 + } ); let r = XcmExecutor::::prepare_and_execute( diff --git a/polkadot/xcm/xcm-builder/src/tests/assets.rs b/polkadot/xcm/xcm-builder/src/tests/assets.rs index b510eab8df53e..0b8e79ce054ed 100644 --- a/polkadot/xcm/xcm-builder/src/tests/assets.rs +++ b/polkadot/xcm/xcm-builder/src/tests/assets.rs @@ -100,7 +100,7 @@ fn exchange_asset_should_fail_when_no_deal_possible() { ); assert_eq!( r, - Outcome::Incomplete { used: Weight::from_parts(40, 40), error: XcmError::NoDeal } + Outcome::Incomplete { used: Weight::from_parts(40, 40), error: XcmError::NoDeal, index: 0 } ); assert_eq!(asset_list(Parent), vec![(Parent, 1000u128).into()]); assert_eq!(exchange_assets(), vec![(Here, 100u128).into()].into()); @@ -286,7 +286,11 @@ fn basic_asset_trap_should_work() { ); assert_eq!( r, - Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::UnknownClaim } + Outcome::Incomplete { + used: Weight::from_parts(10, 10), + error: XcmError::UnknownClaim, + index: 0 + } ); assert_eq!(asset_list(Parachain(1)), vec![(Here, 900u128).into()]); assert_eq!(asset_list(AccountIndex64 { index: 3, network: None }), vec![]); @@ -311,7 +315,11 @@ fn basic_asset_trap_should_work() { ); assert_eq!( r, - Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::UnknownClaim } + Outcome::Incomplete { + used: Weight::from_parts(10, 10), + error: XcmError::UnknownClaim, + index: 0 + } ); assert_eq!(asset_list(Parachain(1)), vec![(Here, 900u128).into()]); assert_eq!(asset_list(AccountIndex64 { index: 3, network: None }), vec![]); @@ -336,7 +344,11 @@ fn basic_asset_trap_should_work() { ); assert_eq!( r, - Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::UnknownClaim } + Outcome::Incomplete { + used: Weight::from_parts(10, 10), + error: XcmError::UnknownClaim, + index: 0 + } ); assert_eq!(asset_list(Parachain(1)), vec![(Here, 900u128).into()]); assert_eq!(asset_list(AccountIndex64 { index: 3, network: None }), vec![]); @@ -382,7 +394,11 @@ fn basic_asset_trap_should_work() { ); assert_eq!( r, - Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::UnknownClaim } + Outcome::Incomplete { + used: Weight::from_parts(10, 10), + error: XcmError::UnknownClaim, + index: 0 + } ); } @@ -446,7 +462,8 @@ fn max_assets_limit_should_work() { r, Outcome::Incomplete { used: Weight::from_parts(95, 95), - error: XcmError::HoldingWouldOverflow + error: XcmError::HoldingWouldOverflow, + index: 0 } ); @@ -503,7 +520,8 @@ fn max_assets_limit_should_work() { r, Outcome::Incomplete { used: Weight::from_parts(95, 95), - error: XcmError::HoldingWouldOverflow + error: XcmError::HoldingWouldOverflow, + index: 0 } ); @@ -533,7 +551,8 @@ fn max_assets_limit_should_work() { r, Outcome::Incomplete { used: Weight::from_parts(25, 25), - error: XcmError::HoldingWouldOverflow + error: XcmError::HoldingWouldOverflow, + index: 0 } ); } diff --git a/polkadot/xcm/xcm-builder/src/tests/bridging/universal_exports.rs b/polkadot/xcm/xcm-builder/src/tests/bridging/universal_exports.rs index 160c6c9af50fd..8205e3cb29922 100644 --- a/polkadot/xcm/xcm-builder/src/tests/bridging/universal_exports.rs +++ b/polkadot/xcm/xcm-builder/src/tests/bridging/universal_exports.rs @@ -83,7 +83,11 @@ fn sovereign_paid_remote_exporter_produces_xcm_which_does_not_trap_assets() { ); assert_eq!( r, - Outcome::Incomplete { used: Weight::from_parts(50, 50), error: XcmError::Unroutable } + Outcome::Incomplete { + used: Weight::from_parts(50, 50), + error: XcmError::Unroutable, + index: 0 + } ); // check empty trapped assets assert!(TrappedAssets::get().is_empty()); diff --git a/polkadot/xcm/xcm-builder/src/tests/expecting.rs b/polkadot/xcm/xcm-builder/src/tests/expecting.rs index 1b36ef4517c97..c6a04c61afe75 100644 --- a/polkadot/xcm/xcm-builder/src/tests/expecting.rs +++ b/polkadot/xcm/xcm-builder/src/tests/expecting.rs @@ -78,7 +78,8 @@ fn expect_pallet_should_fail_correctly() { r, Outcome::Incomplete { used: Weight::from_parts(10, 10), - error: XcmError::VersionIncompatible + error: XcmError::VersionIncompatible, + index: 0 } ); @@ -99,7 +100,11 @@ fn expect_pallet_should_fail_correctly() { ); assert_eq!( r, - Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::NameMismatch } + Outcome::Incomplete { + used: Weight::from_parts(10, 10), + error: XcmError::NameMismatch, + index: 0 + } ); let message = Xcm(vec![ExpectPallet { @@ -119,7 +124,11 @@ fn expect_pallet_should_fail_correctly() { ); assert_eq!( r, - Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::NameMismatch } + Outcome::Incomplete { + used: Weight::from_parts(10, 10), + error: XcmError::NameMismatch, + index: 0 + } ); let message = Xcm(vec![ExpectPallet { @@ -139,7 +148,11 @@ fn expect_pallet_should_fail_correctly() { ); assert_eq!( r, - Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::NameMismatch } + Outcome::Incomplete { + used: Weight::from_parts(10, 10), + error: XcmError::NameMismatch, + index: 0 + } ); let message = Xcm(vec![ExpectPallet { @@ -159,7 +172,11 @@ fn expect_pallet_should_fail_correctly() { ); assert_eq!( r, - Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::PalletNotFound } + Outcome::Incomplete { + used: Weight::from_parts(10, 10), + error: XcmError::PalletNotFound, + index: 0 + } ); let message = Xcm(vec![ExpectPallet { @@ -181,7 +198,8 @@ fn expect_pallet_should_fail_correctly() { r, Outcome::Incomplete { used: Weight::from_parts(10, 10), - error: XcmError::VersionIncompatible + error: XcmError::VersionIncompatible, + index: 0 } ); @@ -204,7 +222,8 @@ fn expect_pallet_should_fail_correctly() { r, Outcome::Incomplete { used: Weight::from_parts(10, 10), - error: XcmError::VersionIncompatible + error: XcmError::VersionIncompatible, + index: 0 } ); @@ -227,7 +246,8 @@ fn expect_pallet_should_fail_correctly() { r, Outcome::Incomplete { used: Weight::from_parts(10, 10), - error: XcmError::VersionIncompatible + error: XcmError::VersionIncompatible, + index: 0 } ); } diff --git a/polkadot/xcm/xcm-builder/src/tests/locking.rs b/polkadot/xcm/xcm-builder/src/tests/locking.rs index 75160e311551e..bab1a1609d688 100644 --- a/polkadot/xcm/xcm-builder/src/tests/locking.rs +++ b/polkadot/xcm/xcm-builder/src/tests/locking.rs @@ -121,7 +121,11 @@ fn lock_should_fail_correctly() { ); assert_eq!( r, - Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::LockError } + Outcome::Incomplete { + used: Weight::from_parts(10, 10), + error: XcmError::LockError, + index: 0 + } ); assert_eq!(sent_xcm(), vec![]); assert_eq!(take_lock_trace(), vec![]); @@ -147,7 +151,11 @@ fn lock_should_fail_correctly() { ); assert_eq!( r, - Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::NotHoldingFees } + Outcome::Incomplete { + used: Weight::from_parts(10, 10), + error: XcmError::NotHoldingFees, + index: 0 + } ); assert_eq!(sent_xcm(), vec![]); assert_eq!(take_lock_trace(), vec![]); @@ -244,7 +252,11 @@ fn remote_unlock_should_fail_correctly() { ); assert_eq!( r, - Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::LockError } + Outcome::Incomplete { + used: Weight::from_parts(10, 10), + error: XcmError::LockError, + index: 0 + } ); assert_eq!(sent_xcm(), vec![]); assert_eq!(take_lock_trace(), vec![]); @@ -280,7 +292,11 @@ fn remote_unlock_should_fail_correctly() { ); assert_eq!( r, - Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::NotHoldingFees } + Outcome::Incomplete { + used: Weight::from_parts(10, 10), + error: XcmError::NotHoldingFees, + index: 0 + } ); assert_eq!(sent_xcm(), vec![]); diff --git a/polkadot/xcm/xcm-builder/src/tests/origins.rs b/polkadot/xcm/xcm-builder/src/tests/origins.rs index 3cdc0a8eb36c2..264ae6a74a634 100644 --- a/polkadot/xcm/xcm-builder/src/tests/origins.rs +++ b/polkadot/xcm/xcm-builder/src/tests/origins.rs @@ -39,7 +39,11 @@ fn universal_origin_should_work() { ); assert_eq!( r, - Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::InvalidLocation } + Outcome::Incomplete { + used: Weight::from_parts(10, 10), + error: XcmError::InvalidLocation, + index: 0 + } ); let message = Xcm(vec![ @@ -56,7 +60,11 @@ fn universal_origin_should_work() { ); assert_eq!( r, - Outcome::Incomplete { used: Weight::from_parts(20, 20), error: XcmError::NotWithdrawable } + Outcome::Incomplete { + used: Weight::from_parts(20, 20), + error: XcmError::NotWithdrawable, + index: 0 + } ); add_asset((Ancestor(2), GlobalConsensus(Kusama)), (Parent, 100)); @@ -130,7 +138,11 @@ fn unpaid_execution_should_work() { ); assert_eq!( r, - Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::BadOrigin } + Outcome::Incomplete { + used: Weight::from_parts(10, 10), + error: XcmError::BadOrigin, + index: 0 + } ); let r = XcmExecutor::::prepare_and_execute( Parachain(2), @@ -141,7 +153,11 @@ fn unpaid_execution_should_work() { ); assert_eq!( r, - Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::Barrier } + Outcome::Incomplete { + used: Weight::from_parts(10, 10), + error: XcmError::Barrier, + index: 0 + } ); let message = Xcm(vec![UnpaidExecution { diff --git a/polkadot/xcm/xcm-builder/src/tests/querying.rs b/polkadot/xcm/xcm-builder/src/tests/querying.rs index 062b508368f77..7c8612fa4271a 100644 --- a/polkadot/xcm/xcm-builder/src/tests/querying.rs +++ b/polkadot/xcm/xcm-builder/src/tests/querying.rs @@ -132,6 +132,10 @@ fn prepaid_result_of_query_should_get_free_execution() { ); assert_eq!( r, - Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::Barrier } + Outcome::Incomplete { + used: Weight::from_parts(10, 10), + error: XcmError::Barrier, + index: 0 + } ); } diff --git a/polkadot/xcm/xcm-builder/src/tests/transacting.rs b/polkadot/xcm/xcm-builder/src/tests/transacting.rs index ba932beaeb3d9..9d7b7209d6491 100644 --- a/polkadot/xcm/xcm-builder/src/tests/transacting.rs +++ b/polkadot/xcm/xcm-builder/src/tests/transacting.rs @@ -234,7 +234,11 @@ fn expect_successful_transact_status_should_work() { ); assert_eq!( r, - Outcome::Incomplete { used: Weight::from_parts(70, 70), error: XcmError::ExpectationFalse } + Outcome::Incomplete { + used: Weight::from_parts(70, 70), + error: XcmError::ExpectationFalse, + index: 0 + } ); } @@ -280,7 +284,11 @@ fn expect_failed_transact_status_should_work() { ); assert_eq!( r, - Outcome::Incomplete { used: Weight::from_parts(70, 70), error: XcmError::ExpectationFalse } + Outcome::Incomplete { + used: Weight::from_parts(70, 70), + error: XcmError::ExpectationFalse, + index: 0 + } ); } diff --git a/polkadot/xcm/xcm-builder/src/tests/version_subscriptions.rs b/polkadot/xcm/xcm-builder/src/tests/version_subscriptions.rs index df36b3c573106..70c547df401a7 100644 --- a/polkadot/xcm/xcm-builder/src/tests/version_subscriptions.rs +++ b/polkadot/xcm/xcm-builder/src/tests/version_subscriptions.rs @@ -37,7 +37,11 @@ fn simple_version_subscriptions_should_work() { weight_limit, Weight::zero(), ), - Outcome::Incomplete { used: Weight::from_parts(20, 20), error: XcmError::Barrier } + Outcome::Incomplete { + used: Weight::from_parts(20, 20), + error: XcmError::Barrier, + index: 0 + } ); // this case fails because the additional `SetAppendix` instruction is not allowed in the @@ -50,7 +54,11 @@ fn simple_version_subscriptions_should_work() { weight_limit, Weight::zero(), ), - Outcome::Incomplete { used: Weight::from_parts(20, 20), error: XcmError::Barrier } + Outcome::Incomplete { + used: Weight::from_parts(20, 20), + error: XcmError::Barrier, + index: 0 + } ); let message = Xcm::(vec![SubscribeVersion { @@ -68,7 +76,11 @@ fn simple_version_subscriptions_should_work() { ); assert_eq!( r, - Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::Barrier } + Outcome::Incomplete { + used: Weight::from_parts(10, 10), + error: XcmError::Barrier, + index: 0 + } ); let r = XcmExecutor::::prepare_and_execute( @@ -104,7 +116,11 @@ fn version_subscription_instruction_should_work() { ); assert_eq!( r, - Outcome::Incomplete { used: Weight::from_parts(20, 20), error: XcmError::BadOrigin } + Outcome::Incomplete { + used: Weight::from_parts(20, 20), + error: XcmError::BadOrigin, + index: 0 + } ); let message = Xcm::(vec![ @@ -144,7 +160,11 @@ fn simple_version_unsubscriptions_should_work() { ); assert_eq!( r, - Outcome::Incomplete { used: Weight::from_parts(20, 20), error: XcmError::Barrier } + Outcome::Incomplete { + used: Weight::from_parts(20, 20), + error: XcmError::Barrier, + index: 0 + } ); let origin = Parachain(1000); @@ -160,7 +180,11 @@ fn simple_version_unsubscriptions_should_work() { ); assert_eq!( r, - Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::Barrier } + Outcome::Incomplete { + used: Weight::from_parts(10, 10), + error: XcmError::Barrier, + index: 0 + } ); let r = XcmExecutor::::prepare_and_execute( @@ -196,7 +220,11 @@ fn version_unsubscription_instruction_should_work() { ); assert_eq!( r, - Outcome::Incomplete { used: Weight::from_parts(20, 20), error: XcmError::BadOrigin } + Outcome::Incomplete { + used: Weight::from_parts(20, 20), + error: XcmError::BadOrigin, + index: 0 + } ); // Fine to do it when origin is untouched. diff --git a/polkadot/xcm/xcm-builder/src/tests/weight.rs b/polkadot/xcm/xcm-builder/src/tests/weight.rs index 637e30cce998b..435beb87cc361 100644 --- a/polkadot/xcm/xcm-builder/src/tests/weight.rs +++ b/polkadot/xcm/xcm-builder/src/tests/weight.rs @@ -114,7 +114,11 @@ fn errors_should_return_unused_weight() { ); assert_eq!( r, - Outcome::Incomplete { used: Weight::from_parts(30, 30), error: XcmError::NotWithdrawable } + Outcome::Incomplete { + used: Weight::from_parts(30, 30), + error: XcmError::NotWithdrawable, + index: 0 + } ); assert_eq!(asset_list(AccountIndex64 { index: 3, network: None }), vec![(Here, 10u128).into()]); assert_eq!(asset_list(Here), vec![(Here, 1u128).into()]); @@ -129,7 +133,11 @@ fn errors_should_return_unused_weight() { ); assert_eq!( r, - Outcome::Incomplete { used: Weight::from_parts(20, 20), error: XcmError::NotWithdrawable } + Outcome::Incomplete { + used: Weight::from_parts(20, 20), + error: XcmError::NotWithdrawable, + index: 0 + } ); assert_eq!(asset_list(AccountIndex64 { index: 3, network: None }), vec![(Here, 11u128).into()]); assert_eq!(asset_list(Here), vec![]); @@ -144,7 +152,11 @@ fn errors_should_return_unused_weight() { ); assert_eq!( r, - Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::NotWithdrawable } + Outcome::Incomplete { + used: Weight::from_parts(10, 10), + error: XcmError::NotWithdrawable, + index: 0 + } ); assert_eq!(asset_list(AccountIndex64 { index: 3, network: None }), vec![(Here, 11u128).into()]); assert_eq!(asset_list(Here), vec![]); diff --git a/polkadot/xcm/xcm-builder/tests/scenarios.rs b/polkadot/xcm/xcm-builder/tests/scenarios.rs index e3a1924a19d7a..bd999bee027ff 100644 --- a/polkadot/xcm/xcm-builder/tests/scenarios.rs +++ b/polkadot/xcm/xcm-builder/tests/scenarios.rs @@ -147,7 +147,8 @@ fn report_holding_works() { r, Outcome::Incomplete { used: weight - BaseXcmWeight::get(), - error: XcmError::FailedToTransactAsset("AccountIdConversionFailed") + error: XcmError::FailedToTransactAsset("AccountIdConversionFailed"), + index: 0 } ); // there should be no query response sent for the failed deposit @@ -235,7 +236,10 @@ fn teleport_to_asset_hub_works() { weight, Weight::zero(), ); - assert_eq!(r, Outcome::Incomplete { used: weight, error: UntrustedTeleportLocation }); + assert_eq!( + r, + Outcome::Incomplete { used: weight, error: UntrustedTeleportLocation, index: 0 } + ); // teleports are allowed from asset hub to kusama. let message = Xcm(vec![ @@ -422,7 +426,8 @@ fn recursive_xcm_execution_fail() { outcome, Outcome::Incomplete { used: Weight::from_parts(3000000000, 3072), - error: XcmError::Barrier + error: XcmError::Barrier, + index: 0 } ); }); diff --git a/polkadot/xcm/xcm-executor/src/lib.rs b/polkadot/xcm/xcm-executor/src/lib.rs index 3677c9535258a..e9cb7ec433fe4 100644 --- a/polkadot/xcm/xcm-executor/src/lib.rs +++ b/polkadot/xcm/xcm-executor/src/lib.rs @@ -233,10 +233,7 @@ impl ExecuteXcm for XcmExecutor Result> { match Config::Weigher::weight(&mut message) { Ok(weight) => Ok(WeighedMessage(weight, message)), - Err(_) => { - tracing::debug!(target: "xcm::prepare", "Failed to prepare message due to uncomputable weight"); - Err(message) - }, + Err(_) => Err(message), } } fn execute( @@ -419,7 +416,11 @@ impl XcmExecutor { original_origin = ?self.original_origin, "Execution failed", ); - Outcome::Incomplete { used: weight_used, error, index } + Outcome::Incomplete { + used: weight_used, + error, + index: index.try_into().unwrap_or(0), + } }, } } diff --git a/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs b/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs index 5e5567c18716a..f3b51ccd8f48c 100644 --- a/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs +++ b/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs @@ -237,11 +237,12 @@ pub mod mock_msg_queue { max_weight, Weight::zero(), ) { - Outcome::Error { error } => (Err(error), Event::Fail(Some(hash), error)), + Outcome::Error { error, .. } => + (Err(error), Event::Fail(Some(hash), error)), Outcome::Complete { used } => (Ok(used), Event::Success(Some(hash))), // As far as the caller is concerned, this was dispatched without error, so // we just report the weight used. - Outcome::Incomplete { used, error } => + Outcome::Incomplete { used, error, .. } => (Ok(used), Event::Fail(Some(hash), error)), } }, diff --git a/polkadot/xcm/xcm-simulator/src/mock_message_queue.rs b/polkadot/xcm/xcm-simulator/src/mock_message_queue.rs index 9d1c20314f197..e23cdd343368f 100644 --- a/polkadot/xcm/xcm-simulator/src/mock_message_queue.rs +++ b/polkadot/xcm/xcm-simulator/src/mock_message_queue.rs @@ -107,13 +107,13 @@ pub mod pallet { max_weight, Weight::zero(), ) { - Outcome::Error { error } => + Outcome::Error { error, .. } => (Err(error), Event::Fail { message_id: Some(hash), error }), Outcome::Complete { used } => (Ok(used), Event::Success { message_id: Some(hash) }), // As far as the caller is concerned, this was dispatched without error, so // we just report the weight used. - Outcome::Incomplete { used, error } => + Outcome::Incomplete { used, error, .. } => (Ok(used), Event::Fail { message_id: Some(hash), error }), } }, diff --git a/prdoc/pr_7730.prdoc b/prdoc/pr_7730.prdoc index 89d464dfc7560..5e2f023981a2c 100644 --- a/prdoc/pr_7730.prdoc +++ b/prdoc/pr_7730.prdoc @@ -4,9 +4,25 @@ doc: description: |- To address the issue of vague `LocalExecutionIncomplete` errors in `pallet-xcm`, the PR introduces `LocalExecutionIncompleteWithError(ExecutionError)`, which nests a compact `ExecutionError` enum—aligned with `XcmError` and excluding strings like in `FailedToTransactAsset`: to provide detailed error information within FRAME's 4-byte limit. This enhances error reporting by specifying causes like insufficient balance or asset transaction failures, with strings logged for debugging. crates: +- name: emulated-integration-tests-common + bump: patch - name: pallet-xcm bump: patch -- name: xcm-executor +- name: pallet-contracts-mock-network + bump: patch +- name: pallet-revive-mock-network + bump: patch +- name: parachains-runtimes-test-utils + bump: patch +- name: staging-xcm + bump: patch +- name: staging-xcm-builder + bump: patch +- name: staging-xcm-executor + bump: patch +- name: xcm-simulator + bump: patch +- name: xcm-simulator-fuzzer bump: patch - name: asset-hub-westend-integration-tests bump: none diff --git a/substrate/frame/contracts/mock-network/src/mocks/msg_queue.rs b/substrate/frame/contracts/mock-network/src/mocks/msg_queue.rs index 25e39ee89051c..7d82c28fcaf61 100644 --- a/substrate/frame/contracts/mock-network/src/mocks/msg_queue.rs +++ b/substrate/frame/contracts/mock-network/src/mocks/msg_queue.rs @@ -113,11 +113,12 @@ pub mod pallet { max_weight, Weight::zero(), ) { - Outcome::Error { error } => (Err(error), Event::Fail(Some(hash), error)), + Outcome::Error { error, .. } => + (Err(error), Event::Fail(Some(hash), error)), Outcome::Complete { used } => (Ok(used), Event::Success(Some(hash))), // As far as the caller is concerned, this was dispatched without error, so // we just report the weight used. - Outcome::Incomplete { used, error } => + Outcome::Incomplete { used, error, .. } => (Ok(used), Event::Fail(Some(hash), error)), } }, diff --git a/substrate/frame/revive/mock-network/src/mocks/msg_queue.rs b/substrate/frame/revive/mock-network/src/mocks/msg_queue.rs index 25e39ee89051c..7d82c28fcaf61 100644 --- a/substrate/frame/revive/mock-network/src/mocks/msg_queue.rs +++ b/substrate/frame/revive/mock-network/src/mocks/msg_queue.rs @@ -113,11 +113,12 @@ pub mod pallet { max_weight, Weight::zero(), ) { - Outcome::Error { error } => (Err(error), Event::Fail(Some(hash), error)), + Outcome::Error { error, .. } => + (Err(error), Event::Fail(Some(hash), error)), Outcome::Complete { used } => (Ok(used), Event::Success(Some(hash))), // As far as the caller is concerned, this was dispatched without error, so // we just report the weight used. - Outcome::Incomplete { used, error } => + Outcome::Incomplete { used, error, .. } => (Ok(used), Event::Fail(Some(hash), error)), } },