1
// Copyright 2024 Moonbeam foundation
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

            
17
//! Unit testing
18
use {
19
	crate::mock::*,
20
	crate::{Error, Trader, XcmPaymentApiError},
21
	frame_support::pallet_prelude::Weight,
22
	frame_support::{assert_noop, assert_ok},
23
	sp_runtime::DispatchError,
24
	xcm::v5::{
25
		Asset, AssetId as XcmAssetId, Error as XcmError, Fungibility, Location, XcmContext, XcmHash,
26
	},
27
	xcm::{IntoVersion, VersionedAssetId},
28
	xcm_executor::traits::WeightTrader,
29
};
30

            
31
3
fn xcm_fees_account() -> <Test as frame_system::Config>::AccountId {
32
3
	<Test as crate::Config>::XcmFeesAccount::get()
33
3
}
34

            
35
#[test]
36
1
fn test_add_supported_asset() {
37
1
	new_test_ext().execute_with(|| {
38
		// Call with bad origin
39
1
		assert_noop!(
40
1
			XcmWeightTrader::add_asset(
41
1
				RuntimeOrigin::signed(EditAccount::get()),
42
1
				Location::parent(),
43
				1_000,
44
			),
45
1
			DispatchError::BadOrigin
46
		);
47

            
48
		// Call with invalid location
49
1
		assert_noop!(
50
1
			XcmWeightTrader::add_asset(
51
1
				RuntimeOrigin::signed(AddAccount::get()),
52
1
				Location::new(2, []),
53
				1_000,
54
			),
55
1
			Error::<Test>::XcmLocationFiltered
56
		);
57

            
58
		// Call with invalid price
59
1
		assert_noop!(
60
1
			XcmWeightTrader::add_asset(
61
1
				RuntimeOrigin::signed(AddAccount::get()),
62
1
				Location::parent(),
63
				0,
64
			),
65
1
			Error::<Test>::PriceCannotBeZero
66
		);
67

            
68
		// Call with the right origin
69
1
		assert_ok!(XcmWeightTrader::add_asset(
70
1
			RuntimeOrigin::signed(AddAccount::get()),
71
1
			Location::parent(),
72
			1_000,
73
		));
74

            
75
		// The account should be supported
76
1
		assert_eq!(
77
1
			XcmWeightTrader::get_asset_relative_price(&Location::parent()),
78
			Some(1_000),
79
		);
80

            
81
		// Check storage
82
1
		assert_eq!(
83
1
			crate::pallet::SupportedAssets::<Test>::get(&Location::parent()),
84
			Some((true, 1_000))
85
		);
86

            
87
		// Try to add the same asset twice (should fail)
88
1
		assert_noop!(
89
1
			XcmWeightTrader::add_asset(
90
1
				RuntimeOrigin::signed(AddAccount::get()),
91
1
				Location::parent(),
92
				1_000,
93
			),
94
1
			Error::<Test>::AssetAlreadyAdded
95
		);
96
1
	})
97
1
}
98

            
99
#[test]
100
1
fn test_edit_supported_asset() {
101
1
	new_test_ext().execute_with(|| {
102
		// Should not be able to edit an asset not added yet
103
1
		assert_noop!(
104
1
			XcmWeightTrader::edit_asset(
105
1
				RuntimeOrigin::signed(EditAccount::get()),
106
1
				Location::parent(),
107
				2_000,
108
			),
109
1
			Error::<Test>::AssetNotFound
110
		);
111

            
112
		// Setup (add a supported asset)
113
1
		assert_ok!(XcmWeightTrader::add_asset(
114
1
			RuntimeOrigin::signed(AddAccount::get()),
115
1
			Location::parent(),
116
			1_000,
117
		));
118
1
		assert_eq!(
119
1
			XcmWeightTrader::get_asset_relative_price(&Location::parent()),
120
			Some(1_000),
121
		);
122

            
123
		// Call with bad origin
124
1
		assert_noop!(
125
1
			XcmWeightTrader::edit_asset(
126
1
				RuntimeOrigin::signed(AddAccount::get()),
127
1
				Location::parent(),
128
				2_000,
129
			),
130
1
			DispatchError::BadOrigin
131
		);
132

            
133
		// Call with invalid price
134
1
		assert_noop!(
135
1
			XcmWeightTrader::edit_asset(
136
1
				RuntimeOrigin::signed(EditAccount::get()),
137
1
				Location::parent(),
138
				0,
139
			),
140
1
			Error::<Test>::PriceCannotBeZero
141
		);
142

            
143
		// Call with right origin and valid params
144
1
		assert_ok!(XcmWeightTrader::edit_asset(
145
1
			RuntimeOrigin::signed(EditAccount::get()),
146
1
			Location::parent(),
147
			2_000,
148
		),);
149

            
150
		// The account should be supported
151
1
		assert_eq!(
152
1
			XcmWeightTrader::get_asset_relative_price(&Location::parent()),
153
			Some(2_000),
154
		);
155

            
156
		// Check storage
157
1
		assert_eq!(
158
1
			crate::pallet::SupportedAssets::<Test>::get(&Location::parent()),
159
			Some((true, 2_000))
160
		);
161
1
	})
162
1
}
163

            
164
#[test]
165
1
fn test_pause_asset_support() {
166
1
	new_test_ext().execute_with(|| {
167
		// Should not be able to pause an asset not added yet
168
1
		assert_noop!(
169
1
			XcmWeightTrader::pause_asset_support(
170
1
				RuntimeOrigin::signed(PauseAccount::get()),
171
1
				Location::parent(),
172
			),
173
1
			Error::<Test>::AssetNotFound
174
		);
175

            
176
		// Setup (add a supported asset)
177
1
		assert_ok!(XcmWeightTrader::add_asset(
178
1
			RuntimeOrigin::signed(AddAccount::get()),
179
1
			Location::parent(),
180
			1_000,
181
		));
182
1
		assert_eq!(
183
1
			XcmWeightTrader::get_asset_relative_price(&Location::parent()),
184
			Some(1_000),
185
		);
186

            
187
		// Call with bad origin
188
1
		assert_noop!(
189
1
			XcmWeightTrader::pause_asset_support(
190
1
				RuntimeOrigin::signed(AddAccount::get()),
191
1
				Location::parent(),
192
			),
193
1
			DispatchError::BadOrigin
194
		);
195

            
196
		// Call with right origin and valid params
197
1
		assert_ok!(XcmWeightTrader::pause_asset_support(
198
1
			RuntimeOrigin::signed(PauseAccount::get()),
199
1
			Location::parent(),
200
		));
201

            
202
		// The asset should be paused
203
1
		assert_eq!(
204
1
			XcmWeightTrader::get_asset_relative_price(&Location::parent()),
205
			None,
206
		);
207

            
208
		// Check storage
209
1
		assert_eq!(
210
1
			crate::pallet::SupportedAssets::<Test>::get(&Location::parent()),
211
			Some((false, 1_000))
212
		);
213

            
214
		// Should not be able to pause an asset already paused
215
1
		assert_noop!(
216
1
			XcmWeightTrader::pause_asset_support(
217
1
				RuntimeOrigin::signed(PauseAccount::get()),
218
1
				Location::parent(),
219
			),
220
1
			Error::<Test>::AssetAlreadyPaused
221
		);
222

            
223
		// Should be able to update relative price of paused asset
224
1
		assert_ok!(XcmWeightTrader::edit_asset(
225
1
			RuntimeOrigin::signed(EditAccount::get()),
226
1
			Location::parent(),
227
			500
228
		));
229

            
230
		// The asset should still be paused
231
1
		assert_eq!(
232
1
			XcmWeightTrader::get_asset_relative_price(&Location::parent()),
233
			None,
234
		);
235

            
236
		// Check storage
237
1
		assert_eq!(
238
1
			crate::pallet::SupportedAssets::<Test>::get(&Location::parent()),
239
			Some((false, 500))
240
		);
241
1
	})
242
1
}
243

            
244
#[test]
245
1
fn test_resume_asset_support() {
246
1
	new_test_ext().execute_with(|| {
247
		// Setup (add a supported asset and pause it)
248
1
		assert_ok!(XcmWeightTrader::add_asset(
249
1
			RuntimeOrigin::signed(AddAccount::get()),
250
1
			Location::parent(),
251
			1_000,
252
		));
253
1
		assert_ok!(XcmWeightTrader::pause_asset_support(
254
1
			RuntimeOrigin::signed(PauseAccount::get()),
255
1
			Location::parent(),
256
		));
257
1
		assert_eq!(
258
1
			crate::pallet::SupportedAssets::<Test>::get(&Location::parent()),
259
			Some((false, 1_000))
260
		);
261

            
262
		// Call with bad origin
263
1
		assert_noop!(
264
1
			XcmWeightTrader::resume_asset_support(
265
1
				RuntimeOrigin::signed(AddAccount::get()),
266
1
				Location::parent(),
267
			),
268
1
			DispatchError::BadOrigin
269
		);
270

            
271
		// Call with invalid location
272
1
		assert_noop!(
273
1
			XcmWeightTrader::resume_asset_support(
274
1
				RuntimeOrigin::signed(ResumeAccount::get()),
275
1
				Location::new(2, []),
276
			),
277
1
			Error::<Test>::AssetNotFound
278
		);
279

            
280
		// Call with right origin and valid params
281
1
		assert_ok!(XcmWeightTrader::resume_asset_support(
282
1
			RuntimeOrigin::signed(ResumeAccount::get()),
283
1
			Location::parent(),
284
		));
285

            
286
		// The asset should be supported again
287
1
		assert_eq!(
288
1
			XcmWeightTrader::get_asset_relative_price(&Location::parent()),
289
			Some(1_000),
290
		);
291

            
292
		// Check storage
293
1
		assert_eq!(
294
1
			crate::pallet::SupportedAssets::<Test>::get(&Location::parent()),
295
			Some((true, 1_000))
296
		);
297

            
298
		// Should not be able to resume an asset already active
299
1
		assert_noop!(
300
1
			XcmWeightTrader::resume_asset_support(
301
1
				RuntimeOrigin::signed(ResumeAccount::get()),
302
1
				Location::parent(),
303
			),
304
1
			Error::<Test>::AssetNotPaused
305
		);
306
1
	})
307
1
}
308

            
309
#[test]
310
1
fn test_remove_asset_support() {
311
1
	new_test_ext().execute_with(|| {
312
		// Should not be able to remove an asset not added yet
313
1
		assert_noop!(
314
1
			XcmWeightTrader::remove_asset(
315
1
				RuntimeOrigin::signed(RemoveAccount::get()),
316
1
				Location::parent(),
317
			),
318
1
			Error::<Test>::AssetNotFound
319
		);
320

            
321
		// Setup (add a supported asset)
322
1
		assert_ok!(XcmWeightTrader::add_asset(
323
1
			RuntimeOrigin::signed(AddAccount::get()),
324
1
			Location::parent(),
325
			1_000,
326
		));
327
1
		assert_eq!(
328
1
			XcmWeightTrader::get_asset_relative_price(&Location::parent()),
329
			Some(1_000),
330
		);
331

            
332
		// Call with bad origin
333
1
		assert_noop!(
334
1
			XcmWeightTrader::remove_asset(
335
1
				RuntimeOrigin::signed(AddAccount::get()),
336
1
				Location::parent(),
337
			),
338
1
			DispatchError::BadOrigin
339
		);
340

            
341
		// Call with right origin and valid params
342
1
		assert_ok!(XcmWeightTrader::remove_asset(
343
1
			RuntimeOrigin::signed(RemoveAccount::get()),
344
1
			Location::parent(),
345
		));
346

            
347
		// The account should be removed
348
1
		assert_eq!(
349
1
			XcmWeightTrader::get_asset_relative_price(&Location::parent()),
350
			None,
351
		);
352

            
353
		// Check storage
354
1
		assert_eq!(
355
1
			crate::pallet::SupportedAssets::<Test>::get(&Location::parent()),
356
			None
357
		);
358

            
359
		// Should not be able to pause an asset already removed
360
1
		assert_noop!(
361
1
			XcmWeightTrader::remove_asset(
362
1
				RuntimeOrigin::signed(RemoveAccount::get()),
363
1
				Location::parent(),
364
			),
365
1
			Error::<Test>::AssetNotFound
366
		);
367
1
	})
368
1
}
369

            
370
#[test]
371
1
fn test_trader_native_asset() {
372
1
	new_test_ext().execute_with(|| {
373
1
		let weight_to_buy = Weight::from_parts(10_000, 0);
374
1
		let dummy_xcm_context = XcmContext::with_message_id(XcmHash::default());
375

            
376
		// Should not be able to buy weight with too low asset balance
377
1
		assert_eq!(
378
1
			Trader::<Test>::new().buy_weight(
379
1
				weight_to_buy,
380
1
				Asset {
381
1
					fun: Fungibility::Fungible(9_999),
382
1
					id: XcmAssetId(Location::here()),
383
1
				}
384
1
				.into(),
385
1
				&dummy_xcm_context
386
			),
387
			Err(XcmError::TooExpensive)
388
		);
389

            
390
		// Should not be able to buy weight with unsupported asset
391
1
		assert_eq!(
392
1
			Trader::<Test>::new().buy_weight(
393
1
				weight_to_buy,
394
1
				Asset {
395
1
					fun: Fungibility::Fungible(10_000),
396
1
					id: XcmAssetId(Location::parent()),
397
1
				}
398
1
				.into(),
399
1
				&dummy_xcm_context
400
			),
401
			Err(XcmError::AssetNotFound)
402
		);
403

            
404
		// Should not be able to buy weight without asset
405
1
		assert_eq!(
406
1
			Trader::<Test>::new().buy_weight(weight_to_buy, Default::default(), &dummy_xcm_context),
407
			Err(XcmError::AssetNotFound)
408
		);
409

            
410
		// Should be able to buy weight with just enough native asset
411
1
		let mut trader = Trader::<Test>::new();
412
1
		assert_eq!(
413
1
			trader.buy_weight(
414
1
				weight_to_buy,
415
1
				Asset {
416
1
					fun: Fungibility::Fungible(10_000),
417
1
					id: XcmAssetId(Location::here()),
418
1
				}
419
1
				.into(),
420
1
				&dummy_xcm_context
421
			),
422
1
			Ok(Default::default())
423
		);
424

            
425
		// Should not refund any funds
426
		// `xcm-executor` calls `refund_weight` with the *surplus* weight to refund.
427
		// When there is no surplus, nothing should be refunded.
428
1
		let weight_to_refund = Weight::zero();
429
1
		assert_eq!(
430
1
			trader.refund_weight(weight_to_refund, &dummy_xcm_context),
431
			None
432
		);
433

            
434
		// Should not be able to buy weight again with the same trader
435
1
		assert_eq!(
436
1
			trader.buy_weight(
437
1
				weight_to_buy,
438
1
				Asset {
439
1
					fun: Fungibility::Fungible(10_000),
440
1
					id: XcmAssetId(Location::here()),
441
1
				}
442
1
				.into(),
443
1
				&dummy_xcm_context
444
			),
445
			Err(XcmError::NotWithdrawable)
446
		);
447

            
448
		// Fees asset should be deposited into XcmFeesAccount
449
1
		drop(trader);
450
1
		assert_eq!(Balances::free_balance(&xcm_fees_account()), 10_000);
451

            
452
		// Should be able to buy weight with more native asset (and get back unused amount)
453
1
		let mut trader = Trader::<Test>::new();
454
1
		assert_eq!(
455
1
			trader.buy_weight(
456
1
				weight_to_buy,
457
1
				Asset {
458
1
					fun: Fungibility::Fungible(11_000),
459
1
					id: XcmAssetId(Location::here()),
460
1
				}
461
1
				.into(),
462
1
				&dummy_xcm_context
463
			),
464
1
			Ok(Asset {
465
1
				fun: Fungibility::Fungible(1_000),
466
1
				id: XcmAssetId(Location::here()),
467
1
			}
468
1
			.into())
469
		);
470

            
471
		// Should be able to refund unused weights
472
1
		let weight_to_refund = Weight::from_parts(2_000, 0);
473
1
		assert_eq!(
474
1
			trader.refund_weight(weight_to_refund, &dummy_xcm_context),
475
1
			Some(Asset {
476
1
				fun: Fungibility::Fungible(2_000),
477
1
				id: XcmAssetId(Location::here()),
478
1
			})
479
		);
480

            
481
		// Fees asset should be deposited again into XcmFeesAccount (2 times cost minus one refund)
482
1
		drop(trader);
483
1
		assert_eq!(
484
1
			Balances::free_balance(&xcm_fees_account()),
485
			(2 * 10_000) - 2_000
486
		);
487
1
	})
488
1
}
489

            
490
#[test]
491
1
fn test_trader_parent_asset() {
492
1
	new_test_ext().execute_with(|| {
493
1
		let weight_to_buy = Weight::from_parts(10_000, 0);
494
1
		let dummy_xcm_context = XcmContext::with_message_id(XcmHash::default());
495

            
496
		// Setup (add a supported asset)
497
1
		assert_ok!(XcmWeightTrader::add_asset(
498
1
			RuntimeOrigin::signed(AddAccount::get()),
499
1
			Location::parent(),
500
			500_000_000,
501
		));
502
1
		assert_eq!(
503
1
			XcmWeightTrader::get_asset_relative_price(&Location::parent()),
504
			Some(500_000_000),
505
		);
506

            
507
		// Should be able to pay fees with registered asset
508
1
		let mut trader = Trader::<Test>::new();
509
1
		assert_eq!(
510
1
			trader.buy_weight(
511
1
				weight_to_buy,
512
1
				Asset {
513
1
					fun: Fungibility::Fungible(22_000_000_000_000),
514
1
					id: XcmAssetId(Location::parent()),
515
1
				}
516
1
				.into(),
517
1
				&dummy_xcm_context
518
			),
519
1
			Ok(Asset {
520
1
				fun: Fungibility::Fungible(2_000_000_000_000),
521
1
				id: XcmAssetId(Location::parent()),
522
1
			}
523
1
			.into())
524
		);
525

            
526
		// Should be able to refund unused weights
527
1
		let weight_to_refund = Weight::from_parts(2_000, 0);
528
1
		assert_eq!(
529
1
			trader.refund_weight(weight_to_refund, &dummy_xcm_context),
530
1
			Some(Asset {
531
1
				fun: Fungibility::Fungible(4_000_000_000_000),
532
1
				id: XcmAssetId(Location::parent()),
533
1
			})
534
		);
535

            
536
		// Fees asset should be deposited into XcmFeesAccount
537
1
		drop(trader);
538
1
		assert_eq!(
539
1
			get_parent_asset_deposited(),
540
1
			Some((xcm_fees_account(), 20_000_000_000_000 - 4_000_000_000_000))
541
		);
542

            
543
		// Should not be able to buy weight if the asset is not a first position
544
1
		assert_eq!(
545
1
			Trader::<Test>::new().buy_weight(
546
1
				weight_to_buy,
547
1
				vec![
548
1
					Asset {
549
1
						fun: Fungibility::Fungible(10),
550
1
						id: XcmAssetId(Location::here()),
551
1
					},
552
1
					Asset {
553
1
						fun: Fungibility::Fungible(30_000),
554
1
						id: XcmAssetId(Location::parent()),
555
1
					}
556
				]
557
1
				.into(),
558
1
				&dummy_xcm_context
559
			),
560
			Err(XcmError::TooExpensive)
561
		);
562
1
	})
563
1
}
564

            
565
#[test]
566
1
fn test_query_acceptable_payment_assets() {
567
1
	new_test_ext().execute_with(|| {
568
		// By default, only native asset should be supported
569
1
		assert_eq!(
570
1
			XcmWeightTrader::query_acceptable_payment_assets(5),
571
1
			Ok(vec![VersionedAssetId::from(XcmAssetId(
572
1
				<Test as crate::Config>::NativeLocation::get()
573
1
			))])
574
		);
575

            
576
		// We should support XCMv3
577
1
		assert_eq!(
578
1
			XcmWeightTrader::query_acceptable_payment_assets(3),
579
1
			Ok(vec![VersionedAssetId::from(XcmAssetId(
580
1
				<Test as crate::Config>::NativeLocation::get()
581
1
			))
582
1
			.into_version(xcm::v3::VERSION)
583
1
			.expect("native location should be convertible to v3")])
584
		);
585

            
586
		// We should not support XCMv2
587
1
		assert_eq!(
588
1
			XcmWeightTrader::query_acceptable_payment_assets(2),
589
			Err(XcmPaymentApiError::UnhandledXcmVersion)
590
		);
591

            
592
		// Setup (add a supported asset)
593
1
		assert_ok!(XcmWeightTrader::add_asset(
594
1
			RuntimeOrigin::signed(AddAccount::get()),
595
1
			Location::parent(),
596
			500_000_000,
597
		));
598
1
		assert_eq!(
599
1
			XcmWeightTrader::get_asset_relative_price(&Location::parent()),
600
			Some(500_000_000),
601
		);
602

            
603
		// We should support parent asset now
604
1
		assert_eq!(
605
1
			XcmWeightTrader::query_acceptable_payment_assets(5),
606
1
			Ok(vec![
607
1
				VersionedAssetId::from(XcmAssetId(<Test as crate::Config>::NativeLocation::get())),
608
1
				VersionedAssetId::from(XcmAssetId(Location::parent()))
609
1
			])
610
		);
611

            
612
		// Setup: pause parent asset
613
1
		assert_ok!(XcmWeightTrader::pause_asset_support(
614
1
			RuntimeOrigin::signed(PauseAccount::get()),
615
1
			Location::parent(),
616
		));
617
1
		assert_eq!(
618
1
			XcmWeightTrader::get_asset_relative_price(&Location::parent()),
619
			None
620
		);
621

            
622
		// We should not support paused assets
623
1
		assert_eq!(
624
1
			XcmWeightTrader::query_acceptable_payment_assets(5),
625
1
			Ok(vec![VersionedAssetId::from(XcmAssetId(
626
1
				<Test as crate::Config>::NativeLocation::get()
627
1
			)),])
628
		);
629
1
	})
630
1
}
631

            
632
#[test]
633
1
fn test_query_weight_to_asset_fee() {
634
1
	new_test_ext().execute_with(|| {
635
1
		let native_asset =
636
1
			VersionedAssetId::from(XcmAssetId(<Test as crate::Config>::NativeLocation::get()));
637
1
		let parent_asset = VersionedAssetId::from(XcmAssetId(Location::parent()));
638
1
		let weight_to_buy = Weight::from_parts(10_000, 0);
639

            
640
		// Native asset price should be 1:1
641
1
		assert_eq!(
642
1
			XcmWeightTrader::query_weight_to_asset_fee(weight_to_buy, native_asset.clone()),
643
			Ok(10_000)
644
		);
645

            
646
		// Should not be able to query fees for an unsupported asset
647
1
		assert_eq!(
648
1
			XcmWeightTrader::query_weight_to_asset_fee(weight_to_buy, parent_asset.clone()),
649
			Err(XcmPaymentApiError::AssetNotFound)
650
		);
651

            
652
		// Setup (add a supported asset)
653
1
		assert_ok!(XcmWeightTrader::add_asset(
654
1
			RuntimeOrigin::signed(AddAccount::get()),
655
1
			Location::parent(),
656
			500_000_000,
657
		));
658
1
		assert_eq!(
659
1
			XcmWeightTrader::get_asset_relative_price(&Location::parent()),
660
			Some(500_000_000),
661
		);
662

            
663
		// Parent asset price should be 0.5
664
1
		assert_eq!(
665
1
			XcmWeightTrader::query_weight_to_asset_fee(weight_to_buy, parent_asset.clone()),
666
			Ok(2 * 10_000_000_000_000)
667
		);
668

            
669
		// Setup: pause parent asset
670
1
		assert_ok!(XcmWeightTrader::pause_asset_support(
671
1
			RuntimeOrigin::signed(PauseAccount::get()),
672
1
			Location::parent(),
673
		));
674
1
		assert_eq!(
675
1
			XcmWeightTrader::get_asset_relative_price(&Location::parent()),
676
			None
677
		);
678

            
679
		// We should not support paused assets
680
1
		assert_eq!(
681
1
			XcmWeightTrader::query_weight_to_asset_fee(weight_to_buy, parent_asset.clone()),
682
			Err(XcmPaymentApiError::AssetNotFound)
683
		);
684

            
685
		// Setup: unpause parent asset and edit price
686
1
		assert_ok!(XcmWeightTrader::resume_asset_support(
687
1
			RuntimeOrigin::signed(ResumeAccount::get()),
688
1
			Location::parent(),
689
		));
690
1
		assert_ok!(XcmWeightTrader::edit_asset(
691
1
			RuntimeOrigin::signed(EditAccount::get()),
692
1
			Location::parent(),
693
			2_000_000_000,
694
		));
695
1
		assert_eq!(
696
1
			XcmWeightTrader::get_asset_relative_price(&Location::parent()),
697
			Some(2_000_000_000),
698
		);
699

            
700
		// We should support unpaused asset with new price
701
1
		assert_eq!(
702
1
			XcmWeightTrader::query_weight_to_asset_fee(weight_to_buy, parent_asset),
703
1
			Ok(10_000_000_000_000 / 2)
704
		);
705
1
	})
706
1
}