mirror of
https://github.com/status-im/MyCrypto.git
synced 2025-02-10 02:04:32 +00:00
[FEATURE] Additional validation
This commit is contained in:
parent
40be251e7b
commit
37e81f7040
@ -95,7 +95,7 @@ interface SetWindowSizeFieldAction {
|
||||
type: TypeKeys.WINDOW_SIZE_FIELD_SET;
|
||||
payload: {
|
||||
raw: string;
|
||||
value: number | null;
|
||||
value: Wei | null;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -4,11 +4,17 @@ import { SagaIterator } from 'redux-saga';
|
||||
import { TypeKeys } from 'actions/transaction/constants';
|
||||
import { SetWindowSizeFieldAction } from 'actions/transaction';
|
||||
import { SetCurrentWindowSizeAction } from '../../../actions/transaction/actionTypes/windowSize';
|
||||
import { validNumber } from 'libs/validators';
|
||||
import BN from 'bn.js';
|
||||
|
||||
export function* setCurrentWindowSize({ payload: raw }: SetCurrentWindowSizeAction): SagaIterator {
|
||||
let value: number | null = null;
|
||||
let value: BN | null = null;
|
||||
|
||||
value = parseInt(raw, 10);
|
||||
if (!validNumber(parseInt(raw, 10))) {
|
||||
yield call(setField, { raw, value: null });
|
||||
}
|
||||
|
||||
value = new BN(raw);
|
||||
|
||||
yield call(setField, { value, raw });
|
||||
}
|
||||
|
@ -3,7 +3,12 @@ import { select, fork, call, take, apply, put } from 'redux-saga/effects';
|
||||
import { getOffline, getNodeLib } from 'selectors/config';
|
||||
import {
|
||||
ICurrentSchedulingToggle,
|
||||
ICurrentWindowSize
|
||||
ICurrentWindowSize,
|
||||
ICurrentWindowStart,
|
||||
ICurrentScheduleType,
|
||||
ICurrentScheduleTimezone,
|
||||
ICurrentScheduleTimestamp,
|
||||
ICurrentTimeBounty
|
||||
} from 'containers/Tabs/ScheduleTransaction/selectors';
|
||||
import {
|
||||
getSchedulingToggle,
|
||||
@ -39,7 +44,7 @@ import { gasPriceToBase } from 'libs/units';
|
||||
import BN from 'bn.js';
|
||||
import { bufferToHex } from 'ethereumjs-util';
|
||||
import RequestFactory from 'libs/scheduling/contracts/RequestFactory';
|
||||
import { dateTimeToUnixTimestamp, windowSizeBlockToMin } from 'selectors/transaction/helpers';
|
||||
import { windowSizeBlockToMin, calculateWindowStart } from 'selectors/transaction/helpers';
|
||||
|
||||
export function* shouldValidateParams(): SagaIterator {
|
||||
while (true) {
|
||||
@ -74,24 +79,25 @@ function* checkSchedulingParametersValidity() {
|
||||
const currentTo = yield select(getCurrentTo);
|
||||
const currentValue = yield select(getCurrentValue);
|
||||
const callData = yield select(getData);
|
||||
const scheduleType = yield select(getScheduleType);
|
||||
const windowStart = yield select(getWindowStart);
|
||||
const scheduleType: ICurrentScheduleType = yield select(getScheduleType);
|
||||
const windowStart: ICurrentWindowStart = yield select(getWindowStart);
|
||||
const windowSize: ICurrentWindowSize = yield select(getWindowSize);
|
||||
const timeBounty = yield select(getTimeBounty);
|
||||
const timeBounty: ICurrentTimeBounty = yield select(getTimeBounty);
|
||||
const scheduleGasPrice = yield select(getScheduleGasPrice);
|
||||
const scheduleGasLimit = yield select(getScheduleGasLimit);
|
||||
const deposit = yield select(getScheduleDeposit);
|
||||
const node = yield select(getNodeLib);
|
||||
const wallet = yield select(getWalletInst);
|
||||
const scheduleTimestamp = yield select(getScheduleTimestamp);
|
||||
const scheduleTimezone = yield select(getScheduleTimezone);
|
||||
const scheduleTimestamp: ICurrentScheduleTimestamp = yield select(getScheduleTimestamp);
|
||||
const scheduleTimezone: ICurrentScheduleTimezone = yield select(getScheduleTimezone);
|
||||
|
||||
if (
|
||||
!currentValue.value ||
|
||||
!currentTo.value ||
|
||||
!scheduleGasPrice.value ||
|
||||
!wallet ||
|
||||
!windowSize.value
|
||||
!windowSize.value ||
|
||||
!windowStart.value
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@ -112,10 +118,13 @@ function* checkSchedulingParametersValidity() {
|
||||
callData.value ? bufferToHex(callData.value) : '',
|
||||
callGasLimit,
|
||||
currentValue.value,
|
||||
windowSizeBlockToMin(windowSize.value, scheduleType.value) || 0,
|
||||
scheduleType.value === 'time'
|
||||
? dateTimeToUnixTimestamp(scheduleTimestamp, scheduleTimezone.value)
|
||||
: windowStart.value,
|
||||
windowSizeBlockToMin(windowSize.value, scheduleType.value),
|
||||
calculateWindowStart(
|
||||
scheduleType.value,
|
||||
scheduleTimestamp,
|
||||
scheduleTimezone.value,
|
||||
windowStart.value
|
||||
),
|
||||
scheduleGasPrice.value,
|
||||
timeBounty.value,
|
||||
deposit.value || new BN(0),
|
||||
|
@ -1,12 +1,8 @@
|
||||
import { AppState } from 'reducers';
|
||||
import moment from 'moment';
|
||||
import 'moment-timezone';
|
||||
|
||||
export const isWindowSizeValid = (transactionFields: AppState['transaction']['fields']) => {
|
||||
const { windowSize } = transactionFields;
|
||||
|
||||
return Boolean(windowSize && windowSize.value);
|
||||
};
|
||||
import { ICurrentScheduleTimestamp } from '.';
|
||||
import BN from 'bn.js';
|
||||
|
||||
export const isWindowStartValid = (
|
||||
transactionFields: AppState['transaction']['fields'],
|
||||
@ -24,16 +20,29 @@ export const isScheduleTimestampValid = (transactionFields: AppState['transactio
|
||||
return Boolean(scheduleTimestamp && scheduleTimestamp.value && scheduleTimestamp.value > now);
|
||||
};
|
||||
|
||||
export const dateTimeToUnixTimestamp = (scheduleTimestamp: any, timezone: string) => {
|
||||
export const dateTimeToUnixTimestamp = (
|
||||
scheduleTimestamp: ICurrentScheduleTimestamp,
|
||||
timezone: string
|
||||
) => {
|
||||
if (scheduleTimestamp.value) {
|
||||
return moment.tz(scheduleTimestamp.raw, timezone).unix();
|
||||
}
|
||||
return scheduleTimestamp.value;
|
||||
};
|
||||
|
||||
export const windowSizeBlockToMin = (numberInput: number | null, scheduleType: string | null) => {
|
||||
export const windowSizeBlockToMin = (numberInput: BN | null, scheduleType: string | null) => {
|
||||
if (numberInput && scheduleType && scheduleType === 'time') {
|
||||
return numberInput * 60;
|
||||
return numberInput.mul(new BN(60));
|
||||
}
|
||||
return numberInput;
|
||||
};
|
||||
|
||||
export const calculateWindowStart = (
|
||||
scheduleType: string | null,
|
||||
scheduleTimestamp: any,
|
||||
scheduleTimezone: string,
|
||||
blockWindowStart: number | null
|
||||
): number =>
|
||||
(scheduleType === 'time'
|
||||
? dateTimeToUnixTimestamp(scheduleTimestamp, scheduleTimezone)
|
||||
: blockWindowStart) || 0;
|
||||
|
@ -3,10 +3,7 @@ import {
|
||||
getCurrentTo,
|
||||
getCurrentValue,
|
||||
getFields,
|
||||
getUnit,
|
||||
getDataExists,
|
||||
getData,
|
||||
getValidGasCost,
|
||||
getScheduleType,
|
||||
getWindowStart,
|
||||
getNonce,
|
||||
@ -21,81 +18,71 @@ import {
|
||||
getScheduleDeposit,
|
||||
getScheduleTimestamp,
|
||||
getScheduleTimezone,
|
||||
IGetTransaction
|
||||
IGetTransaction,
|
||||
getTransaction,
|
||||
isValidCurrentTimeBounty,
|
||||
isWindowSizeValid
|
||||
} from 'selectors/transaction';
|
||||
import { Address, gasPriceToBase } from 'libs/units';
|
||||
import {
|
||||
EAC_SCHEDULING_CONFIG,
|
||||
getScheduleData,
|
||||
calcEACEndowment,
|
||||
EAC_ADDRESSES
|
||||
getSchedulerAddress
|
||||
} from 'libs/scheduling';
|
||||
import BN from 'bn.js';
|
||||
import { makeTransaction } from 'libs/transaction';
|
||||
import {
|
||||
isFullTx,
|
||||
isWindowSizeValid,
|
||||
isWindowStartValid,
|
||||
isScheduleTimestampValid,
|
||||
dateTimeToUnixTimestamp,
|
||||
windowSizeBlockToMin
|
||||
windowSizeBlockToMin,
|
||||
calculateWindowStart
|
||||
} from 'selectors/transaction/helpers';
|
||||
import EthTx from 'ethereumjs-tx';
|
||||
import { getLatestBlock } from 'selectors/config';
|
||||
|
||||
export const getSchedulingTransaction = (state: AppState): IGetTransaction => {
|
||||
const { isFullTransaction } = getTransaction(state);
|
||||
|
||||
const currentTo = getCurrentTo(state);
|
||||
const currentValue = getCurrentValue(state);
|
||||
const transactionFields = getFields(state);
|
||||
const unit = getUnit(state);
|
||||
const dataExists = getDataExists(state);
|
||||
const callData = getData(state);
|
||||
const validGasCost = getValidGasCost(state);
|
||||
const scheduleType = getScheduleType(state);
|
||||
const windowStart = getWindowStart(state);
|
||||
const windowSize = getWindowSize(state);
|
||||
const nonce = getNonce(state);
|
||||
const gasPrice = getGasPrice(state);
|
||||
const timeBounty = getTimeBounty(state);
|
||||
const windowSizeValid = isWindowSizeValid(transactionFields);
|
||||
const windowStartValid = isWindowStartValid(transactionFields, getLatestBlock(state));
|
||||
const scheduleTimestamp = getScheduleTimestamp(state);
|
||||
const scheduleTimestampValid = isScheduleTimestampValid(transactionFields);
|
||||
const scheduleTimezone = getScheduleTimezone(state);
|
||||
const scheduleGasPrice = getScheduleGasPrice(state);
|
||||
const scheduleGasPriceValid = isValidScheduleGasPrice(state);
|
||||
const scheduleGasLimit = getScheduleGasLimit(state);
|
||||
const scheduleGasLimitValid = isValidScheduleGasLimit(state);
|
||||
const depositValid = isValidScheduleDeposit(state);
|
||||
const deposit = getScheduleDeposit(state);
|
||||
const scheduleType = getScheduleType(state);
|
||||
|
||||
const endowment = calcEACEndowment(
|
||||
scheduleGasLimit.value || EAC_SCHEDULING_CONFIG.SCHEDULE_GAS_LIMIT_FALLBACK,
|
||||
currentValue.value || new BN(0),
|
||||
scheduleGasPrice.value || gasPriceToBase(EAC_SCHEDULING_CONFIG.SCHEDULE_GAS_PRICE_FALLBACK),
|
||||
scheduleGasLimit.value,
|
||||
currentValue.value,
|
||||
scheduleGasPrice.value,
|
||||
timeBounty.value
|
||||
);
|
||||
|
||||
const isFullTransaction =
|
||||
isFullTx(state, transactionFields, currentTo, currentValue, dataExists, validGasCost, unit) &&
|
||||
(windowStartValid || scheduleTimestampValid) &&
|
||||
windowSizeValid &&
|
||||
scheduleGasPriceValid &&
|
||||
scheduleGasLimitValid &&
|
||||
depositValid;
|
||||
|
||||
let transactionData = null;
|
||||
|
||||
if (isFullTransaction) {
|
||||
const transactionFullAndValid = isFullTransaction && isSchedulingTransactionValid(state);
|
||||
|
||||
if (transactionFullAndValid) {
|
||||
const deposit = getScheduleDeposit(state);
|
||||
const scheduleTimestamp = getScheduleTimestamp(state);
|
||||
const windowSize = getWindowSize(state);
|
||||
const callData = getData(state);
|
||||
const scheduleTimezone = getScheduleTimezone(state);
|
||||
const windowStart = getWindowStart(state);
|
||||
|
||||
transactionData = getScheduleData(
|
||||
currentTo.raw,
|
||||
callData.raw,
|
||||
scheduleGasLimit.value,
|
||||
currentValue.value,
|
||||
windowSizeBlockToMin(windowSize.value, scheduleType.value),
|
||||
scheduleType.value === 'time'
|
||||
? dateTimeToUnixTimestamp(scheduleTimestamp, scheduleTimezone.value)
|
||||
: windowStart.value,
|
||||
calculateWindowStart(
|
||||
scheduleType.value,
|
||||
scheduleTimestamp,
|
||||
scheduleTimezone.value,
|
||||
windowStart.value
|
||||
),
|
||||
scheduleGasPrice.value,
|
||||
timeBounty.value,
|
||||
deposit.value
|
||||
@ -103,11 +90,7 @@ export const getSchedulingTransaction = (state: AppState): IGetTransaction => {
|
||||
}
|
||||
|
||||
const transactionOptions = {
|
||||
to: Address(
|
||||
scheduleType.value === 'time'
|
||||
? EAC_ADDRESSES.KOVAN.timestampScheduler
|
||||
: EAC_ADDRESSES.KOVAN.blockScheduler
|
||||
),
|
||||
to: getSchedulerAddress(scheduleType.value),
|
||||
data: transactionData,
|
||||
gasLimit: EAC_SCHEDULING_CONFIG.SCHEDULING_GAS_LIMIT,
|
||||
gasPrice: gasPrice.value,
|
||||
@ -119,10 +102,30 @@ export const getSchedulingTransaction = (state: AppState): IGetTransaction => {
|
||||
transactionOptions.nonce = new BN(nonce.raw);
|
||||
}
|
||||
|
||||
const transaction: EthTx = makeTransaction(transactionOptions);
|
||||
const schedulingTransaction: EthTx = makeTransaction(transactionOptions);
|
||||
|
||||
return {
|
||||
transaction,
|
||||
isFullTransaction
|
||||
transaction: schedulingTransaction,
|
||||
isFullTransaction: transactionFullAndValid
|
||||
};
|
||||
};
|
||||
|
||||
const isSchedulingTransactionValid = (state: AppState): boolean => {
|
||||
const transactionFields = getFields(state);
|
||||
const windowSizeValid = isWindowSizeValid(state);
|
||||
const windowStartValid = isWindowStartValid(transactionFields, getLatestBlock(state));
|
||||
const scheduleTimestampValid = isScheduleTimestampValid(transactionFields);
|
||||
const scheduleGasPriceValid = isValidScheduleGasPrice(state);
|
||||
const scheduleGasLimitValid = isValidScheduleGasLimit(state);
|
||||
const depositValid = isValidScheduleDeposit(state);
|
||||
const timeBountyValid = isValidCurrentTimeBounty(state);
|
||||
|
||||
return (
|
||||
(windowStartValid || scheduleTimestampValid) &&
|
||||
windowSizeValid &&
|
||||
scheduleGasPriceValid &&
|
||||
scheduleGasLimitValid &&
|
||||
depositValid &&
|
||||
timeBountyValid
|
||||
);
|
||||
};
|
||||
|
@ -1,15 +1,21 @@
|
||||
import { AppState } from 'reducers';
|
||||
import { getWindowSize } from './fields';
|
||||
import BN from 'bn.js';
|
||||
|
||||
interface ICurrentWindowSize {
|
||||
raw: string;
|
||||
value: number | null;
|
||||
value: BN | null;
|
||||
}
|
||||
|
||||
const isValidCurrentWindowSize = (state: AppState) => {
|
||||
const currentWindowSize = getWindowSize(state);
|
||||
|
||||
return currentWindowSize && currentWindowSize.value && currentWindowSize.value > 0;
|
||||
return (
|
||||
currentWindowSize &&
|
||||
currentWindowSize.value &&
|
||||
currentWindowSize.value.gt(new BN(0)) &&
|
||||
currentWindowSize.value.bitLength() <= 256
|
||||
);
|
||||
};
|
||||
|
||||
const getCurrentWindowSize = (state: AppState): ICurrentWindowSize => getWindowSize(state);
|
||||
|
@ -1,6 +1,6 @@
|
||||
import BN from 'bn.js';
|
||||
import abi from 'ethereumjs-abi';
|
||||
import { toWei, Units } from '../units';
|
||||
import { toWei, Units, gasPriceToBase, Address } from '../units';
|
||||
import { toBuffer } from 'ethereumjs-util';
|
||||
import RequestFactory from './contracts/RequestFactory';
|
||||
|
||||
@ -47,8 +47,22 @@ export const calcEACFutureExecutionCost = (
|
||||
.add(totalGas.mul(callGasPrice));
|
||||
};
|
||||
|
||||
export const calcEACEndowment = (callGas: BN, callValue: BN, callGasPrice: BN, timeBounty: BN) =>
|
||||
callValue.add(calcEACFutureExecutionCost(callGas, callGasPrice, timeBounty));
|
||||
export const calcEACEndowment = (
|
||||
callGas: BN | null,
|
||||
callValue: BN | null,
|
||||
callGasPrice: BN | null,
|
||||
timeBounty: BN
|
||||
) => {
|
||||
callValue = callValue || new BN(0);
|
||||
|
||||
return callValue.add(
|
||||
calcEACFutureExecutionCost(
|
||||
callGas || EAC_SCHEDULING_CONFIG.SCHEDULE_GAS_LIMIT_FALLBACK,
|
||||
callGasPrice || gasPriceToBase(EAC_SCHEDULING_CONFIG.SCHEDULE_GAS_PRICE_FALLBACK),
|
||||
timeBounty
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
export const calcEACTotalCost = (
|
||||
callGas: BN,
|
||||
@ -68,7 +82,7 @@ export const getScheduleData = (
|
||||
callData: string | Buffer = '',
|
||||
callGas: BN | null,
|
||||
callValue: BN | null,
|
||||
windowSize: number | null,
|
||||
windowSize: BN | null,
|
||||
windowStart: any,
|
||||
callGasPrice: BN | null,
|
||||
timeBounty: BN | null,
|
||||
@ -91,7 +105,8 @@ export const getScheduleData = (
|
||||
!timeBounty ||
|
||||
timeBounty.lt(new BN(0)) ||
|
||||
callGasPrice.lt(new BN(0)) ||
|
||||
windowSize < 0
|
||||
windowSize.lt(new BN(0)) ||
|
||||
windowSize.bitLength() > 256
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@ -133,8 +148,8 @@ export const getValidateRequestParamsData = (
|
||||
callData = '',
|
||||
callGas: BN,
|
||||
callValue: any,
|
||||
windowSize: number,
|
||||
windowStart: BN,
|
||||
windowSize: BN | null,
|
||||
windowStart: number,
|
||||
gasPrice: BN,
|
||||
timeBounty: BN,
|
||||
requiredDeposit: BN,
|
||||
@ -142,6 +157,8 @@ export const getValidateRequestParamsData = (
|
||||
endowment: BN,
|
||||
fromAddress: string
|
||||
): string => {
|
||||
windowSize = windowSize || new BN(0);
|
||||
|
||||
const temporalUnit = isTimestamp ? 2 : 1;
|
||||
const freezePeriod = isTimestamp ? 3 * 60 : 10; // 3 minutes or 10 blocks
|
||||
const reservedWindowSize = isTimestamp ? 5 * 60 : 16; // 5 minutes or 16 blocks
|
||||
@ -172,3 +189,10 @@ export const getValidateRequestParamsData = (
|
||||
export const getTXDetailsCheckURL = (txHash: string) => {
|
||||
return `${EAC_SCHEDULING_CONFIG.DAPP_ADDRESS}/awaiting/scheduler/${txHash}`;
|
||||
};
|
||||
|
||||
export const getSchedulerAddress = (scheduleType: string | null): Address =>
|
||||
Address(
|
||||
scheduleType === 'time'
|
||||
? EAC_ADDRESSES.KOVAN.timestampScheduler
|
||||
: EAC_ADDRESSES.KOVAN.blockScheduler
|
||||
);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { getTo, getValue, getScheduleGasPrice } from './fields';
|
||||
import { getTo, getValue, getScheduleGasPrice, getWindowSize } from './fields';
|
||||
import { getUnit, getTokenTo, getTokenValue } from './meta';
|
||||
import { AppState } from 'reducers';
|
||||
import { TokenValue, Wei, Address } from 'libs/units';
|
||||
@ -64,7 +64,13 @@ const isValidScheduleDeposit = (state: AppState): boolean => {
|
||||
return true;
|
||||
}
|
||||
|
||||
return depositValue.gte(new BN('0'));
|
||||
return depositValue.gte(new BN('0')) && depositValue.bitLength() <= 256;
|
||||
};
|
||||
|
||||
const isWindowSizeValid = (state: AppState): boolean => {
|
||||
const windowSize = getWindowSize(state);
|
||||
|
||||
return Boolean(windowSize && windowSize.value && windowSize.value.bitLength() <= 256);
|
||||
};
|
||||
|
||||
function getCurrentToAddressMessage(state: AppState): AddressMessage | undefined {
|
||||
@ -84,5 +90,6 @@ export {
|
||||
isValidScheduleGasLimit,
|
||||
isValidScheduleGasPrice,
|
||||
isValidScheduleDeposit,
|
||||
isWindowSizeValid,
|
||||
getCurrentToAddressMessage
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user