Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion modules/sdk-coin-xrp/src/xrp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,12 @@ export class Xrp extends BaseCoin {
const expectedOutput = txParams.recipients && txParams.recipients[0];

const comparator = (recipient1, recipient2) => {
if (utils.getAddressDetails(recipient1.address).address !== utils.getAddressDetails(recipient2.address).address) {
const r1Details = utils.getAddressDetails(recipient1.address);
const r2Details = utils.getAddressDetails(recipient2.address);
if (r1Details.address !== r2Details.address) {
return false;
}
if (r1Details.destinationTag !== r2Details.destinationTag) {
return false;
}
const amount1 = new BigNumber(recipient1.amount);
Expand Down
72 changes: 72 additions & 0 deletions modules/sdk-coin-xrp/test/unit/xrp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -920,6 +920,78 @@ describe('XRP:', function () {
});
});

describe('verifyTransaction destination tag enforcement', () => {
// txHex for: Payment from rBSpCz8PafXTJHppDcNnex7dYnbe3tSuFG to rfjub8A4dpSD5nnszUFTsLprxu1W398jwc
// DestinationTag: 0, Amount: 253481 drops
const txHexWithDt0 =
'{"TransactionType":"Payment","Account":"rBSpCz8PafXTJHppDcNnex7dYnbe3tSuFG","Destination":"rfjub8A4dpSD5nnszUFTsLprxu1W398jwc","DestinationTag":0,"Amount":"253481","Flags":2147483648,"LastLedgerSequence":1626225,"Fee":"45","Sequence":7}';
// txHex for: same but DestinationTag: 42
const txHexWithDt42 =
'{"TransactionType":"Payment","Account":"rBSpCz8PafXTJHppDcNnex7dYnbe3tSuFG","Destination":"rfjub8A4dpSD5nnszUFTsLprxu1W398jwc","DestinationTag":42,"Amount":"253481","Flags":2147483648,"LastLedgerSequence":1626225,"Fee":"45","Sequence":7}';
// txHex for: same but no DestinationTag
const txHexNoDt =
'{"TransactionType":"Payment","Account":"rBSpCz8PafXTJHppDcNnex7dYnbe3tSuFG","Destination":"rfjub8A4dpSD5nnszUFTsLprxu1W398jwc","Amount":"253481","Flags":2147483648,"LastLedgerSequence":1626225,"Fee":"45","Sequence":7}';

it('should pass when transaction and recipient both have matching destination tag', async function () {
const result = await basecoin.verifyTransaction({
txParams: {
recipients: [{ address: 'rfjub8A4dpSD5nnszUFTsLprxu1W398jwc?dt=0', amount: '253481' }],
},
txPrebuild: { txHex: txHexWithDt0 },
});
result.should.equal(true);
});

it('should pass when transaction and recipient both have no destination tag', async function () {
const result = await basecoin.verifyTransaction({
txParams: {
recipients: [{ address: 'rfjub8A4dpSD5nnszUFTsLprxu1W398jwc', amount: '253481' }],
},
txPrebuild: { txHex: txHexNoDt },
});
result.should.equal(true);
});

it('should reject when transaction has destination tag 0 but recipient has no destination tag', async function () {
await assert.rejects(
async () =>
basecoin.verifyTransaction({
txParams: {
recipients: [{ address: 'rfjub8A4dpSD5nnszUFTsLprxu1W398jwc', amount: '253481' }],
},
txPrebuild: { txHex: txHexWithDt0 },
}),
{ message: 'transaction prebuild does not match expected output' }
);
});

it('should reject when transaction has no destination tag but recipient has destination tag 0', async function () {
await assert.rejects(
async () =>
basecoin.verifyTransaction({
txParams: {
recipients: [{ address: 'rfjub8A4dpSD5nnszUFTsLprxu1W398jwc?dt=0', amount: '253481' }],
},
txPrebuild: { txHex: txHexNoDt },
}),
{ message: 'transaction prebuild does not match expected output' }
);
});

it('should reject when transaction has destination tag 42 but recipient has destination tag 0', async function () {
await assert.rejects(
async () =>
basecoin.verifyTransaction({
txParams: {
recipients: [{ address: 'rfjub8A4dpSD5nnszUFTsLprxu1W398jwc?dt=0', amount: '253481' }],
},
txPrebuild: { txHex: txHexWithDt42 },
}),
{ message: 'transaction prebuild does not match expected output' }
);
});
});

describe('blind signing token enablement protection', () => {
it('should verify as valid the enabletoken intent when prebuild tx matchs user intent ', async function () {
const { txParams, txPrebuildRaw, walletData } = testData.enableTokenFixtures;
Expand Down
Loading