git.delta.rocks / unique-network / refs/commits / 9f2f03a30137

difftreelog

test(xcmUnique) switch to `uniqueAssetId` , typo

PraetorP2023-09-27parent: #eae22fa.patch.diff
in: master

2 files changed

modifiedtests/src/xcm/lowLevelXcmUnique.test.tsdiffbeforeafterboth
before · tests/src/xcm/lowLevelXcmUnique.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 config from '../config';19import {itSub, expect, describeXCM, usingPlaygrounds, usingAcalaPlaygrounds, usingMoonbeamPlaygrounds, usingAstarPlaygrounds, usingPolkadexPlaygrounds} from '../util';20import {Event} from '../util/playgrounds/unique.dev';21import {nToBigInt} from '@polkadot/util';22import {hexToString} from '@polkadot/util';23import {ASTAR_DECIMALS, NETWORKS, SAFE_XCM_VERSION, UNIQUE_CHAIN, UNQ_DECIMALS, acalaUrl, astarUrl, expectFailedToTransact, expectUntrustedReserveLocationFail, getDevPlayground, mapToChainId, mapToChainUrl, maxWaitBlocks, moonbeamUrl, polkadexUrl, uniqueAssetId, uniqueVersionedMultilocation} from './xcm.types';242526const TRANSFER_AMOUNT = 2000000_000_000_000_000_000_000n;27const SENDER_BUDGET = 2n * TRANSFER_AMOUNT;28const SENDBACK_AMOUNT = TRANSFER_AMOUNT / 2n;29const STAYED_ON_TARGET_CHAIN = TRANSFER_AMOUNT - SENDBACK_AMOUNT;30const TARGET_CHAIN_TOKEN_TRANSFER_AMOUNT = 100_000_000_000n;3132let balanceUniqueTokenInit: bigint;33let balanceUniqueTokenMiddle: bigint;34let balanceUniqueTokenFinal: bigint;35let unqFees: bigint;363738async function genericSendUnqTo(39  networkName: keyof typeof NETWORKS,40  randomAccount: IKeyringPair,41  randomAccountOnTargetChain = randomAccount,42) {43  const networkUrl = mapToChainUrl(networkName);44  const targetPlayground = getDevPlayground(networkName);45  await usingPlaygrounds(async (helper) => {46    balanceUniqueTokenInit = await helper.balance.getSubstrate(randomAccount.address);47    const destination = {48      V2: {49        parents: 1,50        interior: {51          X1: {52            Parachain: mapToChainId(networkName),53          },54        },55      },56    };5758    const beneficiary = {59      V2: {60        parents: 0,61        interior: {62          X1: (63            networkName == 'moonbeam' ?64              {65                AccountKey20: {66                  network: 'Any',67                  key: randomAccountOnTargetChain.address,68                },69              }70              :71              {72                AccountId32: {73                  network: 'Any',74                  id: randomAccountOnTargetChain.addressRaw,75                },76              }77          ),78        },79      },80    };8182    const assets = {83      V2: [84        {85          id: {86            Concrete: {87              parents: 0,88              interior: 'Here',89            },90          },91          fun: {92            Fungible: TRANSFER_AMOUNT,93          },94        },95      ],96    };97    const feeAssetItem = 0;9899    await helper.xcm.limitedReserveTransferAssets(randomAccount, destination, beneficiary, assets, feeAssetItem, 'Unlimited');100    const messageSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);101    balanceUniqueTokenMiddle = await helper.balance.getSubstrate(randomAccount.address);102103    unqFees = balanceUniqueTokenInit - balanceUniqueTokenMiddle - TRANSFER_AMOUNT;104    console.log('[Unique -> %s] transaction fees on Unique: %s UNQ', networkName, helper.util.bigIntToDecimals(unqFees));105    expect(unqFees > 0n, 'Negative fees UNQ, looks like nothing was transferred').to.be.true;106107    await targetPlayground(networkUrl, async (helper) => {108      /*109        Since only the parachain part of the Polkadex110        infrastructure is launched (without their111        solochain validators), processing incoming112        assets will lead to an error.113        This error indicates that the Polkadex chain114        received a message from the Unique network,115        since the hash is being checked to ensure116        it matches what was sent.117      */118      if(networkName == 'polkadex') {119        await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Fail, event => event.messageHash == messageSent.messageHash);120      } else {121        await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Success, event => event.messageHash == messageSent.messageHash);122      }123    });124125  });126}127128async function genericSendUnqBack(129  networkName: keyof typeof NETWORKS,130  sudoer: IKeyringPair,131  randomAccountOnUnq: IKeyringPair,132) {133  const networkUrl = mapToChainUrl(networkName);134135  const targetPlayground = getDevPlayground(networkName);136  await usingPlaygrounds(async (helper) => {137138    const xcmProgram = helper.arrange.makeXcmProgramWithdrawDeposit(139      randomAccountOnUnq.addressRaw,140      {141        Concrete: {142          parents: 1,143          interior: {144            X1: {Parachain: UNIQUE_CHAIN},145          },146        },147      },148      SENDBACK_AMOUNT,149    );150151    let xcmProgramSent: any;152153154    await targetPlayground(networkUrl, async (helper) => {155      if('getSudo' in helper) {156        await helper.getSudo().xcm.send(sudoer, uniqueVersionedMultilocation, xcmProgram);157        xcmProgramSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);158      } else if('fastDemocracy' in helper) {159        const xcmSend = helper.constructApiCall('api.tx.polkadotXcm.send', [uniqueVersionedMultilocation, xcmProgram]);160        // Needed to bypass the call filter.161        const batchCall = helper.encodeApiCall('api.tx.utility.batch', [[xcmSend]]);162        await helper.fastDemocracy.executeProposal(`sending ${networkName} -> Unique via XCM program`, batchCall);163        xcmProgramSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);164      }165    });166167    await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Success, event => event.messageHash == xcmProgramSent.messageHash);168169    balanceUniqueTokenFinal = await helper.balance.getSubstrate(randomAccountOnUnq.address);170171    expect(balanceUniqueTokenFinal).to.be.equal(balanceUniqueTokenInit - unqFees - STAYED_ON_TARGET_CHAIN);172173  });174}175176async function genericSendOnlyOwnedBalance(177  networkName: keyof typeof NETWORKS,178  sudoer: IKeyringPair,179) {180  const networkUrl = mapToChainUrl(networkName);181  const targetPlayground = getDevPlayground(networkName);182183  const targetChainBalance = 10000n * (10n ** UNQ_DECIMALS);184185  await usingPlaygrounds(async (helper) => {186    const targetChainSovereignAccount = helper.address.paraSiblingSovereignAccount(mapToChainId(networkName));187    await helper.getSudo().balance.setBalanceSubstrate(sudoer, targetChainSovereignAccount, targetChainBalance);188    const moreThanTargetChainHas = 2n * targetChainBalance;189190    const targetAccount = helper.arrange.createEmptyAccount();191192    const maliciousXcmProgram = helper.arrange.makeXcmProgramWithdrawDeposit(193      targetAccount.addressRaw,194      {195        Concrete: {196          parents: 0,197          interior: 'Here',198        },199      },200      moreThanTargetChainHas,201    );202203    let maliciousXcmProgramSent: any;204205206    await targetPlayground(networkUrl, async (helper) => {207      if('getSudo' in helper) {208        await helper.getSudo().xcm.send(sudoer, uniqueVersionedMultilocation, maliciousXcmProgram);209        maliciousXcmProgramSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);210      } else if('fastDemocracy' in helper) {211        const xcmSend = helper.constructApiCall('api.tx.polkadotXcm.send', [uniqueVersionedMultilocation, maliciousXcmProgram]);212        // Needed to bypass the call filter.213        const batchCall = helper.encodeApiCall('api.tx.utility.batch', [[xcmSend]]);214        await helper.fastDemocracy.executeProposal(`sending ${networkName} -> Unique via XCM program`, batchCall);215        maliciousXcmProgramSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);216      }217    });218219    await expectFailedToTransact(helper, maliciousXcmProgramSent);220221    const targetAccountBalance = await helper.balance.getSubstrate(targetAccount.address);222    expect(targetAccountBalance).to.be.equal(0n);223  });224}225226async function genericReserveTransferUNQfrom(netwokrName: keyof typeof NETWORKS, sudoer: IKeyringPair) {227  const networkUrl = mapToChainUrl(netwokrName);228  const targetPlayground = getDevPlayground(netwokrName);229230  await usingPlaygrounds(async (helper) => {231    const testAmount = 10_000n * (10n ** UNQ_DECIMALS);232    const targetAccount = helper.arrange.createEmptyAccount();233234    const maliciousXcmProgramFullId = helper.arrange.makeXcmProgramReserveAssetDeposited(235      targetAccount.addressRaw,236      {237        Concrete: {238          parents: 1,239          interior: {240            X1: {241              Parachain: UNIQUE_CHAIN,242            },243          },244        },245      },246      testAmount,247    );248249    const maliciousXcmProgramHereId = helper.arrange.makeXcmProgramReserveAssetDeposited(250      targetAccount.addressRaw,251      {252        Concrete: {253          parents: 0,254          interior: 'Here',255        },256      },257      testAmount,258    );259260    let maliciousXcmProgramFullIdSent: any;261    let maliciousXcmProgramHereIdSent: any;262    const maxWaitBlocks = 3;263264    // Try to trick Unique using full UNQ identification265    await targetPlayground(networkUrl, async (helper) => {266      if('getSudo' in helper) {267        await helper.getSudo().xcm.send(sudoer, uniqueVersionedMultilocation, maliciousXcmProgramFullId);268        maliciousXcmProgramFullIdSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);269      }270      // Moonbeam case271      else if('fastDemocracy' in helper) {272        const xcmSend = helper.constructApiCall('api.tx.polkadotXcm.send', [uniqueVersionedMultilocation, maliciousXcmProgramFullId]);273        // Needed to bypass the call filter.274        const batchCall = helper.encodeApiCall('api.tx.utility.batch', [[xcmSend]]);275        await helper.fastDemocracy.executeProposal(`${netwokrName} try to act like a reserve location for UNQ using path asset identification`,batchCall);276277        maliciousXcmProgramFullIdSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);278      }279    });280281282    await expectUntrustedReserveLocationFail(helper, maliciousXcmProgramFullIdSent);283284    let accountBalance = await helper.balance.getSubstrate(targetAccount.address);285    expect(accountBalance).to.be.equal(0n);286287    // Try to trick Unique using shortened UNQ identification288    await targetPlayground(networkUrl, async (helper) => {289      if('getSudo' in helper) {290        await helper.getSudo().xcm.send(sudoer, uniqueVersionedMultilocation, maliciousXcmProgramHereId);291        maliciousXcmProgramHereIdSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);292      }293      else if('fastDemocracy' in helper) {294        const xcmSend = helper.constructApiCall('api.tx.polkadotXcm.send', [uniqueVersionedMultilocation, maliciousXcmProgramHereId]);295        // Needed to bypass the call filter.296        const batchCall = helper.encodeApiCall('api.tx.utility.batch', [[xcmSend]]);297        await helper.fastDemocracy.executeProposal(`${netwokrName} try to act like a reserve location for UNQ using "here" asset identification`, batchCall);298299        maliciousXcmProgramHereIdSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);300      }301    });302303    await expectUntrustedReserveLocationFail(helper, maliciousXcmProgramHereIdSent);304305    accountBalance = await helper.balance.getSubstrate(targetAccount.address);306    expect(accountBalance).to.be.equal(0n);307  });308}309310async function genericRejectNativeToknsFrom(netwokrName: keyof typeof NETWORKS, sudoerOnTargetChain: IKeyringPair) {311  const networkUrl = mapToChainUrl(netwokrName);312  const targetPlayground = getDevPlayground(netwokrName);313  let messageSent: any;314315  await usingPlaygrounds(async (helper) => {316    const maliciousXcmProgramFullId = helper.arrange.makeXcmProgramReserveAssetDeposited(317      helper.arrange.createEmptyAccount().addressRaw,318      {319        Concrete: {320          parents: 1,321          interior: {322            X1: {323              Parachain: mapToChainId(netwokrName),324            },325          },326        },327      },328      TARGET_CHAIN_TOKEN_TRANSFER_AMOUNT,329    );330    await targetPlayground(networkUrl, async (helper) => {331      if('getSudo' in helper) {332        await helper.getSudo().xcm.send(sudoerOnTargetChain, uniqueVersionedMultilocation, maliciousXcmProgramFullId);333        messageSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);334      } else if('fastDemocracy' in helper) {335        const xcmSend = helper.constructApiCall('api.tx.polkadotXcm.send', [uniqueVersionedMultilocation, maliciousXcmProgramFullId]);336        // Needed to bypass the call filter.337        const batchCall = helper.encodeApiCall('api.tx.utility.batch', [[xcmSend]]);338        await helper.fastDemocracy.executeProposal(`${netwokrName} sending native tokens to the Unique via fast democracy`, batchCall);339340        messageSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);341      }342    });343    await expectFailedToTransact(helper, messageSent);344  });345}346347348describeXCM('[XCMLL] Integration test: Exchanging tokens with Acala', () => {349  let alice: IKeyringPair;350  let randomAccount: IKeyringPair;351352  before(async () => {353    await usingPlaygrounds(async (helper, privateKey) => {354      alice = await privateKey('//Alice');355      console.log(config.acalaUrl);356      randomAccount = helper.arrange.createEmptyAccount();357358      // Set the default version to wrap the first message to other chains.359      await helper.getSudo().xcm.setSafeXcmVersion(alice, SAFE_XCM_VERSION);360    });361362    await usingAcalaPlaygrounds(acalaUrl, async (helper) => {363      const destination = {364        V2: {365          parents: 1,366          interior: {367            X1: {368              Parachain: UNIQUE_CHAIN,369            },370          },371        },372      };373374      const metadata = {375        name: 'Unique Network',376        symbol: 'UNQ',377        decimals: 18,378        minimalBalance: 1250_000_000_000_000_000n,379      };380      const assets = (await (helper.callRpc('api.query.assetRegistry.assetMetadatas.entries'))).map(([_k, v] : [any, any]) =>381        hexToString(v.toJSON()['symbol'])) as string[];382383      if(!assets.includes('UNQ')) {384        await helper.getSudo().assetRegistry.registerForeignAsset(alice, destination, metadata);385      } else {386        console.log('UNQ token already registered on Acala assetRegistry pallet');387      }388      await helper.balance.transferToSubstrate(alice, randomAccount.address, 10000000000000n);389    });390391    await usingPlaygrounds(async (helper) => {392      await helper.balance.transferToSubstrate(alice, randomAccount.address, SENDER_BUDGET);393      balanceUniqueTokenInit = await helper.balance.getSubstrate(randomAccount.address);394    });395  });396397  itSub('Should connect and send UNQ to Acala', async () => {398    await genericSendUnqTo('acala', randomAccount);399  });400401  itSub('Should connect to Acala and send UNQ back', async () => {402    await genericSendUnqBack('acala', alice, randomAccount);403  });404405  itSub('Acala can send only up to its balance', async () => {406    await genericSendOnlyOwnedBalance('acala', alice);407  });408409  itSub('Should not accept reserve transfer of UNQ from Acala', async () => {410    await genericReserveTransferUNQfrom('acala', alice);411  });412});413414describeXCM('[XCMLL] Integration test: Exchanging tokens with Polkadex', () => {415  let alice: IKeyringPair;416  let randomAccount: IKeyringPair;417418  before(async () => {419    await usingPlaygrounds(async (helper, privateKey) => {420      alice = await privateKey('//Alice');421      randomAccount = helper.arrange.createEmptyAccount();422423      // Set the default version to wrap the first message to other chains.424      await helper.getSudo().xcm.setSafeXcmVersion(alice, SAFE_XCM_VERSION);425    });426427    await usingPolkadexPlaygrounds(polkadexUrl, async (helper) => {428      const isWhitelisted = ((await helper.callRpc('api.query.xcmHelper.whitelistedTokens', []))429        .toJSON() as [])430        .map(nToBigInt).length != 0;431      /*432      Check whether the Unique token has been added433      to the whitelist, since an error will occur434      if it is added again. Needed for debugging435      when this test is run multiple times.436      */437      if(isWhitelisted) {438        console.log('UNQ token is already whitelisted on Polkadex');439      } else {440        await helper.getSudo().xcmHelper.whitelistToken(alice, uniqueAssetId);441      }442443      await helper.balance.transferToSubstrate(alice, randomAccount.address, 10000000000000n);444    });445446    await usingPlaygrounds(async (helper) => {447      await helper.balance.transferToSubstrate(alice, randomAccount.address, SENDER_BUDGET);448      balanceUniqueTokenInit = await helper.balance.getSubstrate(randomAccount.address);449    });450  });451452  itSub('Should connect and send UNQ to Polkadex', async () => {453    await genericSendUnqTo('polkadex', randomAccount);454  });455456457  itSub('Should connect to Polkadex and send UNQ back', async () => {458    await genericSendUnqBack('polkadex', alice, randomAccount);459  });460461  itSub('Polkadex can send only up to its balance', async () => {462    await genericSendOnlyOwnedBalance('polkadex', alice);463  });464465  itSub('Should not accept reserve transfer of UNQ from Polkadex', async () => {466    await genericReserveTransferUNQfrom('polkadex', alice);467  });468});469470// These tests are relevant only when471// the the corresponding foreign assets are not registered472describeXCM('[XCMLL] Integration test: Unique rejects non-native tokens', () => {473  let alice: IKeyringPair;474475  before(async () => {476    await usingPlaygrounds(async (helper, privateKey) => {477      alice = await privateKey('//Alice');478479      // Set the default version to wrap the first message to other chains.480      await helper.getSudo().xcm.setSafeXcmVersion(alice, SAFE_XCM_VERSION);481    });482  });483484  itSub('Unique rejects ACA tokens from Acala', async () => {485    await genericRejectNativeToknsFrom('acala', alice);486  });487488  itSub('Unique rejects GLMR tokens from Moonbeam', async () => {489    await genericRejectNativeToknsFrom('moonbeam', alice);490  });491492  itSub('Unique rejects ASTR tokens from Astar', async () => {493    await genericRejectNativeToknsFrom('astar', alice);494  });495496  itSub('Unique rejects PDX tokens from Polkadex', async () => {497    await genericRejectNativeToknsFrom('polkadex', alice);498  });499});500501describeXCM('[XCMLL] Integration test: Exchanging UNQ with Moonbeam', () => {502  // Unique constants503  let alice: IKeyringPair;504  let uniqueAssetLocation;505506  let randomAccountUnique: IKeyringPair;507  let randomAccountMoonbeam: IKeyringPair;508509  // Moonbeam constants510  let assetId: string;511512  const uniqueAssetMetadata = {513    name: 'xcUnique',514    symbol: 'xcUNQ',515    decimals: 18,516    isFrozen: false,517    minimalBalance: 1n,518  };519520521  before(async () => {522    await usingPlaygrounds(async (helper, privateKey) => {523      alice = await privateKey('//Alice');524      [randomAccountUnique] = await helper.arrange.createAccounts([0n], alice);525526527      // Set the default version to wrap the first message to other chains.528      await helper.getSudo().xcm.setSafeXcmVersion(alice, SAFE_XCM_VERSION);529    });530531    await usingMoonbeamPlaygrounds(moonbeamUrl, async (helper) => {532      const alithAccount = helper.account.alithAccount();533      const baltatharAccount = helper.account.baltatharAccount();534      const dorothyAccount = helper.account.dorothyAccount();535536      randomAccountMoonbeam = helper.account.create();537538      // >>> Sponsoring Dorothy >>>539      console.log('Sponsoring Dorothy.......');540      await helper.balance.transferToEthereum(alithAccount, dorothyAccount.address, 11_000_000_000_000_000_000n);541      console.log('Sponsoring Dorothy.......DONE');542      // <<< Sponsoring Dorothy <<<543      uniqueAssetLocation = {544        XCM: {545          parents: 1,546          interior: {X1: {Parachain: UNIQUE_CHAIN}},547        },548      };549      const existentialDeposit = 1n;550      const isSufficient = true;551      const unitsPerSecond = 1n;552      const numAssetsWeightHint = 0;553554      if((await helper.assetManager.assetTypeId(uniqueAssetLocation)).toJSON()) {555        console.log('Unique asset already registered on Moonbeam');556      } else {557        const encodedProposal = helper.assetManager.makeRegisterForeignAssetProposal({558          location: uniqueAssetLocation,559          metadata: uniqueAssetMetadata,560          existentialDeposit,561          isSufficient,562          unitsPerSecond,563          numAssetsWeightHint,564        });565566        console.log('Encoded proposal for registerForeignAsset & setAssetUnitsPerSecond is %s', encodedProposal);567568        await helper.fastDemocracy.executeProposal('register UNQ foreign asset', encodedProposal);569      }570571      // >>> Acquire Unique AssetId Info on Moonbeam >>>572      console.log('Acquire Unique AssetId Info on Moonbeam.......');573574      assetId = (await helper.assetManager.assetTypeId(uniqueAssetLocation)).toString();575576      console.log('UNQ asset ID is %s', assetId);577      console.log('Acquire Unique AssetId Info on Moonbeam.......DONE');578579      // >>> Sponsoring random Account >>>580      console.log('Sponsoring random Account.......');581      await helper.balance.transferToEthereum(baltatharAccount, randomAccountMoonbeam.address, 11_000_000_000_000_000_000n);582      console.log('Sponsoring random Account.......DONE');583      // <<< Sponsoring random Account <<<584    });585586    await usingPlaygrounds(async (helper) => {587      await helper.balance.transferToSubstrate(alice, randomAccountUnique.address, SENDER_BUDGET);588      balanceUniqueTokenInit = await helper.balance.getSubstrate(randomAccountUnique.address);589    });590  });591592  itSub('Should connect and send UNQ to Moonbeam', async () => {593    await genericSendUnqTo('moonbeam', randomAccountUnique, randomAccountMoonbeam);594  });595596  itSub('Should connect to Moonbeam and send UNQ back', async () => {597    await genericSendUnqBack('moonbeam', alice, randomAccountUnique);598  });599600  itSub('Moonbeam can send only up to its balance', async () => {601    await genericSendOnlyOwnedBalance('moonbeam', alice);602  });603604  itSub('Should not accept reserve transfer of UNQ from Moonbeam', async () => {605    await genericReserveTransferUNQfrom('moonbeam', alice);606  });607});608609describeXCM('[XCMLL] Integration test: Exchanging tokens with Astar', () => {610  let alice: IKeyringPair;611  let randomAccount: IKeyringPair;612613  const UNQ_ASSET_ID_ON_ASTAR = 1;614  const UNQ_MINIMAL_BALANCE_ON_ASTAR = 1n;615616  // Unique -> Astar617  const astarInitialBalance = 1n * (10n ** ASTAR_DECIMALS); // 1 ASTR, existential deposit required to actually create the account on Astar.618  const unitsPerSecond = 228_000_000_000n; // This is Phala's value. What will be ours?619620  before(async () => {621    await usingPlaygrounds(async (helper, privateKey) => {622      alice = await privateKey('//Alice');623      randomAccount = helper.arrange.createEmptyAccount();624      await helper.balance.transferToSubstrate(alice, randomAccount.address, SENDER_BUDGET);625      console.log('randomAccount', randomAccount.address);626627      // Set the default version to wrap the first message to other chains.628      await helper.getSudo().xcm.setSafeXcmVersion(alice, SAFE_XCM_VERSION);629    });630631    await usingAstarPlaygrounds(astarUrl, async (helper) => {632      if(!(await helper.callRpc('api.query.assets.asset', [UNQ_ASSET_ID_ON_ASTAR])).toJSON()) {633        console.log('1. Create foreign asset and metadata');634        // TODO update metadata with values from production635        await helper.assets.create(636          alice,637          UNQ_ASSET_ID_ON_ASTAR,638          alice.address,639          UNQ_MINIMAL_BALANCE_ON_ASTAR,640        );641642        await helper.assets.setMetadata(643          alice,644          UNQ_ASSET_ID_ON_ASTAR,645          'Cross chain UNQ',646          'xcUNQ',647          Number(UNQ_DECIMALS),648        );649650        console.log('2. Register asset location on Astar');651        const assetLocation = {652          V2: {653            parents: 1,654            interior: {655              X1: {656                Parachain: UNIQUE_CHAIN,657              },658            },659          },660        };661662        await helper.getSudo().executeExtrinsic(alice, 'api.tx.xcAssetConfig.registerAssetLocation', [assetLocation, UNQ_ASSET_ID_ON_ASTAR]);663664        console.log('3. Set UNQ payment for XCM execution on Astar');665        await helper.getSudo().executeExtrinsic(alice, 'api.tx.xcAssetConfig.setAssetUnitsPerSecond', [assetLocation, unitsPerSecond]);666      } else {667        console.log('UNQ is already registered on Astar');668      }669      console.log('4. Transfer 1 ASTR to recipient to create the account (needed due to existential balance)');670      await helper.balance.transferToSubstrate(alice, randomAccount.address, astarInitialBalance);671    });672  });673674  itSub('Should connect and send UNQ to Astar', async () => {675    await genericSendUnqTo('astar', randomAccount);676  });677678  itSub('Should connect to Astar and send UNQ back', async () => {679    await genericSendUnqBack('astar', alice, randomAccount);680  });681682  itSub('Astar can send only up to its balance', async () => {683    await genericSendOnlyOwnedBalance('astar', alice);684  });685686  itSub('Should not accept reserve transfer of UNQ from Astar', async () => {687    await genericReserveTransferUNQfrom('astar', alice);688  });689});
modifiedtests/src/xcm/xcmUnique.test.tsdiffbeforeafterboth
--- a/tests/src/xcm/xcmUnique.test.ts
+++ b/tests/src/xcm/xcmUnique.test.ts
@@ -728,16 +728,7 @@
 
     const maliciousXcmProgramFullId = helper.arrange.makeXcmProgramReserveAssetDeposited(
       targetAccount.addressRaw,
-      {
-        Concrete: {
-          parents: 1,
-          interior: {
-            X1: {
-              Parachain: UNIQUE_CHAIN,
-            },
-          },
-        },
-      },
+      uniqueAssetId,
       testAmount,
     );
 
@@ -900,14 +891,7 @@
 
     const xcmProgram = helper.arrange.makeXcmProgramWithdrawDeposit(
       randomAccount.addressRaw,
-      {
-        Concrete: {
-          parents: 1,
-          interior: {
-            X1: {Parachain: UNIQUE_CHAIN},
-          },
-        },
-      },
+      uniqueAssetId,
       TRANSFER_AMOUNT,
     );
 
@@ -978,16 +962,7 @@
 
     const maliciousXcmProgramFullId = helper.arrange.makeXcmProgramReserveAssetDeposited(
       targetAccount.addressRaw,
-      {
-        Concrete: {
-          parents: 1,
-          interior: {
-            X1: {
-              Parachain: UNIQUE_CHAIN,
-            },
-          },
-        },
-      },
+      uniqueAssetId,
       testAmount,
     );
 
@@ -1477,16 +1452,7 @@
 
     const maliciousXcmProgramFullId = helper.arrange.makeXcmProgramReserveAssetDeposited(
       targetAccount.addressRaw,
-      {
-        Concrete: {
-          parents: 0,
-          interior: {
-            X1: {
-              Parachain: UNIQUE_CHAIN,
-            },
-          },
-        },
-      },
+      uniqueAssetId,
       testAmount,
     );
 
@@ -1821,16 +1787,7 @@
 
     const maliciousXcmProgramFullId = helper.arrange.makeXcmProgramReserveAssetDeposited(
       targetAccount.addressRaw,
-      {
-        Concrete: {
-          parents: 1,
-          interior: {
-            X1: {
-              Parachain: UNIQUE_CHAIN,
-            },
-          },
-        },
-      },
+      uniqueAssetId,
       testAmount,
     );