From 45834b0d2a054dd574ec4b4c1f6c21f916bcbaa1 Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Wed, 12 Jun 2019 23:58:58 +0300 Subject: [PATCH 1/6] RSK address checksum --- old-ui/app/account-detail.js | 7 ++- old-ui/app/add-suggested-token.js | 7 +-- .../account-dropdowns.component.js | 7 ++- old-ui/app/components/account-panel.js | 2 +- old-ui/app/components/pending-tx.js | 13 +++--- old-ui/app/components/send/executor-cell.js | 4 +- old-ui/app/components/send/send-profile.js | 2 +- old-ui/app/components/shift-list-item.js | 4 +- old-ui/app/components/token-cell.js | 5 +-- .../app/components/transaction-list-item.js | 14 +++--- old-ui/app/util.js | 45 +++++++++++++++---- old-ui/lib/contract-namer.js | 6 +-- old-ui/lib/icon-factory.js | 4 +- old-ui/lib/lost-accounts-notice.js | 4 +- test/unit/old-ui/app/util.spec.js | 4 +- 15 files changed, 77 insertions(+), 51 deletions(-) diff --git a/old-ui/app/account-detail.js b/old-ui/app/account-detail.js index 7a57c248f..e67f001c9 100644 --- a/old-ui/app/account-detail.js +++ b/old-ui/app/account-detail.js @@ -4,12 +4,11 @@ const Component = require('react').Component const h = require('react-hyperscript') const connect = require('react-redux').connect const actions = require('../../ui/app/actions') -const { getCurrentKeyring, ifContractAcc, valuesFor } = require('./util') +const { getCurrentKeyring, ifContractAcc, valuesFor, toChecksumAddress } = require('./util') const Identicon = require('./components/identicon') const EthBalance = require('./components/eth-balance') const TransactionList = require('./components/transaction-list') const ExportAccountView = require('./components/account-export') -const ethUtil = require('ethereumjs-util') const EditableLabel = require('./components/editable-label') const TabBar = require('./components/tab-bar') const TokenList = require('./components/token-list') @@ -50,11 +49,11 @@ function AccountDetailScreen () { AccountDetailScreen.prototype.render = function () { var props = this.props + const { network, conversionRate, currentCurrency } = props var selected = props.address || Object.keys(props.accounts)[0] - var checksumAddress = selected && ethUtil.toChecksumAddress(selected) + var checksumAddress = selected && toChecksumAddress(network, selected) var identity = props.identities[selected] var account = props.accounts[selected] - const { network, conversionRate, currentCurrency } = props if (Object.keys(props.suggestedTokens).length > 0) { this.props.dispatch(actions.showAddSuggestedTokenPage()) diff --git a/old-ui/app/add-suggested-token.js b/old-ui/app/add-suggested-token.js index 0b69d4f3d..d8b2058dc 100644 --- a/old-ui/app/add-suggested-token.js +++ b/old-ui/app/add-suggested-token.js @@ -6,7 +6,7 @@ const actions = require('../../ui/app/actions') const Tooltip = require('./components/tooltip.js') const ethUtil = require('ethereumjs-util') const Copyable = require('./components/copy/copyable') -const addressSummary = require('./util').addressSummary +const { addressSummary, toChecksumAddress } = require('./util') module.exports = connect(mapStateToProps)(AddSuggestedTokenScreen) @@ -30,6 +30,7 @@ AddSuggestedTokenScreen.prototype.render = function () { const state = this.state const props = this.props const { warning } = state + const { network } = props const key = Object.keys(props.suggestedTokens)[0] const { address, symbol, decimals } = props.suggestedTokens[key] @@ -77,7 +78,7 @@ AddSuggestedTokenScreen.prototype.render = function () { style: { display: 'flex' }, }, [ h(Copyable, { - value: ethUtil.toChecksumAddress(address), + value: toChecksumAddress(network, address), }, [ h('span#token-address', { style: { @@ -87,7 +88,7 @@ AddSuggestedTokenScreen.prototype.render = function () { margin: '8px', display: 'flex', }, - }, addressSummary(address, 24, 4, false)), + }, addressSummary(network, address, 24, 4, false)), ]), ]), diff --git a/old-ui/app/components/account-dropdowns/account-dropdowns.component.js b/old-ui/app/components/account-dropdowns/account-dropdowns.component.js index 6250850f0..32ebce467 100644 --- a/old-ui/app/components/account-dropdowns/account-dropdowns.component.js +++ b/old-ui/app/components/account-dropdowns/account-dropdowns.component.js @@ -3,10 +3,9 @@ import PropTypes from 'prop-types' import actions from '../../../../ui/app/actions' import { connect } from 'react-redux' import { Dropdown, DropdownMenuItem } from '../dropdown' -import ethUtil from 'ethereumjs-util' import copyToClipboard from 'copy-to-clipboard' import ethNetProps from 'eth-net-props' -import { getCurrentKeyring, ifContractAcc, ifHardwareAcc, getAllKeyRingsAccounts } from '../../util' +import { getCurrentKeyring, ifContractAcc, ifHardwareAcc, getAllKeyRingsAccounts, toChecksumAddress } from '../../util' import { importTypes } from '../../accounts/import/enums' import { getFullABI } from '../../accounts/import/helpers' import log from 'loglevel' @@ -217,8 +216,8 @@ class AccountDropdowns extends Component { } copyAddress = () => { - const { selected } = this.props - const checkSumAddress = selected && ethUtil.toChecksumAddress(selected) + const { selected, network } = this.props + const checkSumAddress = selected && toChecksumAddress(network, selected) copyToClipboard(checkSumAddress) } diff --git a/old-ui/app/components/account-panel.js b/old-ui/app/components/account-panel.js index c1f941ec7..70c0f9797 100644 --- a/old-ui/app/components/account-panel.js +++ b/old-ui/app/components/account-panel.js @@ -26,7 +26,7 @@ AccountPanel.prototype.render = function () { attributes: [ { key: 'Address', - value: addressSummary(identity.address), + value: addressSummary(state.network, identity.address), }, balanceOrFaucetingIndication(account, isFauceting, state.network), ], diff --git a/old-ui/app/components/pending-tx.js b/old-ui/app/components/pending-tx.js index a08e76e5a..14d8cd47a 100644 --- a/old-ui/app/components/pending-tx.js +++ b/old-ui/app/components/pending-tx.js @@ -13,8 +13,7 @@ const MiniAccountPanel = require('./mini-account-panel') const Copyable = require('./copy/copyable') const EthBalance = require('./eth-balance') const TokenBalance = require('./token-balance') -const addressSummary = util.addressSummary -const accountSummary = util.accountSummary +const { addressSummary, accountSummary, toChecksumAddress } = util const nameForAddress = require('../../lib/contract-namer') const BNInput = require('./bn-as-decimal-input') const { getEnvironmentType } = require('../../../app/scripts/lib/util') @@ -240,14 +239,14 @@ PendingTx.prototype.render = function () { }, accountSummary(identity.name, 6, 4)), h(Copyable, { - value: ethUtil.toChecksumAddress(address), + value: toChecksumAddress(network, address), }, [ h('span.font-small', { style: { fontFamily: 'Nunito Regular', color: 'rgba(255, 255, 255, 0.7)', }, - }, addressSummary(address, 6, 4, false)), + }, addressSummary(network, address, 6, 4, false)), ]), h('span.font-small', { @@ -565,17 +564,17 @@ PendingTx.prototype.miniAccountPanelForRecipient = function (isToken, tokensTran display: 'inline-block', whiteSpace: 'nowrap', }, - }, accountSummary(nameForAddress(to, props.identities)), 6, 4), + }, accountSummary(nameForAddress(to, props.identities, props.network)), 6, 4), h(Copyable, { - value: ethUtil.toChecksumAddress(to), + value: toChecksumAddress(props.network, to), }, [ h('span.font-small', { style: { fontFamily: 'Nunito Regular', color: 'rgba(255, 255, 255, 0.7)', }, - }, addressSummary(to, 6, 4, false)), + }, addressSummary(props.network, to, 6, 4, false)), ]), ]), ]) diff --git a/old-ui/app/components/send/executor-cell.js b/old-ui/app/components/send/executor-cell.js index fe0d0624f..1b2884152 100644 --- a/old-ui/app/components/send/executor-cell.js +++ b/old-ui/app/components/send/executor-cell.js @@ -16,12 +16,14 @@ class ExecutorCell extends Component { address: PropTypes.string, identity: PropTypes.object, onClick: PropTypes.func, + network: PropTypes.string, } render () { const { address, identity, + network, } = this.props const { isSelected } = this.state @@ -70,7 +72,7 @@ class ExecutorCell extends Component { style={{ color: 'rgba(255, 255, 255, 0.7)' }} >
- {addressSummary(address)} + {addressSummary(network, address)}
diff --git a/old-ui/app/components/send/send-profile.js b/old-ui/app/components/send/send-profile.js index 300e6df29..0d432053c 100644 --- a/old-ui/app/components/send/send-profile.js +++ b/old-ui/app/components/send/send-profile.js @@ -59,7 +59,7 @@ class SendProfile extends Component { }} >
- {addressSummary(address)} + {addressSummary(network, address)}
{/* balance */} diff --git a/old-ui/app/components/shift-list-item.js b/old-ui/app/components/shift-list-item.js index c27dd8ed6..fb9ebf593 100644 --- a/old-ui/app/components/shift-list-item.js +++ b/old-ui/app/components/shift-list-item.js @@ -152,7 +152,7 @@ ShiftListItem.prototype.renderInfo = function () { }, [ `${props.depositType} to ETH via ShapeShift`, h(CopyButton, { - value: this.props.depositAddress, + value: props.depositAddress, })]), h('div', { style: { @@ -219,7 +219,7 @@ ShiftListItem.prototype.renderInfo = function () { display: 'inline-flex', }, }, [ - addressSummary(props.response.transaction), + addressSummary(props.network, props.response.transaction), h(CopyButton, { value: this.props.response.transaction, }), diff --git a/old-ui/app/components/token-cell.js b/old-ui/app/components/token-cell.js index c311be35d..c0aa60b95 100644 --- a/old-ui/app/components/token-cell.js +++ b/old-ui/app/components/token-cell.js @@ -5,12 +5,11 @@ const Identicon = require('./identicon') const ethNetProps = require('eth-net-props') const Dropdown = require('./dropdown').Dropdown const DropdownMenuItem = require('./dropdown').DropdownMenuItem -const ethUtil = require('ethereumjs-util') const copyToClipboard = require('copy-to-clipboard') const actions = require('../../../ui/app/actions') const connect = require('react-redux').connect const { MAINNET_CODE } = require('../../../app/scripts/controllers/network/enums') -import { countSignificantDecimals } from '../util' +import { countSignificantDecimals, toChecksumAddress } from '../util' const tokenCellDropDownPrefix = 'token-cell_dropdown_' @@ -132,7 +131,7 @@ TokenCell.prototype.renderTokenOptions = function (menuToTop, ind) { { closeMenu: () => {}, onClick: () => { - const checkSumAddress = address && ethUtil.toChecksumAddress(address) + const checkSumAddress = address && toChecksumAddress(network, address) copyToClipboard(checkSumAddress) }, }, diff --git a/old-ui/app/components/transaction-list-item.js b/old-ui/app/components/transaction-list-item.js index 5158a5bec..ac1876abe 100644 --- a/old-ui/app/components/transaction-list-item.js +++ b/old-ui/app/components/transaction-list-item.js @@ -14,6 +14,7 @@ const ethNetProps = require('eth-net-props') const TransactionIcon = require('./transaction-list-item-icon') const ShiftListItem = require('./shift-list-item') +const { ifRSK } = require('../util') const { POA_CODE, DAI_CODE, @@ -25,7 +26,6 @@ const { POA_CODE, GOERLI_TESTNET_CODE, CLASSIC_CODE, RSK_CODE, - RSK_TESTNET_CODE, } = require('../../../app/scripts/controllers/network/enums') const mapDispatchToProps = dispatch => { @@ -165,7 +165,7 @@ TransactionListItem.prototype.render = function () { }, [ domainField(txParams), h('div.flex-row', [ - recipientField(txParams, transaction, isTx, isMsg, numericNet), + recipientField(txParams, transaction, isTx, isMsg, network), ]), h('div', { style: { @@ -240,13 +240,13 @@ function domainField (txParams) { ]) } -function recipientField (txParams, transaction, isTx, isMsg, numericNet) { +function recipientField (txParams, transaction, isTx, isMsg, network) { let message if (isMsg) { message = 'Signature Requested' } else if (txParams.to) { - message = addressSummary(txParams.to) + message = addressSummary(network, txParams.to) } else { message = 'Contract Deployment' } @@ -260,7 +260,7 @@ function recipientField (txParams, transaction, isTx, isMsg, numericNet) { h('span', (!txParams.to ? {style: {whiteSpace: 'nowrap'}} : null), message), // Places a copy button if tx is successful, else places a placeholder empty div. transaction.hash ? h(CopyButton, { value: transaction.hash, display: 'inline' }) : h('div', {style: { display: 'flex', alignItems: 'center', width: '26px' }}), - renderErrorOrWarning(transaction, numericNet), + renderErrorOrWarning(transaction, network), ]) } @@ -268,7 +268,7 @@ function formatDate (date) { return vreme.format(new Date(date), 'March 16 2014 14:30') } -function renderErrorOrWarning (transaction, numericNet) { +function renderErrorOrWarning (transaction, network) { const { status, err, warning } = transaction // show dropped @@ -295,7 +295,7 @@ function renderErrorOrWarning (transaction, numericNet) { } // show warning - const isRSK = numericNet === RSK_CODE || numericNet === RSK_TESTNET_CODE + const isRSK = ifRSK(network) if (warning && !isRSK || (isRSK && !warning.error.includes('[ethjs-rpc] rpc error with payload'))) { const message = warning.message return h(Tooltip, { diff --git a/old-ui/app/util.js b/old-ui/app/util.js index 2c237ad54..f42f3f1a5 100644 --- a/old-ui/app/util.js +++ b/old-ui/app/util.js @@ -1,5 +1,9 @@ const ethUtil = require('ethereumjs-util') const ethNetProps = require('eth-net-props') +const { + RSK_CODE, + RSK_TESTNET_CODE, +} = require('../../app/scripts/controllers/network/enums') var valueTable = { wei: '1000000000000000000', @@ -23,7 +27,6 @@ module.exports = { valuesFor: valuesFor, addressSummary: addressSummary, accountSummary: accountSummary, - miniAddressSummary: miniAddressSummary, isAllOneCase: isAllOneCase, isValidAddress: isValidAddress, isValidENSAddress, @@ -47,6 +50,8 @@ module.exports = { ifContractAcc, ifHardwareAcc, getAllKeyRingsAccounts, + ifRSK, + toChecksumAddress, } function valuesFor (obj) { @@ -55,9 +60,9 @@ function valuesFor (obj) { .map(function (key) { return obj[key] }) } -function addressSummary (address, firstSegLength = 10, lastSegLength = 4, includeHex = true) { +function addressSummary (network, address, firstSegLength = 10, lastSegLength = 4, includeHex = true) { if (!address) return '' - let checked = ethUtil.toChecksumAddress(address) + let checked = toChecksumAddress(network, address) if (!includeHex) { checked = ethUtil.stripHexPrefix(checked) } @@ -72,12 +77,6 @@ function accountSummary (acc, firstSegLength = 6, lastSegLength = 4) { return acc.slice(0, firstSegLength) + '...' + acc.slice(posOfLastPart) } -function miniAddressSummary (address) { - if (!address) return '' - var checked = ethUtil.toChecksumAddress(address) - return checked ? checked.slice(0, 4) + '...' + checked.slice(-4) : '...' -} - function isValidAddress (address) { var prefixed = ethUtil.addHexPrefix(address) if (address === '0x0000000000000000000000000000000000000000') return false @@ -375,3 +374,31 @@ function getAllKeyRingsAccounts (keyrings, network) { }, []) return accountOrder } + +function toChecksumAddressRSK (address, chainId = null) { + const stripAddress = ethUtil.stripHexPrefix(address).toLowerCase() + const prefix = chainId != null ? (chainId.toString() + '0x') : '' + const keccakHash = ethUtil.sha3(prefix + stripAddress).toString('hex') + let output = '0x' + + for (let i = 0; i < stripAddress.length; i++) { + output += parseInt(keccakHash[i], 16) >= 8 ? + stripAddress[i].toUpperCase() : + stripAddress[i] +} + + return output +} + +function toChecksumAddress (network, address, chainId = null) { + if (ifRSK(network)) { + return toChecksumAddressRSK(address, parseInt(network)) + } else { + return ethUtil.toChecksumAddress(address, chainId) + } +} + +function ifRSK (network) { + const numericNet = isNaN(network) ? network : parseInt(network) + return numericNet === RSK_CODE || numericNet === RSK_TESTNET_CODE +} diff --git a/old-ui/lib/contract-namer.js b/old-ui/lib/contract-namer.js index f05e770cc..945b9a46e 100644 --- a/old-ui/lib/contract-namer.js +++ b/old-ui/lib/contract-namer.js @@ -6,10 +6,10 @@ */ const contractMap = require('eth-contract-metadata') -const ethUtil = require('ethereumjs-util') +const { toChecksumAddress } = require('../app/util') -module.exports = function (addr, identities = {}) { - const checksummed = ethUtil.toChecksumAddress(addr) +module.exports = function (addr, identities = {}, network) { + const checksummed = toChecksumAddress(network, addr) if (contractMap[checksummed] && contractMap[checksummed].name) { return contractMap[checksummed].name } diff --git a/old-ui/lib/icon-factory.js b/old-ui/lib/icon-factory.js index 41d283716..ae01f2243 100644 --- a/old-ui/lib/icon-factory.js +++ b/old-ui/lib/icon-factory.js @@ -1,9 +1,9 @@ var iconFactory const isValidAddress = require('ethereumjs-util').isValidAddress -const toChecksumAddress = require('ethereumjs-util').toChecksumAddress const contractMapETH = require('eth-contract-metadata') const contractMapPOA = require('poa-contract-metadata') const colors = require('../../colors') +const { toChecksumAddress } = require('../app/util') module.exports = function (rockicon) { if (!iconFactory) { @@ -20,7 +20,7 @@ function IconFactory (rockicon) { IconFactory.prototype.iconForAddress = function (address, diameter, network) { const networkID = parseInt(network) - const addr = toChecksumAddress(address) + const addr = toChecksumAddress(network, address) if (iconExistsFor(addr, networkID)) { return imageElFor(addr, networkID) } diff --git a/old-ui/lib/lost-accounts-notice.js b/old-ui/lib/lost-accounts-notice.js index 948b13db6..1699c9d7b 100644 --- a/old-ui/lib/lost-accounts-notice.js +++ b/old-ui/lib/lost-accounts-notice.js @@ -4,14 +4,14 @@ module.exports = function (lostAccounts) { return { date: new Date().toDateString(), title: 'Account Problem Caught', - body: `MetaMask has fixed a bug where some accounts were previously mis-generated. This was a rare issue, but you were affected! + body: `NiftyWallet has fixed a bug where some accounts were previously mis-generated. This was a rare issue, but you were affected! We have successfully imported the accounts that were mis-generated, but they will no longer be recovered with your normal seed phrase. We have marked the affected accounts as "Loose", and recommend you transfer ether and tokens away from those accounts, or export & back them up elsewhere. Your affected accounts are: -${lostAccounts.map(acct => ` - ${summary(acct)}`).join('\n')} +${lostAccounts.map(acct => ` - ${summary(null, acct)}`).join('\n')} These accounts have been marked as "Loose" so they will be easy to recognize in the account list. diff --git a/test/unit/old-ui/app/util.spec.js b/test/unit/old-ui/app/util.spec.js index 2bf9d833a..73fa3b2f8 100644 --- a/test/unit/old-ui/app/util.spec.js +++ b/test/unit/old-ui/app/util.spec.js @@ -90,13 +90,13 @@ describe('ifContractAcc(keyring) function', () => { describe('#addressSummary', function () { it('should add case-sensitive checksum', function () { const address = '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825' - const result = addressSummary(address) + const result = addressSummary(1, address) assert.equal(result, '0xFDEa65C8...b825') }) it('should accept arguments for firstseg, lastseg, and keepPrefix', function () { const address = '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825' - const result = addressSummary(address, 4, 4, false) + const result = addressSummary(1, address, 4, 4, false) assert.equal(result, 'FDEa...b825') }) }) From c1142ddda9683e454b3cb5dfac229046de7ed52e Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Sun, 16 Jun 2019 21:21:24 +0300 Subject: [PATCH 2/6] Validate checksum address for RSK on sendind txs --- old-ui/app/add-suggested-token.js | 23 +++-- .../add-token/add-token.component.js | 6 +- old-ui/app/components/pending-tx.js | 2 +- old-ui/app/components/send/send-token.js | 8 +- old-ui/app/components/send/send.js | 4 +- .../app/components/transaction-list-item.js | 2 +- old-ui/app/util.js | 92 +++++++++++-------- test/unit/old-ui/app/util.spec.js | 42 +++++++++ 8 files changed, 119 insertions(+), 60 deletions(-) diff --git a/old-ui/app/add-suggested-token.js b/old-ui/app/add-suggested-token.js index d8b2058dc..a35039269 100644 --- a/old-ui/app/add-suggested-token.js +++ b/old-ui/app/add-suggested-token.js @@ -6,7 +6,7 @@ const actions = require('../../ui/app/actions') const Tooltip = require('./components/tooltip.js') const ethUtil = require('ethereumjs-util') const Copyable = require('./components/copy/copyable') -const { addressSummary, toChecksumAddress } = require('./util') +const { addressSummary, toChecksumAddress, isValidAddress } = require('./util') module.exports = connect(mapStateToProps)(AddSuggestedTokenScreen) @@ -27,12 +27,10 @@ function AddSuggestedTokenScreen () { } AddSuggestedTokenScreen.prototype.render = function () { - const state = this.state - const props = this.props - const { warning } = state - const { network } = props - const key = Object.keys(props.suggestedTokens)[0] - const { address, symbol, decimals } = props.suggestedTokens[key] + const { warning } = this.state + const { network, suggestedTokens, dispatch } = this.props + const key = Object.keys(suggestedTokens)[0] + const { address, symbol, decimals } = suggestedTokens[key] return ( h('.flex-column.flex-grow', [ @@ -133,7 +131,7 @@ AddSuggestedTokenScreen.prototype.render = function () { margin: '8px', }, onClick: (event) => { - this.props.dispatch(actions.removeSuggestedTokens()) + dispatch(actions.removeSuggestedTokens()) }, }, 'Cancel'), @@ -146,9 +144,9 @@ AddSuggestedTokenScreen.prototype.render = function () { const valid = this.validateInputs({ address, symbol, decimals }) if (!valid) return - this.props.dispatch(actions.addToken(address.trim(), symbol.trim(), decimals)) + dispatch(actions.addToken(address.trim(), symbol.trim(), decimals)) .then(() => { - this.props.dispatch(actions.removeSuggestedTokens()) + dispatch(actions.removeSuggestedTokens()) }) }, }, 'Add'), @@ -163,12 +161,13 @@ AddSuggestedTokenScreen.prototype.componentWillMount = function () { } AddSuggestedTokenScreen.prototype.validateInputs = function (opts) { + const { network, identities } = this.props let msg = '' - const identitiesList = Object.keys(this.props.identities) + const identitiesList = Object.keys(identities) const { address, symbol, decimals } = opts const standardAddress = ethUtil.addHexPrefix(address).toLowerCase() - const validAddress = ethUtil.isValidAddress(address) + const validAddress = isValidAddress(address, network) if (!validAddress) { msg += 'Address is invalid.' } diff --git a/old-ui/app/components/add-token/add-token.component.js b/old-ui/app/components/add-token/add-token.component.js index b8264189f..db52ee71c 100644 --- a/old-ui/app/components/add-token/add-token.component.js +++ b/old-ui/app/components/add-token/add-token.component.js @@ -4,7 +4,7 @@ const h = require('react-hyperscript') const Tooltip = require('../tooltip.js') const TabBar = require('../tab-bar') const { checkExistingAddresses } = require('./util') -const { getCurrentKeyring, ifContractAcc } = require('../../util') +const { getCurrentKeyring, ifContractAcc, isValidAddress } = require('../../util') const TokenList = require('./token-list') const TokenSearch = require('./token-search') const { tokenInfoGetter } = require('../../../../ui/app/token-util') @@ -351,7 +351,7 @@ class AddTokenScreen extends Component { const { customAddress: address, customSymbol: symbol, customDecimals: decimals } = state const standardAddress = ethUtil.addHexPrefix(address).toLowerCase() - const validAddress = ethUtil.isValidAddress(address) + const validAddress = isValidAddress(address, network) if (!validAddress) { msg += 'Address is invalid.' } @@ -472,7 +472,7 @@ class AddTokenScreen extends Component { autoFilled: false, }) - const isValidAddress = ethUtil.isValidAddress(customAddress) + const isValidAddress = isValidAddress(customAddress, network) const standardAddress = ethUtil.addHexPrefix(customAddress).toLowerCase() let warning diff --git a/old-ui/app/components/pending-tx.js b/old-ui/app/components/pending-tx.js index 14d8cd47a..0a447b162 100644 --- a/old-ui/app/components/pending-tx.js +++ b/old-ui/app/components/pending-tx.js @@ -115,7 +115,7 @@ PendingTx.prototype.render = function () { const balance = account ? account.balance : '0x0' // recipient check - const isValidAddress = !txParams.to || util.isValidAddress(txParams.to) + const isValidAddress = !txParams.to || util.isValidAddress(txParams.to, network) // Gas const gas = txParams.gas diff --git a/old-ui/app/components/send/send-token.js b/old-ui/app/components/send/send-token.js index f2308c694..d2068499b 100644 --- a/old-ui/app/components/send/send-token.js +++ b/old-ui/app/components/send/send-token.js @@ -124,8 +124,8 @@ class SendTransactionScreen extends PersistentForm { createFreshTokenTracker () { this.setState({isLoading: true}) - const { address, tokenAddress } = this.props - if (!isValidAddress(tokenAddress)) return + const { address, tokenAddress, network } = this.props + if (!isValidAddress(tokenAddress, network)) return if (this.tracker) { // Clean up old trackers when refreshing: this.tracker.stop() @@ -225,12 +225,12 @@ class SendTransactionScreen extends PersistentForm { return this.props.displayWarning(message) } - if ((isInvalidChecksumAddress(recipient))) { + if ((isInvalidChecksumAddress(recipient, this.props.network))) { message = 'Recipient address checksum is invalid.' return this.props.displayWarning(message) } - if (!isValidAddress(recipient) || (!recipient)) { + if (!isValidAddress(recipient, this.props.network) || (!recipient)) { message = 'Recipient address is invalid.' return this.props.displayWarning(message) } diff --git a/old-ui/app/components/send/send.js b/old-ui/app/components/send/send.js index 5d38a2a99..dad2f50da 100644 --- a/old-ui/app/components/send/send.js +++ b/old-ui/app/components/send/send.js @@ -205,12 +205,12 @@ SendTransactionScreen.prototype.onSubmit = function () { return this.props.dispatch(actions.displayWarning(message)) } - if ((isInvalidChecksumAddress(recipient))) { + if ((isInvalidChecksumAddress(recipient, this.props.network))) { message = 'Recipient address checksum is invalid.' return this.props.dispatch(actions.displayWarning(message)) } - if ((!isValidAddress(recipient) && !txData) || (!recipient && !txData)) { + if ((!isValidAddress(recipient, this.props.network) && !txData) || (!recipient && !txData)) { message = 'Recipient address is invalid.' return this.props.dispatch(actions.displayWarning(message)) } diff --git a/old-ui/app/components/transaction-list-item.js b/old-ui/app/components/transaction-list-item.js index ac1876abe..0a8e8a9ab 100644 --- a/old-ui/app/components/transaction-list-item.js +++ b/old-ui/app/components/transaction-list-item.js @@ -296,7 +296,7 @@ function renderErrorOrWarning (transaction, network) { // show warning const isRSK = ifRSK(network) - if (warning && !isRSK || (isRSK && !warning.error.includes('[ethjs-rpc] rpc error with payload'))) { + if (warning && !isRSK || (isRSK && warning && !warning.error.includes('[ethjs-rpc] rpc error with payload'))) { const message = warning.message return h(Tooltip, { title: message, diff --git a/old-ui/app/util.js b/old-ui/app/util.js index f42f3f1a5..0a64a37e8 100644 --- a/old-ui/app/util.js +++ b/old-ui/app/util.js @@ -24,25 +24,25 @@ for (var currency in valueTable) { } module.exports = { - valuesFor: valuesFor, - addressSummary: addressSummary, - accountSummary: accountSummary, - isAllOneCase: isAllOneCase, - isValidAddress: isValidAddress, + valuesFor, + addressSummary, + accountSummary, + isAllOneCase, + isValidAddress, isValidENSAddress, - numericBalance: numericBalance, - parseBalance: parseBalance, - formatBalance: formatBalance, - generateBalanceObject: generateBalanceObject, - dataSize: dataSize, - readableDate: readableDate, - normalizeToWei: normalizeToWei, - normalizeEthStringToWei: normalizeEthStringToWei, - normalizeNumberToWei: normalizeNumberToWei, - valueTable: valueTable, - bnTable: bnTable, - isHex: isHex, - exportAsFile: exportAsFile, + numericBalance, + parseBalance, + formatBalance, + generateBalanceObject, + dataSize, + readableDate, + normalizeToWei, + normalizeEthStringToWei, + normalizeNumberToWei, + valueTable, + bnTable, + isHex, + exportAsFile, isInvalidChecksumAddress, countSignificantDecimals, getCurrentKeyring, @@ -52,6 +52,7 @@ module.exports = { getAllKeyRingsAccounts, ifRSK, toChecksumAddress, + isValidChecksumAddress, } function valuesFor (obj) { @@ -77,20 +78,27 @@ function accountSummary (acc, firstSegLength = 6, lastSegLength = 4) { return acc.slice(0, firstSegLength) + '...' + acc.slice(posOfLastPart) } -function isValidAddress (address) { +function isValidAddress (address, network) { var prefixed = ethUtil.addHexPrefix(address) - if (address === '0x0000000000000000000000000000000000000000') return false - return (isAllOneCase(prefixed) && ethUtil.isValidAddress(prefixed)) || ethUtil.isValidChecksumAddress(prefixed) + if (ifRSK(network)) { + // console.log('addHexPrefixRSK:', prefixed) + if (address === '0x0000000000000000000000000000000000000000') return false + return (ethUtil.isValidAddress(prefixed)) + } else { + // console.log('addHexPrefix:', prefixed) + if (address === '0x0000000000000000000000000000000000000000') return false + return (isAllOneCase(prefixed) && ethUtil.isValidAddress(prefixed)) || ethUtil.isValidChecksumAddress(prefixed) + } } function isValidENSAddress (address) { return address.match(/^.{7,}\.(eth|test)$/) } -function isInvalidChecksumAddress (address) { +function isInvalidChecksumAddress (address, network) { var prefixed = ethUtil.addHexPrefix(address) if (address === '0x0000000000000000000000000000000000000000') return false - return !isAllOneCase(prefixed) && !ethUtil.isValidChecksumAddress(prefixed) && ethUtil.isValidAddress(prefixed) + return !isAllOneCase(prefixed) && !isValidChecksumAddress(network, prefixed) } function isAllOneCase (address) { @@ -375,19 +383,26 @@ function getAllKeyRingsAccounts (keyrings, network) { return accountOrder } -function toChecksumAddressRSK (address, chainId = null) { - const stripAddress = ethUtil.stripHexPrefix(address).toLowerCase() - const prefix = chainId != null ? (chainId.toString() + '0x') : '' - const keccakHash = ethUtil.sha3(prefix + stripAddress).toString('hex') - let output = '0x' - - for (let i = 0; i < stripAddress.length; i++) { - output += parseInt(keccakHash[i], 16) >= 8 ? - stripAddress[i].toUpperCase() : - stripAddress[i] +function ifRSK (network) { + if (!network) return false + const numericNet = isNaN(network) ? network : parseInt(network) + return numericNet === RSK_CODE || numericNet === RSK_TESTNET_CODE } - return output +function toChecksumAddressRSK (address, chainId = null) { + const zeroX = '0x' + const stripAddress = ethUtil.stripHexPrefix(address).toLowerCase() + const prefix = chainId != null ? (chainId.toString() + zeroX) : '' + const keccakHash = ethUtil.sha3(prefix + stripAddress).toString('hex') + let output = zeroX + + for (let i = 0; i < stripAddress.length; i++) { + output += parseInt(keccakHash[i], 16) >= 8 ? + stripAddress[i].toUpperCase() : + stripAddress[i] + } + + return output } function toChecksumAddress (network, address, chainId = null) { @@ -398,7 +413,10 @@ function toChecksumAddress (network, address, chainId = null) { } } -function ifRSK (network) { - const numericNet = isNaN(network) ? network : parseInt(network) - return numericNet === RSK_CODE || numericNet === RSK_TESTNET_CODE +function isValidChecksumAddress (network, address) { + // console.log('isValidAddress(address):', isValidAddress(address, network)) + // console.log('toChecksumAddress(network, address) === address', toChecksumAddress(network, address) === address) + // console.log('ethUtil.isValidAddress(address)', ethUtil.isValidAddress(address)) + // console.log('isAllOneCase', isAllOneCase(address)) + return isValidAddress(address, network) && toChecksumAddress(network, address) === address } diff --git a/test/unit/old-ui/app/util.spec.js b/test/unit/old-ui/app/util.spec.js index 73fa3b2f8..4ff18eebf 100644 --- a/test/unit/old-ui/app/util.spec.js +++ b/test/unit/old-ui/app/util.spec.js @@ -13,6 +13,9 @@ const { normalizeEthStringToWei, normalizeNumberToWei, isHex, + ifRSK, + toChecksumAddress, + isValidChecksumAddress, } = require('../../../../old-ui/app/util') const ethUtil = require('ethereumjs-util') let ethInWei = '1' @@ -329,4 +332,43 @@ describe('normalizing values', function () { assert(result) }) }) + + describe('#ifRSK', function () { + it('checks if this is RSK chain', function () { + var result1 = ifRSK(30) + assert(result1) + var result2 = ifRSK(31) + assert(result2) + var result3 = ifRSK(1) + assert(!result3) + var result4 = ifRSK() + assert(!result4) + }) + }) + + const addr = '0xB707b030A7887a21cc595Cd139746A8c2Ed91615' + const addrRSKMainnet = '0xB707b030A7887a21Cc595cD139746A8c2ED91615' + const addrRSKTestnet = '0xB707b030a7887a21Cc595CD139746a8C2ED91615' + const addrETHMainnet = '0xB707b030A7887a21cc595Cd139746A8c2Ed91615' + describe('#toChecksumAddress', function () { + it('calculates correct checksum', function () { + var resultMainnet = toChecksumAddress('30', addr) + assert.equal(resultMainnet, addrRSKMainnet) + var resultTestnet = toChecksumAddress('31', addr) + assert.equal(resultTestnet, addrRSKTestnet) + var resultNotRSK = toChecksumAddress('1', addr) + assert.equal(resultNotRSK, addrETHMainnet) + }) + }) + + describe('#isValidChecksumAddress', function () { + it('checks if is valid checksum address', function () { + var resultMainnet = isValidChecksumAddress('30', addrRSKMainnet) + assert(resultMainnet) + var resultTestnet = isValidChecksumAddress('31', addrRSKTestnet) + assert(resultTestnet) + var resultNotRSK = isValidChecksumAddress('1', addrETHMainnet) + assert(resultNotRSK) + }) + }) }) From d973c28d2d0b38b108df57e9fc9adc4abde85364 Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Sun, 16 Jun 2019 21:48:44 +0300 Subject: [PATCH 3/6] Fix: address checksum in QR code screen --- old-ui/app/account-qr.js | 10 +++++++--- old-ui/app/util.js | 6 ------ 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/old-ui/app/account-qr.js b/old-ui/app/account-qr.js index cc9aadd80..7e3b7f269 100644 --- a/old-ui/app/account-qr.js +++ b/old-ui/app/account-qr.js @@ -5,6 +5,7 @@ const {qrcode: qrCode} = require('qrcode-npm') const {connect} = require('react-redux') const {isHexPrefixed} = require('ethereumjs-util') const CopyButton = require('./components/copy/copy-button') +const { toChecksumAddress } = require('./util') class AccountQrScreen extends PureComponent { static defaultProps = { @@ -14,11 +15,13 @@ class AccountQrScreen extends PureComponent { static propTypes = { Qr: PropTypes.object.isRequired, warning: PropTypes.node, + network: PropTypes.string, } render () { - const {Qr, warning} = this.props + const {Qr, warning, network} = this.props const address = `${isHexPrefixed(Qr.data) ? 'ethereum:' : ''}${Qr.data}` + const addressChecksum = toChecksumAddress(network, Qr.data) const qrImage = qrCode(4, 'M') qrImage.addData(address) @@ -51,9 +54,9 @@ class AccountQrScreen extends PureComponent { style: { width: '247px', }, - }, Qr.data), + }, addressChecksum), h(CopyButton, { - value: Qr.data, + value: addressChecksum, }), ]), ]) @@ -64,6 +67,7 @@ function mapStateToProps (state) { return { Qr: state.appState.Qr, warning: state.appState.warning, + network: state.metamask.network, } } diff --git a/old-ui/app/util.js b/old-ui/app/util.js index 0a64a37e8..54f104654 100644 --- a/old-ui/app/util.js +++ b/old-ui/app/util.js @@ -81,11 +81,9 @@ function accountSummary (acc, firstSegLength = 6, lastSegLength = 4) { function isValidAddress (address, network) { var prefixed = ethUtil.addHexPrefix(address) if (ifRSK(network)) { - // console.log('addHexPrefixRSK:', prefixed) if (address === '0x0000000000000000000000000000000000000000') return false return (ethUtil.isValidAddress(prefixed)) } else { - // console.log('addHexPrefix:', prefixed) if (address === '0x0000000000000000000000000000000000000000') return false return (isAllOneCase(prefixed) && ethUtil.isValidAddress(prefixed)) || ethUtil.isValidChecksumAddress(prefixed) } @@ -414,9 +412,5 @@ function toChecksumAddress (network, address, chainId = null) { } function isValidChecksumAddress (network, address) { - // console.log('isValidAddress(address):', isValidAddress(address, network)) - // console.log('toChecksumAddress(network, address) === address', toChecksumAddress(network, address) === address) - // console.log('ethUtil.isValidAddress(address)', ethUtil.isValidAddress(address)) - // console.log('isAllOneCase', isAllOneCase(address)) return isValidAddress(address, network) && toChecksumAddress(network, address) === address } From bfdb205fd31f38b17cf1c896684b7523044cd7a6 Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Wed, 19 Jun 2019 02:49:12 +0300 Subject: [PATCH 4/6] Display address checksum behind QR-code for RSK chains --- old-ui/app/account-qr.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/old-ui/app/account-qr.js b/old-ui/app/account-qr.js index 7e3b7f269..b6bd727bd 100644 --- a/old-ui/app/account-qr.js +++ b/old-ui/app/account-qr.js @@ -5,7 +5,7 @@ const {qrcode: qrCode} = require('qrcode-npm') const {connect} = require('react-redux') const {isHexPrefixed} = require('ethereumjs-util') const CopyButton = require('./components/copy/copy-button') -const { toChecksumAddress } = require('./util') +const { toChecksumAddress, ifRSK } = require('./util') class AccountQrScreen extends PureComponent { static defaultProps = { @@ -20,8 +20,8 @@ class AccountQrScreen extends PureComponent { render () { const {Qr, warning, network} = this.props - const address = `${isHexPrefixed(Qr.data) ? 'ethereum:' : ''}${Qr.data}` const addressChecksum = toChecksumAddress(network, Qr.data) + const address = ifRSK ? addressChecksum : `${isHexPrefixed(Qr.data) ? 'ethereum:' : ''}${Qr.data}` const qrImage = qrCode(4, 'M') qrImage.addData(address) From 955b4b5d5f2a0857f3ddfc146b12146ad24c503a Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Wed, 19 Jun 2019 10:26:07 +0300 Subject: [PATCH 5/6] lint fix --- old-ui/app/account-qr.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/old-ui/app/account-qr.js b/old-ui/app/account-qr.js index b6bd727bd..9ab715c53 100644 --- a/old-ui/app/account-qr.js +++ b/old-ui/app/account-qr.js @@ -21,7 +21,7 @@ class AccountQrScreen extends PureComponent { render () { const {Qr, warning, network} = this.props const addressChecksum = toChecksumAddress(network, Qr.data) - const address = ifRSK ? addressChecksum : `${isHexPrefixed(Qr.data) ? 'ethereum:' : ''}${Qr.data}` + const address = ifRSK ? addressChecksum : `${isHexPrefixed(Qr.data) ? 'ethereum:' : ''}${Qr.data}` const qrImage = qrCode(4, 'M') qrImage.addData(address) From 7d44c6c037165b5aef4b8d91cb37aaff24ceaa7c Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Wed, 19 Jun 2019 14:17:41 +0300 Subject: [PATCH 6/6] Update old-ui/app/util.js Co-Authored-By: Gerardo Nardelli --- old-ui/app/util.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/old-ui/app/util.js b/old-ui/app/util.js index 54f104654..a05fb3219 100644 --- a/old-ui/app/util.js +++ b/old-ui/app/util.js @@ -390,7 +390,7 @@ function ifRSK (network) { function toChecksumAddressRSK (address, chainId = null) { const zeroX = '0x' const stripAddress = ethUtil.stripHexPrefix(address).toLowerCase() - const prefix = chainId != null ? (chainId.toString() + zeroX) : '' + const prefix = chainId !== null ? (chainId.toString() + zeroX) : '' const keccakHash = ethUtil.sha3(prefix + stripAddress).toString('hex') let output = zeroX