Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions modules/abstract-eth/src/abstractEthLikeNewCoins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Expand Down
7 changes: 4 additions & 3 deletions modules/bitgo/test/v2/unit/internal/tssUtils/ecdsa.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand All @@ -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',
Expand Down