From 5995568e195e6a213b21048716fd98f357603e1a Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Mon, 8 Oct 2018 17:51:25 +0200 Subject: [PATCH 1/3] allow "0x" prefix in transaction data fix: #101 --- src/actions/SendFormActions.js | 2 +- src/actions/SendFormValidationActions.js | 2 +- src/actions/TxActions.js | 4 ++-- src/actions/Web3Actions.js | 4 ++-- src/utils/ethUtils.js | 7 +++---- 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/actions/SendFormActions.js b/src/actions/SendFormActions.js index f26664f3..ddd8ddf5 100644 --- a/src/actions/SendFormActions.js +++ b/src/actions/SendFormActions.js @@ -397,7 +397,7 @@ const estimateGasPrice = (): AsyncAction => async (dispatch: Dispatch, getState: } const requestedData = state.data; - const re = /^[0-9A-Fa-f]+$/g; // TODO: allow "0x" prefix + const re = /^(0x|0X)?[0-9A-Fa-f]+$/g; if (!re.test(requestedData)) { // stop "calculatingGasLimit" process dispatch(onGasLimitChange(requestedData.length > 0 ? state.gasLimit : network.defaultGasLimit.toString())); diff --git a/src/actions/SendFormValidationActions.js b/src/actions/SendFormValidationActions.js index 97c71ed4..4fb99bd4 100644 --- a/src/actions/SendFormValidationActions.js +++ b/src/actions/SendFormValidationActions.js @@ -19,7 +19,7 @@ const NUMBER_RE: RegExp = new RegExp('^(0|0\\.([0-9]+)?|[1-9][0-9]*\\.?([0-9]+)? const UPPERCASE_RE = new RegExp('^(.*[A-Z].*)$'); const ABS_RE = new RegExp('^[0-9]+$'); const ETH_18_RE = new RegExp('^(0|0\\.([0-9]{0,18})?|[1-9][0-9]*\\.?([0-9]{0,18})?|\\.[0-9]{0,18})$'); -const HEX_RE = new RegExp('^[0-9A-Fa-f]+$'); +const HEX_RE = new RegExp('^(0x|0X)?[0-9A-Fa-f]+$'); const dynamicRegexp = (decimals: number): RegExp => { if (decimals > 0) { return new RegExp(`^(0|0\\.([0-9]{0,${decimals}})?|[1-9][0-9]*\\.?([0-9]{0,${decimals}})?|\\.[0-9]{1,${decimals}})$`); diff --git a/src/actions/TxActions.js b/src/actions/TxActions.js index 67c93c9f..ad34a5e7 100644 --- a/src/actions/TxActions.js +++ b/src/actions/TxActions.js @@ -5,6 +5,7 @@ import EthereumjsUnits from 'ethereumjs-units'; import BigNumber from 'bignumber.js'; import { toHex } from 'web3-utils'; // eslint-disable-line import/no-extraneous-dependencies import { initWeb3 } from 'actions/Web3Actions'; +import * as ethUtils from 'utils/ethUtils'; import type { Dispatch, @@ -29,10 +30,9 @@ type EthereumTxRequest = { export const prepareEthereumTx = (tx: EthereumTxRequest): PromiseAction => async (dispatch: Dispatch): Promise => { const instance = await dispatch(initWeb3(tx.network)); const { token } = tx; - let data: string = `0x${tx.data}`; // TODO: check if already prefixed + let data: string = ethUtils.sanitizeHex(tx.data); // TODO: check if already prefixed let value: string = toHex(EthereumjsUnits.convert(tx.amount, 'ether', 'wei')); let to: string = tx.to; // eslint-disable-line prefer-destructuring - if (token) { // smart contract transaction const contract = instance.erc20.clone(); diff --git a/src/actions/Web3Actions.js b/src/actions/Web3Actions.js index 53c26a3b..2c3d9131 100644 --- a/src/actions/Web3Actions.js +++ b/src/actions/Web3Actions.js @@ -7,6 +7,7 @@ import EthereumjsUnits from 'ethereumjs-units'; import type { EstimateGasOptions } from 'web3'; import * as WEB3 from 'actions/constants/web3'; import * as PENDING from 'actions/constants/pendingTx'; +import * as ethUtils from 'utils/ethUtils'; import type { Dispatch, @@ -272,8 +273,7 @@ export const updateGasPrice = (network: string): PromiseAction => async (d export const estimateGasLimit = (network: string, $options: EstimateGasOptions): PromiseAction => async (dispatch: Dispatch): Promise => { const instance = await dispatch(initWeb3(network)); - // TODO: allow data starting with 0x ... - const data = `0x${$options.data.length % 2 === 0 ? $options.data : `0${$options.data}`}`; + const data = ethUtils.sanitizeHex($options.data); const options = { ...$options, to: '0x0000000000000000000000000000000000000000', diff --git a/src/utils/ethUtils.js b/src/utils/ethUtils.js index 2d4b553e..94e61a6f 100644 --- a/src/utils/ethUtils.js +++ b/src/utils/ethUtils.js @@ -7,15 +7,14 @@ export const decimalToHex = (dec: number): string => new BigNumber(dec).toString export const padLeftEven = (hex: string): string => (hex.length % 2 !== 0 ? `0${hex}` : hex); -export const sanitizeHex = ($hex: number | string): ?string => { - if (typeof $hex !== 'string') return null; - const hex = $hex.substring(0, 2) === '0x' ? $hex.substring(2) : $hex; +export const sanitizeHex = ($hex: string): string => { + const hex = $hex.toLowerCase().substring(0, 2) === '0x' ? $hex.substring(2) : $hex; if (hex === '') return ''; return `0x${padLeftEven(hex)}`; }; export const hexToDecimal = (hex: number): string => { - const sanitized: ?string = sanitizeHex(hex); + const sanitized: ?string = sanitizeHex(hex.toString()); return !sanitized ? 'null' : new BigNumber(sanitized).toString(); }; From 4da23c1db24476e6caf86f175f9f57293e9ad8a2 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Mon, 8 Oct 2018 17:52:48 +0200 Subject: [PATCH 2/3] remove comment --- src/actions/TxActions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/actions/TxActions.js b/src/actions/TxActions.js index ad34a5e7..e3d35cd5 100644 --- a/src/actions/TxActions.js +++ b/src/actions/TxActions.js @@ -30,7 +30,7 @@ type EthereumTxRequest = { export const prepareEthereumTx = (tx: EthereumTxRequest): PromiseAction => async (dispatch: Dispatch): Promise => { const instance = await dispatch(initWeb3(tx.network)); const { token } = tx; - let data: string = ethUtils.sanitizeHex(tx.data); // TODO: check if already prefixed + let data: string = ethUtils.sanitizeHex(tx.data); let value: string = toHex(EthereumjsUnits.convert(tx.amount, 'ether', 'wei')); let to: string = tx.to; // eslint-disable-line prefer-destructuring if (token) { From 51ed553e9aefd37b551ba10b2083daeeac9ac0dd Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Tue, 9 Oct 2018 10:42:36 +0200 Subject: [PATCH 3/3] move hex regexp to /utils/ethUtils --- src/actions/SendFormActions.js | 4 ++-- src/actions/SendFormValidationActions.js | 4 ++-- src/utils/ethUtils.js | 5 +++++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/actions/SendFormActions.js b/src/actions/SendFormActions.js index ddd8ddf5..6b3899c8 100644 --- a/src/actions/SendFormActions.js +++ b/src/actions/SendFormActions.js @@ -11,6 +11,7 @@ import * as ValidationActions from 'actions/SendFormValidationActions'; import { initialState } from 'reducers/SendFormReducer'; import { findToken } from 'reducers/TokensReducer'; import * as reducerUtils from 'reducers/utils'; +import * as ethUtils from 'utils/ethUtils'; import type { Dispatch, @@ -397,8 +398,7 @@ const estimateGasPrice = (): AsyncAction => async (dispatch: Dispatch, getState: } const requestedData = state.data; - const re = /^(0x|0X)?[0-9A-Fa-f]+$/g; - if (!re.test(requestedData)) { + if (!ethUtils.isHex(requestedData)) { // stop "calculatingGasLimit" process dispatch(onGasLimitChange(requestedData.length > 0 ? state.gasLimit : network.defaultGasLimit.toString())); return; diff --git a/src/actions/SendFormValidationActions.js b/src/actions/SendFormValidationActions.js index 4fb99bd4..327ccff3 100644 --- a/src/actions/SendFormValidationActions.js +++ b/src/actions/SendFormValidationActions.js @@ -6,6 +6,7 @@ import EthereumjsUnits from 'ethereumjs-units'; import { findToken } from 'reducers/TokensReducer'; import { findDevice, getPendingAmount } from 'reducers/utils'; import * as SEND from 'actions/constants/send'; +import * as ethUtils from 'utils/ethUtils'; import type { Dispatch, @@ -19,7 +20,6 @@ const NUMBER_RE: RegExp = new RegExp('^(0|0\\.([0-9]+)?|[1-9][0-9]*\\.?([0-9]+)? const UPPERCASE_RE = new RegExp('^(.*[A-Z].*)$'); const ABS_RE = new RegExp('^[0-9]+$'); const ETH_18_RE = new RegExp('^(0|0\\.([0-9]{0,18})?|[1-9][0-9]*\\.?([0-9]{0,18})?|\\.[0-9]{0,18})$'); -const HEX_RE = new RegExp('^(0x|0X)?[0-9A-Fa-f]+$'); const dynamicRegexp = (decimals: number): RegExp => { if (decimals > 0) { return new RegExp(`^(0|0\\.([0-9]{0,${decimals}})?|[1-9][0-9]*\\.?([0-9]{0,${decimals}})?|\\.[0-9]{1,${decimals}})$`); @@ -326,7 +326,7 @@ export const nonceValidation = ($state: State): PayloadAction => (dispatc export const dataValidation = ($state: State): PayloadAction => (): State => { const state = { ...$state }; if (!state.touched.data || state.data.length === 0) return state; - if (!HEX_RE.test(state.data)) { + if (!ethUtils.isHex(state.data)) { state.errors.data = 'Data is not valid hexadecimal'; } return state; diff --git a/src/utils/ethUtils.js b/src/utils/ethUtils.js index 94e61a6f..baa15dbb 100644 --- a/src/utils/ethUtils.js +++ b/src/utils/ethUtils.js @@ -39,4 +39,9 @@ export const validateAddress = (address: string): ?string => { return 'Address is not a valid checksum'; } return null; +}; + +export const isHex = (str: string): boolean => { + const regExp = /^(0x|0X)?[0-9A-Fa-f]+$/g; + return regExp.test(str); }; \ No newline at end of file