From 30ab99c79c0212b571a7c475836a8e80bbc819fe Mon Sep 17 00:00:00 2001 From: Agustin Pane Date: Tue, 12 May 2020 15:33:39 -0300 Subject: [PATCH] (Fix) #876 - Checksummed addresses (#884) * Checksum addresses when build address book from localStorage Checksum owner's addresses when build safe from localStorage * ChecksumAddresses when add new addressBook entry ChecksumAddresses when add new owner ChecksumAddresses when replaces owner * Adds checksumAddress function Replaces old web3 usage with checksumAddress * Refactors all web3.utils.toChecksumAddress with checksumAddress() * Fix duplicating var name --- .../addressBook/store/reducer/addressBook.js | 3 ++- .../safe/transactions/incomingTxHistory.js | 4 ++-- src/logic/safe/transactions/txHistory.js | 8 ++++---- .../safe/components/AddressBook/index.jsx | 20 ++++++++++++++----- .../Tokens/screens/AddCustomToken/index.jsx | 4 ++-- .../ManageOwners/AddOwnerModal/index.jsx | 3 ++- .../ManageOwners/ReplaceOwnerModal/index.jsx | 7 +++++-- src/routes/safe/store/actions/fetchSafe.js | 18 +++++++++-------- .../safe/store/actions/loadDefaultSafe.js | 5 ++--- src/routes/safe/store/reducer/safe.js | 4 ++-- src/routes/safe/store/selectors/index.js | 5 +++-- src/utils/checksumAddress.js | 7 +++++++ 12 files changed, 56 insertions(+), 32 deletions(-) create mode 100644 src/utils/checksumAddress.js diff --git a/src/logic/addressBook/store/reducer/addressBook.js b/src/logic/addressBook/store/reducer/addressBook.js index 93f4ebf7..2f8e5bfb 100644 --- a/src/logic/addressBook/store/reducer/addressBook.js +++ b/src/logic/addressBook/store/reducer/addressBook.js @@ -12,6 +12,7 @@ import { REMOVE_ENTRY } from '~/logic/addressBook/store/actions/removeAddressBoo import { UPDATE_ENTRY } from '~/logic/addressBook/store/actions/updateAddressBookEntry' import { getAddressesListFromAdbk } from '~/logic/addressBook/utils' import { sameAddress } from '~/logic/wallets/ethAddresses' +import { checksumAddress } from '~/utils/checksumAddress' export const ADDRESS_BOOK_REDUCER_ID = 'addressBook' @@ -20,7 +21,7 @@ export type State = Map> export const buildAddressBook = (storedAdbk: AddressBook): AddressBookProps => { let addressBookBuilt = Map([]) Object.entries(storedAdbk).forEach((adbkProps: Array) => { - const safeAddress = adbkProps[0] + const safeAddress = checksumAddress(adbkProps[0]) const adbkRecords = adbkProps[1].map(makeAddressBookEntry) const adbkSafeEntries = List(adbkRecords) addressBookBuilt = addressBookBuilt.set(safeAddress, adbkSafeEntries) diff --git a/src/logic/safe/transactions/incomingTxHistory.js b/src/logic/safe/transactions/incomingTxHistory.js index b716c9c6..36d69a54 100644 --- a/src/logic/safe/transactions/incomingTxHistory.js +++ b/src/logic/safe/transactions/incomingTxHistory.js @@ -1,10 +1,10 @@ // @flow import { getIncomingTxServiceUriTo, getTxServiceHost } from '~/config' -import { getWeb3 } from '~/logic/wallets/getWeb3' +import { checksumAddress } from '~/utils/checksumAddress' export const buildIncomingTxServiceUrl = (safeAddress: string) => { const host = getTxServiceHost() - const address = getWeb3().utils.toChecksumAddress(safeAddress) + const address = checksumAddress(safeAddress) const base = getIncomingTxServiceUriTo(address) return `${host}${base}` diff --git a/src/logic/safe/transactions/txHistory.js b/src/logic/safe/transactions/txHistory.js index e597e8d9..08dcee27 100644 --- a/src/logic/safe/transactions/txHistory.js +++ b/src/logic/safe/transactions/txHistory.js @@ -2,7 +2,7 @@ import axios from 'axios' import { getTxServiceHost, getTxServiceUriFrom } from '~/config' -import { getWeb3 } from '~/logic/wallets/getWeb3' +import { checksumAddress } from '~/utils/checksumAddress' export type TxServiceType = 'confirmation' | 'execution' | 'initialised' export type Operation = 0 | 1 | 2 @@ -38,7 +38,7 @@ const calculateBodyFrom = async ( ) return { - to: getWeb3().utils.toChecksumAddress(to), + to: checksumAddress(to), value: valueInWei, data, operation, @@ -50,7 +50,7 @@ const calculateBodyFrom = async ( refundReceiver, contractTransactionHash, transactionHash, - sender: getWeb3().utils.toChecksumAddress(sender), + sender: checksumAddress(sender), origin, signature, } @@ -58,7 +58,7 @@ const calculateBodyFrom = async ( export const buildTxServiceUrl = (safeAddress: string) => { const host = getTxServiceHost() - const address = getWeb3().utils.toChecksumAddress(safeAddress) + const address = checksumAddress(safeAddress) const base = getTxServiceUriFrom(address) return `${host}${base}` } diff --git a/src/routes/safe/components/AddressBook/index.jsx b/src/routes/safe/components/AddressBook/index.jsx index 1b776314..e9af8066 100644 --- a/src/routes/safe/components/AddressBook/index.jsx +++ b/src/routes/safe/components/AddressBook/index.jsx @@ -44,6 +44,7 @@ import type { OwnerRow } from '~/routes/safe/components/Settings/ManageOwners/da import RemoveOwnerIcon from '~/routes/safe/components/Settings/assets/icons/bin.svg' import RemoveOwnerIconDisabled from '~/routes/safe/components/Settings/assets/icons/disabled-bin.svg' import { addressBookQueryParamsSelector, safesListSelector } from '~/routes/safe/store/selectors' +import { checksumAddress } from '~/utils/checksumAddress' type Props = { classes: Object, @@ -69,7 +70,8 @@ const AddressBookTable = ({ classes }: Props) => { useEffect(() => { if (entryAddressToEditOrCreateNew) { - const key = addressBook.findKey((entry) => entry.address === entryAddressToEditOrCreateNew) + const checksumEntryAdd = checksumAddress(entryAddressToEditOrCreateNew) + const key = addressBook.findKey((entry) => entry.address === checksumEntryAdd) if (key >= 0) { // Edit old entry const value = addressBook.get(key) @@ -79,7 +81,7 @@ const AddressBookTable = ({ classes }: Props) => { setSelectedEntry({ entry: { name: '', - address: entryAddressToEditOrCreateNew, + address: checksumEntryAdd, isNew: true, }, }) @@ -89,17 +91,25 @@ const AddressBookTable = ({ classes }: Props) => { const newEntryModalHandler = (entry: AddressBookEntry) => { setEditCreateEntryModalOpen(false) - dispatch(addAddressBookEntry(makeAddressBookEntry(entry))) + const checksumEntries = { + ...entry, + address: checksumAddress(entry.address), + } + dispatch(addAddressBookEntry(makeAddressBookEntry(checksumEntries))) } const editEntryModalHandler = (entry: AddressBookEntry) => { setSelectedEntry(null) setEditCreateEntryModalOpen(false) - dispatch(updateAddressBookEntry(makeAddressBookEntry(entry))) + const checksumEntries = { + ...entry, + address: checksumAddress(entry.address), + } + dispatch(updateAddressBookEntry(makeAddressBookEntry(checksumEntries))) } const deleteEntryModalHandler = () => { - const entryAddress = selectedEntry.entry.address + const entryAddress = checksumAddress(selectedEntry.entry.address) setSelectedEntry(null) setDeleteEntryModalOpen(false) dispatch(removeAddressBookEntry(entryAddress)) diff --git a/src/routes/safe/components/Balances/Tokens/screens/AddCustomToken/index.jsx b/src/routes/safe/components/Balances/Tokens/screens/AddCustomToken/index.jsx index 085c4c5a..a27be2bb 100644 --- a/src/routes/safe/components/Balances/Tokens/screens/AddCustomToken/index.jsx +++ b/src/routes/safe/components/Balances/Tokens/screens/AddCustomToken/index.jsx @@ -21,8 +21,8 @@ import Img from '~/components/layout/Img' import Paragraph from '~/components/layout/Paragraph' import Row from '~/components/layout/Row' import { type Token, type TokenProps } from '~/logic/tokens/store/model/token' -import { getWeb3 } from '~/logic/wallets/getWeb3' import TokenPlaceholder from '~/routes/safe/components/Balances/assets/token_placeholder.svg' +import { checksumAddress } from '~/utils/checksumAddress' export const ADD_CUSTOM_TOKEN_ADDRESS_INPUT_TEST_ID = 'add-custom-token-address-input' export const ADD_CUSTOM_TOKEN_SYMBOLS_INPUT_TEST_ID = 'add-custom-token-symbols-input' @@ -65,7 +65,7 @@ const AddCustomToken = (props: Props) => { const [formValues, setFormValues] = useState(INITIAL_FORM_STATE) const handleSubmit = (values) => { - const address = getWeb3().utils.toChecksumAddress(values.address) + const address = checksumAddress(values.address) const token = { address, decimals: values.decimals, diff --git a/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.jsx b/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.jsx index e76e1a4d..29be4886 100644 --- a/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.jsx @@ -17,6 +17,7 @@ import addSafeOwner from '~/routes/safe/store/actions/addSafeOwner' import createTransaction from '~/routes/safe/store/actions/createTransaction' import { type Owner } from '~/routes/safe/store/models/owner' import { safeOwnersSelector, safeParamAddressFromStateSelector } from '~/routes/safe/store/selectors' +import { checksumAddress } from '~/utils/checksumAddress' const styles = () => ({ biggerModalWindow: { @@ -91,7 +92,7 @@ const AddOwner = ({ classes, closeSnackbar, enqueueSnackbar, isOpen, onClose }: setValues((stateValues) => ({ ...stateValues, ownerName: newValues.ownerName, - ownerAddress: newValues.ownerAddress, + ownerAddress: checksumAddress(newValues.ownerAddress), })) setActiveScreen('selectThreshold') } diff --git a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx index fdcdb5f1..16258d80 100644 --- a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx @@ -14,6 +14,7 @@ import { TX_NOTIFICATION_TYPES } from '~/logic/safe/transactions' import createTransaction from '~/routes/safe/store/actions/createTransaction' import replaceSafeOwner from '~/routes/safe/store/actions/replaceSafeOwner' import { safeParamAddressFromStateSelector, safeThresholdSelector } from '~/routes/safe/store/selectors' +import { checksumAddress } from '~/utils/checksumAddress' const styles = () => ({ biggerModalWindow: { @@ -96,8 +97,10 @@ const ReplaceOwner = ({ classes, closeSnackbar, enqueueSnackbar, isOpen, onClose const onClickBack = () => setActiveScreen('checkOwner') const ownerSubmitted = (newValues: Object) => { - values.ownerName = newValues.ownerName - values.ownerAddress = newValues.ownerAddress + const { ownerAddress, ownerName } = newValues + const checksumAddr = checksumAddress(ownerAddress) + values.ownerName = ownerName + values.ownerAddress = checksumAddr setValues(values) setActiveScreen('reviewReplaceOwner') } diff --git a/src/routes/safe/store/actions/fetchSafe.js b/src/routes/safe/store/actions/fetchSafe.js index df9b29f3..a85dac77 100644 --- a/src/routes/safe/store/actions/fetchSafe.js +++ b/src/routes/safe/store/actions/fetchSafe.js @@ -7,7 +7,7 @@ import generateBatchRequests from '~/logic/contracts/generateBatchRequests' import { getLocalSafe, getSafeName } from '~/logic/safe/utils' import { enabledFeatures, safeNeedsUpdate } from '~/logic/safe/utils/safeVersion' import { sameAddress } from '~/logic/wallets/ethAddresses' -import { getBalanceInEtherOf, getWeb3 } from '~/logic/wallets/getWeb3' +import { getBalanceInEtherOf } from '~/logic/wallets/getWeb3' import addSafe from '~/routes/safe/store/actions/addSafe' import addSafeOwner from '~/routes/safe/store/actions/addSafeOwner' import removeSafeOwner from '~/routes/safe/store/actions/removeSafeOwner' @@ -15,29 +15,31 @@ import updateSafe from '~/routes/safe/store/actions/updateSafe' import { makeOwner } from '~/routes/safe/store/models/owner' import type { SafeProps } from '~/routes/safe/store/models/safe' import { type GlobalState } from '~/store' +import { checksumAddress } from '~/utils/checksumAddress' const buildOwnersFrom = ( safeOwners: string[], localSafe: SafeProps | {}, // eslint-disable-next-line ) => safeOwners.map((ownerAddress: string) => { + const convertedAdd = checksumAddress(ownerAddress) if (!localSafe) { - return makeOwner({ name: 'UNKNOWN', address: ownerAddress }) + return makeOwner({ name: 'UNKNOWN', address: convertedAdd }) } - const storedOwner = localSafe.owners.find(({ address }) => sameAddress(address, ownerAddress)) + const storedOwner = localSafe.owners.find(({ address }) => sameAddress(address, convertedAdd)) if (!storedOwner) { - return makeOwner({ name: 'UNKNOWN', address: ownerAddress }) + return makeOwner({ name: 'UNKNOWN', address: convertedAdd }) } return makeOwner({ name: storedOwner.name || 'UNKNOWN', - address: ownerAddress, + address: convertedAdd, }) }) export const buildSafe = async (safeAdd: string, safeName: string, latestMasterContractVersion: string) => { - const safeAddress = getWeb3().utils.toChecksumAddress(safeAdd) + const safeAddress = checksumAddress(safeAdd) const safeParams = ['getThreshold', 'nonce', 'VERSION', 'getOwners'] const [[thresholdStr, nonceStr, currentVersion, remoteOwners], localSafe, ethBalance] = await Promise.all([ @@ -72,7 +74,7 @@ export const buildSafe = async (safeAdd: string, safeName: string, latestMasterC } export const checkAndUpdateSafe = (safeAdd: string) => async (dispatch: ReduxDispatch<*>) => { - const safeAddress = getWeb3().utils.toChecksumAddress(safeAdd) + const safeAddress = checksumAddress(safeAdd) // Check if the owner's safe did change and update them const safeParams = ['getThreshold', 'nonce', 'getOwners'] const [[remoteThreshold, remoteNonce, remoteOwners], localSafe] = await Promise.all([ @@ -125,7 +127,7 @@ export const checkAndUpdateSafe = (safeAdd: string) => async (dispatch: ReduxDis // eslint-disable-next-line consistent-return export default (safeAdd: string) => async (dispatch: ReduxDispatch, getState: () => GlobalState) => { try { - const safeAddress = getWeb3().utils.toChecksumAddress(safeAdd) + const safeAddress = checksumAddress(safeAdd) const safeName = (await getSafeName(safeAddress)) || 'LOADED SAFE' const latestMasterContractVersion = getState().safes.get('latestMasterContractVersion') const safeProps: SafeProps = await buildSafe(safeAddress, safeName, latestMasterContractVersion) diff --git a/src/routes/safe/store/actions/loadDefaultSafe.js b/src/routes/safe/store/actions/loadDefaultSafe.js index eec7ce80..1f689102 100644 --- a/src/routes/safe/store/actions/loadDefaultSafe.js +++ b/src/routes/safe/store/actions/loadDefaultSafe.js @@ -4,14 +4,13 @@ import type { Dispatch as ReduxDispatch } from 'redux' import setDefaultSafe from './setDefaultSafe' import { getDefaultSafe } from '~/logic/safe/utils' -import { getWeb3 } from '~/logic/wallets/getWeb3' import { type GlobalState } from '~/store/index' +import { checksumAddress } from '~/utils/checksumAddress' const loadDefaultSafe = () => async (dispatch: ReduxDispatch) => { try { const defaultSafe: string = await getDefaultSafe() - const checksumed = - defaultSafe && defaultSafe.length > 0 ? getWeb3().utils.toChecksumAddress(defaultSafe) : defaultSafe + const checksumed = defaultSafe && defaultSafe.length > 0 ? checksumAddress(defaultSafe) : defaultSafe dispatch(setDefaultSafe(checksumed)) } catch (err) { // eslint-disable-next-line diff --git a/src/routes/safe/store/reducer/safe.js b/src/routes/safe/store/reducer/safe.js index 879d81dd..a8b11db8 100644 --- a/src/routes/safe/store/reducer/safe.js +++ b/src/routes/safe/store/reducer/safe.js @@ -2,7 +2,6 @@ import { Map, Set } from 'immutable' import { type ActionType, handleActions } from 'redux-actions' -import { getWeb3 } from '~/logic/wallets/getWeb3' import { ACTIVATE_TOKEN_FOR_ALL_SAFES } from '~/routes/safe/store/actions/activateTokenForAllSafes' import { ADD_SAFE, buildOwnersFrom } from '~/routes/safe/store/actions/addSafe' import { ADD_SAFE_OWNER } from '~/routes/safe/store/actions/addSafeOwner' @@ -15,6 +14,7 @@ import { SET_LATEST_MASTER_CONTRACT_VERSION } from '~/routes/safe/store/actions/ import { UPDATE_SAFE } from '~/routes/safe/store/actions/updateSafe' import { makeOwner } from '~/routes/safe/store/models/owner' import SafeRecord, { type SafeProps } from '~/routes/safe/store/models/safe' +import { checksumAddress } from '~/utils/checksumAddress' export const SAFE_REDUCER_ID = 'safes' @@ -22,7 +22,7 @@ export type SafeReducerState = Map export const buildSafe = (storedSafe: SafeProps) => { const names = storedSafe.owners.map((owner) => owner.name) - const addresses = storedSafe.owners.map((owner) => getWeb3().utils.toChecksumAddress(owner.address)) + const addresses = storedSafe.owners.map((owner) => checksumAddress(owner.address)) const owners = buildOwnersFrom(Array.from(names), Array.from(addresses)) const activeTokens = Set(storedSafe.activeTokens) const activeAssets = Set(storedSafe.activeAssets) diff --git a/src/routes/safe/store/selectors/index.js b/src/routes/safe/store/selectors/index.js index e346eae2..d38e4ee4 100644 --- a/src/routes/safe/store/selectors/index.js +++ b/src/routes/safe/store/selectors/index.js @@ -19,6 +19,7 @@ import { import { SAFE_REDUCER_ID } from '~/routes/safe/store/reducer/safe' import { TRANSACTIONS_REDUCER_ID, type State as TransactionsState } from '~/routes/safe/store/reducer/transactions' import { type GlobalState } from '~/store/index' +import { checksumAddress } from '~/utils/checksumAddress' export type RouterProps = { match: Match, @@ -76,7 +77,7 @@ export const safeParamAddressFromStateSelector = (state: GlobalState): string | export const safeParamAddressSelector = (state: GlobalState, props: RouterProps) => { const urlAdd = props.match.params[SAFE_PARAM_ADDRESS] - return urlAdd ? getWeb3().utils.toChecksumAddress(urlAdd) : '' + return urlAdd ? checksumAddress(urlAdd) : '' } type TxSelectorType = OutputSelector> @@ -150,7 +151,7 @@ export const safeSelector: OutputSelector { + if (!address) return null + return getWeb3().utils.toChecksumAddress(address) +}