diff --git a/cumulus/pallets/xcmp-queue/src/lib.rs b/cumulus/pallets/xcmp-queue/src/lib.rs index b703ae7fc944c..d62d81cf9d953 100644 --- a/cumulus/pallets/xcmp-queue/src/lib.rs +++ b/cumulus/pallets/xcmp-queue/src/lib.rs @@ -557,8 +557,11 @@ impl Pallet { new_page.extend_from_slice(&encoded_fragment[..]); let last_page_size = new_page.len(); let number_of_pages = (channel_details.last_index - channel_details.first_index) as u32; - let bounded_page = BoundedVec::::try_from(new_page) - .map_err(|_| MessageSendError::TooBig)?; + let bounded_page = + BoundedVec::::try_from(new_page).map_err(|error| { + log::debug!(target: LOG_TARGET, "Failed to create bounded message page: {error:?}"); + MessageSendError::TooBig + })?; let bounded_page = WeakBoundedVec::force_from(bounded_page.into_inner(), None); >::insert(recipient, page_index, bounded_page); >::put(all_channels); @@ -585,14 +588,19 @@ impl Pallet { if let Some(details) = s.iter_mut().find(|item| item.recipient == dest) { details.signals_exist = true; } else { - s.try_push(OutboundChannelDetails::new(dest).with_signals()) - .map_err(|_| Error::::TooManyActiveOutboundChannels)?; + s.try_push(OutboundChannelDetails::new(dest).with_signals()).map_err(|error| { + log::debug!(target: LOG_TARGET, "Failed to activate XCMP channel: {error:?}"); + Error::::TooManyActiveOutboundChannels + })?; } let page = BoundedVec::::try_from( (XcmpMessageFormat::Signals, signal).encode(), ) - .map_err(|_| Error::::TooBig)?; + .map_err(|error| { + log::debug!(target: LOG_TARGET, "Failed to encode signal message: {error:?}"); + Error::::TooBig + })?; let page = WeakBoundedVec::force_from(page.into_inner(), None); >::insert(dest, page); @@ -699,9 +707,16 @@ impl Pallet { return Err(()) } - let xcm = VersionedXcm::<()>::decode_with_depth_limit(MAX_XCM_DECODE_DEPTH, data) - .map_err(|_| ())?; - Ok(Some(xcm.encode().try_into().map_err(|_| ())?)) + let xcm = VersionedXcm::<()>::decode_with_depth_limit(MAX_XCM_DECODE_DEPTH, data).map_err( + |error| { + log::debug!(target: LOG_TARGET, "Failed to decode XCM with depth limit: {error:?}"); + () + }, + )?; + Ok(Some(xcm.encode().try_into().map_err(|error| { + log::debug!(target: LOG_TARGET, "Failed to encode XCM after decoding: {error:?}"); + () + })?)) } /// Split concatenated encoded `VersionedXcm`s or `MaybeDoubleEncodedVersionedXcm`s into diff --git a/cumulus/parachains/common/src/xcm_config.rs b/cumulus/parachains/common/src/xcm_config.rs index 3e149098027bb..9807c8328b995 100644 --- a/cumulus/parachains/common/src/xcm_config.rs +++ b/cumulus/parachains/common/src/xcm_config.rs @@ -45,6 +45,11 @@ where >::AssetId, >::Balance, >, + >::AssetId, + >::Balance, + >>::Error: core::fmt::Debug, { fn charge_weight_in_fungibles( asset_id: as Inspect< @@ -59,7 +64,10 @@ where // If the amount gotten is not at least the ED, then make it be the ED of the asset // This is to avoid burning assets and decreasing the supply let asset_amount = BalanceConverter::to_asset_balance(amount, asset_id) - .map_err(|_| XcmError::TooExpensive)?; + .map_err(|error| { + log::debug!(target: "xcm::charge_weight_in_fungibles", "AssetFeeAsExistentialDepositMultiplier cannot convert to valid balance (possibly below ED): {error:?}"); + XcmError::TooExpensive + })?; Ok(asset_amount) } } diff --git a/polkadot/runtime/common/src/xcm_sender.rs b/polkadot/runtime/common/src/xcm_sender.rs index 711aac4c02965..b0fe08402b627 100644 --- a/polkadot/runtime/common/src/xcm_sender.rs +++ b/polkadot/runtime/common/src/xcm_sender.rs @@ -136,7 +136,13 @@ where let hash = sp_io::hashing::blake2_256(&blob[..]); dmp::Pallet::::queue_downward_message(&config, para, blob) .map(|()| hash) - .map_err(|_| SendError::Transport(&"Error placing into DMP queue")) + .map_err(|error| { + log::debug!( + target: "xcm::xcm_sender::deliver", + "Failed to place into DMP queue: error: {error:?}, id: {hash:?}", + ); + SendError::Transport(&"Error placing into DMP queue") + }) } #[cfg(feature = "runtime-benchmarks")] diff --git a/polkadot/runtime/parachains/src/dmp.rs b/polkadot/runtime/parachains/src/dmp.rs index 27c4ec933bdb6..469474be693a2 100644 --- a/polkadot/runtime/parachains/src/dmp.rs +++ b/polkadot/runtime/parachains/src/dmp.rs @@ -66,7 +66,7 @@ mod tests; const THRESHOLD_FACTOR: u32 = 2; /// An error sending a downward message. -#[cfg_attr(test, derive(Debug))] +#[derive(Debug)] pub enum QueueDownwardMessageError { /// The message being sent exceeds the configured max message size. ExceedsMaxMessageSize, diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index ecb8640c4bf7e..e654ee9448458 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -349,7 +349,13 @@ pub mod pallet { let outcome = (|| { let origin_location = T::ExecuteXcmOrigin::ensure_origin(origin)?; let mut hash = message.using_encoded(sp_io::hashing::blake2_256); - let message = (*message).try_into().map_err(|()| Error::::BadVersion)?; + let message = (*message).try_into().map_err(|()| { + tracing::debug!( + target: "xcm::pallet_xcm::execute", id=?hash, + "Failed to convert VersionedXcm to Xcm", + ); + Error::::BadVersion + })?; let value = (origin_location, message); ensure!(T::XcmExecuteFilter::contains(&value), Error::::Filtered); let (origin_location, message) = value; @@ -362,6 +368,10 @@ pub mod pallet { )) })() .map_err(|e: DispatchError| { + tracing::debug!( + target: "xcm::pallet_xcm::execute", error=?e, + "Failed XCM pre-execution validation or filter", + ); e.with_weight(::execute()) })?; @@ -397,10 +407,27 @@ pub mod pallet { message: Box>, ) -> Result { let origin_location = T::SendXcmOrigin::ensure_origin(origin)?; - let interior: Junctions = - origin_location.clone().try_into().map_err(|_| Error::::InvalidOrigin)?; - let dest = Location::try_from(*dest).map_err(|()| Error::::BadVersion)?; - let message: Xcm<()> = (*message).try_into().map_err(|()| Error::::BadVersion)?; + let interior: Junctions = origin_location.clone().try_into().map_err(|_| { + tracing::debug!( + target: "xcm::pallet_xcm::send", + "Failed to convert origin_location to interior Junctions", + ); + Error::::InvalidOrigin + })?; + let dest = Location::try_from(*dest).map_err(|()| { + tracing::debug!( + target: "xcm::pallet_xcm::send", + "Failed to convert destination VersionedLocation to Location", + ); + Error::::BadVersion + })?; + let message: Xcm<()> = (*message).try_into().map_err(|()| { + tracing::debug!( + target: "xcm::pallet_xcm::send", + "Failed to convert VersionedXcm message to Xcm", + ); + Error::::BadVersion + })?; let message_id = Self::send_xcm(interior, dest.clone(), message.clone()) .map_err(|error| { @@ -434,8 +461,13 @@ pub mod pallet { let query_id = ::new_query( responder, timeout, - Location::try_from(match_querier) - .map_err(|_| Into::::into(Error::::BadVersion))?, + Location::try_from(match_querier).map_err(|_| { + tracing::debug!( + target: "xcm::pallet_xcm::query", + "Failed to convert VersionedLocation for match_querier", + ); + Into::::into(Error::::BadVersion) + })?, ); Ok(query_id) @@ -1220,9 +1252,18 @@ pub mod pallet { location: Box, ) -> DispatchResult { T::AdminOrigin::ensure_origin(origin)?; - let location: Location = - (*location).try_into().map_err(|()| Error::::BadLocation)?; + let location: Location = (*location).try_into().map_err(|()| { + tracing::debug!( + target: "xcm::pallet_xcm::force_subscribe_version_notify", + "Failed to convert VersionedLocation for subscription target" + ); + Error::::BadLocation + })?; Self::request_version_notify(location).map_err(|e| { + tracing::debug!( + target: "xcm::pallet_xcm::force_subscribe_version_notify", error=?e, + "Failed to subscribe for version notifications for location" + ); match e { XcmError::InvalidLocation => Error::::AlreadySubscribed, _ => Error::::InvalidOrigin, @@ -1243,9 +1284,18 @@ pub mod pallet { location: Box, ) -> DispatchResult { T::AdminOrigin::ensure_origin(origin)?; - let location: Location = - (*location).try_into().map_err(|()| Error::::BadLocation)?; + let location: Location = (*location).try_into().map_err(|()| { + tracing::debug!( + target: "xcm::pallet_xcm::force_unsubscribe_version_notify", + "Failed to convert VersionedLocation for unsubscription target" + ); + Error::::BadLocation + })?; Self::unrequest_version_notify(location).map_err(|e| { + tracing::debug!( + target: "xcm::pallet_xcm::force_unsubscribe_version_notify", error=?e, + "Failed to unsubscribe from version notifications for location" + ); match e { XcmError::InvalidLocation => Error::::NoSubscription, _ => Error::::InvalidOrigin, @@ -1396,10 +1446,27 @@ pub mod pallet { weight_limit: WeightLimit, ) -> DispatchResult { let origin = T::ExecuteXcmOrigin::ensure_origin(origin)?; - let dest = (*dest).try_into().map_err(|()| Error::::BadVersion)?; - let beneficiary: Location = - (*beneficiary).try_into().map_err(|()| Error::::BadVersion)?; - let assets: Assets = (*assets).try_into().map_err(|()| Error::::BadVersion)?; + let dest = (*dest).try_into().map_err(|()| { + tracing::debug!( + target: "xcm::pallet_xcm::transfer_assets", + "Failed to convert destination VersionedLocation", + ); + Error::::BadVersion + })?; + let beneficiary: Location = (*beneficiary).try_into().map_err(|()| { + tracing::debug!( + target: "xcm::pallet_xcm::transfer_assets", + "Failed to convert beneficiary VersionedLocation", + ); + Error::::BadVersion + })?; + let assets: Assets = (*assets).try_into().map_err(|()| { + tracing::debug!( + target: "xcm::pallet_xcm::transfer_assets", + "Failed to convert VersionedAssets", + ); + Error::::BadVersion + })?; tracing::debug!( target: "xcm::pallet_xcm::transfer_assets", ?origin, ?dest, ?beneficiary, ?assets, ?fee_asset_item, ?weight_limit, @@ -1440,10 +1507,21 @@ pub mod pallet { tracing::debug!(target: "xcm::pallet_xcm::claim_assets", ?origin_location, ?assets, ?beneficiary); // Extract version from `assets`. let assets_version = assets.identify_version(); - let assets: Assets = (*assets).try_into().map_err(|()| Error::::BadVersion)?; + let assets: Assets = (*assets).try_into().map_err(|()| { + tracing::debug!( + target: "xcm::pallet_xcm::claim_assets", + "Failed to convert input VersionedAssets", + ); + Error::::BadVersion + })?; let number_of_assets = assets.len() as u32; - let beneficiary: Location = - (*beneficiary).try_into().map_err(|()| Error::::BadVersion)?; + let beneficiary: Location = (*beneficiary).try_into().map_err(|()| { + tracing::debug!( + target: "xcm::pallet_xcm::claim_assets", + "Failed to convert beneficiary VersionedLocation", + ); + Error::::BadVersion + })?; let ticket: Location = GeneralIndex(assets_version as u128).into(); let mut message = Xcm(vec![ ClaimAsset { assets, ticket }, @@ -1529,12 +1607,34 @@ pub mod pallet { weight_limit: WeightLimit, ) -> DispatchResult { let origin_location = T::ExecuteXcmOrigin::ensure_origin(origin)?; - let dest: Location = (*dest).try_into().map_err(|()| Error::::BadVersion)?; - let assets: Assets = (*assets).try_into().map_err(|()| Error::::BadVersion)?; - let fees_id: AssetId = - (*remote_fees_id).try_into().map_err(|()| Error::::BadVersion)?; - let remote_xcm: Xcm<()> = - (*custom_xcm_on_dest).try_into().map_err(|()| Error::::BadVersion)?; + let dest: Location = (*dest).try_into().map_err(|()| { + tracing::debug!( + target: "xcm::pallet_xcm::transfer_assets_using_type_and_then", + "Failed to convert destination VersionedLocation", + ); + Error::::BadVersion + })?; + let assets: Assets = (*assets).try_into().map_err(|()| { + tracing::debug!( + target: "xcm::pallet_xcm::transfer_assets_using_type_and_then", + "Failed to convert VersionedAssets", + ); + Error::::BadVersion + })?; + let fees_id: AssetId = (*remote_fees_id).try_into().map_err(|()| { + tracing::debug!( + target: "xcm::pallet_xcm::transfer_assets_using_type_and_then", + "Failed to convert remote_fees_id VersionedAssetId", + ); + Error::::BadVersion + })?; + let remote_xcm: Xcm<()> = (*custom_xcm_on_dest).try_into().map_err(|()| { + tracing::debug!( + target: "xcm::pallet_xcm::transfer_assets_using_type_and_then", + "Failed to convert custom_xcm_on_dest VersionedXcm", + ); + Error::::BadVersion + })?; tracing::debug!( target: "xcm::pallet_xcm::transfer_assets_using_type_and_then", ?origin_location, ?dest, ?assets, ?assets_transfer_type, ?fees_id, ?fees_transfer_type, @@ -1577,8 +1677,13 @@ pub mod pallet { ) -> DispatchResult { let signed_origin = ensure_signed(origin.clone())?; let origin_location: Location = T::ExecuteXcmOrigin::ensure_origin(origin)?; - let new_aliaser: Location = - (*aliaser).try_into().map_err(|()| Error::::BadVersion)?; + let new_aliaser: Location = (*aliaser).try_into().map_err(|()| { + tracing::debug!( + target: "xcm::pallet_xcm::add_authorized_alias", + "Failed to convert aliaser VersionedLocation", + ); + Error::::BadVersion + })?; ensure!(origin_location != new_aliaser, Error::::BadLocation); // remove `network` from inner `AccountId32` for easier matching let origin_location = match origin_location.unpack() { @@ -1609,7 +1714,13 @@ pub mod pallet { // if it doesn't, we try to add it let aliaser = OriginAliaser { location: versioned_aliaser.clone(), expiry: expires }; - aliasers.try_push(aliaser).map_err(|_| Error::::TooManyAuthorizedAliases)?; + aliasers.try_push(aliaser).map_err(|_| { + tracing::debug!( + target: "xcm::pallet_xcm::add_authorized_alias", + "Failed to add new aliaser to existing entry", + ); + Error::::TooManyAuthorizedAliases + })?; // we try to update the ticket (the storage deposit) ticket = ticket.update(&signed_origin, aliasers_footprint(aliasers.len()))?; } @@ -1620,7 +1731,13 @@ pub mod pallet { let aliaser = OriginAliaser { location: versioned_aliaser.clone(), expiry: expires }; let mut aliasers = BoundedVec::::new(); - aliasers.try_push(aliaser).map_err(|_| Error::::TooManyAuthorizedAliases)?; + aliasers.try_push(aliaser).map_err(|error| { + tracing::debug!( + target: "xcm::pallet_xcm::add_authorized_alias", ?error, + "Failed to add first aliaser to new entry", + ); + Error::::TooManyAuthorizedAliases + })?; AuthorizedAliasesEntry { aliasers, ticket } }; // write to storage @@ -1642,7 +1759,13 @@ pub mod pallet { ) -> DispatchResult { let signed_origin = ensure_signed(origin.clone())?; let origin_location: Location = T::ExecuteXcmOrigin::ensure_origin(origin)?; - let to_remove: Location = (*aliaser).try_into().map_err(|()| Error::::BadVersion)?; + let to_remove: Location = (*aliaser).try_into().map_err(|()| { + tracing::debug!( + target: "xcm::pallet_xcm::remove_authorized_alias", + "Failed to convert aliaser VersionedLocation", + ); + Error::::BadVersion + })?; ensure!(origin_location != to_remove, Error::::BadLocation); // remove `network` from inner `AccountId32` for easier matching let origin_location = match origin_location.unpack() { @@ -1712,6 +1835,7 @@ pub mod pallet { }); Ok(()) } else { + tracing::debug!(target: "xcm::pallet_xcm::remove_all_authorized_aliases", "No authorized alias entry found for the origin"); Err(Error::::AliasNotFound.into()) } } @@ -1765,9 +1889,14 @@ impl QueryHandler for Pallet { timeout: Self::BlockNumber, ) -> Result { let responder = responder.into(); - let destination = Self::UniversalLocation::get() - .invert_target(&responder) - .map_err(|()| XcmError::LocationNotInvertible)?; + let destination = + Self::UniversalLocation::get().invert_target(&responder).map_err(|()| { + tracing::debug!( + target: "xcm::pallet_xcm::report_outcome", + "Failed to invert responder Location", + ); + XcmError::LocationNotInvertible + })?; let query_id = Self::new_query(responder, timeout, Here); let response_info = QueryResponseInfo { destination, query_id, max_weight: Weight::zero() }; let report_error = Xcm(vec![ReportError(response_info)]); @@ -1784,11 +1913,29 @@ impl QueryHandler for Pallet { Self::deposit_event(Event::ResponseTaken { query_id }); QueryResponseStatus::Ready { response, at } }, - Err(_) => QueryResponseStatus::UnexpectedVersion, + Err(_) => { + tracing::debug!( + target: "xcm::pallet_xcm::take_response", ?query_id, + "Failed to convert VersionedResponse to Response for query", + ); + QueryResponseStatus::UnexpectedVersion + }, }, Some(QueryStatus::Pending { timeout, .. }) => QueryResponseStatus::Pending { timeout }, - Some(_) => QueryResponseStatus::UnexpectedVersion, - None => QueryResponseStatus::NotFound, + Some(_) => { + tracing::debug!( + target: "xcm::pallet_xcm::take_response", ?query_id, + "Unexpected QueryStatus variant for query", + ); + QueryResponseStatus::UnexpectedVersion + }, + None => { + tracing::debug!( + target: "xcm::pallet_xcm::take_response", ?query_id, + "Query ID not found`", + ); + QueryResponseStatus::NotFound + }, } } @@ -1867,10 +2014,27 @@ impl Pallet { weight_limit: WeightLimit, ) -> DispatchResult { let origin_location = T::ExecuteXcmOrigin::ensure_origin(origin)?; - let dest = (*dest).try_into().map_err(|()| Error::::BadVersion)?; - let beneficiary: Location = - (*beneficiary).try_into().map_err(|()| Error::::BadVersion)?; - let assets: Assets = (*assets).try_into().map_err(|()| Error::::BadVersion)?; + let dest = (*dest).try_into().map_err(|()| { + tracing::debug!( + target: "xcm::pallet_xcm::do_reserve_transfer_assets", + "Failed to convert destination VersionedLocation", + ); + Error::::BadVersion + })?; + let beneficiary: Location = (*beneficiary).try_into().map_err(|()| { + tracing::debug!( + target: "xcm::pallet_xcm::do_reserve_transfer_assets", + "Failed to convert beneficiary VersionedLocation", + ); + Error::::BadVersion + })?; + let assets: Assets = (*assets).try_into().map_err(|()| { + tracing::debug!( + target: "xcm::pallet_xcm::do_reserve_transfer_assets", + "Failed to convert VersionedAssets", + ); + Error::::BadVersion + })?; tracing::debug!( target: "xcm::pallet_xcm::do_reserve_transfer_assets", ?origin_location, ?dest, ?beneficiary, ?assets, ?fee_asset_item, @@ -1913,10 +2077,27 @@ impl Pallet { weight_limit: WeightLimit, ) -> DispatchResult { let origin_location = T::ExecuteXcmOrigin::ensure_origin(origin)?; - let dest = (*dest).try_into().map_err(|()| Error::::BadVersion)?; - let beneficiary: Location = - (*beneficiary).try_into().map_err(|()| Error::::BadVersion)?; - let assets: Assets = (*assets).try_into().map_err(|()| Error::::BadVersion)?; + let dest = (*dest).try_into().map_err(|()| { + tracing::debug!( + target: "xcm::pallet_xcm::do_teleport_assets", + "Failed to convert destination VersionedLocation", + ); + Error::::BadVersion + })?; + let beneficiary: Location = (*beneficiary).try_into().map_err(|()| { + tracing::debug!( + target: "xcm::pallet_xcm::do_teleport_assets", + "Failed to convert beneficiary VersionedLocation", + ); + Error::::BadVersion + })?; + let assets: Assets = (*assets).try_into().map_err(|()| { + tracing::debug!( + target: "xcm::pallet_xcm::do_teleport_assets", + "Failed to convert VersionedAssets", + ); + Error::::BadVersion + })?; tracing::debug!( target: "xcm::pallet_xcm::do_teleport_assets", ?origin_location, ?dest, ?beneficiary, ?assets, ?fee_asset_item, ?weight_limit, @@ -2050,7 +2231,13 @@ impl Pallet { }; Self::remote_reserve_transfer_program( origin.clone(), - reserve.try_into().map_err(|()| Error::::BadVersion)?, + reserve.try_into().map_err(|()| { + tracing::debug!( + target: "xcm::pallet_xcm::build_xcm_transfer_type", + "Failed to convert remote reserve location", + ); + Error::::BadVersion + })?, beneficiary, dest.clone(), assets, @@ -2177,10 +2364,13 @@ impl Pallet { ensure!(T::XcmReserveTransferFilter::contains(&value), Error::::Filtered); let context = T::UniversalLocation::get(); - let reanchored_fees = fees - .clone() - .reanchored(&dest, &context) - .map_err(|_| Error::::CannotReanchor)?; + let reanchored_fees = fees.clone().reanchored(&dest, &context).map_err(|_| { + tracing::debug!( + target: "xcm::pallet_xcm::local_reserve_fees_instructions", + "Failed to re-anchor fees", + ); + Error::::CannotReanchor + })?; let local_execute_xcm = Xcm(vec![ // move `fees` to `dest`s local sovereign account @@ -2946,7 +3136,13 @@ impl Pallet { Ok((dest, forwarded_xcms)) }) .collect::, ()>>() - .map_err(|()| XcmDryRunApiError::VersionedConversionFailed) + .map_err(|()| { + tracing::debug!( + target: "xcm::pallet_xcm::convert_forwarded_xcms", + "Failed to convert VersionedLocation to requested version", + ); + XcmDryRunApiError::VersionedConversionFailed + }) } /// Given a list of asset ids, returns the correct API response for @@ -3020,7 +3216,10 @@ impl Pallet { }); TransactionOutcome::Rollback(result) - }).map_err(|_| XcmPaymentApiError::AssetNotFound)?; + }).map_err(|error| { + tracing::debug!(target: "xcm::pallet::query_weight_to_asset_fee", ?error, "Failed to execute transaction"); + XcmPaymentApiError::AssetNotFound + })?; let Some(unspent) = unspent.fungible.get(&asset) else { tracing::error!(target: "xcm::pallet::query_weight_to_asset_fee", ?asset, "The trader didn't return the needed fungible asset"); @@ -3224,9 +3423,13 @@ impl Pallet { timeout: BlockNumberFor, ) -> Result<(), XcmError> { let responder = responder.into(); - let destination = T::UniversalLocation::get() - .invert_target(&responder) - .map_err(|()| XcmError::LocationNotInvertible)?; + let destination = T::UniversalLocation::get().invert_target(&responder).map_err(|()| { + tracing::debug!( + target: "xcm::pallet_xcm::report_outcome_notify", + "Failed to invert responder location to universal location", + ); + XcmError::LocationNotInvertible + })?; let notify: ::RuntimeCall = notify.into(); let max_weight = notify.get_dispatch_info().call_weight; let query_id = Self::new_notify_query(responder, notify, timeout, Here); @@ -3274,8 +3477,13 @@ impl Pallet { /// - the `assets` are not known on this chain; /// - the `assets` cannot be withdrawn with that location as the Origin. fn charge_fees(location: Location, assets: Assets) -> DispatchResult { - T::XcmExecutor::charge_fees(location.clone(), assets.clone()) - .map_err(|_| Error::::FeesNotMet)?; + T::XcmExecutor::charge_fees(location.clone(), assets.clone()).map_err(|error| { + tracing::debug!( + target: "xcm::pallet_xcm::charge_fees", ?error, + "Failed to charge fees for location with assets", + ); + Error::::FeesNotMet + })?; Self::deposit_event(Event::FeesPaid { paying: location, fees: assets }); Ok(()) } @@ -3379,9 +3587,15 @@ impl xcm_executor::traits::Enact for LockTicket { locks[index].0 = locks[index].0.max(self.amount); }, None => { - locks - .try_push((self.amount, self.unlocker.into())) - .map_err(|(_balance, _location)| UnexpectedState)?; + locks.try_push((self.amount, self.unlocker.into())).map_err( + |(balance, location)| { + tracing::debug!( + target: "xcm::pallet_xcm::enact", ?balance, ?location, + "Failed to lock fungibles", + ); + UnexpectedState + }, + )?; }, } LockedFungibles::::insert(&self.sovereign_account, locks); diff --git a/polkadot/xcm/xcm-builder/src/currency_adapter.rs b/polkadot/xcm/xcm-builder/src/currency_adapter.rs index 1681e4dc6500c..e51a61371f427 100644 --- a/polkadot/xcm/xcm-builder/src/currency_adapter.rs +++ b/polkadot/xcm/xcm-builder/src/currency_adapter.rs @@ -19,7 +19,7 @@ #![allow(deprecated)] use super::MintLocation; -use core::{marker::PhantomData, result}; +use core::{fmt::Debug, marker::PhantomData, result}; use frame_support::traits::{ExistenceRequirement::AllowDeath, Get, WithdrawReasons}; use sp_runtime::traits::CheckedSub; use xcm::latest::{Asset, Error as XcmError, Location, Result, XcmContext}; @@ -113,7 +113,10 @@ impl< WithdrawReasons::TRANSFER, new_balance, ) - .map_err(|_| XcmError::NotWithdrawable) + .map_err(|error| { + tracing::debug!(target: "xcm::currency_adapter", ?error, "Failed to ensure can withdraw"); + XcmError::NotWithdrawable + }) } fn accrue_checked(checked_account: AccountId, amount: Currency::Balance) { let _ = Currency::deposit_creating(&checked_account, amount); @@ -137,7 +140,7 @@ impl< Currency: frame_support::traits::Currency, Matcher: MatchesFungible, AccountIdConverter: ConvertLocation, - AccountId: Clone, // can't get away without it since Currency is generic over it. + AccountId: Clone + Debug, // can't get away without it since Currency is generic over it. CheckedAccount: Get>, > TransactAsset for CurrencyAdapter @@ -214,8 +217,12 @@ impl< let amount = Matcher::matches_fungible(what).ok_or(Error::AssetNotHandled)?; let who = AccountIdConverter::convert_location(who).ok_or(Error::AccountIdConversionFailed)?; - let _ = Currency::withdraw(&who, amount, WithdrawReasons::TRANSFER, AllowDeath) - .map_err(|e| XcmError::FailedToTransactAsset(e.into()))?; + let _ = Currency::withdraw(&who, amount, WithdrawReasons::TRANSFER, AllowDeath).map_err( + |error| { + tracing::debug!(target: "xcm::currency_adapter", ?error, ?who, ?amount, "Failed to withdraw asset"); + XcmError::FailedToTransactAsset(error.into()) + }, + )?; Ok(what.clone().into()) } @@ -231,8 +238,10 @@ impl< AccountIdConverter::convert_location(from).ok_or(Error::AccountIdConversionFailed)?; let to = AccountIdConverter::convert_location(to).ok_or(Error::AccountIdConversionFailed)?; - Currency::transfer(&from, &to, amount, AllowDeath) - .map_err(|e| XcmError::FailedToTransactAsset(e.into()))?; + Currency::transfer(&from, &to, amount, AllowDeath).map_err(|error| { + tracing::debug!(target: "xcm::currency_adapter", ?error, ?from, ?to, ?amount, "Failed to transfer asset"); + XcmError::FailedToTransactAsset(error.into()) + })?; Ok(asset.clone().into()) } } diff --git a/polkadot/xcm/xcm-builder/src/fungible_adapter.rs b/polkadot/xcm/xcm-builder/src/fungible_adapter.rs index 10dd929fa478d..ef7f8f676512f 100644 --- a/polkadot/xcm/xcm-builder/src/fungible_adapter.rs +++ b/polkadot/xcm/xcm-builder/src/fungible_adapter.rs @@ -17,7 +17,7 @@ //! Adapters to work with [`frame_support::traits::fungible`] through XCM. use super::MintLocation; -use core::{marker::PhantomData, result}; +use core::{fmt::Debug, marker::PhantomData, result}; use frame_support::traits::{ tokens::{ fungible, Fortitude::Polite, Precision::Exact, Preservation::Expendable, Provenance::Minted, @@ -40,7 +40,7 @@ impl< Fungible: fungible::Mutate, Matcher: MatchesFungible, AccountIdConverter: ConvertLocation, - AccountId: Eq + Clone, + AccountId: Eq + Clone + Debug, > TransactAsset for FungibleTransferAdapter { fn internal_transfer_asset( @@ -60,8 +60,13 @@ impl< .ok_or(MatchError::AccountIdConversionFailed)?; let dest = AccountIdConverter::convert_location(to) .ok_or(MatchError::AccountIdConversionFailed)?; - Fungible::transfer(&source, &dest, amount, Expendable) - .map_err(|error| XcmError::FailedToTransactAsset(error.into()))?; + Fungible::transfer(&source, &dest, amount, Expendable).map_err(|error| { + tracing::debug!( + target: "xcm::fungible_adapter", ?error, ?source, ?dest, ?amount, + "Failed to transfer asset", + ); + XcmError::FailedToTransactAsset(error.into()) + })?; Ok(what.clone().into()) } } @@ -77,20 +82,32 @@ impl< Fungible: fungible::Mutate, Matcher: MatchesFungible, AccountIdConverter: ConvertLocation, - AccountId: Eq + Clone, + AccountId: Eq + Clone + Debug, CheckingAccount: Get>, > FungibleMutateAdapter { fn can_accrue_checked(checking_account: AccountId, amount: Fungible::Balance) -> XcmResult { Fungible::can_deposit(&checking_account, amount, Minted) .into_result() - .map_err(|_| XcmError::NotDepositable) + .map_err(|error| { + tracing::debug!( + target: "xcm::fungible_adapter", ?error, ?checking_account, ?amount, + "Failed to deposit funds into account", + ); + XcmError::NotDepositable + }) } fn can_reduce_checked(checking_account: AccountId, amount: Fungible::Balance) -> XcmResult { Fungible::can_withdraw(&checking_account, amount) .into_result(false) - .map_err(|_| XcmError::NotWithdrawable) + .map_err(|error| { + tracing::debug!( + target: "xcm::fungible_adapter", ?error, ?checking_account, ?amount, + "Failed to withdraw funds from account", + ); + XcmError::NotWithdrawable + }) .map(|_| ()) } @@ -109,7 +126,7 @@ impl< Fungible: fungible::Mutate, Matcher: MatchesFungible, AccountIdConverter: ConvertLocation, - AccountId: Eq + Clone, + AccountId: Eq + Clone + Debug, CheckingAccount: Get>, > TransactAsset for FungibleMutateAdapter @@ -192,8 +209,13 @@ impl< let amount = Matcher::matches_fungible(what).ok_or(MatchError::AssetNotHandled)?; let who = AccountIdConverter::convert_location(who) .ok_or(MatchError::AccountIdConversionFailed)?; - Fungible::mint_into(&who, amount) - .map_err(|error| XcmError::FailedToTransactAsset(error.into()))?; + Fungible::mint_into(&who, amount).map_err(|error| { + tracing::debug!( + target: "xcm::fungible_adapter", ?error, ?who, ?amount, + "Failed to deposit assets", + ); + XcmError::FailedToTransactAsset(error.into()) + })?; Ok(()) } @@ -210,8 +232,13 @@ impl< let amount = Matcher::matches_fungible(what).ok_or(MatchError::AssetNotHandled)?; let who = AccountIdConverter::convert_location(who) .ok_or(MatchError::AccountIdConversionFailed)?; - Fungible::burn_from(&who, amount, Expendable, Exact, Polite) - .map_err(|error| XcmError::FailedToTransactAsset(error.into()))?; + Fungible::burn_from(&who, amount, Expendable, Exact, Polite).map_err(|error| { + tracing::debug!( + target: "xcm::fungible_adapter", ?error, ?who, ?amount, + "Failed to withdraw assets", + ); + XcmError::FailedToTransactAsset(error.into()) + })?; Ok(what.clone().into()) } } @@ -226,7 +253,7 @@ impl< Fungible: fungible::Mutate, Matcher: MatchesFungible, AccountIdConverter: ConvertLocation, - AccountId: Eq + Clone, + AccountId: Eq + Clone + Debug, CheckingAccount: Get>, > TransactAsset for FungibleAdapter diff --git a/polkadot/xcm/xcm-builder/src/fungibles_adapter.rs b/polkadot/xcm/xcm-builder/src/fungibles_adapter.rs index f412dc42db5d0..74d459654191c 100644 --- a/polkadot/xcm/xcm-builder/src/fungibles_adapter.rs +++ b/polkadot/xcm/xcm-builder/src/fungibles_adapter.rs @@ -154,7 +154,8 @@ impl< Assets: fungibles::Mutate, Matcher: MatchesFungibles, AccountIdConverter: ConvertLocation, - AccountId: Eq + Clone, /* can't get away without it since Currency is generic over it. */ + AccountId: Eq + Clone + Debug, /* can't get away without it since Currency is generic + * over it. */ CheckAsset: AssetChecking, CheckingAccount: Get, > @@ -164,13 +165,25 @@ impl< let checking_account = CheckingAccount::get(); Assets::can_deposit(asset_id, &checking_account, amount, Minted) .into_result() - .map_err(|_| XcmError::NotDepositable) + .map_err(|error| { + tracing::debug!( + target: "xcm::fungibles_adapter", ?error, ?checking_account, ?amount, + "Failed to check if asset can be accrued" + ); + XcmError::NotDepositable + }) } fn can_reduce_checked(asset_id: Assets::AssetId, amount: Assets::Balance) -> XcmResult { let checking_account = CheckingAccount::get(); Assets::can_withdraw(asset_id, &checking_account, amount) .into_result(false) - .map_err(|_| XcmError::NotWithdrawable) + .map_err(|error| { + tracing::debug!( + target: "xcm::fungibles_adapter", ?error, ?checking_account, ?amount, + "Failed to check if asset can be reduced" + ); + XcmError::NotWithdrawable + }) .map(|_| ()) } fn accrue_checked(asset_id: Assets::AssetId, amount: Assets::Balance) { @@ -190,7 +203,8 @@ impl< Assets: fungibles::Mutate, Matcher: MatchesFungibles, AccountIdConverter: ConvertLocation, - AccountId: Eq + Clone, /* can't get away without it since Currency is generic over it. */ + AccountId: Eq + Clone + Debug, /* can't get away without it since Currency is generic + * over it. */ CheckAsset: AssetChecking, CheckingAccount: Get, > TransactAsset @@ -281,8 +295,10 @@ impl< let (asset_id, amount) = Matcher::matches_fungibles(what)?; let who = AccountIdConverter::convert_location(who) .ok_or(MatchError::AccountIdConversionFailed)?; - Assets::mint_into(asset_id, &who, amount) - .map_err(|e| XcmError::FailedToTransactAsset(e.into()))?; + Assets::mint_into(asset_id, &who, amount).map_err(|error| { + tracing::debug!(target: "xcm::fungibles_adapter", ?error, ?who, ?amount, "Failed to deposit asset"); + XcmError::FailedToTransactAsset(error.into()) + })?; Ok(()) } @@ -300,8 +316,10 @@ impl< let (asset_id, amount) = Matcher::matches_fungibles(what)?; let who = AccountIdConverter::convert_location(who) .ok_or(MatchError::AccountIdConversionFailed)?; - Assets::burn_from(asset_id, &who, amount, Expendable, Exact, Polite) - .map_err(|e| XcmError::FailedToTransactAsset(e.into()))?; + Assets::burn_from(asset_id, &who, amount, Expendable, Exact, Polite).map_err(|error| { + tracing::debug!(target: "xcm::fungibles_adapter", ?error, ?who, ?amount, "Failed to withdraw asset"); + XcmError::FailedToTransactAsset(error.into()) + })?; Ok(what.clone().into()) } } diff --git a/polkadot/xcm/xcm-builder/src/pay.rs b/polkadot/xcm/xcm-builder/src/pay.rs index 0093051290b74..7e8cdf2c3ce6c 100644 --- a/polkadot/xcm/xcm-builder/src/pay.rs +++ b/polkadot/xcm/xcm-builder/src/pay.rs @@ -97,14 +97,20 @@ impl< asset_kind: Self::AssetKind, amount: Self::Balance, ) -> Result { - let locatable = AssetKindToLocatableAsset::try_convert(asset_kind) - .map_err(|_| xcm::latest::Error::InvalidLocation)?; + let locatable = AssetKindToLocatableAsset::try_convert(asset_kind).map_err(|error| { + tracing::debug!(target: "xcm::pay", ?error, "Failed to convert asset kind to locatable asset"); + xcm::latest::Error::InvalidLocation + })?; let LocatableAssetId { asset_id, location: asset_location } = locatable; - let destination = Querier::UniversalLocation::get() - .invert_target(&asset_location) - .map_err(|()| Self::Error::LocationNotInvertible)?; - let beneficiary = BeneficiaryRefToLocation::try_convert(&who) - .map_err(|_| xcm::latest::Error::InvalidLocation)?; + let destination = + Querier::UniversalLocation::get().invert_target(&asset_location).map_err(|()| { + tracing::debug!(target: "xcm::pay", "Failed to invert asset location"); + Self::Error::LocationNotInvertible + })?; + let beneficiary = BeneficiaryRefToLocation::try_convert(&who).map_err(|error| { + tracing::debug!(target: "xcm::pay", ?error, "Failed to convert beneficiary to location"); + xcm::latest::Error::InvalidLocation + })?; let query_id = Querier::new_query(asset_location.clone(), Timeout::get(), Interior::get()); diff --git a/polkadot/xcm/xcm-builder/src/transactional.rs b/polkadot/xcm/xcm-builder/src/transactional.rs index ffe379b0ed41d..85c9abfe6b3ac 100644 --- a/polkadot/xcm/xcm-builder/src/transactional.rs +++ b/polkadot/xcm/xcm-builder/src/transactional.rs @@ -35,6 +35,9 @@ impl ProcessTransaction for FrameTransactionalProcessor { _ => TransactionOutcome::Rollback(Ok(output)), } }) - .map_err(|_| XcmError::ExceedsStackLimit)? + .map_err(|error| { + tracing::debug!(target: "xcm::transactional", ?error, "Failed to process XCM transaction"); + XcmError::ExceedsStackLimit + })? } } diff --git a/polkadot/xcm/xcm-builder/src/universal_exports.rs b/polkadot/xcm/xcm-builder/src/universal_exports.rs index 573165928b33c..584fe5916d7e2 100644 --- a/polkadot/xcm/xcm-builder/src/universal_exports.rs +++ b/polkadot/xcm/xcm-builder/src/universal_exports.rs @@ -77,7 +77,10 @@ impl> SendXcm // This `clone` ensures that `dest` is not consumed in any case. let d = dest.clone().ok_or(MissingArgument)?; let universal_source = UniversalLocation::get(); - let devolved = ensure_is_remote(universal_source.clone(), d).map_err(|_| NotApplicable)?; + let devolved = ensure_is_remote(universal_source.clone(), d).map_err(|error| { + tracing::debug!(target: "xcm::universal_exports", ?error, "Failed to devolve location"); + NotApplicable + })?; let (remote_network, remote_location) = devolved; let xcm = msg.take().ok_or(MissingArgument)?; @@ -121,7 +124,10 @@ impl> SendXcm // This `clone` ensures that `dest` is not consumed in any case. let d = dest.clone().ok_or(MissingArgument)?; let universal_source = UniversalLocation::get(); - let devolved = ensure_is_remote(universal_source.clone(), d).map_err(|_| NotApplicable)?; + let devolved = ensure_is_remote(universal_source.clone(), d).map_err(|error| { + tracing::debug!(target: "xcm::universal_exports", ?error, "Failed to devolve location"); + NotApplicable + })?; let (remote_network, remote_location) = devolved; let xcm = msg.take().ok_or(MissingArgument)?; @@ -266,7 +272,10 @@ impl SendResult { // This `clone` ensures that `dest` is not consumed in any case. let d = dest.clone().ok_or(MissingArgument)?; - let devolved = ensure_is_remote(UniversalLocation::get(), d).map_err(|_| NotApplicable)?; + let devolved = ensure_is_remote(UniversalLocation::get(), d).map_err(|error| { + tracing::debug!(target: "xcm::universal_exports", ?error, "Failed to devolve location"); + NotApplicable + })?; let (remote_network, remote_location) = devolved; let xcm = msg.take().ok_or(MissingArgument)?; @@ -351,7 +360,10 @@ impl SendResult { // This `clone` ensures that `dest` is not consumed in any case. let d = dest.clone().ok_or(MissingArgument)?; - let devolved = ensure_is_remote(UniversalLocation::get(), d).map_err(|_| NotApplicable)?; + let devolved = ensure_is_remote(UniversalLocation::get(), d).map_err(|error| { + tracing::debug!(target: "xcm::universal_exports", ?error, "Failed to devolve location"); + NotApplicable + })?; let (remote_network, remote_location) = devolved; let xcm = msg.take().ok_or(MissingArgument)?; @@ -371,8 +383,10 @@ impl None, }; - let local_from_bridge = - UniversalLocation::get().invert_target(&bridge).map_err(|_| Unroutable)?; + let local_from_bridge = UniversalLocation::get().invert_target(&bridge).map_err(|_| { + tracing::debug!(target: "xcm::universal_exports", "Failed to invert bridge location"); + Unroutable + })?; let export_instruction = ExportMessage { network: remote_network, destination: remote_location, @@ -380,10 +394,11 @@ impl) -> Result<(), DispatchBlobError> { let our_universal = OurPlace::get(); - let our_global = - our_universal.global_consensus().map_err(|()| DispatchBlobError::Unbridgable)?; + let our_global = our_universal.global_consensus().map_err(|()| { + tracing::debug!(target: "xcm::universal_exports", "Failed to get global consensus"); + DispatchBlobError::Unbridgable + })?; let BridgeMessage { universal_dest, message } = - Decode::decode(&mut &blob[..]).map_err(|_| DispatchBlobError::InvalidEncoding)?; - let universal_dest: InteriorLocation = universal_dest - .try_into() - .map_err(|_| DispatchBlobError::UnsupportedLocationVersion)?; + Decode::decode(&mut &blob[..]).map_err(|error| { + tracing::debug!(target: "xcm::universal_exports", ?error, "Failed to decode blob"); + DispatchBlobError::InvalidEncoding + })?; + let universal_dest: InteriorLocation = universal_dest.try_into().map_err(|_| { + tracing::debug!(target: "xcm::universal_exports", "Failed to convert universal destination"); + DispatchBlobError::UnsupportedLocationVersion + })?; // `universal_dest` is the desired destination within the universe: first we need to check // we're in the right global consensus. let intended_global = universal_dest .global_consensus() - .map_err(|()| DispatchBlobError::NonUniversalDestination)?; + .map_err(|()| { + tracing::debug!(target: "xcm::universal_exports", "Failed to get global consensus from universal destination"); + DispatchBlobError::NonUniversalDestination })?; ensure!(intended_global == our_global, DispatchBlobError::WrongGlobal); let dest = universal_dest.relative_to(&our_universal); - let mut message: Xcm<()> = - message.try_into().map_err(|_| DispatchBlobError::UnsupportedXcmVersion)?; + let mut message: Xcm<()> = message.try_into().map_err(|_| { + tracing::debug!(target: "xcm::universal_exports", "Failed to convert message"); + DispatchBlobError::UnsupportedXcmVersion + })?; // Prepend our bridge instance discriminator. // Can be used for fine-grained control of origin on destination in case of multiple bridge @@ -528,7 +553,10 @@ impl< message.0.insert(0, DescendOrigin(bridge_instance)); } - send_xcm::(dest, message).map_err(|_| DispatchBlobError::RoutingError)?; + send_xcm::(dest, message).map_err(|error| { + tracing::debug!(target: "xcm::universal_exports", ?error, "Failed to send XCM"); + DispatchBlobError::RoutingError + })?; Ok(()) } } @@ -595,7 +623,10 @@ impl< .take() .ok_or(SendError::MissingArgument)? .split_global() - .map_err(|()| SendError::Unroutable)?; + .map_err(|()| { + tracing::debug!(target: "xcm::universal_exports", "Failed to split global consensus"); + SendError::Unroutable + })?; let mut message = message.take().ok_or(SendError::MissingArgument)?; let maybe_id = match message.last() { Some(SetTopic(t)) => Some(*t), @@ -609,12 +640,15 @@ impl< // We cannot use the latest `Versioned` because we don't know if the target chain already // supports the same version. Therefore, we better control the destination version with best // efforts. - let message = VersionedXcm::from(message) - .into_version(version) - .map_err(|()| SendError::DestinationUnsupported)?; + let message = VersionedXcm::from(message).into_version(version).map_err(|()| { + tracing::debug!(target: "xcm::universal_exports", "Failed to convert message to versioned XCM"); + SendError::DestinationUnsupported + })?; let universal_dest = VersionedInteriorLocation::from(universal_dest) .into_version(version) - .map_err(|()| SendError::DestinationUnsupported)?; + .map_err(|()| { + tracing::debug!(target: "xcm::universal_exports", "Failed to convert destination to versioned location"); + SendError::DestinationUnsupported })?; let id = maybe_id.unwrap_or_else(|| message.using_encoded(sp_io::hashing::blake2_256)); let blob = BridgeMessage { universal_dest, message }.encode(); diff --git a/polkadot/xcm/xcm-executor/src/lib.rs b/polkadot/xcm/xcm-executor/src/lib.rs index 951601e696e6a..6b9837d627e0f 100644 --- a/polkadot/xcm/xcm-executor/src/lib.rs +++ b/polkadot/xcm/xcm-executor/src/lib.rs @@ -984,7 +984,16 @@ impl XcmExecutor { let reanchor_context = Config::UniversalLocation::get(); assets .reanchor(&dest, &reanchor_context) - .map_err(|()| XcmError::LocationFull)?; + .map_err(|()| { + tracing::debug!( + target: "xcm::process_instruction::transfer_reserve_asset", + ?assets, + ?dest, + ?reanchor_context, + "Failed to reanchor assets to destination in context" + ); + XcmError::LocationFull + })?; let mut message = vec![ReserveAssetDeposited(assets), ClearOrigin]; message.extend(xcm.0.into_iter()); self.send(dest, Xcm(message), FeeReason::TransferReserveAsset)?; @@ -1265,7 +1274,13 @@ impl XcmExecutor { let teleport_fees = self .holding .try_take(fees_filter) - .map_err(|_| XcmError::NotHoldingFees)?; + .map_err(|error| { + tracing::debug!( + target: "xcm::process_instruction::initiate_transfer", ?error, + "Failed to take specified teleport fees from holding" + ); + XcmError::NotHoldingFees + })?; Self::do_teleport_assets( teleport_fees, &destination, @@ -1277,7 +1292,13 @@ impl XcmExecutor { let reserve_deposit_fees = self .holding .try_take(fees_filter) - .map_err(|_| XcmError::NotHoldingFees)?; + .map_err(|error| { + tracing::debug!( + target: "xcm::process_instruction::initiate_transfer", ?error, + "Failed to take specified reserve deposit fees from holding" + ); + XcmError::NotHoldingFees + })?; Self::do_reserve_deposit_assets( reserve_deposit_fees, &destination, @@ -1289,7 +1310,13 @@ impl XcmExecutor { let reserve_withdraw_fees = self .holding .try_take(fees_filter) - .map_err(|_| XcmError::NotHoldingFees)?; + .map_err(|error| { + tracing::debug!( + target: "xcm::process_instruction::initiate_transfer", ?error, + "Failed to take specified reserve withdraw fees from holding" + ); + XcmError::NotHoldingFees + })?; Self::do_reserve_withdraw_assets( reserve_withdraw_fees, &mut self.holding, @@ -1437,7 +1464,13 @@ impl XcmExecutor { // Pay for execution fees. let result = Config::TransactionalProcessor::process(|| { let max_fee = - self.holding.try_take(asset.into()).map_err(|_| XcmError::NotHoldingFees)?; + self.holding.try_take(asset.into()).map_err(|error| { + tracing::debug!( + target: "xcm::process_instruction::pay_fees", ?error, + "Failed to take fees from holding" + ); + XcmError::NotHoldingFees + })?; let unspent = self.trader.buy_weight(self.message_weight, max_fee, &self.context)?; // Move unspent to the `fees` register, it can later be moved to holding @@ -1563,7 +1596,13 @@ impl XcmExecutor { .collect::, XcmError>>()?; let QueryResponseInfo { destination, query_id, max_weight } = response_info; let response = - Response::PalletsInfo(pallets.try_into().map_err(|_| XcmError::Overflow)?); + Response::PalletsInfo(pallets.try_into().map_err(|error| { + tracing::debug!( + target: "xcm::process_instruction::query_pallet", ?error, + "Failed to convert pallets to response info" + ); + XcmError::Overflow + })?); let querier = Self::to_querier(self.cloned_origin(), &destination)?; let instruction = QueryResponse { query_id, response, max_weight, querier }; let message = Xcm(vec![instruction]); @@ -1621,7 +1660,13 @@ impl XcmExecutor { let origin = self.context.origin.as_ref().ok_or(XcmError::BadOrigin)?.clone(); let universal_source = Config::UniversalLocation::get() .within_global(origin) - .map_err(|()| XcmError::Unanchored)?; + .map_err(|()| { + tracing::debug!( + target: "xcm::process_instruction::export_message", + "Failed to reanchor origin to universal location", + ); + XcmError::Unanchored + })?; let hash = (self.origin_ref(), &destination).using_encoded(blake2_128); let channel = u32::decode(&mut hash.as_ref()).unwrap_or(0); // Hash identifies the lane on the exporter which we use. We use the pairwise diff --git a/prdoc/pr_8724.prdoc b/prdoc/pr_8724.prdoc new file mode 100644 index 0000000000000..59fb83bd0a06f --- /dev/null +++ b/prdoc/pr_8724.prdoc @@ -0,0 +1,20 @@ +title: Implement detailed logging for XCM failures +doc: +- audience: Runtime Dev + description: |- + This PR improves diagnostics in XCM-related code by adding detailed error logging, especially within map_err paths. It includes clearer messages, standardized log targets, and richer context to aid runtime developers and node operators in debugging and monitoring. +crates: +- name: cumulus-pallet-xcmp-queue + bump: patch +- name: parachains-common + bump: minor +- name: polkadot-runtime-common + bump: patch +- name: polkadot-runtime-parachains + bump: minor +- name: staging-xcm-executor + bump: patch +- name: staging-xcm-builder + bump: minor +- name: pallet-xcm + bump: patch