difftreelog
refactor event helpers
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.tsdiffbeforeafterboth--- a/tests/src/xcm/xcmQuartz.test.ts
+++ b/tests/src/xcm/xcmQuartz.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, usingKaruraPlaygrounds, usingRelayPlaygrounds, usingMoonriverPlaygrounds, usingStateminePlaygrounds, usingShidenPlaygrounds} from '../util';
-import {DevUniqueHelper} from '../util/playgrounds/unique.dev';
+import {DevUniqueHelper, Event} from '../util/playgrounds/unique.dev';
const QUARTZ_CHAIN = 2095;
const STATEMINE_CHAIN = 1000;
@@ -673,30 +672,20 @@
moreThanKaruraHas,
);
+ let maliciousXcmProgramSent: any;
+ const maxWaitBlocks = 3;
+
// Try to trick Quartz
await usingKaruraPlaygrounds(karuraUrl, async (helper) => {
await helper.getSudo().xcm.send(alice, quartzMultilocation, 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);
@@ -765,30 +754,21 @@
testAmount,
);
+ let maliciousXcmProgramFullIdSent: any;
+ let maliciousXcmProgramHereIdSent: any;
+ const maxWaitBlocks = 3;
+
// Try to trick Quartz using full QTZ identification
await usingKaruraPlaygrounds(karuraUrl, async (helper) => {
await helper.getSudo().xcm.send(alice, quartzMultilocation, 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);
@@ -796,24 +776,14 @@
// Try to trick Quartz using shortened QTZ identification
await usingKaruraPlaygrounds(karuraUrl, async (helper) => {
await helper.getSudo().xcm.send(alice, quartzMultilocation, 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);
@@ -834,6 +804,10 @@
let quartzAccountMultilocation: any;
let quartzCombinedMultilocation: any;
+ let messageSent: any;
+
+ const maxWaitBlocks = 3;
+
before(async () => {
await usingPlaygrounds(async (helper, privateKey) => {
alice = await privateKey('//Alice');
@@ -883,26 +857,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('Quartz rejects KAR tokens from Karura', async ({helper}) => {
@@ -912,9 +871,11 @@
};
const destination = quartzCombinedMultilocation;
await helper.xTokens.transfer(alice, id, testAmount, destination, 'Unlimited');
+
+ messageSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);
});
- await expectFailedToTransact('KAR', helper);
+ await expectFailedToTransact(helper, messageSent);
});
itSub('Quartz rejects MOVR tokens from Moonriver', async ({helper}) => {
@@ -922,9 +883,11 @@
const id = 'SelfReserve';
const destination = quartzCombinedMultilocation;
await helper.xTokens.transfer(alith, id, testAmount, destination, 'Unlimited');
+
+ messageSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);
});
- await expectFailedToTransact('MOVR', helper);
+ await expectFailedToTransact(helper, messageSent);
});
itSub('Quartz rejects SDN tokens from Shiden', async ({helper}) => {
@@ -952,9 +915,11 @@
assets,
feeAssetItem,
]);
+
+ messageSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);
});
- await expectFailedToTransact('SDN', helper);
+ await expectFailedToTransact(helper, messageSent);
});
});
@@ -1193,6 +1158,9 @@
moreThanMoonriverHas,
);
+ let maliciousXcmProgramSent: any;
+ const maxWaitBlocks = 3;
+
// Try to trick Quartz
await usingMoonriverPlaygrounds(moonriverUrl, async (helper) => {
const xcmSend = helper.constructApiCall('api.tx.polkadotXcm.send', [quartzMultilocation, maliciousXcmProgram]);
@@ -1200,27 +1168,14 @@
// Needed to bypass the call filter.
const batchCall = helper.encodeApiCall('api.tx.utility.batch', [[xcmSend]]);
await helper.fastDemocracy.executeProposal('try to spend more QTZ than Moonriver 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);
@@ -1293,6 +1248,10 @@
testAmount,
);
+ let maliciousXcmProgramFullIdSent: any;
+ let maliciousXcmProgramHereIdSent: any;
+ const maxWaitBlocks = 3;
+
// Try to trick Quartz using full QTZ identification
await usingMoonriverPlaygrounds(moonriverUrl, async (helper) => {
const xcmSend = helper.constructApiCall('api.tx.polkadotXcm.send', [quartzMultilocation, maliciousXcmProgramFullId]);
@@ -1300,27 +1259,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 QTZ 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 'isUntrustedReserveLocation', 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);
@@ -1332,24 +1278,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 QTZ 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 'isUntrustedReserveLocation', 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);
@@ -1598,31 +1534,21 @@
moreThanShidenHas,
);
+ let maliciousXcmProgramSent: any;
+ const maxWaitBlocks = 3;
+
// Try to trick Quartz
await usingShidenPlaygrounds(shidenUrl, async (helper) => {
await helper.getSudo().xcm.send(alice, quartzMultilocation, 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);
@@ -1690,30 +1616,21 @@
testAmount,
);
+ let maliciousXcmProgramFullIdSent: any;
+ let maliciousXcmProgramHereIdSent: any;
+ const maxWaitBlocks = 3;
+
// Try to trick Quartz using full QTZ identification
await usingShidenPlaygrounds(shidenUrl, async (helper) => {
await helper.getSudo().xcm.send(alice, quartzMultilocation, 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 'isUntrustedReserveLocation', 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);
@@ -1721,24 +1638,14 @@
// Try to trick Quartz using shortened QTZ identification
await usingShidenPlaygrounds(shidenUrl, async (helper) => {
await helper.getSudo().xcm.send(alice, quartzMultilocation, 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 'isUntrustedReserveLocation', 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);
tests/src/xcm/xcmUnique.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, usingAcalaPlaygrounds, usingRelayPlaygrounds, usingMoonbeamPlaygrounds, usingStatemintPlaygrounds, usingAstarPlaygrounds} from '../util';19import {itSub, expect, describeXCM, usingPlaygrounds, usingAcalaPlaygrounds, usingRelayPlaygrounds, usingMoonbeamPlaygrounds, usingStatemintPlaygrounds, usingAstarPlaygrounds} from '../util';21import {DevUniqueHelper} from '../util/playgrounds/unique.dev';20import {DevUniqueHelper, Event} from '../util/playgrounds/unique.dev';222123const UNIQUE_CHAIN = 2037;22const UNIQUE_CHAIN = 2037;24const STATEMINT_CHAIN = 1000;23const STATEMINT_CHAIN = 1000;675 moreThanAcalaHas,674 moreThanAcalaHas,676 );675 );676677 let maliciousXcmProgramSent: any;678 const maxWaitBlocks = 3;677679678 // Try to trick Unique680 // Try to trick Unique679 await usingAcalaPlaygrounds(acalaUrl, async (helper) => {681 await usingAcalaPlaygrounds(acalaUrl, async (helper) => {680 await helper.getSudo().xcm.send(alice, uniqueMultilocation, maliciousXcmProgram);682 await helper.getSudo().xcm.send(alice, uniqueMultilocation, maliciousXcmProgram);683684 maliciousXcmProgramSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);681 });685 });682683 const maxWaitBlocks = 3;684 const outcomeField = 1;685686686 const xcmpQueueFailEvent = await helper.wait.eventData<XcmV2TraitsError>(687 await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Fail, event => {687 maxWaitBlocks,688 return event.messageHash() == maliciousXcmProgramSent.messageHash()688 'xcmpQueue',689 && event.outcome().isFailedToTransactAsset;689 'Fail',690 outcomeField,691 );690 });692693 expect(694 xcmpQueueFailEvent != null,695 '\'xcmpQueue.FailEvent\' event is expected',696 ).to.be.true;697698 expect(699 xcmpQueueFailEvent!.isFailedToTransactAsset,700 `The XCM error should be 'FailedToTransactAsset', got '${xcmpQueueFailEvent!.toHuman()}'`,701 ).to.be.true;702691703 targetAccountBalance = await helper.balance.getSubstrate(targetAccount.address);692 targetAccountBalance = await helper.balance.getSubstrate(targetAccount.address);704 expect(targetAccountBalance).to.be.equal(0n);693 expect(targetAccountBalance).to.be.equal(0n);767 testAmount,756 testAmount,768 );757 );758759 let maliciousXcmProgramFullIdSent: any;760 let maliciousXcmProgramHereIdSent: any;761 const maxWaitBlocks = 3;769762770 // Try to trick Unique using full UNQ identification763 // Try to trick Unique using full UNQ identification771 await usingAcalaPlaygrounds(acalaUrl, async (helper) => {764 await usingAcalaPlaygrounds(acalaUrl, async (helper) => {772 await helper.getSudo().xcm.send(alice, uniqueMultilocation, maliciousXcmProgramFullId);765 await helper.getSudo().xcm.send(alice, uniqueMultilocation, maliciousXcmProgramFullId);766767 maliciousXcmProgramFullIdSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);773 });768 });774775 const maxWaitBlocks = 3;776 const outcomeField = 1;777769778 let xcmpQueueFailEvent = await helper.wait.eventData<XcmV2TraitsError>(770 await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Fail, event => {779 maxWaitBlocks,771 return event.messageHash() == maliciousXcmProgramFullIdSent.messageHash()780 'xcmpQueue',772 && event.outcome().isUntrustedReserveLocation;781 'Fail',782 outcomeField,783 );773 });784785 expect(786 xcmpQueueFailEvent != null,787 '\'xcmpQueue.FailEvent\' event is expected',788 ).to.be.true;789790 expect(791 xcmpQueueFailEvent!.isUntrustedReserveLocation,792 `The XCM error should be 'UntrustedReserveLocation', got '${xcmpQueueFailEvent!.toHuman()}'`,793 ).to.be.true;794774795 let accountBalance = await helper.balance.getSubstrate(targetAccount.address);775 let accountBalance = await helper.balance.getSubstrate(targetAccount.address);796 expect(accountBalance).to.be.equal(0n);776 expect(accountBalance).to.be.equal(0n);799 await usingAcalaPlaygrounds(acalaUrl, async (helper) => {779 await usingAcalaPlaygrounds(acalaUrl, async (helper) => {800 await helper.getSudo().xcm.send(alice, uniqueMultilocation, maliciousXcmProgramHereId);780 await helper.getSudo().xcm.send(alice, uniqueMultilocation, maliciousXcmProgramHereId);781782 maliciousXcmProgramHereIdSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);801 });783 });802784803 xcmpQueueFailEvent = await helper.wait.eventData<XcmV2TraitsError>(785 await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Fail, event => {804 maxWaitBlocks,786 return event.messageHash() == maliciousXcmProgramHereIdSent.messageHash()805 'xcmpQueue',787 && event.outcome().isUntrustedReserveLocation;806 'Fail',807 outcomeField,808 );788 });809810 expect(811 xcmpQueueFailEvent != null,812 '\'xcmpQueue.FailEvent\' event is expected',813 ).to.be.true;814815 expect(816 xcmpQueueFailEvent!.isUntrustedReserveLocation,817 `The XCM error should be 'UntrustedReserveLocation', got '${xcmpQueueFailEvent!.toHuman()}'`,818 ).to.be.true;819789820 accountBalance = await helper.balance.getSubstrate(targetAccount.address);790 accountBalance = await helper.balance.getSubstrate(targetAccount.address);821 expect(accountBalance).to.be.equal(0n);791 expect(accountBalance).to.be.equal(0n);836 let uniqueAccountMultilocation: any;806 let uniqueAccountMultilocation: any;837 let uniqueCombinedMultilocation: any;807 let uniqueCombinedMultilocation: any;808809 let messageSent: any;810811 const maxWaitBlocks = 3;838812839 before(async () => {813 before(async () => {840 await usingPlaygrounds(async (helper, privateKey) => {814 await usingPlaygrounds(async (helper, privateKey) => {885 });859 });886 });860 });887861888 const expectFailedToTransact = async (network: string, helper: DevUniqueHelper) => {862 const expectFailedToTransact = async (helper: DevUniqueHelper, messageSent: any) => {889 const maxWaitBlocks = 3;890 const outcomeField = 1;891892 const xcmpQueueFailEvent = await helper.wait.eventData<XcmV2TraitsError>(863 await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Fail, event => {893 maxWaitBlocks,864 return event.messageHash() == messageSent.messageHash()894 'xcmpQueue',865 && event.outcome().isFailedToTransactAsset;895 'Fail',896 outcomeField,897 );866 });898899 expect(900 xcmpQueueFailEvent != null,901 `[reject ${network} tokens] 'xcmpQueue.FailEvent' event is expected`,902 ).to.be.true;903904 expect(905 xcmpQueueFailEvent!.isFailedToTransactAsset,906 `[reject ${network} tokens] The XCM error should be 'FailedToTransactAsset', got '${xcmpQueueFailEvent!.toHuman()}'`,907 ).to.be.true;908 };867 };909868910 itSub('Unique rejects ACA tokens from Acala', async ({helper}) => {869 itSub('Unique rejects ACA tokens from Acala', async ({helper}) => {915 const destination = uniqueCombinedMultilocation;874 const destination = uniqueCombinedMultilocation;916 await helper.xTokens.transfer(alice, id, testAmount, destination, 'Unlimited');875 await helper.xTokens.transfer(alice, id, testAmount, destination, 'Unlimited');876877 messageSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);917 });878 });918879919 await expectFailedToTransact('ACA', helper);880 await expectFailedToTransact(helper, messageSent);920 });881 });921882922 itSub('Unique rejects GLMR tokens from Moonbeam', async ({helper}) => {883 itSub('Unique rejects GLMR tokens from Moonbeam', async ({helper}) => {925 const destination = uniqueCombinedMultilocation;886 const destination = uniqueCombinedMultilocation;926 await helper.xTokens.transfer(alith, id, testAmount, destination, 'Unlimited');887 await helper.xTokens.transfer(alith, id, testAmount, destination, 'Unlimited');888889 messageSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);927 });890 });928891929 await expectFailedToTransact('GLMR', helper);892 await expectFailedToTransact(helper, messageSent);930 });893 });931894932 itSub('Unique rejects ASTR tokens from Astar', async ({helper}) => {895 itSub('Unique rejects ASTR tokens from Astar', async ({helper}) => {955 feeAssetItem,918 feeAssetItem,956 ]);919 ]);920921 messageSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);957 });922 });958923959 await expectFailedToTransact('ASTR', helper);924 await expectFailedToTransact(helper, messageSent);960 });925 });961});926});9629271196 moreThanMoonbeamHas,1161 moreThanMoonbeamHas,1197 );1162 );11631164 let maliciousXcmProgramSent: any;1165 const maxWaitBlocks = 3;119811661199 // Try to trick Unique1167 // Try to trick Unique1200 await usingMoonbeamPlaygrounds(moonbeamUrl, async (helper) => {1168 await usingMoonbeamPlaygrounds(moonbeamUrl, async (helper) => {1204 const batchCall = helper.encodeApiCall('api.tx.utility.batch', [[xcmSend]]);1172 const batchCall = helper.encodeApiCall('api.tx.utility.batch', [[xcmSend]]);1205 await helper.fastDemocracy.executeProposal('try to spend more UNQ than Moonbeam has', batchCall);1173 await helper.fastDemocracy.executeProposal('try to spend more UNQ than Moonbeam has', batchCall);11741175 maliciousXcmProgramSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);1206 });1176 });12071208 const maxWaitBlocks = 3;1209 const outcomeField = 1;121011771211 const xcmpQueueFailEvent = await helper.wait.eventData<XcmV2TraitsError>(1178 await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Fail, event => {1212 maxWaitBlocks,1179 return event.messageHash() == maliciousXcmProgramSent.messageHash()1213 'xcmpQueue',1180 && event.outcome().isFailedToTransactAsset;1214 'Fail',1215 outcomeField,1216 );1181 });12171218 expect(1219 xcmpQueueFailEvent != null,1220 '\'xcmpQueue.FailEvent\' event is expected',1221 ).to.be.true;12221223 expect(1224 xcmpQueueFailEvent!.isFailedToTransactAsset,1225 `The XCM error should be 'FailedToTransactAsset', got '${xcmpQueueFailEvent!.toHuman()}'`,1226 ).to.be.true;122711821228 targetAccountBalance = await helper.balance.getSubstrate(targetAccount.address);1183 targetAccountBalance = await helper.balance.getSubstrate(targetAccount.address);1229 expect(targetAccountBalance).to.be.equal(0n);1184 expect(targetAccountBalance).to.be.equal(0n);1296 testAmount,1251 testAmount,1297 );1252 );12531254 let maliciousXcmProgramFullIdSent: any;1255 let maliciousXcmProgramHereIdSent: any;1256 const maxWaitBlocks = 3;129812571299 // Try to trick Unique using full UNQ identification1258 // Try to trick Unique using full UNQ identification1300 await usingMoonbeamPlaygrounds(moonbeamUrl, async (helper) => {1259 await usingMoonbeamPlaygrounds(moonbeamUrl, async (helper) => {1304 const batchCall = helper.encodeApiCall('api.tx.utility.batch', [[xcmSend]]);1263 const batchCall = helper.encodeApiCall('api.tx.utility.batch', [[xcmSend]]);1305 await helper.fastDemocracy.executeProposal('try to act like a reserve location for UNQ using path asset identification', batchCall);1264 await helper.fastDemocracy.executeProposal('try to act like a reserve location for UNQ using path asset identification', batchCall);12651266 maliciousXcmProgramFullIdSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);1306 });1267 });13071308 const maxWaitBlocks = 3;1309 const outcomeField = 1;131012681311 let xcmpQueueFailEvent = await helper.wait.eventData<XcmV2TraitsError>(1269 await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Fail, event => {1312 maxWaitBlocks,1270 return event.messageHash() == maliciousXcmProgramFullIdSent.messageHash()1313 'xcmpQueue',1271 && event.outcome().isUntrustedReserveLocation;1314 'Fail',1315 outcomeField,1316 );1272 });13171318 expect(1319 xcmpQueueFailEvent != null,1320 '\'xcmpQueue.FailEvent\' event is expected',1321 ).to.be.true;13221323 expect(1324 xcmpQueueFailEvent!.isUntrustedReserveLocation,1325 `The XCM error should be 'UntrustedReserveLocation', got '${xcmpQueueFailEvent!.toHuman()}'`,1326 ).to.be.true;132712731328 let accountBalance = await helper.balance.getSubstrate(targetAccount.address);1274 let accountBalance = await helper.balance.getSubstrate(targetAccount.address);1329 expect(accountBalance).to.be.equal(0n);1275 expect(accountBalance).to.be.equal(0n);1336 const batchCall = helper.encodeApiCall('api.tx.utility.batch', [[xcmSend]]);1282 const batchCall = helper.encodeApiCall('api.tx.utility.batch', [[xcmSend]]);1337 await helper.fastDemocracy.executeProposal('try to act like a reserve location for UNQ using "here" asset identification', batchCall);1283 await helper.fastDemocracy.executeProposal('try to act like a reserve location for UNQ using "here" asset identification', batchCall);12841285 maliciousXcmProgramHereIdSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);1338 });1286 });133912871340 xcmpQueueFailEvent = await helper.wait.eventData<XcmV2TraitsError>(1288 await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Fail, event => {1341 maxWaitBlocks,1289 return event.messageHash() == maliciousXcmProgramHereIdSent.messageHash()1342 'xcmpQueue',1290 && event.outcome().isUntrustedReserveLocation;1343 'Fail',1344 outcomeField,1345 );1291 });13461347 expect(1348 xcmpQueueFailEvent != null,1349 '\'xcmpQueue.FailEvent\' event is expected',1350 ).to.be.true;13511352 expect(1353 xcmpQueueFailEvent!.isUntrustedReserveLocation,1354 `The XCM error should be 'UntrustedReserveLocation', got '${xcmpQueueFailEvent!.toHuman()}'`,1355 ).to.be.true;135612921357 accountBalance = await helper.balance.getSubstrate(targetAccount.address);1293 accountBalance = await helper.balance.getSubstrate(targetAccount.address);1358 expect(accountBalance).to.be.equal(0n);1294 expect(accountBalance).to.be.equal(0n);1600 moreThanAstarHas,1536 moreThanAstarHas,1601 );1537 );15381539 let maliciousXcmProgramSent: any;1540 const maxWaitBlocks = 3;160215411603 // Try to trick Unique1542 // Try to trick Unique1604 await usingAstarPlaygrounds(astarUrl, async (helper) => {1543 await usingAstarPlaygrounds(astarUrl, async (helper) => {1605 await helper.getSudo().xcm.send(alice, uniqueMultilocation, maliciousXcmProgram);1544 await helper.getSudo().xcm.send(alice, uniqueMultilocation, maliciousXcmProgram);15451546 maliciousXcmProgramSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);1606 });1547 });16071608 const maxWaitBlocks = 3;1609 const outcomeField = 1;161015481611 const xcmpQueueFailEvent = await helper.wait.eventData<XcmV2TraitsError>(1549 await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Fail, event => {1612 maxWaitBlocks,1550 return event.messageHash() == maliciousXcmProgramSent.messageHash()1613 'xcmpQueue',1551 && event.outcome().isFailedToTransactAsset;1614 'Fail',1615 outcomeField,1616 );1552 });16171618 expect(1619 xcmpQueueFailEvent != null,1620 '\'xcmpQueue.FailEvent\' event is expected',1621 ).to.be.true;16221623 expect(1624 xcmpQueueFailEvent!.isFailedToTransactAsset,1625 `The XCM error should be 'FailedToTransactAsset', got '${xcmpQueueFailEvent!.toHuman()}'`,1626 ).to.be.true;162715531628 targetAccountBalance = await helper.balance.getSubstrate(targetAccount.address);1554 targetAccountBalance = await helper.balance.getSubstrate(targetAccount.address);1629 expect(targetAccountBalance).to.be.equal(0n);1555 expect(targetAccountBalance).to.be.equal(0n);1692 testAmount,1618 testAmount,1693 );1619 );16201621 let maliciousXcmProgramFullIdSent: any;1622 let maliciousXcmProgramHereIdSent: any;1623 const maxWaitBlocks = 3;169416241695 // Try to trick Unique using full UNQ identification1625 // Try to trick Unique using full UNQ identification1696 await usingAstarPlaygrounds(astarUrl, async (helper) => {1626 await usingAstarPlaygrounds(astarUrl, async (helper) => {1697 await helper.getSudo().xcm.send(alice, uniqueMultilocation, maliciousXcmProgramFullId);1627 await helper.getSudo().xcm.send(alice, uniqueMultilocation, maliciousXcmProgramFullId);16281629 maliciousXcmProgramFullIdSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);1698 });1630 });16991700 const maxWaitBlocks = 3;1701 const outcomeField = 1;170216311703 let xcmpQueueFailEvent = await helper.wait.eventData<XcmV2TraitsError>(1632 await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Fail, event => {1704 maxWaitBlocks,1633 return event.messageHash() == maliciousXcmProgramFullIdSent.messageHash()1705 'xcmpQueue',1634 && event.outcome().isUntrustedReserveLocation;1706 'Fail',1707 outcomeField,1708 );1635 });17091710 expect(1711 xcmpQueueFailEvent != null,1712 '\'xcmpQueue.FailEvent\' event is expected',1713 ).to.be.true;17141715 expect(1716 xcmpQueueFailEvent!.isUntrustedReserveLocation,1717 `The XCM error should be 'UntrustedReserveLocation', got '${xcmpQueueFailEvent!.toHuman()}'`,1718 ).to.be.true;171916361720 let accountBalance = await helper.balance.getSubstrate(targetAccount.address);1637 let accountBalance = await helper.balance.getSubstrate(targetAccount.address);1721 expect(accountBalance).to.be.equal(0n);1638 expect(accountBalance).to.be.equal(0n);1724 await usingAstarPlaygrounds(astarUrl, async (helper) => {1641 await usingAstarPlaygrounds(astarUrl, async (helper) => {1725 await helper.getSudo().xcm.send(alice, uniqueMultilocation, maliciousXcmProgramHereId);1642 await helper.getSudo().xcm.send(alice, uniqueMultilocation, maliciousXcmProgramHereId);16431644 maliciousXcmProgramHereIdSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);1726 });1645 });172716461728 xcmpQueueFailEvent = await helper.wait.eventData<XcmV2TraitsError>(1647 await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Fail, event => {1729 maxWaitBlocks,1648 return event.messageHash() == maliciousXcmProgramHereIdSent.messageHash()1730 'xcmpQueue',1649 && event.outcome().isUntrustedReserveLocation;1731 'Fail',1732 outcomeField,1733 );1650 });17341735 expect(1736 xcmpQueueFailEvent != null,1737 '\'xcmpQueue.FailEvent\' event is expected',1738 ).to.be.true;17391740 expect(1741 xcmpQueueFailEvent!.isUntrustedReserveLocation,1742 `The XCM error should be 'UntrustedReserveLocation', got '${xcmpQueueFailEvent!.toHuman()}'`,1743 ).to.be.true;174416511745 accountBalance = await helper.balance.getSubstrate(targetAccount.address);1652 accountBalance = await helper.balance.getSubstrate(targetAccount.address);1746 expect(accountBalance).to.be.equal(0n);1653 expect(accountBalance).to.be.equal(0n);