From 34d6291608791aae69e582d21b36cb5870e34949 Mon Sep 17 00:00:00 2001 From: andrepimenta Date: Wed, 25 Aug 2021 13:33:56 +0100 Subject: [PATCH] Parse transaction data correctly --- app/components/Nav/Main/index.js | 28 +++++---- .../TransactionReviewInformation/index.js | 59 +++++++++++++++---- app/util/transactions/index.js | 55 +++++++++++++++++ package.json | 1 + 4 files changed, 122 insertions(+), 21 deletions(-) diff --git a/app/components/Nav/Main/index.js b/app/components/Nav/Main/index.js index c6796576524..0cad690e75f 100644 --- a/app/components/Nav/Main/index.js +++ b/app/components/Nav/Main/index.js @@ -23,7 +23,7 @@ import I18n, { strings } from '../../../../locales/i18n'; import { colors } from '../../../styles/common'; import LockManager from '../../../core/LockManager'; import FadeOutOverlay from '../../UI/FadeOutOverlay'; -import { hexToBN, fromWei, renderFromTokenMinimalUnit } from '../../../util/number'; +import { hexToBN, fromWei } from '../../../util/number'; import { setEtherTransaction, setTransactionObject } from '../../../actions/transaction'; import PersonalSign from '../../UI/PersonalSign'; import TypedSign from '../../UI/TypedSign'; @@ -33,9 +33,12 @@ import Device from '../../../util/device'; import { getMethodData, TOKEN_METHOD_TRANSFER, - decodeTransferData, APPROVE_FUNCTION_SIGNATURE, - decodeApproveData + decodeApproveData, + getTokenValueParam, + getTokenAddressParam, + calcTokenAmount, + getTokenValueParamAsHex } from '../../../util/transactions'; import { BN } from 'ethereumjs-util'; import Logger from '../../../util/Logger'; @@ -66,6 +69,10 @@ import { ANALYTICS_EVENT_OPTS } from '../../../util/analytics'; import BigNumber from 'bignumber.js'; import { setInfuraAvailabilityBlocked, setInfuraAvailabilityNotBlocked } from '../../../actions/infuraAvailability'; import { toLowerCaseEquals } from '../../../util/general'; +import { ethers } from 'ethers'; +import abi from 'human-standard-token-abi'; + +const hstInterface = new ethers.utils.Interface(abi); const styles = StyleSheet.create({ flex: { @@ -366,13 +373,14 @@ const Main = props => { } } - const decodedData = decodeTransferData('transfer', data); - transactionMeta.transaction.value = hexToBN(decodedData[2]); - transactionMeta.transaction.readableValue = renderFromTokenMinimalUnit( - hexToBN(decodedData[2]), - asset.decimals - ); - transactionMeta.transaction.to = decodedData[0]; + const tokenData = hstInterface.parseTransaction({ data }); + const tokenValue = getTokenValueParam(tokenData); + const toAddress = getTokenAddressParam(tokenData); + const tokenAmount = tokenData && calcTokenAmount(tokenValue, asset.decimals).toFixed(); + + transactionMeta.transaction.value = hexToBN(getTokenValueParamAsHex(tokenData)); + transactionMeta.transaction.readableValue = tokenAmount; + transactionMeta.transaction.to = toAddress; setTransactionObject({ type: 'INDIVIDUAL_TOKEN_TRANSACTION', diff --git a/app/components/UI/TransactionReview/TransactionReviewInformation/index.js b/app/components/UI/TransactionReview/TransactionReviewInformation/index.js index 35feb54240f..cde1f7391f1 100644 --- a/app/components/UI/TransactionReview/TransactionReviewInformation/index.js +++ b/app/components/UI/TransactionReview/TransactionReviewInformation/index.js @@ -307,17 +307,6 @@ class TransactionReviewInformation extends PureComponent { contractExchangeRates } = this.props; - const { totalMinNative, totalMinConversion, totalMaxNative, totalMaxConversion } = calculateAmountsEIP1559({ - value: value && BNToHex(value), - nativeCurrency, - currentCurrency, - conversionRate, - gasFeeMinConversion, - gasFeeMinNative, - gasFeeMaxNative, - gasFeeMaxConversion - }); - let renderableTotalMinNative, renderableTotalMinConversion, renderableTotalMaxNative, @@ -325,6 +314,22 @@ class TransactionReviewInformation extends PureComponent { const totals = { ETH: () => { + const { + totalMinNative, + totalMinConversion, + totalMaxNative, + totalMaxConversion + } = calculateAmountsEIP1559({ + value: value && BNToHex(value), + nativeCurrency, + currentCurrency, + conversionRate, + gasFeeMinConversion, + gasFeeMinNative, + gasFeeMaxNative, + gasFeeMaxConversion + }); + [ renderableTotalMinNative, renderableTotalMinConversion, @@ -347,6 +352,22 @@ class TransactionReviewInformation extends PureComponent { ]; }, ERC20: () => { + const { + totalMinNative, + totalMinConversion, + totalMaxNative, + totalMaxConversion + } = calculateAmountsEIP1559({ + value: '0x0', + nativeCurrency, + currentCurrency, + conversionRate, + gasFeeMinConversion, + gasFeeMinNative, + gasFeeMaxNative, + gasFeeMaxConversion + }); + const tokenAmount = renderFromTokenMinimalUnit(value, selectedAsset.decimals); const exchangeRate = contractExchangeRates[selectedAsset.address]; const symbol = selectedAsset.symbol; @@ -376,6 +397,22 @@ class TransactionReviewInformation extends PureComponent { ]; }, ERC721: () => { + const { + totalMinNative, + totalMinConversion, + totalMaxNative, + totalMaxConversion + } = calculateAmountsEIP1559({ + value: '0x0', + nativeCurrency, + currentCurrency, + conversionRate, + gasFeeMinConversion, + gasFeeMinNative, + gasFeeMaxNative, + gasFeeMaxConversion + }); + [ renderableTotalMinNative, renderableTotalMinConversion, diff --git a/app/util/transactions/index.js b/app/util/transactions/index.js index 084cc132919..b8a43b60b8b 100644 --- a/app/util/transactions/index.js +++ b/app/util/transactions/index.js @@ -32,6 +32,8 @@ import { import humanizeDuration from 'humanize-duration'; +import BigNumber from 'bignumber.js'; + const { SAI_ADDRESS } = AppConstants; export const TOKEN_METHOD_TRANSFER = 'transfer'; @@ -1118,3 +1120,56 @@ export function validateTransactionActionBalance(transaction, rate, accounts) { return false; } } + +export function calcTokenAmount(value, decimals) { + const multiplier = Math.pow(10, Number(decimals || 0)); + return new BigNumber(String(value)).div(multiplier); +} + +export function calcTokenValue(value, decimals) { + const multiplier = Math.pow(10, Number(decimals || 0)); + return new BigNumber(String(value)).times(multiplier); +} + +/** + * Attempts to get the address parameter of the given token transaction data + * (i.e. function call) per the Human Standard Token ABI, in the following + * order: + * - The '_to' parameter, if present + * - The first parameter, if present + * + * @param {Object} tokenData - ethers Interface token data. + * @returns {string | undefined} A lowercase address string. + */ +export function getTokenAddressParam(tokenData = {}) { + const value = tokenData?.args?._to || tokenData?.args?.[0]; + return value?.toString().toLowerCase(); +} + +/** + * Gets the '_hex' parameter of the given token transaction data + * (i.e function call) per the Human Standard Token ABI, if present. + * + * @param {Object} tokenData - ethers Interface token data. + * @returns {string | undefined} A hex string value. + */ +export function getTokenValueParamAsHex(tokenData = {}) { + const value = tokenData?.args?._value?._hex || tokenData?.args?.[1]._hex; + return value?.toLowerCase(); +} + +/** + * Gets the '_value' parameter of the given token transaction data + * (i.e function call) per the Human Standard Token ABI, if present. + * + * @param {Object} tokenData - ethers Interface token data. + * @returns {string | undefined} A decimal string value. + */ +export function getTokenValueParam(tokenData = {}) { + return tokenData?.args?._value?.toString(); +} + +export function getTokenValue(tokenParams = []) { + const valueData = tokenParams.find(param => param.name === '_value'); + return valueData && valueData.value; +} diff --git a/package.json b/package.json index 263aabaa4fc..9329654783b 100644 --- a/package.json +++ b/package.json @@ -129,6 +129,7 @@ "events": "3.0.0", "fuse.js": "3.4.4", "https-browserify": "0.0.1", + "human-standard-token-abi": "^2.0.0", "humanize-duration": "^3.27.0", "improved-yarn-audit": "^2.3.3", "is-url": "^1.2.4",