@@ -20,7 +20,35 @@ use parity_scale_codec::{Decode, Encode};
20
20
use precompile_utils:: prelude:: * ;
21
21
use sp_core:: { H256 , U256 } ;
22
22
use sp_std:: vec:: Vec ;
23
- use xcm:: VersionedLocation ;
23
+
24
+ // The Polkadot-sdk removed support for XCM Location V1, but the GMP precompile still needs to support it,
25
+ // so we have to wrap VersionedLocation to re-add support for XCM Location V1.
26
+ #[ derive( Encode , Decode , Debug ) ]
27
+ pub enum VersionedLocation {
28
+ #[ codec( index = 1 ) ] // v2 is same as v1 and therefore re-using the v1 index
29
+ V2 ( deprecated_xcm_v2:: MultiLocationV2 ) ,
30
+ #[ codec( index = 3 ) ]
31
+ V3 ( xcm:: v3:: MultiLocation ) ,
32
+ #[ codec( index = 4 ) ]
33
+ V4 ( xcm:: v4:: Location ) ,
34
+ #[ codec( index = 5 ) ]
35
+ V5 ( xcm:: v5:: Location ) ,
36
+ }
37
+
38
+ impl TryFrom < VersionedLocation > for xcm:: latest:: Location {
39
+ type Error = ( ) ;
40
+
41
+ fn try_from ( value : VersionedLocation ) -> Result < Self , Self :: Error > {
42
+ match value {
43
+ VersionedLocation :: V2 ( location) => {
44
+ xcm:: VersionedLocation :: V3 ( location. try_into ( ) ?) . try_into ( )
45
+ }
46
+ VersionedLocation :: V3 ( location) => xcm:: VersionedLocation :: V3 ( location) . try_into ( ) ,
47
+ VersionedLocation :: V4 ( location) => xcm:: VersionedLocation :: V4 ( location) . try_into ( ) ,
48
+ VersionedLocation :: V5 ( location) => xcm:: VersionedLocation :: V5 ( location) . try_into ( ) ,
49
+ }
50
+ }
51
+ }
24
52
25
53
// A user action which will attempt to route the transferred assets to the account/chain specified
26
54
// by the given Location. Recall that a Location can contain both a chain and an account
@@ -91,3 +119,254 @@ pub struct WormholeTransferWithPayloadData {
91
119
pub from_address : H256 ,
92
120
pub payload : BoundedBytes < crate :: GetCallDataLimit > ,
93
121
}
122
+
123
+ /// Reimplement the deprecated xcm v2 Location types to allow for backwards compatibility
124
+ mod deprecated_xcm_v2 {
125
+ use super :: * ;
126
+
127
+ #[ derive( Clone , Eq , PartialEq , Ord , PartialOrd , Encode , Decode , Debug ) ]
128
+ pub struct MultiLocationV2 {
129
+ pub parents : u8 ,
130
+ pub interior : JunctionsV2 ,
131
+ }
132
+
133
+ impl TryFrom < MultiLocationV2 > for xcm:: v3:: MultiLocation {
134
+ type Error = ( ) ;
135
+
136
+ fn try_from ( value : MultiLocationV2 ) -> Result < Self , Self :: Error > {
137
+ Ok ( xcm:: v3:: MultiLocation :: new (
138
+ value. parents ,
139
+ xcm:: v3:: Junctions :: try_from ( value. interior ) ?,
140
+ ) )
141
+ }
142
+ }
143
+
144
+ #[ derive( Clone , Eq , PartialEq , Ord , PartialOrd , Encode , Decode , Debug ) ]
145
+ pub enum JunctionsV2 {
146
+ /// The interpreting consensus system.
147
+ Here ,
148
+ /// A relative path comprising 1 junction.
149
+ X1 ( JunctionV2 ) ,
150
+ /// A relative path comprising 2 junctions.
151
+ X2 ( JunctionV2 , JunctionV2 ) ,
152
+ /// A relative path comprising 3 junctions.
153
+ X3 ( JunctionV2 , JunctionV2 , JunctionV2 ) ,
154
+ /// A relative path comprising 4 junctions.
155
+ X4 ( JunctionV2 , JunctionV2 , JunctionV2 , JunctionV2 ) ,
156
+ /// A relative path comprising 5 junctions.
157
+ X5 ( JunctionV2 , JunctionV2 , JunctionV2 , JunctionV2 , JunctionV2 ) ,
158
+ /// A relative path comprising 6 junctions.
159
+ X6 (
160
+ JunctionV2 ,
161
+ JunctionV2 ,
162
+ JunctionV2 ,
163
+ JunctionV2 ,
164
+ JunctionV2 ,
165
+ JunctionV2 ,
166
+ ) ,
167
+ /// A relative path comprising 7 junctions.
168
+ X7 (
169
+ JunctionV2 ,
170
+ JunctionV2 ,
171
+ JunctionV2 ,
172
+ JunctionV2 ,
173
+ JunctionV2 ,
174
+ JunctionV2 ,
175
+ JunctionV2 ,
176
+ ) ,
177
+ /// A relative path comprising 8 junctions.
178
+ X8 (
179
+ JunctionV2 ,
180
+ JunctionV2 ,
181
+ JunctionV2 ,
182
+ JunctionV2 ,
183
+ JunctionV2 ,
184
+ JunctionV2 ,
185
+ JunctionV2 ,
186
+ JunctionV2 ,
187
+ ) ,
188
+ }
189
+
190
+ impl TryFrom < JunctionsV2 > for xcm:: v3:: Junctions {
191
+ type Error = ( ) ;
192
+
193
+ fn try_from ( value : JunctionsV2 ) -> Result < Self , Self :: Error > {
194
+ use JunctionsV2 :: * ;
195
+ Ok ( match value {
196
+ Here => Self :: Here ,
197
+ X1 ( j1) => Self :: X1 ( j1. try_into ( ) ?) ,
198
+ X2 ( j1, j2) => Self :: X2 ( j1. try_into ( ) ?, j2. try_into ( ) ?) ,
199
+ X3 ( j1, j2, j3) => Self :: X3 ( j1. try_into ( ) ?, j2. try_into ( ) ?, j3. try_into ( ) ?) ,
200
+ X4 ( j1, j2, j3, j4) => Self :: X4 (
201
+ j1. try_into ( ) ?,
202
+ j2. try_into ( ) ?,
203
+ j3. try_into ( ) ?,
204
+ j4. try_into ( ) ?,
205
+ ) ,
206
+ X5 ( j1, j2, j3, j4, j5) => Self :: X5 (
207
+ j1. try_into ( ) ?,
208
+ j2. try_into ( ) ?,
209
+ j3. try_into ( ) ?,
210
+ j4. try_into ( ) ?,
211
+ j5. try_into ( ) ?,
212
+ ) ,
213
+ X6 ( j1, j2, j3, j4, j5, j6) => Self :: X6 (
214
+ j1. try_into ( ) ?,
215
+ j2. try_into ( ) ?,
216
+ j3. try_into ( ) ?,
217
+ j4. try_into ( ) ?,
218
+ j5. try_into ( ) ?,
219
+ j6. try_into ( ) ?,
220
+ ) ,
221
+ X7 ( j1, j2, j3, j4, j5, j6, j7) => Self :: X7 (
222
+ j1. try_into ( ) ?,
223
+ j2. try_into ( ) ?,
224
+ j3. try_into ( ) ?,
225
+ j4. try_into ( ) ?,
226
+ j5. try_into ( ) ?,
227
+ j6. try_into ( ) ?,
228
+ j7. try_into ( ) ?,
229
+ ) ,
230
+ X8 ( j1, j2, j3, j4, j5, j6, j7, j8) => Self :: X8 (
231
+ j1. try_into ( ) ?,
232
+ j2. try_into ( ) ?,
233
+ j3. try_into ( ) ?,
234
+ j4. try_into ( ) ?,
235
+ j5. try_into ( ) ?,
236
+ j6. try_into ( ) ?,
237
+ j7. try_into ( ) ?,
238
+ j8. try_into ( ) ?,
239
+ ) ,
240
+ } )
241
+ }
242
+ }
243
+
244
+ #[ derive( Clone , Eq , PartialEq , Ord , PartialOrd , Encode , Decode , Debug ) ]
245
+ pub enum JunctionV2 {
246
+ /// An indexed parachain belonging to and operated by the context.
247
+ ///
248
+ /// Generally used when the context is a Polkadot Relay-chain.
249
+ Parachain ( #[ codec( compact) ] u32 ) ,
250
+ /// A 32-byte identifier for an account of a specific network that is respected as a sovereign
251
+ /// endpoint within the context.
252
+ ///
253
+ /// Generally used when the context is a Substrate-based chain.
254
+ AccountId32 { network : NetworkIdV2 , id : [ u8 ; 32 ] } ,
255
+ /// An 8-byte index for an account of a specific network that is respected as a sovereign
256
+ /// endpoint within the context.
257
+ ///
258
+ /// May be used when the context is a Frame-based chain and includes e.g. an indices pallet.
259
+ AccountIndex64 {
260
+ network : NetworkIdV2 ,
261
+ #[ codec( compact) ]
262
+ index : u64 ,
263
+ } ,
264
+ /// A 20-byte identifier for an account of a specific network that is respected as a sovereign
265
+ /// endpoint within the context.
266
+ ///
267
+ /// May be used when the context is an Ethereum or Bitcoin chain or smart-contract.
268
+ AccountKey20 { network : NetworkIdV2 , key : [ u8 ; 20 ] } ,
269
+ /// An instanced, indexed pallet that forms a constituent part of the context.
270
+ ///
271
+ /// Generally used when the context is a Frame-based chain.
272
+ PalletInstance ( u8 ) ,
273
+ /// A non-descript index within the context location.
274
+ ///
275
+ /// Usage will vary widely owing to its generality.
276
+ ///
277
+ /// NOTE: Try to avoid using this and instead use a more specific item.
278
+ GeneralIndex ( #[ codec( compact) ] u128 ) ,
279
+ /// A nondescript datum acting as a key within the context location.
280
+ ///
281
+ /// Usage will vary widely owing to its generality.
282
+ ///
283
+ /// NOTE: Try to avoid using this and instead use a more specific item.
284
+ GeneralKey ( sp_runtime:: WeakBoundedVec < u8 , sp_core:: ConstU32 < 32 > > ) ,
285
+ /// The unambiguous child.
286
+ ///
287
+ /// Not currently used except as a fallback when deriving ancestry.
288
+ OnlyChild ,
289
+ // The GMP precompile doesn't need to support Plurality Junction
290
+ //Plurality { id: BodyId, part: BodyPart },
291
+ }
292
+
293
+ impl TryFrom < JunctionV2 > for xcm:: v3:: Junction {
294
+ type Error = ( ) ;
295
+
296
+ fn try_from ( value : JunctionV2 ) -> Result < Self , ( ) > {
297
+ use JunctionV2 :: * ;
298
+ Ok ( match value {
299
+ Parachain ( id) => Self :: Parachain ( id) ,
300
+ AccountId32 { network, id } => Self :: AccountId32 {
301
+ network : network. into ( ) ,
302
+ id,
303
+ } ,
304
+ AccountIndex64 { network, index } => Self :: AccountIndex64 {
305
+ network : network. into ( ) ,
306
+ index,
307
+ } ,
308
+ AccountKey20 { network, key } => Self :: AccountKey20 {
309
+ network : network. into ( ) ,
310
+ key,
311
+ } ,
312
+ PalletInstance ( index) => Self :: PalletInstance ( index) ,
313
+ GeneralIndex ( id) => Self :: GeneralIndex ( id) ,
314
+ GeneralKey ( key) => match key. len ( ) {
315
+ len @ 0 ..=32 => Self :: GeneralKey {
316
+ length : len as u8 ,
317
+ data : {
318
+ let mut data = [ 0u8 ; 32 ] ;
319
+ data[ ..len] . copy_from_slice ( & key[ ..] ) ;
320
+ data
321
+ } ,
322
+ } ,
323
+ _ => return Err ( ( ) ) ,
324
+ } ,
325
+ OnlyChild => Self :: OnlyChild ,
326
+ } )
327
+ }
328
+ }
329
+
330
+ #[ derive( Clone , Eq , PartialEq , Ord , PartialOrd , Encode , Decode , Debug ) ]
331
+ pub enum NetworkIdV2 {
332
+ /// Unidentified/any.
333
+ Any ,
334
+ /// Some named network.
335
+ Named ( sp_runtime:: WeakBoundedVec < u8 , sp_core:: ConstU32 < 32 > > ) ,
336
+ /// The Polkadot Relay chain
337
+ Polkadot ,
338
+ /// Kusama.
339
+ Kusama ,
340
+ }
341
+
342
+ impl From < NetworkIdV2 > for Option < xcm:: v3:: NetworkId > {
343
+ fn from ( old : NetworkIdV2 ) -> Option < xcm:: v3:: NetworkId > {
344
+ use NetworkIdV2 :: * ;
345
+ match old {
346
+ Any => None ,
347
+ Named ( _) => None ,
348
+ Polkadot => Some ( xcm:: v3:: NetworkId :: Polkadot ) ,
349
+ Kusama => Some ( xcm:: v3:: NetworkId :: Kusama ) ,
350
+ }
351
+ }
352
+ }
353
+ }
354
+
355
+ #[ cfg( test) ]
356
+ mod tests {
357
+ use super :: * ;
358
+
359
+ #[ test]
360
+ fn test_versioned_user_action_decode ( ) {
361
+ // Encoded payload from this wormhole transfer:
362
+ // https://wormholescan.io/#/tx/0x7a6985578742291842d25d80091cb8661f9ebf9301b266d6d4cd324758310569?view=advanced
363
+ let encoded_payload = hex:: decode (
364
+ "0001010200c91f0100c862582c20ec0a5429c6d2239da9908f4b6c93ab4e2589784f8a5452f65f0e45" ,
365
+ )
366
+ . unwrap ( ) ;
367
+
368
+ // Ensure we can decode the VersionedUserAction
369
+ let _versioned_user_action = VersionedUserAction :: decode ( & mut & encoded_payload[ ..] )
370
+ . expect ( "Failed to decode VersionedUserAction" ) ;
371
+ }
372
+ }
0 commit comments