From c1e4504675d3652599b9b208abf19a54de923916 Mon Sep 17 00:00:00 2001 From: Sachu Shaji Abraham Date: Mon, 19 Jun 2023 18:17:29 +0530 Subject: [PATCH] fix(sdk-coin-avaxc): fix recovery to multisig address this change removes unnecessary data append to avaxc recovery code Ticket: EA-585 --- modules/sdk-coin-avaxc/package.json | 3 +- modules/sdk-coin-avaxc/src/avaxc.ts | 12 +---- modules/sdk-coin-avaxc/test/unit/avaxc.ts | 9 +++- modules/sdk-coin-avaxc/test/unit/helpers.ts | 51 +++++++++++++++++++++ 4 files changed, 63 insertions(+), 12 deletions(-) create mode 100644 modules/sdk-coin-avaxc/test/unit/helpers.ts diff --git a/modules/sdk-coin-avaxc/package.json b/modules/sdk-coin-avaxc/package.json index 116ae47c5a..3c5dbb9913 100644 --- a/modules/sdk-coin-avaxc/package.json +++ b/modules/sdk-coin-avaxc/package.json @@ -56,6 +56,7 @@ }, "devDependencies": { "@bitgo/sdk-api": "^1.10.5", - "@bitgo/sdk-test": "^1.2.23" + "@bitgo/sdk-test": "^1.2.23", + "ethers": "^5.1.3" } } diff --git a/modules/sdk-coin-avaxc/src/avaxc.ts b/modules/sdk-coin-avaxc/src/avaxc.ts index f766bdd66c..f5f1412174 100644 --- a/modules/sdk-coin-avaxc/src/avaxc.ts +++ b/modules/sdk-coin-avaxc/src/avaxc.ts @@ -37,7 +37,7 @@ import { import { isValidEthAddress } from './lib/utils'; import { KeyPair as AvaxcKeyPair, TransactionBuilder } from './lib'; import request from 'superagent'; -import { bufferToHex, pubToAddress } from 'ethereumjs-util'; +import { pubToAddress } from 'ethereumjs-util'; import { Buffer } from 'buffer'; import { AvaxSignTransactionOptions, @@ -628,13 +628,6 @@ export class AvaxC extends BaseCoin { gasLimit: gasLimit.toString(10), }; - // calculate send data - const sendMethodArgs = this.getSendMethodArgs(txInfo); - const sendMethodName = 'sendMultiSig'; - const methodSignature = optionalDeps.ethAbi.methodID(sendMethodName, _.map(sendMethodArgs, 'type')); - const encodedArgs = optionalDeps.ethAbi.rawEncode(_.map(sendMethodArgs, 'type'), _.map(sendMethodArgs, 'value')); - const sendData = Buffer.concat([methodSignature, encodedArgs]); - const txBuilder = this.getTransactionBuilder() as TransactionBuilder; txBuilder.counter(backupKeyNonce); txBuilder.contract(params.walletContractAddress); @@ -658,8 +651,7 @@ export class AvaxC extends BaseCoin { .amount(recipients[0].amount) .contractSequenceId(sequenceId) .expirationTime(this.getDefaultExpireTime()) - .to(params.recoveryDestination) - .data(bufferToHex(sendData as Buffer)); + .to(params.recoveryDestination); if (isUnsignedSweep) { const tx = await txBuilder.build(); diff --git a/modules/sdk-coin-avaxc/test/unit/avaxc.ts b/modules/sdk-coin-avaxc/test/unit/avaxc.ts index c8f0146bb6..1ff5b131f7 100644 --- a/modules/sdk-coin-avaxc/test/unit/avaxc.ts +++ b/modules/sdk-coin-avaxc/test/unit/avaxc.ts @@ -11,6 +11,7 @@ import { AvaxSignTransactionOptions } from '../../src/iface'; import * as should from 'should'; import { EXPORT_C, IMPORT_C } from '../resources/avaxc'; import { TavaxP } from '@bitgo/sdk-coin-avaxp'; +import { decodeTransaction, parseTransaction, walletSimpleABI } from './helpers'; nock.enableNetConnect(); @@ -888,8 +889,14 @@ describe('Avalanche C-Chain', function () { recoveryDestination, gasPrice, }); + const parsedTx = parseTransaction(recovery.txHex); - // id and tx will always be different because of expireTime + const decodedSendMultisigCallData = decodeTransaction(JSON.stringify(walletSimpleABI), parsedTx.data); + + const safeTransferFromCallData = decodedSendMultisigCallData.args[2]; + const safeTransferFromDestination = decodedSendMultisigCallData.args[0]; + safeTransferFromDestination.toLowerCase().should.equal(recoveryDestination); + safeTransferFromCallData.should.be.equal('0x'); recovery.should.not.be.undefined(); recovery.should.have.properties('txHex', 'userKey', 'backupKey'); recovery.recipients.length.should.equal(1); diff --git a/modules/sdk-coin-avaxc/test/unit/helpers.ts b/modules/sdk-coin-avaxc/test/unit/helpers.ts new file mode 100644 index 0000000000..373151245f --- /dev/null +++ b/modules/sdk-coin-avaxc/test/unit/helpers.ts @@ -0,0 +1,51 @@ +import { ethers } from 'ethers'; + +export function decodeTransaction(abi: string, calldata: string): ethers.utils.TransactionDescription { + const contractInterface = new ethers.utils.Interface(abi); + return contractInterface.parseTransaction({ data: calldata }); +} + +export function parseTransaction(txHex: string): ethers.Transaction { + return ethers.utils.parseTransaction(txHex); +} + +export const walletSimpleABI = [ + { + inputs: [ + { + internalType: 'address', + name: 'toAddress', + type: 'address', + }, + { + internalType: 'uint256', + name: 'value', + type: 'uint256', + }, + { + internalType: 'bytes', + name: 'data', + type: 'bytes', + }, + { + internalType: 'uint256', + name: 'expireTime', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'sequenceId', + type: 'uint256', + }, + { + internalType: 'bytes', + name: 'signature', + type: 'bytes', + }, + ], + name: 'sendMultiSig', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, +];