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

difftreelog

test other chains can spend only up to balance

Daniel Shiposha2023-04-12parent: #c319502.patch.diff
in: master

4 files changed

modifiedtests/src/util/playgrounds/unique.dev.tsdiffbeforeafterboth
--- a/tests/src/util/playgrounds/unique.dev.ts
+++ b/tests/src/util/playgrounds/unique.dev.ts
@@ -420,6 +420,63 @@
 
     return capture;
   }
+
+  makeXcmProgramWithdrawDeposit(beneficiary: Uint8Array, amount: bigint | string) {
+    return {
+      V2: [
+        {
+          WithdrawAsset: [
+            {
+              id: {
+                Concrete: {
+                  parents: 0,
+                  interior: 'Here',
+                },
+              },
+              fun: {
+                Fungible: amount,
+              },
+            },
+          ],
+        },
+        {
+          BuyExecution: {
+            fees: {
+              id: {
+                Concrete: {
+                  parents: 0,
+                  interior: 'Here',
+                },
+              },
+              fun: {
+                Fungible: amount,
+              },
+            },
+            weightLimit: 'Unlimited'
+          },
+        },
+        {
+          DepositAsset: {
+            assets: {
+              Wild: 'All'
+            },
+            maxAssets: 1,
+            beneficiary: {
+              parents: 0,
+              interior: {
+                X1: {
+                  AccountId32: {
+                    network: 'Any',
+                    id: beneficiary
+                  },
+                },
+              },
+            },
+          }
+        },
+      ],
+    };
+  }
 }
 
 class MoonbeamAccountGroup {
modifiedtests/src/util/playgrounds/unique.tsdiffbeforeafterboth
--- a/tests/src/util/playgrounds/unique.ts
+++ b/tests/src/util/playgrounds/unique.ts
@@ -2446,6 +2446,10 @@
     return this.ethBalanceGroup.getEthereum(address);
   }
 
+  async setBalanceSubstrate(signer: TSigner, address: TSubstrateAccount, amount: bigint | string, reservedAmount: bigint | string = 0n) {
+    await this.helper.executeExtrinsic(signer, 'api.tx.balances.setBalance', [address, amount, reservedAmount], true);
+  }
+
   /**
    * Transfer tokens to substrate address
    * @param signer keyring of signer
modifiedtests/src/xcm/xcmQuartz.test.tsdiffbeforeafterboth
643 expect(qtzFees == 0n).to.be.true;643 expect(qtzFees == 0n).to.be.true;
644 });644 });
645
646 itSub('Karura can send only up to its balance', async ({helper}) => {
647 // set Karura's sovereign account's balance
648 const karuraBalance = 10000n * (10n ** QTZ_DECIMALS);
649 const karuraSovereignAccount = helper.address.paraSiblingSovereignAccount(KARURA_CHAIN);
650 await helper.getSudo().balance.setBalanceSubstrate(alice, karuraSovereignAccount, karuraBalance);
651
652 const moreThanKaruraHas = karuraBalance * 2n;
653
654 let targetAccountBalance = 0n;
655 const [targetAccount] = await helper.arrange.createAccounts([targetAccountBalance], alice);
656
657 const quartzMultilocation = {
658 V1: {
659 parents: 1,
660 interior: {
661 X1: {Parachain: QUARTZ_CHAIN},
662 },
663 },
664 };
665
666 const maliciousXcmProgram = helper.arrange.makeXcmProgramWithdrawDeposit(targetAccount.addressRaw, moreThanKaruraHas);
667
668 // Try to trick Quartz
669 await usingKaruraPlaygrounds(karuraUrl, async (helper) => {
670 await helper.getSudo().executeExtrinsic(
671 alice,
672 'api.tx.polkadotXcm.send',
673 [
674 quartzMultilocation,
675 maliciousXcmProgram,
676 ],
677 true,
678 );
679 });
680
681 const maxWaitBlocks = 3;
682
683 const xcmpQueueFailEvent = await helper.wait.eventOutcome<XcmV2TraitsError>(
684 maxWaitBlocks,
685 'xcmpQueue',
686 'Fail',
687 );
688
689 expect(
690 xcmpQueueFailEvent != null,
691 `'xcmpQueue.FailEvent' event is expected`,
692 ).to.be.true;
693
694 expect(
695 xcmpQueueFailEvent!.isFailedToTransactAsset,
696 `The XCM error should be 'FailedToTransactAsset'`,
697 ).to.be.true;
698
699 targetAccountBalance = await helper.balance.getSubstrate(targetAccount.address);
700 expect(targetAccountBalance).to.be.equal(0n);
701
702 // But Karura still can send the correct amount
703 const validTransferAmount = karuraBalance / 2n;
704 const validXcmProgram = helper.arrange.makeXcmProgramWithdrawDeposit(targetAccount.addressRaw, validTransferAmount);
705
706 await usingKaruraPlaygrounds(karuraUrl, async (helper) => {
707 await helper.getSudo().executeExtrinsic(
708 alice,
709 'api.tx.polkadotXcm.send',
710 [
711 quartzMultilocation,
712 validXcmProgram,
713 ],
714 true,
715 );
716 });
717
718 await helper.wait.newBlocks(maxWaitBlocks);
719
720 targetAccountBalance = await helper.balance.getSubstrate(targetAccount.address);
721 expect(targetAccountBalance).to.be.equal(validTransferAmount);
722 });
645});723});
646724
647// These tests are relevant only when725// These tests are relevant only when
1061 expect(qtzFees == 0n).to.be.true;1139 expect(qtzFees == 0n).to.be.true;
1062 });1140 });
1141
1142 itSub.skip('Moonriver can send only up to its balance', async ({helper}) => {
1143 throw Error("Not yet implemented");
1144 });
1063});1145});
10641146
1065describeXCM('[XCM] Integration test: Exchanging tokens with Shiden', () => {1147describeXCM('[XCM] Integration test: Exchanging tokens with Shiden', () => {
1273 expect(balanceQTZ).to.eq(balanceAfterQuartzToShidenXCM + qtzFromShidenTransfered);1355 expect(balanceQTZ).to.eq(balanceAfterQuartzToShidenXCM + qtzFromShidenTransfered);
1274 });1356 });
1357
1358 itSub('Shiden can send only up to its balance', async ({helper}) => {
1359 // set Shiden's sovereign account's balance
1360 const shidenBalance = 10000n * (10n ** QTZ_DECIMALS);
1361 const shidenSovereignAccount = helper.address.paraSiblingSovereignAccount(SHIDEN_CHAIN);
1362 await helper.getSudo().balance.setBalanceSubstrate(alice, shidenSovereignAccount, shidenBalance);
1363
1364 const moreThanShidenHas = shidenBalance * 2n;
1365
1366 let targetAccountBalance = 0n;
1367 const [targetAccount] = await helper.arrange.createAccounts([targetAccountBalance], alice);
1368
1369 const quartzMultilocation = {
1370 V1: {
1371 parents: 1,
1372 interior: {
1373 X1: {Parachain: QUARTZ_CHAIN},
1374 },
1375 },
1376 };
1377
1378 const maliciousXcmProgram = helper.arrange.makeXcmProgramWithdrawDeposit(targetAccount.addressRaw, moreThanShidenHas);
1379
1380 // Try to trick Quartz
1381 await usingShidenPlaygrounds(shidenUrl, async (helper) => {
1382 await helper.getSudo().executeExtrinsic(
1383 alice,
1384 'api.tx.polkadotXcm.send',
1385 [
1386 quartzMultilocation,
1387 maliciousXcmProgram,
1388 ],
1389 true,
1390 );
1391 });
1392
1393 const maxWaitBlocks = 3;
1394
1395 const xcmpQueueFailEvent = await helper.wait.eventOutcome<XcmV2TraitsError>(
1396 maxWaitBlocks,
1397 'xcmpQueue',
1398 'Fail',
1399 );
1400
1401 expect(
1402 xcmpQueueFailEvent != null,
1403 `'xcmpQueue.FailEvent' event is expected`,
1404 ).to.be.true;
1405
1406 expect(
1407 xcmpQueueFailEvent!.isFailedToTransactAsset,
1408 `The XCM error should be 'FailedToTransactAsset'`,
1409 ).to.be.true;
1410
1411 targetAccountBalance = await helper.balance.getSubstrate(targetAccount.address);
1412 expect(targetAccountBalance).to.be.equal(0n);
1413
1414 // But Shiden still can send the correct amount
1415 const validTransferAmount = shidenBalance / 2n;
1416 const validXcmProgram = helper.arrange.makeXcmProgramWithdrawDeposit(targetAccount.addressRaw, validTransferAmount);
1417
1418 await usingShidenPlaygrounds(shidenUrl, async (helper) => {
1419 await helper.getSudo().executeExtrinsic(
1420 alice,
1421 'api.tx.polkadotXcm.send',
1422 [
1423 quartzMultilocation,
1424 validXcmProgram,
1425 ],
1426 true,
1427 );
1428 });
1429
1430 await helper.wait.newBlocks(maxWaitBlocks);
1431
1432 targetAccountBalance = await helper.balance.getSubstrate(targetAccount.address);
1433 expect(targetAccountBalance).to.be.equal(validTransferAmount);
1434 });
1275});1435});
12761436
modifiedtests/src/xcm/xcmUnique.test.tsdiffbeforeafterboth
--- a/tests/src/xcm/xcmUnique.test.ts
+++ b/tests/src/xcm/xcmUnique.test.ts
@@ -644,6 +644,84 @@
     console.log('[Acala -> Unique] transaction fees on Unique: %s UNQ', helper.util.bigIntToDecimals(unqFees));
     expect(unqFees == 0n).to.be.true;
   });
+
+  itSub('Acala can send only up to its balance', async ({helper}) => {
+    // set Acala's sovereign account's balance
+    const acalaBalance = 10000n * (10n ** UNQ_DECIMALS);
+    const acalaSovereignAccount = helper.address.paraSiblingSovereignAccount(ACALA_CHAIN);
+    await helper.getSudo().balance.setBalanceSubstrate(alice, acalaSovereignAccount, acalaBalance);
+
+    const moreThanAcalaHas = acalaBalance * 2n;
+
+    let targetAccountBalance = 0n;
+    const [targetAccount] = await helper.arrange.createAccounts([targetAccountBalance], alice);
+
+    const uniqueMultilocation = {
+      V1: {
+        parents: 1,
+        interior: {
+          X1: {Parachain: UNIQUE_CHAIN},
+        },
+      },
+    };
+
+    const maliciousXcmProgram = helper.arrange.makeXcmProgramWithdrawDeposit(targetAccount.addressRaw, moreThanAcalaHas);
+
+    // Try to trick Unique
+    await usingAcalaPlaygrounds(acalaUrl, async (helper) => {
+      await helper.getSudo().executeExtrinsic(
+        alice,
+        'api.tx.polkadotXcm.send',
+        [
+          uniqueMultilocation,
+          maliciousXcmProgram,
+        ],
+        true,
+      );
+    });
+
+    const maxWaitBlocks = 3;
+
+    const xcmpQueueFailEvent = await helper.wait.eventOutcome<XcmV2TraitsError>(
+      maxWaitBlocks,
+      'xcmpQueue',
+      'Fail',
+    );
+
+    expect(
+      xcmpQueueFailEvent != null,
+      `'xcmpQueue.FailEvent' event is expected`,
+    ).to.be.true;
+
+    expect(
+      xcmpQueueFailEvent!.isFailedToTransactAsset,
+      `The XCM error should be 'FailedToTransactAsset'`,
+    ).to.be.true;
+
+    targetAccountBalance = await helper.balance.getSubstrate(targetAccount.address);
+    expect(targetAccountBalance).to.be.equal(0n);
+
+    // But Acala still can send the correct amount
+    const validTransferAmount = acalaBalance / 2n;
+    const validXcmProgram = helper.arrange.makeXcmProgramWithdrawDeposit(targetAccount.addressRaw, validTransferAmount);
+
+    await usingAcalaPlaygrounds(acalaUrl, async (helper) => {
+      await helper.getSudo().executeExtrinsic(
+        alice,
+        'api.tx.polkadotXcm.send',
+        [
+          uniqueMultilocation,
+          validXcmProgram,
+        ],
+        true,
+      );
+    });
+
+    await helper.wait.newBlocks(maxWaitBlocks);
+
+    targetAccountBalance = await helper.balance.getSubstrate(targetAccount.address);
+    expect(targetAccountBalance).to.be.equal(validTransferAmount);
+  });
 });
 
 // These tests are relevant only when
@@ -1063,6 +1141,10 @@
     console.log('[Moonbeam -> Unique] transaction fees on Unique: %s UNQ', helper.util.bigIntToDecimals(unqFees));
     expect(unqFees == 0n).to.be.true;
   });
+
+  itSub.skip('Moonbeam can send only up to its balance', async ({helper}) => {
+    throw Error("Not yet implemented");
+  });
 });
 
 describeXCM('[XCM] Integration test: Exchanging tokens with Astar', () => {
@@ -1330,4 +1412,82 @@
       await helper.xcm.limitedReserveTransferAssets(randomAccount, destination, beneficiary, assets, feeAssetItem, 'Unlimited');
     });
   });
+
+  itSub('Astar can send only up to its balance', async ({helper}) => {
+    // set Astar's sovereign account's balance
+    const astarBalance = 10000n * (10n ** UNQ_DECIMALS);
+    const astarSovereignAccount = helper.address.paraSiblingSovereignAccount(ASTAR_CHAIN);
+    await helper.getSudo().balance.setBalanceSubstrate(alice, astarSovereignAccount, astarBalance);
+
+    const moreThanShidenHas = astarBalance * 2n;
+
+    let targetAccountBalance = 0n;
+    const [targetAccount] = await helper.arrange.createAccounts([targetAccountBalance], alice);
+
+    const uniqueMultilocation = {
+      V1: {
+        parents: 1,
+        interior: {
+          X1: {Parachain: UNIQUE_CHAIN},
+        },
+      },
+    };
+
+    const maliciousXcmProgram = helper.arrange.makeXcmProgramWithdrawDeposit(targetAccount.addressRaw, moreThanShidenHas);
+
+    // Try to trick Unique
+    await usingAstarPlaygrounds(astarUrl, async (helper) => {
+      await helper.getSudo().executeExtrinsic(
+        alice,
+        'api.tx.polkadotXcm.send',
+        [
+          uniqueMultilocation,
+          maliciousXcmProgram,
+        ],
+        true,
+      );
+    });
+
+    const maxWaitBlocks = 3;
+
+    const xcmpQueueFailEvent = await helper.wait.eventOutcome<XcmV2TraitsError>(
+      maxWaitBlocks,
+      'xcmpQueue',
+      'Fail',
+    );
+
+    expect(
+      xcmpQueueFailEvent != null,
+      `'xcmpQueue.FailEvent' event is expected`,
+    ).to.be.true;
+
+    expect(
+      xcmpQueueFailEvent!.isFailedToTransactAsset,
+      `The XCM error should be 'FailedToTransactAsset'`,
+    ).to.be.true;
+
+    targetAccountBalance = await helper.balance.getSubstrate(targetAccount.address);
+    expect(targetAccountBalance).to.be.equal(0n);
+
+    // But Astar still can send the correct amount
+    const validTransferAmount = astarBalance / 2n;
+    const validXcmProgram = helper.arrange.makeXcmProgramWithdrawDeposit(targetAccount.addressRaw, validTransferAmount);
+
+    await usingAstarPlaygrounds(astarUrl, async (helper) => {
+      await helper.getSudo().executeExtrinsic(
+        alice,
+        'api.tx.polkadotXcm.send',
+        [
+          uniqueMultilocation,
+          validXcmProgram,
+        ],
+        true,
+      );
+    });
+
+    await helper.wait.newBlocks(maxWaitBlocks);
+
+    targetAccountBalance = await helper.balance.getSubstrate(targetAccount.address);
+    expect(targetAccountBalance).to.be.equal(validTransferAmount);
+  });
 });