fix(bug): user can input invalid lifetime for tx (#10862)

* fix lifetime input

* updated isLifetime
This commit is contained in:
Alberto Nicolas Penayo 2024-08-23 12:51:24 -03:00 committed by GitHub
parent 738dec1e7c
commit 0d59324dec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 49 additions and 16 deletions

View File

@ -24,6 +24,7 @@ interface Props {
isDisabled?: boolean;
isError?: boolean;
isFull?: boolean;
isLifetime?: boolean;
isLoading?: boolean;
isSi?: boolean;
isDecimal?: boolean;
@ -94,13 +95,41 @@ function isValidNumber (bn: BN, bitLength: BitLength, isSigned: boolean, isZeroa
return true;
}
function inputToBn (api: ApiPromise, input: string, si: SiDef | null, bitLength: BitLength, isSigned: boolean, isZeroable: boolean, maxValue?: BN | null, decimals?: number): [BN, boolean] {
function inputToBn (api: ApiPromise, input: string, si: SiDef | null, bitLength: BitLength, isLifetime: boolean, isSigned: boolean, isZeroable: boolean, maxValue?: BN | null, decimals?: number): [string, BN, boolean] {
const [siPower, basePower, siUnitPower] = getSiPowers(si, decimals);
// eslint-disable-next-line @typescript-eslint/prefer-regexp-exec
const isDecimalValue = input.match(/^(\d+)\.(\d+)$/);
let result;
if (isLifetime) {
const maxLifetime = new BN(api.consts.system.blockHashCount);
if (isDecimalValue) {
if (siUnitPower - isDecimalValue[2].length < -basePower) {
result = new BN(-1);
}
const div = new BN(input.replace(/\.\d*$/, ''));
const modString = input.replace(/^\d+\./, '').substring(0, api.registry.chainDecimals[0]);
const mod = new BN(modString);
result = BN.min(div
.mul(BN_TEN.pow(siPower))
.add(mod.mul(BN_TEN.pow(new BN(basePower + siUnitPower - modString.length)))), maxLifetime);
} else {
result = BN.min(new BN(input.replace(/[^\d]/g, ''))
.mul(BN_TEN.pow(siPower))
.muln(isSigned && input.startsWith('-') ? -1 : 1), maxLifetime);
}
return [
result.toString(),
result,
isValidNumber(result, bitLength, isSigned, isZeroable, maxValue)
];
}
if (isDecimalValue) {
if (siUnitPower - isDecimalValue[2].length < -basePower) {
result = new BN(-1);
@ -120,15 +149,15 @@ function inputToBn (api: ApiPromise, input: string, si: SiDef | null, bitLength:
}
return [
result.toString(),
result,
isValidNumber(result, bitLength, isSigned, isZeroable, maxValue)
];
}
function getValuesFromString (api: ApiPromise, value: string, si: SiDef | null, bitLength: BitLength, isSigned: boolean, isZeroable: boolean, maxValue?: BN | null, decimals?: number): [string, BN, boolean] {
function getValuesFromString (api: ApiPromise, value: string, si: SiDef | null, bitLength: BitLength, isLifetime: boolean, isSigned: boolean, isZeroable: boolean, maxValue?: BN | null, decimals?: number): [string, BN, boolean] {
return [
value,
...inputToBn(api, value, si, bitLength, isSigned, isZeroable, maxValue, decimals)
...inputToBn(api, value, si, bitLength, isLifetime, isSigned, isZeroable, maxValue, decimals)
];
}
@ -142,19 +171,18 @@ function getValuesFromBn (valueBn: BN, si: SiDef | null, isSigned: boolean, isZe
? valueBn.div(BN_TEN.pow(new BN(decimals + si.power))).toString()
: valueBn.toString(),
valueBn,
isZeroable || isSigned
? true
: valueBn.gt(BN_ZERO)
isZeroable || isSigned ? true : valueBn.gt(BN_ZERO)
];
}
function getValues (api: ApiPromise, value: BN | string = BN_ZERO, si: SiDef | null, bitLength: BitLength, isSigned: boolean, isZeroable: boolean, maxValue?: BN | null, decimals?: number): [string, BN, boolean] {
function getValues (api: ApiPromise, value: BN | string = BN_ZERO, si: SiDef | null, bitLength: BitLength, isLifetime: boolean, isSigned: boolean, isZeroable: boolean, maxValue?: BN | null, decimals?: number): [string, BN, boolean] {
return isBn(value)
? getValuesFromBn(value, si, isSigned, isZeroable, decimals)
: getValuesFromString(api, value, si, bitLength, isSigned, isZeroable, maxValue, decimals);
: getValuesFromString(api, value, si, bitLength, isLifetime, isSigned, isZeroable, maxValue, decimals);
}
function InputNumber ({ autoFocus, bitLength = DEFAULT_BITLENGTH, children, className = '', defaultValue, isDecimal, isDisabled, isError = false, isFull, isLoading, isSi, isSigned = false, isWarning, isZeroable = true, label, labelExtra, maxLength, maxValue, onChange, onEnter, onEscape, placeholder, siDecimals, siDefault, siSymbol, value: propsValue }: Props): React.ReactElement<Props> {
function InputNumber ({ autoFocus, bitLength = DEFAULT_BITLENGTH, children, className = '', defaultValue, isDecimal, isDisabled, isError = false, isFull, isLifetime, isLoading, isSi, isSigned = false, isWarning, isZeroable = true, label, labelExtra, maxLength, maxValue, onChange, onEnter, onEscape, placeholder, siDecimals, siDefault, siSymbol, value: propsValue }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const { api } = useApi();
const [si] = useState<SiDef | null>(() =>
@ -163,8 +191,9 @@ function InputNumber ({ autoFocus, bitLength = DEFAULT_BITLENGTH, children, clas
: null
);
const [[value, valueBn, isValid], setValues] = useState<[string, BN, boolean]>(() =>
getValues(api, propsValue || defaultValue, si, bitLength, isSigned, isZeroable, maxValue, siDecimals)
getValues(api, propsValue || defaultValue, si, bitLength, !!isLifetime, isSigned, isZeroable, maxValue, siDecimals)
);
const [isPreKeyDown, setIsPreKeyDown] = useState(false);
useEffect((): void => {
@ -172,14 +201,17 @@ function InputNumber ({ autoFocus, bitLength = DEFAULT_BITLENGTH, children, clas
}, [isValid, onChange, valueBn]);
const _onChangeWithSi = useCallback(
(input: string, si: SiDef | null) => setValues(
getValuesFromString(api, input, si, bitLength, isSigned, isZeroable, maxValue, siDecimals)
),
[api, bitLength, isSigned, isZeroable, maxValue, siDecimals]
(input: string, si: SiDef | null) =>
setValues(
getValuesFromString(api, input, si, bitLength, !!isLifetime, isSigned, isZeroable, maxValue, siDecimals)
),
[api, bitLength, isLifetime, isSigned, isZeroable, maxValue, siDecimals]
);
const _onChange = useCallback(
(input: string) => _onChangeWithSi(input, si),
(input: string) => {
_onChangeWithSi(input, si);
},
[_onChangeWithSi, si]
);

View File

@ -62,6 +62,7 @@ function SignFields ({ address, onChange, signedTx }: Props): React.ReactElement
/>
<InputNumber
isDisabled={!!signedTx}
isLifetime={true}
isZeroable
label={t('Lifetime (# of blocks)')}
labelExtra={t('Set to 0 to make transaction immortal')}