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