From 37a8f4f03325d76c32b4764381e3d2d7976dd414 Mon Sep 17 00:00:00 2001 From: Akash Gianchandani Date: Thu, 4 Apr 2024 17:23:05 +0530 Subject: [PATCH] fix(abstract-eth): fix opeth:op transfers WIN-2643 TICKET: WIN-2643 This PR fixes the issue with optimism token transfers. Optimism token has the same contract address on eth and op chain, which is causing issues while transferring the token. --- .../src/abstractEthLikeNewCoins.ts | 6 +++++- modules/abstract-eth/src/lib/transaction.ts | 2 +- modules/abstract-eth/src/lib/utils.ts | 14 ++++++++++++-- .../sdk-coin-opeth/test/unit/opethToken.ts | 19 +++++++++++++++++-- 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/modules/abstract-eth/src/abstractEthLikeNewCoins.ts b/modules/abstract-eth/src/abstractEthLikeNewCoins.ts index d795445b4c..617ba998eb 100644 --- a/modules/abstract-eth/src/abstractEthLikeNewCoins.ts +++ b/modules/abstract-eth/src/abstractEthLikeNewCoins.ts @@ -1730,7 +1730,11 @@ export abstract class AbstractEthLikeNewCoins extends AbstractEthLikeCoin { const transferBuilder = txBuilder.transfer() as TransferBuilder; const network = this.getNetwork(); - const token = getToken(params.tokenContractAddress as string, network as EthLikeNetwork)?.name as string; + const token = getToken( + params.tokenContractAddress as string, + network as EthLikeNetwork, + this.staticsCoin?.family as string + )?.name as string; transferBuilder .coin(token) diff --git a/modules/abstract-eth/src/lib/transaction.ts b/modules/abstract-eth/src/lib/transaction.ts index 9c8a05d740..8a347f7f96 100644 --- a/modules/abstract-eth/src/lib/transaction.ts +++ b/modules/abstract-eth/src/lib/transaction.ts @@ -101,7 +101,7 @@ export class Transaction extends BaseTransaction { const { to, amount, tokenContractAddress, signature } = decodeTransferData(txData.data); let coinName: string; if (tokenContractAddress) { - const token = getToken(tokenContractAddress, this._coinConfig.network); + const token = getToken(tokenContractAddress, this._coinConfig.network, this._coinConfig.family); coinName = token ? token.name : UNSUPPORTED_COIN_NAME; } else { coinName = this._coinConfig.name; diff --git a/modules/abstract-eth/src/lib/utils.ts b/modules/abstract-eth/src/lib/utils.ts index 8753b38415..fdf1540dc9 100644 --- a/modules/abstract-eth/src/lib/utils.ts +++ b/modules/abstract-eth/src/lib/utils.ts @@ -638,13 +638,23 @@ export function getBufferedByteCode(methodId: string, rawData: string): Buffer { * Get the statics coin object matching a given contract address if it exists * * @param tokenContractAddress The contract address to match against + * @param network - the coin network + * @param family - the coin family * @returns statics BaseCoin object for the matching token */ -export function getToken(tokenContractAddress: string, network: BaseNetwork): Readonly | undefined { +export function getToken( + tokenContractAddress: string, + network: BaseNetwork, + family: string +): Readonly | undefined { + // filter the coins array to find the token with the matching contract address, network and coin family + // coin family is needed to avoid causing issues when a token has same contract address on two different chains const tokens = coins.filter((coin) => { if (coin instanceof ContractAddressDefinedToken) { return ( - coin.network.type === network.type && coin.contractAddress.toLowerCase() === tokenContractAddress.toLowerCase() + coin.network.type === network.type && + coin.family === family && + coin.contractAddress.toLowerCase() === tokenContractAddress.toLowerCase() ); } return false; diff --git a/modules/sdk-coin-opeth/test/unit/opethToken.ts b/modules/sdk-coin-opeth/test/unit/opethToken.ts index e11421339d..be2da5fd48 100644 --- a/modules/sdk-coin-opeth/test/unit/opethToken.ts +++ b/modules/sdk-coin-opeth/test/unit/opethToken.ts @@ -1,19 +1,24 @@ import 'should'; - +import assert from 'assert'; import { TestBitGo, TestBitGoAPI } from '@bitgo/sdk-test'; -import { register } from '../../src'; import { BitGoAPI } from '@bitgo/sdk-api'; +import { getToken } from '@bitgo/abstract-eth'; + +import { register } from '../../src'; describe('Opeth Token:', function () { let bitgo: TestBitGoAPI; let opethTokenCoin; + let opTokenCoin; const tokenName = 'topeth:terc18dp'; + const opToken = 'opeth:op'; before(function () { bitgo = TestBitGo.decorate(BitGoAPI, { env: 'test' }); register(bitgo); bitgo.initializeTestVars(); opethTokenCoin = bitgo.coin(tokenName); + opTokenCoin = bitgo.coin(opToken); }); it('should return constants', function () { @@ -32,4 +37,14 @@ describe('Opeth Token:', function () { const tokencoinBycontractAddress = bitgo.coin(opethTokenCoin.tokenContractAddress); opethTokenCoin.should.deepEqual(tokencoinBycontractAddress); }); + + it('should return only one token for optimism token contract address', function () { + const token = getToken( + '0x4200000000000000000000000000000000000042', + opTokenCoin.getNetwork(), + opTokenCoin.getFamily() + ); + assert(token); + token.name.should.equal('opeth:op'); + }); });