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
18 changes: 17 additions & 1 deletion modules/abstract-eth/src/abstractEthLikeNewCoins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2858,7 +2858,23 @@ export abstract class AbstractEthLikeNewCoins extends AbstractEthLikeCoin {
{ address: addHexPrefix(recipientAddress.toString()), amount: amount.toString() },
]);
}
if (expectedDestination.toLowerCase() !== addHexPrefix(recipientAddress.toString()).toLowerCase()) {

// Check if recipients[0].data exists (WalletConnect flow)
let expectedRecipientAddress: string;
const recipientData = (recipients[0] as any).data;
if (recipientData && recipientData.startsWith('0xa9059cbb')) {
// WalletConnect: decode expected recipient from recipients[0].data
const [expectedRecipient] = getRawDecoded(
['address', 'uint256'],
getBufferedByteCode('0xa9059cbb', recipientData)
);
expectedRecipientAddress = addHexPrefix(expectedRecipient.toString()).toLowerCase();
} else {
// Normal flow: use recipients[0].address
expectedRecipientAddress = expectedDestination.toLowerCase();
}

if (expectedRecipientAddress !== addHexPrefix(recipientAddress.toString()).toLowerCase()) {
throwRecipientMismatch('destination address does not match with the recipient address', [
{ address: addHexPrefix(recipientAddress.toString()), amount: amount.toString() },
]);
Expand Down
33 changes: 33 additions & 0 deletions modules/bitgo/test/v2/unit/internal/tssUtils/ecdsa.ts
Original file line number Diff line number Diff line change
Expand Up @@ -856,6 +856,39 @@ describe('TSS Ecdsa Utils:', async function () {
.should.be.rejectedWith('the transaction amount in txPrebuild does not match the value given by client');
});

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
const signableHex =
'02f86f83088bb00283e1d7dd84768ea6898301e04b94d9327fd36c3312466efed23ff0493453ee32f55180b844a9059cbb0000000000000000000000007d7e63af583ba73ba5c927dbd028153963566bef00000000000000000000000000000000000000000000000000470de4df820000c0';
const serializedTxHex =
'02f87283088bb00283e1d7dd84768ea6898301e04b94d9327fd36c3312466efed23ff0493453ee32f55180b844a9059cbb0000000000000000000000007d7e63af583ba73ba5c927dbd028153963566bef00000000000000000000000000000000000000000000000000470de4df820000c0808080';
await setupSignTxRequestNocks(true, userSignShare, aShare, dShare, enterpriseData, {
signableHex,
serializedTxHex,
apiVersion: 'full',
});
await tssUtils.signTxRequest({
txRequest: txRequestId,
prv: JSON.stringify({
pShare: userKeyShare.pShare,
bitgoNShare: bitgoKeyShare.nShares[1],
backupNShare: backupKeyShare.nShares[1],
}),
reqId,
txParams: {
recipients: [
{
address: '0xd9327fd36c3312466efed23ff0493453ee32f551', // Token contract address
amount: '20000000000000000',
data: '0xa9059cbb0000000000000000000000007d7e63af583ba73ba5c927dbd028153963566bef00000000000000000000000000000000000000000000000000470de4df820000', // ERC20 transfer calldata with actual recipient
},
],
type: 'transfer',
},
});
});

it('getOfflineSignerPaillierModulus should succeed', async function () {
const paillierModulus = tssUtils.getOfflineSignerPaillierModulus({
prv: JSON.stringify({
Expand Down
1 change: 1 addition & 0 deletions modules/sdk-core/src/bitgo/baseCoin/iBaseCoin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export interface ITransactionRecipient {
amount: string | number;
tokenName?: string;
memo?: string;
data?: string;
}

/**
Expand Down