diff --git a/Cargo.lock b/Cargo.lock index 3e9b3f309..62d42714d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8604,7 +8604,6 @@ dependencies = [ "sp-runtime 24.0.0 (git+https://github.com/pendulum-chain/polkadot-sdk?rev=22dd6dee5148a0879306337bd8619c16224cc07b)", "sp-std 8.0.0 (git+https://github.com/pendulum-chain/polkadot-sdk?rev=22dd6dee5148a0879306337bd8619c16224cc07b)", "staging-xcm", - "staging-xcm-executor", ] [[package]] diff --git a/pallets/xcm-teleport/Cargo.toml b/pallets/xcm-teleport/Cargo.toml index c5b4ad131..ddcddefec 100644 --- a/pallets/xcm-teleport/Cargo.toml +++ b/pallets/xcm-teleport/Cargo.toml @@ -16,7 +16,6 @@ sp-runtime = { workspace = true } sp-std = { workspace = true } xcm = { workspace = true } -staging-xcm-executor = { workspace = true } # benchmarking frame-benchmarking = { workspace = true, optional = true } @@ -29,7 +28,6 @@ runtime-benchmarks = [ "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "sp-runtime/runtime-benchmarks", - "staging-xcm-executor/runtime-benchmarks", ] std = [ "frame-support/std", @@ -40,7 +38,6 @@ std = [ "sp-runtime/std", "sp-std/std", "xcm/std", - "staging-xcm-executor/std", "frame-benchmarking?/std", ] try-runtime = [ diff --git a/pallets/xcm-teleport/src/lib.rs b/pallets/xcm-teleport/src/lib.rs index 1545398cf..28f12cec0 100644 --- a/pallets/xcm-teleport/src/lib.rs +++ b/pallets/xcm-teleport/src/lib.rs @@ -47,7 +47,6 @@ pub mod pallet { traits::{Currency, ExistenceRequirement, WithdrawReasons}, }; use frame_system::pallet_prelude::*; - use sp_std::vec; use xcm::v3::{ prelude::*, Instruction, Junction, Junctions, MultiAsset, MultiAssetFilter, MultiAssets, MultiLocation, SendXcm, WeightLimit, WildFungibility, WildMultiAsset, Xcm, @@ -172,15 +171,17 @@ pub mod pallet { .try_into() .map_err(|_| Error::::AmountConversionFailed)?; - // 1. Withdraw and burn native tokens from the sender's account. - // Dropping the NegativeImbalance burns the tokens (reduces total issuance). - let _imbalance = T::Currency::withdraw( + // 1. Withdraw native tokens from the sender's account. + // We keep the imbalance and only burn it after successful XCM delivery. + // If validation or delivery fails locally, we refund the tokens back to the sender. + // Note: If the message is delivered but fails during execution on AssetHub, + // the tokens are still burned (remote execution failures cannot be detected here). + let imbalance = T::Currency::withdraw( &sender, amount, WithdrawReasons::TRANSFER, ExistenceRequirement::AllowDeath, )?; - // _imbalance is dropped here → tokens are burned // 2. Construct the remote XCM message for AssetHub. let fee_asset_location = T::FeeAssetOnDest::get(); @@ -245,22 +246,31 @@ pub mod pallet { asset_hub, amount_u128, fee_amount, ); - let (ticket, _price) = T::XcmRouter::validate(&mut Some(asset_hub), &mut Some(message)) - .map_err(|e| { + let (ticket, _price) = match T::XcmRouter::validate(&mut Some(asset_hub), &mut Some(message)) { + Ok(result) => result, + Err(e) => { log::error!( target: "xcm-teleport", "Failed to validate XCM message: {:?}", e ); - Error::::XcmSendFailed - })?; + // Refund the withdrawn tokens back to the sender + T::Currency::resolve_creating(&sender, imbalance); + return Err(Error::::XcmSendFailed.into()); + }, + }; - T::XcmRouter::deliver(ticket).map_err(|e| { + if let Err(e) = T::XcmRouter::deliver(ticket) { log::error!( target: "xcm-teleport", "Failed to deliver XCM message: {:?}", e ); - Error::::XcmSendFailed - })?; + // Refund the withdrawn tokens back to the sender + T::Currency::resolve_creating(&sender, imbalance); + return Err(Error::::XcmSendFailed.into()); + } + + // Drop the imbalance to burn the tokens (successful teleport) + drop(imbalance); // 4. Emit event Self::deposit_event(Event::NativeTeleportedToAssetHub { diff --git a/runtime/pendulum/src/xcm_config.rs b/runtime/pendulum/src/xcm_config.rs index 93693a974..c323fa10d 100644 --- a/runtime/pendulum/src/xcm_config.rs +++ b/runtime/pendulum/src/xcm_config.rs @@ -335,7 +335,7 @@ impl staging_xcm_executor::Config for XcmConfig { type AssetTransactor = LocalAssetTransactor; type OriginConverter = XcmOriginToTransactDispatchOrigin; type IsReserve = MultiNativeAsset; - // Teleporting is disabled. + // Teleporting is restricted to assets/origins defined in TrustedTeleporters. type IsTeleporter = TrustedTeleporters; type UniversalLocation = UniversalLocation; type Barrier = Barrier;