1pub use super::v3::GetWeight;
20use super::{
21 v3::{
22 Instruction as OldInstruction, PalletInfo as OldPalletInfo,
23 QueryResponseInfo as OldQueryResponseInfo, Response as OldResponse, Xcm as OldXcm,
24 },
25 v5::{
26 Instruction as NewInstruction, PalletInfo as NewPalletInfo,
27 QueryResponseInfo as NewQueryResponseInfo, Response as NewResponse, Xcm as NewXcm,
28 },
29};
30use crate::{utils::decode_xcm_instructions, DoubleEncoded};
31use alloc::{vec, vec::Vec};
32use bounded_collections::{parameter_types, BoundedVec};
33use codec::{
34 self, Decode, DecodeWithMemTracking, Encode, Error as CodecError, Input as CodecInput,
35 MaxEncodedLen,
36};
37use core::{fmt::Debug, result};
38use derive_where::derive_where;
39use frame_support::dispatch::GetDispatchInfo;
40use scale_info::TypeInfo;
41
42mod asset;
43mod junction;
44pub(crate) mod junctions;
45mod location;
46mod traits;
47
48pub use asset::{
49 Asset, AssetFilter, AssetId, AssetInstance, Assets, Fungibility, WildAsset, WildFungibility,
50 MAX_ITEMS_IN_ASSETS,
51};
52pub use junction::{BodyId, BodyPart, Junction, NetworkId};
53pub use junctions::Junctions;
54pub use location::{Ancestor, AncestorThen, InteriorLocation, Location, Parent, ParentThen};
55pub use traits::{
56 send_xcm, validate_send, Error, ExecuteXcm, Outcome, PreparedMessage, Reanchorable, Result,
57 SendError, SendResult, SendXcm, Weight, XcmHash,
58};
59pub use super::v3::{MaxDispatchErrorLen, MaybeErrorCode, OriginKind, WeightLimit};
61
62pub const VERSION: super::Version = 4;
64
65pub type QueryId = u64;
67
68#[derive(Default, Encode, DecodeWithMemTracking, TypeInfo)]
69#[derive_where(Clone, Eq, PartialEq, Debug)]
70#[codec(encode_bound())]
71#[codec(decode_bound())]
72#[scale_info(bounds(), skip_type_params(Call))]
73pub struct Xcm<Call>(pub Vec<Instruction<Call>>);
74
75impl<Call> Decode for Xcm<Call> {
76 fn decode<I: CodecInput>(input: &mut I) -> core::result::Result<Self, CodecError> {
77 Ok(Xcm(decode_xcm_instructions(input)?))
78 }
79}
80
81impl<Call> Xcm<Call> {
82 pub fn new() -> Self {
84 Self(vec![])
85 }
86
87 pub fn is_empty(&self) -> bool {
89 self.0.is_empty()
90 }
91
92 pub fn len(&self) -> usize {
94 self.0.len()
95 }
96
97 pub fn inner(&self) -> &[Instruction<Call>] {
99 &self.0
100 }
101
102 pub fn inner_mut(&mut self) -> &mut Vec<Instruction<Call>> {
104 &mut self.0
105 }
106
107 pub fn into_inner(self) -> Vec<Instruction<Call>> {
109 self.0
110 }
111
112 pub fn iter(&self) -> impl Iterator<Item = &Instruction<Call>> {
114 self.0.iter()
115 }
116
117 pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Instruction<Call>> {
119 self.0.iter_mut()
120 }
121
122 pub fn into_iter(self) -> impl Iterator<Item = Instruction<Call>> {
124 self.0.into_iter()
125 }
126
127 pub fn or_else(self, f: impl FnOnce() -> Self) -> Self {
130 if self.0.is_empty() {
131 f()
132 } else {
133 self
134 }
135 }
136
137 pub fn first(&self) -> Option<&Instruction<Call>> {
139 self.0.first()
140 }
141
142 pub fn last(&self) -> Option<&Instruction<Call>> {
144 self.0.last()
145 }
146
147 pub fn only(&self) -> Option<&Instruction<Call>> {
149 if self.0.len() == 1 {
150 self.0.first()
151 } else {
152 None
153 }
154 }
155
156 pub fn into_only(mut self) -> core::result::Result<Instruction<Call>, Self> {
159 if self.0.len() == 1 {
160 self.0.pop().ok_or(self)
161 } else {
162 Err(self)
163 }
164 }
165}
166
167impl<Call> From<Vec<Instruction<Call>>> for Xcm<Call> {
168 fn from(c: Vec<Instruction<Call>>) -> Self {
169 Self(c)
170 }
171}
172
173impl<Call> From<Xcm<Call>> for Vec<Instruction<Call>> {
174 fn from(c: Xcm<Call>) -> Self {
175 c.0
176 }
177}
178
179pub mod prelude {
181 mod contents {
182 pub use super::super::{
183 send_xcm, validate_send, Ancestor, AncestorThen, Asset,
184 AssetFilter::{self, *},
185 AssetId,
186 AssetInstance::{self, *},
187 Assets, BodyId, BodyPart, Error as XcmError, ExecuteXcm,
188 Fungibility::{self, *},
189 Instruction::*,
190 InteriorLocation,
191 Junction::{self, *},
192 Junctions::{self, Here},
193 Location, MaybeErrorCode,
194 NetworkId::{self, *},
195 OriginKind, Outcome, PalletInfo, Parent, ParentThen, PreparedMessage, QueryId,
196 QueryResponseInfo, Reanchorable, Response, Result as XcmResult, SendError, SendResult,
197 SendXcm, Weight,
198 WeightLimit::{self, *},
199 WildAsset::{self, *},
200 WildFungibility::{self, Fungible as WildFungible, NonFungible as WildNonFungible},
201 XcmContext, XcmHash, XcmWeightInfo, VERSION as XCM_VERSION,
202 };
203 }
204 pub use super::{Instruction, Xcm};
205 pub use contents::*;
206 pub mod opaque {
207 pub use super::{
208 super::opaque::{Instruction, Xcm},
209 contents::*,
210 };
211 }
212}
213
214parameter_types! {
215 pub MaxPalletNameLen: u32 = 48;
216 pub MaxPalletsInfo: u32 = 64;
217}
218
219#[derive(
220 Clone, Eq, PartialEq, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo, MaxEncodedLen,
221)]
222pub struct PalletInfo {
223 #[codec(compact)]
224 pub index: u32,
225 pub name: BoundedVec<u8, MaxPalletNameLen>,
226 pub module_name: BoundedVec<u8, MaxPalletNameLen>,
227 #[codec(compact)]
228 pub major: u32,
229 #[codec(compact)]
230 pub minor: u32,
231 #[codec(compact)]
232 pub patch: u32,
233}
234
235impl TryInto<OldPalletInfo> for PalletInfo {
236 type Error = ();
237
238 fn try_into(self) -> result::Result<OldPalletInfo, Self::Error> {
239 OldPalletInfo::new(
240 self.index,
241 self.name.into_inner(),
242 self.module_name.into_inner(),
243 self.major,
244 self.minor,
245 self.patch,
246 )
247 .map_err(|_| ())
248 }
249}
250
251impl TryInto<NewPalletInfo> for PalletInfo {
252 type Error = ();
253
254 fn try_into(self) -> result::Result<NewPalletInfo, Self::Error> {
255 NewPalletInfo::new(
256 self.index,
257 self.name.into_inner(),
258 self.module_name.into_inner(),
259 self.major,
260 self.minor,
261 self.patch,
262 )
263 .map_err(|_| ())
264 }
265}
266
267impl PalletInfo {
268 pub fn new(
269 index: u32,
270 name: Vec<u8>,
271 module_name: Vec<u8>,
272 major: u32,
273 minor: u32,
274 patch: u32,
275 ) -> result::Result<Self, Error> {
276 let name = BoundedVec::try_from(name).map_err(|_| Error::Overflow)?;
277 let module_name = BoundedVec::try_from(module_name).map_err(|_| Error::Overflow)?;
278
279 Ok(Self { index, name, module_name, major, minor, patch })
280 }
281}
282
283#[derive(
285 Clone, Eq, PartialEq, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo, MaxEncodedLen,
286)]
287pub enum Response {
288 Null,
290 Assets(Assets),
292 ExecutionResult(Option<(u32, Error)>),
294 Version(super::Version),
296 PalletsInfo(BoundedVec<PalletInfo, MaxPalletsInfo>),
298 DispatchResult(MaybeErrorCode),
300}
301
302impl Default for Response {
303 fn default() -> Self {
304 Self::Null
305 }
306}
307
308impl TryFrom<OldResponse> for Response {
309 type Error = ();
310
311 fn try_from(old: OldResponse) -> result::Result<Self, Self::Error> {
312 use OldResponse::*;
313 Ok(match old {
314 Null => Self::Null,
315 Assets(assets) => Self::Assets(assets.try_into()?),
316 ExecutionResult(result) => {
317 Self::ExecutionResult(result.map(|(num, old_error)| (num, old_error.into())))
318 },
319 Version(version) => Self::Version(version),
320 PalletsInfo(pallet_info) => {
321 let inner = pallet_info
322 .into_iter()
323 .map(TryInto::try_into)
324 .collect::<result::Result<Vec<_>, _>>()?;
325 Self::PalletsInfo(
326 BoundedVec::<PalletInfo, MaxPalletsInfo>::try_from(inner).map_err(|_| ())?,
327 )
328 },
329 DispatchResult(maybe_error) => Self::DispatchResult(maybe_error),
330 })
331 }
332}
333
334impl TryFrom<NewResponse> for Response {
335 type Error = ();
336
337 fn try_from(new: NewResponse) -> result::Result<Self, Self::Error> {
338 use NewResponse::*;
339 Ok(match new {
340 Null => Self::Null,
341 Assets(assets) => Self::Assets(assets.try_into()?),
342 ExecutionResult(result) => Self::ExecutionResult(
343 result
344 .map(|(num, new_error)| (num, new_error.try_into()))
345 .map(|(num, result)| result.map(|inner| (num, inner)))
346 .transpose()?,
347 ),
348 Version(version) => Self::Version(version),
349 PalletsInfo(pallet_info) => {
350 let inner = pallet_info
351 .into_iter()
352 .map(TryInto::try_into)
353 .collect::<result::Result<Vec<_>, _>>()?;
354 Self::PalletsInfo(
355 BoundedVec::<PalletInfo, MaxPalletsInfo>::try_from(inner).map_err(|_| ())?,
356 )
357 },
358 DispatchResult(maybe_error) => {
359 Self::DispatchResult(maybe_error.try_into().map_err(|_| ())?)
360 },
361 })
362 }
363}
364
365#[derive(Clone, Eq, PartialEq, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo)]
367pub struct QueryResponseInfo {
368 pub destination: Location,
370 #[codec(compact)]
372 pub query_id: QueryId,
373 pub max_weight: Weight,
375}
376
377impl TryFrom<NewQueryResponseInfo> for QueryResponseInfo {
378 type Error = ();
379
380 fn try_from(new: NewQueryResponseInfo) -> result::Result<Self, Self::Error> {
381 Ok(Self {
382 destination: new.destination.try_into()?,
383 query_id: new.query_id,
384 max_weight: new.max_weight,
385 })
386 }
387}
388
389impl TryFrom<OldQueryResponseInfo> for QueryResponseInfo {
390 type Error = ();
391
392 fn try_from(old: OldQueryResponseInfo) -> result::Result<Self, Self::Error> {
393 Ok(Self {
394 destination: old.destination.try_into()?,
395 query_id: old.query_id,
396 max_weight: old.max_weight,
397 })
398 }
399}
400
401#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug)]
403pub struct XcmContext {
404 pub origin: Option<Location>,
406 pub message_id: XcmHash,
409 pub topic: Option<[u8; 32]>,
411}
412
413impl XcmContext {
414 pub fn with_message_id(message_id: XcmHash) -> XcmContext {
417 XcmContext { origin: None, message_id, topic: None }
418 }
419}
420
421#[derive(
430 Encode,
431 Decode,
432 DecodeWithMemTracking,
433 TypeInfo,
434 xcm_procedural::XcmWeightInfoTrait,
435 xcm_procedural::Builder,
436)]
437#[derive_where(Clone, Eq, PartialEq, Debug)]
438#[codec(encode_bound())]
439#[codec(decode_bound())]
440#[codec(decode_with_mem_tracking_bound())]
441#[scale_info(bounds(), skip_type_params(Call))]
442pub enum Instruction<Call> {
443 #[builder(loads_holding)]
452 WithdrawAsset(Assets),
453
454 #[builder(loads_holding)]
466 ReserveAssetDeposited(Assets),
467
468 #[builder(loads_holding)]
480 ReceiveTeleportedAsset(Assets),
481
482 QueryResponse {
500 #[codec(compact)]
501 query_id: QueryId,
502 response: Response,
503 max_weight: Weight,
504 querier: Option<Location>,
505 },
506
507 TransferAsset { assets: Assets, beneficiary: Location },
519
520 TransferReserveAsset { assets: Assets, dest: Location, xcm: Xcm<()> },
539
540 Transact { origin_kind: OriginKind, require_weight_at_most: Weight, call: DoubleEncoded<Call> },
556
557 HrmpNewChannelOpenRequest {
569 #[codec(compact)]
570 sender: u32,
571 #[codec(compact)]
572 max_message_size: u32,
573 #[codec(compact)]
574 max_capacity: u32,
575 },
576
577 HrmpChannelAccepted {
587 #[codec(compact)]
590 recipient: u32,
591 },
592
593 HrmpChannelClosing {
604 #[codec(compact)]
605 initiator: u32,
606 #[codec(compact)]
607 sender: u32,
608 #[codec(compact)]
609 recipient: u32,
610 },
611
612 ClearOrigin,
624
625 DescendOrigin(InteriorLocation),
631
632 ReportError(QueryResponseInfo),
642
643 DepositAsset { assets: AssetFilter, beneficiary: Location },
653
654 DepositReserveAsset { assets: AssetFilter, dest: Location, xcm: Xcm<()> },
671
672 ExchangeAsset { give: AssetFilter, want: Assets, maximal: bool },
688
689 InitiateReserveWithdraw { assets: AssetFilter, reserve: Location, xcm: Xcm<()> },
704
705 InitiateTeleport { assets: AssetFilter, dest: Location, xcm: Xcm<()> },
720
721 ReportHolding { response_info: QueryResponseInfo, assets: AssetFilter },
734
735 #[builder(pays_fees)]
747 BuyExecution { fees: Asset, weight_limit: WeightLimit },
748
749 RefundSurplus,
755
756 SetErrorHandler(Xcm<Call>),
771
772 SetAppendix(Xcm<Call>),
787
788 ClearError,
794
795 #[builder(loads_holding)]
806 ClaimAsset { assets: Assets, ticket: Location },
807
808 Trap(#[codec(compact)] u64),
815
816 SubscribeVersion {
829 #[codec(compact)]
830 query_id: QueryId,
831 max_response_weight: Weight,
832 },
833
834 UnsubscribeVersion,
840
841 BurnAsset(Assets),
851
852 ExpectAsset(Assets),
859
860 ExpectOrigin(Option<Location>),
867
868 ExpectError(Option<(u32, Error)>),
875
876 ExpectTransactStatus(MaybeErrorCode),
885
886 QueryPallet { module_name: Vec<u8>, response_info: QueryResponseInfo },
901
902 ExpectPallet {
921 #[codec(compact)]
922 index: u32,
923 name: Vec<u8>,
924 module_name: Vec<u8>,
925 #[codec(compact)]
926 crate_major: u32,
927 #[codec(compact)]
928 min_crate_minor: u32,
929 },
930
931 ReportTransactStatus(QueryResponseInfo),
943
944 ClearTransactStatus,
952
953 UniversalOrigin(Junction),
967
968 ExportMessage { network: NetworkId, destination: InteriorLocation, xcm: Xcm<()> },
988
989 LockAsset { asset: Asset, unlocker: Location },
1004
1005 UnlockAsset { asset: Asset, target: Location },
1017
1018 NoteUnlockable { asset: Asset, owner: Location },
1032
1033 RequestUnlock { asset: Asset, locker: Location },
1046
1047 SetFeesMode { jit_withdraw: bool },
1056
1057 SetTopic([u8; 32]),
1069
1070 ClearTopic,
1076
1077 AliasOrigin(Location),
1083
1084 UnpaidExecution { weight_limit: WeightLimit, check_origin: Option<Location> },
1095}
1096
1097impl<Call> Xcm<Call> {
1098 pub fn into<C>(self) -> Xcm<C> {
1099 Xcm::from(self)
1100 }
1101 pub fn from<C>(xcm: Xcm<C>) -> Self {
1102 Self(xcm.0.into_iter().map(Instruction::<Call>::from).collect())
1103 }
1104}
1105
1106impl<Call> Instruction<Call> {
1107 pub fn into<C>(self) -> Instruction<C> {
1108 Instruction::from(self)
1109 }
1110 pub fn from<C>(xcm: Instruction<C>) -> Self {
1111 use Instruction::*;
1112 match xcm {
1113 WithdrawAsset(assets) => WithdrawAsset(assets),
1114 ReserveAssetDeposited(assets) => ReserveAssetDeposited(assets),
1115 ReceiveTeleportedAsset(assets) => ReceiveTeleportedAsset(assets),
1116 QueryResponse { query_id, response, max_weight, querier } => {
1117 QueryResponse { query_id, response, max_weight, querier }
1118 },
1119 TransferAsset { assets, beneficiary } => TransferAsset { assets, beneficiary },
1120 TransferReserveAsset { assets, dest, xcm } => {
1121 TransferReserveAsset { assets, dest, xcm }
1122 },
1123 HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity } => {
1124 HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity }
1125 },
1126 HrmpChannelAccepted { recipient } => HrmpChannelAccepted { recipient },
1127 HrmpChannelClosing { initiator, sender, recipient } => {
1128 HrmpChannelClosing { initiator, sender, recipient }
1129 },
1130 Transact { origin_kind, require_weight_at_most, call } => {
1131 Transact { origin_kind, require_weight_at_most, call: call.into() }
1132 },
1133 ReportError(response_info) => ReportError(response_info),
1134 DepositAsset { assets, beneficiary } => DepositAsset { assets, beneficiary },
1135 DepositReserveAsset { assets, dest, xcm } => DepositReserveAsset { assets, dest, xcm },
1136 ExchangeAsset { give, want, maximal } => ExchangeAsset { give, want, maximal },
1137 InitiateReserveWithdraw { assets, reserve, xcm } => {
1138 InitiateReserveWithdraw { assets, reserve, xcm }
1139 },
1140 InitiateTeleport { assets, dest, xcm } => InitiateTeleport { assets, dest, xcm },
1141 ReportHolding { response_info, assets } => ReportHolding { response_info, assets },
1142 BuyExecution { fees, weight_limit } => BuyExecution { fees, weight_limit },
1143 ClearOrigin => ClearOrigin,
1144 DescendOrigin(who) => DescendOrigin(who),
1145 RefundSurplus => RefundSurplus,
1146 SetErrorHandler(xcm) => SetErrorHandler(xcm.into()),
1147 SetAppendix(xcm) => SetAppendix(xcm.into()),
1148 ClearError => ClearError,
1149 ClaimAsset { assets, ticket } => ClaimAsset { assets, ticket },
1150 Trap(code) => Trap(code),
1151 SubscribeVersion { query_id, max_response_weight } => {
1152 SubscribeVersion { query_id, max_response_weight }
1153 },
1154 UnsubscribeVersion => UnsubscribeVersion,
1155 BurnAsset(assets) => BurnAsset(assets),
1156 ExpectAsset(assets) => ExpectAsset(assets),
1157 ExpectOrigin(origin) => ExpectOrigin(origin),
1158 ExpectError(error) => ExpectError(error),
1159 ExpectTransactStatus(transact_status) => ExpectTransactStatus(transact_status),
1160 QueryPallet { module_name, response_info } => {
1161 QueryPallet { module_name, response_info }
1162 },
1163 ExpectPallet { index, name, module_name, crate_major, min_crate_minor } => {
1164 ExpectPallet { index, name, module_name, crate_major, min_crate_minor }
1165 },
1166 ReportTransactStatus(response_info) => ReportTransactStatus(response_info),
1167 ClearTransactStatus => ClearTransactStatus,
1168 UniversalOrigin(j) => UniversalOrigin(j),
1169 ExportMessage { network, destination, xcm } => {
1170 ExportMessage { network, destination, xcm }
1171 },
1172 LockAsset { asset, unlocker } => LockAsset { asset, unlocker },
1173 UnlockAsset { asset, target } => UnlockAsset { asset, target },
1174 NoteUnlockable { asset, owner } => NoteUnlockable { asset, owner },
1175 RequestUnlock { asset, locker } => RequestUnlock { asset, locker },
1176 SetFeesMode { jit_withdraw } => SetFeesMode { jit_withdraw },
1177 SetTopic(topic) => SetTopic(topic),
1178 ClearTopic => ClearTopic,
1179 AliasOrigin(location) => AliasOrigin(location),
1180 UnpaidExecution { weight_limit, check_origin } => {
1181 UnpaidExecution { weight_limit, check_origin }
1182 },
1183 }
1184 }
1185}
1186
1187impl<Call, W: XcmWeightInfo<Call>> GetWeight<W> for Instruction<Call> {
1189 fn weight(&self) -> Weight {
1190 use Instruction::*;
1191 match self {
1192 WithdrawAsset(assets) => W::withdraw_asset(assets),
1193 ReserveAssetDeposited(assets) => W::reserve_asset_deposited(assets),
1194 ReceiveTeleportedAsset(assets) => W::receive_teleported_asset(assets),
1195 QueryResponse { query_id, response, max_weight, querier } => {
1196 W::query_response(query_id, response, max_weight, querier)
1197 },
1198 TransferAsset { assets, beneficiary } => W::transfer_asset(assets, beneficiary),
1199 TransferReserveAsset { assets, dest, xcm } => {
1200 W::transfer_reserve_asset(&assets, dest, xcm)
1201 },
1202 Transact { origin_kind, require_weight_at_most, call } => {
1203 W::transact(origin_kind, require_weight_at_most, call)
1204 },
1205 HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity } => {
1206 W::hrmp_new_channel_open_request(sender, max_message_size, max_capacity)
1207 },
1208 HrmpChannelAccepted { recipient } => W::hrmp_channel_accepted(recipient),
1209 HrmpChannelClosing { initiator, sender, recipient } => {
1210 W::hrmp_channel_closing(initiator, sender, recipient)
1211 },
1212 ClearOrigin => W::clear_origin(),
1213 DescendOrigin(who) => W::descend_origin(who),
1214 ReportError(response_info) => W::report_error(&response_info),
1215 DepositAsset { assets, beneficiary } => W::deposit_asset(assets, beneficiary),
1216 DepositReserveAsset { assets, dest, xcm } => {
1217 W::deposit_reserve_asset(assets, dest, xcm)
1218 },
1219 ExchangeAsset { give, want, maximal } => W::exchange_asset(give, want, maximal),
1220 InitiateReserveWithdraw { assets, reserve, xcm } => {
1221 W::initiate_reserve_withdraw(assets, reserve, xcm)
1222 },
1223 InitiateTeleport { assets, dest, xcm } => W::initiate_teleport(assets, dest, xcm),
1224 ReportHolding { response_info, assets } => W::report_holding(&response_info, &assets),
1225 BuyExecution { fees, weight_limit } => W::buy_execution(fees, weight_limit),
1226 RefundSurplus => W::refund_surplus(),
1227 SetErrorHandler(xcm) => W::set_error_handler(xcm),
1228 SetAppendix(xcm) => W::set_appendix(xcm),
1229 ClearError => W::clear_error(),
1230 ClaimAsset { assets, ticket } => W::claim_asset(assets, ticket),
1231 Trap(code) => W::trap(code),
1232 SubscribeVersion { query_id, max_response_weight } => {
1233 W::subscribe_version(query_id, max_response_weight)
1234 },
1235 UnsubscribeVersion => W::unsubscribe_version(),
1236 BurnAsset(assets) => W::burn_asset(assets),
1237 ExpectAsset(assets) => W::expect_asset(assets),
1238 ExpectOrigin(origin) => W::expect_origin(origin),
1239 ExpectError(error) => W::expect_error(error),
1240 ExpectTransactStatus(transact_status) => W::expect_transact_status(transact_status),
1241 QueryPallet { module_name, response_info } => {
1242 W::query_pallet(module_name, response_info)
1243 },
1244 ExpectPallet { index, name, module_name, crate_major, min_crate_minor } => {
1245 W::expect_pallet(index, name, module_name, crate_major, min_crate_minor)
1246 },
1247 ReportTransactStatus(response_info) => W::report_transact_status(response_info),
1248 ClearTransactStatus => W::clear_transact_status(),
1249 UniversalOrigin(j) => W::universal_origin(j),
1250 ExportMessage { network, destination, xcm } => {
1251 W::export_message(network, destination, xcm)
1252 },
1253 LockAsset { asset, unlocker } => W::lock_asset(asset, unlocker),
1254 UnlockAsset { asset, target } => W::unlock_asset(asset, target),
1255 NoteUnlockable { asset, owner } => W::note_unlockable(asset, owner),
1256 RequestUnlock { asset, locker } => W::request_unlock(asset, locker),
1257 SetFeesMode { jit_withdraw } => W::set_fees_mode(jit_withdraw),
1258 SetTopic(topic) => W::set_topic(topic),
1259 ClearTopic => W::clear_topic(),
1260 AliasOrigin(location) => W::alias_origin(location),
1261 UnpaidExecution { weight_limit, check_origin } => {
1262 W::unpaid_execution(weight_limit, check_origin)
1263 },
1264 }
1265 }
1266}
1267
1268pub mod opaque {
1269 pub type Xcm = super::Xcm<()>;
1272
1273 pub type Instruction = super::Instruction<()>;
1276}
1277
1278impl<Call> TryFrom<OldXcm<Call>> for Xcm<Call> {
1280 type Error = ();
1281 fn try_from(old_xcm: OldXcm<Call>) -> result::Result<Self, Self::Error> {
1282 Ok(Xcm(old_xcm.0.into_iter().map(TryInto::try_into).collect::<result::Result<_, _>>()?))
1283 }
1284}
1285
1286impl<Call: Decode + GetDispatchInfo> TryFrom<NewXcm<Call>> for Xcm<Call> {
1288 type Error = ();
1289 fn try_from(new_xcm: NewXcm<Call>) -> result::Result<Self, Self::Error> {
1290 Ok(Xcm(new_xcm.0.into_iter().map(TryInto::try_into).collect::<result::Result<_, _>>()?))
1291 }
1292}
1293
1294impl<Call: Decode + GetDispatchInfo> TryFrom<NewInstruction<Call>> for Instruction<Call> {
1296 type Error = ();
1297 fn try_from(new_instruction: NewInstruction<Call>) -> result::Result<Self, Self::Error> {
1298 use NewInstruction::*;
1299 Ok(match new_instruction {
1300 WithdrawAsset(assets) => Self::WithdrawAsset(assets.try_into()?),
1301 ReserveAssetDeposited(assets) => Self::ReserveAssetDeposited(assets.try_into()?),
1302 ReceiveTeleportedAsset(assets) => Self::ReceiveTeleportedAsset(assets.try_into()?),
1303 QueryResponse { query_id, response, max_weight, querier: Some(querier) } => {
1304 Self::QueryResponse {
1305 query_id,
1306 querier: querier.try_into()?,
1307 response: response.try_into()?,
1308 max_weight,
1309 }
1310 },
1311 QueryResponse { query_id, response, max_weight, querier: None } => {
1312 Self::QueryResponse {
1313 query_id,
1314 querier: None,
1315 response: response.try_into()?,
1316 max_weight,
1317 }
1318 },
1319 TransferAsset { assets, beneficiary } => Self::TransferAsset {
1320 assets: assets.try_into()?,
1321 beneficiary: beneficiary.try_into()?,
1322 },
1323 TransferReserveAsset { assets, dest, xcm } => Self::TransferReserveAsset {
1324 assets: assets.try_into()?,
1325 dest: dest.try_into()?,
1326 xcm: xcm.try_into()?,
1327 },
1328 HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity } => {
1329 Self::HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity }
1330 },
1331 HrmpChannelAccepted { recipient } => Self::HrmpChannelAccepted { recipient },
1332 HrmpChannelClosing { initiator, sender, recipient } => {
1333 Self::HrmpChannelClosing { initiator, sender, recipient }
1334 },
1335 Transact { origin_kind, mut call, fallback_max_weight } => {
1336 let require_weight_at_most = match call.take_decoded() {
1339 Ok(decoded) => decoded.get_dispatch_info().call_weight,
1340 Err(error) => {
1341 let fallback_weight = fallback_max_weight.unwrap_or(Weight::MAX);
1342 tracing::debug!(
1343 target: "xcm::versions::v5Tov4",
1344 ?error,
1345 ?fallback_weight,
1346 "Couldn't decode call in Transact"
1347 );
1348 fallback_weight
1349 },
1350 };
1351 Self::Transact { origin_kind, require_weight_at_most, call: call.into() }
1352 },
1353 ReportError(response_info) => Self::ReportError(QueryResponseInfo {
1354 query_id: response_info.query_id,
1355 destination: response_info.destination.try_into().map_err(|_| ())?,
1356 max_weight: response_info.max_weight,
1357 }),
1358 DepositAsset { assets, beneficiary } => {
1359 let beneficiary = beneficiary.try_into()?;
1360 let assets = assets.try_into()?;
1361 Self::DepositAsset { assets, beneficiary }
1362 },
1363 DepositReserveAsset { assets, dest, xcm } => {
1364 let dest = dest.try_into()?;
1365 let xcm = xcm.try_into()?;
1366 let assets = assets.try_into()?;
1367 Self::DepositReserveAsset { assets, dest, xcm }
1368 },
1369 ExchangeAsset { give, want, maximal } => {
1370 let give = give.try_into()?;
1371 let want = want.try_into()?;
1372 Self::ExchangeAsset { give, want, maximal }
1373 },
1374 InitiateReserveWithdraw { assets, reserve, xcm } => {
1375 let assets = assets.try_into()?;
1377 let reserve = reserve.try_into()?;
1378 let xcm = xcm.try_into()?;
1379 Self::InitiateReserveWithdraw { assets, reserve, xcm }
1380 },
1381 InitiateTeleport { assets, dest, xcm } => {
1382 let assets = assets.try_into()?;
1384 let dest = dest.try_into()?;
1385 let xcm = xcm.try_into()?;
1386 Self::InitiateTeleport { assets, dest, xcm }
1387 },
1388 ReportHolding { response_info, assets } => {
1389 let response_info = QueryResponseInfo {
1390 destination: response_info.destination.try_into().map_err(|_| ())?,
1391 query_id: response_info.query_id,
1392 max_weight: response_info.max_weight,
1393 };
1394 Self::ReportHolding { response_info, assets: assets.try_into()? }
1395 },
1396 BuyExecution { fees, weight_limit } => {
1397 let fees = fees.try_into()?;
1398 let weight_limit = weight_limit.into();
1399 Self::BuyExecution { fees, weight_limit }
1400 },
1401 ClearOrigin => Self::ClearOrigin,
1402 DescendOrigin(who) => Self::DescendOrigin(who.try_into()?),
1403 RefundSurplus => Self::RefundSurplus,
1404 SetErrorHandler(xcm) => Self::SetErrorHandler(xcm.try_into()?),
1405 SetAppendix(xcm) => Self::SetAppendix(xcm.try_into()?),
1406 ClearError => Self::ClearError,
1407 ClaimAsset { assets, ticket } => {
1408 let assets = assets.try_into()?;
1409 let ticket = ticket.try_into()?;
1410 Self::ClaimAsset { assets, ticket }
1411 },
1412 Trap(code) => Self::Trap(code),
1413 SubscribeVersion { query_id, max_response_weight } => {
1414 Self::SubscribeVersion { query_id, max_response_weight }
1415 },
1416 UnsubscribeVersion => Self::UnsubscribeVersion,
1417 BurnAsset(assets) => Self::BurnAsset(assets.try_into()?),
1418 ExpectAsset(assets) => Self::ExpectAsset(assets.try_into()?),
1419 ExpectOrigin(maybe_origin) => {
1420 Self::ExpectOrigin(maybe_origin.map(|origin| origin.try_into()).transpose()?)
1421 },
1422 ExpectError(maybe_error) => Self::ExpectError(
1423 maybe_error
1424 .map(|(num, new_error)| (num, new_error.try_into()))
1425 .map(|(num, result)| result.map(|inner| (num, inner)))
1426 .transpose()?,
1427 ),
1428 ExpectTransactStatus(maybe_error_code) => Self::ExpectTransactStatus(maybe_error_code),
1429 QueryPallet { module_name, response_info } => {
1430 Self::QueryPallet { module_name, response_info: response_info.try_into()? }
1431 },
1432 ExpectPallet { index, name, module_name, crate_major, min_crate_minor } => {
1433 Self::ExpectPallet { index, name, module_name, crate_major, min_crate_minor }
1434 },
1435 ReportTransactStatus(response_info) => {
1436 Self::ReportTransactStatus(response_info.try_into()?)
1437 },
1438 ClearTransactStatus => Self::ClearTransactStatus,
1439 UniversalOrigin(junction) => Self::UniversalOrigin(junction.try_into()?),
1440 ExportMessage { network, destination, xcm } => Self::ExportMessage {
1441 network: network.into(),
1442 destination: destination.try_into()?,
1443 xcm: xcm.try_into()?,
1444 },
1445 LockAsset { asset, unlocker } => {
1446 Self::LockAsset { asset: asset.try_into()?, unlocker: unlocker.try_into()? }
1447 },
1448 UnlockAsset { asset, target } => {
1449 Self::UnlockAsset { asset: asset.try_into()?, target: target.try_into()? }
1450 },
1451 NoteUnlockable { asset, owner } => {
1452 Self::NoteUnlockable { asset: asset.try_into()?, owner: owner.try_into()? }
1453 },
1454 RequestUnlock { asset, locker } => {
1455 Self::RequestUnlock { asset: asset.try_into()?, locker: locker.try_into()? }
1456 },
1457 SetFeesMode { jit_withdraw } => Self::SetFeesMode { jit_withdraw },
1458 SetTopic(topic) => Self::SetTopic(topic),
1459 ClearTopic => Self::ClearTopic,
1460 AliasOrigin(location) => Self::AliasOrigin(location.try_into()?),
1461 UnpaidExecution { weight_limit, check_origin } => Self::UnpaidExecution {
1462 weight_limit,
1463 check_origin: check_origin.map(|origin| origin.try_into()).transpose()?,
1464 },
1465 InitiateTransfer { .. } |
1466 PayFees { .. } |
1467 SetHints { .. } |
1468 ExecuteWithOrigin { .. } => {
1469 tracing::debug!(target: "xcm::versions::v5tov4", ?new_instruction, "not supported by v4");
1470 return Err(());
1471 },
1472 })
1473 }
1474}
1475
1476impl<Call> TryFrom<OldInstruction<Call>> for Instruction<Call> {
1478 type Error = ();
1479 fn try_from(old_instruction: OldInstruction<Call>) -> result::Result<Self, Self::Error> {
1480 use OldInstruction::*;
1481 Ok(match old_instruction {
1482 WithdrawAsset(assets) => Self::WithdrawAsset(assets.try_into()?),
1483 ReserveAssetDeposited(assets) => Self::ReserveAssetDeposited(assets.try_into()?),
1484 ReceiveTeleportedAsset(assets) => Self::ReceiveTeleportedAsset(assets.try_into()?),
1485 QueryResponse { query_id, response, max_weight, querier: Some(querier) } => {
1486 Self::QueryResponse {
1487 query_id,
1488 querier: querier.try_into()?,
1489 response: response.try_into()?,
1490 max_weight,
1491 }
1492 },
1493 QueryResponse { query_id, response, max_weight, querier: None } => {
1494 Self::QueryResponse {
1495 query_id,
1496 querier: None,
1497 response: response.try_into()?,
1498 max_weight,
1499 }
1500 },
1501 TransferAsset { assets, beneficiary } => Self::TransferAsset {
1502 assets: assets.try_into()?,
1503 beneficiary: beneficiary.try_into()?,
1504 },
1505 TransferReserveAsset { assets, dest, xcm } => Self::TransferReserveAsset {
1506 assets: assets.try_into()?,
1507 dest: dest.try_into()?,
1508 xcm: xcm.try_into()?,
1509 },
1510 HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity } => {
1511 Self::HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity }
1512 },
1513 HrmpChannelAccepted { recipient } => Self::HrmpChannelAccepted { recipient },
1514 HrmpChannelClosing { initiator, sender, recipient } => {
1515 Self::HrmpChannelClosing { initiator, sender, recipient }
1516 },
1517 Transact { origin_kind, require_weight_at_most, call } => {
1518 Self::Transact { origin_kind, require_weight_at_most, call: call.into() }
1519 },
1520 ReportError(response_info) => Self::ReportError(QueryResponseInfo {
1521 query_id: response_info.query_id,
1522 destination: response_info.destination.try_into().map_err(|_| ())?,
1523 max_weight: response_info.max_weight,
1524 }),
1525 DepositAsset { assets, beneficiary } => {
1526 let beneficiary = beneficiary.try_into()?;
1527 let assets = assets.try_into()?;
1528 Self::DepositAsset { assets, beneficiary }
1529 },
1530 DepositReserveAsset { assets, dest, xcm } => {
1531 let dest = dest.try_into()?;
1532 let xcm = xcm.try_into()?;
1533 let assets = assets.try_into()?;
1534 Self::DepositReserveAsset { assets, dest, xcm }
1535 },
1536 ExchangeAsset { give, want, maximal } => {
1537 let give = give.try_into()?;
1538 let want = want.try_into()?;
1539 Self::ExchangeAsset { give, want, maximal }
1540 },
1541 InitiateReserveWithdraw { assets, reserve, xcm } => {
1542 let assets = assets.try_into()?;
1543 let reserve = reserve.try_into()?;
1544 let xcm = xcm.try_into()?;
1545 Self::InitiateReserveWithdraw { assets, reserve, xcm }
1546 },
1547 InitiateTeleport { assets, dest, xcm } => {
1548 let assets = assets.try_into()?;
1549 let dest = dest.try_into()?;
1550 let xcm = xcm.try_into()?;
1551 Self::InitiateTeleport { assets, dest, xcm }
1552 },
1553 ReportHolding { response_info, assets } => {
1554 let response_info = QueryResponseInfo {
1555 destination: response_info.destination.try_into().map_err(|_| ())?,
1556 query_id: response_info.query_id,
1557 max_weight: response_info.max_weight,
1558 };
1559 Self::ReportHolding { response_info, assets: assets.try_into()? }
1560 },
1561 BuyExecution { fees, weight_limit } => {
1562 let fees = fees.try_into()?;
1563 let weight_limit = weight_limit.into();
1564 Self::BuyExecution { fees, weight_limit }
1565 },
1566 ClearOrigin => Self::ClearOrigin,
1567 DescendOrigin(who) => Self::DescendOrigin(who.try_into()?),
1568 RefundSurplus => Self::RefundSurplus,
1569 SetErrorHandler(xcm) => Self::SetErrorHandler(xcm.try_into()?),
1570 SetAppendix(xcm) => Self::SetAppendix(xcm.try_into()?),
1571 ClearError => Self::ClearError,
1572 ClaimAsset { assets, ticket } => {
1573 let assets = assets.try_into()?;
1574 let ticket = ticket.try_into()?;
1575 Self::ClaimAsset { assets, ticket }
1576 },
1577 Trap(code) => Self::Trap(code),
1578 SubscribeVersion { query_id, max_response_weight } => {
1579 Self::SubscribeVersion { query_id, max_response_weight }
1580 },
1581 UnsubscribeVersion => Self::UnsubscribeVersion,
1582 BurnAsset(assets) => Self::BurnAsset(assets.try_into()?),
1583 ExpectAsset(assets) => Self::ExpectAsset(assets.try_into()?),
1584 ExpectOrigin(maybe_location) => Self::ExpectOrigin(
1585 maybe_location.map(|location| location.try_into()).transpose().map_err(|_| ())?,
1586 ),
1587 ExpectError(maybe_error) => Self::ExpectError(
1588 maybe_error.map(|error| error.try_into()).transpose().map_err(|_| ())?,
1589 ),
1590 ExpectTransactStatus(maybe_error_code) => Self::ExpectTransactStatus(maybe_error_code),
1591 QueryPallet { module_name, response_info } => Self::QueryPallet {
1592 module_name,
1593 response_info: response_info.try_into().map_err(|_| ())?,
1594 },
1595 ExpectPallet { index, name, module_name, crate_major, min_crate_minor } => {
1596 Self::ExpectPallet { index, name, module_name, crate_major, min_crate_minor }
1597 },
1598 ReportTransactStatus(response_info) => {
1599 Self::ReportTransactStatus(response_info.try_into().map_err(|_| ())?)
1600 },
1601 ClearTransactStatus => Self::ClearTransactStatus,
1602 UniversalOrigin(junction) => {
1603 Self::UniversalOrigin(junction.try_into().map_err(|_| ())?)
1604 },
1605 ExportMessage { network, destination, xcm } => Self::ExportMessage {
1606 network: network.into(),
1607 destination: destination.try_into().map_err(|_| ())?,
1608 xcm: xcm.try_into().map_err(|_| ())?,
1609 },
1610 LockAsset { asset, unlocker } => Self::LockAsset {
1611 asset: asset.try_into().map_err(|_| ())?,
1612 unlocker: unlocker.try_into().map_err(|_| ())?,
1613 },
1614 UnlockAsset { asset, target } => Self::UnlockAsset {
1615 asset: asset.try_into().map_err(|_| ())?,
1616 target: target.try_into().map_err(|_| ())?,
1617 },
1618 NoteUnlockable { asset, owner } => Self::NoteUnlockable {
1619 asset: asset.try_into().map_err(|_| ())?,
1620 owner: owner.try_into().map_err(|_| ())?,
1621 },
1622 RequestUnlock { asset, locker } => Self::RequestUnlock {
1623 asset: asset.try_into().map_err(|_| ())?,
1624 locker: locker.try_into().map_err(|_| ())?,
1625 },
1626 SetFeesMode { jit_withdraw } => Self::SetFeesMode { jit_withdraw },
1627 SetTopic(topic) => Self::SetTopic(topic),
1628 ClearTopic => Self::ClearTopic,
1629 AliasOrigin(location) => Self::AliasOrigin(location.try_into().map_err(|_| ())?),
1630 UnpaidExecution { weight_limit, check_origin } => Self::UnpaidExecution {
1631 weight_limit,
1632 check_origin: check_origin
1633 .map(|location| location.try_into())
1634 .transpose()
1635 .map_err(|_| ())?,
1636 },
1637 })
1638 }
1639}
1640
1641#[cfg(test)]
1642mod tests {
1643 use super::{prelude::*, *};
1644 use crate::{
1645 v3::{
1646 Junctions::Here as OldHere, MultiAssetFilter as OldMultiAssetFilter,
1647 WildMultiAsset as OldWildMultiAsset,
1648 },
1649 MAX_INSTRUCTIONS_TO_DECODE,
1650 };
1651
1652 #[test]
1653 fn basic_roundtrip_works() {
1654 let xcm = Xcm::<()>(vec![TransferAsset {
1655 assets: (Here, 1u128).into(),
1656 beneficiary: Here.into(),
1657 }]);
1658 let old_xcm = OldXcm::<()>(vec![OldInstruction::TransferAsset {
1659 assets: (OldHere, 1u128).into(),
1660 beneficiary: OldHere.into(),
1661 }]);
1662 assert_eq!(old_xcm, OldXcm::<()>::try_from(xcm.clone()).unwrap());
1663 let new_xcm: Xcm<()> = old_xcm.try_into().unwrap();
1664 assert_eq!(new_xcm, xcm);
1665 }
1666
1667 #[test]
1668 fn teleport_roundtrip_works() {
1669 let xcm = Xcm::<()>(vec![
1670 ReceiveTeleportedAsset((Here, 1u128).into()),
1671 ClearOrigin,
1672 DepositAsset { assets: Wild(AllCounted(1)), beneficiary: Here.into() },
1673 ]);
1674 let old_xcm: OldXcm<()> = OldXcm::<()>(vec![
1675 OldInstruction::ReceiveTeleportedAsset((OldHere, 1u128).into()),
1676 OldInstruction::ClearOrigin,
1677 OldInstruction::DepositAsset {
1678 assets: crate::v3::MultiAssetFilter::Wild(crate::v3::WildMultiAsset::AllCounted(1)),
1679 beneficiary: OldHere.into(),
1680 },
1681 ]);
1682 assert_eq!(old_xcm, OldXcm::<()>::try_from(xcm.clone()).unwrap());
1683 let new_xcm: Xcm<()> = old_xcm.try_into().unwrap();
1684 assert_eq!(new_xcm, xcm);
1685 }
1686
1687 #[test]
1688 fn reserve_deposit_roundtrip_works() {
1689 let xcm = Xcm::<()>(vec![
1690 ReserveAssetDeposited((Here, 1u128).into()),
1691 ClearOrigin,
1692 BuyExecution {
1693 fees: (Here, 1u128).into(),
1694 weight_limit: Some(Weight::from_parts(1, 1)).into(),
1695 },
1696 DepositAsset { assets: Wild(AllCounted(1)), beneficiary: Here.into() },
1697 ]);
1698 let old_xcm = OldXcm::<()>(vec![
1699 OldInstruction::ReserveAssetDeposited((OldHere, 1u128).into()),
1700 OldInstruction::ClearOrigin,
1701 OldInstruction::BuyExecution {
1702 fees: (OldHere, 1u128).into(),
1703 weight_limit: WeightLimit::Limited(Weight::from_parts(1, 1)),
1704 },
1705 OldInstruction::DepositAsset {
1706 assets: crate::v3::MultiAssetFilter::Wild(crate::v3::WildMultiAsset::AllCounted(1)),
1707 beneficiary: OldHere.into(),
1708 },
1709 ]);
1710 assert_eq!(old_xcm, OldXcm::<()>::try_from(xcm.clone()).unwrap());
1711 let new_xcm: Xcm<()> = old_xcm.try_into().unwrap();
1712 assert_eq!(new_xcm, xcm);
1713 }
1714
1715 #[test]
1716 fn deposit_asset_roundtrip_works() {
1717 let xcm = Xcm::<()>(vec![
1718 WithdrawAsset((Here, 1u128).into()),
1719 DepositAsset { assets: Wild(AllCounted(1)), beneficiary: Here.into() },
1720 ]);
1721 let old_xcm = OldXcm::<()>(vec![
1722 OldInstruction::WithdrawAsset((OldHere, 1u128).into()),
1723 OldInstruction::DepositAsset {
1724 assets: OldMultiAssetFilter::Wild(OldWildMultiAsset::AllCounted(1)),
1725 beneficiary: OldHere.into(),
1726 },
1727 ]);
1728 assert_eq!(old_xcm, OldXcm::<()>::try_from(xcm.clone()).unwrap());
1729 let new_xcm: Xcm<()> = old_xcm.try_into().unwrap();
1730 assert_eq!(new_xcm, xcm);
1731 }
1732
1733 #[test]
1734 fn deposit_reserve_asset_roundtrip_works() {
1735 let xcm = Xcm::<()>(vec![
1736 WithdrawAsset((Here, 1u128).into()),
1737 DepositReserveAsset {
1738 assets: Wild(AllCounted(1)),
1739 dest: Here.into(),
1740 xcm: Xcm::<()>(vec![]),
1741 },
1742 ]);
1743 let old_xcm = OldXcm::<()>(vec![
1744 OldInstruction::WithdrawAsset((OldHere, 1u128).into()),
1745 OldInstruction::DepositReserveAsset {
1746 assets: OldMultiAssetFilter::Wild(OldWildMultiAsset::AllCounted(1)),
1747 dest: OldHere.into(),
1748 xcm: OldXcm::<()>(vec![]),
1749 },
1750 ]);
1751 assert_eq!(old_xcm, OldXcm::<()>::try_from(xcm.clone()).unwrap());
1752 let new_xcm: Xcm<()> = old_xcm.try_into().unwrap();
1753 assert_eq!(new_xcm, xcm);
1754 }
1755
1756 #[test]
1757 fn decoding_respects_limit() {
1758 let max_xcm = Xcm::<()>(vec![ClearOrigin; MAX_INSTRUCTIONS_TO_DECODE as usize]);
1759 let encoded = max_xcm.encode();
1760 assert!(Xcm::<()>::decode(&mut &encoded[..]).is_ok());
1761
1762 let big_xcm = Xcm::<()>(vec![ClearOrigin; MAX_INSTRUCTIONS_TO_DECODE as usize + 1]);
1763 let encoded = big_xcm.encode();
1764 assert!(Xcm::<()>::decode(&mut &encoded[..]).is_err());
1765
1766 let nested_xcm = Xcm::<()>(vec![
1767 DepositReserveAsset {
1768 assets: All.into(),
1769 dest: Here.into(),
1770 xcm: max_xcm,
1771 };
1772 (MAX_INSTRUCTIONS_TO_DECODE / 2) as usize
1773 ]);
1774 let encoded = nested_xcm.encode();
1775 assert!(Xcm::<()>::decode(&mut &encoded[..]).is_err());
1776
1777 let even_more_nested_xcm = Xcm::<()>(vec![SetAppendix(nested_xcm); 64]);
1778 let encoded = even_more_nested_xcm.encode();
1779 assert_eq!(encoded.len(), 342530);
1780 assert_eq!(MAX_INSTRUCTIONS_TO_DECODE, 100, "precondition");
1782 assert!(Xcm::<()>::decode(&mut &encoded[..]).is_err());
1783 }
1784}