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

difftreelog

fix explaning comment about SetTopic relay router

Daniel Shiposha2023-10-02parent: #a6308d9.patch.diff
in: master

2 files changed

modifiedtests/src/xcm/lowLevelXcmQuartz.test.tsdiffbeforeafterboth
before · tests/src/xcm/lowLevelXcmQuartz.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 {itSub, describeXCM, usingPlaygrounds, usingKaruraPlaygrounds,  usingMoonriverPlaygrounds, usingShidenPlaygrounds, usingRelayPlaygrounds} from '../util';19import {QUARTZ_CHAIN,  QTZ_DECIMALS,  SHIDEN_DECIMALS, karuraUrl, moonriverUrl,  shidenUrl,  SAFE_XCM_VERSION, XcmTestHelper, TRANSFER_AMOUNT, SENDER_BUDGET, relayUrl} from './xcm.types';20import {hexToString} from '@polkadot/util';2122const testHelper = new XcmTestHelper('quartz');2324describeXCM('[XCMLL] Integration test: Exchanging tokens with Karura', () => {25  let alice: IKeyringPair;26  let randomAccount: IKeyringPair;2728  before(async () => {29    await usingPlaygrounds(async (helper, privateKey) => {30      alice = await privateKey('//Alice');31      [randomAccount] = await helper.arrange.createAccounts([0n], alice);3233      // Set the default version to wrap the first message to other chains.34      await helper.getSudo().xcm.setSafeXcmVersion(alice, SAFE_XCM_VERSION);35    });3637    await usingKaruraPlaygrounds(karuraUrl, async (helper) => {38      const destination = {39        V2: {40          parents: 1,41          interior: {42            X1: {43              Parachain: QUARTZ_CHAIN,44            },45          },46        },47      };4849      const metadata = {50        name: 'Quartz',51        symbol: 'QTZ',52        decimals: 18,53        minimalBalance: 1000000000000000000n,54      };5556      const assets = (await (helper.callRpc('api.query.assetRegistry.assetMetadatas.entries'))).map(([_k, v]: [any, any]) =>57        hexToString(v.toJSON()['symbol'])) as string[];5859      if(!assets.includes('QTZ')) {60        await helper.getSudo().assetRegistry.registerForeignAsset(alice, destination, metadata);61      } else {62        console.log('QTZ token already registered on Karura assetRegistry pallet');63      }64      await helper.balance.transferToSubstrate(alice, randomAccount.address, 10000000000000n);65    });6667    await usingPlaygrounds(async (helper) => {68      await helper.balance.transferToSubstrate(alice, randomAccount.address, SENDER_BUDGET);69    });70  });7172  itSub('Should connect and send QTZ to Karura', async () => {73    await testHelper.sendUnqTo('karura', randomAccount);74  });7576  itSub('Should connect to Karura and send QTZ back', async () => {77    await testHelper.sendUnqBack('karura', alice, randomAccount);78  });7980  itSub('Karura can send only up to its balance', async () => {81    await testHelper.sendOnlyOwnedBalance('karura', alice);82  });83});84// These tests are relevant only when85// the the corresponding foreign assets are not registered86describeXCM('[XCMLL] Integration test: Quartz rejects non-native tokens', () => {87  let alice: IKeyringPair;888990  before(async () => {91    await usingPlaygrounds(async (helper, privateKey) => {92      alice = await privateKey('//Alice');93949596      // Set the default version to wrap the first message to other chains.97      await helper.getSudo().xcm.setSafeXcmVersion(alice, SAFE_XCM_VERSION);98    });99  });100101  itSub('Quartz rejects KAR tokens from Karura', async () => {102    await testHelper.rejectNativeTokensFrom('karura', alice);103  });104105  itSub('Quartz rejects MOVR tokens from Moonriver', async () => {106    await testHelper.rejectNativeTokensFrom('moonriver', alice);107  });108109  itSub('Quartz rejects SDN tokens from Shiden', async () => {110    await testHelper.rejectNativeTokensFrom('shiden', alice);111  });112});113114describeXCM('[XCMLL] Integration test: Exchanging QTZ with Moonriver', () => {115  // Quartz constants116  let alice: IKeyringPair;117  let quartzAssetLocation;118119  let randomAccountQuartz: IKeyringPair;120  let randomAccountMoonriver: IKeyringPair;121122  // Moonriver constants123  let assetId: string;124125  const quartzAssetMetadata = {126    name: 'xcQuartz',127    symbol: 'xcQTZ',128    decimals: 18,129    isFrozen: false,130    minimalBalance: 1n,131  };132133134  before(async () => {135    await usingPlaygrounds(async (helper, privateKey) => {136      alice = await privateKey('//Alice');137      [randomAccountQuartz] = await helper.arrange.createAccounts([0n], alice);138139140      // Set the default version to wrap the first message to other chains.141      await helper.getSudo().xcm.setSafeXcmVersion(alice, SAFE_XCM_VERSION);142    });143144    await usingMoonriverPlaygrounds(moonriverUrl, async (helper) => {145      const alithAccount = helper.account.alithAccount();146      const baltatharAccount = helper.account.baltatharAccount();147      const dorothyAccount = helper.account.dorothyAccount();148149      randomAccountMoonriver = helper.account.create();150151      // >>> Sponsoring Dorothy >>>152      console.log('Sponsoring Dorothy.......');153      await helper.balance.transferToEthereum(alithAccount, dorothyAccount.address, 11_000_000_000_000_000_000n);154      console.log('Sponsoring Dorothy.......DONE');155      // <<< Sponsoring Dorothy <<<156157      quartzAssetLocation = {158        XCM: {159          parents: 1,160          interior: {X1: {Parachain: QUARTZ_CHAIN}},161        },162      };163      const existentialDeposit = 1n;164      const isSufficient = true;165      const unitsPerSecond = 1n;166      const numAssetsWeightHint = 0;167      if((await helper.assetManager.assetTypeId(quartzAssetLocation)).toJSON()) {168        console.log('Quartz asset already registered on Moonriver');169      } else {170        const encodedProposal = helper.assetManager.makeRegisterForeignAssetProposal({171          location: quartzAssetLocation,172          metadata: quartzAssetMetadata,173          existentialDeposit,174          isSufficient,175          unitsPerSecond,176          numAssetsWeightHint,177        });178179        console.log('Encoded proposal for registerForeignAsset & setAssetUnitsPerSecond is %s', encodedProposal);180181        await helper.fastDemocracy.executeProposal('register QTZ foreign asset', encodedProposal);182      }183      // >>> Acquire Quartz AssetId Info on Moonriver >>>184      console.log('Acquire Quartz AssetId Info on Moonriver.......');185186      assetId = (await helper.assetManager.assetTypeId(quartzAssetLocation)).toString();187188      console.log('QTZ asset ID is %s', assetId);189      console.log('Acquire Quartz AssetId Info on Moonriver.......DONE');190      // >>> Acquire Quartz AssetId Info on Moonriver >>>191192      // >>> Sponsoring random Account >>>193      console.log('Sponsoring random Account.......');194      await helper.balance.transferToEthereum(baltatharAccount, randomAccountMoonriver.address, 11_000_000_000_000_000_000n);195      console.log('Sponsoring random Account.......DONE');196      // <<< Sponsoring random Account <<<197    });198199    await usingPlaygrounds(async (helper) => {200      await helper.balance.transferToSubstrate(alice, randomAccountQuartz.address, 10n * TRANSFER_AMOUNT);201    });202  });203204  itSub('Should connect and send QTZ to Moonriver', async () => {205    await testHelper.sendUnqTo('moonriver', randomAccountQuartz, randomAccountMoonriver);206  });207208  itSub('Should connect to Moonriver and send QTZ back', async () => {209    await testHelper.sendUnqBack('moonriver', alice, randomAccountQuartz);210  });211212  itSub('Moonriver can send only up to its balance', async () => {213    await testHelper.sendOnlyOwnedBalance('moonriver', alice);214  });215216  itSub('Should not accept reserve transfer of QTZ from Moonriver', async () => {217    await testHelper.reserveTransferUNQfrom('moonriver', alice);218  });219});220221describeXCM('[XCMLL] Integration test: Exchanging tokens with Shiden', () => {222  let alice: IKeyringPair;223  let randomAccount: IKeyringPair;224225  const QTZ_ASSET_ID_ON_SHIDEN = 1;226  const QTZ_MINIMAL_BALANCE_ON_SHIDEN = 1n;227228  // Quartz -> Shiden229  const shidenInitialBalance = 1n * (10n ** SHIDEN_DECIMALS); // 1 SHD, existential deposit required to actually create the account on Shiden230  const unitsPerSecond = 228_000_000_000n; // This is Phala's value. What will be ours?231232233234  before(async () => {235    await usingPlaygrounds(async (helper, privateKey) => {236      alice = await privateKey('//Alice');237      randomAccount = helper.arrange.createEmptyAccount();238      await helper.balance.transferToSubstrate(alice, randomAccount.address, SENDER_BUDGET);239      console.log('sender: ', randomAccount.address);240241      // Set the default version to wrap the first message to other chains.242      await helper.getSudo().xcm.setSafeXcmVersion(alice, SAFE_XCM_VERSION);243    });244245    await usingShidenPlaygrounds(shidenUrl, async (helper) => {246      if(!(await helper.callRpc('api.query.assets.asset', [QTZ_ASSET_ID_ON_SHIDEN])).toJSON()) {247        console.log('1. Create foreign asset and metadata');248        // TODO update metadata with values from production249        await helper.assets.create(250          alice,251          QTZ_ASSET_ID_ON_SHIDEN,252          alice.address,253          QTZ_MINIMAL_BALANCE_ON_SHIDEN,254        );255256        await helper.assets.setMetadata(257          alice,258          QTZ_ASSET_ID_ON_SHIDEN,259          'Cross chain QTZ',260          'xcQTZ',261          Number(QTZ_DECIMALS),262        );263264        console.log('2. Register asset location on Shiden');265        const assetLocation = {266          V2: {267            parents: 1,268            interior: {269              X1: {270                Parachain: QUARTZ_CHAIN,271              },272            },273          },274        };275276        await helper.getSudo().executeExtrinsic(alice, 'api.tx.xcAssetConfig.registerAssetLocation', [assetLocation, QTZ_ASSET_ID_ON_SHIDEN]);277278        console.log('3. Set QTZ payment for XCM execution on Shiden');279        await helper.getSudo().executeExtrinsic(alice, 'api.tx.xcAssetConfig.setAssetUnitsPerSecond', [assetLocation, unitsPerSecond]);280      } else {281        console.log('QTZ is already registered on Shiden');282      }283      console.log('4. Transfer 1 SDN to recipient to create the account (needed due to existential balance)');284      await helper.balance.transferToSubstrate(alice, randomAccount.address, shidenInitialBalance);285    });286  });287288  itSub('Should connect and send QTZ to Shiden', async () => {289    await testHelper.sendUnqTo('shiden', randomAccount);290  });291292  itSub('Should connect to Shiden and send QTZ back', async () => {293    await testHelper.sendUnqBack('shiden', alice, randomAccount);294  });295296  itSub('Shiden can send only up to its balance', async () => {297    await testHelper.sendOnlyOwnedBalance('shiden', alice);298  });299300  itSub('Should not accept reserve transfer of QTZ from Shiden', async () => {301    await testHelper.reserveTransferUNQfrom('shiden', alice);302  });303});304305describeXCM('[XCMLL] Integration test: The relay can do some root ops', () => {306  let sudoer: IKeyringPair;307308  before(async function () {309    await usingRelayPlaygrounds(relayUrl, async (_, privateKey) => {310      sudoer = await privateKey('//Alice');311    });312  });313314  // At the moment there is no reliable way315  // to establish the correspondence between the `ExecutedDownward` event316  // and the relay's sent message due to `SetTopic` instruction317  // containing an unpredictable topic silently added by the relay on the router level.318  // This changes the message hash on arrival to our chain.319  //320  // See:321  // * The relay's router: https://github.com/paritytech/polkadot-sdk/blob/f60318f68687e601c47de5ad5ca88e2c3f8139a7/polkadot/runtime/westend/src/xcm_config.rs#L83322  // * The `WithUniqueTopic` helper: https://github.com/paritytech/polkadot-sdk/blob/945ebbbcf66646be13d5b1d1bc26c8b0d3296d9e/polkadot/xcm/xcm-builder/src/routing.rs#L36323  //324  // Because of this, we insert time gaps between tests so325  // different `ExecutedDownward` events won't interfere with each other.326  afterEach(async () => {327    await usingPlaygrounds(async (helper) => {328      await helper.wait.newBlocks(3);329    });330  });331332  itSub('The relay can set storage', async () => {333    await testHelper.relayIsPermittedToSetStorage(sudoer, 'plain');334  });335336  itSub('The relay can batch set storage', async () => {337    await testHelper.relayIsPermittedToSetStorage(sudoer, 'batch');338  });339340  itSub('The relay can batchAll set storage', async () => {341    await testHelper.relayIsPermittedToSetStorage(sudoer, 'batchAll');342  });343344  itSub('The relay can forceBatch set storage', async () => {345    await testHelper.relayIsPermittedToSetStorage(sudoer, 'forceBatch');346  });347348  itSub('[negative] The relay cannot set balance', async () => {349    await testHelper.relayIsNotPermittedToSetBalance(sudoer, 'plain');350  });351352  itSub('[negative] The relay cannot set balance via batch', async () => {353    await testHelper.relayIsNotPermittedToSetBalance(sudoer, 'batch');354  });355356  itSub('[negative] The relay cannot set balance via batchAll', async () => {357    await testHelper.relayIsNotPermittedToSetBalance(sudoer, 'batchAll');358  });359360  itSub('[negative] The relay cannot set balance via forceBatch', async () => {361    await testHelper.relayIsNotPermittedToSetBalance(sudoer, 'forceBatch');362  });363364  itSub('[negative] The relay cannot set balance via dispatchAs', async () => {365    await testHelper.relayIsNotPermittedToSetBalance(sudoer, 'dispatchAs');366  });367});
after · tests/src/xcm/lowLevelXcmQuartz.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 {itSub, describeXCM, usingPlaygrounds, usingKaruraPlaygrounds,  usingMoonriverPlaygrounds, usingShidenPlaygrounds, usingRelayPlaygrounds} from '../util';19import {QUARTZ_CHAIN,  QTZ_DECIMALS,  SHIDEN_DECIMALS, karuraUrl, moonriverUrl,  shidenUrl,  SAFE_XCM_VERSION, XcmTestHelper, TRANSFER_AMOUNT, SENDER_BUDGET, relayUrl} from './xcm.types';20import {hexToString} from '@polkadot/util';2122const testHelper = new XcmTestHelper('quartz');2324describeXCM('[XCMLL] Integration test: Exchanging tokens with Karura', () => {25  let alice: IKeyringPair;26  let randomAccount: IKeyringPair;2728  before(async () => {29    await usingPlaygrounds(async (helper, privateKey) => {30      alice = await privateKey('//Alice');31      [randomAccount] = await helper.arrange.createAccounts([0n], alice);3233      // Set the default version to wrap the first message to other chains.34      await helper.getSudo().xcm.setSafeXcmVersion(alice, SAFE_XCM_VERSION);35    });3637    await usingKaruraPlaygrounds(karuraUrl, async (helper) => {38      const destination = {39        V2: {40          parents: 1,41          interior: {42            X1: {43              Parachain: QUARTZ_CHAIN,44            },45          },46        },47      };4849      const metadata = {50        name: 'Quartz',51        symbol: 'QTZ',52        decimals: 18,53        minimalBalance: 1000000000000000000n,54      };5556      const assets = (await (helper.callRpc('api.query.assetRegistry.assetMetadatas.entries'))).map(([_k, v]: [any, any]) =>57        hexToString(v.toJSON()['symbol'])) as string[];5859      if(!assets.includes('QTZ')) {60        await helper.getSudo().assetRegistry.registerForeignAsset(alice, destination, metadata);61      } else {62        console.log('QTZ token already registered on Karura assetRegistry pallet');63      }64      await helper.balance.transferToSubstrate(alice, randomAccount.address, 10000000000000n);65    });6667    await usingPlaygrounds(async (helper) => {68      await helper.balance.transferToSubstrate(alice, randomAccount.address, SENDER_BUDGET);69    });70  });7172  itSub('Should connect and send QTZ to Karura', async () => {73    await testHelper.sendUnqTo('karura', randomAccount);74  });7576  itSub('Should connect to Karura and send QTZ back', async () => {77    await testHelper.sendUnqBack('karura', alice, randomAccount);78  });7980  itSub('Karura can send only up to its balance', async () => {81    await testHelper.sendOnlyOwnedBalance('karura', alice);82  });83});84// These tests are relevant only when85// the the corresponding foreign assets are not registered86describeXCM('[XCMLL] Integration test: Quartz rejects non-native tokens', () => {87  let alice: IKeyringPair;888990  before(async () => {91    await usingPlaygrounds(async (helper, privateKey) => {92      alice = await privateKey('//Alice');93949596      // Set the default version to wrap the first message to other chains.97      await helper.getSudo().xcm.setSafeXcmVersion(alice, SAFE_XCM_VERSION);98    });99  });100101  itSub('Quartz rejects KAR tokens from Karura', async () => {102    await testHelper.rejectNativeTokensFrom('karura', alice);103  });104105  itSub('Quartz rejects MOVR tokens from Moonriver', async () => {106    await testHelper.rejectNativeTokensFrom('moonriver', alice);107  });108109  itSub('Quartz rejects SDN tokens from Shiden', async () => {110    await testHelper.rejectNativeTokensFrom('shiden', alice);111  });112});113114describeXCM('[XCMLL] Integration test: Exchanging QTZ with Moonriver', () => {115  // Quartz constants116  let alice: IKeyringPair;117  let quartzAssetLocation;118119  let randomAccountQuartz: IKeyringPair;120  let randomAccountMoonriver: IKeyringPair;121122  // Moonriver constants123  let assetId: string;124125  const quartzAssetMetadata = {126    name: 'xcQuartz',127    symbol: 'xcQTZ',128    decimals: 18,129    isFrozen: false,130    minimalBalance: 1n,131  };132133134  before(async () => {135    await usingPlaygrounds(async (helper, privateKey) => {136      alice = await privateKey('//Alice');137      [randomAccountQuartz] = await helper.arrange.createAccounts([0n], alice);138139140      // Set the default version to wrap the first message to other chains.141      await helper.getSudo().xcm.setSafeXcmVersion(alice, SAFE_XCM_VERSION);142    });143144    await usingMoonriverPlaygrounds(moonriverUrl, async (helper) => {145      const alithAccount = helper.account.alithAccount();146      const baltatharAccount = helper.account.baltatharAccount();147      const dorothyAccount = helper.account.dorothyAccount();148149      randomAccountMoonriver = helper.account.create();150151      // >>> Sponsoring Dorothy >>>152      console.log('Sponsoring Dorothy.......');153      await helper.balance.transferToEthereum(alithAccount, dorothyAccount.address, 11_000_000_000_000_000_000n);154      console.log('Sponsoring Dorothy.......DONE');155      // <<< Sponsoring Dorothy <<<156157      quartzAssetLocation = {158        XCM: {159          parents: 1,160          interior: {X1: {Parachain: QUARTZ_CHAIN}},161        },162      };163      const existentialDeposit = 1n;164      const isSufficient = true;165      const unitsPerSecond = 1n;166      const numAssetsWeightHint = 0;167      if((await helper.assetManager.assetTypeId(quartzAssetLocation)).toJSON()) {168        console.log('Quartz asset already registered on Moonriver');169      } else {170        const encodedProposal = helper.assetManager.makeRegisterForeignAssetProposal({171          location: quartzAssetLocation,172          metadata: quartzAssetMetadata,173          existentialDeposit,174          isSufficient,175          unitsPerSecond,176          numAssetsWeightHint,177        });178179        console.log('Encoded proposal for registerForeignAsset & setAssetUnitsPerSecond is %s', encodedProposal);180181        await helper.fastDemocracy.executeProposal('register QTZ foreign asset', encodedProposal);182      }183      // >>> Acquire Quartz AssetId Info on Moonriver >>>184      console.log('Acquire Quartz AssetId Info on Moonriver.......');185186      assetId = (await helper.assetManager.assetTypeId(quartzAssetLocation)).toString();187188      console.log('QTZ asset ID is %s', assetId);189      console.log('Acquire Quartz AssetId Info on Moonriver.......DONE');190      // >>> Acquire Quartz AssetId Info on Moonriver >>>191192      // >>> Sponsoring random Account >>>193      console.log('Sponsoring random Account.......');194      await helper.balance.transferToEthereum(baltatharAccount, randomAccountMoonriver.address, 11_000_000_000_000_000_000n);195      console.log('Sponsoring random Account.......DONE');196      // <<< Sponsoring random Account <<<197    });198199    await usingPlaygrounds(async (helper) => {200      await helper.balance.transferToSubstrate(alice, randomAccountQuartz.address, 10n * TRANSFER_AMOUNT);201    });202  });203204  itSub('Should connect and send QTZ to Moonriver', async () => {205    await testHelper.sendUnqTo('moonriver', randomAccountQuartz, randomAccountMoonriver);206  });207208  itSub('Should connect to Moonriver and send QTZ back', async () => {209    await testHelper.sendUnqBack('moonriver', alice, randomAccountQuartz);210  });211212  itSub('Moonriver can send only up to its balance', async () => {213    await testHelper.sendOnlyOwnedBalance('moonriver', alice);214  });215216  itSub('Should not accept reserve transfer of QTZ from Moonriver', async () => {217    await testHelper.reserveTransferUNQfrom('moonriver', alice);218  });219});220221describeXCM('[XCMLL] Integration test: Exchanging tokens with Shiden', () => {222  let alice: IKeyringPair;223  let randomAccount: IKeyringPair;224225  const QTZ_ASSET_ID_ON_SHIDEN = 1;226  const QTZ_MINIMAL_BALANCE_ON_SHIDEN = 1n;227228  // Quartz -> Shiden229  const shidenInitialBalance = 1n * (10n ** SHIDEN_DECIMALS); // 1 SHD, existential deposit required to actually create the account on Shiden230  const unitsPerSecond = 228_000_000_000n; // This is Phala's value. What will be ours?231232233234  before(async () => {235    await usingPlaygrounds(async (helper, privateKey) => {236      alice = await privateKey('//Alice');237      randomAccount = helper.arrange.createEmptyAccount();238      await helper.balance.transferToSubstrate(alice, randomAccount.address, SENDER_BUDGET);239      console.log('sender: ', randomAccount.address);240241      // Set the default version to wrap the first message to other chains.242      await helper.getSudo().xcm.setSafeXcmVersion(alice, SAFE_XCM_VERSION);243    });244245    await usingShidenPlaygrounds(shidenUrl, async (helper) => {246      if(!(await helper.callRpc('api.query.assets.asset', [QTZ_ASSET_ID_ON_SHIDEN])).toJSON()) {247        console.log('1. Create foreign asset and metadata');248        // TODO update metadata with values from production249        await helper.assets.create(250          alice,251          QTZ_ASSET_ID_ON_SHIDEN,252          alice.address,253          QTZ_MINIMAL_BALANCE_ON_SHIDEN,254        );255256        await helper.assets.setMetadata(257          alice,258          QTZ_ASSET_ID_ON_SHIDEN,259          'Cross chain QTZ',260          'xcQTZ',261          Number(QTZ_DECIMALS),262        );263264        console.log('2. Register asset location on Shiden');265        const assetLocation = {266          V2: {267            parents: 1,268            interior: {269              X1: {270                Parachain: QUARTZ_CHAIN,271              },272            },273          },274        };275276        await helper.getSudo().executeExtrinsic(alice, 'api.tx.xcAssetConfig.registerAssetLocation', [assetLocation, QTZ_ASSET_ID_ON_SHIDEN]);277278        console.log('3. Set QTZ payment for XCM execution on Shiden');279        await helper.getSudo().executeExtrinsic(alice, 'api.tx.xcAssetConfig.setAssetUnitsPerSecond', [assetLocation, unitsPerSecond]);280      } else {281        console.log('QTZ is already registered on Shiden');282      }283      console.log('4. Transfer 1 SDN to recipient to create the account (needed due to existential balance)');284      await helper.balance.transferToSubstrate(alice, randomAccount.address, shidenInitialBalance);285    });286  });287288  itSub('Should connect and send QTZ to Shiden', async () => {289    await testHelper.sendUnqTo('shiden', randomAccount);290  });291292  itSub('Should connect to Shiden and send QTZ back', async () => {293    await testHelper.sendUnqBack('shiden', alice, randomAccount);294  });295296  itSub('Shiden can send only up to its balance', async () => {297    await testHelper.sendOnlyOwnedBalance('shiden', alice);298  });299300  itSub('Should not accept reserve transfer of QTZ from Shiden', async () => {301    await testHelper.reserveTransferUNQfrom('shiden', alice);302  });303});304305describeXCM('[XCMLL] Integration test: The relay can do some root ops', () => {306  let sudoer: IKeyringPair;307308  before(async function () {309    await usingRelayPlaygrounds(relayUrl, async (_, privateKey) => {310      sudoer = await privateKey('//Alice');311    });312  });313314  // At the moment there is no reliable way315  // to establish the correspondence between the `ExecutedDownward` event316  // and the relay's sent message due to `SetTopic` instruction317  // containing an unpredictable topic silently added by the relay's messages on the router level.318  // This changes the message hash on arrival to our chain.319  //320  // See:321  // * The relay's router: https://github.com/paritytech/polkadot-sdk/blob/f60318f68687e601c47de5ad5ca88e2c3f8139a7/polkadot/runtime/westend/src/xcm_config.rs#L83322  // * The `WithUniqueTopic` helper: https://github.com/paritytech/polkadot-sdk/blob/945ebbbcf66646be13d5b1d1bc26c8b0d3296d9e/polkadot/xcm/xcm-builder/src/routing.rs#L36323  //324  // Because of this, we insert time gaps between tests so325  // different `ExecutedDownward` events won't interfere with each other.326  afterEach(async () => {327    await usingPlaygrounds(async (helper) => {328      await helper.wait.newBlocks(3);329    });330  });331332  itSub('The relay can set storage', async () => {333    await testHelper.relayIsPermittedToSetStorage(sudoer, 'plain');334  });335336  itSub('The relay can batch set storage', async () => {337    await testHelper.relayIsPermittedToSetStorage(sudoer, 'batch');338  });339340  itSub('The relay can batchAll set storage', async () => {341    await testHelper.relayIsPermittedToSetStorage(sudoer, 'batchAll');342  });343344  itSub('The relay can forceBatch set storage', async () => {345    await testHelper.relayIsPermittedToSetStorage(sudoer, 'forceBatch');346  });347348  itSub('[negative] The relay cannot set balance', async () => {349    await testHelper.relayIsNotPermittedToSetBalance(sudoer, 'plain');350  });351352  itSub('[negative] The relay cannot set balance via batch', async () => {353    await testHelper.relayIsNotPermittedToSetBalance(sudoer, 'batch');354  });355356  itSub('[negative] The relay cannot set balance via batchAll', async () => {357    await testHelper.relayIsNotPermittedToSetBalance(sudoer, 'batchAll');358  });359360  itSub('[negative] The relay cannot set balance via forceBatch', async () => {361    await testHelper.relayIsNotPermittedToSetBalance(sudoer, 'forceBatch');362  });363364  itSub('[negative] The relay cannot set balance via dispatchAs', async () => {365    await testHelper.relayIsNotPermittedToSetBalance(sudoer, 'dispatchAs');366  });367});
modifiedtests/src/xcm/lowLevelXcmUnique.test.tsdiffbeforeafterboth
--- a/tests/src/xcm/lowLevelXcmUnique.test.ts
+++ b/tests/src/xcm/lowLevelXcmUnique.test.ts
@@ -378,7 +378,7 @@
   // At the moment there is no reliable way
   // to establish the correspondence between the `ExecutedDownward` event
   // and the relay's sent message due to `SetTopic` instruction
-  // containing an unpredictable topic silently added by the relay on the router level.
+  // containing an unpredictable topic silently added by the relay's messages on the router level.
   // This changes the message hash on arrival to our chain.
   //
   // See: