fix: Send refuses every amount the confirmation screen would refuse (closes #532)
Send accepted any amount parseFloat() read as above zero, so "1e-3", "1abc" and an amount with a nonzero digit past the token's decimal places reached ConfirmTx, which then refused them. isValidAmount() in src/shared/txValidation.js is now the one check: Review and Max on Send call it with the token's decimal places, and validateTransfer() calls it for ConfirmTx, which now also refuses a zero amount and a token amount with a nonzero digit past the token's places. Zeros past those places are accepted, since the amount encoded for the transfer is the same. Model: opus-5-5
This commit is contained in:
@@ -6,6 +6,7 @@ const {
|
||||
FEE_UNAVAILABLE,
|
||||
feeReserveWei,
|
||||
feeEstimateWei,
|
||||
isValidAmount,
|
||||
maxEthAmount,
|
||||
maxTokenAmount,
|
||||
toFixedPoint,
|
||||
@@ -33,6 +34,49 @@ describe("toFixedPoint", () => {
|
||||
});
|
||||
});
|
||||
|
||||
// The one amount check the Send screen and the confirmation screen share.
|
||||
// The screens themselves are driven in tests/sendAmountRule.test.js.
|
||||
describe("isValidAmount", () => {
|
||||
test("accepts a number above zero written as digits and a decimal point", () => {
|
||||
expect(isValidAmount("0.5")).toBe(true);
|
||||
expect(isValidAmount("12")).toBe(true);
|
||||
expect(isValidAmount(".5")).toBe(true);
|
||||
expect(isValidAmount("0.000000000000000001")).toBe(true);
|
||||
});
|
||||
|
||||
test("refuses an exponent, trailing text, zero and a negative amount", () => {
|
||||
expect(isValidAmount("1e-3")).toBe(false);
|
||||
expect(isValidAmount("1abc")).toBe(false);
|
||||
expect(isValidAmount("0")).toBe(false);
|
||||
expect(isValidAmount("0.0")).toBe(false);
|
||||
expect(isValidAmount("-1")).toBe(false);
|
||||
expect(isValidAmount("")).toBe(false);
|
||||
expect(isValidAmount(undefined)).toBe(false);
|
||||
});
|
||||
|
||||
test("refuses a digit other than 0 past the token's places", () => {
|
||||
expect(isValidAmount("0.000001", 6)).toBe(true);
|
||||
expect(isValidAmount("0.0000001", 6)).toBe(false);
|
||||
expect(isValidAmount("5", 0)).toBe(true);
|
||||
expect(isValidAmount("0.5", 0)).toBe(false);
|
||||
});
|
||||
|
||||
test("accepts zeros past the token's places, which leave the amount unchanged", () => {
|
||||
expect(isValidAmount("1.0000000", 6)).toBe(true);
|
||||
expect(isValidAmount("5.0", 0)).toBe(true);
|
||||
expect(isValidAmount("1.0000000000000000000")).toBe(true);
|
||||
expect(isValidAmount("0.0000000", 6)).toBe(false);
|
||||
});
|
||||
|
||||
test("holds ETH, a token of unknown places, and any token to 18 places", () => {
|
||||
const nineteen = "0.0000000000000000001";
|
||||
expect(isValidAmount(nineteen)).toBe(false);
|
||||
expect(isValidAmount(nineteen, null)).toBe(false);
|
||||
expect(isValidAmount(nineteen, 24)).toBe(false);
|
||||
expect(isValidAmount("0.000000000000000001", 24)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("validateTransfer, native ETH", () => {
|
||||
const eth = (over) => ({
|
||||
isErc20: false,
|
||||
@@ -134,6 +178,17 @@ describe("validateTransfer, native ETH", () => {
|
||||
).toEqual({ canSend: false, codes: [CODES.AMOUNT_INVALID] });
|
||||
});
|
||||
|
||||
test("rejects a zero amount and an exponent", () => {
|
||||
expect(validateTransfer(eth({ amount: "0" }))).toEqual({
|
||||
canSend: false,
|
||||
codes: [CODES.AMOUNT_INVALID],
|
||||
});
|
||||
expect(validateTransfer(eth({ amount: "1e-3" }))).toEqual({
|
||||
canSend: false,
|
||||
codes: [CODES.AMOUNT_INVALID],
|
||||
});
|
||||
});
|
||||
|
||||
test("treats a missing balance as zero, not as unlimited", () => {
|
||||
const r = validateTransfer(eth({ ethBalance: undefined }));
|
||||
expect(r.codes).toEqual([CODES.INSUFFICIENT_ETH]);
|
||||
@@ -205,6 +260,16 @@ describe("validateTransfer, ERC-20", () => {
|
||||
expect(r).toEqual({ canSend: false, codes: [CODES.AMOUNT_INVALID] });
|
||||
});
|
||||
|
||||
test("rejects more decimal places than the token has", () => {
|
||||
const r = validateTransfer(
|
||||
erc20({ amount: "0.0000001", tokenDecimals: 6 }),
|
||||
);
|
||||
expect(r).toEqual({ canSend: false, codes: [CODES.AMOUNT_INVALID] });
|
||||
expect(
|
||||
validateTransfer(erc20({ amount: "0.000001", tokenDecimals: 6 })),
|
||||
).toEqual({ canSend: true, codes: [] });
|
||||
});
|
||||
|
||||
test("treats a missing token balance as zero", () => {
|
||||
const r = validateTransfer(erc20({ tokenBalance: undefined }));
|
||||
expect(r.codes).toEqual([CODES.INSUFFICIENT_TOKEN]);
|
||||
|
||||
Reference in New Issue
Block a user