difftreelog
Merge pull request #923 from UniqueNetwork/fix/xcm-tests-wait-for-events
in: master
4 files changed
tests/src/scheduler.seqtest.tsdiffbeforeafterboth--- a/tests/src/scheduler.seqtest.ts
+++ b/tests/src/scheduler.seqtest.ts
@@ -16,7 +16,7 @@
import {expect, itSched, itSub, Pallets, requirePalletsOrSkip, usingPlaygrounds} from './util';
import {IKeyringPair} from '@polkadot/types/types';
-import {DevUniqueHelper} from './util/playgrounds/unique.dev';
+import {DevUniqueHelper, Event} from './util/playgrounds/unique.dev';
describe('Scheduling token and balance transfers', () => {
let superuser: IKeyringPair;
@@ -411,19 +411,13 @@
const priority = 112;
await helper.getSudo().scheduler.changePriority(superuser, scheduledId, priority);
- const priorityChanged = await helper.wait.event(
- waitForBlocks,
- 'scheduler',
- 'PriorityChanged',
- );
-
- expect(priorityChanged !== null).to.be.true;
+ const priorityChanged = await helper.wait.expectEvent(waitForBlocks, Event.Scheduler.PriorityChanged);
- const [blockNumber, index] = priorityChanged!.event.data[0].toJSON() as any[];
+ const [blockNumber, index] = priorityChanged.task();
expect(blockNumber).to.be.equal(executionBlock);
expect(index).to.be.equal(0);
- expect(priorityChanged!.event.data[1].toString()).to.be.equal(priority.toString());
+ expect(priorityChanged.priority().toString()).to.be.equal(priority.toString());
});
itSub('Prioritized operations execute in valid order', async ({helper}) => {
@@ -668,13 +662,7 @@
await expect(helper.scheduler.changePriority(alice, scheduledId, priority))
.to.be.rejectedWith(/BadOrigin/);
- const priorityChanged = await helper.wait.event(
- waitForBlocks,
- 'scheduler',
- 'PriorityChanged',
- );
-
- expect(priorityChanged === null).to.be.true;
+ await helper.wait.expectEvent(waitForBlocks, Event.Scheduler.PriorityChanged);
});
});
tests/src/util/playgrounds/unique.dev.tsdiffbeforeafterboth--- a/tests/src/util/playgrounds/unique.dev.ts
+++ b/tests/src/util/playgrounds/unique.dev.ts
@@ -9,7 +9,7 @@
import {IKeyringPair} from '@polkadot/types/types';
import {EventRecord} from '@polkadot/types/interfaces';
import {ICrossAccountId, IPovInfo, TSigner} from './types';
-import {FrameSystemEventRecord} from '@polkadot/types/lookup';
+import {FrameSystemEventRecord, XcmV2TraitsError} from '@polkadot/types/lookup';
import {VoidFn} from '@polkadot/api/types';
import {Pallets} from '..';
import {spawnSync} from 'child_process';
@@ -59,6 +59,130 @@
}
}
+export interface IEventHelper {
+ section(): string;
+
+ method(): string;
+
+ bindEventRecord(e: FrameSystemEventRecord): void;
+
+ raw(): FrameSystemEventRecord;
+}
+
+// eslint-disable-next-line @typescript-eslint/naming-convention
+function EventHelper(section: string, method: string) {
+ return class implements IEventHelper {
+ eventRecord: FrameSystemEventRecord | null;
+ _section: string;
+ _method: string;
+
+ constructor() {
+ this.eventRecord = null;
+ this._section = section;
+ this._method = method;
+ }
+
+ section(): string {
+ return this._section;
+ }
+
+ method(): string {
+ return this._method;
+ }
+
+ bindEventRecord(e: FrameSystemEventRecord) {
+ this.eventRecord = e;
+ }
+
+ raw() {
+ return this.eventRecord!;
+ }
+
+ eventJsonData<T = any>(index: number) {
+ return this.raw().event.data[index].toJSON() as T;
+ }
+
+ eventData<T>(index: number) {
+ return this.raw().event.data[index] as T;
+ }
+ };
+}
+
+// eslint-disable-next-line @typescript-eslint/naming-convention
+function EventSection(section: string) {
+ return class Section {
+ static section = section;
+
+ static Method(name: string) {
+ return EventHelper(Section.section, name);
+ }
+ };
+}
+
+export class Event {
+ static Democracy = class extends EventSection('democracy') {
+ static Started = class extends this.Method('Started') {
+ referendumIndex() {
+ return this.eventJsonData<number>(0);
+ }
+
+ threshold() {
+ return this.eventJsonData(1);
+ }
+ };
+
+ static Voted = class extends this.Method('Voted') {
+ voter() {
+ return this.eventJsonData(0);
+ }
+
+ referendumIndex() {
+ return this.eventJsonData<number>(1);
+ }
+
+ vote() {
+ return this.eventJsonData(2);
+ }
+ };
+
+ static Passed = class extends this.Method('Passed') {
+ referendumIndex() {
+ return this.eventJsonData<number>(0);
+ }
+ };
+ };
+
+ static Scheduler = class extends EventSection('scheduler') {
+ static PriorityChanged = class extends this.Method('PriorityChanged') {
+ task() {
+ return this.eventJsonData(0);
+ }
+
+ priority() {
+ return this.eventJsonData(1);
+ }
+ };
+ };
+
+ static XcmpQueue = class extends EventSection('xcmpQueue') {
+ static XcmpMessageSent = class extends this.Method('XcmpMessageSent') {
+ messageHash() {
+ return this.eventJsonData(0);
+ }
+ };
+
+ static Fail = class extends this.Method('Fail') {
+ messageHash() {
+ return this.eventJsonData(0);
+ }
+
+ outcome() {
+ return this.eventData<XcmV2TraitsError>(1);
+ }
+ };
+ };
+}
+
export class DevUniqueHelper extends UniqueHelper {
/**
* Arrange methods for tests
@@ -634,12 +758,12 @@
console.log('\t* Fast track proposal through technical committee.......DONE');
// <<< Fast track proposal through technical committee <<<
- const refIndexField = 0;
- const referendumIndex = await this.helper.wait.eventData<number>(3, 'democracy', 'Started', refIndexField);
+ const democracyStarted = await this.helper.wait.expectEvent(3, Event.Democracy.Started);
+ const referendumIndex = democracyStarted.referendumIndex();
// >>> Referendum voting >>>
console.log(`\t* Referendum #${referendumIndex} voting.......`);
- await this.helper.democracy.referendumVote(dorothyAccount, referendumIndex!, {
+ await this.helper.democracy.referendumVote(dorothyAccount, referendumIndex, {
balance: 10_000_000_000_000_000_000n,
vote: {aye: true, conviction: 1},
});
@@ -647,7 +771,10 @@
// <<< Referendum voting <<<
// Wait the proposal to pass
- await this.helper.wait.event(3, 'democracy', 'Passed');
+ await this.helper.wait.expectEvent(3, Event.Democracy.Passed, event => {
+ return event.referendumIndex() == referendumIndex;
+ });
+
await this.helper.wait.newBlocks(1);
console.log(`[democracy] executing '${proposalDesciption}' proposal.......DONE`);
@@ -794,13 +921,18 @@
return promise;
}
- event(maxBlocksToWait: number, eventSection: string, eventMethod: string) {
+ event<T extends IEventHelper>(
+ maxBlocksToWait: number,
+ eventHelperType: new () => T,
+ filter: (_: T) => boolean = () => { return true; },
+ ) {
// eslint-disable-next-line no-async-promise-executor
- const promise = new Promise<EventRecord | null>(async (resolve) => {
+ const promise = new Promise<T | null>(async (resolve) => {
const unsubscribe = await this.helper.getApi().rpc.chain.subscribeNewHeads(async header => {
+ const eventHelper = new eventHelperType();
const blockNumber = header.number.toHuman();
const blockHash = header.hash;
- const eventIdStr = `${eventSection}.${eventMethod}`;
+ const eventIdStr = `${eventHelper.section()}.${eventHelper.method()}`;
const waitLimitStr = `wait blocks remaining: ${maxBlocksToWait}`;
this.helper.logger.log(`[Block #${blockNumber}] Waiting for event \`${eventIdStr}\` (${waitLimitStr})`);
@@ -809,16 +941,24 @@
const eventRecords = (await apiAt.query.system.events()) as any;
const neededEvent = eventRecords.toArray().find((r: FrameSystemEventRecord) => {
- return r.event.section == eventSection && r.event.method == eventMethod;
+ if (
+ r.event.section == eventHelper.section()
+ && r.event.method == eventHelper.method()
+ ) {
+ eventHelper.bindEventRecord(r);
+ return filter(eventHelper);
+ } else {
+ return false;
+ }
});
if (neededEvent) {
unsubscribe();
- resolve(neededEvent);
+ resolve(eventHelper);
} else if (maxBlocksToWait > 0) {
maxBlocksToWait--;
} else {
- this.helper.logger.log(`Event \`${eventIdStr}\` is NOT found`);
+ this.helper.logger.log(`Eligible event \`${eventIdStr}\` is NOT found`);
unsubscribe();
resolve(null);
}
@@ -827,17 +967,18 @@
return promise;
}
- async eventData<EventT>(maxBlocksToWait: number, eventSection: string, eventMethod: string, fieldIndex: number) {
- const eventRecord = await this.event(maxBlocksToWait, eventSection, eventMethod);
-
- if (eventRecord == null) {
- return null;
+ async expectEvent<T extends IEventHelper>(
+ maxBlocksToWait: number,
+ eventHelperType: new () => T,
+ filter: (e: T) => boolean = () => { return true; },
+ ) {
+ const e = await this.event(maxBlocksToWait, eventHelperType, filter);
+ if (e == null) {
+ const eventHelper = new eventHelperType();
+ throw Error(`The event '${eventHelper.section()}.${eventHelper.method()}' is expected`);
+ } else {
+ return e;
}
-
- const event = eventRecord!.event;
- const data = event.data[fieldIndex] as EventT;
-
- return data;
}
}
tests/src/xcm/xcmQuartz.test.tsdiffbeforeafterboth161617import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';18import config from '../config';18import config from '../config';19import {XcmV2TraitsError} from '../interfaces';20import {itSub, expect, describeXCM, usingPlaygrounds, usingKaruraPlaygrounds, usingRelayPlaygrounds, usingMoonriverPlaygrounds, usingStateminePlaygrounds, usingShidenPlaygrounds} from '../util';19import {itSub, expect, describeXCM, usingPlaygrounds, usingKaruraPlaygrounds, usingRelayPlaygrounds, usingMoonriverPlaygrounds, usingStateminePlaygrounds, usingShidenPlaygrounds} from '../util';21import {DevUniqueHelper} from '../util/playgrounds/unique.dev';20import {DevUniqueHelper, Event} from '../util/playgrounds/unique.dev';222123const QUARTZ_CHAIN = 2095;22const QUARTZ_CHAIN = 2095;24const STATEMINE_CHAIN = 1000;23const STATEMINE_CHAIN = 1000;673 moreThanKaruraHas,672 moreThanKaruraHas,674 );673 );674675 let maliciousXcmProgramSent: any;676 const maxWaitBlocks = 3;675677676 // Try to trick Quartz678 // Try to trick Quartz677 await usingKaruraPlaygrounds(karuraUrl, async (helper) => {679 await usingKaruraPlaygrounds(karuraUrl, async (helper) => {678 await helper.getSudo().xcm.send(alice, quartzMultilocation, maliciousXcmProgram);680 await helper.getSudo().xcm.send(alice, quartzMultilocation, maliciousXcmProgram);681682 maliciousXcmProgramSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);679 });683 });680681 const maxWaitBlocks = 3;682 const outcomeField = 1;683684684 const xcmpQueueFailEvent = await helper.wait.eventData<XcmV2TraitsError>(685 await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Fail, event => {685 maxWaitBlocks,686 return event.messageHash() == maliciousXcmProgramSent.messageHash()686 'xcmpQueue',687 && event.outcome().isFailedToTransactAsset;687 'Fail',688 outcomeField,689 );688 });690691 expect(692 xcmpQueueFailEvent != null,693 '\'xcmpQueue.FailEvent\' event is expected',694 ).to.be.true;695696 expect(697 xcmpQueueFailEvent!.isFailedToTransactAsset,698 `The XCM error should be 'FailedToTransactAsset', got '${xcmpQueueFailEvent!.toHuman()}'`,699 ).to.be.true;700689701 targetAccountBalance = await helper.balance.getSubstrate(targetAccount.address);690 targetAccountBalance = await helper.balance.getSubstrate(targetAccount.address);702 expect(targetAccountBalance).to.be.equal(0n);691 expect(targetAccountBalance).to.be.equal(0n);765 testAmount,754 testAmount,766 );755 );756757 let maliciousXcmProgramFullIdSent: any;758 let maliciousXcmProgramHereIdSent: any;759 const maxWaitBlocks = 3;767760768 // Try to trick Quartz using full QTZ identification761 // Try to trick Quartz using full QTZ identification769 await usingKaruraPlaygrounds(karuraUrl, async (helper) => {762 await usingKaruraPlaygrounds(karuraUrl, async (helper) => {770 await helper.getSudo().xcm.send(alice, quartzMultilocation, maliciousXcmProgramFullId);763 await helper.getSudo().xcm.send(alice, quartzMultilocation, maliciousXcmProgramFullId);764765 maliciousXcmProgramFullIdSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);771 });766 });772773 const maxWaitBlocks = 3;774 const outcomeField = 1;775767776 let xcmpQueueFailEvent = await helper.wait.eventData<XcmV2TraitsError>(768 await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Fail, event => {777 maxWaitBlocks,769 return event.messageHash() == maliciousXcmProgramFullIdSent.messageHash()778 'xcmpQueue',770 && event.outcome().isUntrustedReserveLocation;779 'Fail',780 outcomeField,781 );771 });782783 expect(784 xcmpQueueFailEvent != null,785 '\'xcmpQueue.FailEvent\' event is expected',786 ).to.be.true;787788 expect(789 xcmpQueueFailEvent!.isUntrustedReserveLocation,790 `The XCM error should be 'UntrustedReserveLocation', got '${xcmpQueueFailEvent!.toHuman()}'`,791 ).to.be.true;792772793 let accountBalance = await helper.balance.getSubstrate(targetAccount.address);773 let accountBalance = await helper.balance.getSubstrate(targetAccount.address);794 expect(accountBalance).to.be.equal(0n);774 expect(accountBalance).to.be.equal(0n);797 await usingKaruraPlaygrounds(karuraUrl, async (helper) => {777 await usingKaruraPlaygrounds(karuraUrl, async (helper) => {798 await helper.getSudo().xcm.send(alice, quartzMultilocation, maliciousXcmProgramHereId);778 await helper.getSudo().xcm.send(alice, quartzMultilocation, maliciousXcmProgramHereId);779780 maliciousXcmProgramHereIdSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);799 });781 });800782801 xcmpQueueFailEvent = await helper.wait.eventData<XcmV2TraitsError>(783 await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Fail, event => {802 maxWaitBlocks,784 return event.messageHash() == maliciousXcmProgramHereIdSent.messageHash()803 'xcmpQueue',785 && event.outcome().isUntrustedReserveLocation;804 'Fail',805 outcomeField,806 );786 });807808 expect(809 xcmpQueueFailEvent != null,810 '\'xcmpQueue.FailEvent\' event is expected',811 ).to.be.true;812813 expect(814 xcmpQueueFailEvent!.isUntrustedReserveLocation,815 `The XCM error should be 'UntrustedReserveLocation', got '${xcmpQueueFailEvent!.toHuman()}'`,816 ).to.be.true;817787818 accountBalance = await helper.balance.getSubstrate(targetAccount.address);788 accountBalance = await helper.balance.getSubstrate(targetAccount.address);819 expect(accountBalance).to.be.equal(0n);789 expect(accountBalance).to.be.equal(0n);834 let quartzAccountMultilocation: any;804 let quartzAccountMultilocation: any;835 let quartzCombinedMultilocation: any;805 let quartzCombinedMultilocation: any;806807 let messageSent: any;808809 const maxWaitBlocks = 3;836810837 before(async () => {811 before(async () => {838 await usingPlaygrounds(async (helper, privateKey) => {812 await usingPlaygrounds(async (helper, privateKey) => {883 });857 });884 });858 });885859886 const expectFailedToTransact = async (network: string, helper: DevUniqueHelper) => {860 const expectFailedToTransact = async (helper: DevUniqueHelper, messageSent: any) => {887 const maxWaitBlocks = 3;888 const outcomeField = 1;889890 const xcmpQueueFailEvent = await helper.wait.eventData<XcmV2TraitsError>(861 await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Fail, event => {891 maxWaitBlocks,862 return event.messageHash() == messageSent.messageHash()892 'xcmpQueue',863 && event.outcome().isFailedToTransactAsset;893 'Fail',894 outcomeField,895 );864 });896897 expect(898 xcmpQueueFailEvent != null,899 `[reject ${network} tokens] 'xcmpQueue.FailEvent' event is expected`,900 ).to.be.true;901902 expect(903 xcmpQueueFailEvent!.isFailedToTransactAsset,904 `[reject ${network} tokens] The XCM error should be 'FailedToTransactAsset', got '${xcmpQueueFailEvent!.toHuman()}'`,905 ).to.be.true;906 };865 };907866908 itSub('Quartz rejects KAR tokens from Karura', async ({helper}) => {867 itSub('Quartz rejects KAR tokens from Karura', async ({helper}) => {913 const destination = quartzCombinedMultilocation;872 const destination = quartzCombinedMultilocation;914 await helper.xTokens.transfer(alice, id, testAmount, destination, 'Unlimited');873 await helper.xTokens.transfer(alice, id, testAmount, destination, 'Unlimited');874875 messageSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);915 });876 });916877917 await expectFailedToTransact('KAR', helper);878 await expectFailedToTransact(helper, messageSent);918 });879 });919880920 itSub('Quartz rejects MOVR tokens from Moonriver', async ({helper}) => {881 itSub('Quartz rejects MOVR tokens from Moonriver', async ({helper}) => {923 const destination = quartzCombinedMultilocation;884 const destination = quartzCombinedMultilocation;924 await helper.xTokens.transfer(alith, id, testAmount, destination, 'Unlimited');885 await helper.xTokens.transfer(alith, id, testAmount, destination, 'Unlimited');886887 messageSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);925 });888 });926889927 await expectFailedToTransact('MOVR', helper);890 await expectFailedToTransact(helper, messageSent);928 });891 });929892930 itSub('Quartz rejects SDN tokens from Shiden', async ({helper}) => {893 itSub('Quartz rejects SDN tokens from Shiden', async ({helper}) => {953 feeAssetItem,916 feeAssetItem,954 ]);917 ]);918919 messageSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);955 });920 });956921957 await expectFailedToTransact('SDN', helper);922 await expectFailedToTransact(helper, messageSent);958 });923 });959});924});9609251193 moreThanMoonriverHas,1158 moreThanMoonriverHas,1194 );1159 );11601161 let maliciousXcmProgramSent: any;1162 const maxWaitBlocks = 3;119511631196 // Try to trick Quartz1164 // Try to trick Quartz1197 await usingMoonriverPlaygrounds(moonriverUrl, async (helper) => {1165 await usingMoonriverPlaygrounds(moonriverUrl, async (helper) => {1201 const batchCall = helper.encodeApiCall('api.tx.utility.batch', [[xcmSend]]);1169 const batchCall = helper.encodeApiCall('api.tx.utility.batch', [[xcmSend]]);1202 await helper.fastDemocracy.executeProposal('try to spend more QTZ than Moonriver has', batchCall);1170 await helper.fastDemocracy.executeProposal('try to spend more QTZ than Moonriver has', batchCall);11711172 maliciousXcmProgramSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);1203 });1173 });12041205 const maxWaitBlocks = 3;1206 const outcomeField = 1;120711741208 const xcmpQueueFailEvent = await helper.wait.eventData<XcmV2TraitsError>(1175 await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Fail, event => {1209 maxWaitBlocks,1176 return event.messageHash() == maliciousXcmProgramSent.messageHash()1210 'xcmpQueue',1177 && event.outcome().isFailedToTransactAsset;1211 'Fail',1212 outcomeField,1213 );1178 });12141215 expect(1216 xcmpQueueFailEvent != null,1217 '\'xcmpQueue.FailEvent\' event is expected',1218 ).to.be.true;12191220 expect(1221 xcmpQueueFailEvent!.isFailedToTransactAsset,1222 `The XCM error should be 'FailedToTransactAsset', got '${xcmpQueueFailEvent!.toHuman()}'`,1223 ).to.be.true;122411791225 targetAccountBalance = await helper.balance.getSubstrate(targetAccount.address);1180 targetAccountBalance = await helper.balance.getSubstrate(targetAccount.address);1226 expect(targetAccountBalance).to.be.equal(0n);1181 expect(targetAccountBalance).to.be.equal(0n);1293 testAmount,1248 testAmount,1294 );1249 );12501251 let maliciousXcmProgramFullIdSent: any;1252 let maliciousXcmProgramHereIdSent: any;1253 const maxWaitBlocks = 3;129512541296 // Try to trick Quartz using full QTZ identification1255 // Try to trick Quartz using full QTZ identification1297 await usingMoonriverPlaygrounds(moonriverUrl, async (helper) => {1256 await usingMoonriverPlaygrounds(moonriverUrl, async (helper) => {1301 const batchCall = helper.encodeApiCall('api.tx.utility.batch', [[xcmSend]]);1260 const batchCall = helper.encodeApiCall('api.tx.utility.batch', [[xcmSend]]);1302 await helper.fastDemocracy.executeProposal('try to act like a reserve location for QTZ using path asset identification', batchCall);1261 await helper.fastDemocracy.executeProposal('try to act like a reserve location for QTZ using path asset identification', batchCall);12621263 maliciousXcmProgramFullIdSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);1303 });1264 });13041305 const maxWaitBlocks = 3;1306 const outcomeField = 1;130712651308 let xcmpQueueFailEvent = await helper.wait.eventData<XcmV2TraitsError>(1266 await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Fail, event => {1309 maxWaitBlocks,1267 return event.messageHash() == maliciousXcmProgramFullIdSent.messageHash()1310 'xcmpQueue',1268 && event.outcome().isUntrustedReserveLocation;1311 'Fail',1312 outcomeField,1313 );1269 });13141315 expect(1316 xcmpQueueFailEvent != null,1317 '\'xcmpQueue.FailEvent\' event is expected',1318 ).to.be.true;13191320 expect(1321 xcmpQueueFailEvent!.isUntrustedReserveLocation,1322 `The XCM error should be 'isUntrustedReserveLocation', got '${xcmpQueueFailEvent!.toHuman()}'`,1323 ).to.be.true;132412701325 let accountBalance = await helper.balance.getSubstrate(targetAccount.address);1271 let accountBalance = await helper.balance.getSubstrate(targetAccount.address);1326 expect(accountBalance).to.be.equal(0n);1272 expect(accountBalance).to.be.equal(0n);1333 const batchCall = helper.encodeApiCall('api.tx.utility.batch', [[xcmSend]]);1279 const batchCall = helper.encodeApiCall('api.tx.utility.batch', [[xcmSend]]);1334 await helper.fastDemocracy.executeProposal('try to act like a reserve location for QTZ using "here" asset identification', batchCall);1280 await helper.fastDemocracy.executeProposal('try to act like a reserve location for QTZ using "here" asset identification', batchCall);12811282 maliciousXcmProgramHereIdSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);1335 });1283 });133612841337 xcmpQueueFailEvent = await helper.wait.eventData<XcmV2TraitsError>(1285 await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Fail, event => {1338 maxWaitBlocks,1286 return event.messageHash() == maliciousXcmProgramHereIdSent.messageHash()1339 'xcmpQueue',1287 && event.outcome().isUntrustedReserveLocation;1340 'Fail',1341 outcomeField,1342 );1288 });13431344 expect(1345 xcmpQueueFailEvent != null,1346 '\'xcmpQueue.FailEvent\' event is expected',1347 ).to.be.true;13481349 expect(1350 xcmpQueueFailEvent!.isUntrustedReserveLocation,1351 `The XCM error should be 'isUntrustedReserveLocation', got '${xcmpQueueFailEvent!.toHuman()}'`,1352 ).to.be.true;135312891354 accountBalance = await helper.balance.getSubstrate(targetAccount.address);1290 accountBalance = await helper.balance.getSubstrate(targetAccount.address);1355 expect(accountBalance).to.be.equal(0n);1291 expect(accountBalance).to.be.equal(0n);1598 moreThanShidenHas,1534 moreThanShidenHas,1599 );1535 );15361537 let maliciousXcmProgramSent: any;1538 const maxWaitBlocks = 3;160015391601 // Try to trick Quartz1540 // Try to trick Quartz1602 await usingShidenPlaygrounds(shidenUrl, async (helper) => {1541 await usingShidenPlaygrounds(shidenUrl, async (helper) => {1603 await helper.getSudo().xcm.send(alice, quartzMultilocation, maliciousXcmProgram);1542 await helper.getSudo().xcm.send(alice, quartzMultilocation, maliciousXcmProgram);15431544 maliciousXcmProgramSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);1604 });1545 });16051606 const maxWaitBlocks = 3;1607 const outcomeField = 1;160815461609 const xcmpQueueFailEvent = await helper.wait.eventData<XcmV2TraitsError>(1547 await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Fail, event => {1610 maxWaitBlocks,1548 return event.messageHash() == maliciousXcmProgramSent.messageHash()1611 'xcmpQueue',1549 && event.outcome().isFailedToTransactAsset;1612 'Fail',1613 outcomeField,1614 );1550 });16151616 expect(1617 xcmpQueueFailEvent != null,1618 '\'xcmpQueue.FailEvent\' event is expected',1619 ).to.be.true;16201621 expect(1622 xcmpQueueFailEvent!.isFailedToTransactAsset,1623 `The XCM error should be 'FailedToTransactAsset', got '${xcmpQueueFailEvent!.toHuman()}'`,1624 ).to.be.true;162515511626 targetAccountBalance = await helper.balance.getSubstrate(targetAccount.address);1552 targetAccountBalance = await helper.balance.getSubstrate(targetAccount.address);1627 expect(targetAccountBalance).to.be.equal(0n);1553 expect(targetAccountBalance).to.be.equal(0n);1690 testAmount,1616 testAmount,1691 );1617 );16181619 let maliciousXcmProgramFullIdSent: any;1620 let maliciousXcmProgramHereIdSent: any;1621 const maxWaitBlocks = 3;169216221693 // Try to trick Quartz using full QTZ identification1623 // Try to trick Quartz using full QTZ identification1694 await usingShidenPlaygrounds(shidenUrl, async (helper) => {1624 await usingShidenPlaygrounds(shidenUrl, async (helper) => {1695 await helper.getSudo().xcm.send(alice, quartzMultilocation, maliciousXcmProgramFullId);1625 await helper.getSudo().xcm.send(alice, quartzMultilocation, maliciousXcmProgramFullId);16261627 maliciousXcmProgramFullIdSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);1696 });1628 });16971698 const maxWaitBlocks = 3;1699 const outcomeField = 1;170016291701 let xcmpQueueFailEvent = await helper.wait.eventData<XcmV2TraitsError>(1630 await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Fail, event => {1702 maxWaitBlocks,1631 return event.messageHash() == maliciousXcmProgramFullIdSent.messageHash()1703 'xcmpQueue',1632 && event.outcome().isUntrustedReserveLocation;1704 'Fail',1705 outcomeField,1706 );1633 });17071708 expect(1709 xcmpQueueFailEvent != null,1710 '\'xcmpQueue.FailEvent\' event is expected',1711 ).to.be.true;17121713 expect(1714 xcmpQueueFailEvent!.isUntrustedReserveLocation,1715 `The XCM error should be 'isUntrustedReserveLocation', got '${xcmpQueueFailEvent!.toHuman()}'`,1716 ).to.be.true;171716341718 let accountBalance = await helper.balance.getSubstrate(targetAccount.address);1635 let accountBalance = await helper.balance.getSubstrate(targetAccount.address);1719 expect(accountBalance).to.be.equal(0n);1636 expect(accountBalance).to.be.equal(0n);1722 await usingShidenPlaygrounds(shidenUrl, async (helper) => {1639 await usingShidenPlaygrounds(shidenUrl, async (helper) => {1723 await helper.getSudo().xcm.send(alice, quartzMultilocation, maliciousXcmProgramHereId);1640 await helper.getSudo().xcm.send(alice, quartzMultilocation, maliciousXcmProgramHereId);16411642 maliciousXcmProgramHereIdSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);1724 });1643 });172516441726 xcmpQueueFailEvent = await helper.wait.eventData<XcmV2TraitsError>(1645 await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Fail, event => {1727 maxWaitBlocks,1646 return event.messageHash() == maliciousXcmProgramHereIdSent.messageHash()1728 'xcmpQueue',1647 && event.outcome().isUntrustedReserveLocation;1729 'Fail',1730 outcomeField,1731 );1648 });17321733 expect(1734 xcmpQueueFailEvent != null,1735 '\'xcmpQueue.FailEvent\' event is expected',1736 ).to.be.true;17371738 expect(1739 xcmpQueueFailEvent!.isUntrustedReserveLocation,1740 `The XCM error should be 'isUntrustedReserveLocation', got '${xcmpQueueFailEvent!.toHuman()}'`,1741 ).to.be.true;174216491743 accountBalance = await helper.balance.getSubstrate(targetAccount.address);1650 accountBalance = await helper.balance.getSubstrate(targetAccount.address);1744 expect(accountBalance).to.be.equal(0n);1651 expect(accountBalance).to.be.equal(0n);tests/src/xcm/xcmUnique.test.tsdiffbeforeafterboth--- a/tests/src/xcm/xcmUnique.test.ts
+++ b/tests/src/xcm/xcmUnique.test.ts
@@ -16,9 +16,8 @@
import {IKeyringPair} from '@polkadot/types/types';
import config from '../config';
-import {XcmV2TraitsError} from '../interfaces';
import {itSub, expect, describeXCM, usingPlaygrounds, usingAcalaPlaygrounds, usingRelayPlaygrounds, usingMoonbeamPlaygrounds, usingStatemintPlaygrounds, usingAstarPlaygrounds} from '../util';
-import {DevUniqueHelper} from '../util/playgrounds/unique.dev';
+import {DevUniqueHelper, Event} from '../util/playgrounds/unique.dev';
const UNIQUE_CHAIN = 2037;
const STATEMINT_CHAIN = 1000;
@@ -675,30 +674,20 @@
moreThanAcalaHas,
);
+ let maliciousXcmProgramSent: any;
+ const maxWaitBlocks = 3;
+
// Try to trick Unique
await usingAcalaPlaygrounds(acalaUrl, async (helper) => {
await helper.getSudo().xcm.send(alice, uniqueMultilocation, maliciousXcmProgram);
+
+ maliciousXcmProgramSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);
});
- const maxWaitBlocks = 3;
- const outcomeField = 1;
-
- const xcmpQueueFailEvent = await helper.wait.eventData<XcmV2TraitsError>(
- maxWaitBlocks,
- 'xcmpQueue',
- 'Fail',
- outcomeField,
- );
-
- expect(
- xcmpQueueFailEvent != null,
- '\'xcmpQueue.FailEvent\' event is expected',
- ).to.be.true;
-
- expect(
- xcmpQueueFailEvent!.isFailedToTransactAsset,
- `The XCM error should be 'FailedToTransactAsset', got '${xcmpQueueFailEvent!.toHuman()}'`,
- ).to.be.true;
+ await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Fail, event => {
+ return event.messageHash() == maliciousXcmProgramSent.messageHash()
+ && event.outcome().isFailedToTransactAsset;
+ });
targetAccountBalance = await helper.balance.getSubstrate(targetAccount.address);
expect(targetAccountBalance).to.be.equal(0n);
@@ -767,30 +756,21 @@
testAmount,
);
+ let maliciousXcmProgramFullIdSent: any;
+ let maliciousXcmProgramHereIdSent: any;
+ const maxWaitBlocks = 3;
+
// Try to trick Unique using full UNQ identification
await usingAcalaPlaygrounds(acalaUrl, async (helper) => {
await helper.getSudo().xcm.send(alice, uniqueMultilocation, maliciousXcmProgramFullId);
- });
- const maxWaitBlocks = 3;
- const outcomeField = 1;
-
- let xcmpQueueFailEvent = await helper.wait.eventData<XcmV2TraitsError>(
- maxWaitBlocks,
- 'xcmpQueue',
- 'Fail',
- outcomeField,
- );
+ maliciousXcmProgramFullIdSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);
+ });
- expect(
- xcmpQueueFailEvent != null,
- '\'xcmpQueue.FailEvent\' event is expected',
- ).to.be.true;
-
- expect(
- xcmpQueueFailEvent!.isUntrustedReserveLocation,
- `The XCM error should be 'UntrustedReserveLocation', got '${xcmpQueueFailEvent!.toHuman()}'`,
- ).to.be.true;
+ await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Fail, event => {
+ return event.messageHash() == maliciousXcmProgramFullIdSent.messageHash()
+ && event.outcome().isUntrustedReserveLocation;
+ });
let accountBalance = await helper.balance.getSubstrate(targetAccount.address);
expect(accountBalance).to.be.equal(0n);
@@ -798,24 +778,14 @@
// Try to trick Unique using shortened UNQ identification
await usingAcalaPlaygrounds(acalaUrl, async (helper) => {
await helper.getSudo().xcm.send(alice, uniqueMultilocation, maliciousXcmProgramHereId);
- });
- xcmpQueueFailEvent = await helper.wait.eventData<XcmV2TraitsError>(
- maxWaitBlocks,
- 'xcmpQueue',
- 'Fail',
- outcomeField,
- );
-
- expect(
- xcmpQueueFailEvent != null,
- '\'xcmpQueue.FailEvent\' event is expected',
- ).to.be.true;
+ maliciousXcmProgramHereIdSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);
+ });
- expect(
- xcmpQueueFailEvent!.isUntrustedReserveLocation,
- `The XCM error should be 'UntrustedReserveLocation', got '${xcmpQueueFailEvent!.toHuman()}'`,
- ).to.be.true;
+ await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Fail, event => {
+ return event.messageHash() == maliciousXcmProgramHereIdSent.messageHash()
+ && event.outcome().isUntrustedReserveLocation;
+ });
accountBalance = await helper.balance.getSubstrate(targetAccount.address);
expect(accountBalance).to.be.equal(0n);
@@ -836,6 +806,10 @@
let uniqueAccountMultilocation: any;
let uniqueCombinedMultilocation: any;
+ let messageSent: any;
+
+ const maxWaitBlocks = 3;
+
before(async () => {
await usingPlaygrounds(async (helper, privateKey) => {
alice = await privateKey('//Alice');
@@ -885,26 +859,11 @@
});
});
- const expectFailedToTransact = async (network: string, helper: DevUniqueHelper) => {
- const maxWaitBlocks = 3;
- const outcomeField = 1;
-
- const xcmpQueueFailEvent = await helper.wait.eventData<XcmV2TraitsError>(
- maxWaitBlocks,
- 'xcmpQueue',
- 'Fail',
- outcomeField,
- );
-
- expect(
- xcmpQueueFailEvent != null,
- `[reject ${network} tokens] 'xcmpQueue.FailEvent' event is expected`,
- ).to.be.true;
-
- expect(
- xcmpQueueFailEvent!.isFailedToTransactAsset,
- `[reject ${network} tokens] The XCM error should be 'FailedToTransactAsset', got '${xcmpQueueFailEvent!.toHuman()}'`,
- ).to.be.true;
+ const expectFailedToTransact = async (helper: DevUniqueHelper, messageSent: any) => {
+ await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Fail, event => {
+ return event.messageHash() == messageSent.messageHash()
+ && event.outcome().isFailedToTransactAsset;
+ });
};
itSub('Unique rejects ACA tokens from Acala', async ({helper}) => {
@@ -914,9 +873,11 @@
};
const destination = uniqueCombinedMultilocation;
await helper.xTokens.transfer(alice, id, testAmount, destination, 'Unlimited');
+
+ messageSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);
});
- await expectFailedToTransact('ACA', helper);
+ await expectFailedToTransact(helper, messageSent);
});
itSub('Unique rejects GLMR tokens from Moonbeam', async ({helper}) => {
@@ -924,9 +885,11 @@
const id = 'SelfReserve';
const destination = uniqueCombinedMultilocation;
await helper.xTokens.transfer(alith, id, testAmount, destination, 'Unlimited');
+
+ messageSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);
});
- await expectFailedToTransact('GLMR', helper);
+ await expectFailedToTransact(helper, messageSent);
});
itSub('Unique rejects ASTR tokens from Astar', async ({helper}) => {
@@ -954,9 +917,11 @@
assets,
feeAssetItem,
]);
+
+ messageSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);
});
- await expectFailedToTransact('ASTR', helper);
+ await expectFailedToTransact(helper, messageSent);
});
});
@@ -1196,6 +1161,9 @@
moreThanMoonbeamHas,
);
+ let maliciousXcmProgramSent: any;
+ const maxWaitBlocks = 3;
+
// Try to trick Unique
await usingMoonbeamPlaygrounds(moonbeamUrl, async (helper) => {
const xcmSend = helper.constructApiCall('api.tx.polkadotXcm.send', [uniqueMultilocation, maliciousXcmProgram]);
@@ -1203,27 +1171,14 @@
// Needed to bypass the call filter.
const batchCall = helper.encodeApiCall('api.tx.utility.batch', [[xcmSend]]);
await helper.fastDemocracy.executeProposal('try to spend more UNQ than Moonbeam has', batchCall);
- });
- const maxWaitBlocks = 3;
- const outcomeField = 1;
-
- const xcmpQueueFailEvent = await helper.wait.eventData<XcmV2TraitsError>(
- maxWaitBlocks,
- 'xcmpQueue',
- 'Fail',
- outcomeField,
- );
-
- expect(
- xcmpQueueFailEvent != null,
- '\'xcmpQueue.FailEvent\' event is expected',
- ).to.be.true;
+ maliciousXcmProgramSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);
+ });
- expect(
- xcmpQueueFailEvent!.isFailedToTransactAsset,
- `The XCM error should be 'FailedToTransactAsset', got '${xcmpQueueFailEvent!.toHuman()}'`,
- ).to.be.true;
+ await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Fail, event => {
+ return event.messageHash() == maliciousXcmProgramSent.messageHash()
+ && event.outcome().isFailedToTransactAsset;
+ });
targetAccountBalance = await helper.balance.getSubstrate(targetAccount.address);
expect(targetAccountBalance).to.be.equal(0n);
@@ -1296,6 +1251,10 @@
testAmount,
);
+ let maliciousXcmProgramFullIdSent: any;
+ let maliciousXcmProgramHereIdSent: any;
+ const maxWaitBlocks = 3;
+
// Try to trick Unique using full UNQ identification
await usingMoonbeamPlaygrounds(moonbeamUrl, async (helper) => {
const xcmSend = helper.constructApiCall('api.tx.polkadotXcm.send', [uniqueMultilocation, maliciousXcmProgramFullId]);
@@ -1303,27 +1262,14 @@
// Needed to bypass the call filter.
const batchCall = helper.encodeApiCall('api.tx.utility.batch', [[xcmSend]]);
await helper.fastDemocracy.executeProposal('try to act like a reserve location for UNQ using path asset identification', batchCall);
- });
-
- const maxWaitBlocks = 3;
- const outcomeField = 1;
- let xcmpQueueFailEvent = await helper.wait.eventData<XcmV2TraitsError>(
- maxWaitBlocks,
- 'xcmpQueue',
- 'Fail',
- outcomeField,
- );
-
- expect(
- xcmpQueueFailEvent != null,
- '\'xcmpQueue.FailEvent\' event is expected',
- ).to.be.true;
+ maliciousXcmProgramFullIdSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);
+ });
- expect(
- xcmpQueueFailEvent!.isUntrustedReserveLocation,
- `The XCM error should be 'UntrustedReserveLocation', got '${xcmpQueueFailEvent!.toHuman()}'`,
- ).to.be.true;
+ await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Fail, event => {
+ return event.messageHash() == maliciousXcmProgramFullIdSent.messageHash()
+ && event.outcome().isUntrustedReserveLocation;
+ });
let accountBalance = await helper.balance.getSubstrate(targetAccount.address);
expect(accountBalance).to.be.equal(0n);
@@ -1335,24 +1281,14 @@
// Needed to bypass the call filter.
const batchCall = helper.encodeApiCall('api.tx.utility.batch', [[xcmSend]]);
await helper.fastDemocracy.executeProposal('try to act like a reserve location for UNQ using "here" asset identification', batchCall);
- });
- xcmpQueueFailEvent = await helper.wait.eventData<XcmV2TraitsError>(
- maxWaitBlocks,
- 'xcmpQueue',
- 'Fail',
- outcomeField,
- );
-
- expect(
- xcmpQueueFailEvent != null,
- '\'xcmpQueue.FailEvent\' event is expected',
- ).to.be.true;
+ maliciousXcmProgramHereIdSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);
+ });
- expect(
- xcmpQueueFailEvent!.isUntrustedReserveLocation,
- `The XCM error should be 'UntrustedReserveLocation', got '${xcmpQueueFailEvent!.toHuman()}'`,
- ).to.be.true;
+ await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Fail, event => {
+ return event.messageHash() == maliciousXcmProgramHereIdSent.messageHash()
+ && event.outcome().isUntrustedReserveLocation;
+ });
accountBalance = await helper.balance.getSubstrate(targetAccount.address);
expect(accountBalance).to.be.equal(0n);
@@ -1600,31 +1536,21 @@
moreThanAstarHas,
);
+ let maliciousXcmProgramSent: any;
+ const maxWaitBlocks = 3;
+
// Try to trick Unique
await usingAstarPlaygrounds(astarUrl, async (helper) => {
await helper.getSudo().xcm.send(alice, uniqueMultilocation, maliciousXcmProgram);
+
+ maliciousXcmProgramSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);
});
- const maxWaitBlocks = 3;
- const outcomeField = 1;
-
- const xcmpQueueFailEvent = await helper.wait.eventData<XcmV2TraitsError>(
- maxWaitBlocks,
- 'xcmpQueue',
- 'Fail',
- outcomeField,
- );
+ await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Fail, event => {
+ return event.messageHash() == maliciousXcmProgramSent.messageHash()
+ && event.outcome().isFailedToTransactAsset;
+ });
- expect(
- xcmpQueueFailEvent != null,
- '\'xcmpQueue.FailEvent\' event is expected',
- ).to.be.true;
-
- expect(
- xcmpQueueFailEvent!.isFailedToTransactAsset,
- `The XCM error should be 'FailedToTransactAsset', got '${xcmpQueueFailEvent!.toHuman()}'`,
- ).to.be.true;
-
targetAccountBalance = await helper.balance.getSubstrate(targetAccount.address);
expect(targetAccountBalance).to.be.equal(0n);
@@ -1692,30 +1618,21 @@
testAmount,
);
+ let maliciousXcmProgramFullIdSent: any;
+ let maliciousXcmProgramHereIdSent: any;
+ const maxWaitBlocks = 3;
+
// Try to trick Unique using full UNQ identification
await usingAstarPlaygrounds(astarUrl, async (helper) => {
await helper.getSudo().xcm.send(alice, uniqueMultilocation, maliciousXcmProgramFullId);
- });
- const maxWaitBlocks = 3;
- const outcomeField = 1;
+ maliciousXcmProgramFullIdSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);
+ });
- let xcmpQueueFailEvent = await helper.wait.eventData<XcmV2TraitsError>(
- maxWaitBlocks,
- 'xcmpQueue',
- 'Fail',
- outcomeField,
- );
-
- expect(
- xcmpQueueFailEvent != null,
- '\'xcmpQueue.FailEvent\' event is expected',
- ).to.be.true;
-
- expect(
- xcmpQueueFailEvent!.isUntrustedReserveLocation,
- `The XCM error should be 'UntrustedReserveLocation', got '${xcmpQueueFailEvent!.toHuman()}'`,
- ).to.be.true;
+ await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Fail, event => {
+ return event.messageHash() == maliciousXcmProgramFullIdSent.messageHash()
+ && event.outcome().isUntrustedReserveLocation;
+ });
let accountBalance = await helper.balance.getSubstrate(targetAccount.address);
expect(accountBalance).to.be.equal(0n);
@@ -1723,24 +1640,14 @@
// Try to trick Unique using shortened UNQ identification
await usingAstarPlaygrounds(astarUrl, async (helper) => {
await helper.getSudo().xcm.send(alice, uniqueMultilocation, maliciousXcmProgramHereId);
- });
- xcmpQueueFailEvent = await helper.wait.eventData<XcmV2TraitsError>(
- maxWaitBlocks,
- 'xcmpQueue',
- 'Fail',
- outcomeField,
- );
-
- expect(
- xcmpQueueFailEvent != null,
- '\'xcmpQueue.FailEvent\' event is expected',
- ).to.be.true;
+ maliciousXcmProgramHereIdSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);
+ });
- expect(
- xcmpQueueFailEvent!.isUntrustedReserveLocation,
- `The XCM error should be 'UntrustedReserveLocation', got '${xcmpQueueFailEvent!.toHuman()}'`,
- ).to.be.true;
+ await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Fail, event => {
+ return event.messageHash() == maliciousXcmProgramHereIdSent.messageHash()
+ && event.outcome().isUntrustedReserveLocation;
+ });
accountBalance = await helper.balance.getSubstrate(targetAccount.address);
expect(accountBalance).to.be.equal(0n);