diff --git a/modules/abstract-eth/src/abstractEthLikeNewCoins.ts b/modules/abstract-eth/src/abstractEthLikeNewCoins.ts index 20246605ff..05f0c38f43 100644 --- a/modules/abstract-eth/src/abstractEthLikeNewCoins.ts +++ b/modules/abstract-eth/src/abstractEthLikeNewCoins.ts @@ -2853,25 +2853,30 @@ export abstract class AbstractEthLikeNewCoins extends AbstractEthLikeCoin { ['address', 'uint256'], getBufferedByteCode('0xa9059cbb', txJson.data) ); - if (expectedAmount !== amount.toString()) { - throwRecipientMismatch('the transaction amount in txPrebuild does not match the value given by client', [ - { address: addHexPrefix(recipientAddress.toString()), amount: amount.toString() }, - ]); - } // Check if recipients[0].data exists (WalletConnect flow) let expectedRecipientAddress: string; + let expectedTokenAmount: string; const recipientData = (recipients[0] as any).data; + if (recipientData && recipientData.startsWith('0xa9059cbb')) { - // WalletConnect: decode expected recipient from recipients[0].data - const [expectedRecipient] = getRawDecoded( + // WalletConnect: decode expected recipient and amount from recipients[0].data + const [expectedRecipient, expectedAmount] = getRawDecoded( ['address', 'uint256'], getBufferedByteCode('0xa9059cbb', recipientData) ); expectedRecipientAddress = addHexPrefix(expectedRecipient.toString()).toLowerCase(); + expectedTokenAmount = expectedAmount.toString(); } else { - // Normal flow: use recipients[0].address + // Normal flow: use recipients[0].address and recipients[0].amount expectedRecipientAddress = expectedDestination.toLowerCase(); + expectedTokenAmount = expectedAmount; + } + + if (expectedTokenAmount !== amount.toString()) { + throwRecipientMismatch('the transaction amount in txPrebuild does not match the value given by client', [ + { address: addHexPrefix(recipientAddress.toString()), amount: amount.toString() }, + ]); } if (expectedRecipientAddress !== addHexPrefix(recipientAddress.toString()).toLowerCase()) { diff --git a/modules/bitgo/test/v2/unit/internal/tssUtils/ecdsa.ts b/modules/bitgo/test/v2/unit/internal/tssUtils/ecdsa.ts index 53c167f496..6e9574b491 100644 --- a/modules/bitgo/test/v2/unit/internal/tssUtils/ecdsa.ts +++ b/modules/bitgo/test/v2/unit/internal/tssUtils/ecdsa.ts @@ -858,7 +858,8 @@ describe('TSS Ecdsa Utils:', async function () { it('signTxRequest should succeed for WalletConnect ERC20 transfer with data field', async function () { nock.cleanAll(); - // WalletConnect ERC20 transfer: recipients[0].address is token contract, recipients[0].data contains the actual recipient + // WalletConnect ERC20 transfer: recipients[0].address is token contract, recipients[0].amount is 0 (no native coins) + // recipients[0].data contains the actual recipient and token amount const signableHex = '02f86f83088bb00283e1d7dd84768ea6898301e04b94d9327fd36c3312466efed23ff0493453ee32f55180b844a9059cbb0000000000000000000000007d7e63af583ba73ba5c927dbd028153963566bef00000000000000000000000000000000000000000000000000470de4df820000c0'; const serializedTxHex = @@ -880,8 +881,8 @@ describe('TSS Ecdsa Utils:', async function () { recipients: [ { address: '0xd9327fd36c3312466efed23ff0493453ee32f551', // Token contract address - amount: '20000000000000000', - data: '0xa9059cbb0000000000000000000000007d7e63af583ba73ba5c927dbd028153963566bef00000000000000000000000000000000000000000000000000470de4df820000', // ERC20 transfer calldata with actual recipient + amount: '0', // No native coins sent + data: '0xa9059cbb0000000000000000000000007d7e63af583ba73ba5c927dbd028153963566bef00000000000000000000000000000000000000000000000000470de4df820000', // ERC20 transfer calldata with actual recipient and token amount }, ], type: 'transfer',