referrerpolicy=no-referrer-when-downgrade

staging_xcm/v5/
mod.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Polkadot.
3
4// Polkadot is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Polkadot is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
16
17//! Version 5 of the Cross-Consensus Message format data structures.
18
19pub use super::v3::GetWeight;
20use super::v4::{
21	Instruction as OldInstruction, PalletInfo as OldPalletInfo,
22	QueryResponseInfo as OldQueryResponseInfo, Response as OldResponse, Xcm as OldXcm,
23};
24use crate::{utils::decode_xcm_instructions, DoubleEncoded};
25use alloc::{vec, vec::Vec};
26use bounded_collections::{parameter_types, BoundedVec};
27use codec::{
28	self, Decode, DecodeWithMemTracking, Encode, Error as CodecError, Input as CodecInput,
29	MaxEncodedLen,
30};
31use core::{fmt::Debug, result};
32use derive_where::derive_where;
33use scale_info::TypeInfo;
34
35mod asset;
36mod junction;
37pub(crate) mod junctions;
38mod location;
39mod traits;
40
41pub use asset::{
42	Asset, AssetFilter, AssetId, AssetInstance, AssetTransferFilter, Assets, Fungibility,
43	WildAsset, WildFungibility, MAX_ITEMS_IN_ASSETS,
44};
45pub use junction::{
46	BodyId, BodyPart, Junction, NetworkId, ROCOCO_GENESIS_HASH, WESTEND_GENESIS_HASH,
47};
48pub use junctions::Junctions;
49pub use location::{Ancestor, AncestorThen, InteriorLocation, Location, Parent, ParentThen};
50pub use traits::{
51	send_xcm, validate_send, Error, ExecuteXcm, InstructionError, InstructionIndex, Outcome,
52	PreparedMessage, Reanchorable, Result, SendError, SendResult, SendXcm, Weight, XcmHash,
53};
54// These parts of XCM v4 are unchanged in XCM v5, and are re-imported here.
55pub use super::v4::{MaxDispatchErrorLen, MaybeErrorCode, OriginKind, WeightLimit};
56
57pub const VERSION: super::Version = 5;
58
59/// An identifier for a query.
60pub type QueryId = u64;
61
62#[derive(Default, DecodeWithMemTracking, Encode, TypeInfo)]
63#[derive_where(Clone, Eq, PartialEq, Debug)]
64#[codec(encode_bound())]
65#[codec(decode_with_mem_tracking_bound(Call: Decode))]
66#[scale_info(bounds(), skip_type_params(Call))]
67pub struct Xcm<Call>(pub Vec<Instruction<Call>>);
68
69impl<Call> Decode for Xcm<Call>
70where
71	Call: Decode,
72{
73	fn decode<I: CodecInput>(input: &mut I) -> core::result::Result<Self, CodecError> {
74		Ok(Xcm(decode_xcm_instructions(input)?))
75	}
76}
77
78impl<Call> Xcm<Call> {
79	/// Create an empty instance.
80	pub fn new() -> Self {
81		Self(vec![])
82	}
83
84	/// Return `true` if no instructions are held in `self`.
85	pub fn is_empty(&self) -> bool {
86		self.0.is_empty()
87	}
88
89	/// Return the number of instructions held in `self`.
90	pub fn len(&self) -> usize {
91		self.0.len()
92	}
93
94	/// Return a reference to the inner value.
95	pub fn inner(&self) -> &[Instruction<Call>] {
96		&self.0
97	}
98
99	/// Return a mutable reference to the inner value.
100	pub fn inner_mut(&mut self) -> &mut Vec<Instruction<Call>> {
101		&mut self.0
102	}
103
104	/// Consume and return the inner value.
105	pub fn into_inner(self) -> Vec<Instruction<Call>> {
106		self.0
107	}
108
109	/// Return an iterator over references to the items.
110	pub fn iter(&self) -> impl Iterator<Item = &Instruction<Call>> {
111		self.0.iter()
112	}
113
114	/// Return an iterator over mutable references to the items.
115	pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Instruction<Call>> {
116		self.0.iter_mut()
117	}
118
119	/// Consume and return an iterator over the items.
120	pub fn into_iter(self) -> impl Iterator<Item = Instruction<Call>> {
121		self.0.into_iter()
122	}
123
124	/// Consume and either return `self` if it contains some instructions, or if it's empty, then
125	/// instead return the result of `f`.
126	pub fn or_else(self, f: impl FnOnce() -> Self) -> Self {
127		if self.0.is_empty() {
128			f()
129		} else {
130			self
131		}
132	}
133
134	/// Return the first instruction, if any.
135	pub fn first(&self) -> Option<&Instruction<Call>> {
136		self.0.first()
137	}
138
139	/// Return the last instruction, if any.
140	pub fn last(&self) -> Option<&Instruction<Call>> {
141		self.0.last()
142	}
143
144	/// Return the only instruction, contained in `Self`, iff only one exists (`None` otherwise).
145	pub fn only(&self) -> Option<&Instruction<Call>> {
146		if self.0.len() == 1 {
147			self.0.first()
148		} else {
149			None
150		}
151	}
152
153	/// Return the only instruction, contained in `Self`, iff only one exists (returns `self`
154	/// otherwise).
155	pub fn into_only(mut self) -> core::result::Result<Instruction<Call>, Self> {
156		if self.0.len() == 1 {
157			self.0.pop().ok_or(self)
158		} else {
159			Err(self)
160		}
161	}
162}
163
164impl<Call> From<Vec<Instruction<Call>>> for Xcm<Call> {
165	fn from(c: Vec<Instruction<Call>>) -> Self {
166		Self(c)
167	}
168}
169
170impl<Call> From<Xcm<Call>> for Vec<Instruction<Call>> {
171	fn from(c: Xcm<Call>) -> Self {
172		c.0
173	}
174}
175
176/// A prelude for importing all types typically used when interacting with XCM messages.
177pub mod prelude {
178	mod contents {
179		pub use super::super::{
180			send_xcm, validate_send, Ancestor, AncestorThen, Asset,
181			AssetFilter::{self, *},
182			AssetId,
183			AssetInstance::{self, *},
184			Assets, BodyId, BodyPart, Error as XcmError, ExecuteXcm,
185			Fungibility::{self, *},
186			Hint::{self, *},
187			HintNumVariants,
188			Instruction::*,
189			InstructionError, InstructionIndex, InteriorLocation,
190			Junction::{self, *},
191			Junctions::{self, Here},
192			Location, MaxAssetTransferFilters, MaybeErrorCode,
193			NetworkId::{self, *},
194			OriginKind, Outcome, PalletInfo, Parent, ParentThen, PreparedMessage, QueryId,
195			QueryResponseInfo, Reanchorable, Response, Result as XcmResult, SendError, SendResult,
196			SendXcm, Weight,
197			WeightLimit::{self, *},
198			WildAsset::{self, *},
199			WildFungibility::{self, Fungible as WildFungible, NonFungible as WildNonFungible},
200			XcmContext, XcmHash, XcmWeightInfo, VERSION as XCM_VERSION,
201		};
202	}
203	pub use super::{Instruction, Xcm};
204	pub use contents::*;
205	pub mod opaque {
206		pub use super::{
207			super::opaque::{Instruction, Xcm},
208			contents::*,
209		};
210	}
211}
212
213parameter_types! {
214	pub MaxPalletNameLen: u32 = 48;
215	pub MaxPalletsInfo: u32 = 64;
216	pub MaxAssetTransferFilters: u32 = 6;
217}
218
219#[derive(
220	Clone, Eq, PartialEq, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo, MaxEncodedLen,
221)]
222pub struct PalletInfo {
223	#[codec(compact)]
224	pub index: u32,
225	pub name: BoundedVec<u8, MaxPalletNameLen>,
226	pub module_name: BoundedVec<u8, MaxPalletNameLen>,
227	#[codec(compact)]
228	pub major: u32,
229	#[codec(compact)]
230	pub minor: u32,
231	#[codec(compact)]
232	pub patch: u32,
233}
234
235impl TryInto<OldPalletInfo> for PalletInfo {
236	type Error = ();
237
238	fn try_into(self) -> result::Result<OldPalletInfo, Self::Error> {
239		OldPalletInfo::new(
240			self.index,
241			self.name.into_inner(),
242			self.module_name.into_inner(),
243			self.major,
244			self.minor,
245			self.patch,
246		)
247		.map_err(|_| ())
248	}
249}
250
251impl PalletInfo {
252	pub fn new(
253		index: u32,
254		name: Vec<u8>,
255		module_name: Vec<u8>,
256		major: u32,
257		minor: u32,
258		patch: u32,
259	) -> result::Result<Self, Error> {
260		let name = BoundedVec::try_from(name).map_err(|_| Error::Overflow)?;
261		let module_name = BoundedVec::try_from(module_name).map_err(|_| Error::Overflow)?;
262
263		Ok(Self { index, name, module_name, major, minor, patch })
264	}
265}
266
267/// Response data to a query.
268#[derive(
269	Clone, Eq, PartialEq, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo, MaxEncodedLen,
270)]
271pub enum Response {
272	/// No response. Serves as a neutral default.
273	Null,
274	/// Some assets.
275	Assets(Assets),
276	/// The outcome of an XCM instruction.
277	ExecutionResult(Option<(u32, Error)>),
278	/// An XCM version.
279	Version(super::Version),
280	/// The index, instance name, pallet name and version of some pallets.
281	PalletsInfo(BoundedVec<PalletInfo, MaxPalletsInfo>),
282	/// The status of a dispatch attempt using `Transact`.
283	DispatchResult(MaybeErrorCode),
284}
285
286impl Default for Response {
287	fn default() -> Self {
288		Self::Null
289	}
290}
291
292impl TryFrom<OldResponse> for Response {
293	type Error = ();
294
295	fn try_from(old: OldResponse) -> result::Result<Self, Self::Error> {
296		use OldResponse::*;
297		Ok(match old {
298			Null => Self::Null,
299			Assets(assets) => Self::Assets(assets.try_into()?),
300			ExecutionResult(result) => Self::ExecutionResult(
301				result
302					.map(|(num, old_error)| (num, old_error.try_into()))
303					.map(|(num, result)| result.map(|inner| (num, inner)))
304					.transpose()?,
305			),
306			Version(version) => Self::Version(version),
307			PalletsInfo(pallet_info) => {
308				let inner = pallet_info
309					.into_iter()
310					.map(TryInto::try_into)
311					.collect::<result::Result<Vec<_>, _>>()?;
312				Self::PalletsInfo(
313					BoundedVec::<PalletInfo, MaxPalletsInfo>::try_from(inner).map_err(|_| ())?,
314				)
315			},
316			DispatchResult(maybe_error) => Self::DispatchResult(maybe_error),
317		})
318	}
319}
320
321/// Information regarding the composition of a query response.
322#[derive(Clone, Eq, PartialEq, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo)]
323pub struct QueryResponseInfo {
324	/// The destination to which the query response message should be send.
325	pub destination: Location,
326	/// The `query_id` field of the `QueryResponse` message.
327	#[codec(compact)]
328	pub query_id: QueryId,
329	/// The `max_weight` field of the `QueryResponse` message.
330	pub max_weight: Weight,
331}
332
333impl TryFrom<OldQueryResponseInfo> for QueryResponseInfo {
334	type Error = ();
335
336	fn try_from(old: OldQueryResponseInfo) -> result::Result<Self, Self::Error> {
337		Ok(Self {
338			destination: old.destination.try_into()?,
339			query_id: old.query_id,
340			max_weight: old.max_weight,
341		})
342	}
343}
344
345/// Contextual data pertaining to a specific list of XCM instructions.
346#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug)]
347pub struct XcmContext {
348	/// The current value of the Origin register of the `XCVM`.
349	pub origin: Option<Location>,
350	/// The identity of the XCM; this may be a hash of its versioned encoding but could also be
351	/// a high-level identity set by an appropriate barrier.
352	pub message_id: XcmHash,
353	/// The current value of the Topic register of the `XCVM`.
354	pub topic: Option<[u8; 32]>,
355}
356
357impl XcmContext {
358	/// Constructor which sets the message ID to the supplied parameter and leaves the origin and
359	/// topic unset.
360	pub fn with_message_id(message_id: XcmHash) -> XcmContext {
361		XcmContext { origin: None, message_id, topic: None }
362	}
363
364	/// Returns the topic if set, otherwise the message_id.
365	pub fn topic_or_message_id(&self) -> XcmHash {
366		if let Some(id) = self.topic {
367			id.into()
368		} else {
369			self.message_id
370		}
371	}
372}
373
374/// Cross-Consensus Message: A message from one consensus system to another.
375///
376/// Consensus systems that may send and receive messages include blockchains and smart contracts.
377///
378/// All messages are delivered from a known *origin*, expressed as a `Location`.
379///
380/// This is the inner XCM format and is version-sensitive. Messages are typically passed using the
381/// outer XCM format, known as `VersionedXcm`.
382#[derive(
383	Encode,
384	Decode,
385	DecodeWithMemTracking,
386	TypeInfo,
387	xcm_procedural::XcmWeightInfoTrait,
388	xcm_procedural::Builder,
389)]
390#[derive_where(Clone, Eq, PartialEq, Debug)]
391#[codec(encode_bound())]
392#[codec(decode_bound(Call: Decode))]
393#[codec(decode_with_mem_tracking_bound(Call: Decode))]
394#[scale_info(bounds(), skip_type_params(Call))]
395pub enum Instruction<Call> {
396	/// Withdraw asset(s) (`assets`) from the ownership of `origin` and place them into the Holding
397	/// Register.
398	///
399	/// - `assets`: The asset(s) to be withdrawn into holding.
400	///
401	/// Kind: *Command*.
402	///
403	/// Errors:
404	#[builder(loads_holding)]
405	WithdrawAsset(Assets),
406
407	/// Asset(s) (`assets`) have been received into the ownership of this system on the `origin`
408	/// system and equivalent derivatives should be placed into the Holding Register.
409	///
410	/// - `assets`: The asset(s) that are minted into holding.
411	///
412	/// Safety: `origin` must be trusted to have received and be storing `assets` such that they
413	/// may later be withdrawn should this system send a corresponding message.
414	///
415	/// Kind: *Trusted Indication*.
416	///
417	/// Errors:
418	#[builder(loads_holding)]
419	ReserveAssetDeposited(Assets),
420
421	/// Asset(s) (`assets`) have been destroyed on the `origin` system and equivalent assets should
422	/// be created and placed into the Holding Register.
423	///
424	/// - `assets`: The asset(s) that are minted into the Holding Register.
425	///
426	/// Safety: `origin` must be trusted to have irrevocably destroyed the corresponding `assets`
427	/// prior as a consequence of sending this message.
428	///
429	/// Kind: *Trusted Indication*.
430	///
431	/// Errors:
432	#[builder(loads_holding)]
433	ReceiveTeleportedAsset(Assets),
434
435	/// Respond with information that the local system is expecting.
436	///
437	/// - `query_id`: The identifier of the query that resulted in this message being sent.
438	/// - `response`: The message content.
439	/// - `max_weight`: The maximum weight that handling this response should take.
440	/// - `querier`: The location responsible for the initiation of the response, if there is one.
441	///   In general this will tend to be the same location as the receiver of this message. NOTE:
442	///   As usual, this is interpreted from the perspective of the receiving consensus system.
443	///
444	/// Safety: Since this is information only, there are no immediate concerns. However, it should
445	/// be remembered that even if the Origin behaves reasonably, it can always be asked to make
446	/// a response to a third-party chain who may or may not be expecting the response. Therefore
447	/// the `querier` should be checked to match the expected value.
448	///
449	/// Kind: *Information*.
450	///
451	/// Errors:
452	QueryResponse {
453		#[codec(compact)]
454		query_id: QueryId,
455		response: Response,
456		max_weight: Weight,
457		querier: Option<Location>,
458	},
459
460	/// Withdraw asset(s) (`assets`) from the ownership of `origin` and place equivalent assets
461	/// under the ownership of `beneficiary`.
462	///
463	/// - `assets`: The asset(s) to be withdrawn.
464	/// - `beneficiary`: The new owner for the assets.
465	///
466	/// Safety: No concerns.
467	///
468	/// Kind: *Command*.
469	///
470	/// Errors:
471	TransferAsset { assets: Assets, beneficiary: Location },
472
473	/// Withdraw asset(s) (`assets`) from the ownership of `origin` and place equivalent assets
474	/// under the ownership of `dest` within this consensus system (i.e. its sovereign account).
475	///
476	/// Send an onward XCM message to `dest` of `ReserveAssetDeposited` with the given
477	/// `xcm`.
478	///
479	/// - `assets`: The asset(s) to be withdrawn.
480	/// - `dest`: The location whose sovereign account will own the assets and thus the effective
481	///   beneficiary for the assets and the notification target for the reserve asset deposit
482	///   message.
483	/// - `xcm`: The instructions that should follow the `ReserveAssetDeposited` instruction, which
484	///   is sent onwards to `dest`.
485	///
486	/// Safety: No concerns.
487	///
488	/// Kind: *Command*.
489	///
490	/// Errors:
491	TransferReserveAsset { assets: Assets, dest: Location, xcm: Xcm<()> },
492
493	/// Apply the encoded transaction `call`, whose dispatch-origin should be `origin` as expressed
494	/// by the kind of origin `origin_kind`.
495	///
496	/// The Transact Status Register is set according to the result of dispatching the call.
497	///
498	/// - `origin_kind`: The means of expressing the message origin as a dispatch origin.
499	/// - `call`: The encoded transaction to be applied.
500	/// - `fallback_max_weight`: Used for compatibility with previous versions. Corresponds to the
501	///   `require_weight_at_most` parameter in previous versions. If you don't care about
502	///   compatibility you can just put `None`. WARNING: If you do, your XCM might not work with
503	///   older versions. Make sure to dry-run and validate.
504	///
505	/// Safety: No concerns.
506	///
507	/// Kind: *Command*.
508	///
509	/// Errors:
510	Transact {
511		origin_kind: OriginKind,
512		fallback_max_weight: Option<Weight>,
513		call: DoubleEncoded<Call>,
514	},
515
516	/// A message to notify about a new incoming HRMP channel. This message is meant to be sent by
517	/// the relay-chain to a para.
518	///
519	/// - `sender`: The sender in the to-be opened channel. Also, the initiator of the channel
520	///   opening.
521	/// - `max_message_size`: The maximum size of a message proposed by the sender.
522	/// - `max_capacity`: The maximum number of messages that can be queued in the channel.
523	///
524	/// Safety: The message should originate directly from the relay-chain.
525	///
526	/// Kind: *System Notification*
527	HrmpNewChannelOpenRequest {
528		#[codec(compact)]
529		sender: u32,
530		#[codec(compact)]
531		max_message_size: u32,
532		#[codec(compact)]
533		max_capacity: u32,
534	},
535
536	/// A message to notify about that a previously sent open channel request has been accepted by
537	/// the recipient. That means that the channel will be opened during the next relay-chain
538	/// session change. This message is meant to be sent by the relay-chain to a para.
539	///
540	/// Safety: The message should originate directly from the relay-chain.
541	///
542	/// Kind: *System Notification*
543	///
544	/// Errors:
545	HrmpChannelAccepted {
546		// NOTE: We keep this as a structured item to a) keep it consistent with the other Hrmp
547		// items; and b) because the field's meaning is not obvious/mentioned from the item name.
548		#[codec(compact)]
549		recipient: u32,
550	},
551
552	/// A message to notify that the other party in an open channel decided to close it. In
553	/// particular, `initiator` is going to close the channel opened from `sender` to the
554	/// `recipient`. The close will be enacted at the next relay-chain session change. This message
555	/// is meant to be sent by the relay-chain to a para.
556	///
557	/// Safety: The message should originate directly from the relay-chain.
558	///
559	/// Kind: *System Notification*
560	///
561	/// Errors:
562	HrmpChannelClosing {
563		#[codec(compact)]
564		initiator: u32,
565		#[codec(compact)]
566		sender: u32,
567		#[codec(compact)]
568		recipient: u32,
569	},
570
571	/// Clear the origin.
572	///
573	/// This may be used by the XCM author to ensure that later instructions cannot command the
574	/// authority of the origin (e.g. if they are being relayed from an untrusted source, as often
575	/// the case with `ReserveAssetDeposited`).
576	///
577	/// Safety: No concerns.
578	///
579	/// Kind: *Command*.
580	///
581	/// Errors:
582	ClearOrigin,
583
584	/// Mutate the origin to some interior location.
585	///
586	/// Kind: *Command*
587	///
588	/// Errors:
589	DescendOrigin(InteriorLocation),
590
591	/// Immediately report the contents of the Error Register to the given destination via XCM.
592	///
593	/// A `QueryResponse` message of type `ExecutionOutcome` is sent to the described destination.
594	///
595	/// - `response_info`: Information for making the response.
596	///
597	/// Kind: *Command*
598	///
599	/// Errors:
600	ReportError(QueryResponseInfo),
601
602	/// Remove the asset(s) (`assets`) from the Holding Register and place equivalent assets under
603	/// the ownership of `beneficiary` within this consensus system.
604	///
605	/// - `assets`: The asset(s) to remove from holding.
606	/// - `beneficiary`: The new owner for the assets.
607	///
608	/// Kind: *Command*
609	///
610	/// Errors:
611	DepositAsset { assets: AssetFilter, beneficiary: Location },
612
613	/// Remove the asset(s) (`assets`) from the Holding Register and place equivalent assets under
614	/// the ownership of `dest` within this consensus system (i.e. deposit them into its sovereign
615	/// account).
616	///
617	/// Send an onward XCM message to `dest` of `ReserveAssetDeposited` with the given `effects`.
618	///
619	/// - `assets`: The asset(s) to remove from holding.
620	/// - `dest`: The location whose sovereign account will own the assets and thus the effective
621	///   beneficiary for the assets and the notification target for the reserve asset deposit
622	///   message.
623	/// - `xcm`: The orders that should follow the `ReserveAssetDeposited` instruction which is
624	///   sent onwards to `dest`.
625	///
626	/// Kind: *Command*
627	///
628	/// Errors:
629	DepositReserveAsset { assets: AssetFilter, dest: Location, xcm: Xcm<()> },
630
631	/// Remove the asset(s) (`want`) from the Holding Register and replace them with alternative
632	/// assets.
633	///
634	/// The minimum amount of assets to be received into the Holding Register for the order not to
635	/// fail may be stated.
636	///
637	/// - `give`: The maximum amount of assets to remove from holding.
638	/// - `want`: The minimum amount of assets which `give` should be exchanged for.
639	/// - `maximal`: If `true`, then prefer to give as much as possible up to the limit of `give`
640	///   and receive accordingly more. If `false`, then prefer to give as little as possible in
641	///   order to receive as little as possible while receiving at least `want`.
642	///
643	/// Kind: *Command*
644	///
645	/// Errors:
646	ExchangeAsset { give: AssetFilter, want: Assets, maximal: bool },
647
648	/// Remove the asset(s) (`assets`) from holding and send a `WithdrawAsset` XCM message to a
649	/// reserve location.
650	///
651	/// - `assets`: The asset(s) to remove from holding.
652	/// - `reserve`: A valid location that acts as a reserve for all asset(s) in `assets`. The
653	///   sovereign account of this consensus system *on the reserve location* will have
654	///   appropriate assets withdrawn and `effects` will be executed on them. There will typically
655	///   be only one valid location on any given asset/chain combination.
656	/// - `xcm`: The instructions to execute on the assets once withdrawn *on the reserve
657	///   location*.
658	///
659	/// Kind: *Command*
660	///
661	/// Errors:
662	InitiateReserveWithdraw { assets: AssetFilter, reserve: Location, xcm: Xcm<()> },
663
664	/// Remove the asset(s) (`assets`) from holding and send a `ReceiveTeleportedAsset` XCM message
665	/// to a `dest` location.
666	///
667	/// - `assets`: The asset(s) to remove from holding.
668	/// - `dest`: A valid location that respects teleports coming from this location.
669	/// - `xcm`: The instructions to execute on the assets once arrived *on the destination
670	///   location*.
671	///
672	/// NOTE: The `dest` location *MUST* respect this origin as a valid teleportation origin for
673	/// all `assets`. If it does not, then the assets may be lost.
674	///
675	/// Kind: *Command*
676	///
677	/// Errors:
678	InitiateTeleport { assets: AssetFilter, dest: Location, xcm: Xcm<()> },
679
680	/// Report to a given destination the contents of the Holding Register.
681	///
682	/// A `QueryResponse` message of type `Assets` is sent to the described destination.
683	///
684	/// - `response_info`: Information for making the response.
685	/// - `assets`: A filter for the assets that should be reported back. The assets reported back
686	///   will be, asset-wise, *the lesser of this value and the holding register*. No wildcards
687	///   will be used when reporting assets back.
688	///
689	/// Kind: *Command*
690	///
691	/// Errors:
692	ReportHolding { response_info: QueryResponseInfo, assets: AssetFilter },
693
694	/// Pay for the execution of some XCM `xcm` and `orders` with up to `weight`
695	/// picoseconds of execution time, paying for this with up to `fees` from the Holding Register.
696	///
697	/// - `fees`: The asset(s) to remove from the Holding Register to pay for fees.
698	/// - `weight_limit`: The maximum amount of weight to purchase; this must be at least the
699	///   expected maximum weight of the total XCM to be executed for the
700	///   `AllowTopLevelPaidExecutionFrom` barrier to allow the XCM be executed.
701	///
702	/// Kind: *Command*
703	///
704	/// Errors:
705	#[builder(pays_fees)]
706	BuyExecution { fees: Asset, weight_limit: WeightLimit },
707
708	/// Refund any surplus weight previously bought with `BuyExecution`.
709	///
710	/// Kind: *Command*
711	///
712	/// Errors: None.
713	RefundSurplus,
714
715	/// Set the Error Handler Register. This is code that should be called in the case of an error
716	/// happening.
717	///
718	/// An error occurring within execution of this code will _NOT_ result in the error register
719	/// being set, nor will an error handler be called due to it. The error handler and appendix
720	/// may each still be set.
721	///
722	/// The apparent weight of this instruction is inclusive of the inner `Xcm`; the executing
723	/// weight however includes only the difference between the previous handler and the new
724	/// handler, which can reasonably be negative, which would result in a surplus.
725	///
726	/// Kind: *Command*
727	///
728	/// Errors: None.
729	SetErrorHandler(Xcm<Call>),
730
731	/// Set the Appendix Register. This is code that should be called after code execution
732	/// (including the error handler if any) is finished. This will be called regardless of whether
733	/// an error occurred.
734	///
735	/// Any error occurring due to execution of this code will result in the error register being
736	/// set, and the error handler (if set) firing.
737	///
738	/// The apparent weight of this instruction is inclusive of the inner `Xcm`; the executing
739	/// weight however includes only the difference between the previous appendix and the new
740	/// appendix, which can reasonably be negative, which would result in a surplus.
741	///
742	/// Kind: *Command*
743	///
744	/// Errors: None.
745	SetAppendix(Xcm<Call>),
746
747	/// Clear the Error Register.
748	///
749	/// Kind: *Command*
750	///
751	/// Errors: None.
752	ClearError,
753
754	/// Create some assets which are being held on behalf of the origin.
755	///
756	/// - `assets`: The assets which are to be claimed. This must match exactly with the assets
757	///   claimable by the origin of the ticket.
758	/// - `ticket`: The ticket of the asset; this is an abstract identifier to help locate the
759	///   asset.
760	///
761	/// Kind: *Command*
762	///
763	/// Errors:
764	#[builder(loads_holding)]
765	ClaimAsset { assets: Assets, ticket: Location },
766
767	/// Always throws an error of type `Trap`.
768	///
769	/// Kind: *Command*
770	///
771	/// Errors:
772	/// - `Trap`: All circumstances, whose inner value is the same as this item's inner value.
773	Trap(#[codec(compact)] u64),
774
775	/// Ask the destination system to respond with the most recent version of XCM that they
776	/// support in a `QueryResponse` instruction. Any changes to this should also elicit similar
777	/// responses when they happen.
778	///
779	/// - `query_id`: An identifier that will be replicated into the returned XCM message.
780	/// - `max_response_weight`: The maximum amount of weight that the `QueryResponse` item which
781	///   is sent as a reply may take to execute. NOTE: If this is unexpectedly large then the
782	///   response may not execute at all.
783	///
784	/// Kind: *Command*
785	///
786	/// Errors: *Fallible*
787	SubscribeVersion {
788		#[codec(compact)]
789		query_id: QueryId,
790		max_response_weight: Weight,
791	},
792
793	/// Cancel the effect of a previous `SubscribeVersion` instruction.
794	///
795	/// Kind: *Command*
796	///
797	/// Errors: *Fallible*
798	UnsubscribeVersion,
799
800	/// Reduce Holding by up to the given assets.
801	///
802	/// Holding is reduced by as much as possible up to the assets in the parameter. It is not an
803	/// error if the Holding does not contain the assets (to make this an error, use `ExpectAsset`
804	/// prior).
805	///
806	/// Kind: *Command*
807	///
808	/// Errors: *Infallible*
809	BurnAsset(Assets),
810
811	/// Throw an error if Holding does not contain at least the given assets.
812	///
813	/// Kind: *Command*
814	///
815	/// Errors:
816	/// - `ExpectationFalse`: If Holding Register does not contain the assets in the parameter.
817	ExpectAsset(Assets),
818
819	/// Ensure that the Origin Register equals some given value and throw an error if not.
820	///
821	/// Kind: *Command*
822	///
823	/// Errors:
824	/// - `ExpectationFalse`: If Origin Register is not equal to the parameter.
825	ExpectOrigin(Option<Location>),
826
827	/// Ensure that the Error Register equals some given value and throw an error if not.
828	///
829	/// Kind: *Command*
830	///
831	/// Errors:
832	/// - `ExpectationFalse`: If the value of the Error Register is not equal to the parameter.
833	ExpectError(Option<(u32, Error)>),
834
835	/// Ensure that the Transact Status Register equals some given value and throw an error if
836	/// not.
837	///
838	/// Kind: *Command*
839	///
840	/// Errors:
841	/// - `ExpectationFalse`: If the value of the Transact Status Register is not equal to the
842	///   parameter.
843	ExpectTransactStatus(MaybeErrorCode),
844
845	/// Query the existence of a particular pallet type.
846	///
847	/// - `module_name`: The module name of the pallet to query.
848	/// - `response_info`: Information for making the response.
849	///
850	/// Sends a `QueryResponse` to Origin whose data field `PalletsInfo` containing the information
851	/// of all pallets on the local chain whose name is equal to `name`. This is empty in the case
852	/// that the local chain is not based on Substrate Frame.
853	///
854	/// Safety: No concerns.
855	///
856	/// Kind: *Command*
857	///
858	/// Errors: *Fallible*.
859	QueryPallet { module_name: Vec<u8>, response_info: QueryResponseInfo },
860
861	/// Ensure that a particular pallet with a particular version exists.
862	///
863	/// - `index: Compact`: The index which identifies the pallet. An error if no pallet exists at
864	///   this index.
865	/// - `name: Vec<u8>`: Name which must be equal to the name of the pallet.
866	/// - `module_name: Vec<u8>`: Module name which must be equal to the name of the module in
867	///   which the pallet exists.
868	/// - `crate_major: Compact`: Version number which must be equal to the major version of the
869	///   crate which implements the pallet.
870	/// - `min_crate_minor: Compact`: Version number which must be at most the minor version of the
871	///   crate which implements the pallet.
872	///
873	/// Safety: No concerns.
874	///
875	/// Kind: *Command*
876	///
877	/// Errors:
878	/// - `ExpectationFalse`: In case any of the expectations are broken.
879	ExpectPallet {
880		#[codec(compact)]
881		index: u32,
882		name: Vec<u8>,
883		module_name: Vec<u8>,
884		#[codec(compact)]
885		crate_major: u32,
886		#[codec(compact)]
887		min_crate_minor: u32,
888	},
889
890	/// Send a `QueryResponse` message containing the value of the Transact Status Register to some
891	/// destination.
892	///
893	/// - `query_response_info`: The information needed for constructing and sending the
894	///   `QueryResponse` message.
895	///
896	/// Safety: No concerns.
897	///
898	/// Kind: *Command*
899	///
900	/// Errors: *Fallible*.
901	ReportTransactStatus(QueryResponseInfo),
902
903	/// Set the Transact Status Register to its default, cleared, value.
904	///
905	/// Safety: No concerns.
906	///
907	/// Kind: *Command*
908	///
909	/// Errors: *Infallible*.
910	ClearTransactStatus,
911
912	/// Set the Origin Register to be some child of the Universal Ancestor.
913	///
914	/// Safety: Should only be usable if the Origin is trusted to represent the Universal Ancestor
915	/// child in general. In general, no Origin should be able to represent the Universal Ancestor
916	/// child which is the root of the local consensus system since it would by extension
917	/// allow it to act as any location within the local consensus.
918	///
919	/// The `Junction` parameter should generally be a `GlobalConsensus` variant since it is only
920	/// these which are children of the Universal Ancestor.
921	///
922	/// Kind: *Command*
923	///
924	/// Errors: *Fallible*.
925	UniversalOrigin(Junction),
926
927	/// Send a message on to Non-Local Consensus system.
928	///
929	/// This will tend to utilize some extra-consensus mechanism, the obvious one being a bridge.
930	/// A fee may be charged; this may be determined based on the contents of `xcm`. It will be
931	/// taken from the Holding register.
932	///
933	/// - `network`: The remote consensus system to which the message should be exported.
934	/// - `destination`: The location relative to the remote consensus system to which the message
935	///   should be sent on arrival.
936	/// - `xcm`: The message to be exported.
937	///
938	/// As an example, to export a message for execution on Statemine (parachain #1000 in the
939	/// Kusama network), you would call with `network: NetworkId::Kusama` and
940	/// `destination: [Parachain(1000)].into()`. Alternatively, to export a message for execution
941	/// on Polkadot, you would call with `network: NetworkId:: Polkadot` and `destination: Here`.
942	///
943	/// Kind: *Command*
944	///
945	/// Errors: *Fallible*.
946	ExportMessage { network: NetworkId, destination: InteriorLocation, xcm: Xcm<()> },
947
948	/// Lock the locally held asset and prevent further transfer or withdrawal.
949	///
950	/// This restriction may be removed by the `UnlockAsset` instruction being called with an
951	/// Origin of `unlocker` and a `target` equal to the current `Origin`.
952	///
953	/// If the locking is successful, then a `NoteUnlockable` instruction is sent to `unlocker`.
954	///
955	/// - `asset`: The asset(s) which should be locked.
956	/// - `unlocker`: The value which the Origin must be for a corresponding `UnlockAsset`
957	///   instruction to work.
958	///
959	/// Kind: *Command*.
960	///
961	/// Errors:
962	LockAsset { asset: Asset, unlocker: Location },
963
964	/// Remove the lock over `asset` on this chain and (if nothing else is preventing it) allow the
965	/// asset to be transferred.
966	///
967	/// - `asset`: The asset to be unlocked.
968	/// - `target`: The owner of the asset on the local chain.
969	///
970	/// Safety: No concerns.
971	///
972	/// Kind: *Command*.
973	///
974	/// Errors:
975	UnlockAsset { asset: Asset, target: Location },
976
977	/// Asset (`asset`) has been locked on the `origin` system and may not be transferred. It may
978	/// only be unlocked with the receipt of the `UnlockAsset` instruction from this chain.
979	///
980	/// - `asset`: The asset(s) which are now unlockable from this origin.
981	/// - `owner`: The owner of the asset on the chain in which it was locked. This may be a
982	///   location specific to the origin network.
983	///
984	/// Safety: `origin` must be trusted to have locked the corresponding `asset`
985	/// prior as a consequence of sending this message.
986	///
987	/// Kind: *Trusted Indication*.
988	///
989	/// Errors:
990	NoteUnlockable { asset: Asset, owner: Location },
991
992	/// Send an `UnlockAsset` instruction to the `locker` for the given `asset`.
993	///
994	/// This may fail if the local system is making use of the fact that the asset is locked or,
995	/// of course, if there is no record that the asset actually is locked.
996	///
997	/// - `asset`: The asset(s) to be unlocked.
998	/// - `locker`: The location from which a previous `NoteUnlockable` was sent and to which an
999	///   `UnlockAsset` should be sent.
1000	///
1001	/// Kind: *Command*.
1002	///
1003	/// Errors:
1004	RequestUnlock { asset: Asset, locker: Location },
1005
1006	/// Sets the Fees Mode Register.
1007	///
1008	/// - `jit_withdraw`: The fees mode item; if set to `true` then fees for any instructions are
1009	///   withdrawn as needed using the same mechanism as `WithdrawAssets`.
1010	///
1011	/// Kind: *Command*.
1012	///
1013	/// Errors:
1014	SetFeesMode { jit_withdraw: bool },
1015
1016	/// Set the Topic Register.
1017	///
1018	/// The 32-byte array identifier in the parameter is not guaranteed to be
1019	/// unique; if such a property is desired, it is up to the code author to
1020	/// enforce uniqueness.
1021	///
1022	/// Safety: No concerns.
1023	///
1024	/// Kind: *Command*
1025	///
1026	/// Errors:
1027	SetTopic([u8; 32]),
1028
1029	/// Clear the Topic Register.
1030	///
1031	/// Kind: *Command*
1032	///
1033	/// Errors: None.
1034	ClearTopic,
1035
1036	/// Alter the current Origin to another given origin.
1037	///
1038	/// Kind: *Command*
1039	///
1040	/// Errors: If the existing state would not allow such a change.
1041	AliasOrigin(Location),
1042
1043	/// A directive to indicate that the origin expects free execution of the message.
1044	///
1045	/// At execution time, this instruction just does a check on the Origin register.
1046	/// However, at the barrier stage messages starting with this instruction can be disregarded if
1047	/// the origin is not acceptable for free execution or the `weight_limit` is `Limited` and
1048	/// insufficient.
1049	///
1050	/// Kind: *Indication*
1051	///
1052	/// Errors: If the given origin is `Some` and not equal to the current Origin register.
1053	UnpaidExecution { weight_limit: WeightLimit, check_origin: Option<Location> },
1054
1055	/// Takes an asset, uses it to pay for execution and puts the rest in the fees register.
1056	///
1057	/// Successor to `BuyExecution`.
1058	/// Defined in [Fellowship RFC 105](https://github.com/polkadot-fellows/RFCs/pull/105).
1059	/// Subsequent `PayFees` after the first one are noops.
1060	#[builder(pays_fees)]
1061	PayFees { asset: Asset },
1062
1063	/// Initiates cross-chain transfer as follows:
1064	///
1065	/// Assets in the holding register are matched using the given list of `AssetTransferFilter`s,
1066	/// they are then transferred based on their specified transfer type:
1067	///
1068	/// - teleport: burn local assets and append a `ReceiveTeleportedAsset` XCM instruction to the
1069	///   XCM program to be sent onward to the `destination` location,
1070	///
1071	/// - reserve deposit: place assets under the ownership of `destination` within this consensus
1072	///   system (i.e. its sovereign account), and append a `ReserveAssetDeposited` XCM instruction
1073	///   to the XCM program to be sent onward to the `destination` location,
1074	///
1075	/// - reserve withdraw: burn local assets and append a `WithdrawAsset` XCM instruction to the
1076	///   XCM program to be sent onward to the `destination` location,
1077	///
1078	/// The onward XCM is then appended a `ClearOrigin` to allow safe execution of any following
1079	/// custom XCM instructions provided in `remote_xcm`.
1080	///
1081	/// The onward XCM also contains either a `PayFees` or `UnpaidExecution` instruction based
1082	/// on the presence of the `remote_fees` parameter (see below).
1083	///
1084	/// If an XCM program requires going through multiple hops, it can compose this instruction to
1085	/// be used at every chain along the path, describing that specific leg of the flow.
1086	///
1087	/// Parameters:
1088	/// - `destination`: The location of the program next hop.
1089	/// - `remote_fees`: If set to `Some(asset_xfer_filter)`, the single asset matching
1090	///   `asset_xfer_filter` in the holding register will be transferred first in the remote XCM
1091	///   program, followed by a `PayFees(fee)`, then rest of transfers follow. This guarantees
1092	///   `remote_xcm` will successfully pass a `AllowTopLevelPaidExecutionFrom` barrier. If set to
1093	///   `None`, a `UnpaidExecution` instruction is appended instead. Please note that these
1094	///   assets are **reserved** for fees, they are sent to the fees register rather than holding.
1095	///   Best practice is to only add here enough to cover fees, and transfer the rest through the
1096	///   `assets` parameter.
1097	/// - `preserve_origin`: Specifies whether the original origin should be preserved or cleared,
1098	///   using the instructions `AliasOrigin` or `ClearOrigin` respectively.
1099	/// - `assets`: List of asset filters matched against existing assets in holding. These are
1100	///   transferred over to `destination` using the specified transfer type, and deposited to
1101	///   holding on `destination`.
1102	/// - `remote_xcm`: Custom instructions that will be executed on the `destination` chain. Note
1103	///   that these instructions will be executed after a `ClearOrigin` so their origin will be
1104	///   `None`.
1105	///
1106	/// Safety: No concerns.
1107	///
1108	/// Kind: *Command*
1109	InitiateTransfer {
1110		destination: Location,
1111		remote_fees: Option<AssetTransferFilter>,
1112		preserve_origin: bool,
1113		assets: BoundedVec<AssetTransferFilter, MaxAssetTransferFilters>,
1114		remote_xcm: Xcm<()>,
1115	},
1116
1117	/// Executes inner `xcm` with origin set to the provided `descendant_origin`. Once the inner
1118	/// `xcm` is executed, the original origin (the one active for this instruction) is restored.
1119	///
1120	/// Parameters:
1121	/// - `descendant_origin`: The origin that will be used during the execution of the inner
1122	///   `xcm`. If set to `None`, the inner `xcm` is executed with no origin. If set to `Some(o)`,
1123	///   the inner `xcm` is executed as if there was a `DescendOrigin(o)` executed before it, and
1124	///   runs the inner xcm with origin: `original_origin.append_with(o)`.
1125	/// - `xcm`: Inner instructions that will be executed with the origin modified according to
1126	///   `descendant_origin`.
1127	///
1128	/// Safety: No concerns.
1129	///
1130	/// Kind: *Command*
1131	///
1132	/// Errors:
1133	/// - `BadOrigin`
1134	ExecuteWithOrigin { descendant_origin: Option<InteriorLocation>, xcm: Xcm<Call> },
1135
1136	/// Set hints for XCM execution.
1137	///
1138	/// These hints change the behaviour of the XCM program they are present in.
1139	///
1140	/// Parameters:
1141	///
1142	/// - `hints`: A bounded vector of `ExecutionHint`, specifying the different hints that will
1143	/// be activated.
1144	SetHints { hints: BoundedVec<Hint, HintNumVariants> },
1145}
1146
1147#[derive(
1148	Encode,
1149	Decode,
1150	DecodeWithMemTracking,
1151	TypeInfo,
1152	Debug,
1153	PartialEq,
1154	Eq,
1155	Clone,
1156	xcm_procedural::NumVariants,
1157)]
1158pub enum Hint {
1159	/// Set asset claimer for all the trapped assets during the execution.
1160	///
1161	/// - `location`: The claimer of any assets potentially trapped during the execution of current
1162	///   XCM. It can be an arbitrary location, not necessarily the caller or origin.
1163	AssetClaimer { location: Location },
1164}
1165
1166impl<Call> Xcm<Call> {
1167	pub fn into<C>(self) -> Xcm<C> {
1168		Xcm::from(self)
1169	}
1170	pub fn from<C>(xcm: Xcm<C>) -> Self {
1171		Self(xcm.0.into_iter().map(Instruction::<Call>::from).collect())
1172	}
1173}
1174
1175impl<Call> Instruction<Call> {
1176	pub fn into<C>(self) -> Instruction<C> {
1177		Instruction::from(self)
1178	}
1179	pub fn from<C>(xcm: Instruction<C>) -> Self {
1180		use Instruction::*;
1181		match xcm {
1182			WithdrawAsset(assets) => WithdrawAsset(assets),
1183			ReserveAssetDeposited(assets) => ReserveAssetDeposited(assets),
1184			ReceiveTeleportedAsset(assets) => ReceiveTeleportedAsset(assets),
1185			QueryResponse { query_id, response, max_weight, querier } => {
1186				QueryResponse { query_id, response, max_weight, querier }
1187			},
1188			TransferAsset { assets, beneficiary } => TransferAsset { assets, beneficiary },
1189			TransferReserveAsset { assets, dest, xcm } => {
1190				TransferReserveAsset { assets, dest, xcm }
1191			},
1192			HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity } => {
1193				HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity }
1194			},
1195			HrmpChannelAccepted { recipient } => HrmpChannelAccepted { recipient },
1196			HrmpChannelClosing { initiator, sender, recipient } => {
1197				HrmpChannelClosing { initiator, sender, recipient }
1198			},
1199			Transact { origin_kind, call, fallback_max_weight } => {
1200				Transact { origin_kind, call: call.transmute_encoded(), fallback_max_weight }
1201			},
1202			ReportError(response_info) => ReportError(response_info),
1203			DepositAsset { assets, beneficiary } => DepositAsset { assets, beneficiary },
1204			DepositReserveAsset { assets, dest, xcm } => DepositReserveAsset { assets, dest, xcm },
1205			ExchangeAsset { give, want, maximal } => ExchangeAsset { give, want, maximal },
1206			InitiateReserveWithdraw { assets, reserve, xcm } => {
1207				InitiateReserveWithdraw { assets, reserve, xcm }
1208			},
1209			InitiateTeleport { assets, dest, xcm } => InitiateTeleport { assets, dest, xcm },
1210			ReportHolding { response_info, assets } => ReportHolding { response_info, assets },
1211			BuyExecution { fees, weight_limit } => BuyExecution { fees, weight_limit },
1212			ClearOrigin => ClearOrigin,
1213			DescendOrigin(who) => DescendOrigin(who),
1214			RefundSurplus => RefundSurplus,
1215			SetErrorHandler(xcm) => SetErrorHandler(xcm.into()),
1216			SetAppendix(xcm) => SetAppendix(xcm.into()),
1217			ClearError => ClearError,
1218			SetHints { hints } => SetHints { hints },
1219			ClaimAsset { assets, ticket } => ClaimAsset { assets, ticket },
1220			Trap(code) => Trap(code),
1221			SubscribeVersion { query_id, max_response_weight } => {
1222				SubscribeVersion { query_id, max_response_weight }
1223			},
1224			UnsubscribeVersion => UnsubscribeVersion,
1225			BurnAsset(assets) => BurnAsset(assets),
1226			ExpectAsset(assets) => ExpectAsset(assets),
1227			ExpectOrigin(origin) => ExpectOrigin(origin),
1228			ExpectError(error) => ExpectError(error),
1229			ExpectTransactStatus(transact_status) => ExpectTransactStatus(transact_status),
1230			QueryPallet { module_name, response_info } => {
1231				QueryPallet { module_name, response_info }
1232			},
1233			ExpectPallet { index, name, module_name, crate_major, min_crate_minor } => {
1234				ExpectPallet { index, name, module_name, crate_major, min_crate_minor }
1235			},
1236			ReportTransactStatus(response_info) => ReportTransactStatus(response_info),
1237			ClearTransactStatus => ClearTransactStatus,
1238			UniversalOrigin(j) => UniversalOrigin(j),
1239			ExportMessage { network, destination, xcm } => {
1240				ExportMessage { network, destination, xcm }
1241			},
1242			LockAsset { asset, unlocker } => LockAsset { asset, unlocker },
1243			UnlockAsset { asset, target } => UnlockAsset { asset, target },
1244			NoteUnlockable { asset, owner } => NoteUnlockable { asset, owner },
1245			RequestUnlock { asset, locker } => RequestUnlock { asset, locker },
1246			SetFeesMode { jit_withdraw } => SetFeesMode { jit_withdraw },
1247			SetTopic(topic) => SetTopic(topic),
1248			ClearTopic => ClearTopic,
1249			AliasOrigin(location) => AliasOrigin(location),
1250			UnpaidExecution { weight_limit, check_origin } => {
1251				UnpaidExecution { weight_limit, check_origin }
1252			},
1253			PayFees { asset } => PayFees { asset },
1254			InitiateTransfer { destination, remote_fees, preserve_origin, assets, remote_xcm } => {
1255				InitiateTransfer { destination, remote_fees, preserve_origin, assets, remote_xcm }
1256			},
1257			ExecuteWithOrigin { descendant_origin, xcm } => {
1258				ExecuteWithOrigin { descendant_origin, xcm: xcm.into() }
1259			},
1260		}
1261	}
1262}
1263
1264// TODO: Automate Generation
1265impl<Call, W: XcmWeightInfo<Call>> GetWeight<W> for Instruction<Call> {
1266	fn weight(&self) -> Weight {
1267		use Instruction::*;
1268		match self {
1269			WithdrawAsset(assets) => W::withdraw_asset(assets),
1270			ReserveAssetDeposited(assets) => W::reserve_asset_deposited(assets),
1271			ReceiveTeleportedAsset(assets) => W::receive_teleported_asset(assets),
1272			QueryResponse { query_id, response, max_weight, querier } => {
1273				W::query_response(query_id, response, max_weight, querier)
1274			},
1275			TransferAsset { assets, beneficiary } => W::transfer_asset(assets, beneficiary),
1276			TransferReserveAsset { assets, dest, xcm } => {
1277				W::transfer_reserve_asset(&assets, dest, xcm)
1278			},
1279			Transact { origin_kind, fallback_max_weight, call } => {
1280				W::transact(origin_kind, fallback_max_weight, call)
1281			},
1282			HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity } => {
1283				W::hrmp_new_channel_open_request(sender, max_message_size, max_capacity)
1284			},
1285			HrmpChannelAccepted { recipient } => W::hrmp_channel_accepted(recipient),
1286			HrmpChannelClosing { initiator, sender, recipient } => {
1287				W::hrmp_channel_closing(initiator, sender, recipient)
1288			},
1289			ClearOrigin => W::clear_origin(),
1290			DescendOrigin(who) => W::descend_origin(who),
1291			ReportError(response_info) => W::report_error(&response_info),
1292			DepositAsset { assets, beneficiary } => W::deposit_asset(assets, beneficiary),
1293			DepositReserveAsset { assets, dest, xcm } => {
1294				W::deposit_reserve_asset(assets, dest, xcm)
1295			},
1296			ExchangeAsset { give, want, maximal } => W::exchange_asset(give, want, maximal),
1297			InitiateReserveWithdraw { assets, reserve, xcm } => {
1298				W::initiate_reserve_withdraw(assets, reserve, xcm)
1299			},
1300			InitiateTeleport { assets, dest, xcm } => W::initiate_teleport(assets, dest, xcm),
1301			ReportHolding { response_info, assets } => W::report_holding(&response_info, &assets),
1302			BuyExecution { fees, weight_limit } => W::buy_execution(fees, weight_limit),
1303			RefundSurplus => W::refund_surplus(),
1304			SetErrorHandler(xcm) => W::set_error_handler(xcm),
1305			SetAppendix(xcm) => W::set_appendix(xcm),
1306			ClearError => W::clear_error(),
1307			SetHints { hints } => W::set_hints(hints),
1308			ClaimAsset { assets, ticket } => W::claim_asset(assets, ticket),
1309			Trap(code) => W::trap(code),
1310			SubscribeVersion { query_id, max_response_weight } => {
1311				W::subscribe_version(query_id, max_response_weight)
1312			},
1313			UnsubscribeVersion => W::unsubscribe_version(),
1314			BurnAsset(assets) => W::burn_asset(assets),
1315			ExpectAsset(assets) => W::expect_asset(assets),
1316			ExpectOrigin(origin) => W::expect_origin(origin),
1317			ExpectError(error) => W::expect_error(error),
1318			ExpectTransactStatus(transact_status) => W::expect_transact_status(transact_status),
1319			QueryPallet { module_name, response_info } => {
1320				W::query_pallet(module_name, response_info)
1321			},
1322			ExpectPallet { index, name, module_name, crate_major, min_crate_minor } => {
1323				W::expect_pallet(index, name, module_name, crate_major, min_crate_minor)
1324			},
1325			ReportTransactStatus(response_info) => W::report_transact_status(response_info),
1326			ClearTransactStatus => W::clear_transact_status(),
1327			UniversalOrigin(j) => W::universal_origin(j),
1328			ExportMessage { network, destination, xcm } => {
1329				W::export_message(network, destination, xcm)
1330			},
1331			LockAsset { asset, unlocker } => W::lock_asset(asset, unlocker),
1332			UnlockAsset { asset, target } => W::unlock_asset(asset, target),
1333			NoteUnlockable { asset, owner } => W::note_unlockable(asset, owner),
1334			RequestUnlock { asset, locker } => W::request_unlock(asset, locker),
1335			SetFeesMode { jit_withdraw } => W::set_fees_mode(jit_withdraw),
1336			SetTopic(topic) => W::set_topic(topic),
1337			ClearTopic => W::clear_topic(),
1338			AliasOrigin(location) => W::alias_origin(location),
1339			UnpaidExecution { weight_limit, check_origin } => {
1340				W::unpaid_execution(weight_limit, check_origin)
1341			},
1342			PayFees { asset } => W::pay_fees(asset),
1343			InitiateTransfer { destination, remote_fees, preserve_origin, assets, remote_xcm } => {
1344				W::initiate_transfer(destination, remote_fees, preserve_origin, assets, remote_xcm)
1345			},
1346			ExecuteWithOrigin { descendant_origin, xcm } => {
1347				W::execute_with_origin(descendant_origin, xcm)
1348			},
1349		}
1350	}
1351}
1352
1353pub mod opaque {
1354	/// The basic concrete type of `Xcm`, which doesn't make any assumptions about the
1355	/// format of a call other than it is pre-encoded.
1356	pub type Xcm = super::Xcm<()>;
1357
1358	/// The basic concrete type of `Instruction`, which doesn't make any assumptions about the
1359	/// format of a call other than it is pre-encoded.
1360	pub type Instruction = super::Instruction<()>;
1361}
1362
1363// Convert from a v4 XCM to a v5 XCM
1364impl<Call> TryFrom<OldXcm<Call>> for Xcm<Call> {
1365	type Error = ();
1366	fn try_from(old_xcm: OldXcm<Call>) -> result::Result<Self, Self::Error> {
1367		Ok(Xcm(old_xcm.0.into_iter().map(TryInto::try_into).collect::<result::Result<_, _>>()?))
1368	}
1369}
1370
1371// Convert from a v4 instruction to a v5 instruction
1372impl<Call> TryFrom<OldInstruction<Call>> for Instruction<Call> {
1373	type Error = ();
1374	fn try_from(old_instruction: OldInstruction<Call>) -> result::Result<Self, Self::Error> {
1375		use OldInstruction::*;
1376		Ok(match old_instruction {
1377			WithdrawAsset(assets) => Self::WithdrawAsset(assets.try_into()?),
1378			ReserveAssetDeposited(assets) => Self::ReserveAssetDeposited(assets.try_into()?),
1379			ReceiveTeleportedAsset(assets) => Self::ReceiveTeleportedAsset(assets.try_into()?),
1380			QueryResponse { query_id, response, max_weight, querier: Some(querier) } => {
1381				Self::QueryResponse {
1382					query_id,
1383					querier: querier.try_into()?,
1384					response: response.try_into()?,
1385					max_weight,
1386				}
1387			},
1388			QueryResponse { query_id, response, max_weight, querier: None } => {
1389				Self::QueryResponse {
1390					query_id,
1391					querier: None,
1392					response: response.try_into()?,
1393					max_weight,
1394				}
1395			},
1396			TransferAsset { assets, beneficiary } => Self::TransferAsset {
1397				assets: assets.try_into()?,
1398				beneficiary: beneficiary.try_into()?,
1399			},
1400			TransferReserveAsset { assets, dest, xcm } => Self::TransferReserveAsset {
1401				assets: assets.try_into()?,
1402				dest: dest.try_into()?,
1403				xcm: xcm.try_into()?,
1404			},
1405			HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity } => {
1406				Self::HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity }
1407			},
1408			HrmpChannelAccepted { recipient } => Self::HrmpChannelAccepted { recipient },
1409			HrmpChannelClosing { initiator, sender, recipient } => {
1410				Self::HrmpChannelClosing { initiator, sender, recipient }
1411			},
1412			Transact { origin_kind, require_weight_at_most, call } => Self::Transact {
1413				origin_kind,
1414				call: call.into(),
1415				fallback_max_weight: Some(require_weight_at_most),
1416			},
1417			ReportError(response_info) => Self::ReportError(QueryResponseInfo {
1418				query_id: response_info.query_id,
1419				destination: response_info.destination.try_into().map_err(|_| ())?,
1420				max_weight: response_info.max_weight,
1421			}),
1422			DepositAsset { assets, beneficiary } => {
1423				let beneficiary = beneficiary.try_into()?;
1424				let assets = assets.try_into()?;
1425				Self::DepositAsset { assets, beneficiary }
1426			},
1427			DepositReserveAsset { assets, dest, xcm } => {
1428				let dest = dest.try_into()?;
1429				let xcm = xcm.try_into()?;
1430				let assets = assets.try_into()?;
1431				Self::DepositReserveAsset { assets, dest, xcm }
1432			},
1433			ExchangeAsset { give, want, maximal } => {
1434				let give = give.try_into()?;
1435				let want = want.try_into()?;
1436				Self::ExchangeAsset { give, want, maximal }
1437			},
1438			InitiateReserveWithdraw { assets, reserve, xcm } => {
1439				let assets = assets.try_into()?;
1440				let reserve = reserve.try_into()?;
1441				let xcm = xcm.try_into()?;
1442				Self::InitiateReserveWithdraw { assets, reserve, xcm }
1443			},
1444			InitiateTeleport { assets, dest, xcm } => {
1445				let assets = assets.try_into()?;
1446				let dest = dest.try_into()?;
1447				let xcm = xcm.try_into()?;
1448				Self::InitiateTeleport { assets, dest, xcm }
1449			},
1450			ReportHolding { response_info, assets } => {
1451				let response_info = QueryResponseInfo {
1452					destination: response_info.destination.try_into().map_err(|_| ())?,
1453					query_id: response_info.query_id,
1454					max_weight: response_info.max_weight,
1455				};
1456				Self::ReportHolding { response_info, assets: assets.try_into()? }
1457			},
1458			BuyExecution { fees, weight_limit } => {
1459				let fees = fees.try_into()?;
1460				let weight_limit = weight_limit.into();
1461				Self::BuyExecution { fees, weight_limit }
1462			},
1463			ClearOrigin => Self::ClearOrigin,
1464			DescendOrigin(who) => Self::DescendOrigin(who.try_into()?),
1465			RefundSurplus => Self::RefundSurplus,
1466			SetErrorHandler(xcm) => Self::SetErrorHandler(xcm.try_into()?),
1467			SetAppendix(xcm) => Self::SetAppendix(xcm.try_into()?),
1468			ClearError => Self::ClearError,
1469			ClaimAsset { assets, ticket } => {
1470				let assets = assets.try_into()?;
1471				let ticket = ticket.try_into()?;
1472				Self::ClaimAsset { assets, ticket }
1473			},
1474			Trap(code) => Self::Trap(code),
1475			SubscribeVersion { query_id, max_response_weight } => {
1476				Self::SubscribeVersion { query_id, max_response_weight }
1477			},
1478			UnsubscribeVersion => Self::UnsubscribeVersion,
1479			BurnAsset(assets) => Self::BurnAsset(assets.try_into()?),
1480			ExpectAsset(assets) => Self::ExpectAsset(assets.try_into()?),
1481			ExpectOrigin(maybe_location) => Self::ExpectOrigin(
1482				maybe_location.map(|location| location.try_into()).transpose().map_err(|_| ())?,
1483			),
1484			ExpectError(maybe_error) => Self::ExpectError(
1485				maybe_error
1486					.map(|(num, old_error)| (num, old_error.try_into()))
1487					.map(|(num, result)| result.map(|inner| (num, inner)))
1488					.transpose()
1489					.map_err(|_| ())?,
1490			),
1491			ExpectTransactStatus(maybe_error_code) => Self::ExpectTransactStatus(maybe_error_code),
1492			QueryPallet { module_name, response_info } => Self::QueryPallet {
1493				module_name,
1494				response_info: response_info.try_into().map_err(|_| ())?,
1495			},
1496			ExpectPallet { index, name, module_name, crate_major, min_crate_minor } => {
1497				Self::ExpectPallet { index, name, module_name, crate_major, min_crate_minor }
1498			},
1499			ReportTransactStatus(response_info) => {
1500				Self::ReportTransactStatus(response_info.try_into().map_err(|_| ())?)
1501			},
1502			ClearTransactStatus => Self::ClearTransactStatus,
1503			UniversalOrigin(junction) => {
1504				Self::UniversalOrigin(junction.try_into().map_err(|_| ())?)
1505			},
1506			ExportMessage { network, destination, xcm } => Self::ExportMessage {
1507				network: network.into(),
1508				destination: destination.try_into().map_err(|_| ())?,
1509				xcm: xcm.try_into().map_err(|_| ())?,
1510			},
1511			LockAsset { asset, unlocker } => Self::LockAsset {
1512				asset: asset.try_into().map_err(|_| ())?,
1513				unlocker: unlocker.try_into().map_err(|_| ())?,
1514			},
1515			UnlockAsset { asset, target } => Self::UnlockAsset {
1516				asset: asset.try_into().map_err(|_| ())?,
1517				target: target.try_into().map_err(|_| ())?,
1518			},
1519			NoteUnlockable { asset, owner } => Self::NoteUnlockable {
1520				asset: asset.try_into().map_err(|_| ())?,
1521				owner: owner.try_into().map_err(|_| ())?,
1522			},
1523			RequestUnlock { asset, locker } => Self::RequestUnlock {
1524				asset: asset.try_into().map_err(|_| ())?,
1525				locker: locker.try_into().map_err(|_| ())?,
1526			},
1527			SetFeesMode { jit_withdraw } => Self::SetFeesMode { jit_withdraw },
1528			SetTopic(topic) => Self::SetTopic(topic),
1529			ClearTopic => Self::ClearTopic,
1530			AliasOrigin(location) => Self::AliasOrigin(location.try_into().map_err(|_| ())?),
1531			UnpaidExecution { weight_limit, check_origin } => Self::UnpaidExecution {
1532				weight_limit,
1533				check_origin: check_origin
1534					.map(|location| location.try_into())
1535					.transpose()
1536					.map_err(|_| ())?,
1537			},
1538		})
1539	}
1540}
1541
1542#[cfg(test)]
1543mod tests {
1544	use super::{prelude::*, *};
1545	use crate::{
1546		v4::{
1547			AssetFilter as OldAssetFilter, Junctions::Here as OldHere, WildAsset as OldWildAsset,
1548		},
1549		MAX_INSTRUCTIONS_TO_DECODE,
1550	};
1551
1552	#[test]
1553	fn basic_roundtrip_works() {
1554		let xcm = Xcm::<()>(vec![TransferAsset {
1555			assets: (Here, 1u128).into(),
1556			beneficiary: Here.into(),
1557		}]);
1558		let old_xcm = OldXcm::<()>(vec![OldInstruction::TransferAsset {
1559			assets: (OldHere, 1u128).into(),
1560			beneficiary: OldHere.into(),
1561		}]);
1562		assert_eq!(old_xcm, OldXcm::<()>::try_from(xcm.clone()).unwrap());
1563		let new_xcm: Xcm<()> = old_xcm.try_into().unwrap();
1564		assert_eq!(new_xcm, xcm);
1565	}
1566
1567	#[test]
1568	fn teleport_roundtrip_works() {
1569		let xcm = Xcm::<()>(vec![
1570			ReceiveTeleportedAsset((Here, 1u128).into()),
1571			ClearOrigin,
1572			DepositAsset { assets: Wild(AllCounted(1)), beneficiary: Here.into() },
1573		]);
1574		let old_xcm: OldXcm<()> = OldXcm::<()>(vec![
1575			OldInstruction::ReceiveTeleportedAsset((OldHere, 1u128).into()),
1576			OldInstruction::ClearOrigin,
1577			OldInstruction::DepositAsset {
1578				assets: crate::v4::AssetFilter::Wild(crate::v4::WildAsset::AllCounted(1)),
1579				beneficiary: OldHere.into(),
1580			},
1581		]);
1582		assert_eq!(old_xcm, OldXcm::<()>::try_from(xcm.clone()).unwrap());
1583		let new_xcm: Xcm<()> = old_xcm.try_into().unwrap();
1584		assert_eq!(new_xcm, xcm);
1585	}
1586
1587	#[test]
1588	fn reserve_deposit_roundtrip_works() {
1589		let xcm = Xcm::<()>(vec![
1590			ReserveAssetDeposited((Here, 1u128).into()),
1591			ClearOrigin,
1592			BuyExecution {
1593				fees: (Here, 1u128).into(),
1594				weight_limit: Some(Weight::from_parts(1, 1)).into(),
1595			},
1596			DepositAsset { assets: Wild(AllCounted(1)), beneficiary: Here.into() },
1597		]);
1598		let old_xcm = OldXcm::<()>(vec![
1599			OldInstruction::ReserveAssetDeposited((OldHere, 1u128).into()),
1600			OldInstruction::ClearOrigin,
1601			OldInstruction::BuyExecution {
1602				fees: (OldHere, 1u128).into(),
1603				weight_limit: WeightLimit::Limited(Weight::from_parts(1, 1)),
1604			},
1605			OldInstruction::DepositAsset {
1606				assets: crate::v4::AssetFilter::Wild(crate::v4::WildAsset::AllCounted(1)),
1607				beneficiary: OldHere.into(),
1608			},
1609		]);
1610		assert_eq!(old_xcm, OldXcm::<()>::try_from(xcm.clone()).unwrap());
1611		let new_xcm: Xcm<()> = old_xcm.try_into().unwrap();
1612		assert_eq!(new_xcm, xcm);
1613	}
1614
1615	#[test]
1616	fn deposit_asset_roundtrip_works() {
1617		let xcm = Xcm::<()>(vec![
1618			WithdrawAsset((Here, 1u128).into()),
1619			DepositAsset { assets: Wild(AllCounted(1)), beneficiary: Here.into() },
1620		]);
1621		let old_xcm = OldXcm::<()>(vec![
1622			OldInstruction::WithdrawAsset((OldHere, 1u128).into()),
1623			OldInstruction::DepositAsset {
1624				assets: OldAssetFilter::Wild(OldWildAsset::AllCounted(1)),
1625				beneficiary: OldHere.into(),
1626			},
1627		]);
1628		assert_eq!(old_xcm, OldXcm::<()>::try_from(xcm.clone()).unwrap());
1629		let new_xcm: Xcm<()> = old_xcm.try_into().unwrap();
1630		assert_eq!(new_xcm, xcm);
1631	}
1632
1633	#[test]
1634	fn deposit_reserve_asset_roundtrip_works() {
1635		let xcm = Xcm::<()>(vec![
1636			WithdrawAsset((Here, 1u128).into()),
1637			DepositReserveAsset {
1638				assets: Wild(AllCounted(1)),
1639				dest: Here.into(),
1640				xcm: Xcm::<()>(vec![]),
1641			},
1642		]);
1643		let old_xcm = OldXcm::<()>(vec![
1644			OldInstruction::WithdrawAsset((OldHere, 1u128).into()),
1645			OldInstruction::DepositReserveAsset {
1646				assets: OldAssetFilter::Wild(OldWildAsset::AllCounted(1)),
1647				dest: OldHere.into(),
1648				xcm: OldXcm::<()>(vec![]),
1649			},
1650		]);
1651		assert_eq!(old_xcm, OldXcm::<()>::try_from(xcm.clone()).unwrap());
1652		let new_xcm: Xcm<()> = old_xcm.try_into().unwrap();
1653		assert_eq!(new_xcm, xcm);
1654	}
1655
1656	#[test]
1657	fn transact_roundtrip_works() {
1658		// We can convert as long as there's a fallback.
1659		let xcm = Xcm::<()>(vec![
1660			WithdrawAsset((Here, 1u128).into()),
1661			Transact {
1662				origin_kind: OriginKind::SovereignAccount,
1663				call: vec![200, 200, 200].into(),
1664				fallback_max_weight: Some(Weight::from_parts(1_000_000, 1_024)),
1665			},
1666		]);
1667		let old_xcm = OldXcm::<()>(vec![
1668			OldInstruction::WithdrawAsset((OldHere, 1u128).into()),
1669			OldInstruction::Transact {
1670				origin_kind: OriginKind::SovereignAccount,
1671				call: vec![200, 200, 200].into(),
1672				require_weight_at_most: Weight::from_parts(1_000_000, 1_024),
1673			},
1674		]);
1675		assert_eq!(old_xcm, OldXcm::<()>::try_from(xcm.clone()).unwrap());
1676		let new_xcm: Xcm<()> = old_xcm.try_into().unwrap();
1677		assert_eq!(new_xcm, xcm);
1678
1679		// If we have no fallback the resulting message won't know the weight.
1680		let xcm_without_fallback = Xcm::<()>(vec![
1681			WithdrawAsset((Here, 1u128).into()),
1682			Transact {
1683				origin_kind: OriginKind::SovereignAccount,
1684				call: vec![200, 200, 200].into(),
1685				fallback_max_weight: None,
1686			},
1687		]);
1688		let old_xcm = OldXcm::<()>(vec![
1689			OldInstruction::WithdrawAsset((OldHere, 1u128).into()),
1690			OldInstruction::Transact {
1691				origin_kind: OriginKind::SovereignAccount,
1692				call: vec![200, 200, 200].into(),
1693				require_weight_at_most: Weight::MAX,
1694			},
1695		]);
1696		assert_eq!(old_xcm, OldXcm::<()>::try_from(xcm_without_fallback.clone()).unwrap());
1697		let new_xcm: Xcm<()> = old_xcm.try_into().unwrap();
1698		let xcm_with_max_weight_fallback = Xcm::<()>(vec![
1699			WithdrawAsset((Here, 1u128).into()),
1700			Transact {
1701				origin_kind: OriginKind::SovereignAccount,
1702				call: vec![200, 200, 200].into(),
1703				fallback_max_weight: Some(Weight::MAX),
1704			},
1705		]);
1706		assert_eq!(new_xcm, xcm_with_max_weight_fallback);
1707	}
1708
1709	#[test]
1710	fn decoding_respects_limit() {
1711		let max_xcm = Xcm::<()>(vec![ClearOrigin; MAX_INSTRUCTIONS_TO_DECODE as usize]);
1712		let encoded = max_xcm.encode();
1713		assert!(Xcm::<()>::decode(&mut &encoded[..]).is_ok());
1714
1715		let big_xcm = Xcm::<()>(vec![ClearOrigin; MAX_INSTRUCTIONS_TO_DECODE as usize + 1]);
1716		let encoded = big_xcm.encode();
1717		assert!(Xcm::<()>::decode(&mut &encoded[..]).is_err());
1718
1719		let nested_xcm = Xcm::<()>(vec![
1720			DepositReserveAsset {
1721				assets: All.into(),
1722				dest: Here.into(),
1723				xcm: max_xcm,
1724			};
1725			(MAX_INSTRUCTIONS_TO_DECODE / 2) as usize
1726		]);
1727		let encoded = nested_xcm.encode();
1728		assert!(Xcm::<()>::decode(&mut &encoded[..]).is_err());
1729
1730		let even_more_nested_xcm = Xcm::<()>(vec![SetAppendix(nested_xcm); 64]);
1731		let encoded = even_more_nested_xcm.encode();
1732		assert_eq!(encoded.len(), 342530);
1733		// This should not decode since the limit is 100
1734		assert_eq!(MAX_INSTRUCTIONS_TO_DECODE, 100, "precondition");
1735		assert!(Xcm::<()>::decode(&mut &encoded[..]).is_err());
1736	}
1737}