1234567891011121314151617import {IKeyringPair} from '@polkadot/types/types';18import {blake2AsHex} from '@polkadot/util-crypto';19import config from '../config';20import {XcmV2TraitsError} from '../interfaces';21import {itSub, expect, describeXCM, usingPlaygrounds, usingAcalaPlaygrounds, usingRelayPlaygrounds, usingMoonbeamPlaygrounds, usingStatemintPlaygrounds} from '../util';2223const UNIQUE_CHAIN = 2037;24const STATEMINT_CHAIN = 1000;25const ACALA_CHAIN = 2000;26const MOONBEAM_CHAIN = 2004;2728const STATEMINT_PALLET_INSTANCE = 50;2930const relayUrl = config.relayUrl;31const statemintUrl = config.statemintUrl;32const acalaUrl = config.acalaUrl;33const moonbeamUrl = config.moonbeamUrl;3435const RELAY_DECIMALS = 12;36const STATEMINT_DECIMALS = 12;37const ACALA_DECIMALS = 12;3839const TRANSFER_AMOUNT = 2000000000000000000000000n;4041const FUNDING_AMOUNT = 3_500_000_0000_000_000n;4243const TRANSFER_AMOUNT_RELAY = 50_000_000_000_000_000n;4445const 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;5152describeXCM('[XCM] Integration test: Exchanging USDT with Statemint', () => {53 let alice: IKeyringPair;54 let bob: IKeyringPair;5556 let balanceStmnBefore: bigint;57 let balanceStmnAfter: bigint;5859 let balanceUniqueBefore: bigint;60 let balanceUniqueAfter: bigint;61 let balanceUniqueFinal: bigint;6263 let balanceBobBefore: bigint;64 let balanceBobAfter: bigint;65 let balanceBobFinal: bigint;6667 let balanceBobRelayTokenBefore: bigint;68 let balanceBobRelayTokenAfter: bigint;697071 before(async () => {72 await usingPlaygrounds(async (_helper, privateKey) => {73 alice = await privateKey('//Alice');74 bob = await privateKey('//Bob'); 75 });7677 await usingRelayPlaygrounds(relayUrl, async (helper) => {78 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 });8283 await usingStatemintPlaygrounds(statemintUrl, async (helper) => {84 const sovereignFundingAmount = 3_500_000_000n;8586 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 );105106 107 108 109 const parachainSovereingAccount = helper.address.paraSiblingSovereignAccount(UNIQUE_CHAIN);110 await helper.balance.transferToSubstrate(bob, parachainSovereingAccount, sovereignFundingAmount);111 });112113114 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 };131132 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 });142143144 145 146 await usingRelayPlaygrounds(relayUrl, async (helper) => {147 const destination = {148 V1: {149 parents: 0,150 interior: {X1: {151 Parachain: UNIQUE_CHAIN,152 },153 },154 }};155156 const beneficiary = {157 V1: {158 parents: 0,159 interior: {X1: {160 AccountId32: {161 network: 'Any',162 id: alice.addressRaw,163 },164 }},165 },166 };167168 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 };183184 const feeAssetItem = 0;185186 await helper.xcm.limitedReserveTransferAssets(alice, destination, beneficiary, assets, feeAssetItem, 'Unlimited');187 });188189 });190191 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 }};201202 const beneficiary = {203 V1: {204 parents: 0,205 interior: {X1: {206 AccountId32: {207 network: 'Any',208 id: alice.addressRaw,209 },210 }},211 },212 };213214 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 };237238 const feeAssetItem = 0;239240 balanceStmnBefore = await helper.balance.getSubstrate(alice.address);241 await helper.xcm.limitedReserveTransferAssets(alice, dest, beneficiary, assets, feeAssetItem, 'Unlimited');242243 balanceStmnAfter = await helper.balance.getSubstrate(alice.address);244245 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;251252 });253254255 256 await helper.wait.newBlocks(3);257258 259 const free = await helper.ft.getBalance(1, {Substrate: alice.address});260261 balanceUniqueAfter = await helper.balance.getSubstrate(alice.address);262263 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 272 expect(free).to.be.equal(TRANSFER_AMOUNT);273 274 expect(balanceUniqueAfter == balanceUniqueBefore).to.be.true;275 });276277 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 };294295 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 ];310311 const feeItem = 1;312313 await helper.xTokens.transferMulticurrencies(alice, currencies, feeItem, destination, 'Unlimited');314315 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;319320 await usingStatemintPlaygrounds(statemintUrl, async (helper) => {321 await helper.wait.newBlocks(3);322323 324 325 expect((await helper.assets.account(USDT_ASSET_ID, alice.address))! == USDT_ASSET_AMOUNT).to.be.true;326 });327 });328329 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'});332333 await usingRelayPlaygrounds(relayUrl, async (helper) => {334 const destination = {335 V1: {336 parents: 0,337 interior: {X1: {338 Parachain: UNIQUE_CHAIN,339 },340 },341 }};342343 const beneficiary = {344 V1: {345 parents: 0,346 interior: {X1: {347 AccountId32: {348 network: 'Any',349 id: bob.addressRaw,350 },351 }},352 },353 };354355 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 };370371 const feeAssetItem = 0;372373 await helper.xcm.limitedReserveTransferAssets(bob, destination, beneficiary, assets, feeAssetItem, 'Unlimited');374 });375376 await helper.wait.newBlocks(3);377378 balanceBobAfter = await helper.balance.getSubstrate(bob.address);379 balanceBobRelayTokenAfter = await helper.tokens.accounts(bob.address, {NativeAssetId: 'Parent'});380381 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 });395396 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 });402403 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 };416417 const currencies: any = [418 [419 {420 NativeAssetId: 'Parent',421 },422 TRANSFER_AMOUNT_RELAY,423 ],424 ];425426 const feeItem = 0;427428 await helper.xTokens.transferMulticurrencies(bob, currencies, feeItem, destination, 'Unlimited');429430 balanceBobFinal = await helper.balance.getSubstrate(bob.address);431 console.log('[Unique -> Relay (Westend)] transaction fees: %s UNQ', helper.util.bigIntToDecimals(balanceBobAfter - balanceBobFinal));432433 await usingRelayPlaygrounds(relayUrl, async (helper) => {434 await helper.wait.newBlocks(10);435 relayTokenBalanceAfter = await helper.balance.getSubstrate(bob.address);436437 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});443444describeXCM('[XCM] Integration test: Exchanging tokens with Acala', () => {445 let alice: IKeyringPair;446 let randomAccount: IKeyringPair;447448 let balanceUniqueTokenInit: bigint;449 let balanceUniqueTokenMiddle: bigint;450 let balanceUniqueTokenFinal: bigint;451 let balanceAcalaTokenInit: bigint;452 let balanceAcalaTokenMiddle: bigint;453 let balanceAcalaTokenFinal: bigint;454 let balanceUniqueForeignTokenInit: bigint;455 let balanceUniqueForeignTokenMiddle: bigint;456 let balanceUniqueForeignTokenFinal: bigint;457458 before(async () => {459 await usingPlaygrounds(async (helper, privateKey) => {460 alice = await privateKey('//Alice');461 [randomAccount] = await helper.arrange.createAccounts([0n], alice);462 });463464 await usingAcalaPlaygrounds(acalaUrl, async (helper) => {465 const destination = {466 V1: {467 parents: 1,468 interior: {469 X1: {470 Parachain: UNIQUE_CHAIN,471 },472 },473 },474 };475476 const metadata = {477 name: 'UNQ',478 symbol: 'UNQ',479 decimals: 18,480 minimalBalance: 1n,481 };482483 await helper.getSudo().assetRegistry.registerForeignAsset(alice, destination, metadata);484 await helper.balance.transferToSubstrate(alice, randomAccount.address, 10000000000000n);485 balanceAcalaTokenInit = await helper.balance.getSubstrate(randomAccount.address);486 balanceUniqueForeignTokenInit = await helper.tokens.accounts(randomAccount.address, {ForeignAsset: 0});487 });488489 await usingPlaygrounds(async (helper) => {490 await helper.balance.transferToSubstrate(alice, randomAccount.address, 10n * TRANSFER_AMOUNT);491 balanceUniqueTokenInit = await helper.balance.getSubstrate(randomAccount.address);492 });493 });494495 itSub('Should connect and send UNQ to Acala', async ({helper}) => {496497 const destination = {498 V1: {499 parents: 1,500 interior: {501 X1: {502 Parachain: ACALA_CHAIN,503 },504 },505 },506 };507508 const beneficiary = {509 V1: {510 parents: 0,511 interior: {512 X1: {513 AccountId32: {514 network: 'Any',515 id: randomAccount.addressRaw,516 },517 },518 },519 },520 };521522 const assets = {523 V1: [524 {525 id: {526 Concrete: {527 parents: 0,528 interior: 'Here',529 },530 },531 fun: {532 Fungible: TRANSFER_AMOUNT,533 },534 },535 ],536 };537538 const feeAssetItem = 0;539540 await helper.xcm.limitedReserveTransferAssets(randomAccount, destination, beneficiary, assets, feeAssetItem, 'Unlimited');541 balanceUniqueTokenMiddle = await helper.balance.getSubstrate(randomAccount.address);542543 const unqFees = balanceUniqueTokenInit - balanceUniqueTokenMiddle - TRANSFER_AMOUNT;544 console.log('[Unique -> Acala] transaction fees on Unique: %s UNQ', helper.util.bigIntToDecimals(unqFees));545 expect(unqFees > 0n, 'Negative fees UNQ, looks like nothing was transferred').to.be.true;546547 await usingAcalaPlaygrounds(acalaUrl, async (helper) => {548 await helper.wait.newBlocks(3);549550 balanceUniqueForeignTokenMiddle = await helper.tokens.accounts(randomAccount.address, {ForeignAsset: 0});551 balanceAcalaTokenMiddle = await helper.balance.getSubstrate(randomAccount.address);552553 const acaFees = balanceAcalaTokenInit - balanceAcalaTokenMiddle;554 const unqIncomeTransfer = balanceUniqueForeignTokenMiddle - balanceUniqueForeignTokenInit;555556 console.log(557 '[Unique -> Acala] transaction fees on Acala: %s ACA',558 helper.util.bigIntToDecimals(acaFees, ACALA_DECIMALS),559 );560 console.log('[Unique -> Acala] income %s UNQ', helper.util.bigIntToDecimals(unqIncomeTransfer));561 expect(acaFees == 0n).to.be.true;562 expect(unqIncomeTransfer == TRANSFER_AMOUNT).to.be.true;563 });564 });565566 itSub('Should connect to Acala and send UNQ back', async ({helper}) => {567 await usingAcalaPlaygrounds(acalaUrl, async (helper) => {568 const destination = {569 V1: {570 parents: 1,571 interior: {572 X2: [573 {Parachain: UNIQUE_CHAIN},574 {575 AccountId32: {576 network: 'Any',577 id: randomAccount.addressRaw,578 },579 },580 ],581 },582 },583 };584585 const id = {586 ForeignAsset: 0,587 };588589 await helper.xTokens.transfer(randomAccount, id, TRANSFER_AMOUNT, destination, 'Unlimited');590 balanceAcalaTokenFinal = await helper.balance.getSubstrate(randomAccount.address);591 balanceUniqueForeignTokenFinal = await helper.tokens.accounts(randomAccount.address, id);592593 const acaFees = balanceAcalaTokenMiddle - balanceAcalaTokenFinal;594 const unqOutcomeTransfer = balanceUniqueForeignTokenMiddle - balanceUniqueForeignTokenFinal;595596 console.log(597 '[Acala -> Unique] transaction fees on Acala: %s ACA',598 helper.util.bigIntToDecimals(acaFees, ACALA_DECIMALS),599 );600 console.log('[Acala -> Unique] outcome %s UNQ', helper.util.bigIntToDecimals(unqOutcomeTransfer));601602 expect(acaFees > 0, 'Negative fees ACA, looks like nothing was transferred').to.be.true;603 expect(unqOutcomeTransfer == TRANSFER_AMOUNT).to.be.true;604 });605606 await helper.wait.newBlocks(3);607608 balanceUniqueTokenFinal = await helper.balance.getSubstrate(randomAccount.address);609 const actuallyDelivered = balanceUniqueTokenFinal - balanceUniqueTokenMiddle;610 expect(actuallyDelivered > 0).to.be.true;611612 console.log('[Acala -> Unique] actually delivered %s UNQ', helper.util.bigIntToDecimals(actuallyDelivered));613614 const unqFees = TRANSFER_AMOUNT - actuallyDelivered;615 console.log('[Acala -> Unique] transaction fees on Unique: %s UNQ', helper.util.bigIntToDecimals(unqFees));616 expect(unqFees == 0n).to.be.true;617 });618});619620621describeXCM('[XCM] Integration test: Unique rejects non-native tokens', () => {622 let alice: IKeyringPair;623624 before(async () => {625 await usingPlaygrounds(async (_helper, privateKey) => {626 alice = await privateKey('//Alice');627 });628 });629630 itSub('Unique rejects ACA tokens from Acala', async ({helper}) => {631 await usingAcalaPlaygrounds(acalaUrl, async (helper) => {632 const destination = {633 V1: {634 parents: 1,635 interior: {636 X2: [637 {Parachain: UNIQUE_CHAIN},638 {639 AccountId32: {640 network: 'Any',641 id: alice.addressRaw,642 },643 },644 ],645 },646 },647 };648649 const id = {650 Token: 'ACA',651 };652653 await helper.xTokens.transfer(alice, id, 100_000_000_000n, destination, 'Unlimited');654 });655656 const maxWaitBlocks = 3;657658 const xcmpQueueFailEvent = await helper.wait.event(maxWaitBlocks, 'xcmpQueue', 'Fail');659660 expect(661 xcmpQueueFailEvent != null,662 '[Acala] xcmpQueue.FailEvent event is expected',663 ).to.be.true;664665 const event = xcmpQueueFailEvent!.event;666 const outcome = event.data[1] as XcmV2TraitsError;667668 expect(669 outcome.isFailedToTransactAsset,670 '[Acala] The XCM error should be `FailedToTransactAsset`',671 ).to.be.true;672 });673});674675describeXCM('[XCM] Integration test: Exchanging UNQ with Moonbeam', () => {676 677 let uniqueDonor: IKeyringPair;678 let uniqueAssetLocation;679680 let randomAccountUnique: IKeyringPair;681 let randomAccountMoonbeam: IKeyringPair;682683 684 let assetId: string;685686 const councilVotingThreshold = 2;687 const technicalCommitteeThreshold = 2;688 const votingPeriod = 3;689 const delayPeriod = 0;690691 const uniqueAssetMetadata = {692 name: 'xcUnique',693 symbol: 'xcUNQ',694 decimals: 18,695 isFrozen: false,696 minimalBalance: 1n,697 };698699 let balanceUniqueTokenInit: bigint;700 let balanceUniqueTokenMiddle: bigint;701 let balanceUniqueTokenFinal: bigint;702 let balanceForeignUnqTokenInit: bigint;703 let balanceForeignUnqTokenMiddle: bigint;704 let balanceForeignUnqTokenFinal: bigint;705 let balanceGlmrTokenInit: bigint;706 let balanceGlmrTokenMiddle: bigint;707 let balanceGlmrTokenFinal: bigint;708709 before(async () => {710 await usingPlaygrounds(async (helper, privateKey) => {711 uniqueDonor = await privateKey('//Alice');712 [randomAccountUnique] = await helper.arrange.createAccounts([0n], uniqueDonor);713714 balanceForeignUnqTokenInit = 0n;715 });716717 await usingMoonbeamPlaygrounds(moonbeamUrl, async (helper) => {718 const alithAccount = helper.account.alithAccount();719 const baltatharAccount = helper.account.baltatharAccount();720 const dorothyAccount = helper.account.dorothyAccount();721722 randomAccountMoonbeam = helper.account.create();723724 725 console.log('Sponsoring Dorothy.......');726 await helper.balance.transferToEthereum(alithAccount, dorothyAccount.address, 11_000_000_000_000_000_000n);727 console.log('Sponsoring Dorothy.......DONE');728 729730 uniqueAssetLocation = {731 XCM: {732 parents: 1,733 interior: {X1: {Parachain: UNIQUE_CHAIN}},734 },735 };736 const existentialDeposit = 1n;737 const isSufficient = true;738 const unitsPerSecond = 1n;739 const numAssetsWeightHint = 0;740741 const encodedProposal = helper.assetManager.makeRegisterForeignAssetProposal({742 location: uniqueAssetLocation,743 metadata: uniqueAssetMetadata,744 existentialDeposit,745 isSufficient,746 unitsPerSecond,747 numAssetsWeightHint,748 });749 const proposalHash = blake2AsHex(encodedProposal);750751 console.log('Encoded proposal for registerForeignAsset & setAssetUnitsPerSecond is %s', encodedProposal);752 console.log('Encoded length %d', encodedProposal.length);753 console.log('Encoded proposal hash for batch utility after schedule is %s', proposalHash);754755 756 console.log('Note motion preimage.......');757 await helper.democracy.notePreimage(baltatharAccount, encodedProposal);758 console.log('Note motion preimage.......DONE');759 760761 762 console.log('Propose external motion through council.......');763 const externalMotion = helper.democracy.externalProposeMajority(proposalHash);764 const encodedMotion = externalMotion?.method.toHex() || '';765 const motionHash = blake2AsHex(encodedMotion);766 console.log('Motion hash is %s', motionHash);767768 await helper.collective.council.propose(baltatharAccount, councilVotingThreshold, externalMotion, externalMotion.encodedLength);769770 const councilProposalIdx = await helper.collective.council.proposalCount() - 1;771 await helper.collective.council.vote(dorothyAccount, motionHash, councilProposalIdx, true);772 await helper.collective.council.vote(baltatharAccount, motionHash, councilProposalIdx, true);773774 await helper.collective.council.close(dorothyAccount, motionHash, councilProposalIdx, 1_000_000_000, externalMotion.encodedLength);775 console.log('Propose external motion through council.......DONE');776 777778 779 console.log('Fast track proposal through technical committee.......');780 const fastTrack = helper.democracy.fastTrack(proposalHash, votingPeriod, delayPeriod);781 const encodedFastTrack = fastTrack?.method.toHex() || '';782 const fastTrackHash = blake2AsHex(encodedFastTrack);783 console.log('FastTrack hash is %s', fastTrackHash);784785 await helper.collective.techCommittee.propose(alithAccount, technicalCommitteeThreshold, fastTrack, fastTrack.encodedLength);786787 const techProposalIdx = await helper.collective.techCommittee.proposalCount() - 1;788 await helper.collective.techCommittee.vote(baltatharAccount, fastTrackHash, techProposalIdx, true);789 await helper.collective.techCommittee.vote(alithAccount, fastTrackHash, techProposalIdx, true);790791 await helper.collective.techCommittee.close(baltatharAccount, fastTrackHash, techProposalIdx, 1_000_000_000, fastTrack.encodedLength);792 console.log('Fast track proposal through technical committee.......DONE');793 794795 796 console.log('Referendum voting.......');797 await helper.democracy.referendumVote(dorothyAccount, 0, {798 balance: 10_000_000_000_000_000_000n,799 vote: {aye: true, conviction: 1},800 });801 console.log('Referendum voting.......DONE');802 803804 805 console.log('Acquire Unique AssetId Info on Moonbeam.......');806807 808 await helper.wait.newBlocks(5);809810 assetId = (await helper.assetManager.assetTypeId(uniqueAssetLocation)).toString();811812 console.log('UNQ asset ID is %s', assetId);813 console.log('Acquire Unique AssetId Info on Moonbeam.......DONE');814 815816 817 console.log('Sponsoring random Account.......');818 await helper.balance.transferToEthereum(baltatharAccount, randomAccountMoonbeam.address, 11_000_000_000_000_000_000n);819 console.log('Sponsoring random Account.......DONE');820 821822 balanceGlmrTokenInit = await helper.balance.getEthereum(randomAccountMoonbeam.address);823 });824825 await usingPlaygrounds(async (helper) => {826 await helper.balance.transferToSubstrate(uniqueDonor, randomAccountUnique.address, 10n * TRANSFER_AMOUNT);827 balanceUniqueTokenInit = await helper.balance.getSubstrate(randomAccountUnique.address);828 });829 });830831 itSub('Should connect and send UNQ to Moonbeam', async ({helper}) => {832 const currencyId = {833 NativeAssetId: 'Here',834 };835 const dest = {836 V1: {837 parents: 1,838 interior: {839 X2: [840 {Parachain: MOONBEAM_CHAIN},841 {AccountKey20: {network: 'Any', key: randomAccountMoonbeam.address}},842 ],843 },844 },845 };846 const amount = TRANSFER_AMOUNT;847848 await helper.xTokens.transfer(randomAccountUnique, currencyId, amount, dest, 'Unlimited');849850 balanceUniqueTokenMiddle = await helper.balance.getSubstrate(randomAccountUnique.address);851 expect(balanceUniqueTokenMiddle < balanceUniqueTokenInit).to.be.true;852853 const transactionFees = balanceUniqueTokenInit - balanceUniqueTokenMiddle - TRANSFER_AMOUNT;854 console.log('[Unique -> Moonbeam] transaction fees on Unique: %s UNQ', helper.util.bigIntToDecimals(transactionFees));855 expect(transactionFees > 0, 'Negative fees UNQ, looks like nothing was transferred').to.be.true;856857 await usingMoonbeamPlaygrounds(moonbeamUrl, async (helper) => {858 await helper.wait.newBlocks(3);859860 balanceGlmrTokenMiddle = await helper.balance.getEthereum(randomAccountMoonbeam.address);861862 const glmrFees = balanceGlmrTokenInit - balanceGlmrTokenMiddle;863 console.log('[Unique -> Moonbeam] transaction fees on Moonbeam: %s GLMR', helper.util.bigIntToDecimals(glmrFees));864 expect(glmrFees == 0n).to.be.true;865866 balanceForeignUnqTokenMiddle = (await helper.assets.account(assetId, randomAccountMoonbeam.address))!;867868 const unqIncomeTransfer = balanceForeignUnqTokenMiddle - balanceForeignUnqTokenInit;869 console.log('[Unique -> Moonbeam] income %s UNQ', helper.util.bigIntToDecimals(unqIncomeTransfer));870 expect(unqIncomeTransfer == TRANSFER_AMOUNT).to.be.true;871 });872 });873874 itSub('Should connect to Moonbeam and send UNQ back', async ({helper}) => {875 await usingMoonbeamPlaygrounds(moonbeamUrl, async (helper) => {876 const asset = {877 V1: {878 id: {879 Concrete: {880 parents: 1,881 interior: {882 X1: {Parachain: UNIQUE_CHAIN},883 },884 },885 },886 fun: {887 Fungible: TRANSFER_AMOUNT,888 },889 },890 };891 const destination = {892 V1: {893 parents: 1,894 interior: {895 X2: [896 {Parachain: UNIQUE_CHAIN},897 {AccountId32: {network: 'Any', id: randomAccountUnique.addressRaw}},898 ],899 },900 },901 };902 const destWeight = 50000000;903904 await helper.xTokens.transferMultiasset(randomAccountMoonbeam, asset, destination, destWeight);905906 balanceGlmrTokenFinal = await helper.balance.getEthereum(randomAccountMoonbeam.address);907908 const glmrFees = balanceGlmrTokenMiddle - balanceGlmrTokenFinal;909 console.log('[Moonbeam -> Unique] transaction fees on Moonbeam: %s GLMR', helper.util.bigIntToDecimals(glmrFees));910 expect(glmrFees > 0, 'Negative fees GLMR, looks like nothing was transferred').to.be.true;911912 const unqRandomAccountAsset = await helper.assets.account(assetId, randomAccountMoonbeam.address);913914 expect(unqRandomAccountAsset).to.be.null;915916 balanceForeignUnqTokenFinal = 0n;917918 const unqOutcomeTransfer = balanceForeignUnqTokenMiddle - balanceForeignUnqTokenFinal;919 console.log('[Unique -> Moonbeam] outcome %s UNQ', helper.util.bigIntToDecimals(unqOutcomeTransfer));920 expect(unqOutcomeTransfer == TRANSFER_AMOUNT).to.be.true;921 });922923 await helper.wait.newBlocks(3);924925 balanceUniqueTokenFinal = await helper.balance.getSubstrate(randomAccountUnique.address);926 const actuallyDelivered = balanceUniqueTokenFinal - balanceUniqueTokenMiddle;927 expect(actuallyDelivered > 0).to.be.true;928929 console.log('[Moonbeam -> Unique] actually delivered %s UNQ', helper.util.bigIntToDecimals(actuallyDelivered));930931 const unqFees = TRANSFER_AMOUNT - actuallyDelivered;932 console.log('[Moonbeam -> Unique] transaction fees on Unique: %s UNQ', helper.util.bigIntToDecimals(unqFees));933 expect(unqFees == 0n).to.be.true;934 });935});