Skip to content

Commit 577c6c6

Browse files
fix(sdk-coin-sui): verify consolidation txHex
- verify platform built consolidaiton hexs send funds to root address of wallet - test case to verify spoofed transactions are caught TICKET: WP-5727
1 parent bd24111 commit 577c6c6

File tree

2 files changed

+195
-1
lines changed

2 files changed

+195
-1
lines changed

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ export class Sui extends BaseCoin {
141141
async verifyTransaction(params: VerifyTransactionOptions): Promise<boolean> {
142142
let totalAmount = new BigNumber(0);
143143
const coinConfig = coins.get(this.getChain());
144-
const { txPrebuild: txPrebuild, txParams: txParams } = params;
144+
const { txPrebuild: txPrebuild, txParams: txParams, verification, wallet } = params;
145145
const transaction = new TransferTransaction(coinConfig);
146146
const rawTx = txPrebuild.txHex;
147147
if (!rawTx) {
@@ -173,6 +173,17 @@ export class Sui extends BaseCoin {
173173
throw new Error('Tx total amount does not match with expected total amount field');
174174
}
175175
}
176+
177+
if (verification?.consolidationToBaseAddress) {
178+
const baseAddress = wallet.coinSpecific()?.baseAddress || wallet.coinSpecific()?.rootAddress;
179+
180+
for (const output of explainedTx.outputs) {
181+
if (output.address !== baseAddress) {
182+
throw new Error('Consolidation transaction output address does not match wallet base address');
183+
}
184+
}
185+
}
186+
176187
return true;
177188
}
178189

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

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import { SuiTransactionType } from '../../src/lib/iface';
1212
import { getBuilderFactory } from './getBuilderFactory';
1313
import { keys } from '../resources/sui';
1414
import { Buffer } from 'buffer';
15+
import { common, TransactionPrebuild, Wallet } from '@bitgo/sdk-core';
16+
import nock from 'nock';
1517

1618
describe('SUI:', function () {
1719
let bitgo: TestBitGoAPI;
@@ -117,6 +119,187 @@ describe('SUI:', function () {
117119
});
118120
verify.should.equal(true);
119121
});
122+
123+
it('should fail to verify a spoofed consolidation transaction', async function () {
124+
// Set up wallet data
125+
const walletData = {
126+
id: '62e156dbd641c000076bbabe04041a90',
127+
coin: 'tsui',
128+
keys: [
129+
'5b3424f91bf349930e34017500000000',
130+
'5b3424f91bf349930e34017600000000',
131+
'5b3424f91bf349930e34017700000000',
132+
],
133+
coinSpecific: {
134+
rootAddress: '0x6f0f4e0eef19176628ee0ebc80eef89194afd9e19e59444e64b997f1254f6cd8',
135+
},
136+
multisigType: 'tss',
137+
};
138+
139+
const consolidationTx = {
140+
txRequestId: '13857c1a-9b61-4b85-96f1-10af125f68a0',
141+
walletId: '644c3d6c5232f00007680040',
142+
txHex:
143+
'0000020008e6e6753b0000000000206f0f4e0eef19176628ee0ebc80eef89194afd9e19e59444e64b997f1254f6cd80202000101000001010200000101001670472c44b59058032840b94a7fd7405b4b87cbf67f4eb60e1b7781ce03ddad01222b818b450dcd2164b25ba5a57b0507e59a4c8eb6d7cadd08ea609db17c611d4e12d014000000002023fc27576626762904339b0abe1ff99c99799c93bea46e8bf452f23c68992db11670472c44b59058032840b94a7fd7405b4b87cbf67f4eb60e1b7781ce03ddade8030000000000001ae324000000000000',
144+
feeInfo: {
145+
fee: 2417434,
146+
feeString: '2417434',
147+
},
148+
txInfo: {
149+
minerFee: '2417434',
150+
spendAmount: '997582566',
151+
spendAmounts: [
152+
{
153+
coinName: 'tsui',
154+
amountString: '997582566',
155+
},
156+
],
157+
payGoFee: '0',
158+
outputs: [
159+
{
160+
address: '0x6f0f4e0eef19176628ee0ebc80eef89194afd9e19e59444e64b997f1254f6cd8',
161+
value: 997582566,
162+
wallet: '644c3d6c5232f00007680040',
163+
wallets: ['644c3d6c5232f00007680040'],
164+
enterprise: '62cc59b727443a0007089033',
165+
enterprises: ['62cc59b727443a0007089033'],
166+
valueString: '997582566',
167+
coinName: 'tsui',
168+
walletType: 'hot',
169+
walletTypes: ['hot'],
170+
},
171+
],
172+
inputs: [
173+
{
174+
value: 997582566,
175+
address: '0x1670472c44b59058032840b94a7fd7405b4b87cbf67f4eb60e1b7781ce03ddad',
176+
valueString: '997582566',
177+
},
178+
],
179+
type: 'Transfer',
180+
},
181+
consolidateId: '68b648892ee9355c97e4b96d0945b2ca',
182+
coin: 'tsui',
183+
};
184+
const bgUrl = common.Environments['mock'].uri;
185+
const walletObj = new Wallet(bitgo, basecoin, walletData);
186+
187+
nock(bgUrl)
188+
.post('/api/v2/tsui/wallet/62e156dbd641c000076bbabe04041a90/consolidateAccount/build')
189+
.reply(200, [
190+
{
191+
...consolidationTx,
192+
txHex:
193+
'000002000800e1f5050000000000208771273969acf0356ed0f33c1c52b109bbfe0de3369e9fb9837d52a5a438c6500202000101000001010200000101006f0f4e0eef19176628ee0ebc80eef89194afd9e19e59444e64b997f1254f6cd80122de95b31347a2f0d9715c560dfdfc8fd351782ca5e275d4bc3a98ea78769bce4f12d0140000000020ea639081929603fe2580873f4aa64701746d089f973b0827a222d784e992ee266f0f4e0eef19176628ee0ebc80eef89194afd9e19e59444e64b997f1254f6cd8e803000000000000a48821000000000000',
194+
},
195+
]);
196+
197+
nock(bgUrl)
198+
.get('/api/v2/tsui/key/5b3424f91bf349930e34017500000000')
199+
.reply(200, [
200+
{
201+
encryptedPrv: 'fakePrv',
202+
},
203+
]);
204+
205+
// Call the function to test
206+
await assert.rejects(
207+
async () => {
208+
await walletObj.sendAccountConsolidations({
209+
walletPassphrase: 'password',
210+
verification: {
211+
consolidationToBaseAddress: true,
212+
},
213+
});
214+
},
215+
{
216+
message: 'Consolidation transaction output address does not match wallet base address',
217+
}
218+
);
219+
});
220+
221+
it('should verify valid a consolidation transaction', async () => {
222+
// Set up wallet data
223+
const walletData = {
224+
id: '62e156dbd641c000076bbabe04041a90',
225+
coin: 'tsui',
226+
keys: [
227+
'5b3424f91bf349930e34017500000000',
228+
'5b3424f91bf349930e34017600000000',
229+
'5b3424f91bf349930e34017700000000',
230+
],
231+
coinSpecific: {
232+
rootAddress: '0x6f0f4e0eef19176628ee0ebc80eef89194afd9e19e59444e64b997f1254f6cd8',
233+
},
234+
multisigType: 'tss',
235+
};
236+
237+
const consolidationTx = {
238+
txRequestId: '13857c1a-9b61-4b85-96f1-10af125f68a0',
239+
walletId: '644c3d6c5232f00007680040',
240+
txHex:
241+
'0000020008e6e6753b0000000000206f0f4e0eef19176628ee0ebc80eef89194afd9e19e59444e64b997f1254f6cd80202000101000001010200000101001670472c44b59058032840b94a7fd7405b4b87cbf67f4eb60e1b7781ce03ddad01222b818b450dcd2164b25ba5a57b0507e59a4c8eb6d7cadd08ea609db17c611d4e12d014000000002023fc27576626762904339b0abe1ff99c99799c93bea46e8bf452f23c68992db11670472c44b59058032840b94a7fd7405b4b87cbf67f4eb60e1b7781ce03ddade8030000000000001ae324000000000000',
242+
feeInfo: {
243+
fee: 2417434,
244+
feeString: '2417434',
245+
},
246+
txInfo: {
247+
minerFee: '2417434',
248+
spendAmount: '997582566',
249+
spendAmounts: [
250+
{
251+
coinName: 'tsui',
252+
amountString: '997582566',
253+
},
254+
],
255+
payGoFee: '0',
256+
outputs: [
257+
{
258+
address: '0x6f0f4e0eef19176628ee0ebc80eef89194afd9e19e59444e64b997f1254f6cd8',
259+
value: 997582566,
260+
wallet: '644c3d6c5232f00007680040',
261+
wallets: ['644c3d6c5232f00007680040'],
262+
enterprise: '62cc59b727443a0007089033',
263+
enterprises: ['62cc59b727443a0007089033'],
264+
valueString: '997582566',
265+
coinName: 'tsui',
266+
walletType: 'hot',
267+
walletTypes: ['hot'],
268+
},
269+
],
270+
inputs: [
271+
{
272+
value: 997582566,
273+
address: '0x1670472c44b59058032840b94a7fd7405b4b87cbf67f4eb60e1b7781ce03ddad',
274+
valueString: '997582566',
275+
},
276+
],
277+
type: 'Transfer',
278+
},
279+
consolidateId: '68b648892ee9355c97e4b96d0945b2ca',
280+
coin: 'tsui',
281+
};
282+
283+
try {
284+
if (
285+
!(await basecoin.verifyTransaction({
286+
blockhash: '',
287+
feePayer: '',
288+
txParams: {},
289+
txPrebuild: consolidationTx as unknown as TransactionPrebuild,
290+
walletType: 'tss',
291+
wallet: new Wallet(bitgo, basecoin, walletData),
292+
verification: {
293+
consolidationToBaseAddress: true,
294+
},
295+
}))
296+
) {
297+
assert.fail('Transaction should pass verification');
298+
}
299+
} catch (e) {
300+
assert.fail('Transaction should pass verification');
301+
}
302+
});
120303
});
121304

122305
describe('Explain Transaction: ', () => {

0 commit comments

Comments
 (0)