difftreelog
fix explaning comment about SetTopic relay router
in: master
2 files changed
tests/src/xcm/lowLevelXcmQuartz.test.tsdiffbeforeafterboth1// 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});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});tests/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: