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