1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-22 18:00:18 +01:00

create safer isValidAddress method (#11089)

This commit is contained in:
Brad Decker 2021-05-17 14:00:59 -05:00 committed by ryanml
parent 761288b18f
commit 8254213b9c
20 changed files with 227 additions and 171 deletions

View File

@ -2,12 +2,12 @@ import { strict as assert } from 'assert';
import { ObservableStore } from '@metamask/obs-store';
import { ethErrors } from 'eth-rpc-errors';
import { normalize as normalizeAddress } from 'eth-sig-util';
import { isValidAddress } from 'ethereumjs-util';
import ethers from 'ethers';
import log from 'loglevel';
import { LISTED_CONTRACT_ADDRESSES } from '../../../shared/constants/tokens';
import { NETWORK_TYPE_TO_ID_MAP } from '../../../shared/constants/network';
import { isPrefixedFormattedHexString } from '../../../shared/modules/network.utils';
import { isValidHexAddress } from '../../../shared/modules/hexstring-utils';
import { NETWORK_EVENTS } from './network';
export default class PreferencesController {
@ -836,7 +836,7 @@ export default class PreferencesController {
`Invalid decimals "${decimals}": must be 0 <= 36.`,
);
}
if (!isValidAddress(address)) {
if (!isValidHexAddress(address, { allowNonPrefixed: false })) {
throw ethErrors.rpc.invalidParams(`Invalid address "${address}".`);
}
}

View File

@ -1,7 +1,7 @@
import { isValidAddress } from 'ethereumjs-util';
import { ethErrors } from 'eth-rpc-errors';
import { addHexPrefix } from '../../../lib/util';
import { TRANSACTION_STATUSES } from '../../../../../shared/constants/transaction';
import { isValidHexAddress } from '../../../../../shared/modules/hexstring-utils';
const normalizers = {
from: (from) => addHexPrefix(from),
@ -110,7 +110,7 @@ export function validateFrom(txParams) {
`Invalid "from" address "${txParams.from}": not a string.`,
);
}
if (!isValidAddress(txParams.from)) {
if (!isValidHexAddress(txParams.from, { allowNonPrefixed: false })) {
throw ethErrors.rpc.invalidParams('Invalid "from" address.');
}
}
@ -128,7 +128,10 @@ export function validateRecipient(txParams) {
} else {
throw ethErrors.rpc.invalidParams('Invalid "to" address.');
}
} else if (txParams.to !== undefined && !isValidAddress(txParams.to)) {
} else if (
txParams.to !== undefined &&
!isValidHexAddress(txParams.to, { allowNonPrefixed: false })
) {
throw ethErrors.rpc.invalidParams('Invalid "to" address.');
}
return txParams;

View File

@ -3,12 +3,12 @@ import assert from 'assert';
import { ObservableStore } from '@metamask/obs-store';
import { ethErrors } from 'eth-rpc-errors';
import { typedSignatureHash, TYPED_MESSAGE_SCHEMA } from 'eth-sig-util';
import { isValidAddress } from 'ethereumjs-util';
import log from 'loglevel';
import jsonschema from 'jsonschema';
import { MESSAGE_TYPE } from '../../../shared/constants/app';
import { METAMASK_CONTROLLER_EVENTS } from '../metamask-controller';
import createId from '../../../shared/modules/random-id';
import { isValidHexAddress } from '../../../shared/modules/hexstring-utils';
/**
* Represents, and contains data about, an 'eth_signTypedData' type signature request. These are created when a
@ -160,7 +160,8 @@ export default class TypedMessageManager extends EventEmitter {
assert.ok('data' in params, 'Params must include a "data" field.');
assert.ok('from' in params, 'Params must include a "from" field.');
assert.ok(
typeof params.from === 'string' && isValidAddress(params.from),
typeof params.from === 'string' &&
isValidHexAddress(params.from, { allowNonPrefixed: false }),
'"from" field must be a valid, lowercase, hexadecimal Ethereum address string.',
);

View File

@ -0,0 +1,53 @@
import {
isHexString,
isValidAddress,
isValidChecksumAddress,
addHexPrefix,
} from 'ethereumjs-util';
export const BURN_ADDRESS = '0x0000000000000000000000000000000000000000';
export function isBurnAddress(address) {
return address === BURN_ADDRESS;
}
/**
* Validates that the input is a hex address. This utility method is a thin
* wrapper around ethereumjs-util.isValidAddress, with the exception that it
* does not throw an error when provided values that are not hex strings. In
* addition, and by default, this method will return true for hex strings that
* meet the length requirement of a hex address, but are not prefixed with `0x`
* Finally, if the mixedCaseUseChecksum flag is true and a mixed case string is
* provided this method will validate it has the proper checksum formatting.
* @param {string} possibleAddress - Input parameter to check against
* @param {Object} [options] - options bag
* @param {boolean} [options.allowNonPrefixed] - If true will first ensure '0x'
* is prepended to the string
* @param {boolean} [options.mixedCaseUseChecksum] - If true will treat mixed
* case addresses as checksum addresses and validate that proper checksum
* format is used
* @returns {boolean} whether or not the input is a valid hex address
*/
export function isValidHexAddress(
possibleAddress,
{ allowNonPrefixed = true, mixedCaseUseChecksum = false } = {},
) {
const addressToCheck = allowNonPrefixed
? addHexPrefix(possibleAddress)
: possibleAddress;
if (!isHexString(addressToCheck)) {
return false;
}
if (mixedCaseUseChecksum) {
const prefixRemoved = addressToCheck.slice(2);
const lower = prefixRemoved.toLowerCase();
const upper = prefixRemoved.toUpperCase();
const allOneCase = prefixRemoved === lower || prefixRemoved === upper;
if (!allOneCase) {
return isValidChecksumAddress(addressToCheck);
}
}
return isValidAddress(addressToCheck);
}

View File

@ -0,0 +1,57 @@
import { strict as assert } from 'assert';
import { toChecksumAddress } from 'ethereumjs-util';
import { isValidHexAddress } from './hexstring-utils';
describe('hexstring utils', function () {
describe('isValidHexAddress', function () {
it('should allow 40-char non-prefixed hex', function () {
const address = 'fdea65c8e26263f6d9a1b5de9555d2931a33b825';
const result = isValidHexAddress(address);
assert.equal(result, true);
});
it('should allow 42-char prefixed hex', function () {
const address = '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825';
const result = isValidHexAddress(address);
assert.equal(result, true);
});
it('should NOT allow 40-char non-prefixed hex when allowNonPrefixed is false', function () {
const address = 'fdea65c8e26263f6d9a1b5de9555d2931a33b825';
const result = isValidHexAddress(address, { allowNonPrefixed: false });
assert.equal(result, false);
});
it('should NOT allow any length of non hex-prefixed string', function () {
const address = 'fdea65c8e26263f6d9a1b5de9555d2931a33b85';
const result = isValidHexAddress(address);
assert.equal(result, false);
});
it('should NOT allow less than 42 character hex-prefixed string', function () {
const address = '0xfdea65ce26263f6d9a1b5de9555d2931a33b85';
const result = isValidHexAddress(address);
assert.equal(result, false);
});
it('should recognize correct capitalized checksum', function () {
const address = '0xFDEa65C8e26263F6d9A1B5de9555D2931A33b825';
const result = isValidHexAddress(address, { mixedCaseUseChecksum: true });
assert.equal(result, true);
});
it('should recognize incorrect capitalized checksum', function () {
const address = '0xFDea65C8e26263F6d9A1B5de9555D2931A33b825';
const result = isValidHexAddress(address, { mixedCaseUseChecksum: true });
assert.equal(result, false);
});
it('should recognize this sample hashed address', function () {
const address = '0x5Fda30Bb72B8Dfe20e48A00dFc108d0915BE9Bb0';
const result = isValidHexAddress(address, { mixedCaseUseChecksum: true });
const hashed = toChecksumAddress(address.toLowerCase());
assert.equal(hashed, address);
assert.equal(result, true);
});
});
});

View File

@ -2,8 +2,9 @@ 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 { checksumAddress, isHex } from '../../../helpers/utils/util';
import { checksumAddress } from '../../../helpers/utils/util';
import Jazzicon from '../jazzicon';
import BlockieIdenticon from './blockieIdenticon';
@ -85,12 +86,12 @@ export default class Identicon extends PureComponent {
}
if (address) {
if (isHex(address)) {
const checksummedAddress = checksumAddress(address);
const checksummedAddress =
isHexString(addHexPrefix(address)) &&
checksumAddress(addHexPrefix(address));
if (contractMap[checksummedAddress]?.logo) {
return this.renderJazzicon();
}
if (contractMap[checksummedAddress]?.logo) {
return this.renderJazzicon();
}
return (

View File

@ -38,7 +38,11 @@ describe('Identicon', () => {
it('renders div with address prop', () => {
const wrapper = mount(
<Identicon store={store} className="test-address" address="0x0" />,
<Identicon
store={store}
className="test-address"
address="0x0000000000000000000000000000000000000000"
/>,
);
expect(wrapper.find('div.test-address').prop('className')).toStrictEqual(

View File

@ -78,20 +78,6 @@ export function addressSummary(
: '...';
}
export function isValidAddress(address) {
if (!address || address === '0x0000000000000000000000000000000000000000') {
return false;
}
const prefixed = addHexPrefix(address);
if (!isHex(prefixed)) {
return false;
}
return (
(isAllOneCase(prefixed.slice(2)) && ethUtil.isValidAddress(prefixed)) ||
ethUtil.isValidChecksumAddress(prefixed)
);
}
export function isValidDomainName(address) {
const match = punycode
.toASCII(address)
@ -112,15 +98,6 @@ export function isOriginContractAddress(to, sendTokenAddress) {
return to.toLowerCase() === sendTokenAddress.toLowerCase();
}
export function isAllOneCase(address) {
if (!address) {
return true;
}
const lower = address.toLowerCase();
const upper = address.toUpperCase();
return address === lower || address === upper;
}
// Takes wei Hex, returns wei BN, even if input is null
export function numericBalance(balance) {
if (!balance) {
@ -182,10 +159,6 @@ export function formatBalance(
return formatted;
}
export function isHex(str) {
return Boolean(str.match(/^(0x)?[0-9a-fA-F]+$/u));
}
export function getContractAtAddress(tokenAddress) {
return global.eth.contract(abi).at(tokenAddress);
}
@ -253,13 +226,6 @@ export function shortenAddress(address = '') {
return `${address.slice(0, 6)}...${address.slice(-4)}`;
}
export function isValidAddressHead(address) {
const addressLengthIsLessThanFull = address.length < 42;
const addressIsHex = isHex(address);
return addressLengthIsLessThanFull && addressIsHex;
}
export function getAccountByAddress(accounts = [], targetAddress) {
return accounts.find(({ address }) => address === targetAddress);
}

View File

@ -1,4 +1,4 @@
import { BN, toChecksumAddress } from 'ethereumjs-util';
import { BN } from 'ethereumjs-util';
import * as util from './util';
describe('util', () => {
@ -47,52 +47,6 @@ describe('util', () => {
});
});
describe('#isValidAddress', () => {
it('should allow 40-char non-prefixed hex', () => {
const address = 'fdea65c8e26263f6d9a1b5de9555d2931a33b825';
const result = util.isValidAddress(address);
expect(result).toStrictEqual(true);
});
it('should allow 42-char non-prefixed hex', () => {
const address = '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825';
const result = util.isValidAddress(address);
expect(result).toStrictEqual(true);
});
it('should not allow less non hex-prefixed', () => {
const address = 'fdea65c8e26263f6d9a1b5de9555d2931a33b85';
const result = util.isValidAddress(address);
expect(result).toStrictEqual(false);
});
it('should not allow less hex-prefixed', () => {
const address = '0xfdea65ce26263f6d9a1b5de9555d2931a33b85';
const result = util.isValidAddress(address);
expect(result).toStrictEqual(false);
});
it('should recognize correct capitalized checksum', () => {
const address = '0xFDEa65C8e26263F6d9A1B5de9555D2931A33b825';
const result = util.isValidAddress(address);
expect(result).toStrictEqual(true);
});
it('should recognize incorrect capitalized checksum', () => {
const address = '0xFDea65C8e26263F6d9A1B5de9555D2931A33b825';
const result = util.isValidAddress(address);
expect(result).toStrictEqual(false);
});
it('should recognize this sample hashed address', () => {
const address = '0x5Fda30Bb72B8Dfe20e48A00dFc108d0915BE9Bb0';
const result = util.isValidAddress(address);
const hashed = toChecksumAddress(address.toLowerCase());
expect(hashed).toStrictEqual(address);
expect(result).toStrictEqual(true);
});
});
describe('isValidDomainName', () => {
it('should return true when given a valid domain name', () => {
expect(util.isValidDomainName('foo.bar')).toStrictEqual(true);
@ -239,36 +193,6 @@ describe('util', () => {
});
describe('normalizing values', function () {
describe('#isHex', function () {
it('should return true when given a hex string', function () {
const result = util.isHex(
'c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2',
);
expect(result).toStrictEqual(true);
});
it('should return false when given a non-hex string', () => {
const result = util.isHex(
'c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714imnotreal',
);
expect(result).toStrictEqual(false);
});
it('should return false when given a string containing a non letter/number character', () => {
const result = util.isHex(
'c3ab8ff13720!8ad9047dd39466b3c%8974e592c2fa383d4a396071imnotreal',
);
expect(result).toStrictEqual(false);
});
it('should return true when given a hex string with hex-prefix', () => {
const result = util.isHex(
'0xc3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2',
);
expect(result).toStrictEqual(true);
});
});
describe('#getRandomFileName', () => {
it('should only return a string containing alphanumeric characters', () => {
const result = util.getRandomFileName();

View File

@ -1,15 +1,13 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import {
checkExistingAddresses,
isValidAddress,
} from '../../helpers/utils/util';
import { checkExistingAddresses } from '../../helpers/utils/util';
import { tokenInfoGetter } from '../../helpers/utils/token-util';
import { CONFIRM_ADD_TOKEN_ROUTE } from '../../helpers/constants/routes';
import TextField from '../../components/ui/text-field';
import PageContainer from '../../components/ui/page-container';
import { Tabs, Tab } from '../../components/ui/tabs';
import { addHexPrefix } from '../../../../app/scripts/lib/util';
import { isValidHexAddress } from '../../../../shared/modules/hexstring-utils';
import TokenList from './token-list';
import TokenSearch from './token-search';
@ -167,7 +165,9 @@ class AddToken extends Component {
autoFilled: false,
});
const addressIsValid = isValidAddress(customAddress);
const addressIsValid = isValidHexAddress(customAddress, {
allowNonPrefixed: false,
});
const standardAddress = addHexPrefix(customAddress).toLowerCase();
switch (true) {

View File

@ -2,13 +2,16 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Fuse from 'fuse.js';
import Identicon from '../../../../components/ui/identicon';
import { isValidAddress } from '../../../../helpers/utils/util';
import Dialog from '../../../../components/ui/dialog';
import ContactList from '../../../../components/app/contact-list';
import RecipientGroup from '../../../../components/app/contact-list/recipient-group/recipient-group.component';
import { ellipsify } from '../../send.utils';
import Button from '../../../../components/ui/button';
import Confusable from '../../../../components/ui/confusable';
import {
isBurnAddress,
isValidHexAddress,
} from '../../../../../shared/modules/hexstring-utils';
export default class AddRecipient extends Component {
static propTypes = {
@ -101,7 +104,10 @@ export default class AddRecipient extends Component {
let content;
if (isValidAddress(query)) {
if (
!isBurnAddress(query) &&
isValidHexAddress(query, { mixedCaseUseChecksum: true })
) {
content = this.renderExplicitAddress(query);
} else if (ensResolution) {
content = this.renderExplicitAddress(

View File

@ -11,18 +11,25 @@ import {
} from '../../send.constants';
import {
isValidAddress,
checkExistingAddresses,
isValidDomainName,
isOriginContractAddress,
isDefaultMetaMaskChain,
} from '../../../../helpers/utils/util';
import {
isBurnAddress,
isValidHexAddress,
} from '../../../../../shared/modules/hexstring-utils';
export function getToErrorObject(to, sendTokenAddress, chainId) {
let toError = null;
if (!to) {
toError = REQUIRED_ERROR;
} else if (!isValidAddress(to) && !isValidDomainName(to)) {
} else if (
isBurnAddress(to) ||
(!isValidHexAddress(to, { mixedCaseUseChecksum: true }) &&
!isValidDomainName(to))
) {
toError = isDefaultMetaMaskChain(chainId)
? INVALID_RECIPIENT_ADDRESS_ERROR
: INVALID_RECIPIENT_ADDRESS_NOT_ETH_NETWORK_ERROR;

View File

@ -11,7 +11,6 @@ jest.mock('../../../../../app/helpers/utils/util', () => ({
isDefaultMetaMaskChain: jest.fn().mockReturnValue(true),
isEthNetwork: jest.fn().mockReturnValue(true),
checkExistingAddresses: jest.fn().mockReturnValue(true),
isValidAddress: jest.fn((to) => Boolean(to.match(/^[0xabcdef123456798]+$/u))),
isValidDomainName: jest.requireActual('../../../../../app/helpers/utils/util')
.isValidDomainName,
isOriginContractAddress: jest.requireActual(
@ -19,6 +18,13 @@ jest.mock('../../../../../app/helpers/utils/util', () => ({
).isOriginContractAddress,
}));
jest.mock('../../../../../shared/modules/hexstring-utils', () => ({
isValidHexAddress: jest.fn((to) =>
Boolean(to.match(/^[0xabcdef123456798]+$/u)),
),
isBurnAddress: jest.fn(() => false),
}));
describe('add-recipient utils', () => {
describe('getToErrorObject()', () => {
it('should return a required error if "to" is falsy', () => {

View File

@ -7,13 +7,14 @@ import copyToClipboard from 'copy-to-clipboard/index';
import ENS from 'ethjs-ens';
import networkMap from 'ethereum-ens-network-map';
import log from 'loglevel';
import { isHexString } from 'ethereumjs-util';
import { ellipsify } from '../../send.utils';
import {
isValidDomainName,
isValidAddress,
isValidAddressHead,
} from '../../../../helpers/utils/util';
import { isValidDomainName } from '../../../../helpers/utils/util';
import { MAINNET_NETWORK_ID } from '../../../../../../shared/constants/network';
import {
isBurnAddress,
isValidHexAddress,
} from '../../../../../../shared/modules/hexstring-utils';
// Local Constants
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
@ -143,7 +144,10 @@ export default class EnsInput extends Component {
onPaste = (event) => {
event.clipboardData.items[0].getAsString((text) => {
if (isValidAddress(text)) {
if (
!isBurnAddress(text) &&
isValidHexAddress(text, { mixedCaseUseChecksum: true })
) {
this.props.onPaste(text);
}
});
@ -170,8 +174,11 @@ export default class EnsInput extends Component {
if (
!networkHasEnsSupport &&
!isValidAddress(input) &&
!isValidAddressHead(input)
!(
isBurnAddress(input) === false &&
isValidHexAddress(input, { mixedCaseUseChecksum: true })
) &&
!isHexString(input)
) {
updateEnsResolution('');
updateEnsResolutionError(
@ -182,7 +189,11 @@ export default class EnsInput extends Component {
if (isValidDomainName(input)) {
this.lookupEnsName(input);
} else if (onValidAddressTyped && isValidAddress(input)) {
} else if (
onValidAddressTyped &&
!isBurnAddress(input) &&
isValidHexAddress(input, { mixedCaseUseChecksum: true })
) {
onValidAddressTyped(input);
} else {
updateEnsResolution('');

View File

@ -1,7 +1,7 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { debounce } from 'lodash';
import { isValidAddress } from '../../helpers/utils/util';
import { isValidHexAddress } from '../../../shared/modules/hexstring-utils';
import {
getAmountErrorObject,
getGasFeeErrorObject,
@ -171,7 +171,7 @@ export default class SendTransactionScreen extends Component {
if (qrCodeData) {
if (qrCodeData.type === 'address') {
scannedAddress = qrCodeData.values.address.toLowerCase();
if (isValidAddress(scannedAddress)) {
if (isValidHexAddress(scannedAddress, { allowNonPrefixed: false })) {
const currentAddress = prevTo?.toLowerCase();
if (currentAddress !== scannedAddress) {
updateSendTo(scannedAddress);

View File

@ -4,12 +4,13 @@ import { debounce } from 'lodash';
import Identicon from '../../../../components/ui/identicon';
import TextField from '../../../../components/ui/text-field';
import { CONTACT_LIST_ROUTE } from '../../../../helpers/constants/routes';
import {
isValidAddress,
isValidDomainName,
} from '../../../../helpers/utils/util';
import { isValidDomainName } from '../../../../helpers/utils/util';
import EnsInput from '../../../send/send-content/add-recipient/ens-input';
import PageContainerFooter from '../../../../components/ui/page-container/page-container-footer';
import {
isBurnAddress,
isValidHexAddress,
} from '../../../../../shared/modules/hexstring-utils';
export default class AddContact extends PureComponent {
static contextTypes = {
@ -53,7 +54,9 @@ export default class AddContact extends PureComponent {
}
validate = (address) => {
const valid = isValidAddress(address);
const valid =
!isBurnAddress(address) &&
isValidHexAddress(address, { mixedCaseUseChecksum: true });
const validEnsAddress = isValidDomainName(address);
if (valid || validEnsAddress || address === '') {

View File

@ -4,8 +4,11 @@ import { Redirect } from 'react-router-dom';
import Identicon from '../../../../components/ui/identicon';
import Button from '../../../../components/ui/button/button.component';
import TextField from '../../../../components/ui/text-field';
import { isValidAddress } from '../../../../helpers/utils/util';
import PageContainerFooter from '../../../../components/ui/page-container/page-container-footer';
import {
isBurnAddress,
isValidHexAddress,
} from '../../../../../shared/modules/hexstring-utils';
export default class EditContact extends PureComponent {
static contextTypes = {
@ -135,7 +138,12 @@ export default class EditContact extends PureComponent {
this.state.newAddress !== address
) {
// if the user makes a valid change to the address field, remove the original address
if (isValidAddress(this.state.newAddress)) {
if (
!isBurnAddress(this.state.newAddress) &&
isValidHexAddress(this.state.newAddress, {
mixedCaseUseChecksum: true,
})
) {
await removeFromAddressBook(chainId, address);
await addToAddressBook(
this.state.newAddress,

View File

@ -2,10 +2,13 @@ import { compose } from 'redux';
import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom';
import { getAddressBookEntryName } from '../../selectors';
import { isValidAddress, isHex } from '../../helpers/utils/util';
import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app';
import { getEnvironmentType } from '../../../../app/scripts/lib/util';
import { getMostRecentOverviewPage } from '../../ducks/history/history';
import {
isValidHexAddress,
isBurnAddress,
} from '../../../../shared/modules/hexstring-utils';
import {
ABOUT_US_ROUTE,
@ -64,7 +67,10 @@ const mapStateToProps = (state, ownProps) => {
const addressName = getAddressBookEntryName(
state,
isHex(pathNameTail) && isValidAddress(pathNameTail) ? pathNameTail : '',
!isBurnAddress(pathNameTail) &&
isValidHexAddress(pathNameTail, { mixedCaseUseChecksum: true })
? pathNameTail
: '',
);
return {

View File

@ -1,7 +1,6 @@
import log from 'loglevel';
import BigNumber from 'bignumber.js';
import abi from 'human-standard-token-abi';
import { isValidAddress } from 'ethereumjs-util';
import {
SWAPS_CHAINID_DEFAULT_TOKEN_MAP,
METASWAP_CHAINID_API_HOST_MAP,
@ -35,6 +34,7 @@ import { formatCurrency } from '../../helpers/utils/confirm-tx.util';
import fetchWithCache from '../../helpers/utils/fetch-with-cache';
import { calcGasTotal } from '../send/send.utils';
import { isValidHexAddress } from '../../../shared/modules/hexstring-utils';
const TOKEN_TRANSFER_LOG_TOPIC_HASH =
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef';
@ -74,8 +74,8 @@ const QUOTE_VALIDATORS = [
validator: (trade) =>
trade &&
validHex(trade.data) &&
isValidAddress(trade.to) &&
isValidAddress(trade.from) &&
isValidHexAddress(trade.to, { allowNonPrefixed: false }) &&
isValidHexAddress(trade.from, { allowNonPrefixed: false }) &&
truthyString(trade.value),
},
{
@ -85,8 +85,8 @@ const QUOTE_VALIDATORS = [
approvalTx === null ||
(approvalTx &&
validHex(approvalTx.data) &&
isValidAddress(approvalTx.to) &&
isValidAddress(approvalTx.from)),
isValidHexAddress(approvalTx.to, { allowNonPrefixed: false }) &&
isValidHexAddress(approvalTx.from, { allowNonPrefixed: false })),
},
{
property: 'sourceAmount',
@ -101,12 +101,12 @@ const QUOTE_VALIDATORS = [
{
property: 'sourceToken',
type: 'string',
validator: isValidAddress,
validator: (input) => isValidHexAddress(input, { allowNonPrefixed: false }),
},
{
property: 'destinationToken',
type: 'string',
validator: isValidAddress,
validator: (input) => isValidHexAddress(input, { allowNonPrefixed: false }),
},
{
property: 'aggregator',
@ -146,7 +146,7 @@ const TOKEN_VALIDATORS = [
{
property: 'address',
type: 'string',
validator: isValidAddress,
validator: (input) => isValidHexAddress(input, { allowNonPrefixed: false }),
},
{
property: 'symbol',

View File

@ -1,9 +1,7 @@
import contractMap from '@metamask/contract-metadata';
import {
isValidAddress,
checksumAddress,
isHex,
} from '../app/helpers/utils/util';
import { isHexString, addHexPrefix } from 'ethereumjs-util';
import { isValidHexAddress } from '../../shared/modules/hexstring-utils';
import { checksumAddress } from '../app/helpers/utils/util';
let iconFactory;
@ -22,8 +20,8 @@ function IconFactory(jazzicon) {
IconFactory.prototype.iconForAddress = function (address, diameter) {
let addr = address;
if (isHex(address)) {
addr = checksumAddress(address);
if (isHexString(addHexPrefix(address))) {
addr = checksumAddress(addHexPrefix(address));
}
if (iconExistsFor(addr)) {
@ -56,7 +54,9 @@ IconFactory.prototype.generateNewIdenticon = function (address, diameter) {
function iconExistsFor(address) {
return (
contractMap[address] && isValidAddress(address) && contractMap[address].logo
contractMap[address] &&
isValidHexAddress(address, { allowNonPrefixed: false }) &&
contractMap[address].logo
);
}