git.delta.rocks / unique-network / refs/commits / 8a18c9958995

difftreelog

refactor event helpers

Daniel Shiposha2023-04-21parent: #6e3cf5e.patch.diff
in: master

4 files changed

modifiedtests/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);
   });
 });
 
modifiedtests/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;
   }
 }
 
modifiedtests/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);
modifiedtests/src/xcm/xcmUnique.test.tsdiffbeforeafterboth
1616
17import {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';
2221
23const UNIQUE_CHAIN = 2037;22const UNIQUE_CHAIN = 2037;
24const STATEMINT_CHAIN = 1000;23const STATEMINT_CHAIN = 1000;
675 moreThanAcalaHas,674 moreThanAcalaHas,
676 );675 );
676
677 let maliciousXcmProgramSent: any;
678 const maxWaitBlocks = 3;
677679
678 // Try to trick Unique680 // Try to trick Unique
679 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);
683
684 maliciousXcmProgramSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);
681 });685 });
682
683 const maxWaitBlocks = 3;
684 const outcomeField = 1;
685686
686 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 });
692
693 expect(
694 xcmpQueueFailEvent != null,
695 '\'xcmpQueue.FailEvent\' event is expected',
696 ).to.be.true;
697
698 expect(
699 xcmpQueueFailEvent!.isFailedToTransactAsset,
700 `The XCM error should be 'FailedToTransactAsset', got '${xcmpQueueFailEvent!.toHuman()}'`,
701 ).to.be.true;
702691
703 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 );
758
759 let maliciousXcmProgramFullIdSent: any;
760 let maliciousXcmProgramHereIdSent: any;
761 const maxWaitBlocks = 3;
769762
770 // Try to trick Unique using full UNQ identification763 // Try to trick Unique using full UNQ identification
771 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);
766
767 maliciousXcmProgramFullIdSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);
773 });768 });
774
775 const maxWaitBlocks = 3;
776 const outcomeField = 1;
777769
778 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 });
784
785 expect(
786 xcmpQueueFailEvent != null,
787 '\'xcmpQueue.FailEvent\' event is expected',
788 ).to.be.true;
789
790 expect(
791 xcmpQueueFailEvent!.isUntrustedReserveLocation,
792 `The XCM error should be 'UntrustedReserveLocation', got '${xcmpQueueFailEvent!.toHuman()}'`,
793 ).to.be.true;
794774
795 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);
781
782 maliciousXcmProgramHereIdSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);
801 });783 });
802784
803 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 });
809
810 expect(
811 xcmpQueueFailEvent != null,
812 '\'xcmpQueue.FailEvent\' event is expected',
813 ).to.be.true;
814
815 expect(
816 xcmpQueueFailEvent!.isUntrustedReserveLocation,
817 `The XCM error should be 'UntrustedReserveLocation', got '${xcmpQueueFailEvent!.toHuman()}'`,
818 ).to.be.true;
819789
820 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;
808
809 let messageSent: any;
810
811 const maxWaitBlocks = 3;
838812
839 before(async () => {813 before(async () => {
840 await usingPlaygrounds(async (helper, privateKey) => {814 await usingPlaygrounds(async (helper, privateKey) => {
885 });859 });
886 });860 });
887861
888 const expectFailedToTransact = async (network: string, helper: DevUniqueHelper) => {862 const expectFailedToTransact = async (helper: DevUniqueHelper, messageSent: any) => {
889 const maxWaitBlocks = 3;
890 const outcomeField = 1;
891
892 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 });
898
899 expect(
900 xcmpQueueFailEvent != null,
901 `[reject ${network} tokens] 'xcmpQueue.FailEvent' event is expected`,
902 ).to.be.true;
903
904 expect(
905 xcmpQueueFailEvent!.isFailedToTransactAsset,
906 `[reject ${network} tokens] The XCM error should be 'FailedToTransactAsset', got '${xcmpQueueFailEvent!.toHuman()}'`,
907 ).to.be.true;
908 };867 };
909868
910 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');
876
877 messageSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);
917 });878 });
918879
919 await expectFailedToTransact('ACA', helper);880 await expectFailedToTransact(helper, messageSent);
920 });881 });
921882
922 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');
888
889 messageSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);
927 });890 });
928891
929 await expectFailedToTransact('GLMR', helper);892 await expectFailedToTransact(helper, messageSent);
930 });893 });
931894
932 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 ]);
920
921 messageSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);
957 });922 });
958923
959 await expectFailedToTransact('ASTR', helper);924 await expectFailedToTransact(helper, messageSent);
960 });925 });
961});926});
962927
1196 moreThanMoonbeamHas,1161 moreThanMoonbeamHas,
1197 );1162 );
1163
1164 let maliciousXcmProgramSent: any;
1165 const maxWaitBlocks = 3;
11981166
1199 // Try to trick Unique1167 // Try to trick Unique
1200 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);
1174
1175 maliciousXcmProgramSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);
1206 });1176 });
1207
1208 const maxWaitBlocks = 3;
1209 const outcomeField = 1;
12101177
1211 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 });
1217
1218 expect(
1219 xcmpQueueFailEvent != null,
1220 '\'xcmpQueue.FailEvent\' event is expected',
1221 ).to.be.true;
1222
1223 expect(
1224 xcmpQueueFailEvent!.isFailedToTransactAsset,
1225 `The XCM error should be 'FailedToTransactAsset', got '${xcmpQueueFailEvent!.toHuman()}'`,
1226 ).to.be.true;
12271182
1228 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 );
1253
1254 let maliciousXcmProgramFullIdSent: any;
1255 let maliciousXcmProgramHereIdSent: any;
1256 const maxWaitBlocks = 3;
12981257
1299 // Try to trick Unique using full UNQ identification1258 // Try to trick Unique using full UNQ identification
1300 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);
1265
1266 maliciousXcmProgramFullIdSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);
1306 });1267 });
1307
1308 const maxWaitBlocks = 3;
1309 const outcomeField = 1;
13101268
1311 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 });
1317
1318 expect(
1319 xcmpQueueFailEvent != null,
1320 '\'xcmpQueue.FailEvent\' event is expected',
1321 ).to.be.true;
1322
1323 expect(
1324 xcmpQueueFailEvent!.isUntrustedReserveLocation,
1325 `The XCM error should be 'UntrustedReserveLocation', got '${xcmpQueueFailEvent!.toHuman()}'`,
1326 ).to.be.true;
13271273
1328 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);
1284
1285 maliciousXcmProgramHereIdSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);
1338 });1286 });
13391287
1340 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 });
1346
1347 expect(
1348 xcmpQueueFailEvent != null,
1349 '\'xcmpQueue.FailEvent\' event is expected',
1350 ).to.be.true;
1351
1352 expect(
1353 xcmpQueueFailEvent!.isUntrustedReserveLocation,
1354 `The XCM error should be 'UntrustedReserveLocation', got '${xcmpQueueFailEvent!.toHuman()}'`,
1355 ).to.be.true;
13561292
1357 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 );
1538
1539 let maliciousXcmProgramSent: any;
1540 const maxWaitBlocks = 3;
16021541
1603 // Try to trick Unique1542 // Try to trick Unique
1604 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);
1545
1546 maliciousXcmProgramSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);
1606 });1547 });
1607
1608 const maxWaitBlocks = 3;
1609 const outcomeField = 1;
16101548
1611 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 });
1617
1618 expect(
1619 xcmpQueueFailEvent != null,
1620 '\'xcmpQueue.FailEvent\' event is expected',
1621 ).to.be.true;
1622
1623 expect(
1624 xcmpQueueFailEvent!.isFailedToTransactAsset,
1625 `The XCM error should be 'FailedToTransactAsset', got '${xcmpQueueFailEvent!.toHuman()}'`,
1626 ).to.be.true;
16271553
1628 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 );
1620
1621 let maliciousXcmProgramFullIdSent: any;
1622 let maliciousXcmProgramHereIdSent: any;
1623 const maxWaitBlocks = 3;
16941624
1695 // Try to trick Unique using full UNQ identification1625 // Try to trick Unique using full UNQ identification
1696 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);
1628
1629 maliciousXcmProgramFullIdSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);
1698 });1630 });
1699
1700 const maxWaitBlocks = 3;
1701 const outcomeField = 1;
17021631
1703 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 });
1709
1710 expect(
1711 xcmpQueueFailEvent != null,
1712 '\'xcmpQueue.FailEvent\' event is expected',
1713 ).to.be.true;
1714
1715 expect(
1716 xcmpQueueFailEvent!.isUntrustedReserveLocation,
1717 `The XCM error should be 'UntrustedReserveLocation', got '${xcmpQueueFailEvent!.toHuman()}'`,
1718 ).to.be.true;
17191636
1720 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);
1643
1644 maliciousXcmProgramHereIdSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);
1726 });1645 });
17271646
1728 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 });
1734
1735 expect(
1736 xcmpQueueFailEvent != null,
1737 '\'xcmpQueue.FailEvent\' event is expected',
1738 ).to.be.true;
1739
1740 expect(
1741 xcmpQueueFailEvent!.isUntrustedReserveLocation,
1742 `The XCM error should be 'UntrustedReserveLocation', got '${xcmpQueueFailEvent!.toHuman()}'`,
1743 ).to.be.true;
17441651
1745 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);