git.delta.rocks / unique-network / refs/commits / db0567dfbc40

difftreelog

fix Unique XCM tests

Daniel Shiposha2022-12-22parent: #3f1e2f3.patch.diff
in: master

1 file changed

modifiedtests/src/xcm/xcmUnique.test.tsdiffbeforeafterboth
17import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';
18import {blake2AsHex} from '@polkadot/util-crypto';18import {blake2AsHex} from '@polkadot/util-crypto';
19import config from '../config';19import config from '../config';
20import {XcmV2TraitsError, XcmV2TraitsOutcome} from '../interfaces';20import {XcmV2TraitsError} from '../interfaces';
21import {itSub, expect, describeXCM, usingPlaygrounds, usingAcalaPlaygrounds, usingRelayPlaygrounds, usingMoonbeamPlaygrounds} from '../util';21import {itSub, expect, describeXCM, usingPlaygrounds, usingAcalaPlaygrounds, usingRelayPlaygrounds, usingMoonbeamPlaygrounds, usingStatemintPlaygrounds} from '../util';
2222
23const UNIQUE_CHAIN = 2037;23const UNIQUE_CHAIN = 2037;
24const STATEMINT_CHAIN = 1000;
24const ACALA_CHAIN = 2000;25const ACALA_CHAIN = 2000;
25const MOONBEAM_CHAIN = 2004;26const MOONBEAM_CHAIN = 2004;
2627
28const STATEMINT_PALLET_INSTANCE = 50;
29
27const relayUrl = config.relayUrl;30const relayUrl = config.relayUrl;
31const statemintUrl = config.statemintUrl;
28const acalaUrl = config.acalaUrl;32const acalaUrl = config.acalaUrl;
29const moonbeamUrl = config.moonbeamUrl;33const moonbeamUrl = config.moonbeamUrl;
3034
35const RELAY_DECIMALS = 12;
36const STATEMINT_DECIMALS = 12;
31const ACALA_DECIMALS = 12;37const ACALA_DECIMALS = 12;
3238
33const TRANSFER_AMOUNT = 2000000000000000000000000n;39const TRANSFER_AMOUNT = 2000000000000000000000000n;
3440
41const FUNDING_AMOUNT = 3_500_000_0000_000_000n;
42
43const TRANSFER_AMOUNT_RELAY = 50_000_000_000_000_000n;
44
45const USDT_ASSET_ID = 100;
46const USDT_ASSET_METADATA_DECIMALS = 18;
47const USDT_ASSET_METADATA_NAME = 'USDT';
48const USDT_ASSET_METADATA_DESCRIPTION = 'USDT';
49const USDT_ASSET_METADATA_MINIMAL_BALANCE = 1n;
50const USDT_ASSET_AMOUNT = 10_000_000_000_000_000_000_000_000n;
51
52describeXCM('[XCM] Integration test: Exchanging USDT with Statemint', () => {
53 let alice: IKeyringPair;
54 let bob: IKeyringPair;
55
56 let balanceStmnBefore: bigint;
57 let balanceStmnAfter: bigint;
58
59 let balanceUniqueBefore: bigint;
60 let balanceUniqueAfter: bigint;
61 let balanceUniqueFinal: bigint;
62
63 let balanceBobBefore: bigint;
64 let balanceBobAfter: bigint;
65 let balanceBobFinal: bigint;
66
67 let balanceBobRelayTokenBefore: bigint;
68 let balanceBobRelayTokenAfter: bigint;
69
70
71 before(async () => {
72 await usingPlaygrounds(async (_helper, privateKey) => {
73 alice = await privateKey('//Alice');
74 bob = await privateKey('//Bob'); // sovereign account on Statemint funds donor
75 });
76
77 await usingRelayPlaygrounds(relayUrl, async (helper) => {
78 // Fund accounts on Statemint
79 await helper.xcm.teleportNativeAsset(alice, STATEMINT_CHAIN, alice.addressRaw, FUNDING_AMOUNT);
80 await helper.xcm.teleportNativeAsset(alice, STATEMINT_CHAIN, bob.addressRaw, FUNDING_AMOUNT);
81 });
82
83 await usingStatemintPlaygrounds(statemintUrl, async (helper) => {
84 const sovereignFundingAmount = 3_500_000_000n;
85
86 await helper.assets.create(
87 alice,
88 USDT_ASSET_ID,
89 alice.address,
90 USDT_ASSET_METADATA_MINIMAL_BALANCE,
91 );
92 await helper.assets.setMetadata(
93 alice,
94 USDT_ASSET_ID,
95 USDT_ASSET_METADATA_NAME,
96 USDT_ASSET_METADATA_DESCRIPTION,
97 USDT_ASSET_METADATA_DECIMALS,
98 );
99 await helper.assets.mint(
100 alice,
101 USDT_ASSET_ID,
102 alice.address,
103 USDT_ASSET_AMOUNT,
104 );
105
106 // funding parachain sovereing account on Statemint.
107 // The sovereign account should be created before any action
108 // (the assets pallet on Statemint check if the sovereign account exists)
109 const parachainSovereingAccount = helper.address.paraSiblingSovereignAccount(UNIQUE_CHAIN);
110 await helper.balance.transferToSubstrate(bob, parachainSovereingAccount, sovereignFundingAmount);
111 });
112
113
114 await usingPlaygrounds(async (helper) => {
115 const location = {
116 V1: {
117 parents: 1,
118 interior: {X3: [
119 {
120 Parachain: STATEMINT_CHAIN,
121 },
122 {
123 PalletInstance: STATEMINT_PALLET_INSTANCE,
124 },
125 {
126 GeneralIndex: USDT_ASSET_ID,
127 },
128 ]},
129 },
130 };
131
132 const metadata =
133 {
134 name: USDT_ASSET_ID,
135 symbol: USDT_ASSET_METADATA_NAME,
136 decimals: USDT_ASSET_METADATA_DECIMALS,
137 minimalBalance: USDT_ASSET_METADATA_MINIMAL_BALANCE,
138 };
139 await helper.getSudo().foreignAssets.register(alice, alice.address, location, metadata);
140 balanceUniqueBefore = await helper.balance.getSubstrate(alice.address);
141 });
142
143
144 // Providing the relay currency to the unique sender account
145 // (fee for USDT XCM are paid in relay tokens)
146 await usingRelayPlaygrounds(relayUrl, async (helper) => {
147 const destination = {
148 V1: {
149 parents: 0,
150 interior: {X1: {
151 Parachain: UNIQUE_CHAIN,
152 },
153 },
154 }};
155
156 const beneficiary = {
157 V1: {
158 parents: 0,
159 interior: {X1: {
160 AccountId32: {
161 network: 'Any',
162 id: alice.addressRaw,
163 },
164 }},
165 },
166 };
167
168 const assets = {
169 V1: [
170 {
171 id: {
172 Concrete: {
173 parents: 0,
174 interior: 'Here',
175 },
176 },
177 fun: {
178 Fungible: TRANSFER_AMOUNT_RELAY,
179 },
180 },
181 ],
182 };
183
184 const feeAssetItem = 0;
185
186 await helper.xcm.limitedReserveTransferAssets(alice, destination, beneficiary, assets, feeAssetItem, {Unlimited: null});
187 });
188
189 });
190
191 itSub('Should connect and send USDT from Statemint to Unique', async ({helper}) => {
192 await usingStatemintPlaygrounds(statemintUrl, async (helper) => {
193 const dest = {
194 V1: {
195 parents: 1,
196 interior: {X1: {
197 Parachain: UNIQUE_CHAIN,
198 },
199 },
200 }};
201
202 const beneficiary = {
203 V1: {
204 parents: 0,
205 interior: {X1: {
206 AccountId32: {
207 network: 'Any',
208 id: alice.addressRaw,
209 },
210 }},
211 },
212 };
213
214 const assets = {
215 V1: [
216 {
217 id: {
218 Concrete: {
219 parents: 0,
220 interior: {
221 X2: [
222 {
223 PalletInstance: STATEMINT_PALLET_INSTANCE,
224 },
225 {
226 GeneralIndex: USDT_ASSET_ID,
227 },
228 ]},
229 },
230 },
231 fun: {
232 Fungible: TRANSFER_AMOUNT,
233 },
234 },
235 ],
236 };
237
238 const feeAssetItem = 0;
239
240 balanceStmnBefore = await helper.balance.getSubstrate(alice.address);
241 await helper.xcm.limitedReserveTransferAssets(alice, dest, beneficiary, assets, feeAssetItem, {Unlimited: null});
242
243 balanceStmnAfter = await helper.balance.getSubstrate(alice.address);
244
245 // common good parachain take commission in it native token
246 console.log(
247 '[Statemint -> Unique] transaction fees on Statemint: %s WND',
248 helper.util.bigIntToDecimals(balanceStmnBefore - balanceStmnAfter, STATEMINT_DECIMALS),
249 );
250 expect(balanceStmnBefore > balanceStmnAfter).to.be.true;
251
252 });
253
254
255 // ensure that asset has been delivered
256 await helper.wait.newBlocks(3);
257
258 // expext collection id will be with id 1
259 const free = await helper.ft.getBalance(1, {Substrate: alice.address});
260
261 balanceUniqueAfter = await helper.balance.getSubstrate(alice.address);
262
263 console.log(
264 '[Statemint -> Unique] transaction fees on Unique: %s USDT',
265 helper.util.bigIntToDecimals(TRANSFER_AMOUNT - free, USDT_ASSET_METADATA_DECIMALS),
266 );
267 console.log(
268 '[Statemint -> Unique] transaction fees on Unique: %s UNQ',
269 helper.util.bigIntToDecimals(balanceUniqueAfter - balanceUniqueBefore),
270 );
271 // commission has not paid in USDT token
272 expect(free).to.be.equal(TRANSFER_AMOUNT);
273 // ... and parachain native token
274 expect(balanceUniqueAfter == balanceUniqueBefore).to.be.true;
275 });
276
277 itSub('Should connect and send USDT from Unique to Statemint back', async ({helper}) => {
278 const destination = {
279 V1: {
280 parents: 1,
281 interior: {X2: [
282 {
283 Parachain: STATEMINT_CHAIN,
284 },
285 {
286 AccountId32: {
287 network: 'Any',
288 id: alice.addressRaw,
289 },
290 },
291 ]},
292 },
293 };
294
295 const relayFee = 400_000_000_000_000n;
296 const currencies: [any, bigint][] = [
297 [
298 {
299 ForeignAssetId: 0,
300 },
301 TRANSFER_AMOUNT,
302 ],
303 [
304 {
305 NativeAssetId: 'Parent',
306 },
307 relayFee,
308 ],
309 ];
310
311 const feeItem = 1;
312
313 await helper.xTokens.transferMulticurrencies(alice, currencies, feeItem, destination, {Unlimited: null});
314
315 // the commission has been paid in parachain native token
316 balanceUniqueFinal = await helper.balance.getSubstrate(alice.address);
317 console.log('[Unique -> Statemint] transaction fees on Unique: %s UNQ', helper.util.bigIntToDecimals(balanceUniqueFinal - balanceUniqueAfter));
318 expect(balanceUniqueAfter > balanceUniqueFinal).to.be.true;
319
320 await usingStatemintPlaygrounds(statemintUrl, async (helper) => {
321 await helper.wait.newBlocks(3);
322
323 // The USDT token never paid fees. Its amount not changed from begin value.
324 // Also check that xcm transfer has been succeeded
325 expect((await helper.assets.account(USDT_ASSET_ID, alice.address))! == USDT_ASSET_AMOUNT).to.be.true;
326 });
327 });
328
329 itSub('Should connect and send Relay token to Unique', async ({helper}) => {
330 balanceBobBefore = await helper.balance.getSubstrate(bob.address);
331 balanceBobRelayTokenBefore = await helper.tokens.accounts(bob.address, {NativeAssetId: 'Parent'});
332
333 await usingRelayPlaygrounds(relayUrl, async (helper) => {
334 const destination = {
335 V1: {
336 parents: 0,
337 interior: {X1: {
338 Parachain: UNIQUE_CHAIN,
339 },
340 },
341 }};
342
343 const beneficiary = {
344 V1: {
345 parents: 0,
346 interior: {X1: {
347 AccountId32: {
348 network: 'Any',
349 id: bob.addressRaw,
350 },
351 }},
352 },
353 };
354
355 const assets = {
356 V1: [
357 {
358 id: {
359 Concrete: {
360 parents: 0,
361 interior: 'Here',
362 },
363 },
364 fun: {
365 Fungible: TRANSFER_AMOUNT_RELAY,
366 },
367 },
368 ],
369 };
370
371 const feeAssetItem = 0;
372
373 await helper.xcm.limitedReserveTransferAssets(bob, destination, beneficiary, assets, feeAssetItem, {Unlimited: null});
374 });
375
376 await helper.wait.newBlocks(3);
377
378 balanceBobAfter = await helper.balance.getSubstrate(bob.address);
379 balanceBobRelayTokenAfter = await helper.tokens.accounts(bob.address, {NativeAssetId: 'Parent'});
380
381 const wndFeeOnUnique = balanceBobRelayTokenAfter - TRANSFER_AMOUNT_RELAY - balanceBobRelayTokenBefore;
382 const wndDiffOnUnique = balanceBobRelayTokenAfter - balanceBobRelayTokenBefore;
383 console.log(
384 '[Relay (Westend) -> Unique] transaction fees: %s UNQ',
385 helper.util.bigIntToDecimals(balanceBobAfter - balanceBobBefore),
386 );
387 console.log(
388 '[Relay (Westend) -> Unique] transaction fees: %s WND',
389 helper.util.bigIntToDecimals(wndFeeOnUnique, STATEMINT_DECIMALS),
390 );
391 console.log('[Relay (Westend) -> Unique] actually delivered: %s WND', wndDiffOnUnique);
392 expect(wndFeeOnUnique == 0n, 'No incoming WND fees should be taken').to.be.true;
393 expect(balanceBobBefore == balanceBobAfter, 'No incoming UNQ fees should be taken').to.be.true;
394 });
395
396 itSub('Should connect and send Relay token back', async ({helper}) => {
397 let relayTokenBalanceBefore: bigint;
398 let relayTokenBalanceAfter: bigint;
399 await usingRelayPlaygrounds(relayUrl, async (helper) => {
400 relayTokenBalanceBefore = await helper.balance.getSubstrate(bob.address);
401 });
402
403 const destination = {
404 V1: {
405 parents: 1,
406 interior: {
407 X1:{
408 AccountId32: {
409 network: 'Any',
410 id: bob.addressRaw,
411 },
412 },
413 },
414 },
415 };
416
417 const currencies: any = [
418 [
419 {
420 NativeAssetId: 'Parent',
421 },
422 TRANSFER_AMOUNT_RELAY,
423 ],
424 ];
425
426 const feeItem = 0;
427
428 await helper.xTokens.transferMulticurrencies(bob, currencies, feeItem, destination, {Unlimited: null});
429
430 balanceBobFinal = await helper.balance.getSubstrate(bob.address);
431 console.log('[Unique -> Relay (Westend)] transaction fees: %s UNQ', helper.util.bigIntToDecimals(balanceBobAfter - balanceBobFinal));
432
433 await usingRelayPlaygrounds(relayUrl, async (helper) => {
434 await helper.wait.newBlocks(10);
435 relayTokenBalanceAfter = await helper.balance.getSubstrate(bob.address);
436
437 const diff = relayTokenBalanceAfter - relayTokenBalanceBefore;
438 console.log('[Unique -> Relay (Westend)] actually delivered: %s WND', helper.util.bigIntToDecimals(diff, RELAY_DECIMALS));
439 expect(diff > 0, 'Relay tokens was not delivered back').to.be.true;
440 });
441 });
442});
443
35describeXCM('[XCM] Integration test: Exchanging tokens with Acala', () => {444describeXCM('[XCM] Integration test: Exchanging tokens with Acala', () => {
36 let alice: IKeyringPair;445 let alice: IKeyringPair;
124 };533 };
125534
126 const feeAssetItem = 0;535 const feeAssetItem = 0;
127 const weightLimit = 5000000000;
128536
129 await helper.xcm.limitedReserveTransferAssets(randomAccount, destination, beneficiary, assets, feeAssetItem, weightLimit);537 await helper.xcm.limitedReserveTransferAssets(randomAccount, destination, beneficiary, assets, feeAssetItem, {Unlimited: null});
130
131 balanceUniqueTokenMiddle = await helper.balance.getSubstrate(randomAccount.address);538 balanceUniqueTokenMiddle = await helper.balance.getSubstrate(randomAccount.address);
132539
133 const unqFees = balanceUniqueTokenInit - balanceUniqueTokenMiddle - TRANSFER_AMOUNT;540 const unqFees = balanceUniqueTokenInit - balanceUniqueTokenMiddle - TRANSFER_AMOUNT;
134 console.log('[Unique -> Acala] transaction fees on Unique: %s UNQ', helper.util.bigIntToDecimals(unqFees));541 console.log('[Unique -> Acala] transaction fees on Unique: %s UNQ', helper.util.bigIntToDecimals(unqFees));
135 expect(unqFees > 0n).to.be.true;542 expect(unqFees > 0n, 'Negative fees UNQ, looks like nothing was transferred').to.be.true;
136543
137 await usingAcalaPlaygrounds(acalaUrl, async (helper) => {544 await usingAcalaPlaygrounds(acalaUrl, async (helper) => {
138 await helper.wait.newBlocks(3);545 await helper.wait.newBlocks(3);
176 ForeignAsset: 0,583 ForeignAsset: 0,
177 };584 };
178585
179 const destWeight = 50000000;586 await helper.xTokens.transfer(randomAccount, id, TRANSFER_AMOUNT, destination, {Unlimited: null});
180
181 await helper.xTokens.transfer(randomAccount, id, TRANSFER_AMOUNT, destination, destWeight);
182
183 balanceAcalaTokenFinal = await helper.balance.getSubstrate(randomAccount.address);587 balanceAcalaTokenFinal = await helper.balance.getSubstrate(randomAccount.address);
184 balanceUniqueForeignTokenFinal = await helper.tokens.accounts(randomAccount.address, id);588 balanceUniqueForeignTokenFinal = await helper.tokens.accounts(randomAccount.address, id);
192 );596 );
193 console.log('[Acala -> Unique] outcome %s UNQ', helper.util.bigIntToDecimals(unqOutcomeTransfer));597 console.log('[Acala -> Unique] outcome %s UNQ', helper.util.bigIntToDecimals(unqOutcomeTransfer));
194598
195 expect(acaFees > 0).to.be.true;599 expect(acaFees > 0, 'Negative fees ACA, looks like nothing was transferred').to.be.true;
196 expect(unqOutcomeTransfer == TRANSFER_AMOUNT).to.be.true;600 expect(unqOutcomeTransfer == TRANSFER_AMOUNT).to.be.true;
197 });601 });
198602
220 });624 });
221 });625 });
222626
223 itSub('Unique rejects tokens from the Relay', async ({helper}) => {
224 await usingRelayPlaygrounds(relayUrl, async (helper) => {
225 const destination = {
226 V1: {
227 parents: 0,
228 interior: {X1: {
229 Parachain: UNIQUE_CHAIN,
230 },
231 },
232 }};
233
234 const beneficiary = {
235 V1: {
236 parents: 0,
237 interior: {X1: {
238 AccountId32: {
239 network: 'Any',
240 id: alice.addressRaw,
241 },
242 }},
243 },
244 };
245
246 const assets = {
247 V1: [
248 {
249 id: {
250 Concrete: {
251 parents: 0,
252 interior: 'Here',
253 },
254 },
255 fun: {
256 Fungible: 50_000_000_000_000_000n,
257 },
258 },
259 ],
260 };
261
262 const feeAssetItem = 0;
263 const weightLimit = 5_000_000_000;
264
265 await helper.xcm.limitedReserveTransferAssets(alice, destination, beneficiary, assets, feeAssetItem, weightLimit);
266 });
267
268 const maxWaitBlocks = 3;
269
270 const dmpQueueExecutedDownward = await helper.wait.event(maxWaitBlocks, 'dmpQueue', 'ExecutedDownward');
271
272 expect(
273 dmpQueueExecutedDownward != null,
274 '[Relay] dmpQueue.ExecutedDownward event is expected',
275 ).to.be.true;
276
277 const event = dmpQueueExecutedDownward!.event;
278 const outcome = event.data[1] as XcmV2TraitsOutcome;
279
280 expect(
281 outcome.isIncomplete,
282 '[Relay] The outcome of the XCM should be `Incomplete`',
283 ).to.be.true;
284
285 const incomplete = outcome.asIncomplete;
286 expect(
287 incomplete[1].toString() == 'AssetNotFound',
288 '[Relay] The XCM error should be `AssetNotFound`',
289 ).to.be.true;
290 });
291
292 itSub('Unique rejects ACA tokens from Acala', async ({helper}) => {627 itSub('Unique rejects ACA tokens from Acala', async ({helper}) => {
293 await usingAcalaPlaygrounds(acalaUrl, async (helper) => {628 await usingAcalaPlaygrounds(acalaUrl, async (helper) => {
294 const destination = {629 const destination = {
311 const id = {646 const id = {
312 Token: 'ACA',647 Token: 'ACA',
313 };648 };
314
315 const destWeight = 50000000;
316649
317 await helper.xTokens.transfer(alice, id, 100_000_000_000n, destination, destWeight);650 await helper.xTokens.transfer(alice, id, 100_000_000_000n, destination, {Unlimited: null});
318 });651 });
319652
320 const maxWaitBlocks = 3;653 const maxWaitBlocks = 3;
330 const outcome = event.data[1] as XcmV2TraitsError;663 const outcome = event.data[1] as XcmV2TraitsError;
331664
332 expect(665 expect(
333 outcome.isUntrustedReserveLocation,666 outcome.isFailedToTransactAsset,
334 '[Acala] The XCM error should be `UntrustedReserveLocation`',667 '[Acala] The XCM error should be `FailedToTransactAsset`',
335 ).to.be.true;668 ).to.be.true;
336 });669 });
337});670});
508 },841 },
509 };842 };
510 const amount = TRANSFER_AMOUNT;843 const amount = TRANSFER_AMOUNT;
511 const destWeight = 850000000;
512844
513 await helper.xTokens.transfer(randomAccountUnique, currencyId, amount, dest, destWeight);845 await helper.xTokens.transfer(randomAccountUnique, currencyId, amount, dest, {Unlimited: null});
514846
515 balanceUniqueTokenMiddle = await helper.balance.getSubstrate(randomAccountUnique.address);847 balanceUniqueTokenMiddle = await helper.balance.getSubstrate(randomAccountUnique.address);
516 expect(balanceUniqueTokenMiddle < balanceUniqueTokenInit).to.be.true;848 expect(balanceUniqueTokenMiddle < balanceUniqueTokenInit).to.be.true;
517849
518 const transactionFees = balanceUniqueTokenInit - balanceUniqueTokenMiddle - TRANSFER_AMOUNT;850 const transactionFees = balanceUniqueTokenInit - balanceUniqueTokenMiddle - TRANSFER_AMOUNT;
519 console.log('[Unique -> Moonbeam] transaction fees on Unique: %s UNQ', helper.util.bigIntToDecimals(transactionFees));851 console.log('[Unique -> Moonbeam] transaction fees on Unique: %s UNQ', helper.util.bigIntToDecimals(transactionFees));
520 expect(transactionFees > 0).to.be.true;852 expect(transactionFees > 0, 'Negative fees UNQ, looks like nothing was transferred').to.be.true;
521853
522 await usingMoonbeamPlaygrounds(moonbeamUrl, async (helper) => {854 await usingMoonbeamPlaygrounds(moonbeamUrl, async (helper) => {
523 await helper.wait.newBlocks(3);855 await helper.wait.newBlocks(3);
572904
573 const glmrFees = balanceGlmrTokenMiddle - balanceGlmrTokenFinal;905 const glmrFees = balanceGlmrTokenMiddle - balanceGlmrTokenFinal;
574 console.log('[Moonbeam -> Unique] transaction fees on Moonbeam: %s GLMR', helper.util.bigIntToDecimals(glmrFees));906 console.log('[Moonbeam -> Unique] transaction fees on Moonbeam: %s GLMR', helper.util.bigIntToDecimals(glmrFees));
575 expect(glmrFees > 0).to.be.true;907 expect(glmrFees > 0, 'Negative fees GLMR, looks like nothing was transferred').to.be.true;
576908
577 const unqRandomAccountAsset = await helper.assets.account(assetId, randomAccountMoonbeam.address);909 const unqRandomAccountAsset = await helper.assets.account(assetId, randomAccountMoonbeam.address);
578910