From 03961715f765a77fc74081aded062e7e95a11843 Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Mon, 17 May 2021 16:19:39 -0500 Subject: [PATCH] use safer toChecksum utility (#11117) --- app/scripts/controllers/ens/index.js | 6 +++--- app/scripts/controllers/token-rates.js | 4 ++-- app/scripts/metamask-controller.js | 13 ++++++------ app/scripts/migrations/039.js | 4 ++-- shared/modules/hexstring-utils.js | 20 +++++++++++++++++++ .../account-list-item-component.test.js | 16 +++++++-------- .../account-list-item/account-list-item.js | 4 ++-- .../export-private-key-modal.component.js | 4 ++-- .../selected-account.component.js | 5 +++-- ...transaction-list-item-details.container.js | 4 ++-- .../ui/identicon/identicon.component.js | 9 +++------ ui/app/components/ui/qr-code/qr-code.js | 10 +++++----- .../sender-to-recipient.component.js | 12 +++++++---- ui/app/helpers/utils/util.js | 15 ++------------ ui/app/hooks/useTokensToSearch.js | 10 +++++----- .../confirm-transaction-base.container.js | 11 ++++------ .../add-recipient/add-recipient.js | 5 +++-- .../add-recipient/add-recipient.utils.test.js | 1 + .../view-contact/view-contact.container.js | 4 ++-- ui/app/selectors/selectors.js | 9 +++------ ui/app/store/actions.js | 6 +++--- ui/lib/icon-factory.js | 13 +++++------- 22 files changed, 94 insertions(+), 91 deletions(-) diff --git a/app/scripts/controllers/ens/index.js b/app/scripts/controllers/ens/index.js index a7d4c696b..85477ef7e 100644 --- a/app/scripts/controllers/ens/index.js +++ b/app/scripts/controllers/ens/index.js @@ -1,8 +1,8 @@ import punycode from 'punycode/punycode'; -import { toChecksumAddress } from 'ethereumjs-util'; import { ObservableStore } from '@metamask/obs-store'; import log from 'loglevel'; import { CHAIN_ID_TO_NETWORK_ID_MAP } from '../../../../shared/constants/network'; +import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils'; import Ens from './ens'; const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; @@ -43,7 +43,7 @@ export default class EnsController { } reverseResolveAddress(address) { - return this._reverseResolveAddress(toChecksumAddress(address)); + return this._reverseResolveAddress(toChecksumHexAddress(address)); } async _reverseResolveAddress(address) { @@ -79,7 +79,7 @@ export default class EnsController { return undefined; } - if (toChecksumAddress(registeredAddress) !== address) { + if (toChecksumHexAddress(registeredAddress) !== address) { return undefined; } diff --git a/app/scripts/controllers/token-rates.js b/app/scripts/controllers/token-rates.js index b725b04c9..1bba3f389 100644 --- a/app/scripts/controllers/token-rates.js +++ b/app/scripts/controllers/token-rates.js @@ -1,8 +1,8 @@ import { ObservableStore } from '@metamask/obs-store'; import log from 'loglevel'; import { normalize as normalizeAddress } from 'eth-sig-util'; -import { toChecksumAddress } from 'ethereumjs-util'; import getFetchWithTimeout from '../../../shared/modules/fetch-with-timeout'; +import { toChecksumHexAddress } from '../../../shared/modules/hexstring-utils'; const fetchWithTimeout = getFetchWithTimeout(30000); @@ -45,7 +45,7 @@ export default class TokenRatesController { this._tokens.forEach((token) => { const price = prices[token.address.toLowerCase()] || - prices[toChecksumAddress(token.address)]; + prices[toChecksumHexAddress(token.address)]; contractExchangeRates[normalizeAddress(token.address)] = price ? price[nativeCurrency] : 0; diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 00b3115c8..93faa0b48 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -10,7 +10,7 @@ import createSubscriptionManager from 'eth-json-rpc-filters/subscriptionManager' import providerAsMiddleware from 'eth-json-rpc-middleware/providerAsMiddleware'; import KeyringController from 'eth-keyring-controller'; import { Mutex } from 'await-semaphore'; -import { toChecksumAddress, stripHexPrefix } from 'ethereumjs-util'; +import { stripHexPrefix } from 'ethereumjs-util'; import log from 'loglevel'; import TrezorKeyring from 'eth-trezor-keyring'; import LedgerBridgeKeyring from '@metamask/eth-ledger-bridge-keyring'; @@ -27,6 +27,7 @@ import { import { TRANSACTION_STATUSES } from '../../shared/constants/transaction'; import { MAINNET_CHAIN_ID } from '../../shared/constants/network'; import { UI_NOTIFICATIONS } from '../../shared/notifications'; +import { toChecksumHexAddress } from '../../shared/modules/hexstring-utils'; import ComposableObservableStore from './lib/ComposableObservableStore'; import AccountTracker from './lib/account-tracker'; @@ -1107,14 +1108,14 @@ export default class MetamaskController extends EventEmitter { // Filter ERC20 tokens const filteredAccountTokens = {}; Object.keys(accountTokens).forEach((address) => { - const checksummedAddress = toChecksumAddress(address); + const checksummedAddress = toChecksumHexAddress(address); filteredAccountTokens[checksummedAddress] = {}; Object.keys(accountTokens[address]).forEach((chainId) => { filteredAccountTokens[checksummedAddress][chainId] = chainId === MAINNET_CHAIN_ID ? accountTokens[address][chainId].filter( ({ address: tokenAddress }) => { - const checksumAddress = toChecksumAddress(tokenAddress); + const checksumAddress = toChecksumHexAddress(tokenAddress); return contractMap[checksumAddress] ? contractMap[checksumAddress].erc20 : true; @@ -1151,10 +1152,10 @@ export default class MetamaskController extends EventEmitter { const accounts = { hd: hdAccounts .filter((item, pos) => hdAccounts.indexOf(item) === pos) - .map((address) => toChecksumAddress(address)), + .map((address) => toChecksumHexAddress(address)), simpleKeyPair: simpleKeyPairAccounts .filter((item, pos) => simpleKeyPairAccounts.indexOf(item) === pos) - .map((address) => toChecksumAddress(address)), + .map((address) => toChecksumHexAddress(address)), ledger: [], trezor: [], }; @@ -1164,7 +1165,7 @@ export default class MetamaskController extends EventEmitter { let { transactions } = this.txController.store.getState(); // delete tx for other accounts that we're not importing transactions = Object.values(transactions).filter((tx) => { - const checksummedTxFrom = toChecksumAddress(tx.txParams.from); + const checksummedTxFrom = toChecksumHexAddress(tx.txParams.from); return accounts.hd.includes(checksummedTxFrom); }); diff --git a/app/scripts/migrations/039.js b/app/scripts/migrations/039.js index 7dcf904de..aa288553a 100644 --- a/app/scripts/migrations/039.js +++ b/app/scripts/migrations/039.js @@ -1,5 +1,5 @@ import { cloneDeep } from 'lodash'; -import { toChecksumAddress } from 'ethereumjs-util'; +import { toChecksumHexAddress } from '../../../shared/modules/hexstring-utils'; const version = 39; @@ -12,7 +12,7 @@ function isOldDai(token = {}) { token && typeof token === 'object' && token.symbol === DAI_V1_TOKEN_SYMBOL && - toChecksumAddress(token.address) === DAI_V1_CONTRACT_ADDRESS + toChecksumHexAddress(token.address) === DAI_V1_CONTRACT_ADDRESS ); } diff --git a/shared/modules/hexstring-utils.js b/shared/modules/hexstring-utils.js index f40f537d3..1f895a3c7 100644 --- a/shared/modules/hexstring-utils.js +++ b/shared/modules/hexstring-utils.js @@ -3,6 +3,7 @@ import { isValidAddress, isValidChecksumAddress, addHexPrefix, + toChecksumAddress, } from 'ethereumjs-util'; export const BURN_ADDRESS = '0x0000000000000000000000000000000000000000'; @@ -51,3 +52,22 @@ export function isValidHexAddress( return isValidAddress(addressToCheck); } + +export function toChecksumHexAddress(address) { + if (!address) { + // our internal checksumAddress function that this method replaces would + // return an empty string for nullish input. If any direct usages of + // ethereumjs-util.toChecksumAddress were called with nullish input it + // would have resulted in an error on version 5.1. + return ''; + } + const hexPrefixed = addHexPrefix(address); + if (!isHexString(hexPrefixed)) { + // Version 5.1 of ethereumjs-utils would have returned '0xY' for input 'y' + // but we shouldn't waste effort trying to change case on a clearly invalid + // string. Instead just return the hex prefixed original string which most + // closely mimics the original behavior. + return hexPrefixed; + } + return toChecksumAddress(addHexPrefix(address)); +} diff --git a/ui/app/components/app/account-list-item/account-list-item-component.test.js b/ui/app/components/app/account-list-item/account-list-item-component.test.js index 11d5ba6eb..d8a05ce46 100644 --- a/ui/app/components/app/account-list-item/account-list-item-component.test.js +++ b/ui/app/components/app/account-list-item/account-list-item-component.test.js @@ -1,18 +1,19 @@ import React from 'react'; import { shallow } from 'enzyme'; import sinon from 'sinon'; -import * as utils from '../../../helpers/utils/util'; import Identicon from '../../ui/identicon'; +import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils'; import AccountListItem from './account-list-item'; +jest.mock('../../../../shared/modules/hexstring-utils', () => ({ + toChecksumHexAddress: jest.fn(() => 'mockCheckSumAddress'), +})); + describe('AccountListItem Component', () => { - let wrapper, propsMethodSpies, checksumAddressStub; + let wrapper, propsMethodSpies; describe('render', () => { beforeAll(() => { - checksumAddressStub = sinon - .stub(utils, 'checksumAddress') - .returns('mockCheckSumAddress'); propsMethodSpies = { handleClick: sinon.spy(), }; @@ -36,7 +37,6 @@ describe('AccountListItem Component', () => { afterEach(() => { propsMethodSpies.handleClick.resetHistory(); - checksumAddressStub.resetHistory(); }); afterAll(() => { @@ -126,9 +126,7 @@ describe('AccountListItem Component', () => { expect( wrapper.find('.account-list-item__account-address').text(), ).toStrictEqual('mockCheckSumAddress'); - expect(checksumAddressStub.getCall(0).args).toStrictEqual([ - 'mockAddress', - ]); + expect(toChecksumHexAddress).toHaveBeenCalledWith('mockAddress'); }); it('should not render the account address as a checksumAddress if displayAddress is false', () => { diff --git a/ui/app/components/app/account-list-item/account-list-item.js b/ui/app/components/app/account-list-item/account-list-item.js index 9b0c0e38f..5220dede9 100644 --- a/ui/app/components/app/account-list-item/account-list-item.js +++ b/ui/app/components/app/account-list-item/account-list-item.js @@ -1,8 +1,8 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { checksumAddress } from '../../../helpers/utils/util'; import Identicon from '../../ui/identicon'; import AccountMismatchWarning from '../../ui/account-mismatch-warning/account-mismatch-warning.component'; +import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils'; export default function AccountListItem({ account, @@ -34,7 +34,7 @@ export default function AccountListItem({ {displayAddress && name && (
- {checksumAddress(address)} + {toChecksumHexAddress(address)}
)} diff --git a/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.component.js b/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.component.js index 6ac5219b3..ba6e4ca8b 100644 --- a/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.component.js +++ b/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.component.js @@ -4,10 +4,10 @@ import React, { Component } from 'react'; import { stripHexPrefix } from 'ethereumjs-util'; import copyToClipboard from 'copy-to-clipboard'; -import { checksumAddress } from '../../../../helpers/utils/util'; import ReadOnlyInput from '../../../ui/readonly-input'; import Button from '../../../ui/button'; import AccountModalContainer from '../account-modal-container'; +import { toChecksumHexAddress } from '../../../../../shared/modules/hexstring-utils'; export default class ExportPrivateKeyModal extends Component { static contextTypes = { @@ -149,7 +149,7 @@ export default class ExportPrivateKeyModal extends Component { {name}
diff --git a/ui/app/components/app/selected-account/selected-account.component.js b/ui/app/components/app/selected-account/selected-account.component.js index f703678a1..b52dd033f 100644 --- a/ui/app/components/app/selected-account/selected-account.component.js +++ b/ui/app/components/app/selected-account/selected-account.component.js @@ -1,9 +1,10 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import copyToClipboard from 'copy-to-clipboard'; -import { shortenAddress, checksumAddress } from '../../../helpers/utils/util'; +import { shortenAddress } from '../../../helpers/utils/util'; import Tooltip from '../../ui/tooltip'; +import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils'; class SelectedAccount extends Component { state = { @@ -32,7 +33,7 @@ class SelectedAccount extends Component { render() { const { t } = this.context; const { selectedIdentity } = this.props; - const checksummedAddress = checksumAddress(selectedIdentity.address); + const checksummedAddress = toChecksumHexAddress(selectedIdentity.address); return (
diff --git a/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.container.js b/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.container.js index 4a96082c7..280cec020 100644 --- a/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.container.js +++ b/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.container.js @@ -1,10 +1,10 @@ import { connect } from 'react-redux'; -import { checksumAddress } from '../../../helpers/utils/util'; import { tryReverseResolveAddress } from '../../../store/actions'; import { getAddressBook, getRpcPrefsForCurrentProvider, } from '../../../selectors'; +import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils'; import TransactionListItemDetails from './transaction-list-item-details.component'; const mapStateToProps = (state, ownProps) => { @@ -13,7 +13,7 @@ const mapStateToProps = (state, ownProps) => { const { recipientAddress, senderAddress } = ownProps; let recipientEns; if (recipientAddress) { - const address = checksumAddress(recipientAddress); + const address = toChecksumHexAddress(recipientAddress); recipientEns = ensResolutionsByAddress[address] || ''; } const addressBook = getAddressBook(state); diff --git a/ui/app/components/ui/identicon/identicon.component.js b/ui/app/components/ui/identicon/identicon.component.js index ec2cc70cc..dd6eb5beb 100644 --- a/ui/app/components/ui/identicon/identicon.component.js +++ b/ui/app/components/ui/identicon/identicon.component.js @@ -2,9 +2,8 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import contractMap from '@metamask/contract-metadata'; -import { isHexString, addHexPrefix } from 'ethereumjs-util'; +import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils'; -import { checksumAddress } from '../../../helpers/utils/util'; import Jazzicon from '../jazzicon'; import BlockieIdenticon from './blockieIdenticon'; @@ -86,11 +85,9 @@ export default class Identicon extends PureComponent { } if (address) { - const checksummedAddress = - isHexString(addHexPrefix(address)) && - checksumAddress(addHexPrefix(address)); + const checksummedAddress = toChecksumHexAddress(address); - if (contractMap[checksummedAddress]?.logo) { + if (checksummedAddress && contractMap[checksummedAddress]?.logo) { return this.renderJazzicon(); } diff --git a/ui/app/components/ui/qr-code/qr-code.js b/ui/app/components/ui/qr-code/qr-code.js index 6c00f33fc..db0eeed2c 100644 --- a/ui/app/components/ui/qr-code/qr-code.js +++ b/ui/app/components/ui/qr-code/qr-code.js @@ -4,7 +4,7 @@ import qrCode from 'qrcode-generator'; import { connect } from 'react-redux'; import { isHexPrefixed } from 'ethereumjs-util'; import ReadOnlyInput from '../readonly-input/readonly-input'; -import { checksumAddress } from '../../../helpers/utils/util'; +import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils'; export default connect(mapStateToProps)(QrCodeView); @@ -20,9 +20,9 @@ function mapStateToProps(state) { function QrCodeView(props) { const { Qr, warning } = props; const { message, data } = Qr; - const address = `${isHexPrefixed(data) ? 'ethereum:' : ''}${checksumAddress( - data, - )}`; + const address = `${ + isHexPrefixed(data) ? 'ethereum:' : '' + }${toChecksumHexAddress(data)}`; const qrImage = qrCode(4, 'M'); qrImage.addData(address); qrImage.make(); @@ -50,7 +50,7 @@ function QrCodeView(props) {
); diff --git a/ui/app/components/ui/sender-to-recipient/sender-to-recipient.component.js b/ui/app/components/ui/sender-to-recipient/sender-to-recipient.component.js index 00e099e24..30e42e46f 100644 --- a/ui/app/components/ui/sender-to-recipient/sender-to-recipient.component.js +++ b/ui/app/components/ui/sender-to-recipient/sender-to-recipient.component.js @@ -4,9 +4,10 @@ import classnames from 'classnames'; import copyToClipboard from 'copy-to-clipboard'; import Tooltip from '../tooltip'; import Identicon from '../identicon'; -import { checksumAddress, shortenAddress } from '../../../helpers/utils/util'; +import { shortenAddress } from '../../../helpers/utils/util'; import AccountMismatchWarning from '../account-mismatch-warning/account-mismatch-warning.component'; import { useI18nContext } from '../../../hooks/useI18nContext'; +import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils'; import { DEFAULT_VARIANT, CARDS_VARIANT, @@ -56,7 +57,10 @@ function SenderAddress({ > {!addressOnly && (
- +
)} diff --git a/ui/app/helpers/utils/util.js b/ui/app/helpers/utils/util.js index cea0777a6..512acaef8 100644 --- a/ui/app/helpers/utils/util.js +++ b/ui/app/helpers/utils/util.js @@ -12,6 +12,7 @@ import { RINKEBY_CHAIN_ID, ROPSTEN_CHAIN_ID, } from '../../../../shared/constants/network'; +import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils'; // formatData :: ( date: ) -> String export function formatDate(date, format = "M/d/y 'at' T") { @@ -67,7 +68,7 @@ export function addressSummary( if (!address) { return ''; } - let checked = checksumAddress(address); + let checked = toChecksumHexAddress(address); if (!includeHex) { checked = ethUtil.stripHexPrefix(checked); } @@ -195,18 +196,6 @@ export function exportAsFile(filename, data, type = 'text/csv') { } } -/** - * Safely checksumms a potentially-null address - * - * @param {string} [address] - address to checksum - * @returns {string} checksummed address - * - */ -export function checksumAddress(address) { - const checksummed = address ? ethUtil.toChecksumAddress(address) : ''; - return checksummed; -} - /** * Shortens an Ethereum address for display, preserving the beginning and end. * Returns the given address if it is no longer than 10 characters. diff --git a/ui/app/hooks/useTokensToSearch.js b/ui/app/hooks/useTokensToSearch.js index 4542882f0..e4bc6495e 100644 --- a/ui/app/hooks/useTokensToSearch.js +++ b/ui/app/hooks/useTokensToSearch.js @@ -3,7 +3,6 @@ import { useSelector } from 'react-redux'; import contractMap from '@metamask/contract-metadata'; import BigNumber from 'bignumber.js'; import { isEqual, shuffle } from 'lodash'; -import { checksumAddress } from '../helpers/utils/util'; import { getTokenFiatAmount } from '../helpers/utils/token-util'; import { getTokenExchangeRates, @@ -14,6 +13,7 @@ import { } from '../selectors'; import { getSwapsTokens } from '../ducks/swaps/swaps'; import { isSwapsDefaultTokenSymbol } from '../../../shared/modules/swaps.utils'; +import { toChecksumHexAddress } from '../../../shared/modules/hexstring-utils'; import { useEqualityCheck } from './useEqualityCheck'; const tokenList = shuffle( @@ -58,12 +58,12 @@ export function getRenderableTokenData( ) || ''; const usedIconUrl = iconUrl || - (contractMap[checksumAddress(address)] && - `images/contract/${contractMap[checksumAddress(address)].logo}`); + (contractMap[toChecksumHexAddress(address)] && + `images/contract/${contractMap[toChecksumHexAddress(address)].logo}`); return { ...token, primaryLabel: symbol, - secondaryLabel: name || contractMap[checksumAddress(address)]?.name, + secondaryLabel: name || contractMap[toChecksumHexAddress(address)]?.name, rightPrimaryLabel: string && `${new BigNumber(string).round(6).toString()} ${symbol}`, rightSecondaryLabel: formattedFiat, @@ -71,7 +71,7 @@ export function getRenderableTokenData( identiconAddress: usedIconUrl ? null : address, balance, decimals, - name: name || contractMap[checksumAddress(address)]?.name, + name: name || contractMap[toChecksumHexAddress(address)]?.name, rawFiat, }; } diff --git a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js index 7a761bd9b..48d4ff814 100644 --- a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js +++ b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js @@ -23,11 +23,7 @@ import { getHexGasTotal } from '../../helpers/utils/confirm-tx.util'; import { isBalanceSufficient, calcGasTotal } from '../send/send.utils'; import { conversionGreaterThan } from '../../helpers/utils/conversion-util'; import { MIN_GAS_LIMIT_DEC } from '../send/send.constants'; -import { - checksumAddress, - shortenAddress, - valuesFor, -} from '../../helpers/utils/util'; +import { shortenAddress, valuesFor } from '../../helpers/utils/util'; import { getAdvancedInlineGasShown, getCustomNonceValue, @@ -40,6 +36,7 @@ import { } from '../../selectors'; import { getMostRecentOverviewPage } from '../../ducks/history/history'; import { transactionMatchesNetwork } from '../../../../shared/modules/transaction.utils'; +import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils'; import ConfirmTransactionBase from './confirm-transaction-base.component'; const casedContractMap = Object.keys(contractMap).reduce((acc, base) => { @@ -104,9 +101,9 @@ const mapStateToProps = (state, ownProps) => { const toName = identities[toAddress]?.name || casedContractMap[toAddress]?.name || - shortenAddress(checksumAddress(toAddress)); + shortenAddress(toChecksumHexAddress(toAddress)); - const checksummedAddress = checksumAddress(toAddress); + const checksummedAddress = toChecksumHexAddress(toAddress); const addressBookObject = addressBook[checksummedAddress]; const toEns = ensResolutionsByAddress[checksummedAddress] || ''; const toNickname = addressBookObject ? addressBookObject.name : ''; diff --git a/ui/app/pages/send/send-content/add-recipient/add-recipient.js b/ui/app/pages/send/send-content/add-recipient/add-recipient.js index c1fee499b..5141fda1d 100644 --- a/ui/app/pages/send/send-content/add-recipient/add-recipient.js +++ b/ui/app/pages/send/send-content/add-recipient/add-recipient.js @@ -1,4 +1,3 @@ -import { toChecksumAddress } from 'ethereumjs-util'; import contractMap from '@metamask/contract-metadata'; import { isConfusing } from 'unicode-confusables'; import { @@ -19,6 +18,7 @@ import { import { isBurnAddress, isValidHexAddress, + toChecksumHexAddress, } from '../../../../../shared/modules/hexstring-utils'; export function getToErrorObject(to, sendTokenAddress, chainId) { @@ -44,7 +44,8 @@ export function getToWarningObject(to, tokens = [], sendToken = null) { let toWarning = null; if ( sendToken && - (toChecksumAddress(to) in contractMap || checkExistingAddresses(to, tokens)) + (toChecksumHexAddress(to) in contractMap || + checkExistingAddresses(to, tokens)) ) { toWarning = KNOWN_RECIPIENT_ADDRESS_ERROR; } else if (isValidDomainName(to) && isConfusing(to)) { diff --git a/ui/app/pages/send/send-content/add-recipient/add-recipient.utils.test.js b/ui/app/pages/send/send-content/add-recipient/add-recipient.utils.test.js index 67a87bced..6f7688fa0 100644 --- a/ui/app/pages/send/send-content/add-recipient/add-recipient.utils.test.js +++ b/ui/app/pages/send/send-content/add-recipient/add-recipient.utils.test.js @@ -23,6 +23,7 @@ jest.mock('../../../../../shared/modules/hexstring-utils', () => ({ Boolean(to.match(/^[0xabcdef123456798]+$/u)), ), isBurnAddress: jest.fn(() => false), + toChecksumHexAddress: jest.fn((input) => input), })); describe('add-recipient utils', () => { diff --git a/ui/app/pages/settings/contact-list-tab/view-contact/view-contact.container.js b/ui/app/pages/settings/contact-list-tab/view-contact/view-contact.container.js index 06a753446..275273d0a 100644 --- a/ui/app/pages/settings/contact-list-tab/view-contact/view-contact.container.js +++ b/ui/app/pages/settings/contact-list-tab/view-contact/view-contact.container.js @@ -2,11 +2,11 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withRouter } from 'react-router-dom'; import { getAddressBookEntry } from '../../../../selectors'; -import { checksumAddress } from '../../../../helpers/utils/util'; import { CONTACT_EDIT_ROUTE, CONTACT_LIST_ROUTE, } from '../../../../helpers/constants/routes'; +import { toChecksumHexAddress } from '../../../../../shared/modules/hexstring-utils'; import ViewContact from './view-contact.component'; const mapStateToProps = (state, ownProps) => { @@ -25,7 +25,7 @@ const mapStateToProps = (state, ownProps) => { return { name, address: contact ? address : null, - checkSummedAddress: checksumAddress(address), + checkSummedAddress: toChecksumHexAddress(address), memo, editRoute: CONTACT_EDIT_ROUTE, listRoute: CONTACT_LIST_ROUTE, diff --git a/ui/app/selectors/selectors.js b/ui/app/selectors/selectors.js index 73cebf8db..e5de40dae 100644 --- a/ui/app/selectors/selectors.js +++ b/ui/app/selectors/selectors.js @@ -13,11 +13,7 @@ import { ALLOWED_SWAPS_CHAIN_IDS, } from '../../../shared/constants/swaps'; -import { - shortenAddress, - checksumAddress, - getAccountByAddress, -} from '../helpers/utils/util'; +import { shortenAddress, getAccountByAddress } from '../helpers/utils/util'; import { getValueFromWeiHex, hexToDecimal, @@ -25,6 +21,7 @@ import { import { TEMPLATED_CONFIRMATION_MESSAGE_TYPES } from '../pages/confirmation/templates'; +import { toChecksumHexAddress } from '../../shared/modules/hexstring-utils'; import { getNativeCurrency } from './send'; /** @@ -241,7 +238,7 @@ export function getAddressBook(state) { export function getAddressBookEntry(state, address) { const addressBook = getAddressBook(state); const entry = addressBook.find( - (contact) => contact.address === checksumAddress(address), + (contact) => contact.address === toChecksumHexAddress(address), ); return entry; } diff --git a/ui/app/store/actions.js b/ui/app/store/actions.js index 2d404f52f..cbd90fe84 100644 --- a/ui/app/store/actions.js +++ b/ui/app/store/actions.js @@ -3,7 +3,6 @@ import pify from 'pify'; import log from 'loglevel'; import { capitalize } from 'lodash'; import getBuyEthUrl from '../../../app/scripts/lib/buy-eth-url'; -import { checksumAddress } from '../helpers/utils/util'; import { calcTokenBalance, estimateGasForSend } from '../pages/send/send.utils'; import { fetchLocale, @@ -27,6 +26,7 @@ import { import { switchedToUnconnectedAccount } from '../ducks/alerts/unconnected-account'; import { getUnconnectedAccountAlertEnabledness } from '../ducks/metamask/metamask'; import { LISTED_CONTRACT_ADDRESSES } from '../../../shared/constants/tokens'; +import { toChecksumHexAddress } from '../../../shared/modules/hexstring-utils'; import * as actionConstants from './actionConstants'; let background = null; @@ -1729,7 +1729,7 @@ export function addToAddressBook(recipient, nickname = '', memo = '') { let set; try { set = await promisifiedBackground.setAddressBook( - checksumAddress(recipient), + toChecksumHexAddress(recipient), nickname, chainId, memo, @@ -1755,7 +1755,7 @@ export function removeFromAddressBook(chainId, addressToRemove) { return async () => { await promisifiedBackground.removeFromAddressBook( chainId, - checksumAddress(addressToRemove), + toChecksumHexAddress(addressToRemove), ); }; } diff --git a/ui/lib/icon-factory.js b/ui/lib/icon-factory.js index ac9a035d2..132f5330d 100644 --- a/ui/lib/icon-factory.js +++ b/ui/lib/icon-factory.js @@ -1,7 +1,8 @@ import contractMap from '@metamask/contract-metadata'; -import { isHexString, addHexPrefix } from 'ethereumjs-util'; -import { isValidHexAddress } from '../../shared/modules/hexstring-utils'; -import { checksumAddress } from '../app/helpers/utils/util'; +import { + isValidHexAddress, + toChecksumHexAddress, +} from '../../shared/modules/hexstring-utils'; let iconFactory; @@ -18,11 +19,7 @@ function IconFactory(jazzicon) { } IconFactory.prototype.iconForAddress = function (address, diameter) { - let addr = address; - - if (isHexString(addHexPrefix(address))) { - addr = checksumAddress(addHexPrefix(address)); - } + const addr = toChecksumHexAddress(address); if (iconExistsFor(addr)) { return imageElFor(addr);