From d0aa1432227db2f6e5dc0d894da4aff1439c384a Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Wed, 15 Feb 2023 10:26:32 -0600 Subject: [PATCH] adds test and fix for conversion to use numeric (#17758) --- .../lib/transaction-controller-utils.test.js | 235 +++++++++++++++++- shared/lib/transactions-controller-utils.js | 6 +- 2 files changed, 233 insertions(+), 8 deletions(-) diff --git a/shared/lib/transaction-controller-utils.test.js b/shared/lib/transaction-controller-utils.test.js index 3920466ea..c1e661ed7 100644 --- a/shared/lib/transaction-controller-utils.test.js +++ b/shared/lib/transaction-controller-utils.test.js @@ -1,8 +1,233 @@ -import { calcGasTotal } from './transactions-controller-utils'; +import { EtherDenomination } from '../constants/common'; +import { CHAIN_IDS } from '../constants/network'; +import { TransactionEnvelopeType } from '../constants/transaction'; +import { Numeric } from '../modules/Numeric'; +import { + calcGasTotal, + calcTokenAmount, + getSwapsTokensReceivedFromTxMeta, + TOKEN_TRANSFER_LOG_TOPIC_HASH, +} from './transactions-controller-utils'; -describe('calcGasTotal()', () => { - it('should correctly compute gasTotal', () => { - const result = calcGasTotal(12, 15); - expect(result).toStrictEqual('17a'); +describe('transaction controller utils', () => { + describe('calcGasTotal()', () => { + it('should correctly compute gasTotal', () => { + const result = calcGasTotal(12, 15); + expect(result).toStrictEqual('17a'); + }); + }); + + describe('getSwapsTokensReceivedFromTxMeta', () => { + it('returns null if txMeta is not well formed', () => { + expect(getSwapsTokensReceivedFromTxMeta('ETH', {}, '0x00')).toBe(null); + }); + + it('returns null if tokenSymbol is the default for network but txMeta does not contain a receipt', () => { + expect( + getSwapsTokensReceivedFromTxMeta( + 'ETH', + {}, + '0x00', + '8', + {}, + CHAIN_IDS.MAINNET, + ), + ).toBe(null); + }); + + it('returns null if tokenSymbol is the default for network but txMeta does not contain a preTxBalance', () => { + expect( + getSwapsTokensReceivedFromTxMeta( + 'ETH', + { txReceipt: {}, postTxBalance: '0xe' }, + '0x00', + '8', + {}, + CHAIN_IDS.MAINNET, + ), + ).toBe(null); + }); + + it('returns null if tokenSymbol is the default for network but txMeta does not contain a postTxBalance', () => { + expect( + getSwapsTokensReceivedFromTxMeta( + 'ETH', + { txReceipt: {}, preTxBalance: '0xe' }, + '0x00', + '8', + {}, + CHAIN_IDS.MAINNET, + ), + ).toBe(null); + }); + + it('returns estimated receiving amount if post and pre tx balances are the same', () => { + expect( + getSwapsTokensReceivedFromTxMeta( + 'ETH', + { + txReceipt: {}, + preTxBalance: '0xe', + postTxBalance: '0xe', + swapMetaData: { token_to_amount: '0x1' }, + }, + '0x00', + '0x00', + '8', + {}, + CHAIN_IDS.MAINNET, + ), + ).toBe('0x1'); + }); + + it('returns postTxBalance minus preTxBalance less the cost of gas of the transaction', () => { + const preTxBalance = new Numeric('5000000', 10, EtherDenomination.WEI); + const postTxBalance = new Numeric('5500000', 10, EtherDenomination.WEI); + const gasUsed = new Numeric('28000', 10).toPrefixedHexString(); + const effectiveGasPrice = new Numeric('21', 10).toPrefixedHexString(); + const gasCost = calcGasTotal(gasUsed, effectiveGasPrice); + const ethReceived = postTxBalance + .minus(preTxBalance.minus(gasCost, 16)) + .toDenomination(EtherDenomination.ETH) + .round(6); + expect( + getSwapsTokensReceivedFromTxMeta( + 'ETH', + { + txReceipt: { + gasUsed, + effectiveGasPrice, + type: TransactionEnvelopeType.feeMarket, + }, + preTxBalance: preTxBalance.toPrefixedHexString(), + postTxBalance: postTxBalance.toPrefixedHexString(), + swapMetaData: { token_to_amount: '0x1' }, + }, + '0x00', + '0x00', + '8', + {}, + CHAIN_IDS.MAINNET, + ), + ).toBe(ethReceived.toString()); + }); + + it('returns postTxBalance minus preTxBalance less the cost of gas of the transaction and the approval tx', () => { + const preTxBalance = new Numeric('5000000', 10, EtherDenomination.WEI); + const postTxBalance = new Numeric('5500000', 10, EtherDenomination.WEI); + const gasUsed = new Numeric('28000', 10).toPrefixedHexString(); + const gasUsedApproval = new Numeric('75000', 10).toPrefixedHexString(); + const effectiveGasPrice = new Numeric('21', 10).toPrefixedHexString(); + const effectiveGasPriceApproval = new Numeric( + '15', + 10, + ).toPrefixedHexString(); + const gasCost = new Numeric( + calcGasTotal(gasUsed, effectiveGasPrice), + 16, + ).add(calcGasTotal(gasUsedApproval, effectiveGasPriceApproval), 16); + const ethReceived = postTxBalance + .minus(preTxBalance.minus(gasCost)) + .toDenomination(EtherDenomination.ETH) + .round(6); + expect( + getSwapsTokensReceivedFromTxMeta( + 'ETH', + { + txReceipt: { + gasUsed, + effectiveGasPrice, + type: TransactionEnvelopeType.feeMarket, + }, + preTxBalance: preTxBalance.toPrefixedHexString(), + postTxBalance: postTxBalance.toPrefixedHexString(), + swapMetaData: { token_to_amount: '0x1' }, + }, + '0x00', + '0x00', + '8', + { + txReceipt: { + gasUsed: gasUsedApproval, + effectiveGasPrice: effectiveGasPriceApproval, + type: TransactionEnvelopeType.feeMarket, + }, + }, + CHAIN_IDS.MAINNET, + ), + ).toBe(ethReceived.toString()); + }); + + it('returns postTxBalance minus preTxBalance less the cost of gas of the transaction and the approval tx for legacy txs', () => { + const preTxBalance = new Numeric('5000000', 10, EtherDenomination.WEI); + const postTxBalance = new Numeric('5500000', 10, EtherDenomination.WEI); + const gasUsed = new Numeric('28000', 10).toPrefixedHexString(); + const gasUsedApproval = new Numeric('75000', 10).toPrefixedHexString(); + const gasPrice = new Numeric('21', 10).toPrefixedHexString(); + const gasPriceApproval = new Numeric('15', 10).toPrefixedHexString(); + const gasCost = new Numeric(calcGasTotal(gasUsed, gasPrice), 16).add( + calcGasTotal(gasUsedApproval, gasPriceApproval), + 16, + ); + const ethReceived = postTxBalance + .minus(preTxBalance.minus(gasCost)) + .toDenomination(EtherDenomination.ETH) + .round(6); + expect( + getSwapsTokensReceivedFromTxMeta( + 'ETH', + { + txReceipt: { + gasUsed, + type: TransactionEnvelopeType.legacy, + }, + txParams: { + gasPrice, + }, + preTxBalance: preTxBalance.toPrefixedHexString(), + postTxBalance: postTxBalance.toPrefixedHexString(), + swapMetaData: { token_to_amount: '0x1' }, + }, + '0x00', + '0x00', + '8', + { + txReceipt: { + gasUsed: gasUsedApproval, + type: TransactionEnvelopeType.feeMarket, + }, + txParams: { + gasPrice: gasPriceApproval, + }, + }, + CHAIN_IDS.MAINNET, + ), + ).toBe(ethReceived.toString()); + }); + + it('returns value from tokenTransferLogs if not default token for network', () => { + const logs = [ + { + topics: [TOKEN_TRANSFER_LOG_TOPIC_HASH, '', '0x00'], + address: '0x00', + data: new Numeric('10000', 10).toPrefixedHexString(), + }, + ]; + expect( + getSwapsTokensReceivedFromTxMeta( + 'USDC', + { + txReceipt: { logs, status: '0x1' }, + }, + '0x00', + '0x00', + '8', + { + txReceipt: {}, + }, + CHAIN_IDS.MAINNET, + ), + ).toBe(calcTokenAmount(logs[0].data, 8).toString(10), 6); + }); }); }); diff --git a/shared/lib/transactions-controller-utils.js b/shared/lib/transactions-controller-utils.js index 62cf3892b..3ee2484b6 100644 --- a/shared/lib/transactions-controller-utils.js +++ b/shared/lib/transactions-controller-utils.js @@ -4,7 +4,7 @@ import { TransactionEnvelopeType } from '../constants/transaction'; import { Numeric } from '../modules/Numeric'; import { isSwapsDefaultTokenSymbol } from '../modules/swaps.utils'; -const TOKEN_TRANSFER_LOG_TOPIC_HASH = +export const TOKEN_TRANSFER_LOG_TOPIC_HASH = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'; export const TRANSACTION_NO_CONTRACT_ERROR_KEY = 'transactionErrorNoContract'; @@ -82,7 +82,7 @@ export function getSwapsTokensReceivedFromTxMeta( ? txReceipt.effectiveGasPrice : txMeta.txParams.gasPrice, ); - const totalGasCost = new Numeric(gasCost, 16).plus(approvalTxGasCost); + const totalGasCost = new Numeric(gasCost, 16).add(approvalTxGasCost); const preTxBalanceLessGasCost = new Numeric(txMeta.preTxBalance, 16).minus( totalGasCost, @@ -93,7 +93,7 @@ export function getSwapsTokensReceivedFromTxMeta( 16, EtherDenomination.WEI, ) - .subtract(preTxBalanceLessGasCost) + .minus(preTxBalanceLessGasCost) .toDenomination(EtherDenomination.ETH) .toBase(10) .round(6);