use safer toChecksum utility (#11117)

feature/default_network_editable
Brad Decker 4 years ago committed by ryanml
parent 001a01e5b2
commit 03961715f7
  1. 6
      app/scripts/controllers/ens/index.js
  2. 4
      app/scripts/controllers/token-rates.js
  3. 13
      app/scripts/metamask-controller.js
  4. 4
      app/scripts/migrations/039.js
  5. 20
      shared/modules/hexstring-utils.js
  6. 16
      ui/app/components/app/account-list-item/account-list-item-component.test.js
  7. 4
      ui/app/components/app/account-list-item/account-list-item.js
  8. 4
      ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.component.js
  9. 5
      ui/app/components/app/selected-account/selected-account.component.js
  10. 4
      ui/app/components/app/transaction-list-item-details/transaction-list-item-details.container.js
  11. 9
      ui/app/components/ui/identicon/identicon.component.js
  12. 10
      ui/app/components/ui/qr-code/qr-code.js
  13. 12
      ui/app/components/ui/sender-to-recipient/sender-to-recipient.component.js
  14. 15
      ui/app/helpers/utils/util.js
  15. 10
      ui/app/hooks/useTokensToSearch.js
  16. 11
      ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js
  17. 5
      ui/app/pages/send/send-content/add-recipient/add-recipient.js
  18. 1
      ui/app/pages/send/send-content/add-recipient/add-recipient.utils.test.js
  19. 4
      ui/app/pages/settings/contact-list-tab/view-contact/view-contact.container.js
  20. 9
      ui/app/selectors/selectors.js
  21. 6
      ui/app/store/actions.js
  22. 13
      ui/lib/icon-factory.js

@ -1,8 +1,8 @@
import punycode from 'punycode/punycode'; import punycode from 'punycode/punycode';
import { toChecksumAddress } from 'ethereumjs-util';
import { ObservableStore } from '@metamask/obs-store'; import { ObservableStore } from '@metamask/obs-store';
import log from 'loglevel'; import log from 'loglevel';
import { CHAIN_ID_TO_NETWORK_ID_MAP } from '../../../../shared/constants/network'; import { CHAIN_ID_TO_NETWORK_ID_MAP } from '../../../../shared/constants/network';
import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils';
import Ens from './ens'; import Ens from './ens';
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
@ -43,7 +43,7 @@ export default class EnsController {
} }
reverseResolveAddress(address) { reverseResolveAddress(address) {
return this._reverseResolveAddress(toChecksumAddress(address)); return this._reverseResolveAddress(toChecksumHexAddress(address));
} }
async _reverseResolveAddress(address) { async _reverseResolveAddress(address) {
@ -79,7 +79,7 @@ export default class EnsController {
return undefined; return undefined;
} }
if (toChecksumAddress(registeredAddress) !== address) { if (toChecksumHexAddress(registeredAddress) !== address) {
return undefined; return undefined;
} }

@ -1,8 +1,8 @@
import { ObservableStore } from '@metamask/obs-store'; import { ObservableStore } from '@metamask/obs-store';
import log from 'loglevel'; import log from 'loglevel';
import { normalize as normalizeAddress } from 'eth-sig-util'; import { normalize as normalizeAddress } from 'eth-sig-util';
import { toChecksumAddress } from 'ethereumjs-util';
import getFetchWithTimeout from '../../../shared/modules/fetch-with-timeout'; import getFetchWithTimeout from '../../../shared/modules/fetch-with-timeout';
import { toChecksumHexAddress } from '../../../shared/modules/hexstring-utils';
const fetchWithTimeout = getFetchWithTimeout(30000); const fetchWithTimeout = getFetchWithTimeout(30000);
@ -45,7 +45,7 @@ export default class TokenRatesController {
this._tokens.forEach((token) => { this._tokens.forEach((token) => {
const price = const price =
prices[token.address.toLowerCase()] || prices[token.address.toLowerCase()] ||
prices[toChecksumAddress(token.address)]; prices[toChecksumHexAddress(token.address)];
contractExchangeRates[normalizeAddress(token.address)] = price contractExchangeRates[normalizeAddress(token.address)] = price
? price[nativeCurrency] ? price[nativeCurrency]
: 0; : 0;

@ -10,7 +10,7 @@ import createSubscriptionManager from 'eth-json-rpc-filters/subscriptionManager'
import providerAsMiddleware from 'eth-json-rpc-middleware/providerAsMiddleware'; import providerAsMiddleware from 'eth-json-rpc-middleware/providerAsMiddleware';
import KeyringController from 'eth-keyring-controller'; import KeyringController from 'eth-keyring-controller';
import { Mutex } from 'await-semaphore'; import { Mutex } from 'await-semaphore';
import { toChecksumAddress, stripHexPrefix } from 'ethereumjs-util'; import { stripHexPrefix } from 'ethereumjs-util';
import log from 'loglevel'; import log from 'loglevel';
import TrezorKeyring from 'eth-trezor-keyring'; import TrezorKeyring from 'eth-trezor-keyring';
import LedgerBridgeKeyring from '@metamask/eth-ledger-bridge-keyring'; import LedgerBridgeKeyring from '@metamask/eth-ledger-bridge-keyring';
@ -27,6 +27,7 @@ import {
import { TRANSACTION_STATUSES } from '../../shared/constants/transaction'; import { TRANSACTION_STATUSES } from '../../shared/constants/transaction';
import { MAINNET_CHAIN_ID } from '../../shared/constants/network'; import { MAINNET_CHAIN_ID } from '../../shared/constants/network';
import { UI_NOTIFICATIONS } from '../../shared/notifications'; import { UI_NOTIFICATIONS } from '../../shared/notifications';
import { toChecksumHexAddress } from '../../shared/modules/hexstring-utils';
import ComposableObservableStore from './lib/ComposableObservableStore'; import ComposableObservableStore from './lib/ComposableObservableStore';
import AccountTracker from './lib/account-tracker'; import AccountTracker from './lib/account-tracker';
@ -1107,14 +1108,14 @@ export default class MetamaskController extends EventEmitter {
// Filter ERC20 tokens // Filter ERC20 tokens
const filteredAccountTokens = {}; const filteredAccountTokens = {};
Object.keys(accountTokens).forEach((address) => { Object.keys(accountTokens).forEach((address) => {
const checksummedAddress = toChecksumAddress(address); const checksummedAddress = toChecksumHexAddress(address);
filteredAccountTokens[checksummedAddress] = {}; filteredAccountTokens[checksummedAddress] = {};
Object.keys(accountTokens[address]).forEach((chainId) => { Object.keys(accountTokens[address]).forEach((chainId) => {
filteredAccountTokens[checksummedAddress][chainId] = filteredAccountTokens[checksummedAddress][chainId] =
chainId === MAINNET_CHAIN_ID chainId === MAINNET_CHAIN_ID
? accountTokens[address][chainId].filter( ? accountTokens[address][chainId].filter(
({ address: tokenAddress }) => { ({ address: tokenAddress }) => {
const checksumAddress = toChecksumAddress(tokenAddress); const checksumAddress = toChecksumHexAddress(tokenAddress);
return contractMap[checksumAddress] return contractMap[checksumAddress]
? contractMap[checksumAddress].erc20 ? contractMap[checksumAddress].erc20
: true; : true;
@ -1151,10 +1152,10 @@ export default class MetamaskController extends EventEmitter {
const accounts = { const accounts = {
hd: hdAccounts hd: hdAccounts
.filter((item, pos) => hdAccounts.indexOf(item) === pos) .filter((item, pos) => hdAccounts.indexOf(item) === pos)
.map((address) => toChecksumAddress(address)), .map((address) => toChecksumHexAddress(address)),
simpleKeyPair: simpleKeyPairAccounts simpleKeyPair: simpleKeyPairAccounts
.filter((item, pos) => simpleKeyPairAccounts.indexOf(item) === pos) .filter((item, pos) => simpleKeyPairAccounts.indexOf(item) === pos)
.map((address) => toChecksumAddress(address)), .map((address) => toChecksumHexAddress(address)),
ledger: [], ledger: [],
trezor: [], trezor: [],
}; };
@ -1164,7 +1165,7 @@ export default class MetamaskController extends EventEmitter {
let { transactions } = this.txController.store.getState(); let { transactions } = this.txController.store.getState();
// delete tx for other accounts that we're not importing // delete tx for other accounts that we're not importing
transactions = Object.values(transactions).filter((tx) => { transactions = Object.values(transactions).filter((tx) => {
const checksummedTxFrom = toChecksumAddress(tx.txParams.from); const checksummedTxFrom = toChecksumHexAddress(tx.txParams.from);
return accounts.hd.includes(checksummedTxFrom); return accounts.hd.includes(checksummedTxFrom);
}); });

@ -1,5 +1,5 @@
import { cloneDeep } from 'lodash'; import { cloneDeep } from 'lodash';
import { toChecksumAddress } from 'ethereumjs-util'; import { toChecksumHexAddress } from '../../../shared/modules/hexstring-utils';
const version = 39; const version = 39;
@ -12,7 +12,7 @@ function isOldDai(token = {}) {
token && token &&
typeof token === 'object' && typeof token === 'object' &&
token.symbol === DAI_V1_TOKEN_SYMBOL && token.symbol === DAI_V1_TOKEN_SYMBOL &&
toChecksumAddress(token.address) === DAI_V1_CONTRACT_ADDRESS toChecksumHexAddress(token.address) === DAI_V1_CONTRACT_ADDRESS
); );
} }

@ -3,6 +3,7 @@ import {
isValidAddress, isValidAddress,
isValidChecksumAddress, isValidChecksumAddress,
addHexPrefix, addHexPrefix,
toChecksumAddress,
} from 'ethereumjs-util'; } from 'ethereumjs-util';
export const BURN_ADDRESS = '0x0000000000000000000000000000000000000000'; export const BURN_ADDRESS = '0x0000000000000000000000000000000000000000';
@ -51,3 +52,22 @@ export function isValidHexAddress(
return isValidAddress(addressToCheck); 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));
}

@ -1,18 +1,19 @@
import React from 'react'; import React from 'react';
import { shallow } from 'enzyme'; import { shallow } from 'enzyme';
import sinon from 'sinon'; import sinon from 'sinon';
import * as utils from '../../../helpers/utils/util';
import Identicon from '../../ui/identicon'; import Identicon from '../../ui/identicon';
import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils';
import AccountListItem from './account-list-item'; import AccountListItem from './account-list-item';
jest.mock('../../../../shared/modules/hexstring-utils', () => ({
toChecksumHexAddress: jest.fn(() => 'mockCheckSumAddress'),
}));
describe('AccountListItem Component', () => { describe('AccountListItem Component', () => {
let wrapper, propsMethodSpies, checksumAddressStub; let wrapper, propsMethodSpies;
describe('render', () => { describe('render', () => {
beforeAll(() => { beforeAll(() => {
checksumAddressStub = sinon
.stub(utils, 'checksumAddress')
.returns('mockCheckSumAddress');
propsMethodSpies = { propsMethodSpies = {
handleClick: sinon.spy(), handleClick: sinon.spy(),
}; };
@ -36,7 +37,6 @@ describe('AccountListItem Component', () => {
afterEach(() => { afterEach(() => {
propsMethodSpies.handleClick.resetHistory(); propsMethodSpies.handleClick.resetHistory();
checksumAddressStub.resetHistory();
}); });
afterAll(() => { afterAll(() => {
@ -126,9 +126,7 @@ describe('AccountListItem Component', () => {
expect( expect(
wrapper.find('.account-list-item__account-address').text(), wrapper.find('.account-list-item__account-address').text(),
).toStrictEqual('mockCheckSumAddress'); ).toStrictEqual('mockCheckSumAddress');
expect(checksumAddressStub.getCall(0).args).toStrictEqual([ expect(toChecksumHexAddress).toHaveBeenCalledWith('mockAddress');
'mockAddress',
]);
}); });
it('should not render the account address as a checksumAddress if displayAddress is false', () => { it('should not render the account address as a checksumAddress if displayAddress is false', () => {

@ -1,8 +1,8 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { checksumAddress } from '../../../helpers/utils/util';
import Identicon from '../../ui/identicon'; import Identicon from '../../ui/identicon';
import AccountMismatchWarning from '../../ui/account-mismatch-warning/account-mismatch-warning.component'; import AccountMismatchWarning from '../../ui/account-mismatch-warning/account-mismatch-warning.component';
import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils';
export default function AccountListItem({ export default function AccountListItem({
account, account,
@ -34,7 +34,7 @@ export default function AccountListItem({
{displayAddress && name && ( {displayAddress && name && (
<div className="account-list-item__account-address"> <div className="account-list-item__account-address">
{checksumAddress(address)} {toChecksumHexAddress(address)}
</div> </div>
)} )}
</div> </div>

@ -4,10 +4,10 @@ import React, { Component } from 'react';
import { stripHexPrefix } from 'ethereumjs-util'; import { stripHexPrefix } from 'ethereumjs-util';
import copyToClipboard from 'copy-to-clipboard'; import copyToClipboard from 'copy-to-clipboard';
import { checksumAddress } from '../../../../helpers/utils/util';
import ReadOnlyInput from '../../../ui/readonly-input'; import ReadOnlyInput from '../../../ui/readonly-input';
import Button from '../../../ui/button'; import Button from '../../../ui/button';
import AccountModalContainer from '../account-modal-container'; import AccountModalContainer from '../account-modal-container';
import { toChecksumHexAddress } from '../../../../../shared/modules/hexstring-utils';
export default class ExportPrivateKeyModal extends Component { export default class ExportPrivateKeyModal extends Component {
static contextTypes = { static contextTypes = {
@ -149,7 +149,7 @@ export default class ExportPrivateKeyModal extends Component {
<span className="export-private-key-modal__account-name">{name}</span> <span className="export-private-key-modal__account-name">{name}</span>
<ReadOnlyInput <ReadOnlyInput
wrapperClass="ellip-address-wrapper" wrapperClass="ellip-address-wrapper"
value={checksumAddress(address)} value={toChecksumHexAddress(address)}
/> />
<div className="export-private-key-modal__divider" /> <div className="export-private-key-modal__divider" />
<span className="export-private-key-modal__body-title"> <span className="export-private-key-modal__body-title">

@ -1,9 +1,10 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import copyToClipboard from 'copy-to-clipboard'; 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 Tooltip from '../../ui/tooltip';
import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils';
class SelectedAccount extends Component { class SelectedAccount extends Component {
state = { state = {
@ -32,7 +33,7 @@ class SelectedAccount extends Component {
render() { render() {
const { t } = this.context; const { t } = this.context;
const { selectedIdentity } = this.props; const { selectedIdentity } = this.props;
const checksummedAddress = checksumAddress(selectedIdentity.address); const checksummedAddress = toChecksumHexAddress(selectedIdentity.address);
return ( return (
<div className="selected-account"> <div className="selected-account">

@ -1,10 +1,10 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { checksumAddress } from '../../../helpers/utils/util';
import { tryReverseResolveAddress } from '../../../store/actions'; import { tryReverseResolveAddress } from '../../../store/actions';
import { import {
getAddressBook, getAddressBook,
getRpcPrefsForCurrentProvider, getRpcPrefsForCurrentProvider,
} from '../../../selectors'; } from '../../../selectors';
import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils';
import TransactionListItemDetails from './transaction-list-item-details.component'; import TransactionListItemDetails from './transaction-list-item-details.component';
const mapStateToProps = (state, ownProps) => { const mapStateToProps = (state, ownProps) => {
@ -13,7 +13,7 @@ const mapStateToProps = (state, ownProps) => {
const { recipientAddress, senderAddress } = ownProps; const { recipientAddress, senderAddress } = ownProps;
let recipientEns; let recipientEns;
if (recipientAddress) { if (recipientAddress) {
const address = checksumAddress(recipientAddress); const address = toChecksumHexAddress(recipientAddress);
recipientEns = ensResolutionsByAddress[address] || ''; recipientEns = ensResolutionsByAddress[address] || '';
} }
const addressBook = getAddressBook(state); const addressBook = getAddressBook(state);

@ -2,9 +2,8 @@ import React, { PureComponent } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import classnames from 'classnames'; import classnames from 'classnames';
import contractMap from '@metamask/contract-metadata'; 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 Jazzicon from '../jazzicon';
import BlockieIdenticon from './blockieIdenticon'; import BlockieIdenticon from './blockieIdenticon';
@ -86,11 +85,9 @@ export default class Identicon extends PureComponent {
} }
if (address) { if (address) {
const checksummedAddress = const checksummedAddress = toChecksumHexAddress(address);
isHexString(addHexPrefix(address)) &&
checksumAddress(addHexPrefix(address));
if (contractMap[checksummedAddress]?.logo) { if (checksummedAddress && contractMap[checksummedAddress]?.logo) {
return this.renderJazzicon(); return this.renderJazzicon();
} }

@ -4,7 +4,7 @@ import qrCode from 'qrcode-generator';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { isHexPrefixed } from 'ethereumjs-util'; import { isHexPrefixed } from 'ethereumjs-util';
import ReadOnlyInput from '../readonly-input/readonly-input'; 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); export default connect(mapStateToProps)(QrCodeView);
@ -20,9 +20,9 @@ function mapStateToProps(state) {
function QrCodeView(props) { function QrCodeView(props) {
const { Qr, warning } = props; const { Qr, warning } = props;
const { message, data } = Qr; const { message, data } = Qr;
const address = `${isHexPrefixed(data) ? 'ethereum:' : ''}${checksumAddress( const address = `${
data, isHexPrefixed(data) ? 'ethereum:' : ''
)}`; }${toChecksumHexAddress(data)}`;
const qrImage = qrCode(4, 'M'); const qrImage = qrCode(4, 'M');
qrImage.addData(address); qrImage.addData(address);
qrImage.make(); qrImage.make();
@ -50,7 +50,7 @@ function QrCodeView(props) {
<ReadOnlyInput <ReadOnlyInput
wrapperClass="ellip-address-wrapper" wrapperClass="ellip-address-wrapper"
autoFocus autoFocus
value={checksumAddress(data)} value={toChecksumHexAddress(data)}
/> />
</div> </div>
); );

@ -4,9 +4,10 @@ import classnames from 'classnames';
import copyToClipboard from 'copy-to-clipboard'; import copyToClipboard from 'copy-to-clipboard';
import Tooltip from '../tooltip'; import Tooltip from '../tooltip';
import Identicon from '../identicon'; 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 AccountMismatchWarning from '../account-mismatch-warning/account-mismatch-warning.component';
import { useI18nContext } from '../../../hooks/useI18nContext'; import { useI18nContext } from '../../../hooks/useI18nContext';
import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils';
import { import {
DEFAULT_VARIANT, DEFAULT_VARIANT,
CARDS_VARIANT, CARDS_VARIANT,
@ -56,7 +57,10 @@ function SenderAddress({
> >
{!addressOnly && ( {!addressOnly && (
<div className="sender-to-recipient__sender-icon"> <div className="sender-to-recipient__sender-icon">
<Identicon address={checksumAddress(senderAddress)} diameter={24} /> <Identicon
address={toChecksumHexAddress(senderAddress)}
diameter={24}
/>
</div> </div>
)} )}
<Tooltip <Tooltip
@ -203,8 +207,8 @@ export default function SenderToRecipient({
warnUserOnAccountMismatch, warnUserOnAccountMismatch,
}) { }) {
const t = useI18nContext(); const t = useI18nContext();
const checksummedSenderAddress = checksumAddress(senderAddress); const checksummedSenderAddress = toChecksumHexAddress(senderAddress);
const checksummedRecipientAddress = checksumAddress(recipientAddress); const checksummedRecipientAddress = toChecksumHexAddress(recipientAddress);
return ( return (
<div className={classnames('sender-to-recipient', variantHash[variant])}> <div className={classnames('sender-to-recipient', variantHash[variant])}>

@ -12,6 +12,7 @@ import {
RINKEBY_CHAIN_ID, RINKEBY_CHAIN_ID,
ROPSTEN_CHAIN_ID, ROPSTEN_CHAIN_ID,
} from '../../../../shared/constants/network'; } from '../../../../shared/constants/network';
import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils';
// formatData :: ( date: <Unix Timestamp> ) -> String // formatData :: ( date: <Unix Timestamp> ) -> String
export function formatDate(date, format = "M/d/y 'at' T") { export function formatDate(date, format = "M/d/y 'at' T") {
@ -67,7 +68,7 @@ export function addressSummary(
if (!address) { if (!address) {
return ''; return '';
} }
let checked = checksumAddress(address); let checked = toChecksumHexAddress(address);
if (!includeHex) { if (!includeHex) {
checked = ethUtil.stripHexPrefix(checked); 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. * Shortens an Ethereum address for display, preserving the beginning and end.
* Returns the given address if it is no longer than 10 characters. * Returns the given address if it is no longer than 10 characters.

@ -3,7 +3,6 @@ import { useSelector } from 'react-redux';
import contractMap from '@metamask/contract-metadata'; import contractMap from '@metamask/contract-metadata';
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import { isEqual, shuffle } from 'lodash'; import { isEqual, shuffle } from 'lodash';
import { checksumAddress } from '../helpers/utils/util';
import { getTokenFiatAmount } from '../helpers/utils/token-util'; import { getTokenFiatAmount } from '../helpers/utils/token-util';
import { import {
getTokenExchangeRates, getTokenExchangeRates,
@ -14,6 +13,7 @@ import {
} from '../selectors'; } from '../selectors';
import { getSwapsTokens } from '../ducks/swaps/swaps'; import { getSwapsTokens } from '../ducks/swaps/swaps';
import { isSwapsDefaultTokenSymbol } from '../../../shared/modules/swaps.utils'; import { isSwapsDefaultTokenSymbol } from '../../../shared/modules/swaps.utils';
import { toChecksumHexAddress } from '../../../shared/modules/hexstring-utils';
import { useEqualityCheck } from './useEqualityCheck'; import { useEqualityCheck } from './useEqualityCheck';
const tokenList = shuffle( const tokenList = shuffle(
@ -58,12 +58,12 @@ export function getRenderableTokenData(
) || ''; ) || '';
const usedIconUrl = const usedIconUrl =
iconUrl || iconUrl ||
(contractMap[checksumAddress(address)] && (contractMap[toChecksumHexAddress(address)] &&
`images/contract/${contractMap[checksumAddress(address)].logo}`); `images/contract/${contractMap[toChecksumHexAddress(address)].logo}`);
return { return {
...token, ...token,
primaryLabel: symbol, primaryLabel: symbol,
secondaryLabel: name || contractMap[checksumAddress(address)]?.name, secondaryLabel: name || contractMap[toChecksumHexAddress(address)]?.name,
rightPrimaryLabel: rightPrimaryLabel:
string && `${new BigNumber(string).round(6).toString()} ${symbol}`, string && `${new BigNumber(string).round(6).toString()} ${symbol}`,
rightSecondaryLabel: formattedFiat, rightSecondaryLabel: formattedFiat,
@ -71,7 +71,7 @@ export function getRenderableTokenData(
identiconAddress: usedIconUrl ? null : address, identiconAddress: usedIconUrl ? null : address,
balance, balance,
decimals, decimals,
name: name || contractMap[checksumAddress(address)]?.name, name: name || contractMap[toChecksumHexAddress(address)]?.name,
rawFiat, rawFiat,
}; };
} }

@ -23,11 +23,7 @@ import { getHexGasTotal } from '../../helpers/utils/confirm-tx.util';
import { isBalanceSufficient, calcGasTotal } from '../send/send.utils'; import { isBalanceSufficient, calcGasTotal } from '../send/send.utils';
import { conversionGreaterThan } from '../../helpers/utils/conversion-util'; import { conversionGreaterThan } from '../../helpers/utils/conversion-util';
import { MIN_GAS_LIMIT_DEC } from '../send/send.constants'; import { MIN_GAS_LIMIT_DEC } from '../send/send.constants';
import { import { shortenAddress, valuesFor } from '../../helpers/utils/util';
checksumAddress,
shortenAddress,
valuesFor,
} from '../../helpers/utils/util';
import { import {
getAdvancedInlineGasShown, getAdvancedInlineGasShown,
getCustomNonceValue, getCustomNonceValue,
@ -40,6 +36,7 @@ import {
} from '../../selectors'; } from '../../selectors';
import { getMostRecentOverviewPage } from '../../ducks/history/history'; import { getMostRecentOverviewPage } from '../../ducks/history/history';
import { transactionMatchesNetwork } from '../../../../shared/modules/transaction.utils'; import { transactionMatchesNetwork } from '../../../../shared/modules/transaction.utils';
import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils';
import ConfirmTransactionBase from './confirm-transaction-base.component'; import ConfirmTransactionBase from './confirm-transaction-base.component';
const casedContractMap = Object.keys(contractMap).reduce((acc, base) => { const casedContractMap = Object.keys(contractMap).reduce((acc, base) => {
@ -104,9 +101,9 @@ const mapStateToProps = (state, ownProps) => {
const toName = const toName =
identities[toAddress]?.name || identities[toAddress]?.name ||
casedContractMap[toAddress]?.name || casedContractMap[toAddress]?.name ||
shortenAddress(checksumAddress(toAddress)); shortenAddress(toChecksumHexAddress(toAddress));
const checksummedAddress = checksumAddress(toAddress); const checksummedAddress = toChecksumHexAddress(toAddress);
const addressBookObject = addressBook[checksummedAddress]; const addressBookObject = addressBook[checksummedAddress];
const toEns = ensResolutionsByAddress[checksummedAddress] || ''; const toEns = ensResolutionsByAddress[checksummedAddress] || '';
const toNickname = addressBookObject ? addressBookObject.name : ''; const toNickname = addressBookObject ? addressBookObject.name : '';

@ -1,4 +1,3 @@
import { toChecksumAddress } from 'ethereumjs-util';
import contractMap from '@metamask/contract-metadata'; import contractMap from '@metamask/contract-metadata';
import { isConfusing } from 'unicode-confusables'; import { isConfusing } from 'unicode-confusables';
import { import {
@ -19,6 +18,7 @@ import {
import { import {
isBurnAddress, isBurnAddress,
isValidHexAddress, isValidHexAddress,
toChecksumHexAddress,
} from '../../../../../shared/modules/hexstring-utils'; } from '../../../../../shared/modules/hexstring-utils';
export function getToErrorObject(to, sendTokenAddress, chainId) { export function getToErrorObject(to, sendTokenAddress, chainId) {
@ -44,7 +44,8 @@ export function getToWarningObject(to, tokens = [], sendToken = null) {
let toWarning = null; let toWarning = null;
if ( if (
sendToken && sendToken &&
(toChecksumAddress(to) in contractMap || checkExistingAddresses(to, tokens)) (toChecksumHexAddress(to) in contractMap ||
checkExistingAddresses(to, tokens))
) { ) {
toWarning = KNOWN_RECIPIENT_ADDRESS_ERROR; toWarning = KNOWN_RECIPIENT_ADDRESS_ERROR;
} else if (isValidDomainName(to) && isConfusing(to)) { } else if (isValidDomainName(to) && isConfusing(to)) {

@ -23,6 +23,7 @@ jest.mock('../../../../../shared/modules/hexstring-utils', () => ({
Boolean(to.match(/^[0xabcdef123456798]+$/u)), Boolean(to.match(/^[0xabcdef123456798]+$/u)),
), ),
isBurnAddress: jest.fn(() => false), isBurnAddress: jest.fn(() => false),
toChecksumHexAddress: jest.fn((input) => input),
})); }));
describe('add-recipient utils', () => { describe('add-recipient utils', () => {

@ -2,11 +2,11 @@ import { compose } from 'redux';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom'; import { withRouter } from 'react-router-dom';
import { getAddressBookEntry } from '../../../../selectors'; import { getAddressBookEntry } from '../../../../selectors';
import { checksumAddress } from '../../../../helpers/utils/util';
import { import {
CONTACT_EDIT_ROUTE, CONTACT_EDIT_ROUTE,
CONTACT_LIST_ROUTE, CONTACT_LIST_ROUTE,
} from '../../../../helpers/constants/routes'; } from '../../../../helpers/constants/routes';
import { toChecksumHexAddress } from '../../../../../shared/modules/hexstring-utils';
import ViewContact from './view-contact.component'; import ViewContact from './view-contact.component';
const mapStateToProps = (state, ownProps) => { const mapStateToProps = (state, ownProps) => {
@ -25,7 +25,7 @@ const mapStateToProps = (state, ownProps) => {
return { return {
name, name,
address: contact ? address : null, address: contact ? address : null,
checkSummedAddress: checksumAddress(address), checkSummedAddress: toChecksumHexAddress(address),
memo, memo,
editRoute: CONTACT_EDIT_ROUTE, editRoute: CONTACT_EDIT_ROUTE,
listRoute: CONTACT_LIST_ROUTE, listRoute: CONTACT_LIST_ROUTE,

@ -13,11 +13,7 @@ import {
ALLOWED_SWAPS_CHAIN_IDS, ALLOWED_SWAPS_CHAIN_IDS,
} from '../../../shared/constants/swaps'; } from '../../../shared/constants/swaps';
import { import { shortenAddress, getAccountByAddress } from '../helpers/utils/util';
shortenAddress,
checksumAddress,
getAccountByAddress,
} from '../helpers/utils/util';
import { import {
getValueFromWeiHex, getValueFromWeiHex,
hexToDecimal, hexToDecimal,
@ -25,6 +21,7 @@ import {
import { TEMPLATED_CONFIRMATION_MESSAGE_TYPES } from '../pages/confirmation/templates'; import { TEMPLATED_CONFIRMATION_MESSAGE_TYPES } from '../pages/confirmation/templates';
import { toChecksumHexAddress } from '../../shared/modules/hexstring-utils';
import { getNativeCurrency } from './send'; import { getNativeCurrency } from './send';
/** /**
@ -241,7 +238,7 @@ export function getAddressBook(state) {
export function getAddressBookEntry(state, address) { export function getAddressBookEntry(state, address) {
const addressBook = getAddressBook(state); const addressBook = getAddressBook(state);
const entry = addressBook.find( const entry = addressBook.find(
(contact) => contact.address === checksumAddress(address), (contact) => contact.address === toChecksumHexAddress(address),
); );
return entry; return entry;
} }

@ -3,7 +3,6 @@ import pify from 'pify';
import log from 'loglevel'; import log from 'loglevel';
import { capitalize } from 'lodash'; import { capitalize } from 'lodash';
import getBuyEthUrl from '../../../app/scripts/lib/buy-eth-url'; import getBuyEthUrl from '../../../app/scripts/lib/buy-eth-url';
import { checksumAddress } from '../helpers/utils/util';
import { calcTokenBalance, estimateGasForSend } from '../pages/send/send.utils'; import { calcTokenBalance, estimateGasForSend } from '../pages/send/send.utils';
import { import {
fetchLocale, fetchLocale,
@ -27,6 +26,7 @@ import {
import { switchedToUnconnectedAccount } from '../ducks/alerts/unconnected-account'; import { switchedToUnconnectedAccount } from '../ducks/alerts/unconnected-account';
import { getUnconnectedAccountAlertEnabledness } from '../ducks/metamask/metamask'; import { getUnconnectedAccountAlertEnabledness } from '../ducks/metamask/metamask';
import { LISTED_CONTRACT_ADDRESSES } from '../../../shared/constants/tokens'; import { LISTED_CONTRACT_ADDRESSES } from '../../../shared/constants/tokens';
import { toChecksumHexAddress } from '../../../shared/modules/hexstring-utils';
import * as actionConstants from './actionConstants'; import * as actionConstants from './actionConstants';
let background = null; let background = null;
@ -1729,7 +1729,7 @@ export function addToAddressBook(recipient, nickname = '', memo = '') {
let set; let set;
try { try {
set = await promisifiedBackground.setAddressBook( set = await promisifiedBackground.setAddressBook(
checksumAddress(recipient), toChecksumHexAddress(recipient),
nickname, nickname,
chainId, chainId,
memo, memo,
@ -1755,7 +1755,7 @@ export function removeFromAddressBook(chainId, addressToRemove) {
return async () => { return async () => {
await promisifiedBackground.removeFromAddressBook( await promisifiedBackground.removeFromAddressBook(
chainId, chainId,
checksumAddress(addressToRemove), toChecksumHexAddress(addressToRemove),
); );
}; };
} }

@ -1,7 +1,8 @@
import contractMap from '@metamask/contract-metadata'; import contractMap from '@metamask/contract-metadata';
import { isHexString, addHexPrefix } from 'ethereumjs-util'; import {
import { isValidHexAddress } from '../../shared/modules/hexstring-utils'; isValidHexAddress,
import { checksumAddress } from '../app/helpers/utils/util'; toChecksumHexAddress,
} from '../../shared/modules/hexstring-utils';
let iconFactory; let iconFactory;
@ -18,11 +19,7 @@ function IconFactory(jazzicon) {
} }
IconFactory.prototype.iconForAddress = function (address, diameter) { IconFactory.prototype.iconForAddress = function (address, diameter) {
let addr = address; const addr = toChecksumHexAddress(address);
if (isHexString(addHexPrefix(address))) {
addr = checksumAddress(addHexPrefix(address));
}
if (iconExistsFor(addr)) { if (iconExistsFor(addr)) {
return imageElFor(addr); return imageElFor(addr);

Loading…
Cancel
Save