From c1142ddda9683e454b3cb5dfac229046de7ed52e Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Sun, 16 Jun 2019 21:21:24 +0300 Subject: [PATCH] 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) + }) + }) })