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 moonbeam_tests_primitives::MemoryFeeTrader;
23
use precompile_utils::{prelude::*, testing::*};
24
use sp_core::H160;
25
use sp_std::boxed::Box;
26
use xcm::latest::Location;
27
use xcm_primitives::XcmFeeTrader;
28

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

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

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

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

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

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

            
76
1
		let mut tester = PrecompilesModifierTester::new(precompiles(), Alice, TransactorV2);
77

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

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

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

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

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

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

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

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

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

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

            
161
			// Set fee per second for test setup
162
1
			assert_ok!(<MemoryFeeTrader as XcmFeeTrader>::set_asset_price(
163
1
				Location::parent(),
164
				1
165
			));
166

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

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

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

            
199
			// Set fee per second for test setup
200
1
			assert_ok!(<MemoryFeeTrader as XcmFeeTrader>::set_asset_price(
201
1
				Location::parent(),
202
				1
203
			));
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

            
224
			// 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

            
229
			// Set fee per second for test setup
230
1
			assert_ok!(<MemoryFeeTrader as XcmFeeTrader>::set_asset_price(
231
1
				Location::parent(),
232
				1
233
			));
234
1
			precompiles()
235
1
				.prepare_test(Alice, TransactorV1, input)
236
1
				.expect_cost(2)
237
1
				.expect_no_logs()
238
1
				.execute_returns(1u64);
239
1
		});
240
1
}
241

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

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

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

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

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

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

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

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

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

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

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

            
350
			// Set fee per second for test setup
351
1
			assert_ok!(<MemoryFeeTrader as XcmFeeTrader>::set_asset_price(
352
1
				Location::parent(),
353
				1
354
			));
355

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

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

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

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

            
394
			// Set fee per second for test setup
395
1
			assert_ok!(<MemoryFeeTrader as XcmFeeTrader>::set_asset_price(
396
1
				Location::parent(),
397
				1
398
			));
399

            
400
			// we pay with our current self reserve.
401
1
			let fee_payer_asset = Location::parent().into();
402

            
403
1
			let bytes = vec![1u8, 2u8, 3u8];
404

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

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

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

            
446
			// Set fee per second for test setup
447
1
			assert_ok!(<MemoryFeeTrader as XcmFeeTrader>::set_asset_price(
448
1
				Location::parent(),
449
				1
450
			));
451

            
452
1
			let bytes = vec![1u8, 2u8, 3u8];
453

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

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

            
486
1
			let bytes = vec![1u8, 2u8, 3u8];
487

            
488
1
			let total_weight = 1_000_000_000u64;
489

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

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

            
524
1
			let bytes = vec![1u8, 2u8, 3u8];
525

            
526
			//let total_weight = 1_000_000_000u64;
527
1
			let total_weight = Weight::from_parts(1_000_000_000u64, 82_000u64);
528
1
			let require_weight_at_most = Weight::from_parts(4_000_000u64, 82_000u64);
529

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

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

            
567
			// Set fee per second for test setup
568
1
			assert_ok!(<MemoryFeeTrader as XcmFeeTrader>::set_asset_price(
569
1
				Location::parent(),
570
				1
571
			));
572

            
573
			// Destination
574
1
			let dest = Location::parent().into();
575

            
576
1
			let bytes = vec![1u8, 2u8, 3u8];
577

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

            
596
#[test]
597
1
fn test_transact_signed_v2() {
598
1
	ExtBuilder::default()
599
1
		.with_balances(vec![(Alice.into(), 1000)])
600
1
		.build()
601
1
		.execute_with(|| {
602
			// Destination
603
1
			let dest = Location::parent().into();
604

            
605
1
			let bytes = vec![1u8, 2u8, 3u8];
606

            
607
1
			let total_weight = 1_000_000_000u64;
608

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

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

            
642
1
			let bytes = vec![1u8, 2u8, 3u8];
643

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

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

            
682
			// Set fee per second for test setup
683
1
			assert_ok!(<MemoryFeeTrader as XcmFeeTrader>::set_asset_price(
684
1
				Location::parent(),
685
				1
686
			));
687

            
688
			// Destination
689
1
			let dest = Location::parent().into();
690

            
691
1
			let fee_payer_asset = Location::parent().into();
692

            
693
1
			let bytes = vec![1u8, 2u8, 3u8];
694

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

            
713
#[test]
714
1
fn test_transact_signed_multilocation_v2() {
715
1
	ExtBuilder::default()
716
1
		.with_balances(vec![(Alice.into(), 1000)])
717
1
		.build()
718
1
		.execute_with(|| {
719
			// Destination
720
1
			let dest = Location::parent().into();
721

            
722
1
			let fee_payer_asset = Location::parent().into();
723

            
724
1
			let bytes = vec![1u8, 2u8, 3u8];
725

            
726
1
			let total_weight = 1_000_000_000u64;
727

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

            
748
#[test]
749
1
fn test_transact_through_signed_multilocation_v3() {
750
1
	ExtBuilder::default()
751
1
		.with_balances(vec![(Alice.into(), 1000)])
752
1
		.build()
753
1
		.execute_with(|| {
754
			// register index
755
1
			assert_ok!(XcmTransactor::register(
756
1
				RuntimeOrigin::root(),
757
1
				Alice.into(),
758
				0
759
			));
760

            
761
			// we pay with our current self reserve.
762
1
			let fee_payer_asset = Location::parent();
763

            
764
1
			let bytes = vec![1u8, 2u8, 3u8];
765

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

            
789
#[test]
790
1
fn test_solidity_interface_has_all_function_selectors_documented_and_implemented_v1() {
791
1
	check_precompile_implements_solidity_interfaces(
792
1
		&["src/v1/XcmTransactorV1.sol"],
793
		PCallV1::supports_selector,
794
	)
795
1
}
796

            
797
#[test]
798
1
fn test_solidity_interface_has_all_function_selectors_documented_and_implemented_v2() {
799
1
	check_precompile_implements_solidity_interfaces(
800
1
		&["src/v2/XcmTransactorV2.sol"],
801
		PCallV2::supports_selector,
802
	)
803
1
}
804

            
805
#[test]
806
1
fn test_solidity_interface_has_all_function_selectors_documented_and_implemented_v3() {
807
1
	check_precompile_implements_solidity_interfaces(
808
1
		&["src/v3/XcmTransactorV3.sol"],
809
		PCallV3::supports_selector,
810
	)
811
1
}
812

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