From 45834b0d2a054dd574ec4b4c1f6c21f916bcbaa1 Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Wed, 12 Jun 2019 23:58:58 +0300 Subject: [PATCH] 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') }) })