Skip to content

Commit 91829d6

Browse files
feat(sdk-coin-algo): verify consolidation transaction
Implement verification to ensure consolidation transactions send funds to the wallet's base address (rootAddress). This prevents malicious transactions from redirecting consolidated funds to unauthorized addresses. Changes: - Add consolidationToBaseAddress verification in verifyTransaction method - Verify transaction recipient matches wallet rootAddress for both native (pay) and token (axfer) transactions - Test both positive (valid consolidation) and negative (malicious) cases The verification is triggered when params.verification.consolidationToBaseAddress is set to true, which happens automatically in sendAccountConsolidations. Ticket: WP-5729 TICKET: WP-5729
1 parent 64a2c84 commit 91829d6

File tree

3 files changed

+507
-4
lines changed

3 files changed

+507
-4
lines changed

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

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import {
3030
MultisigType,
3131
multisigTypes,
3232
AuditDecryptedKeyParams,
33+
TxIntentMismatchError,
3334
} from '@bitgo/sdk-core';
3435
import stellar from 'stellar-sdk';
3536
import BigNumber from 'bignumber.js';
@@ -580,7 +581,7 @@ export class Algo extends BaseCoin {
580581
}
581582

582583
async verifyTransaction(params: VerifyTransactionOptions): Promise<boolean> {
583-
const { txParams, txPrebuild } = params;
584+
const { txParams, txPrebuild, wallet, verification } = params;
584585

585586
if (!txParams) {
586587
throw new Error('missing txParams');
@@ -602,14 +603,40 @@ export class Algo extends BaseCoin {
602603
// Validate based on Algorand transaction type
603604
switch (txJson.type) {
604605
case 'pay':
605-
return this.validatePayTransaction(txJson, txParams);
606+
this.validatePayTransaction(txJson, txParams);
607+
break;
606608
case 'axfer':
607-
return this.validateAssetTransferTransaction(txJson, txParams);
609+
this.validateAssetTransferTransaction(txJson, txParams);
610+
break;
608611
default:
609612
// For other transaction types, perform basic validation
610613
this.validateBasicTransaction(txJson);
611-
return true;
614+
break;
612615
}
616+
617+
// Verify consolidation transactions send to base address
618+
if (verification?.consolidationToBaseAddress) {
619+
if (!wallet?.coinSpecific()?.rootAddress) {
620+
throw new Error('Unable to determine base address for consolidation');
621+
}
622+
const rootAddress = wallet.coinSpecific()?.rootAddress as string;
623+
624+
// Verify the transaction recipient matches the rootAddress
625+
if (!txJson.to) {
626+
throw new Error('Transaction is missing recipient address');
627+
}
628+
629+
if (txJson.to !== rootAddress) {
630+
throw new TxIntentMismatchError(
631+
'Consolidation transaction recipient does not match wallet base address',
632+
txJson.to,
633+
[txParams],
634+
txJson
635+
);
636+
}
637+
}
638+
639+
return true;
613640
}
614641

615642
/**

modules/sdk-coin-algo/test/fixtures/resources.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,13 @@ export const base64Txn = {
132132
txid: 'RSWDVNXWLX7UEDVGJR7B7SSCL3Q43UILPYIEX2AMDD72JIFV7TVA',
133133
},
134134
} as const;
135+
136+
export const consolidation = {
137+
// Real consolidation transaction from account-consolidation-build
138+
rootAddress: 'L6OMQGFVXSDOCEXVB3FFRBYUD3FH6UFMT6WNTFYDJXGEV6ZDQ74EXGF6BE',
139+
receiveAddress: 'U3YYPVGS7MOEPLAMOEBQYMQL6K6OG6VA5CL4RGMPXQTMWEWHBSN2RYS774',
140+
txHex:
141+
'iaNhbXTOAJcL+KNmZWXNA+iiZnbOA2bxbqNnZW6sdGVzdG5ldC12MS4womdoxCBIY7UYpLPITsgQ8i1PEIHLD3HwWaesIN7GL39w5Qk6IqJsds4DZvVWo3JjdsQgX5zIGLW8huES9Q7KWIcUHsp/UKyfrNmXA03MSvsjh/ijc25kxCCm8YfU0vscR6wMcQMMMgvyvON6oOiXyJmPvCbLEscMm6R0eXBlo3BheQ==',
142+
amount: '9899000',
143+
txId: 'ROTFDRSEAWKSYIOBE6PKX5TVZIYKRFWEN4PET54ODY3RDMRCMMQA',
144+
} as const;

0 commit comments

Comments
 (0)