RSK address checksum

This commit is contained in:
Victor Baranov 2019-06-12 23:58:58 +03:00
parent 2e36d0b44a
commit 45834b0d2a
15 changed files with 77 additions and 51 deletions

View File

@ -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())

View File

@ -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)),
]),
]),

View File

@ -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)
}

View File

@ -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),
],

View File

@ -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)),
]),
]),
])

View File

@ -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)' }}
>
<div style={{ lineHeight: '16px', fontSize: '14px' }}>
{addressSummary(address)}
{addressSummary(network, address)}
</div>
</div>
</div>

View File

@ -59,7 +59,7 @@ class SendProfile extends Component {
}}
>
<div className="send-profile-address" style={{ lineHeight: '16px', fontSize: '14px' }}>
{addressSummary(address)}
{addressSummary(network, address)}
</div>
</div>
{/* balance */}

View File

@ -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,
}),

View File

@ -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)
},
},

View File

@ -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, {

View File

@ -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
}

View File

@ -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
}

View File

@ -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)
}

View File

@ -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.

View File

@ -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')
})
})