difftreelog
test other chains can spend only up to balance
in: master
4 files changed
tests/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 {
tests/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
tests/src/xcm/xcmQuartz.test.tsdiffbeforeafterboth--- a/tests/src/xcm/xcmQuartz.test.ts
+++ b/tests/src/xcm/xcmQuartz.test.ts
@@ -642,6 +642,84 @@
console.log('[Karura -> Quartz] transaction fees on Quartz: %s QTZ', helper.util.bigIntToDecimals(qtzFees));
expect(qtzFees == 0n).to.be.true;
});
+
+ itSub('Karura can send only up to its balance', async ({helper}) => {
+ // set Karura's sovereign account's balance
+ const karuraBalance = 10000n * (10n ** QTZ_DECIMALS);
+ const karuraSovereignAccount = helper.address.paraSiblingSovereignAccount(KARURA_CHAIN);
+ await helper.getSudo().balance.setBalanceSubstrate(alice, karuraSovereignAccount, karuraBalance);
+
+ const moreThanKaruraHas = karuraBalance * 2n;
+
+ let targetAccountBalance = 0n;
+ const [targetAccount] = await helper.arrange.createAccounts([targetAccountBalance], alice);
+
+ const quartzMultilocation = {
+ V1: {
+ parents: 1,
+ interior: {
+ X1: {Parachain: QUARTZ_CHAIN},
+ },
+ },
+ };
+
+ const maliciousXcmProgram = helper.arrange.makeXcmProgramWithdrawDeposit(targetAccount.addressRaw, moreThanKaruraHas);
+
+ // Try to trick Quartz
+ await usingKaruraPlaygrounds(karuraUrl, async (helper) => {
+ await helper.getSudo().executeExtrinsic(
+ alice,
+ 'api.tx.polkadotXcm.send',
+ [
+ quartzMultilocation,
+ 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 Karura still can send the correct amount
+ const validTransferAmount = karuraBalance / 2n;
+ const validXcmProgram = helper.arrange.makeXcmProgramWithdrawDeposit(targetAccount.addressRaw, validTransferAmount);
+
+ await usingKaruraPlaygrounds(karuraUrl, async (helper) => {
+ await helper.getSudo().executeExtrinsic(
+ alice,
+ 'api.tx.polkadotXcm.send',
+ [
+ quartzMultilocation,
+ 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
@@ -1060,6 +1138,10 @@
console.log('[Moonriver -> Quartz] transaction fees on Quartz: %s QTZ', helper.util.bigIntToDecimals(qtzFees));
expect(qtzFees == 0n).to.be.true;
});
+
+ itSub.skip('Moonriver can send only up to its balance', async ({helper}) => {
+ throw Error("Not yet implemented");
+ });
});
describeXCM('[XCM] Integration test: Exchanging tokens with Shiden', () => {
@@ -1272,4 +1354,82 @@
console.log(`QTZ Balance on Quartz after XCM is: ${balanceQTZ}`);
expect(balanceQTZ).to.eq(balanceAfterQuartzToShidenXCM + qtzFromShidenTransfered);
});
+
+ itSub('Shiden can send only up to its balance', async ({helper}) => {
+ // set Shiden's sovereign account's balance
+ const shidenBalance = 10000n * (10n ** QTZ_DECIMALS);
+ const shidenSovereignAccount = helper.address.paraSiblingSovereignAccount(SHIDEN_CHAIN);
+ await helper.getSudo().balance.setBalanceSubstrate(alice, shidenSovereignAccount, shidenBalance);
+
+ const moreThanShidenHas = shidenBalance * 2n;
+
+ let targetAccountBalance = 0n;
+ const [targetAccount] = await helper.arrange.createAccounts([targetAccountBalance], alice);
+
+ const quartzMultilocation = {
+ V1: {
+ parents: 1,
+ interior: {
+ X1: {Parachain: QUARTZ_CHAIN},
+ },
+ },
+ };
+
+ const maliciousXcmProgram = helper.arrange.makeXcmProgramWithdrawDeposit(targetAccount.addressRaw, moreThanShidenHas);
+
+ // Try to trick Quartz
+ await usingShidenPlaygrounds(shidenUrl, async (helper) => {
+ await helper.getSudo().executeExtrinsic(
+ alice,
+ 'api.tx.polkadotXcm.send',
+ [
+ quartzMultilocation,
+ 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 Shiden still can send the correct amount
+ const validTransferAmount = shidenBalance / 2n;
+ const validXcmProgram = helper.arrange.makeXcmProgramWithdrawDeposit(targetAccount.addressRaw, validTransferAmount);
+
+ await usingShidenPlaygrounds(shidenUrl, async (helper) => {
+ await helper.getSudo().executeExtrinsic(
+ alice,
+ 'api.tx.polkadotXcm.send',
+ [
+ quartzMultilocation,
+ validXcmProgram,
+ ],
+ true,
+ );
+ });
+
+ await helper.wait.newBlocks(maxWaitBlocks);
+
+ targetAccountBalance = await helper.balance.getSubstrate(targetAccount.address);
+ expect(targetAccountBalance).to.be.equal(validTransferAmount);
+ });
});
tests/src/xcm/xcmUnique.test.tsdiffbeforeafterboth645 expect(unqFees == 0n).to.be.true;645 expect(unqFees == 0n).to.be.true;646 });646 });647648 itSub('Acala can send only up to its balance', async ({helper}) => {649 // set Acala's sovereign account's balance650 const acalaBalance = 10000n * (10n ** UNQ_DECIMALS);651 const acalaSovereignAccount = helper.address.paraSiblingSovereignAccount(ACALA_CHAIN);652 await helper.getSudo().balance.setBalanceSubstrate(alice, acalaSovereignAccount, acalaBalance);653654 const moreThanAcalaHas = acalaBalance * 2n;655656 let targetAccountBalance = 0n;657 const [targetAccount] = await helper.arrange.createAccounts([targetAccountBalance], alice);658659 const uniqueMultilocation = {660 V1: {661 parents: 1,662 interior: {663 X1: {Parachain: UNIQUE_CHAIN},664 },665 },666 };667668 const maliciousXcmProgram = helper.arrange.makeXcmProgramWithdrawDeposit(targetAccount.addressRaw, moreThanAcalaHas);669670 // Try to trick Unique671 await usingAcalaPlaygrounds(acalaUrl, async (helper) => {672 await helper.getSudo().executeExtrinsic(673 alice,674 'api.tx.polkadotXcm.send',675 [676 uniqueMultilocation,677 maliciousXcmProgram,678 ],679 true,680 );681 });682683 const maxWaitBlocks = 3;684685 const xcmpQueueFailEvent = await helper.wait.eventOutcome<XcmV2TraitsError>(686 maxWaitBlocks,687 'xcmpQueue',688 'Fail',689 );690691 expect(692 xcmpQueueFailEvent != null,693 `'xcmpQueue.FailEvent' event is expected`,694 ).to.be.true;695696 expect(697 xcmpQueueFailEvent!.isFailedToTransactAsset,698 `The XCM error should be 'FailedToTransactAsset'`,699 ).to.be.true;700701 targetAccountBalance = await helper.balance.getSubstrate(targetAccount.address);702 expect(targetAccountBalance).to.be.equal(0n);703704 // But Acala still can send the correct amount705 const validTransferAmount = acalaBalance / 2n;706 const validXcmProgram = helper.arrange.makeXcmProgramWithdrawDeposit(targetAccount.addressRaw, validTransferAmount);707708 await usingAcalaPlaygrounds(acalaUrl, async (helper) => {709 await helper.getSudo().executeExtrinsic(710 alice,711 'api.tx.polkadotXcm.send',712 [713 uniqueMultilocation,714 validXcmProgram,715 ],716 true,717 );718 });719720 await helper.wait.newBlocks(maxWaitBlocks);721722 targetAccountBalance = await helper.balance.getSubstrate(targetAccount.address);723 expect(targetAccountBalance).to.be.equal(validTransferAmount);724 });647});725});648726649// These tests are relevant only when727// These tests are relevant only when1064 expect(unqFees == 0n).to.be.true;1142 expect(unqFees == 0n).to.be.true;1065 });1143 });11441145 itSub.skip('Moonbeam can send only up to its balance', async ({helper}) => {1146 throw Error("Not yet implemented");1147 });1066});1148});106711491068describeXCM('[XCM] Integration test: Exchanging tokens with Astar', () => {1150describeXCM('[XCM] Integration test: Exchanging tokens with Astar', () => {1331 });1413 });1332 });1414 });14151416 itSub('Astar can send only up to its balance', async ({helper}) => {1417 // set Astar's sovereign account's balance1418 const astarBalance = 10000n * (10n ** UNQ_DECIMALS);1419 const astarSovereignAccount = helper.address.paraSiblingSovereignAccount(ASTAR_CHAIN);1420 await helper.getSudo().balance.setBalanceSubstrate(alice, astarSovereignAccount, astarBalance);14211422 const moreThanShidenHas = astarBalance * 2n;14231424 let targetAccountBalance = 0n;1425 const [targetAccount] = await helper.arrange.createAccounts([targetAccountBalance], alice);14261427 const uniqueMultilocation = {1428 V1: {1429 parents: 1,1430 interior: {1431 X1: {Parachain: UNIQUE_CHAIN},1432 },1433 },1434 };14351436 const maliciousXcmProgram = helper.arrange.makeXcmProgramWithdrawDeposit(targetAccount.addressRaw, moreThanShidenHas);14371438 // Try to trick Unique1439 await usingAstarPlaygrounds(astarUrl, async (helper) => {1440 await helper.getSudo().executeExtrinsic(1441 alice,1442 'api.tx.polkadotXcm.send',1443 [1444 uniqueMultilocation,1445 maliciousXcmProgram,1446 ],1447 true,1448 );1449 });14501451 const maxWaitBlocks = 3;14521453 const xcmpQueueFailEvent = await helper.wait.eventOutcome<XcmV2TraitsError>(1454 maxWaitBlocks,1455 'xcmpQueue',1456 'Fail',1457 );14581459 expect(1460 xcmpQueueFailEvent != null,1461 `'xcmpQueue.FailEvent' event is expected`,1462 ).to.be.true;14631464 expect(1465 xcmpQueueFailEvent!.isFailedToTransactAsset,1466 `The XCM error should be 'FailedToTransactAsset'`,1467 ).to.be.true;14681469 targetAccountBalance = await helper.balance.getSubstrate(targetAccount.address);1470 expect(targetAccountBalance).to.be.equal(0n);14711472 // But Astar still can send the correct amount1473 const validTransferAmount = astarBalance / 2n;1474 const validXcmProgram = helper.arrange.makeXcmProgramWithdrawDeposit(targetAccount.addressRaw, validTransferAmount);14751476 await usingAstarPlaygrounds(astarUrl, async (helper) => {1477 await helper.getSudo().executeExtrinsic(1478 alice,1479 'api.tx.polkadotXcm.send',1480 [1481 uniqueMultilocation,1482 validXcmProgram,1483 ],1484 true,1485 );1486 });14871488 await helper.wait.newBlocks(maxWaitBlocks);14891490 targetAccountBalance = await helper.balance.getSubstrate(targetAccount.address);1491 expect(targetAccountBalance).to.be.equal(validTransferAmount);1492 });1333});1493});13341494