@@ -28,6 +28,7 @@ import {
2828 PresignTransactionOptions as BasePresignTransactionOptions ,
2929 Recipient ,
3030 SignTransactionOptions as BaseSignTransactionOptions ,
31+ TxIntentMismatchError ,
3132 TransactionParams ,
3233 TransactionPrebuild as BaseTransactionPrebuild ,
3334 TransactionRecipient ,
@@ -2767,6 +2768,7 @@ export abstract class AbstractEthLikeNewCoins extends AbstractEthLikeCoin {
27672768 * @param {TransactionPrebuild } params.txPrebuild - prebuild object returned by server
27682769 * @param {Wallet } params.wallet - Wallet object to obtain keys to verify against
27692770 * @returns {boolean }
2771+ * @throws {TxIntentMismatchError } if transaction validation fails
27702772 */
27712773 async verifyTssTransaction ( params : VerifyEthTransactionOptions ) : Promise < boolean > {
27722774 const { txParams, txPrebuild, wallet } = params ;
@@ -2777,13 +2779,18 @@ export abstract class AbstractEthLikeNewCoins extends AbstractEthLikeCoin {
27772779 ( txParams . type && [ 'acceleration' , 'fillNonce' , 'transferToken' , 'tokenApproval' ] . includes ( txParams . type ) )
27782780 )
27792781 ) {
2780- throw new Error ( `missing txParams` ) ;
2782+ throw new TxIntentMismatchError ( `missing txParams` , '' , [ txParams ] , txPrebuild ?. txHex || '' ) ;
27812783 }
27822784 if ( ! wallet || ! txPrebuild ) {
2783- throw new Error ( `missing params` ) ;
2785+ throw new TxIntentMismatchError ( `missing params` , '' , [ txParams ] , txPrebuild ?. txHex || '' ) ;
27842786 }
27852787 if ( txParams . hop && txParams . recipients && txParams . recipients . length > 1 ) {
2786- throw new Error ( `tx cannot be both a batch and hop transaction` ) ;
2788+ throw new TxIntentMismatchError (
2789+ `tx cannot be both a batch and hop transaction` ,
2790+ '' ,
2791+ [ txParams ] ,
2792+ txPrebuild . txHex || ''
2793+ ) ;
27872794 }
27882795
27892796 if ( txParams . type && [ 'transfer' ] . includes ( txParams . type ) ) {
@@ -2798,21 +2805,41 @@ export abstract class AbstractEthLikeNewCoins extends AbstractEthLikeCoin {
27982805 const txJson = tx . toJson ( ) ;
27992806 if ( txJson . data === '0x' ) {
28002807 if ( expectedAmount !== txJson . value ) {
2801- throw new Error ( 'the transaction amount in txPrebuild does not match the value given by client' ) ;
2808+ throw new TxIntentMismatchError (
2809+ 'the transaction amount in txPrebuild does not match the value given by client' ,
2810+ '' ,
2811+ [ txParams ] ,
2812+ txPrebuild . txHex || ''
2813+ ) ;
28022814 }
28032815 if ( expectedDestination . toLowerCase ( ) !== txJson . to . toLowerCase ( ) ) {
2804- throw new Error ( 'destination address does not match with the recipient address' ) ;
2816+ throw new TxIntentMismatchError (
2817+ 'destination address does not match with the recipient address' ,
2818+ '' ,
2819+ [ txParams ] ,
2820+ txPrebuild . txHex || ''
2821+ ) ;
28052822 }
28062823 } else if ( txJson . data . startsWith ( '0xa9059cbb' ) ) {
28072824 const [ recipientAddress , amount ] = getRawDecoded (
28082825 [ 'address' , 'uint256' ] ,
28092826 getBufferedByteCode ( '0xa9059cbb' , txJson . data )
28102827 ) ;
28112828 if ( expectedAmount !== amount . toString ( ) ) {
2812- throw new Error ( 'the transaction amount in txPrebuild does not match the value given by client' ) ;
2829+ throw new TxIntentMismatchError (
2830+ 'the transaction amount in txPrebuild does not match the value given by client' ,
2831+ '' ,
2832+ [ txParams ] ,
2833+ txPrebuild . txHex || ''
2834+ ) ;
28132835 }
28142836 if ( expectedDestination . toLowerCase ( ) !== addHexPrefix ( recipientAddress . toString ( ) ) . toLowerCase ( ) ) {
2815- throw new Error ( 'destination address does not match with the recipient address' ) ;
2837+ throw new TxIntentMismatchError (
2838+ 'destination address does not match with the recipient address' ,
2839+ '' ,
2840+ [ txParams ] ,
2841+ txPrebuild . txHex || ''
2842+ ) ;
28162843 }
28172844 }
28182845 }
@@ -2829,6 +2856,7 @@ export abstract class AbstractEthLikeNewCoins extends AbstractEthLikeCoin {
28292856 * @param {TransactionPrebuild } params.txPrebuild - prebuild object returned by server
28302857 * @param {Wallet } params.wallet - Wallet object to obtain keys to verify against
28312858 * @returns {boolean }
2859+ * @throws {TxIntentMismatchError } if transaction validation fails
28322860 */
28332861 async verifyTransaction ( params : VerifyEthTransactionOptions ) : Promise < boolean > {
28342862 const ethNetwork = this . getNetwork ( ) ;
@@ -2839,20 +2867,33 @@ export abstract class AbstractEthLikeNewCoins extends AbstractEthLikeCoin {
28392867 }
28402868
28412869 if ( ! txParams ?. recipients || ! txPrebuild ?. recipients || ! wallet ) {
2842- throw new Error ( `missing params` ) ;
2870+ throw new TxIntentMismatchError ( `missing params` , '' , [ txParams ] , txPrebuild ?. txHex || '' ) ;
28432871 }
28442872 if ( txParams . hop && txParams . recipients . length > 1 ) {
2845- throw new Error ( `tx cannot be both a batch and hop transaction` ) ;
2873+ throw new TxIntentMismatchError (
2874+ `tx cannot be both a batch and hop transaction` ,
2875+ '' ,
2876+ [ txParams ] ,
2877+ txPrebuild . txHex || ''
2878+ ) ;
28462879 }
28472880 if ( txPrebuild . recipients . length > 1 ) {
2848- throw new Error (
2849- `${ this . getChain ( ) } doesn't support sending to more than 1 destination address within a single transaction. Try again, using only a single recipient.`
2881+ throw new TxIntentMismatchError (
2882+ `${ this . getChain ( ) } doesn't support sending to more than 1 destination address within a single transaction. Try again, using only a single recipient.` ,
2883+ '' ,
2884+ [ txParams ] ,
2885+ txPrebuild . txHex || ''
28502886 ) ;
28512887 }
28522888 if ( txParams . hop && txPrebuild . hopTransaction ) {
28532889 // Check recipient amount for hop transaction
28542890 if ( txParams . recipients . length !== 1 ) {
2855- throw new Error ( `hop transaction only supports 1 recipient but ${ txParams . recipients . length } found` ) ;
2891+ throw new TxIntentMismatchError (
2892+ `hop transaction only supports 1 recipient but ${ txParams . recipients . length } found` ,
2893+ '' ,
2894+ [ txParams ] ,
2895+ txPrebuild . txHex || ''
2896+ ) ;
28562897 }
28572898
28582899 // Check tx sends to hop address
@@ -2862,7 +2903,12 @@ export abstract class AbstractEthLikeNewCoins extends AbstractEthLikeCoin {
28622903 const expectedHopAddress = optionalDeps . ethUtil . stripHexPrefix ( decodedHopTx . getSenderAddress ( ) . toString ( ) ) ;
28632904 const actualHopAddress = optionalDeps . ethUtil . stripHexPrefix ( txPrebuild . recipients [ 0 ] . address ) ;
28642905 if ( expectedHopAddress . toLowerCase ( ) !== actualHopAddress . toLowerCase ( ) ) {
2865- throw new Error ( 'recipient address of txPrebuild does not match hop address' ) ;
2906+ throw new TxIntentMismatchError (
2907+ 'recipient address of txPrebuild does not match hop address' ,
2908+ '' ,
2909+ [ txParams ] ,
2910+ txPrebuild . txHex || ''
2911+ ) ;
28662912 }
28672913
28682914 // Convert TransactionRecipient array to Recipient array
@@ -2880,16 +2926,24 @@ export abstract class AbstractEthLikeNewCoins extends AbstractEthLikeCoin {
28802926 if ( txParams . tokenName ) {
28812927 const expectedTotalAmount = new BigNumber ( 0 ) ;
28822928 if ( ! expectedTotalAmount . isEqualTo ( txPrebuild . recipients [ 0 ] . amount ) ) {
2883- throw new Error ( 'batch token transaction amount in txPrebuild should be zero for token transfers' ) ;
2929+ throw new TxIntentMismatchError (
2930+ 'batch token transaction amount in txPrebuild should be zero for token transfers' ,
2931+ '' ,
2932+ [ txParams ] ,
2933+ txPrebuild . txHex || ''
2934+ ) ;
28842935 }
28852936 } else {
28862937 let expectedTotalAmount = new BigNumber ( 0 ) ;
28872938 for ( let i = 0 ; i < txParams . recipients . length ; i ++ ) {
28882939 expectedTotalAmount = expectedTotalAmount . plus ( txParams . recipients [ i ] . amount ) ;
28892940 }
28902941 if ( ! expectedTotalAmount . isEqualTo ( txPrebuild . recipients [ 0 ] . amount ) ) {
2891- throw new Error (
2892- 'batch transaction amount in txPrebuild received from BitGo servers does not match txParams supplied by client'
2942+ throw new TxIntentMismatchError (
2943+ 'batch transaction amount in txPrebuild received from BitGo servers does not match txParams supplied by client' ,
2944+ '' ,
2945+ [ txParams ] ,
2946+ txPrebuild . txHex || ''
28932947 ) ;
28942948 }
28952949 }
@@ -2900,29 +2954,52 @@ export abstract class AbstractEthLikeNewCoins extends AbstractEthLikeCoin {
29002954 ! batcherContractAddress ||
29012955 batcherContractAddress . toLowerCase ( ) !== txPrebuild . recipients [ 0 ] . address . toLowerCase ( )
29022956 ) {
2903- throw new Error ( 'recipient address of txPrebuild does not match batcher address' ) ;
2957+ throw new TxIntentMismatchError (
2958+ 'recipient address of txPrebuild does not match batcher address' ,
2959+ '' ,
2960+ [ txParams ] ,
2961+ txPrebuild . txHex || ''
2962+ ) ;
29042963 }
29052964 } else {
29062965 // Check recipient address and amount for normal transaction
29072966 if ( txParams . recipients . length !== 1 ) {
2908- throw new Error ( `normal transaction only supports 1 recipient but ${ txParams . recipients . length } found` ) ;
2967+ throw new TxIntentMismatchError (
2968+ `normal transaction only supports 1 recipient but ${ txParams . recipients . length } found` ,
2969+ '' ,
2970+ [ txParams ] ,
2971+ txPrebuild . txHex || ''
2972+ ) ;
29092973 }
29102974 const expectedAmount = new BigNumber ( txParams . recipients [ 0 ] . amount ) ;
29112975 if ( ! expectedAmount . isEqualTo ( txPrebuild . recipients [ 0 ] . amount ) ) {
2912- throw new Error (
2913- 'normal transaction amount in txPrebuild received from BitGo servers does not match txParams supplied by client'
2976+ throw new TxIntentMismatchError (
2977+ 'normal transaction amount in txPrebuild received from BitGo servers does not match txParams supplied by client' ,
2978+ '' ,
2979+ [ txParams ] ,
2980+ txPrebuild . txHex || ''
29142981 ) ;
29152982 }
29162983 if (
29172984 this . isETHAddress ( txParams . recipients [ 0 ] . address ) &&
29182985 txParams . recipients [ 0 ] . address !== txPrebuild . recipients [ 0 ] . address
29192986 ) {
2920- throw new Error ( 'destination address in normal txPrebuild does not match that in txParams supplied by client' ) ;
2987+ throw new TxIntentMismatchError (
2988+ 'destination address in normal txPrebuild does not match that in txParams supplied by client' ,
2989+ '' ,
2990+ [ txParams ] ,
2991+ txPrebuild . txHex || ''
2992+ ) ;
29212993 }
29222994 }
29232995 // Check coin is correct for all transaction types
29242996 if ( ! this . verifyCoin ( txPrebuild ) ) {
2925- throw new Error ( `coin in txPrebuild did not match that in txParams supplied by client` ) ;
2997+ throw new TxIntentMismatchError (
2998+ `coin in txPrebuild did not match that in txParams supplied by client` ,
2999+ '' ,
3000+ [ txParams ] ,
3001+ txPrebuild . txHex || ''
3002+ ) ;
29263003 }
29273004 return true ;
29283005 }
0 commit comments