Skip to content

Commit 3be12f4

Browse files
committed
test(sdk-coin-near): add spoofed TxHex security tests
Add tests for sendTokenEnablements and sendAccountConsolidations TICKET: WP-5782
1 parent 5bb4397 commit 3be12f4

File tree

1 file changed

+200
-0
lines changed

1 file changed

+200
-0
lines changed

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

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,4 +222,204 @@ describe('NEAR Token Enablement Validation', function () {
222222
// should pass validation and be processed successfully
223223
await basecoin.verifyTransaction(verifyOptions);
224224
});
225+
226+
/**
227+
* TEST 6: Security Test - sendTokenEnablements with Spoofed TxHex
228+
*
229+
* This test simulates what happens when the wallet platform's sendTokenEnablements
230+
* method receives a spoofed TxHex from a malicious actor. This test verifies that
231+
* our validation catches the spoofed transaction and prevents the user from being tricked.
232+
*
233+
* The test simulates the flow where:
234+
* 1. Wallet platform calls sendTokenEnablements
235+
* 2. buildTokenEnablements returns a spoofed transaction hex
236+
* 3. sendTokenEnablement calls verifyTransaction during signing
237+
* 4. verifyTransaction detects the spoofed hex and throws an error
238+
*/
239+
it('should throw error when sendTokenEnablements receives spoofed TxHex', async function () {
240+
// Create a mock wallet that implements the sendTokenEnablements flow
241+
const mockWallet = {
242+
id: () => 'test-wallet',
243+
bitgo: bitgo,
244+
baseCoin: basecoin,
245+
246+
// Mock buildTokenEnablements to return a spoofed transaction hex
247+
buildTokenEnablements: async (params: any) => {
248+
return [
249+
{
250+
txHex: testData.rawTx.fungibleTokenTransfer.unsigned, // SPOOFED: This is a transfer, not storage deposit
251+
key: 'test-key',
252+
blockHash: 'test-block-hash',
253+
nonce: BigInt(1),
254+
txParams: {
255+
type: 'enabletoken',
256+
recipients: [
257+
{
258+
address: testData.accounts.account1.address,
259+
amount: '0',
260+
tokenName: 'tnear:tnep24dp',
261+
},
262+
],
263+
},
264+
},
265+
];
266+
},
267+
268+
// Mock sendTokenEnablement to simulate the signing process with verification
269+
sendTokenEnablement: async (params: any) => {
270+
// This is where verifyTransaction would be called during signing
271+
// The spoofed hex should cause verification to fail
272+
const verifyOptions: VerifyTransactionOptions = {
273+
txParams: params.txParams,
274+
txPrebuild: params.prebuildTx,
275+
wallet: mockWallet as any,
276+
};
277+
278+
// This should throw an error because the hex is spoofed
279+
await basecoin.verifyTransaction(verifyOptions);
280+
return { success: true };
281+
},
282+
283+
// Implement the actual sendTokenEnablements method
284+
sendTokenEnablements: async (params: any) => {
285+
const unsignedBuilds = await mockWallet.buildTokenEnablements(params);
286+
const successfulTxs: any[] = [];
287+
const failedTxs = new Array<Error>();
288+
289+
for (const unsignedBuild of unsignedBuilds) {
290+
const unsignedBuildWithOptions = {
291+
...params,
292+
prebuildTx: unsignedBuild,
293+
txParams: unsignedBuild.txParams,
294+
};
295+
try {
296+
const sendTx = await mockWallet.sendTokenEnablement(unsignedBuildWithOptions);
297+
successfulTxs.push(sendTx);
298+
} catch (e) {
299+
failedTxs.push(e);
300+
}
301+
}
302+
303+
return {
304+
success: successfulTxs,
305+
failure: failedTxs,
306+
};
307+
},
308+
};
309+
310+
// Create token enablement parameters
311+
const enableTokensParams = {
312+
enableTokens: [
313+
{
314+
name: 'tnear:tnep24dp',
315+
},
316+
],
317+
};
318+
319+
// Call sendTokenEnablements - this should fail because of the spoofed hex
320+
const result = await mockWallet.sendTokenEnablements(enableTokensParams);
321+
322+
// The result should contain failures due to the spoofed transaction hex
323+
result.success.should.have.length(0);
324+
result.failure.should.have.length(1);
325+
result.failure[0].message.should.containEql('Storage deposit amount not matching!');
326+
});
327+
328+
/**
329+
* TEST 7: Security Test - sendAccountConsolidations with Spoofed TxHex
330+
*
331+
* This test simulates what happens when the wallet platform's sendAccountConsolidations
332+
* method receives a spoofed TxHex from a malicious actor. This test verifies that
333+
* our validation catches the spoofed transaction and prevents the user from being tricked.
334+
*
335+
* The test simulates the flow where:
336+
* 1. Wallet platform calls sendAccountConsolidations
337+
* 2. buildAccountConsolidations returns a spoofed transaction hex
338+
* 3. sendAccountConsolidation calls verifyTransaction during signing
339+
* 4. verifyTransaction detects the spoofed hex and throws an error
340+
*/
341+
it('should throw error when sendAccountConsolidations receives spoofed TxHex', async function () {
342+
// Create a mock wallet that implements the sendAccountConsolidations flow
343+
const mockWallet = {
344+
id: () => 'test-wallet',
345+
bitgo: bitgo,
346+
baseCoin: basecoin,
347+
348+
// Mock buildAccountConsolidations to return a spoofed transaction hex
349+
buildAccountConsolidations: async (params: any) => {
350+
return [
351+
{
352+
txHex: testData.rawTx.fungibleTokenTransfer.unsigned, // SPOOFED: This is a transfer, not consolidation
353+
key: 'test-key',
354+
blockHash: 'test-block-hash',
355+
nonce: BigInt(1),
356+
txParams: {
357+
type: 'consolidate',
358+
recipients: [
359+
{
360+
address: testData.accounts.account1.address,
361+
amount: '1000000',
362+
},
363+
],
364+
},
365+
},
366+
];
367+
},
368+
369+
// Mock sendAccountConsolidation to simulate the signing process with verification
370+
sendAccountConsolidation: async (params: any) => {
371+
// This is where verifyTransaction would be called during signing
372+
// The spoofed hex should cause verification to fail
373+
const verifyOptions: VerifyTransactionOptions = {
374+
txParams: params.txParams,
375+
txPrebuild: params.prebuildTx,
376+
wallet: mockWallet as any,
377+
};
378+
379+
// This should throw an error because the hex is spoofed
380+
await basecoin.verifyTransaction(verifyOptions);
381+
return { success: true };
382+
},
383+
384+
// Implement the actual sendAccountConsolidations method
385+
sendAccountConsolidations: async (params: any) => {
386+
const unsignedBuilds = await mockWallet.buildAccountConsolidations(params);
387+
const successfulTxs: any[] = [];
388+
const failedTxs = new Array<Error>();
389+
390+
for (const unsignedBuild of unsignedBuilds) {
391+
const unsignedBuildWithOptions = {
392+
...params,
393+
prebuildTx: unsignedBuild,
394+
txParams: unsignedBuild.txParams,
395+
};
396+
try {
397+
const sendTx = await mockWallet.sendAccountConsolidation(unsignedBuildWithOptions);
398+
successfulTxs.push(sendTx);
399+
} catch (e) {
400+
failedTxs.push(e);
401+
}
402+
}
403+
404+
return {
405+
success: successfulTxs,
406+
failure: failedTxs,
407+
};
408+
},
409+
};
410+
411+
// Create account consolidation parameters
412+
const consolidationParams = {
413+
consolidateAddresses: [testData.accounts.account2.address],
414+
};
415+
416+
// Call sendAccountConsolidations - this should fail because of the spoofed hex
417+
const result = await mockWallet.sendAccountConsolidations(consolidationParams);
418+
419+
// The result should contain failures due to the spoofed transaction hex
420+
result.success.should.have.length(0);
421+
result.failure.should.have.length(1);
422+
// The error should be related to transaction output mismatch since it's a different transaction type
423+
result.failure[0].message.should.containEql('Tx outputs does not match with expected txParams recipients');
424+
});
225425
});

0 commit comments

Comments
 (0)