difftreelog
test(xcm) qtz/unq rejects relay tokens
in: master
3 files changed
tests/src/util/helpers.tsdiffbeforeafterboth104}104}105105106export function bigIntToDecimals(number: bigint, decimals = 18): string {106export function bigIntToDecimals(number: bigint, decimals = 18): string {107 let numberStr = number.toString();107 const numberStr = number.toString();108 console.log('[0] str = ', numberStr);109110 // Get rid of `n` at the end111 numberStr = numberStr.substring(0, numberStr.length - 1);112 console.log('[1] str = ', numberStr);113114 const dotPos = numberStr.length - decimals;108 const dotPos = numberStr.length - decimals;1091794): Promise<EventRecord | null> {1789): Promise<EventRecord | null> {179517901796 const promise = new Promise<EventRecord | null>(async (resolve) => {1791 const promise = new Promise<EventRecord | null>(async (resolve) => {1797 const unsubscribe = await api.query.system.events(eventRecords => {1792 const unsubscribe = await api.rpc.chain.subscribeNewHeads(async header => {1793 const blockNumber = header.number.toHuman();1794 const blockHash = header.hash;1795 const eventIdStr = `${eventSection}.${eventMethod}`;1796 const waitLimitStr = `wait blocks remaining: ${maxBlocksToWait}`;17971798 console.log(`[Block #${blockNumber}] Waiting for event \`${eventIdStr}\` (${waitLimitStr})`);17991800 const apiAt = await api.at(blockHash);1801 const eventRecords = await apiAt.query.system.events();18021798 const neededEvent = eventRecords.find(r => {1803 const neededEvent = eventRecords.find(r => {1799 return r.event.section == eventSection && r.event.method == eventMethod;1804 return r.event.section == eventSection && r.event.method == eventMethod;1800 });1805 });180118061802 if (neededEvent) {1807 if (neededEvent) {1803 unsubscribe();1808 console.log(`Event \`${eventIdStr}\` is found`);1804 resolve(neededEvent);18091805 }1810 unsubscribe();18061811 resolve(neededEvent);1807 if (maxBlocksToWait > 0) {1812 } else if (maxBlocksToWait > 0) {1808 maxBlocksToWait--;1813 maxBlocksToWait--;1809 } else {1814 } else {1815 console.log(`Event \`${eventIdStr}\` is NOT found`);18161810 unsubscribe();1817 unsubscribe();1811 resolve(null);1818 resolve(null);tests/src/xcm/xcmQuartz.test.tsdiffbeforeafterboth26import {blake2AsHex} from '@polkadot/util-crypto';26import {blake2AsHex} from '@polkadot/util-crypto';27import waitNewBlocks from '../substrate/wait-new-blocks';27import waitNewBlocks from '../substrate/wait-new-blocks';28import getBalance from '../substrate/get-balance';28import getBalance from '../substrate/get-balance';29import {XcmV2TraitsOutcome, XcmV2TraitsError} from '../interfaces';293030chai.use(chaiAsPromised);31chai.use(chaiAsPromised);31const expect = chai.expect;32const expect = chai.expect;34const KARURA_CHAIN = 2000;35const KARURA_CHAIN = 2000;35const MOONRIVER_CHAIN = 2023;36const MOONRIVER_CHAIN = 2023;363738const RELAY_PORT = 9844;37const KARURA_PORT = 9946;39const KARURA_PORT = 9946;38const MOONRIVER_PORT = 9947;40const MOONRIVER_PORT = 9947;394155 return parachainApiOptions(MOONRIVER_PORT);57 return parachainApiOptions(MOONRIVER_PORT);56}58}575960function relayOptions(): ApiOptions {61 return parachainApiOptions(RELAY_PORT);62}6358describe_xcm('Integration test: Exchanging tokens with Karura', () => {64describe_xcm('Integration test: Exchanging tokens with Karura', () => {59 let alice: IKeyringPair;65 let alice: IKeyringPair;60 let randomAccount: IKeyringPair;66 let randomAccount: IKeyringPair;200 const karFees = balanceKaruraTokenInit - balanceKaruraTokenMiddle;206 const karFees = balanceKaruraTokenInit - balanceKaruraTokenMiddle;201 const qtzIncomeTransfer = balanceQuartzForeignTokenMiddle - balanceQuartzForeignTokenInit;207 const qtzIncomeTransfer = balanceQuartzForeignTokenMiddle - balanceQuartzForeignTokenInit;202208203 console.log('209 console.log(204 [Quartz -> Karura] transaction fees on Karura: %s KAR',210 '[Quartz -> Karura] transaction fees on Karura: %s KAR',205 bigIntToDecimals(karFees, KARURA_DECIMALS),211 bigIntToDecimals(karFees, KARURA_DECIMALS),206 );212 );207 console.log('[Quartz -> Karura] income %s QTZ', bigIntToDecimals(qtzIncomeTransfer));213 console.log('[Quartz -> Karura] income %s QTZ', bigIntToDecimals(qtzIncomeTransfer));281 expect(qtzFees == 0n).to.be.true;287 expect(qtzFees == 0n).to.be.true;282 });288 });283 });289 });290});284291285 it('Quartz rejects KAR tokens from Karura', async () => {292// These tests are relevant only when the foreign asset pallet is disabled293describe('Integration test: Quartz rejects non-native tokens', () => {286 // This test is relevant only when the foreign asset pallet is disabled294 let alice: IKeyringPair;287295296 before(async () => {297 await usingApi(async (api, privateKeyWrapper) => {298 alice = privateKeyWrapper('//Alice');299 });300 });301 302 it('Quartz rejects tokens from the Relay', async () => {288 await usingApi(async (api) => {303 await usingApi(async (api) => {289 const destination = {304 const destination = {290 V1: {305 V1: {306 parents: 0,307 interior: {X1: {308 Parachain: QUARTZ_CHAIN,309 },310 },311 }};312313 const beneficiary = {314 V1: {315 parents: 0,316 interior: {X1: {317 AccountId32: {318 network: 'Any',319 id: alice.addressRaw,320 },321 }},322 },323 };324325 const assets = {326 V1: [327 {328 id: {329 Concrete: {330 parents: 0,331 interior: 'Here',332 },333 },334 fun: {335 Fungible: 50_000_000_000_000_000n,336 },337 },338 ],339 };340341 const feeAssetItem = 0;342343 const weightLimit = {344 Limited: 5_000_000_000,345 };346347 const tx = api.tx.xcmPallet.limitedReserveTransferAssets(destination, beneficiary, assets, feeAssetItem, weightLimit);348 const events = await submitTransactionAsync(alice, tx);349 const result = getGenericResult(events);350 expect(result.success).to.be.true;351 }, relayOptions());352353 await usingApi(async api => {354 const maxWaitBlocks = 3;355 const dmpQueueExecutedDownward = await waitEvent(356 api,357 maxWaitBlocks,358 'dmpQueue',359 'ExecutedDownward',360 );361362 expect(363 dmpQueueExecutedDownward != null,364 '[Relay] dmpQueue.ExecutedDownward event is expected',365 ).to.be.true;366367 const event = dmpQueueExecutedDownward!.event;368 const outcome = event.data[1] as XcmV2TraitsOutcome;369370 expect(371 outcome.isIncomplete,372 '[Relay] The outcome of the XCM should be `Incomplete`',373 ).to.be.true;374375 const incomplete = outcome.asIncomplete;376 expect(377 incomplete[1].toString() == 'AssetNotFound',378 '[Relay] The XCM error should be `AssetNotFound`',379 ).to.be.true;380 });381 });382383 it('Quartz rejects KAR tokens from Karura', async () => {384 await usingApi(async (api) => {385 const destination = {386 V1: {291 parents: 1,387 parents: 1,292 interior: {388 interior: {293 X2: [389 X2: [294 {Parachain: QUARTZ_CHAIN},390 {Parachain: QUARTZ_CHAIN},295 {391 {296 AccountId32: {392 AccountId32: {297 network: 'Any',393 network: 'Any',298 id: randomAccount.addressRaw,394 id: alice.addressRaw,299 },395 },300 },396 },301 ],397 ],321417322 expect(418 expect(323 xcmpQueueFailEvent != null,419 xcmpQueueFailEvent != null,324 'Only native token is supported when the Foreign-Assets pallet is not connected',420 '[Karura] xcmpQueue.FailEvent event is expected',421 ).to.be.true;422423 const event = xcmpQueueFailEvent!.event;424 const outcome = event.data[1] as XcmV2TraitsError;425426 expect(427 outcome.isUntrustedReserveLocation,428 '[Karura] The XCM error should be `UntrustedReserveLocation`',325 ).to.be.true;429 ).to.be.true;326 });430 });327 });431 });tests/src/xcm/xcmUnique.test.tsdiffbeforeafterboth26import {blake2AsHex} from '@polkadot/util-crypto';26import {blake2AsHex} from '@polkadot/util-crypto';27import waitNewBlocks from '../substrate/wait-new-blocks';27import waitNewBlocks from '../substrate/wait-new-blocks';28import getBalance from '../substrate/get-balance';28import getBalance from '../substrate/get-balance';29import {XcmV2TraitsError, XcmV2TraitsOutcome} from '../interfaces';293030chai.use(chaiAsPromised);31chai.use(chaiAsPromised);31const expect = chai.expect;32const expect = chai.expect;34const ACALA_CHAIN = 2000;35const ACALA_CHAIN = 2000;35const MOONBEAM_CHAIN = 2004;36const MOONBEAM_CHAIN = 2004;363738const RELAY_PORT = 9844;37const ACALA_PORT = 9946;39const ACALA_PORT = 9946;38const MOONBEAM_PORT = 9947;40const MOONBEAM_PORT = 9947;394155 return parachainApiOptions(MOONBEAM_PORT);57 return parachainApiOptions(MOONBEAM_PORT);56}58}575960function relayOptions(): ApiOptions {61 return parachainApiOptions(RELAY_PORT);62}6364describe_xcm('Integration test: Exchanging tokens with Acala', () => {65 let alice: IKeyringPair;66 let randomAccount: IKeyringPair;67 68 let balanceUniqueTokenInit: bigint;69 let balanceUniqueTokenMiddle: bigint;70 let balanceUniqueTokenFinal: bigint;71 let balanceAcalaTokenInit: bigint;72 let balanceAcalaTokenMiddle: bigint;73 let balanceAcalaTokenFinal: bigint;74 let balanceUniqueForeignTokenInit: bigint;75 let balanceUniqueForeignTokenMiddle: bigint;76 let balanceUniqueForeignTokenFinal: bigint;77 78 before(async () => {79 await usingApi(async (api, privateKeyWrapper) => {80 alice = privateKeyWrapper('//Alice');81 randomAccount = generateKeyringPair();82 });8384 // Acala side85 await usingApi(86 async (api) => {87 const destination = {88 V0: {89 X2: [90 'Parent',91 {92 Parachain: UNIQUE_CHAIN,93 },94 ],95 },96 };97 98 const metadata = {99 name: 'UNQ',100 symbol: 'UNQ',101 decimals: 18,102 minimalBalance: 1,103 };104 105 const tx = api.tx.assetRegistry.registerForeignAsset(destination, metadata);106 const sudoTx = api.tx.sudo.sudo(tx as any);107 const events = await submitTransactionAsync(alice, sudoTx);108 const result = getGenericResult(events);109 expect(result.success).to.be.true;110 111 const tx1 = api.tx.balances.transfer(randomAccount.address, 10000000000000n);112 const events1 = await submitTransactionAsync(alice, tx1);113 const result1 = getGenericResult(events1);114 expect(result1.success).to.be.true;115 116 [balanceAcalaTokenInit] = await getBalance(api, [randomAccount.address]);117 {118 const {free} = (await api.query.tokens.accounts(randomAccount.addressRaw, {ForeignAsset: 0})).toJSON() as any;119 balanceUniqueForeignTokenInit = BigInt(free);120 }121 },122 acalaOptions(),123 );124 125 // Unique side126 await usingApi(async (api) => {127 const tx0 = api.tx.balances.transfer(randomAccount.address, 10n * TRANSFER_AMOUNT);128 const events0 = await submitTransactionAsync(alice, tx0);129 const result0 = getGenericResult(events0);130 expect(result0.success).to.be.true;131 132 [balanceUniqueTokenInit] = await getBalance(api, [randomAccount.address]);133 });134 });135 136 it('Should connect and send UNQ to Acala', async () => {137 138 // Unique side139 await usingApi(async (api) => {140 141 const destination = {142 V0: {143 X2: [144 'Parent',145 {146 Parachain: ACALA_CHAIN,147 },148 ],149 },150 };151 152 const beneficiary = {153 V0: {154 X1: {155 AccountId32: {156 network: 'Any',157 id: randomAccount.addressRaw,158 },159 },160 },161 };162 163 const assets = {164 V1: [165 {166 id: {167 Concrete: {168 parents: 0,169 interior: 'Here',170 },171 },172 fun: {173 Fungible: TRANSFER_AMOUNT,174 },175 },176 ],177 };178 179 const feeAssetItem = 0;180 181 const weightLimit = {182 Limited: 5000000000,183 };184 185 const tx = api.tx.polkadotXcm.limitedReserveTransferAssets(destination, beneficiary, assets, feeAssetItem, weightLimit);186 const events = await submitTransactionAsync(randomAccount, tx);187 const result = getGenericResult(events);188 expect(result.success).to.be.true;189 190 [balanceUniqueTokenMiddle] = await getBalance(api, [randomAccount.address]);191 192 const unqFees = balanceUniqueTokenInit - balanceUniqueTokenMiddle - TRANSFER_AMOUNT;193 console.log('[Unique -> Acala] transaction fees on Unique: %s UNQ', bigIntToDecimals(unqFees));194 expect(unqFees > 0n).to.be.true;195 });196 197 // Acala side198 await usingApi(199 async (api) => {200 await waitNewBlocks(api, 3);201 const {free} = (await api.query.tokens.accounts(randomAccount.addressRaw, {ForeignAsset: 0})).toJSON() as any;202 balanceUniqueForeignTokenMiddle = BigInt(free);203 204 [balanceAcalaTokenMiddle] = await getBalance(api, [randomAccount.address]);205206 const acaFees = balanceAcalaTokenInit - balanceAcalaTokenMiddle;207 const unqIncomeTransfer = balanceUniqueForeignTokenMiddle - balanceUniqueForeignTokenInit;208209 console.log(210 '[Unique -> Acala] transaction fees on Acala: %s ACA',211 bigIntToDecimals(acaFees, ACALA_DECIMALS),212 );213 console.log('[Unique -> Acala] income %s UNQ', bigIntToDecimals(unqIncomeTransfer));214 expect(acaFees == 0n).to.be.true;215 expect(unqIncomeTransfer == TRANSFER_AMOUNT).to.be.true;216 },217 acalaOptions(),218 );219 });220 221 it('Should connect to Acala and send UNQ back', async () => {222 223 // Acala side224 await usingApi(225 async (api) => {226 const destination = {227 V1: {228 parents: 1,229 interior: {230 X2: [231 {Parachain: UNIQUE_CHAIN},232 {233 AccountId32: {234 network: 'Any',235 id: randomAccount.addressRaw,236 },237 },238 ],239 },240 },241 };242 243 const id = {244 ForeignAsset: 0,245 };246247 const destWeight = 50000000;248 249 const tx = api.tx.xTokens.transfer(id, TRANSFER_AMOUNT, destination, destWeight);250 const events = await submitTransactionAsync(randomAccount, tx);251 const result = getGenericResult(events);252 expect(result.success).to.be.true;253 254 [balanceAcalaTokenFinal] = await getBalance(api, [randomAccount.address]);255 {256 const {free} = (await api.query.tokens.accounts(randomAccount.addressRaw, {ForeignAsset: 0})).toJSON() as any;257 balanceUniqueForeignTokenFinal = BigInt(free);258 }259 260 const acaFees = balanceAcalaTokenMiddle - balanceAcalaTokenFinal;261 const unqOutcomeTransfer = balanceUniqueForeignTokenMiddle - balanceUniqueForeignTokenFinal;262263 console.log(264 '[Acala -> Unique] transaction fees on Acala: %s ACA',265 bigIntToDecimals(acaFees, ACALA_DECIMALS),266 );267 console.log('[Acala -> Unique] outcome %s UNQ', bigIntToDecimals(unqOutcomeTransfer));268269 expect(acaFees > 0).to.be.true;270 expect(unqOutcomeTransfer == TRANSFER_AMOUNT).to.be.true;271 },272 acalaOptions(),273 );274275 // Unique side276 await usingApi(async (api) => {277 await waitNewBlocks(api, 3);278 279 [balanceUniqueTokenFinal] = await getBalance(api, [randomAccount.address]);280 const actuallyDelivered = balanceUniqueTokenFinal - balanceUniqueTokenMiddle;281 expect(actuallyDelivered > 0).to.be.true;282283 console.log('[Acala -> Unique] actually delivered %s UNQ', bigIntToDecimals(actuallyDelivered));284 285 const unqFees = TRANSFER_AMOUNT - actuallyDelivered;286 console.log('[Acala -> Unique] transaction fees on Unique: %s UNQ', bigIntToDecimals(unqFees));287 expect(unqFees == 0n).to.be.true;288 });289 });290});291292// These tests are relevant only when the foreign asset pallet is disabled58describe_xcm('Integration test: Exchanging tokens with Acala', () => {293describe('Integration test: Unique rejects non-native tokens', () => {59 let alice: IKeyringPair;294 let alice: IKeyringPair;60 let randomAccount: IKeyringPair;29561 62 let balanceUniqueTokenInit: bigint;63 let balanceUniqueTokenMiddle: bigint;64 let balanceUniqueTokenFinal: bigint;65 let balanceAcalaTokenInit: bigint;66 let balanceAcalaTokenMiddle: bigint;67 let balanceAcalaTokenFinal: bigint;68 let balanceUniqueForeignTokenInit: bigint;69 let balanceUniqueForeignTokenMiddle: bigint;70 let balanceUniqueForeignTokenFinal: bigint;71 72 before(async () => {296 before(async () => {73 await usingApi(async (api, privateKeyWrapper) => {297 await usingApi(async (api, privateKeyWrapper) => {74 alice = privateKeyWrapper('//Alice');298 alice = privateKeyWrapper('//Alice');75 randomAccount = generateKeyringPair();76 });299 });7778 // Acala side79 await usingApi(80 async (api) => {81 const destination = {82 V0: {83 X2: [84 'Parent',85 {86 Parachain: UNIQUE_CHAIN,87 },88 ],89 },90 };91 92 const metadata = {93 name: 'UNQ',94 symbol: 'UNQ',95 decimals: 18,96 minimalBalance: 1,97 };98 99 const tx = api.tx.assetRegistry.registerForeignAsset(destination, metadata);100 const sudoTx = api.tx.sudo.sudo(tx as any);101 const events = await submitTransactionAsync(alice, sudoTx);102 const result = getGenericResult(events);103 expect(result.success).to.be.true;104 105 const tx1 = api.tx.balances.transfer(randomAccount.address, 10000000000000n);106 const events1 = await submitTransactionAsync(alice, tx1);107 const result1 = getGenericResult(events1);108 expect(result1.success).to.be.true;109 110 [balanceAcalaTokenInit] = await getBalance(api, [randomAccount.address]);111 {112 const {free} = (await api.query.tokens.accounts(randomAccount.addressRaw, {ForeignAsset: 0})).toJSON() as any;113 balanceUniqueForeignTokenInit = BigInt(free);114 }115 },116 acalaOptions(),117 );118 119 // Unique side120 await usingApi(async (api) => {121 const tx0 = api.tx.balances.transfer(randomAccount.address, 10n * TRANSFER_AMOUNT);122 const events0 = await submitTransactionAsync(alice, tx0);123 const result0 = getGenericResult(events0);124 expect(result0.success).to.be.true;125 126 [balanceUniqueTokenInit] = await getBalance(api, [randomAccount.address]);127 });128 });300 });129 301 130 it('Should connect and send UNQ to Acala', async () => {302 it('Unique rejects tokens from the Relay', async () => {131 132 // Unique side133 await usingApi(async (api) => {303 await usingApi(async (api) => {134 135 const destination = {304 const destination = {136 V0: {305 V1: {306 parents: 0,137 X2: [307 interior: {X1: {138 'Parent',139 {140 Parachain: ACALA_CHAIN,308 Parachain: UNIQUE_CHAIN,141 },309 },142 ],310 },143 },311 }};144 };312145 146 const beneficiary = {313 const beneficiary = {147 V0: {314 V1: {315 parents: 0,148 X1: {316 interior: {X1: {149 AccountId32: {317 AccountId32: {150 network: 'Any',318 network: 'Any',151 id: randomAccount.addressRaw,319 id: alice.addressRaw,152 },320 },153 },321 }},154 },322 },155 };323 };156 324164 },332 },165 },333 },166 fun: {334 fun: {167 Fungible: TRANSFER_AMOUNT,335 Fungible: 50_000_000_000_000_000n,168 },336 },169 },337 },170 ],338 ],173 const feeAssetItem = 0;341 const feeAssetItem = 0;174 342175 const weightLimit = {343 const weightLimit = {176 Limited: 5000000000,344 Limited: 5_000_000_000,177 };345 };178 346179 const tx = api.tx.polkadotXcm.limitedReserveTransferAssets(destination, beneficiary, assets, feeAssetItem, weightLimit);347 const tx = api.tx.xcmPallet.limitedReserveTransferAssets(destination, beneficiary, assets, feeAssetItem, weightLimit);180 const events = await submitTransactionAsync(randomAccount, tx);348 const events = await submitTransactionAsync(alice, tx);181 const result = getGenericResult(events);349 const result = getGenericResult(events);182 expect(result.success).to.be.true;350 expect(result.success).to.be.true;183 184 [balanceUniqueTokenMiddle] = await getBalance(api, [randomAccount.address]);185 186 const unqFees = balanceUniqueTokenInit - balanceUniqueTokenMiddle - TRANSFER_AMOUNT;187 console.log('[Unique -> Acala] transaction fees on Unique: %s UNQ', bigIntToDecimals(unqFees));188 expect(unqFees > 0n).to.be.true;189 });351 }, relayOptions());190 352191 // Acala side192 await usingApi(353 await usingApi(async api => {193 async (api) => {194 await waitNewBlocks(api, 3);354 const maxWaitBlocks = 3;195 const {free} = (await api.query.tokens.accounts(randomAccount.addressRaw, {ForeignAsset: 0})).toJSON() as any;355 const dmpQueueExecutedDownward = await waitEvent(196 balanceUniqueForeignTokenMiddle = BigInt(free);356 api,197 357 maxWaitBlocks,358 'dmpQueue',359 'ExecutedDownward',360 );361198 [balanceAcalaTokenMiddle] = await getBalance(api, [randomAccount.address]);362 expect(363 dmpQueueExecutedDownward != null,364 '[Relay] dmpQueue.ExecutedDownward event is expected',365 ).to.be.true;199366200 const acaFees = balanceAcalaTokenInit - balanceAcalaTokenMiddle;367 const event = dmpQueueExecutedDownward!.event;201 const unqIncomeTransfer = balanceUniqueForeignTokenMiddle - balanceUniqueForeignTokenInit;368 const outcome = event.data[1] as XcmV2TraitsOutcome;202369203 console.log(204 '[Unique -> Acala] transaction fees on Acala: %s ACA',205 bigIntToDecimals(acaFees, ACALA_DECIMALS),206 );207 console.log('[Unique -> Acala] income %s UNQ', bigIntToDecimals(unqIncomeTransfer));208 expect(acaFees == 0n).to.be.true;370 expect(371 outcome.isIncomplete,372 '[Relay] The outcome of the XCM should be `Incomplete`',373 ).to.be.true;374375 const incomplete = outcome.asIncomplete;209 expect(unqIncomeTransfer == TRANSFER_AMOUNT).to.be.true;376 expect(377 incomplete[1].toString() == 'AssetNotFound',378 '[Relay] The XCM error should be `AssetNotFound`',379 ).to.be.true;210 },380 });211 acalaOptions(),212 );213 });381 });214 215 it('Should connect to Acala and send UNQ back', async () => {216 217 // Acala side218 await usingApi(219 async (api) => {220 const destination = {221 V1: {222 parents: 1,223 interior: {224 X2: [225 {Parachain: UNIQUE_CHAIN},226 {227 AccountId32: {228 network: 'Any',229 id: randomAccount.addressRaw,230 },231 },232 ],233 },234 },235 };236 237 const id = {238 ForeignAsset: 0,239 };240241 const destWeight = 50000000;242 243 const tx = api.tx.xTokens.transfer(id, TRANSFER_AMOUNT, destination, destWeight);244 const events = await submitTransactionAsync(randomAccount, tx);245 const result = getGenericResult(events);246 expect(result.success).to.be.true;247 248 [balanceAcalaTokenFinal] = await getBalance(api, [randomAccount.address]);249 {250 const {free} = (await api.query.tokens.accounts(randomAccount.addressRaw, {ForeignAsset: 0})).toJSON() as any;251 balanceUniqueForeignTokenFinal = BigInt(free);252 }253 254 const acaFees = balanceAcalaTokenMiddle - balanceAcalaTokenFinal;255 const unqOutcomeTransfer = balanceUniqueForeignTokenMiddle - balanceUniqueForeignTokenFinal;256257 console.log(258 '[Acala -> Unique] transaction fees on Acala: %s ACA',259 bigIntToDecimals(acaFees, ACALA_DECIMALS),260 );261 console.log('[Acala -> Unique] outcome %s UNQ', bigIntToDecimals(unqOutcomeTransfer));262263 expect(acaFees > 0).to.be.true;264 expect(unqOutcomeTransfer == TRANSFER_AMOUNT).to.be.true;265 },266 acalaOptions(),267 );268269 // Unique side270 await usingApi(async (api) => {271 await waitNewBlocks(api, 3);272 273 [balanceUniqueTokenFinal] = await getBalance(api, [randomAccount.address]);274 const actuallyDelivered = balanceUniqueTokenFinal - balanceUniqueTokenMiddle;275 expect(actuallyDelivered > 0).to.be.true;276277 console.log('[Acala -> Unique] actually delivered %s UNQ', bigIntToDecimals(actuallyDelivered));278 279 const unqFees = TRANSFER_AMOUNT - actuallyDelivered;280 console.log('[Acala -> Unique] transaction fees on Unique: %s UNQ', bigIntToDecimals(unqFees));281 expect(unqFees == 0n).to.be.true;282 });283 });284382285 it('Unique rejects ACA tokens from Acala', async () => {383 it('Unique rejects ACA tokens from Acala', async () => {286 // This test is relevant only when the foreign asset pallet is disabled287288 await usingApi(async (api) => {384 await usingApi(async (api) => {289 const destination = {385 const destination = {295 {391 {296 AccountId32: {392 AccountId32: {297 network: 'Any',393 network: 'Any',298 id: randomAccount.addressRaw,394 id: alice.addressRaw,299 },395 },300 },396 },301 ],397 ],321417322 expect(418 expect(323 xcmpQueueFailEvent != null,419 xcmpQueueFailEvent != null,324 'Only native token is supported when the Foreign-Assets pallet is not connected',420 '[Acala] xcmpQueue.FailEvent event is expected',325 ).to.be.true;421 ).to.be.true;422423 const event = xcmpQueueFailEvent!.event;424 const outcome = event.data[1] as XcmV2TraitsError;425426 expect(427 outcome.isUntrustedReserveLocation,428 '[Acala] The XCM error should be `UntrustedReserveLocation`',429 ).to.be.true;326 });430 });327 });431 });328});432});