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: 0 additions & 1 deletion Cargo.lock

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

3 changes: 0 additions & 3 deletions pallets/xcm-teleport/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand All @@ -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",
Expand All @@ -40,7 +38,6 @@ std = [
"sp-runtime/std",
"sp-std/std",
"xcm/std",
"staging-xcm-executor/std",
"frame-benchmarking?/std",
]
try-runtime = [
Expand Down
34 changes: 22 additions & 12 deletions pallets/xcm-teleport/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -172,15 +171,17 @@ pub mod pallet {
.try_into()
.map_err(|_| Error::<T>::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();
Expand Down Expand Up @@ -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::<T>::XcmSendFailed
})?;
// Refund the withdrawn tokens back to the sender
T::Currency::resolve_creating(&sender, imbalance);
return Err(Error::<T>::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::<T>::XcmSendFailed
})?;
// Refund the withdrawn tokens back to the sender
T::Currency::resolve_creating(&sender, imbalance);
return Err(Error::<T>::XcmSendFailed.into());
}

// Drop the imbalance to burn the tokens (successful teleport)
drop(imbalance);

// 4. Emit event
Self::deposit_event(Event::NativeTeleportedToAssetHub {
Expand Down
2 changes: 1 addition & 1 deletion runtime/pendulum/src/xcm_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ impl staging_xcm_executor::Config for XcmConfig {
type AssetTransactor = LocalAssetTransactor;
type OriginConverter = XcmOriginToTransactDispatchOrigin;
type IsReserve = MultiNativeAsset<RelativeReserveProvider>;
// Teleporting is disabled.
// Teleporting is restricted to assets/origins defined in TrustedTeleporters.
type IsTeleporter = TrustedTeleporters;
type UniversalLocation = UniversalLocation;
type Barrier = Barrier;
Expand Down