Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
75a24b59e7 |
@@ -1687,9 +1687,12 @@ view would leave a wallet one click from deletion.
|
|||||||
- "Review" (valid inputs, ENS resolved) → **ConfirmTx**
|
- "Review" (valid inputs, ENS resolved) → **ConfirmTx**
|
||||||
- "Review" with an unresolvable ENS name or an invalid amount → flash
|
- "Review" with an unresolvable ENS name or an invalid amount → flash
|
||||||
message, no screen change. An amount is valid when it is a number above
|
message, no screen change. An amount is valid when it is a number above
|
||||||
zero written as digits with at most one decimal point, with no more
|
zero, written as digits with at most one decimal point, with nothing but
|
||||||
decimal places than the token has and never more than 18 (ETH's own),
|
zeros after the token's last decimal place. ETH has 18 places, and a token
|
||||||
which is also the check ConfirmTx makes before anything can be sent
|
with more, or with an unknown number, is held to 18. Zeros past those
|
||||||
|
places leave the amount unchanged, so `1.0000000` of a 6-place token
|
||||||
|
passes and is sent as exactly 1. ConfirmTx makes the same check before
|
||||||
|
anything can be sent
|
||||||
- "Back" → previous screen (Home, AddressDetail, or AddressToken)
|
- "Back" → previous screen (Home, AddressDetail, or AddressToken)
|
||||||
|
|
||||||
#### ConfirmTx (`confirm-tx`)
|
#### ConfirmTx (`confirm-tx`)
|
||||||
|
|||||||
@@ -89,13 +89,16 @@ function toFixedPoint(value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Whether `amount` can be sent: a number above zero, written as digits with
|
// Whether `amount` can be sent: a number above zero, written as digits with
|
||||||
// at most one decimal point ("0.5", "12", ".5"), with no more decimal places
|
// at most one decimal point ("0.5", "12", ".5"), with nothing but zeros after
|
||||||
// than `tokenDecimals`, a token's own, and never more than the 18 the
|
// the token's last decimal place, `tokenDecimals`, and nothing but zeros after
|
||||||
// arithmetic here works in, which are ETH's. ETH, and a token whose decimal
|
// the 18th, the places the arithmetic here works in, which are ETH's. ETH, and
|
||||||
// places are unknown, pass null and are held to the 18 (the confirmation
|
// a token whose decimal places are unknown, pass null and are held to the 18
|
||||||
// screen refuses to send such a token anyway). Refuses "1e-3", "1abc", "0"
|
// (the confirmation screen refuses to send such a token anyway). Zeros past
|
||||||
// and "-1". The Send screen checks it before the confirmation screen opens,
|
// those places are accepted because parseUnits() drops them here and again
|
||||||
// and validateTransfer() checks it again there.
|
// when the transfer is encoded, so "1.0000000" of a 6-place token is exactly
|
||||||
|
// 1 everywhere. Refuses "1e-3", "1abc", "0" and "-1". The Send screen checks
|
||||||
|
// it before the confirmation screen opens, and validateTransfer() checks it
|
||||||
|
// again there.
|
||||||
function isValidAmount(amount, tokenDecimals = null) {
|
function isValidAmount(amount, tokenDecimals = null) {
|
||||||
if (typeof amount !== "string") return false;
|
if (typeof amount !== "string") return false;
|
||||||
const places = Math.min(tokenDecimals ?? SCALE_DECIMALS, SCALE_DECIMALS);
|
const places = Math.min(tokenDecimals ?? SCALE_DECIMALS, SCALE_DECIMALS);
|
||||||
|
|||||||
@@ -194,6 +194,9 @@ describe.each([
|
|||||||
["0.5", "TOK"],
|
["0.5", "TOK"],
|
||||||
// Exactly the 6 decimal places the token has.
|
// Exactly the 6 decimal places the token has.
|
||||||
["0.000001", "TOK"],
|
["0.000001", "TOK"],
|
||||||
|
// Only zeros past the token's 6 places, and past ETH's 18.
|
||||||
|
["1.0000000", "TOK"],
|
||||||
|
["0.5000000000000000000", "ETH"],
|
||||||
])("%s %s", (amount, symbol) => {
|
])("%s %s", (amount, symbol) => {
|
||||||
const token = TOKEN_BY_SYMBOL[symbol];
|
const token = TOKEN_BY_SYMBOL[symbol];
|
||||||
|
|
||||||
|
|||||||
@@ -116,6 +116,12 @@ describe("transferAmountUnits", () => {
|
|||||||
expect(() => transferAmountUnits("0.0000001", 6, 6n)).toThrow();
|
expect(() => transferAmountUnits("0.0000001", 6, 6n)).toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("encodes zeros past the token's scale as the amount typed", () => {
|
||||||
|
// The Send screen accepts "1.0000000" for a 6-place token, so the
|
||||||
|
// transfer must move exactly 1 of it.
|
||||||
|
expect(transferAmountUnits("1.0000000", 6, 6n)).toBe(1000000n);
|
||||||
|
});
|
||||||
|
|
||||||
test("every refusal is a full sentence", () => {
|
test("every refusal is a full sentence", () => {
|
||||||
const messages = [];
|
const messages = [];
|
||||||
for (const args of [
|
for (const args of [
|
||||||
|
|||||||
@@ -54,13 +54,20 @@ describe("isValidAmount", () => {
|
|||||||
expect(isValidAmount(undefined)).toBe(false);
|
expect(isValidAmount(undefined)).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("refuses more decimal places than the token has", () => {
|
test("refuses a digit other than 0 past the token's places", () => {
|
||||||
expect(isValidAmount("0.000001", 6)).toBe(true);
|
expect(isValidAmount("0.000001", 6)).toBe(true);
|
||||||
expect(isValidAmount("0.0000001", 6)).toBe(false);
|
expect(isValidAmount("0.0000001", 6)).toBe(false);
|
||||||
expect(isValidAmount("5", 0)).toBe(true);
|
expect(isValidAmount("5", 0)).toBe(true);
|
||||||
expect(isValidAmount("0.5", 0)).toBe(false);
|
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", () => {
|
test("holds ETH, a token of unknown places, and any token to 18 places", () => {
|
||||||
const nineteen = "0.0000000000000000001";
|
const nineteen = "0.0000000000000000001";
|
||||||
expect(isValidAmount(nineteen)).toBe(false);
|
expect(isValidAmount(nineteen)).toBe(false);
|
||||||
|
|||||||
Reference in New Issue
Block a user