1
// Copyright 2019-2025 PureStake Inc.
2
// This file is part of Moonbeam.
3

            
4
// Moonbeam 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
// Moonbeam 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 Moonbeam.  If not, see <http://www.gnu.org/licenses/>.
16
use crate::mock::{
17
	AssetAddress, ExtBuilder, PCallV1, PCallV2, PCallV3, Precompiles, PrecompilesValue, Runtime,
18
	RuntimeOrigin, TransactorV1, TransactorV2, TransactorV3, XcmTransactor,
19
};
20

            
21
use frame_support::{assert_ok, weights::Weight};
22
use precompile_utils::{prelude::*, testing::*};
23
use sp_core::H160;
24
use sp_std::boxed::Box;
25
use xcm::latest::Location;
26

            
27
26
fn precompiles() -> Precompiles<Runtime> {
28
26
	PrecompilesValue::get()
29
26
}
30

            
31
#[test]
32
1
fn selectors() {
33
1
	assert!(PCallV1::index_to_account_selectors().contains(&0x3fdc4f36));
34
1
	assert!(PCallV1::transact_info_selectors().contains(&0xd07d87c3));
35
1
	assert!(PCallV1::transact_info_with_signed_selectors().contains(&0xb689e20c));
36
1
	assert!(PCallV1::fee_per_second_selectors().contains(&0x906c9990));
37
1
	assert!(PCallV1::transact_through_derivative_multilocation_selectors().contains(&0x94a63c54));
38
1
	assert!(PCallV1::transact_through_derivative_selectors().contains(&0x02ae072d));
39
1
	assert!(PCallV1::transact_through_signed_multilocation_selectors().contains(&0x71d31587));
40
1
	assert!(PCallV1::transact_through_signed_selectors().contains(&0x42ca339d));
41

            
42
1
	assert!(PCallV2::index_to_account_selectors().contains(&0x3fdc4f36));
43
1
	assert!(PCallV2::transact_info_with_signed_selectors().contains(&0xb689e20c));
44
1
	assert!(PCallV2::fee_per_second_selectors().contains(&0x906c9990));
45
1
	assert!(PCallV2::transact_through_derivative_multilocation_selectors().contains(&0xfe430475));
46
1
	assert!(PCallV2::transact_through_derivative_selectors().contains(&0x185de2ae));
47
1
	assert!(PCallV2::transact_through_signed_multilocation_selectors().contains(&0xd7ab340c));
48
1
	assert!(PCallV2::transact_through_signed_selectors().contains(&0xb648f3fe));
49

            
50
1
	assert!(PCallV3::index_to_account_selectors().contains(&0x3fdc4f36));
51
1
	assert!(PCallV3::transact_info_with_signed_selectors().contains(&0xb689e20c));
52
1
	assert!(PCallV3::fee_per_second_selectors().contains(&0x906c9990));
53
1
	assert!(PCallV3::transact_through_derivative_multilocation_selectors().contains(&0xbdacc26b));
54
1
	assert!(PCallV3::transact_through_derivative_selectors().contains(&0xca8c82d8));
55
1
	assert!(PCallV3::transact_through_signed_multilocation_selectors().contains(&0x27b1d492));
56
1
	assert!(PCallV3::transact_through_signed_selectors().contains(&0xb18270cf));
57
1
}
58

            
59
#[test]
60
1
fn modifiers() {
61
1
	ExtBuilder::default().build().execute_with(|| {
62
1
		let mut tester = PrecompilesModifierTester::new(precompiles(), Alice, TransactorV1);
63
1

            
64
1
		tester.test_view_modifier(PCallV1::index_to_account_selectors());
65
1
		tester.test_view_modifier(PCallV1::transact_info_selectors());
66
1
		tester.test_view_modifier(PCallV1::transact_info_with_signed_selectors());
67
1
		tester.test_view_modifier(PCallV1::fee_per_second_selectors());
68
1
		tester
69
1
			.test_default_modifier(PCallV1::transact_through_derivative_multilocation_selectors());
70
1
		tester.test_default_modifier(PCallV1::transact_through_derivative_selectors());
71
1
		tester.test_default_modifier(PCallV1::transact_through_signed_multilocation_selectors());
72
1
		tester.test_default_modifier(PCallV1::transact_through_signed_selectors());
73
1

            
74
1
		let mut tester = PrecompilesModifierTester::new(precompiles(), Alice, TransactorV2);
75
1

            
76
1
		tester.test_view_modifier(PCallV2::index_to_account_selectors());
77
1
		tester.test_view_modifier(PCallV2::transact_info_with_signed_selectors());
78
1
		tester.test_view_modifier(PCallV2::fee_per_second_selectors());
79
1
		tester
80
1
			.test_default_modifier(PCallV2::transact_through_derivative_multilocation_selectors());
81
1
		tester.test_default_modifier(PCallV2::transact_through_derivative_selectors());
82
1
		tester.test_default_modifier(PCallV2::transact_through_signed_multilocation_selectors());
83
1
		tester.test_default_modifier(PCallV2::transact_through_signed_selectors());
84
1
	});
85
1
}
86

            
87
#[test]
88
1
fn selector_less_than_four_bytes() {
89
1
	ExtBuilder::default().build().execute_with(|| {
90
1
		precompiles()
91
1
			.prepare_test(Alice, TransactorV1, vec![1u8, 2u8, 3u8])
92
1
			.execute_reverts(|output| output == b"Tried to read selector out of bounds");
93
1
	});
94
1
}
95

            
96
#[test]
97
1
fn no_selector_exists_but_length_is_right() {
98
1
	ExtBuilder::default().build().execute_with(|| {
99
1
		precompiles()
100
1
			.prepare_test(Alice, TransactorV1, vec![1u8, 2u8, 3u8, 4u8])
101
1
			.execute_reverts(|output| output == b"Unknown selector");
102
1
	});
103
1
}
104

            
105
#[test]
106
1
fn take_index_for_account() {
107
1
	ExtBuilder::default()
108
1
		.with_balances(vec![(Alice.into(), 1000)])
109
1
		.build()
110
1
		.execute_with(|| {
111
1
			let input: Vec<_> = PCallV1::index_to_account { index: 0 }.into();
112
1

            
113
1
			// Assert that errors since no index is assigned
114
1
			precompiles()
115
1
				.prepare_test(Alice, TransactorV1, input.clone())
116
1
				.execute_reverts(|output| output == b"No index assigned");
117
1

            
118
1
			// register index
119
1
			assert_ok!(XcmTransactor::register(
120
1
				RuntimeOrigin::root(),
121
1
				Alice.into(),
122
1
				0
123
1
			));
124

            
125
			// Expected result is zero
126
1
			precompiles()
127
1
				.prepare_test(Alice, TransactorV1, input)
128
1
				.expect_cost(2)
129
1
				.expect_no_logs()
130
1
				.execute_returns(Address(H160::from(Alice)));
131
1
		});
132
1
}
133

            
134
#[test]
135
1
fn take_transact_info() {
136
1
	ExtBuilder::default()
137
1
		.with_balances(vec![(Alice.into(), 1000)])
138
1
		.build()
139
1
		.execute_with(|| {
140
1
			let input: Vec<_> = PCallV1::transact_info {
141
1
				location: Location::parent().into(),
142
1
			}
143
1
			.into();
144
1

            
145
1
			// Assert that errors since no index is assigned
146
1
			precompiles()
147
1
				.prepare_test(Alice, TransactorV1, input.clone())
148
1
				.execute_reverts(|output| output == b"Transact Info not set");
149
1

            
150
1
			// Root can set transact info
151
1
			assert_ok!(XcmTransactor::set_transact_info(
152
1
				RuntimeOrigin::root(),
153
1
				Box::new(xcm::VersionedLocation::from(Location::parent())),
154
1
				Weight::zero(),
155
1
				10000u64.into(),
156
1
				None
157
1
			));
158

            
159
			// Root can set transact info
160
1
			assert_ok!(XcmTransactor::set_fee_per_second(
161
1
				RuntimeOrigin::root(),
162
1
				Box::new(xcm::VersionedLocation::from(Location::parent())),
163
1
				1
164
1
			));
165

            
166
1
			precompiles()
167
1
				.prepare_test(Alice, TransactorV1, input)
168
1
				.expect_cost(3)
169
1
				.expect_no_logs()
170
1
				.execute_returns((0u64, 1u128, 10000u64));
171
1
		});
172
1
}
173
#[test]
174
1
fn take_transact_info_with_signed() {
175
1
	ExtBuilder::default()
176
1
		.with_balances(vec![(Alice.into(), 1000)])
177
1
		.build()
178
1
		.execute_with(|| {
179
1
			let input: Vec<_> = PCallV1::transact_info_with_signed {
180
1
				location: Location::parent().into(),
181
1
			}
182
1
			.into();
183
1

            
184
1
			// Assert that errors since no index is assigned
185
1
			precompiles()
186
1
				.prepare_test(Alice, TransactorV1, input.clone())
187
1
				.execute_reverts(|output| output == b"Transact Info not set");
188
1

            
189
1
			// Root can set transact info
190
1
			assert_ok!(XcmTransactor::set_transact_info(
191
1
				RuntimeOrigin::root(),
192
1
				Box::new(xcm::VersionedLocation::from(Location::parent())),
193
1
				Weight::zero(),
194
1
				10000u64.into(),
195
1
				Some(1.into())
196
1
			));
197

            
198
			// Root can set fee per second
199
1
			assert_ok!(XcmTransactor::set_fee_per_second(
200
1
				RuntimeOrigin::root(),
201
1
				Box::new(xcm::VersionedLocation::from(Location::parent())),
202
1
				1
203
1
			));
204

            
205
1
			precompiles()
206
1
				.prepare_test(Alice, TransactorV1, input)
207
1
				.expect_cost(2)
208
1
				.expect_no_logs()
209
1
				.execute_returns((0u64, 1u128, 10_000u64));
210
1
		});
211
1
}
212

            
213
#[test]
214
1
fn take_fee_per_second() {
215
1
	ExtBuilder::default()
216
1
		.with_balances(vec![(Alice.into(), 1000)])
217
1
		.build()
218
1
		.execute_with(|| {
219
1
			let input: Vec<_> = PCallV1::fee_per_second {
220
1
				location: Location::parent().into(),
221
1
			}
222
1
			.into();
223
1

            
224
1
			// Assert that errors
225
1
			precompiles()
226
1
				.prepare_test(Alice, TransactorV1, input.clone())
227
1
				.execute_reverts(|output| output == b"Fee Per Second not set");
228
1

            
229
1
			// Root can set fee per secnd
230
1
			assert_ok!(XcmTransactor::set_fee_per_second(
231
1
				RuntimeOrigin::root(),
232
1
				Box::new(xcm::VersionedLocation::from(Location::parent())),
233
1
				1
234
1
			));
235
1
			precompiles()
236
1
				.prepare_test(Alice, TransactorV1, input)
237
1
				.expect_cost(2)
238
1
				.expect_no_logs()
239
1
				.execute_returns(1u64);
240
1
		});
241
1
}
242

            
243
#[test]
244
1
fn test_transact_derivative_multilocation_v2() {
245
1
	ExtBuilder::default()
246
1
		.with_balances(vec![(Alice.into(), 1000)])
247
1
		.build()
248
1
		.execute_with(|| {
249
1
			// register index
250
1
			assert_ok!(XcmTransactor::register(
251
1
				RuntimeOrigin::root(),
252
1
				Alice.into(),
253
1
				0
254
1
			));
255

            
256
			// we pay with our current self reserve.
257
1
			let fee_payer_asset = Location::parent().into();
258
1

            
259
1
			let bytes = vec![1u8, 2u8, 3u8];
260
1

            
261
1
			let total_weight = 1_000_000_000u64;
262
1
			// We are transferring asset 0, which we have instructed to be the relay asset
263
1
			precompiles()
264
1
				.prepare_test(
265
1
					Alice,
266
1
					TransactorV2,
267
1
					PCallV2::transact_through_derivative_multilocation {
268
1
						transactor: 0,
269
1
						index: 0,
270
1
						fee_asset: fee_payer_asset,
271
1
						weight: 4000000,
272
1
						inner_call: bytes.into(),
273
1
						fee_amount: u128::from(total_weight).into(),
274
1
						overall_weight: total_weight,
275
1
					},
276
1
				)
277
1
				.expect_cost(188253001)
278
1
				.expect_no_logs()
279
1
				.execute_returns(());
280
1
		});
281
1
}
282

            
283
#[test]
284
1
fn test_transact_derivative_multilocation_v3() {
285
1
	ExtBuilder::default()
286
1
		.with_balances(vec![(Alice.into(), 1000)])
287
1
		.build()
288
1
		.execute_with(|| {
289
1
			// register index
290
1
			assert_ok!(XcmTransactor::register(
291
1
				RuntimeOrigin::root(),
292
1
				Alice.into(),
293
1
				0
294
1
			));
295

            
296
			// we pay with our current self reserve.
297
1
			let fee_payer_asset = Location::parent();
298
1

            
299
1
			let bytes = vec![1u8, 2u8, 3u8];
300
1

            
301
1
			//let total_weight = 1_000_000_000u64;
302
1
			let total_weight = Weight::from_parts(1_000_000_000u64, 82_000u64);
303
1
			let require_weight_at_most = Weight::from_parts(4_000_000u64, 82_000u64);
304
1
			// We are transferring asset 0, which we have instructed to be the relay asset
305
1
			precompiles()
306
1
				.prepare_test(
307
1
					Alice,
308
1
					TransactorV3,
309
1
					PCallV3::transact_through_derivative_multilocation {
310
1
						transactor: 0,
311
1
						index: 0,
312
1
						fee_asset: fee_payer_asset,
313
1
						weight: require_weight_at_most,
314
1
						inner_call: bytes.into(),
315
1
						fee_amount: u128::from(total_weight.ref_time()).into(),
316
1
						overall_weight: total_weight,
317
1
						refund: false,
318
1
					},
319
1
				)
320
1
				.expect_cost(188253001)
321
1
				.expect_no_logs()
322
1
				.execute_returns(());
323
1
		});
324
1
}
325

            
326
#[test]
327
1
fn take_transact_info_with_signed_v3() {
328
1
	ExtBuilder::default()
329
1
		.with_balances(vec![(Alice.into(), 1000)])
330
1
		.build()
331
1
		.execute_with(|| {
332
1
			let input: Vec<_> = PCallV3::transact_info_with_signed {
333
1
				location: Location::parent(),
334
1
			}
335
1
			.into();
336
1

            
337
1
			// Assert that errors since no index is assigned
338
1
			precompiles()
339
1
				.prepare_test(Alice, TransactorV3, input.clone())
340
1
				.execute_reverts(|output| output == b"Transact Info not set");
341
1

            
342
1
			// Root can set transact info
343
1
			assert_ok!(XcmTransactor::set_transact_info(
344
1
				RuntimeOrigin::root(),
345
1
				Box::new(xcm::VersionedLocation::from(Location::parent())),
346
1
				Weight::zero(),
347
1
				10000u64.into(),
348
1
				Some(1.into())
349
1
			));
350

            
351
			// Root can set fee per second
352
1
			assert_ok!(XcmTransactor::set_fee_per_second(
353
1
				RuntimeOrigin::root(),
354
1
				Box::new(xcm::VersionedLocation::from(Location::parent())),
355
1
				1
356
1
			));
357

            
358
1
			let expected_max_weight: Weight = 10_000u64.into();
359
1
			let expected_transact_extra_weight_signed: Weight = 1u64.into();
360
1
			let expected_transact_extra_weight: Weight = 0u64.into();
361
1

            
362
1
			precompiles()
363
1
				.prepare_test(Alice, TransactorV3, input)
364
1
				.expect_cost(2)
365
1
				.expect_no_logs()
366
1
				.execute_returns((
367
1
					expected_transact_extra_weight,
368
1
					expected_transact_extra_weight_signed,
369
1
					expected_max_weight,
370
1
				));
371
1
		});
372
1
}
373

            
374
#[test]
375
1
fn test_transact_derivative_multilocation() {
376
1
	ExtBuilder::default()
377
1
		.with_balances(vec![(Alice.into(), 1000)])
378
1
		.build()
379
1
		.execute_with(|| {
380
1
			// register index
381
1
			assert_ok!(XcmTransactor::register(
382
1
				RuntimeOrigin::root(),
383
1
				Alice.into(),
384
1
				0
385
1
			));
386

            
387
			// Root can set transact info
388
1
			assert_ok!(XcmTransactor::set_transact_info(
389
1
				RuntimeOrigin::root(),
390
1
				Box::new(xcm::VersionedLocation::from(Location::parent())),
391
1
				Weight::zero(),
392
1
				10000000.into(),
393
1
				None
394
1
			));
395

            
396
			// Root can set transact info
397
1
			assert_ok!(XcmTransactor::set_fee_per_second(
398
1
				RuntimeOrigin::root(),
399
1
				Box::new(xcm::VersionedLocation::from(Location::parent())),
400
1
				1
401
1
			));
402

            
403
			// we pay with our current self reserve.
404
1
			let fee_payer_asset = Location::parent().into();
405
1

            
406
1
			let bytes = vec![1u8, 2u8, 3u8];
407
1

            
408
1
			// We are transferring asset 0, which we have instructed to be the relay asset
409
1
			precompiles()
410
1
				.prepare_test(
411
1
					Alice,
412
1
					TransactorV1,
413
1
					PCallV1::transact_through_derivative_multilocation {
414
1
						transactor: 0,
415
1
						index: 0,
416
1
						fee_asset: fee_payer_asset,
417
1
						weight: 4_000_000,
418
1
						inner_call: bytes.into(),
419
1
					},
420
1
				)
421
1
				.expect_cost(188253001)
422
1
				.expect_no_logs()
423
1
				.execute_returns(());
424
1
		});
425
1
}
426

            
427
#[test]
428
1
fn test_transact_derivative() {
429
1
	ExtBuilder::default()
430
1
		.with_balances(vec![(Alice.into(), 1000)])
431
1
		.build()
432
1
		.execute_with(|| {
433
1
			// register index
434
1
			assert_ok!(XcmTransactor::register(
435
1
				RuntimeOrigin::root(),
436
1
				Alice.into(),
437
1
				0
438
1
			));
439

            
440
			// Root can set transact info
441
1
			assert_ok!(XcmTransactor::set_transact_info(
442
1
				RuntimeOrigin::root(),
443
1
				Box::new(xcm::VersionedLocation::from(Location::parent())),
444
1
				Weight::zero(),
445
1
				10000000.into(),
446
1
				None
447
1
			));
448

            
449
			// Root can set transact info
450
1
			assert_ok!(XcmTransactor::set_fee_per_second(
451
1
				RuntimeOrigin::root(),
452
1
				Box::new(xcm::VersionedLocation::from(Location::parent())),
453
1
				1
454
1
			));
455

            
456
1
			let bytes = vec![1u8, 2u8, 3u8];
457
1

            
458
1
			// We are transferring asset 0, which we have instructed to be the relay asset
459
1
			precompiles()
460
1
				.prepare_test(
461
1
					Alice,
462
1
					TransactorV1,
463
1
					PCallV1::transact_through_derivative {
464
1
						transactor: 0,
465
1
						index: 0,
466
1
						currency_id: Address(AssetAddress(0).into()),
467
1
						weight: 4_000_000,
468
1
						inner_call: bytes.into(),
469
1
					},
470
1
				)
471
1
				.expect_cost(188254001)
472
1
				.expect_no_logs()
473
1
				.execute_returns(());
474
1
		});
475
1
}
476

            
477
#[test]
478
1
fn test_transact_derivative_v2() {
479
1
	ExtBuilder::default()
480
1
		.with_balances(vec![(Alice.into(), 1000)])
481
1
		.build()
482
1
		.execute_with(|| {
483
1
			// register index
484
1
			assert_ok!(XcmTransactor::register(
485
1
				RuntimeOrigin::root(),
486
1
				Alice.into(),
487
1
				0
488
1
			));
489

            
490
1
			let bytes = vec![1u8, 2u8, 3u8];
491
1

            
492
1
			let total_weight = 1_000_000_000u64;
493
1

            
494
1
			// We are transferring asset 0, which we have instructed to be the relay asset
495
1
			precompiles()
496
1
				.prepare_test(
497
1
					Alice,
498
1
					TransactorV2,
499
1
					PCallV2::transact_through_derivative {
500
1
						transactor: 0,
501
1
						index: 0,
502
1
						fee_asset: Address(AssetAddress(0).into()),
503
1
						weight: 4_000_000,
504
1
						inner_call: bytes.into(),
505
1
						fee_amount: u128::from(total_weight).into(),
506
1
						overall_weight: total_weight,
507
1
					},
508
1
				)
509
1
				.expect_cost(188254001)
510
1
				.expect_no_logs()
511
1
				.execute_returns(());
512
1
		});
513
1
}
514

            
515
#[test]
516
1
fn test_transact_derivative_v3() {
517
1
	ExtBuilder::default()
518
1
		.with_balances(vec![(Alice.into(), 1000)])
519
1
		.build()
520
1
		.execute_with(|| {
521
1
			// register index
522
1
			assert_ok!(XcmTransactor::register(
523
1
				RuntimeOrigin::root(),
524
1
				Alice.into(),
525
1
				0
526
1
			));
527

            
528
1
			let bytes = vec![1u8, 2u8, 3u8];
529
1

            
530
1
			//let total_weight = 1_000_000_000u64;
531
1
			let total_weight = Weight::from_parts(1_000_000_000u64, 82_000u64);
532
1
			let require_weight_at_most = Weight::from_parts(4_000_000u64, 82_000u64);
533
1

            
534
1
			// We are transferring asset 0, which we have instructed to be the relay asset
535
1
			precompiles()
536
1
				.prepare_test(
537
1
					Alice,
538
1
					TransactorV3,
539
1
					PCallV3::transact_through_derivative {
540
1
						transactor: 0,
541
1
						index: 0,
542
1
						fee_asset: Address(AssetAddress(0).into()),
543
1
						weight: require_weight_at_most,
544
1
						inner_call: bytes.into(),
545
1
						fee_amount: u128::from(total_weight.ref_time()).into(),
546
1
						overall_weight: total_weight,
547
1
						refund: false,
548
1
					},
549
1
				)
550
1
				.expect_cost(188254001)
551
1
				.expect_no_logs()
552
1
				.execute_returns(());
553
1
		});
554
1
}
555

            
556
#[test]
557
1
fn test_transact_signed() {
558
1
	ExtBuilder::default()
559
1
		.with_balances(vec![(Alice.into(), 1000)])
560
1
		.build()
561
1
		.execute_with(|| {
562
1
			// Root can set transact info
563
1
			assert_ok!(XcmTransactor::set_transact_info(
564
1
				RuntimeOrigin::root(),
565
1
				Box::new(xcm::VersionedLocation::from(Location::parent())),
566
1
				Weight::zero(),
567
1
				10000000.into(),
568
1
				Some(1.into())
569
1
			));
570

            
571
			// Root can set transact info
572
1
			assert_ok!(XcmTransactor::set_fee_per_second(
573
1
				RuntimeOrigin::root(),
574
1
				Box::new(xcm::VersionedLocation::from(Location::parent())),
575
1
				1
576
1
			));
577

            
578
			// Destination
579
1
			let dest = Location::parent().into();
580
1

            
581
1
			let bytes = vec![1u8, 2u8, 3u8];
582
1

            
583
1
			// We are transferring asset 0, which we have instructed to be the relay asset
584
1
			precompiles()
585
1
				.prepare_test(
586
1
					Alice,
587
1
					TransactorV1,
588
1
					PCallV1::transact_through_signed {
589
1
						dest,
590
1
						fee_asset: Address(AssetAddress(0).into()),
591
1
						weight: 4_000_000,
592
1
						call: bytes.into(),
593
1
					},
594
1
				)
595
1
				.expect_cost(468449001)
596
1
				.expect_no_logs()
597
1
				.execute_returns(());
598
1
		});
599
1
}
600

            
601
#[test]
602
1
fn test_transact_signed_v2() {
603
1
	ExtBuilder::default()
604
1
		.with_balances(vec![(Alice.into(), 1000)])
605
1
		.build()
606
1
		.execute_with(|| {
607
1
			// Destination
608
1
			let dest = Location::parent().into();
609
1

            
610
1
			let bytes = vec![1u8, 2u8, 3u8];
611
1

            
612
1
			let total_weight = 1_000_000_000u64;
613
1

            
614
1
			// We are transferring asset 0, which we have instructed to be the relay asset
615
1
			precompiles()
616
1
				.prepare_test(
617
1
					Alice,
618
1
					TransactorV2,
619
1
					PCallV2::transact_through_signed {
620
1
						dest,
621
1
						fee_asset: Address(AssetAddress(0).into()),
622
1
						weight: 4_000_000,
623
1
						call: bytes.into(),
624
1
						fee_amount: u128::from(total_weight).into(),
625
1
						overall_weight: total_weight,
626
1
					},
627
1
				)
628
1
				.expect_cost(468449001)
629
1
				.expect_no_logs()
630
1
				.execute_returns(());
631
1
		});
632
1
}
633

            
634
#[test]
635
1
fn test_transact_signed_v3() {
636
1
	ExtBuilder::default()
637
1
		.with_balances(vec![(Alice.into(), 1000)])
638
1
		.build()
639
1
		.execute_with(|| {
640
1
			// register index
641
1
			assert_ok!(XcmTransactor::register(
642
1
				RuntimeOrigin::root(),
643
1
				Alice.into(),
644
1
				0
645
1
			));
646

            
647
1
			let bytes = vec![1u8, 2u8, 3u8];
648
1

            
649
1
			let total_weight = Weight::from_parts(1_000_000_000u64, 82_000u64);
650
1
			let require_weight_at_most = Weight::from_parts(4_000_000u64, 82_000u64);
651
1
			// We are transferring asset 0, which we have instructed to be the relay asset
652
1
			precompiles()
653
1
				.prepare_test(
654
1
					Alice,
655
1
					TransactorV3,
656
1
					PCallV3::transact_through_signed {
657
1
						dest: Location::parent(),
658
1
						fee_asset: Address(AssetAddress(0).into()),
659
1
						weight: require_weight_at_most,
660
1
						call: bytes.into(),
661
1
						fee_amount: u128::from(total_weight.ref_time()).into(),
662
1
						overall_weight: total_weight,
663
1
						refund: false,
664
1
					},
665
1
				)
666
1
				.expect_cost(468449001)
667
1
				.expect_no_logs()
668
1
				.execute_returns(());
669
1
		});
670
1
}
671

            
672
#[test]
673
1
fn test_transact_signed_multilocation() {
674
1
	ExtBuilder::default()
675
1
		.with_balances(vec![(Alice.into(), 1000)])
676
1
		.build()
677
1
		.execute_with(|| {
678
1
			// Root can set transact info
679
1
			assert_ok!(XcmTransactor::set_transact_info(
680
1
				RuntimeOrigin::root(),
681
1
				Box::new(xcm::VersionedLocation::from(Location::parent())),
682
1
				Weight::zero(),
683
1
				10000000.into(),
684
1
				Some(1.into())
685
1
			));
686

            
687
			// Root can set transact info
688
1
			assert_ok!(XcmTransactor::set_fee_per_second(
689
1
				RuntimeOrigin::root(),
690
1
				Box::new(xcm::VersionedLocation::from(Location::parent())),
691
1
				1
692
1
			));
693

            
694
			// Destination
695
1
			let dest = Location::parent().into();
696
1

            
697
1
			let fee_payer_asset = Location::parent().into();
698
1

            
699
1
			let bytes = vec![1u8, 2u8, 3u8];
700
1

            
701
1
			// We are transferring asset 0, which we have instructed to be the relay asset
702
1
			precompiles()
703
1
				.prepare_test(
704
1
					Alice,
705
1
					TransactorV1,
706
1
					PCallV1::transact_through_signed_multilocation {
707
1
						dest,
708
1
						fee_asset: fee_payer_asset,
709
1
						weight: 4_000_000,
710
1
						call: bytes.into(),
711
1
					},
712
1
				)
713
1
				.expect_cost(468448001)
714
1
				.expect_no_logs()
715
1
				.execute_returns(());
716
1
		});
717
1
}
718

            
719
#[test]
720
1
fn test_transact_signed_multilocation_v2() {
721
1
	ExtBuilder::default()
722
1
		.with_balances(vec![(Alice.into(), 1000)])
723
1
		.build()
724
1
		.execute_with(|| {
725
1
			// Destination
726
1
			let dest = Location::parent().into();
727
1

            
728
1
			let fee_payer_asset = Location::parent().into();
729
1

            
730
1
			let bytes = vec![1u8, 2u8, 3u8];
731
1

            
732
1
			let total_weight = 1_000_000_000u64;
733
1

            
734
1
			// We are transferring asset 0, which we have instructed to be the relay asset
735
1
			precompiles()
736
1
				.prepare_test(
737
1
					Alice,
738
1
					TransactorV2,
739
1
					PCallV2::transact_through_signed_multilocation {
740
1
						dest,
741
1
						fee_asset: fee_payer_asset,
742
1
						weight: 4_000_000,
743
1
						call: bytes.into(),
744
1
						fee_amount: u128::from(total_weight).into(),
745
1
						overall_weight: total_weight,
746
1
					},
747
1
				)
748
1
				.expect_cost(468448001)
749
1
				.expect_no_logs()
750
1
				.execute_returns(());
751
1
		});
752
1
}
753

            
754
#[test]
755
1
fn test_transact_through_signed_multilocation_v3() {
756
1
	ExtBuilder::default()
757
1
		.with_balances(vec![(Alice.into(), 1000)])
758
1
		.build()
759
1
		.execute_with(|| {
760
1
			// register index
761
1
			assert_ok!(XcmTransactor::register(
762
1
				RuntimeOrigin::root(),
763
1
				Alice.into(),
764
1
				0
765
1
			));
766

            
767
			// we pay with our current self reserve.
768
1
			let fee_payer_asset = Location::parent();
769
1

            
770
1
			let bytes = vec![1u8, 2u8, 3u8];
771
1

            
772
1
			let total_weight = Weight::from_parts(1_000_000_000u64, 82_000u64);
773
1
			let require_weight_at_most = Weight::from_parts(4_000_000u64, 82_000u64);
774
1
			// We are transferring asset 0, which we have instructed to be the relay asset
775
1
			precompiles()
776
1
				.prepare_test(
777
1
					Alice,
778
1
					TransactorV3,
779
1
					PCallV3::transact_through_signed_multilocation {
780
1
						dest: Location::parent(),
781
1
						fee_asset: fee_payer_asset,
782
1
						weight: require_weight_at_most,
783
1
						call: bytes.into(),
784
1
						fee_amount: u128::from(total_weight.ref_time()).into(),
785
1
						overall_weight: total_weight,
786
1
						refund: false,
787
1
					},
788
1
				)
789
1
				.expect_cost(468448001)
790
1
				.expect_no_logs()
791
1
				.execute_returns(());
792
1
		});
793
1
}
794

            
795
#[test]
796
1
fn test_solidity_interface_has_all_function_selectors_documented_and_implemented_v1() {
797
1
	check_precompile_implements_solidity_interfaces(
798
1
		&["src/v1/XcmTransactorV1.sol"],
799
1
		PCallV1::supports_selector,
800
1
	)
801
1
}
802

            
803
#[test]
804
1
fn test_solidity_interface_has_all_function_selectors_documented_and_implemented_v2() {
805
1
	check_precompile_implements_solidity_interfaces(
806
1
		&["src/v2/XcmTransactorV2.sol"],
807
1
		PCallV2::supports_selector,
808
1
	)
809
1
}
810

            
811
#[test]
812
1
fn test_solidity_interface_has_all_function_selectors_documented_and_implemented_v3() {
813
1
	check_precompile_implements_solidity_interfaces(
814
1
		&["src/v3/XcmTransactorV3.sol"],
815
1
		PCallV3::supports_selector,
816
1
	)
817
1
}
818

            
819
#[test]
820
1
fn test_deprecated_solidity_selectors_are_supported() {
821
8
	for deprecated_function in [
822
		"index_to_account(uint16)",
823
1
		"transact_info((uint8,bytes[]))",
824
1
		"transact_through_derivative_multilocation(uint8,uint16,(uint8,bytes[]),uint64,bytes)",
825
1
		"transact_through_derivative(uint8,uint16,address,uint64,bytes)",
826
1
		"transact_info_with_signed((uint8,bytes[]))",
827
1
		"fee_per_second((uint8,bytes[]))",
828
1
		"transact_through_signed_multilocation((uint8,bytes[]),(uint8,bytes[]),uint64,bytes)",
829
1
		"transact_through_signed((uint8,bytes[]),address,uint64,bytes)",
830
	] {
831
8
		let selector = compute_selector(deprecated_function);
832
8
		if !PCallV1::supports_selector(selector) {
833
			panic!(
834
				"failed decoding selector 0x{:x} => '{}' as Action",
835
				selector, deprecated_function,
836
			)
837
8
		}
838
	}
839
1
}