git.delta.rocks / unique-network / refs/commits / 45e62ca5a277

difftreelog

Remove exclusive tests

Max Andreev2023-03-29parent: #d035b5d.patch.diff
in: master

2 files changed

modifiedtests/src/xcm/xcmQuartz.test.tsdiffbeforeafterboth
after · tests/src/xcm/xcmQuartz.test.ts
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617import {IKeyringPair} from '@polkadot/types/types';18import {blake2AsHex} from '@polkadot/util-crypto';19import config from '../config';20import {XcmV2TraitsError} from '../interfaces';21import {itSub, expect, describeXCM, usingPlaygrounds, usingKaruraPlaygrounds, usingRelayPlaygrounds, usingMoonriverPlaygrounds, usingStateminePlaygrounds, usingShidenPlaygrounds} from '../util';2223const QUARTZ_CHAIN = 2095;24const STATEMINE_CHAIN = 1000;25const KARURA_CHAIN = 2000;26const MOONRIVER_CHAIN = 2023;27const SHIDEN_CHAIN = 2007;2829const STATEMINE_PALLET_INSTANCE = 50;3031const relayUrl = config.relayUrl;32const statemineUrl = config.statemineUrl;33const karuraUrl = config.karuraUrl;34const moonriverUrl = config.moonriverUrl;35const shidenUrl = config.shidenUrl;3637const RELAY_DECIMALS = 12;38const STATEMINE_DECIMALS = 12;39const KARURA_DECIMALS = 12;4041const TRANSFER_AMOUNT = 2000000000000000000000000n;4243const FUNDING_AMOUNT = 3_500_000_0000_000_000n;4445const TRANSFER_AMOUNT_RELAY = 50_000_000_000_000_000n;4647const USDT_ASSET_ID = 100;48const USDT_ASSET_METADATA_DECIMALS = 18;49const USDT_ASSET_METADATA_NAME = 'USDT';50const USDT_ASSET_METADATA_DESCRIPTION = 'USDT';51const USDT_ASSET_METADATA_MINIMAL_BALANCE = 1n;52const USDT_ASSET_AMOUNT = 10_000_000_000_000_000_000_000_000n;5354const SAFE_XCM_VERSION = 2;5556describeXCM('[XCM] Integration test: Exchanging USDT with Statemine', () => {57  let alice: IKeyringPair;58  let bob: IKeyringPair;5960  let balanceStmnBefore: bigint;61  let balanceStmnAfter: bigint;6263  let balanceQuartzBefore: bigint;64  let balanceQuartzAfter: bigint;65  let balanceQuartzFinal: bigint;6667  let balanceBobBefore: bigint;68  let balanceBobAfter: bigint;69  let balanceBobFinal: bigint;7071  let balanceBobRelayTokenBefore: bigint;72  let balanceBobRelayTokenAfter: bigint;737475  before(async () => {76    await usingPlaygrounds(async (helper, privateKey) => {77      alice = await privateKey('//Alice');78      bob = await privateKey('//Bob'); // sovereign account on Statemine(t) funds donor7980      // Set the default version to wrap the first message to other chains.81      await helper.getSudo().xcm.setSafeXcmVersion(alice, SAFE_XCM_VERSION);82    });8384    await usingRelayPlaygrounds(relayUrl, async (helper) => {85      // Fund accounts on Statemine(t)86      await helper.xcm.teleportNativeAsset(alice, STATEMINE_CHAIN, alice.addressRaw, FUNDING_AMOUNT);87      await helper.xcm.teleportNativeAsset(alice, STATEMINE_CHAIN, bob.addressRaw, FUNDING_AMOUNT);88    });8990    await usingStateminePlaygrounds(statemineUrl, async (helper) => {91      const sovereignFundingAmount = 3_500_000_000n;9293      await helper.assets.create(94        alice,95        USDT_ASSET_ID,96        alice.address,97        USDT_ASSET_METADATA_MINIMAL_BALANCE,98      );99      await helper.assets.setMetadata(100        alice,101        USDT_ASSET_ID,102        USDT_ASSET_METADATA_NAME,103        USDT_ASSET_METADATA_DESCRIPTION,104        USDT_ASSET_METADATA_DECIMALS,105      );106      await helper.assets.mint(107        alice,108        USDT_ASSET_ID,109        alice.address,110        USDT_ASSET_AMOUNT,111      );112113      // funding parachain sovereing account on Statemine(t).114      // The sovereign account should be created before any action115      // (the assets pallet on Statemine(t) check if the sovereign account exists)116      const parachainSovereingAccount = helper.address.paraSiblingSovereignAccount(QUARTZ_CHAIN);117      await helper.balance.transferToSubstrate(bob, parachainSovereingAccount, sovereignFundingAmount);118    });119120121    await usingPlaygrounds(async (helper) => {122      const location = {123        V2: {124          parents: 1,125          interior: {X3: [126            {127              Parachain: STATEMINE_CHAIN,128            },129            {130              PalletInstance: STATEMINE_PALLET_INSTANCE,131            },132            {133              GeneralIndex: USDT_ASSET_ID,134            },135          ]},136        },137      };138139      const metadata =140      {141        name: USDT_ASSET_ID,142        symbol: USDT_ASSET_METADATA_NAME,143        decimals: USDT_ASSET_METADATA_DECIMALS,144        minimalBalance: USDT_ASSET_METADATA_MINIMAL_BALANCE,145      };146      await helper.getSudo().foreignAssets.register(alice, alice.address, location, metadata);147      balanceQuartzBefore = await helper.balance.getSubstrate(alice.address);148    });149150151    // Providing the relay currency to the quartz sender account152    // (fee for USDT XCM are paid in relay tokens)153    await usingRelayPlaygrounds(relayUrl, async (helper) => {154      const destination = {155        V1: {156          parents: 0,157          interior: {X1: {158            Parachain: QUARTZ_CHAIN,159          },160          },161        }};162163      const beneficiary = {164        V1: {165          parents: 0,166          interior: {X1: {167            AccountId32: {168              network: 'Any',169              id: alice.addressRaw,170            },171          }},172        },173      };174175      const assets = {176        V1: [177          {178            id: {179              Concrete: {180                parents: 0,181                interior: 'Here',182              },183            },184            fun: {185              Fungible: TRANSFER_AMOUNT_RELAY,186            },187          },188        ],189      };190191      const feeAssetItem = 0;192193      await helper.xcm.limitedReserveTransferAssets(alice, destination, beneficiary, assets, feeAssetItem, 'Unlimited');194    });195196  });197198  itSub('Should connect and send USDT from Statemine to Quartz', async ({helper}) => {199    await usingStateminePlaygrounds(statemineUrl, async (helper) => {200      const dest = {201        V1: {202          parents: 1,203          interior: {X1: {204            Parachain: QUARTZ_CHAIN,205          },206          },207        }};208209      const beneficiary = {210        V1: {211          parents: 0,212          interior: {X1: {213            AccountId32: {214              network: 'Any',215              id: alice.addressRaw,216            },217          }},218        },219      };220221      const assets = {222        V1: [223          {224            id: {225              Concrete: {226                parents: 0,227                interior: {228                  X2: [229                    {230                      PalletInstance: STATEMINE_PALLET_INSTANCE,231                    },232                    {233                      GeneralIndex: USDT_ASSET_ID,234                    },235                  ]},236              },237            },238            fun: {239              Fungible: TRANSFER_AMOUNT,240            },241          },242        ],243      };244245      const feeAssetItem = 0;246247      balanceStmnBefore = await helper.balance.getSubstrate(alice.address);248      await helper.xcm.limitedReserveTransferAssets(alice, dest, beneficiary, assets, feeAssetItem, 'Unlimited');249250      balanceStmnAfter = await helper.balance.getSubstrate(alice.address);251252      // common good parachain take commission in it native token253      console.log(254        '[Statemine -> Quartz] transaction fees on Statemine: %s WND',255        helper.util.bigIntToDecimals(balanceStmnBefore - balanceStmnAfter, STATEMINE_DECIMALS),256      );257      expect(balanceStmnBefore > balanceStmnAfter).to.be.true;258259    });260261262    // ensure that asset has been delivered263    await helper.wait.newBlocks(3);264265    // expext collection id will be with id 1266    const free = await helper.ft.getBalance(1, {Substrate: alice.address});267268    balanceQuartzAfter = await helper.balance.getSubstrate(alice.address);269270    console.log(271      '[Statemine -> Quartz] transaction fees on Quartz: %s USDT',272      helper.util.bigIntToDecimals(TRANSFER_AMOUNT - free, USDT_ASSET_METADATA_DECIMALS),273    );274    console.log(275      '[Statemine -> Quartz] transaction fees on Quartz: %s QTZ',276      helper.util.bigIntToDecimals(balanceQuartzAfter - balanceQuartzBefore),277    );278    // commission has not paid in USDT token279    expect(free).to.be.equal(TRANSFER_AMOUNT);280    // ... and parachain native token281    expect(balanceQuartzAfter == balanceQuartzBefore).to.be.true;282  });283284  itSub('Should connect and send USDT from Quartz to Statemine back', async ({helper}) => {285    const destination = {286      V2: {287        parents: 1,288        interior: {X2: [289          {290            Parachain: STATEMINE_CHAIN,291          },292          {293            AccountId32: {294              network: 'Any',295              id: alice.addressRaw,296            },297          },298        ]},299      },300    };301302    const relayFee = 400_000_000_000_000n;303    const currencies: [any, bigint][] = [304      [305        {306          ForeignAssetId: 0,307        },308        TRANSFER_AMOUNT,309      ],310      [311        {312          NativeAssetId: 'Parent',313        },314        relayFee,315      ],316    ];317318    const feeItem = 1;319320    await helper.xTokens.transferMulticurrencies(alice, currencies, feeItem, destination, 'Unlimited');321322    // the commission has been paid in parachain native token323    balanceQuartzFinal = await helper.balance.getSubstrate(alice.address);324    console.log('[Quartz -> Statemine] transaction fees on Quartz: %s QTZ', helper.util.bigIntToDecimals(balanceQuartzAfter - balanceQuartzFinal));325    expect(balanceQuartzAfter > balanceQuartzFinal).to.be.true;326327    await usingStateminePlaygrounds(statemineUrl, async (helper) => {328      await helper.wait.newBlocks(3);329330      // The USDT token never paid fees. Its amount not changed from begin value.331      // Also check that xcm transfer has been succeeded332      expect((await helper.assets.account(USDT_ASSET_ID, alice.address))! == USDT_ASSET_AMOUNT).to.be.true;333    });334  });335336  itSub('Should connect and send Relay token to Quartz', async ({helper}) => {337    balanceBobBefore = await helper.balance.getSubstrate(bob.address);338    balanceBobRelayTokenBefore = await helper.tokens.accounts(bob.address, {NativeAssetId: 'Parent'});339340    await usingRelayPlaygrounds(relayUrl, async (helper) => {341      const destination = {342        V1: {343          parents: 0,344          interior: {X1: {345            Parachain: QUARTZ_CHAIN,346          },347          },348        }};349350      const beneficiary = {351        V1: {352          parents: 0,353          interior: {X1: {354            AccountId32: {355              network: 'Any',356              id: bob.addressRaw,357            },358          }},359        },360      };361362      const assets = {363        V1: [364          {365            id: {366              Concrete: {367                parents: 0,368                interior: 'Here',369              },370            },371            fun: {372              Fungible: TRANSFER_AMOUNT_RELAY,373            },374          },375        ],376      };377378      const feeAssetItem = 0;379380      await helper.xcm.limitedReserveTransferAssets(bob, destination, beneficiary, assets, feeAssetItem, 'Unlimited');381    });382383    await helper.wait.newBlocks(3);384385    balanceBobAfter = await helper.balance.getSubstrate(bob.address);386    balanceBobRelayTokenAfter = await helper.tokens.accounts(bob.address, {NativeAssetId: 'Parent'});387388    const wndFeeOnQuartz = balanceBobRelayTokenAfter - TRANSFER_AMOUNT_RELAY - balanceBobRelayTokenBefore;389    const wndDiffOnQuartz = balanceBobRelayTokenAfter - balanceBobRelayTokenBefore;390    console.log(391      '[Relay (Westend) -> Quartz] transaction fees: %s QTZ',392      helper.util.bigIntToDecimals(balanceBobAfter - balanceBobBefore),393    );394    console.log(395      '[Relay (Westend) -> Quartz] transaction fees: %s WND',396      helper.util.bigIntToDecimals(wndFeeOnQuartz, STATEMINE_DECIMALS),397    );398    console.log('[Relay (Westend) -> Quartz] actually delivered: %s WND', wndDiffOnQuartz);399    expect(wndFeeOnQuartz == 0n, 'No incoming WND fees should be taken').to.be.true;400    expect(balanceBobBefore == balanceBobAfter, 'No incoming QTZ fees should be taken').to.be.true;401  });402403  itSub('Should connect and send Relay token back', async ({helper}) => {404    let relayTokenBalanceBefore: bigint;405    let relayTokenBalanceAfter: bigint;406    await usingRelayPlaygrounds(relayUrl, async (helper) => {407      relayTokenBalanceBefore = await helper.balance.getSubstrate(bob.address);408    });409410    const destination = {411      V2: {412        parents: 1,413        interior: {414          X1:{415            AccountId32: {416              network: 'Any',417              id: bob.addressRaw,418            },419          },420        },421      },422    };423424    const currencies: any = [425      [426        {427          NativeAssetId: 'Parent',428        },429        TRANSFER_AMOUNT_RELAY,430      ],431    ];432433    const feeItem = 0;434435    await helper.xTokens.transferMulticurrencies(bob, currencies, feeItem, destination, 'Unlimited');436437    balanceBobFinal = await helper.balance.getSubstrate(bob.address);438    console.log('[Quartz -> Relay (Westend)] transaction fees: %s QTZ',  helper.util.bigIntToDecimals(balanceBobAfter - balanceBobFinal));439440    await usingRelayPlaygrounds(relayUrl, async (helper) => {441      await helper.wait.newBlocks(10);442      relayTokenBalanceAfter = await helper.balance.getSubstrate(bob.address);443444      const diff = relayTokenBalanceAfter - relayTokenBalanceBefore;445      console.log('[Quartz -> Relay (Westend)] actually delivered: %s WND', helper.util.bigIntToDecimals(diff, RELAY_DECIMALS));446      expect(diff > 0, 'Relay tokens was not delivered back').to.be.true;447    });448  });449});450451describeXCM('[XCM] Integration test: Exchanging tokens with Karura', () => {452  let alice: IKeyringPair;453  let randomAccount: IKeyringPair;454455  let balanceQuartzTokenInit: bigint;456  let balanceQuartzTokenMiddle: bigint;457  let balanceQuartzTokenFinal: bigint;458  let balanceKaruraTokenInit: bigint;459  let balanceKaruraTokenMiddle: bigint;460  let balanceKaruraTokenFinal: bigint;461  let balanceQuartzForeignTokenInit: bigint;462  let balanceQuartzForeignTokenMiddle: bigint;463  let balanceQuartzForeignTokenFinal: bigint;464465  // computed by a test transfer from prod Quartz to prod Karura.466  // 2 QTZ sent https://quartz.subscan.io/xcm_message/kusama-f60d821b049f8835a3005ce7102285006f5b61e9467  // 1.919176000000000000 QTZ received (you can check Karura's chain state in the corresponding block)468  const expectedKaruraIncomeFee = 2000000000000000000n - 1919176000000000000n;469470  const KARURA_BACKWARD_TRANSFER_AMOUNT = TRANSFER_AMOUNT - expectedKaruraIncomeFee;471472  before(async () => {473    await usingPlaygrounds(async (helper, privateKey) => {474      alice = await privateKey('//Alice');475      [randomAccount] = await helper.arrange.createAccounts([0n], alice);476477      // Set the default version to wrap the first message to other chains.478      await helper.getSudo().xcm.setSafeXcmVersion(alice, SAFE_XCM_VERSION);479    });480481    await usingKaruraPlaygrounds(karuraUrl, async (helper) => {482      const destination = {483        V1: {484          parents: 1,485          interior: {486            X1: {487              Parachain: QUARTZ_CHAIN,488            },489          },490        },491      };492493      const metadata = {494        name: 'Quartz',495        symbol: 'QTZ',496        decimals: 18,497        minimalBalance: 1000000000000000000n,498      };499500      await helper.getSudo().assetRegistry.registerForeignAsset(alice, destination, metadata);501      await helper.balance.transferToSubstrate(alice, randomAccount.address, 10000000000000n);502      balanceKaruraTokenInit = await helper.balance.getSubstrate(randomAccount.address);503      balanceQuartzForeignTokenInit = await helper.tokens.accounts(randomAccount.address, {ForeignAsset: 0});504    });505506    await usingPlaygrounds(async (helper) => {507      await helper.balance.transferToSubstrate(alice, randomAccount.address, 10n * TRANSFER_AMOUNT);508      balanceQuartzTokenInit = await helper.balance.getSubstrate(randomAccount.address);509    });510  });511512  itSub('Should connect and send QTZ to Karura', async ({helper}) => {513    const destination = {514      V2: {515        parents: 1,516        interior: {517          X1: {518            Parachain: KARURA_CHAIN,519          },520        },521      },522    };523524    const beneficiary = {525      V2: {526        parents: 0,527        interior: {528          X1: {529            AccountId32: {530              network: 'Any',531              id: randomAccount.addressRaw,532            },533          },534        },535      },536    };537538    const assets = {539      V2: [540        {541          id: {542            Concrete: {543              parents: 0,544              interior: 'Here',545            },546          },547          fun: {548            Fungible: TRANSFER_AMOUNT,549          },550        },551      ],552    };553554    const feeAssetItem = 0;555556    await helper.xcm.limitedReserveTransferAssets(randomAccount, destination, beneficiary, assets, feeAssetItem, 'Unlimited');557    balanceQuartzTokenMiddle = await helper.balance.getSubstrate(randomAccount.address);558559    const qtzFees = balanceQuartzTokenInit - balanceQuartzTokenMiddle - TRANSFER_AMOUNT;560    expect(qtzFees > 0n, 'Negative fees QTZ, looks like nothing was transferred').to.be.true;561    console.log('[Quartz -> Karura] transaction fees on Quartz: %s QTZ', helper.util.bigIntToDecimals(qtzFees));562563    await usingKaruraPlaygrounds(karuraUrl, async (helper) => {564      await helper.wait.newBlocks(3);565566      balanceQuartzForeignTokenMiddle = await helper.tokens.accounts(randomAccount.address, {ForeignAsset: 0});567      balanceKaruraTokenMiddle = await helper.balance.getSubstrate(randomAccount.address);568569      const karFees = balanceKaruraTokenInit - balanceKaruraTokenMiddle;570      const qtzIncomeTransfer = balanceQuartzForeignTokenMiddle - balanceQuartzForeignTokenInit;571      const karUnqFees = TRANSFER_AMOUNT - qtzIncomeTransfer;572573      console.log(574        '[Quartz -> Karura] transaction fees on Karura: %s KAR',575        helper.util.bigIntToDecimals(karFees, KARURA_DECIMALS),576      );577      console.log(578        '[Quartz -> Karura] transaction fees on Karura: %s QTZ',579        helper.util.bigIntToDecimals(karUnqFees),580      );581      console.log('[Quartz -> Karura] income %s QTZ', helper.util.bigIntToDecimals(qtzIncomeTransfer));582      expect(karFees == 0n).to.be.true;583      expect(584        karUnqFees == expectedKaruraIncomeFee,585        'Karura took different income fee, check the Karura foreign asset config',586      ).to.be.true;587    });588  });589590  itSub('Should connect to Karura and send QTZ back', async ({helper}) => {591    await usingKaruraPlaygrounds(karuraUrl, async (helper) => {592      const destination = {593        V1: {594          parents: 1,595          interior: {596            X2: [597              {Parachain: QUARTZ_CHAIN},598              {599                AccountId32: {600                  network: 'Any',601                  id: randomAccount.addressRaw,602                },603              },604            ],605          },606        },607      };608609      const id = {610        ForeignAsset: 0,611      };612613      await helper.xTokens.transfer(randomAccount, id, KARURA_BACKWARD_TRANSFER_AMOUNT, destination, 'Unlimited');614      balanceKaruraTokenFinal = await helper.balance.getSubstrate(randomAccount.address);615      balanceQuartzForeignTokenFinal = await helper.tokens.accounts(randomAccount.address, id);616617      const karFees = balanceKaruraTokenMiddle - balanceKaruraTokenFinal;618      const qtzOutcomeTransfer = balanceQuartzForeignTokenMiddle - balanceQuartzForeignTokenFinal;619620      console.log(621        '[Karura -> Quartz] transaction fees on Karura: %s KAR',622        helper.util.bigIntToDecimals(karFees, KARURA_DECIMALS),623      );624      console.log('[Karura -> Quartz] outcome %s QTZ', helper.util.bigIntToDecimals(qtzOutcomeTransfer));625626      expect(karFees > 0, 'Negative fees KAR, looks like nothing was transferred').to.be.true;627      expect(qtzOutcomeTransfer == KARURA_BACKWARD_TRANSFER_AMOUNT).to.be.true;628    });629630    await helper.wait.newBlocks(3);631632    balanceQuartzTokenFinal = await helper.balance.getSubstrate(randomAccount.address);633    const actuallyDelivered = balanceQuartzTokenFinal - balanceQuartzTokenMiddle;634    expect(actuallyDelivered > 0).to.be.true;635636    console.log('[Karura -> Quartz] actually delivered %s QTZ', helper.util.bigIntToDecimals(actuallyDelivered));637638    const qtzFees = KARURA_BACKWARD_TRANSFER_AMOUNT - actuallyDelivered;639    console.log('[Karura -> Quartz] transaction fees on Quartz: %s QTZ', helper.util.bigIntToDecimals(qtzFees));640    expect(qtzFees == 0n).to.be.true;641  });642});643644// These tests are relevant only when the foreign asset pallet is disabled645describeXCM('[XCM] Integration test: Quartz rejects non-native tokens', () => {646  let alice: IKeyringPair;647648  before(async () => {649    await usingPlaygrounds(async (helper, privateKey) => {650      alice = await privateKey('//Alice');651652      // Set the default version to wrap the first message to other chains.653      await helper.getSudo().xcm.setSafeXcmVersion(alice, SAFE_XCM_VERSION);654    });655  });656657  itSub('Quartz rejects KAR tokens from Karura', async ({helper}) => {658    await usingKaruraPlaygrounds(karuraUrl, async (helper) => {659      const destination = {660        V1: {661          parents: 1,662          interior: {663            X2: [664              {Parachain: QUARTZ_CHAIN},665              {666                AccountId32: {667                  network: 'Any',668                  id: alice.addressRaw,669                },670              },671            ],672          },673        },674      };675676      const id = {677        Token: 'KAR',678      };679680      await helper.xTokens.transfer(alice, id, 100_000_000_000n, destination, 'Unlimited');681    });682683    const maxWaitBlocks = 3;684685    const xcmpQueueFailEvent = await helper.wait.event(maxWaitBlocks, 'xcmpQueue', 'Fail');686687    expect(688      xcmpQueueFailEvent != null,689      '[Karura] xcmpQueue.FailEvent event is expected',690    ).to.be.true;691692    const event = xcmpQueueFailEvent!.event;693    const outcome = event.data[1] as XcmV2TraitsError;694695    expect(696      outcome.isFailedToTransactAsset,697      '[Karura] The XCM error should be `FailedToTransactAsset`',698    ).to.be.true;699  });700});701702describeXCM('[XCM] Integration test: Exchanging QTZ with Moonriver', () => {703  // Quartz constants704  let quartzDonor: IKeyringPair;705  let quartzAssetLocation;706707  let randomAccountQuartz: IKeyringPair;708  let randomAccountMoonriver: IKeyringPair;709710  // Moonriver constants711  let assetId: string;712713  const councilVotingThreshold = 2;714  const technicalCommitteeThreshold = 2;715  const votingPeriod = 3;716  const delayPeriod = 0;717718  const quartzAssetMetadata = {719    name: 'xcQuartz',720    symbol: 'xcQTZ',721    decimals: 18,722    isFrozen: false,723    minimalBalance: 1n,724  };725726  let balanceQuartzTokenInit: bigint;727  let balanceQuartzTokenMiddle: bigint;728  let balanceQuartzTokenFinal: bigint;729  let balanceForeignQtzTokenInit: bigint;730  let balanceForeignQtzTokenMiddle: bigint;731  let balanceForeignQtzTokenFinal: bigint;732  let balanceMovrTokenInit: bigint;733  let balanceMovrTokenMiddle: bigint;734  let balanceMovrTokenFinal: bigint;735736  before(async () => {737    await usingPlaygrounds(async (helper, privateKey) => {738      quartzDonor = await privateKey('//Alice');739      [randomAccountQuartz] = await helper.arrange.createAccounts([0n], quartzDonor);740741      balanceForeignQtzTokenInit = 0n;742      743      // Set the default version to wrap the first message to other chains.744      const alice = quartzDonor;745      await helper.getSudo().xcm.setSafeXcmVersion(alice, SAFE_XCM_VERSION);746    });747748    await usingMoonriverPlaygrounds(moonriverUrl, async (helper) => {749      const alithAccount = helper.account.alithAccount();750      const baltatharAccount = helper.account.baltatharAccount();751      const dorothyAccount = helper.account.dorothyAccount();752753      randomAccountMoonriver = helper.account.create();754755      // >>> Sponsoring Dorothy >>>756      console.log('Sponsoring Dorothy.......');757      await helper.balance.transferToEthereum(alithAccount, dorothyAccount.address, 11_000_000_000_000_000_000n);758      console.log('Sponsoring Dorothy.......DONE');759      // <<< Sponsoring Dorothy <<<760761      quartzAssetLocation = {762        XCM: {763          parents: 1,764          interior: {X1: {Parachain: QUARTZ_CHAIN}},765        },766      };767      const existentialDeposit = 1n;768      const isSufficient = true;769      const unitsPerSecond = 1n;770      const numAssetsWeightHint = 0;771772      const encodedProposal = helper.assetManager.makeRegisterForeignAssetProposal({773        location: quartzAssetLocation,774        metadata: quartzAssetMetadata,775        existentialDeposit,776        isSufficient,777        unitsPerSecond,778        numAssetsWeightHint,779      });780      const proposalHash = blake2AsHex(encodedProposal);781782      console.log('Encoded proposal for registerForeignAsset & setAssetUnitsPerSecond is %s', encodedProposal);783      console.log('Encoded length %d', encodedProposal.length);784      console.log('Encoded proposal hash for batch utility after schedule is %s', proposalHash);785786      // >>> Note motion preimage >>>787      console.log('Note motion preimage.......');788      await helper.democracy.notePreimage(baltatharAccount, encodedProposal);789      console.log('Note motion preimage.......DONE');790      // <<< Note motion preimage <<<791792      // >>> Propose external motion through council >>>793      console.log('Propose external motion through council.......');794      const externalMotion = helper.democracy.externalProposeMajority({Legacy: proposalHash});795      const encodedMotion = externalMotion?.method.toHex() || '';796      const motionHash = blake2AsHex(encodedMotion);797      console.log('Motion hash is %s', motionHash);798799      await helper.collective.council.propose(baltatharAccount, councilVotingThreshold, externalMotion, externalMotion.encodedLength);800801      const councilProposalIdx = await helper.collective.council.proposalCount() - 1;802      await helper.collective.council.vote(dorothyAccount, motionHash, councilProposalIdx, true);803      await helper.collective.council.vote(baltatharAccount, motionHash, councilProposalIdx, true);804805      await helper.collective.council.close(806        dorothyAccount,807        motionHash,808        councilProposalIdx,809        {810          refTime: 1_000_000_000,811          proofSize: 1_000_000,812        },813        externalMotion.encodedLength,814      );815      console.log('Propose external motion through council.......DONE');816      // <<< Propose external motion through council <<<817818      // >>> Fast track proposal through technical committee >>>819      console.log('Fast track proposal through technical committee.......');820      const fastTrack = helper.democracy.fastTrack(proposalHash, votingPeriod, delayPeriod);821      const encodedFastTrack = fastTrack?.method.toHex() || '';822      const fastTrackHash = blake2AsHex(encodedFastTrack);823      console.log('FastTrack hash is %s', fastTrackHash);824825      await helper.collective.techCommittee.propose(alithAccount, technicalCommitteeThreshold, fastTrack, fastTrack.encodedLength);826827      const techProposalIdx = await helper.collective.techCommittee.proposalCount() - 1;828      await helper.collective.techCommittee.vote(baltatharAccount, fastTrackHash, techProposalIdx, true);829      await helper.collective.techCommittee.vote(alithAccount, fastTrackHash, techProposalIdx, true);830831      await helper.collective.techCommittee.close(832        baltatharAccount,833        fastTrackHash,834        techProposalIdx,835        {836          refTime: 1_000_000_000,837          proofSize: 1_000_000,838        },839        fastTrack.encodedLength,840      );841      console.log('Fast track proposal through technical committee.......DONE');842      // <<< Fast track proposal through technical committee <<<843844      // >>> Referendum voting >>>845      console.log('Referendum voting.......');846      await helper.democracy.referendumVote(dorothyAccount, 0, {847        balance: 10_000_000_000_000_000_000n,848        vote: {aye: true, conviction: 1},849      });850      console.log('Referendum voting.......DONE');851      // <<< Referendum voting <<<852853      // >>> Acquire Quartz AssetId Info on Moonriver >>>854      console.log('Acquire Quartz AssetId Info on Moonriver.......');855856      // Wait for the democracy execute857      await helper.wait.newBlocks(5);858859      assetId = (await helper.assetManager.assetTypeId(quartzAssetLocation)).toString();860861      console.log('QTZ asset ID is %s', assetId);862      console.log('Acquire Quartz AssetId Info on Moonriver.......DONE');863      // >>> Acquire Quartz AssetId Info on Moonriver >>>864865      // >>> Sponsoring random Account >>>866      console.log('Sponsoring random Account.......');867      await helper.balance.transferToEthereum(baltatharAccount, randomAccountMoonriver.address, 11_000_000_000_000_000_000n);868      console.log('Sponsoring random Account.......DONE');869      // <<< Sponsoring random Account <<<870871      balanceMovrTokenInit = await helper.balance.getEthereum(randomAccountMoonriver.address);872    });873874    await usingPlaygrounds(async (helper) => {875      await helper.balance.transferToSubstrate(quartzDonor, randomAccountQuartz.address, 10n * TRANSFER_AMOUNT);876      balanceQuartzTokenInit = await helper.balance.getSubstrate(randomAccountQuartz.address);877    });878  });879880  itSub('Should connect and send QTZ to Moonriver', async ({helper}) => {881    const currencyId = {882      NativeAssetId: 'Here',883    };884    const dest = {885      V2: {886        parents: 1,887        interior: {888          X2: [889            {Parachain: MOONRIVER_CHAIN},890            {AccountKey20: {network: 'Any', key: randomAccountMoonriver.address}},891          ],892        },893      },894    };895    const amount = TRANSFER_AMOUNT;896897    await helper.xTokens.transfer(randomAccountQuartz, currencyId, amount, dest, 'Unlimited');898899    balanceQuartzTokenMiddle = await helper.balance.getSubstrate(randomAccountQuartz.address);900    expect(balanceQuartzTokenMiddle < balanceQuartzTokenInit).to.be.true;901902    const transactionFees = balanceQuartzTokenInit - balanceQuartzTokenMiddle - TRANSFER_AMOUNT;903    console.log('[Quartz -> Moonriver] transaction fees on Quartz: %s QTZ', helper.util.bigIntToDecimals(transactionFees));904    expect(transactionFees > 0, 'Negative fees QTZ, looks like nothing was transferred').to.be.true;905906    await usingMoonriverPlaygrounds(moonriverUrl, async (helper) => {907      await helper.wait.newBlocks(3);908909      balanceMovrTokenMiddle = await helper.balance.getEthereum(randomAccountMoonriver.address);910911      const movrFees = balanceMovrTokenInit - balanceMovrTokenMiddle;912      console.log('[Quartz -> Moonriver] transaction fees on Moonriver: %s MOVR',helper.util.bigIntToDecimals(movrFees));913      expect(movrFees == 0n).to.be.true;914915      balanceForeignQtzTokenMiddle = (await helper.assets.account(assetId, randomAccountMoonriver.address))!; // BigInt(qtzRandomAccountAsset['balance']);916      const qtzIncomeTransfer = balanceForeignQtzTokenMiddle - balanceForeignQtzTokenInit;917      console.log('[Quartz -> Moonriver] income %s QTZ', helper.util.bigIntToDecimals(qtzIncomeTransfer));918      expect(qtzIncomeTransfer == TRANSFER_AMOUNT).to.be.true;919    });920  });921922  itSub('Should connect to Moonriver and send QTZ back', async ({helper}) => {923    await usingMoonriverPlaygrounds(moonriverUrl, async (helper) => {924      const asset = {925        V1: {926          id: {927            Concrete: {928              parents: 1,929              interior: {930                X1: {Parachain: QUARTZ_CHAIN},931              },932            },933          },934          fun: {935            Fungible: TRANSFER_AMOUNT,936          },937        },938      };939      const destination = {940        V1: {941          parents: 1,942          interior: {943            X2: [944              {Parachain: QUARTZ_CHAIN},945              {AccountId32: {network: 'Any', id: randomAccountQuartz.addressRaw}},946            ],947          },948        },949      };950951      await helper.xTokens.transferMultiasset(randomAccountMoonriver, asset, destination, 'Unlimited');952953      balanceMovrTokenFinal = await helper.balance.getEthereum(randomAccountMoonriver.address);954955      const movrFees = balanceMovrTokenMiddle - balanceMovrTokenFinal;956      console.log('[Moonriver -> Quartz] transaction fees on Moonriver: %s MOVR', helper.util.bigIntToDecimals(movrFees));957      expect(movrFees > 0, 'Negative fees MOVR, looks like nothing was transferred').to.be.true;958959      const qtzRandomAccountAsset = await helper.assets.account(assetId, randomAccountMoonriver.address);960961      expect(qtzRandomAccountAsset).to.be.null;962963      balanceForeignQtzTokenFinal = 0n;964965      const qtzOutcomeTransfer = balanceForeignQtzTokenMiddle - balanceForeignQtzTokenFinal;966      console.log('[Quartz -> Moonriver] outcome %s QTZ', helper.util.bigIntToDecimals(qtzOutcomeTransfer));967      expect(qtzOutcomeTransfer == TRANSFER_AMOUNT).to.be.true;968    });969970    await helper.wait.newBlocks(3);971972    balanceQuartzTokenFinal = await helper.balance.getSubstrate(randomAccountQuartz.address);973    const actuallyDelivered = balanceQuartzTokenFinal - balanceQuartzTokenMiddle;974    expect(actuallyDelivered > 0).to.be.true;975976    console.log('[Moonriver -> Quartz] actually delivered %s QTZ', helper.util.bigIntToDecimals(actuallyDelivered));977978    const qtzFees = TRANSFER_AMOUNT - actuallyDelivered;979    console.log('[Moonriver -> Quartz] transaction fees on Quartz: %s QTZ', helper.util.bigIntToDecimals(qtzFees));980    expect(qtzFees == 0n).to.be.true;981  });982});983984describeXCM('[XCM] Integration test: Exchanging tokens with Shiden', () => {985  let alice: IKeyringPair;986  let sender: IKeyringPair;987988  // Quartz -> Shiden989  const shidenInitialBalance = 1n * (10n ** 18n); // 1 SHD, existencial deposit required in order to perform XCM call990  const unitsPerSecond = 228_000_000_000n; // This is Phala's value. What will be ours?991  const qtzToShidenTransferred = 10n * (10n ** 18n); // 10 QTZ992  const qtzToShidenArrived = 9_999_999_999_088_000_000n; // 9.999 ... QTZ, Shiden takes a commision in foreign tokens993  const senderIinitialBalanceQTZ = 100n * (10n ** 18n); // How many QTZ sender has initially994  const senderBalanceAfterXCM = 89_941967662676666465n; // 89.94... QTZ after XCM call995996  // Shiden -> Quartz997  const qtzFromShidenTransfered = 5n * (10n ** 18n); // 5 QTZ998  const qtzOnShidenLeft = qtzToShidenArrived - qtzFromShidenTransfered; // 4.999_999_999_088_000_000n QTZ9991000  before(async () => {1001    await usingPlaygrounds(async (helper, privateKey) => {1002      alice = await privateKey('//Alice');1003      [sender] = await helper.arrange.createAccounts([100n], alice);1004      console.log('sender', sender.address);1005    });10061007    await usingShidenPlaygrounds(shidenUrl, async (helper) => {1008      console.log('1. Create foreign asset and metadata');1009      await helper.assets.create(1010        alice,1011        1,1012        alice.address,1013        1n,1014      );10151016      await helper.assets.setMetadata(1017        alice,1018        1,1019        'Cross chain QTZ',1020        'xcQTZ',1021        18,1022      );10231024      console.log('2. Register asset location');1025      const assetLocation = {1026        V1: {1027          parents: 1,1028          interior: {1029            X1: {1030              Parachain: QUARTZ_CHAIN,1031            },1032          },1033        },1034      };10351036      await helper.getSudo().executeExtrinsic(alice, 'api.tx.xcAssetConfig.registerAssetLocation', [assetLocation, 1]);10371038      console.log('3. Set payment for computation');1039      await helper.getSudo().executeExtrinsic(alice, 'api.tx.xcAssetConfig.setAssetUnitsPerSecond', [assetLocation, unitsPerSecond]);10401041      console.log('4. Transfer 1 SDN to recepient');1042      await helper.balance.transferToSubstrate(alice, sender.address, shidenInitialBalance);1043    });1044  });10451046  itSub('Should connect and send QTZ to Shiden', async ({helper}) => {1047    const destination = {1048      V1: {1049        parents: 1,1050        interior: {1051          X1: {1052            Parachain: SHIDEN_CHAIN,1053          },1054        },1055      },1056    };10571058    const beneficiary = {1059      V1: {1060        parents: 0,1061        interior: {1062          X1: {1063            AccountId32: {1064              network: 'Any',1065              id: sender.addressRaw,1066            },1067          },1068        },1069      },1070    };10711072    const assets = {1073      V1: [1074        {1075          id: {1076            Concrete: {1077              parents: 0,1078              interior: 'Here',1079            },1080          },1081          fun: {1082            Fungible: qtzToShidenTransferred,1083          },1084        },1085      ],1086    };10871088    // Initial balance is 100 QTZ1089    const balanceBefore = await helper.balance.getSubstrate(sender.address);1090    console.log(`Initial balance is: ${balanceBefore}`);1091    expect(balanceBefore).to.eq(senderIinitialBalanceQTZ);10921093    const feeAssetItem = 0;1094    await helper.xcm.limitedReserveTransferAssets(sender, destination, beneficiary, assets, feeAssetItem, 'Unlimited');10951096    // Balance after reserve transfer is less than 901097    const balanceAfter = await helper.balance.getSubstrate(sender.address);1098    console.log(`QTZ Balance on Quartz after XCM is: ${balanceAfter}`);1099    console.log(`Quartz's QTZ commission is: ${balanceBefore - balanceAfter}`);1100    expect(balanceAfter).to.eq(senderBalanceAfterXCM);11011102    await usingShidenPlaygrounds(shidenUrl, async (helper) => {1103      await helper.wait.newBlocks(3);1104      const xcQTZbalance = await helper.assets.account(1, sender.address);1105      const shidenBalance = await helper.balance.getSubstrate(sender.address);11061107      console.log(`xcQTZ balance on Shiden after XCM is: ${xcQTZbalance}`);1108      console.log(`Shiden's QTZ commission is: ${qtzToShidenTransferred - xcQTZbalance!}`);11091110      expect(xcQTZbalance).to.eq(qtzToShidenArrived);1111      // SHD balance does not changed:1112      expect(shidenBalance).to.eq(shidenInitialBalance);1113    });1114  });11151116  itSub('Should connect to Shiden and send QTZ back', async ({helper}) => {1117    await usingShidenPlaygrounds(shidenUrl, async (helper) => {1118      const destination = {1119        V1: {1120          parents: 1,1121          interior: {1122            X1: {1123              Parachain: QUARTZ_CHAIN,1124            },1125          },1126        },1127      };11281129      const beneficiary = {1130        V1: {1131          parents: 0,1132          interior: {1133            X1: {1134              AccountId32: {1135                network: 'Any',1136                id: sender.addressRaw,1137              },1138            },1139          },1140        },1141      };11421143      const assets = {1144        V1: [1145          {1146            id: {1147              Concrete: {1148                parents: 1,1149                interior: {1150                  X1: {1151                    Parachain: QUARTZ_CHAIN,1152                  },1153                },1154              },1155            },1156            fun: {1157              Fungible: qtzFromShidenTransfered,1158            },1159          },1160        ],1161      };11621163      // Initial balance is 1 SDN1164      const balanceSDNbefore = await helper.balance.getSubstrate(sender.address);1165      console.log(`SDN balance is: ${balanceSDNbefore}, it does not changed`);1166      expect(balanceSDNbefore).to.eq(shidenInitialBalance);11671168      const feeAssetItem = 0;1169      // this is non-standard polkadotXcm extension for Astar only. It calls InitiateReserveWithdraw1170      await helper.executeExtrinsic(sender, 'api.tx.polkadotXcm.reserveWithdrawAssets', [destination, beneficiary, assets, feeAssetItem]);11711172      // Balance after reserve transfer is less than 1 SDN1173      const xcQTZbalance = await helper.assets.account(1, sender.address);1174      const balanceSDN = await helper.balance.getSubstrate(sender.address);1175      console.log(`xcQTZ balance on Shiden after XCM is: ${xcQTZbalance}`);11761177      // Assert: xcQTZ balance correctly decreased1178      expect(xcQTZbalance).to.eq(qtzOnShidenLeft);1179      // Assert: SDN balance is 0.996...1180      expect(balanceSDN / (10n ** 15n)).to.eq(996n);1181    });11821183    await helper.wait.newBlocks(3);1184    const balanceQTZ = await helper.balance.getSubstrate(sender.address);1185    console.log(`QTZ Balance on Quartz after XCM is: ${balanceQTZ}`);1186    expect(balanceQTZ).to.eq(senderBalanceAfterXCM + qtzFromShidenTransfered);1187  });1188});
modifiedtests/src/xcm/xcmUnique.test.tsdiffbeforeafterboth
--- a/tests/src/xcm/xcmUnique.test.ts
+++ b/tests/src/xcm/xcmUnique.test.ts
@@ -1045,7 +1045,7 @@
     });
   });
 
-  itSub.only('Should connect and send UNQ to Astar', async ({helper}) => {
+  itSub('Should connect and send UNQ to Astar', async ({helper}) => {
     const destination = {
       V1: {
         parents: 1,
@@ -1115,7 +1115,7 @@
     });
   });
 
-  itSub.only('Should connect to Astar and send UNQ back', async ({helper}) => {
+  itSub('Should connect to Astar and send UNQ back', async ({helper}) => {
     await usingAstarPlaygrounds(astarUrl, async (helper) => {
       const destination = {
         V1: {