Skip to content

Commit cac39f5

Browse files
Merge pull request #7329 from BitGo/revert-7198-revert-WP-3968/fix/near-consolidation-blind-sign
Revert "fix(near): revert breaking consolidation verification logic"
2 parents e5bb0a8 + e269796 commit cac39f5

File tree

4 files changed

+464
-3
lines changed

4 files changed

+464
-3
lines changed

modules/sdk-coin-near/src/near.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -991,7 +991,7 @@ export class Near extends BaseCoin {
991991
async verifyTransaction(params: VerifyTransactionOptions): Promise<boolean> {
992992
let totalAmount = new BigNumber(0);
993993
const coinConfig = coins.get(this.getChain());
994-
const { txPrebuild: txPrebuild, txParams: txParams } = params;
994+
const { txPrebuild: txPrebuild, txParams: txParams, wallet } = params;
995995
const transaction = new Transaction(coinConfig);
996996
const rawTx = txPrebuild.txHex;
997997
if (!rawTx) {
@@ -1059,6 +1059,13 @@ export class Near extends BaseCoin {
10591059
}
10601060
}
10611061

1062+
if (params.verification?.consolidationToBaseAddress) {
1063+
if (!wallet?.coinSpecific()?.rootAddress) {
1064+
throw new Error('Unable to determine base address for consolidation');
1065+
}
1066+
await this.verifyConsolidationToBaseAddress(explainedTx, wallet.coinSpecific()?.rootAddress as string);
1067+
}
1068+
10621069
return true;
10631070
}
10641071

@@ -1277,4 +1284,15 @@ export class Near extends BaseCoin {
12771284
throw new Error(`Invalid transaction type on token enablement: expected "${expectedType}", got "${actualType}".`);
12781285
}
12791286
}
1287+
1288+
protected async verifyConsolidationToBaseAddress(
1289+
explainedTx: TransactionExplanation,
1290+
baseAddress: string
1291+
): Promise<void> {
1292+
for (const output of explainedTx.outputs) {
1293+
if (output.address !== baseAddress) {
1294+
throw new Error('tx outputs does not match with expected address');
1295+
}
1296+
}
1297+
}
12801298
}

modules/sdk-coin-near/src/nep141Token.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ export class Nep141Token extends Near {
6666
}
6767

6868
async verifyTransaction(params: VerifyTransactionOptions): Promise<boolean> {
69-
const { txPrebuild: txPrebuild, txParams: txParams } = params;
69+
const { txPrebuild: txPrebuild, txParams: txParams, wallet } = params;
7070
const rawTx = txPrebuild.txHex;
7171
let totalAmount = new BigNumber(0);
7272
if (!rawTx) {
@@ -105,6 +105,13 @@ export class Nep141Token extends Near {
105105
}
106106
}
107107

108+
if (params.verification?.consolidationToBaseAddress) {
109+
if (!wallet?.coinSpecific()?.rootAddress) {
110+
throw new Error('Unable to determine base address for consolidation');
111+
}
112+
await this.verifyConsolidationToBaseAddress(explainedTx, wallet.coinSpecific()?.rootAddress as string);
113+
}
114+
108115
return true;
109116
}
110117
}

modules/sdk-coin-near/test/unit/near.ts

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@ import { randomBytes } from 'crypto';
33
import should from 'should';
44
import _ from 'lodash';
55
import sinon from 'sinon';
6+
import nock from 'nock';
7+
import assert from 'assert';
68

79
import { BitGoAPI } from '@bitgo/sdk-api';
810
import { TestBitGo, TestBitGoAPI } from '@bitgo/sdk-test';
911
import { coins } from '@bitgo/statics';
12+
import { common, TransactionPrebuild, Wallet } from '@bitgo/sdk-core';
1013

1114
import { KeyPair, Near, TNear, Transaction } from '../../src';
1215
import nearUtils from '../../src/lib/utils';
@@ -422,6 +425,194 @@ describe('NEAR:', function () {
422425
const validTransaction = await basecoin.verifyTransaction({ txParams, txPrebuild });
423426
validTransaction.should.equal(true);
424427
});
428+
429+
it('should verify a spoofed consolidation transaction', async function () {
430+
// Set up wallet data
431+
const walletData = {
432+
id: '62e156dbd641c000076bbabe04041a90',
433+
coin: 'tnear',
434+
keys: [
435+
'5b3424f91bf349930e34017500000000',
436+
'5b3424f91bf349930e34017600000000',
437+
'5b3424f91bf349930e34017700000000',
438+
],
439+
coinSpecific: {
440+
rootAddress: '3a1b77653ea1705ad297db7abe259953b4ad5d2ecc5b50bee9a486f785dd90db',
441+
},
442+
multisigType: 'tss',
443+
};
444+
445+
const consolidationTx = {
446+
txRequestId: '03fdf51a-28e1-4268-b5be-a4afc030ff64',
447+
walletId: '62e156dbd641c000076bbabe',
448+
txHex:
449+
'400000006562376433623333313166616261653338393062363731383536343838383066663831383766353465623565626665343336646131313338333130396638623500eb7d3b3311fabae3890b67185648880ff8187f54eb5ebfe436da11383109f8b5c8a6d8a6f86100004000000061393465333937306165633436626262313536393331636130393065643735666633616164653439373966666566366437346337326435613234376365393466ad19fa7faa45643200f99a992715a02f9806bcbf0c5737ccdf5d61172d61a4f901000000030038bf94dd153d9d7fa7010000000000',
450+
feeInfo: {
451+
fee: 85332111947887500000,
452+
feeString: '85332111947887500377',
453+
},
454+
txInfo: {
455+
minerFee: '0',
456+
spendAmount: '1999915088987500000000000',
457+
spendAmounts: [
458+
{
459+
coinName: 'tnear',
460+
amountString: '1999915088987500000000000',
461+
},
462+
],
463+
payGoFee: '0',
464+
outputs: [
465+
{
466+
address: 'a94e3970aec46bbb156931ca090ed75ff3aade4979ffef6d74c72d5a247ce94f',
467+
value: 1.9999150889875e24,
468+
wallet: '62e156dbd641c000076bbabe',
469+
wallets: ['62e156dbd641c000076bbabe'],
470+
enterprise: '6111785f59548d0007a4d13c',
471+
enterprises: ['6111785f59548d0007a4d13c'],
472+
valueString: '1999915088987500000000000',
473+
coinName: 'tnear',
474+
walletType: 'hot',
475+
walletTypes: ['hot'],
476+
},
477+
],
478+
inputs: [
479+
{
480+
value: 1.9999150889875e24,
481+
address: 'eb7d3b3311fabae3890b67185648880ff8187f54eb5ebfe436da11383109f8b5',
482+
valueString: '1999915088987500000000000',
483+
},
484+
],
485+
type: '0',
486+
},
487+
consolidateId: '68ae77ec62346a69d0aee5a2dda69c8c',
488+
coin: 'tnear',
489+
};
490+
const bgUrl = common.Environments['mock'].uri;
491+
const walletObj = new Wallet(bitgo, basecoin, walletData);
492+
493+
nock(bgUrl)
494+
.post('/api/v2/tnear/wallet/62e156dbd641c000076bbabe04041a90/consolidateAccount/build')
495+
.reply(200, [
496+
{
497+
...consolidationTx,
498+
txHex:
499+
'400000006139346533393730616563343662626231353639333163613039306564373566663361616465343937396666656636643734633732643561323437636539346600a94e3970aec46bbb156931ca090ed75ff3aade4979ffef6d74c72d5a247ce94f1f3dec154a5700004000000066326137386638303336663861343266383730313962316431646336336131623337623139333365653632646464353365373438633530323266316435373961fb6130e6cc30c926fccde8043ce4e43a810ea63b4d3f93623a54176ff8db1cd001000000030000004a480114169545080000000000',
500+
},
501+
]);
502+
503+
nock(bgUrl)
504+
.get('/api/v2/tnear/key/5b3424f91bf349930e34017500000000')
505+
.reply(200, [
506+
{
507+
encryptedPrv: 'fakePrv',
508+
},
509+
]);
510+
511+
nock(bgUrl)
512+
.get('/api/v2/tnear/wallet/62e156dbd641c000076bbabe04041a90/addresses?sort=-1&limit=1')
513+
.reply(200, [
514+
{
515+
address: 'a94e3970aec46bbb156931ca090ed75ff3aade4979ffef6d74c72d5a247ce94f',
516+
},
517+
]);
518+
519+
// Call the function to test
520+
await assert.rejects(
521+
async () => {
522+
await walletObj.sendAccountConsolidations({
523+
walletPassphrase: 'password',
524+
verification: {
525+
consolidationToBaseAddress: true,
526+
},
527+
});
528+
},
529+
{
530+
message: 'tx outputs does not match with expected address',
531+
}
532+
);
533+
});
534+
535+
it('should verify valid a consolidation transaction', async () => {
536+
// Set up wallet data
537+
const walletData = {
538+
id: '62e156dbd641c000076bbabe04041a90',
539+
coin: 'tnear',
540+
keys: [
541+
'5b3424f91bf349930e34017500000000',
542+
'5b3424f91bf349930e34017600000000',
543+
'5b3424f91bf349930e34017700000000',
544+
],
545+
coinSpecific: {
546+
rootAddress: 'a94e3970aec46bbb156931ca090ed75ff3aade4979ffef6d74c72d5a247ce94f',
547+
},
548+
multisigType: 'tss',
549+
};
550+
551+
const consolidationTx = {
552+
txRequestId: '03fdf51a-28e1-4268-b5be-a4afc030ff64',
553+
walletId: '62e156dbd641c000076bbabe',
554+
txHex:
555+
'400000006562376433623333313166616261653338393062363731383536343838383066663831383766353465623565626665343336646131313338333130396638623500eb7d3b3311fabae3890b67185648880ff8187f54eb5ebfe436da11383109f8b5c8a6d8a6f86100004000000061393465333937306165633436626262313536393331636130393065643735666633616164653439373966666566366437346337326435613234376365393466ad19fa7faa45643200f99a992715a02f9806bcbf0c5737ccdf5d61172d61a4f901000000030038bf94dd153d9d7fa7010000000000',
556+
feeInfo: {
557+
fee: 85332111947887500000,
558+
feeString: '85332111947887500377',
559+
},
560+
txInfo: {
561+
minerFee: '0',
562+
spendAmount: '1999915088987500000000000',
563+
spendAmounts: [
564+
{
565+
coinName: 'tnear',
566+
amountString: '1999915088987500000000000',
567+
},
568+
],
569+
payGoFee: '0',
570+
outputs: [
571+
{
572+
address: 'a94e3970aec46bbb156931ca090ed75ff3aade4979ffef6d74c72d5a247ce94f',
573+
value: 1.9999150889875e24,
574+
wallet: '62e156dbd641c000076bbabe',
575+
wallets: ['62e156dbd641c000076bbabe'],
576+
enterprise: '6111785f59548d0007a4d13c',
577+
enterprises: ['6111785f59548d0007a4d13c'],
578+
valueString: '1999915088987500000000000',
579+
coinName: 'tnear',
580+
walletType: 'hot',
581+
walletTypes: ['hot'],
582+
},
583+
],
584+
inputs: [
585+
{
586+
value: 1.9999150889875e24,
587+
address: 'eb7d3b3311fabae3890b67185648880ff8187f54eb5ebfe436da11383109f8b5',
588+
valueString: '1999915088987500000000000',
589+
},
590+
],
591+
type: '0',
592+
},
593+
consolidateId: '68ae77ec62346a69d0aee5a2dda69c8c',
594+
coin: 'tnear',
595+
};
596+
try {
597+
if (
598+
!(await basecoin.verifyTransaction({
599+
blockhash: '',
600+
feePayer: '',
601+
txParams: {},
602+
txPrebuild: consolidationTx as unknown as TransactionPrebuild,
603+
walletType: 'tss',
604+
wallet: new Wallet(bitgo, basecoin, walletData),
605+
verification: {
606+
consolidationToBaseAddress: true,
607+
},
608+
}))
609+
) {
610+
assert.fail('Transaction should pass verification');
611+
}
612+
} catch (e) {
613+
assert.fail('Transaction should pass verification');
614+
}
615+
});
425616
});
426617

427618
describe('Explain Transactions:', () => {

0 commit comments

Comments
 (0)