diff --git a/README.md b/README.md index 1563171..e678f36 100644 --- a/README.md +++ b/README.md @@ -882,9 +882,18 @@ On those screens, when the truncated string would contain no digit from 1 to 9 and the value does, the amount is extended to its first significant digit instead: `0.000000000000000001 DAI`, not `0.0000 DAI`. The test is on the whole truncated string, integer part included, so `1.00005` still shows as `1.0000` — -the exception only fires where the entire displayed figure would read as zero. A -genuine zero still renders `0.0000`, and truncation stays truncation: `0.99999` -shows as `0.9999`, never rounded up. +the exception only fires where the entire displayed figure would read as zero. +Truncation stays truncation: `0.99999` shows as `0.9999`, never rounded up. A +genuine zero reaching this rule renders `0.0000`. The swap screen states a zero +in words before it gets here in only two places. Its `Min. received` line reads +`None (no minimum guaranteed)` for any zero minimum. Its `Amount` line reads +`All available (V4 open delta)` for a V4 exact-in `amountIn` of zero, which V4 +treats as the whole open credit rather than a quantity — but only when that V4 +step is the one that sets the `Amount` line. A Permit2 permit sets it whenever +one is among the steps, so a swap carrying a permit shows the permit's amount +there and never the open-delta wording. Every other zero amount with a known +scale renders `0.0000`, the swap's `Amount` line included; the list of +amount-slot strings below says where. The rule and its exception live in `src/shared/amountDisplay.js` as `truncateAmount()` and `truncateAmountNeverZero()`. Everything the approval and @@ -936,6 +945,49 @@ and compare against. Reading the stored field directly instead answers `null` for a bundled or tracked token the explorer merely omitted, which is not a refusal the wallet has any reason to make. +**Every string an amount slot can show:** taken together, the exceptions above +mean an amount line on the dApp approval screen (and the wait/success/error +screens that carry a figure forward) shows one of a fixed set of strings, not +always a number: + +- A formatted quantity, e.g. `17.1900 USDT`: the token's scale is known. A + figure at or above the floor is truncated to four decimals, one below it is + extended to its first significant digit, and a genuine zero renders `0.0000`, + e.g. `0.0000 USDT`. That zero reaches the ERC-20 `approve`/`transfer` line for + an amount of zero, and the swap's `Amount` line when the step that sets it + states zero: a Permit2 permit, a V2 or V3 exact-in `amountIn`, or a `WRAP_ETH` + (`0.0000 ETH`). This is `truncateAmountNeverZero()` + (`src/shared/amountDisplay.js`). +- `Unlimited`: named rather than formatted, since it needs no scale to describe. + On the ERC-20 line it is an `approve` of the `uint256` maximum, an unbounded + allowance (`src/popup/views/approval.js`); `transfer` has no such case. On a + swap's `Amount` line it is any input amount at or above the `uint160` maximum, + whichever step set the line (`src/shared/uniswap.js`): a Permit2 permit at + that maximum, which is an unbounded permit, or a V2 or V3 exact-in `amountIn` + or `WRAP_ETH` amount that large. That includes the router's whole-balance + value (`2^255`), which tells the router to use all it holds of the token — a + quantity decided at execution, not an allowance. +- `All available (V4 open delta)`: a V4 exact-in swap whose `amountIn` is zero. + V4 reads that zero as "use the whole open delta", not as a literal zero, so + the calldata states no quantity at all. Swap `Amount` line only, and only when + that V4 step is the one that sets the line. A Permit2 permit sets it instead + whenever one is among the steps, and so does any earlier swap or `WRAP_ETH` + step; the line then shows what that step stated (`src/shared/uniswap.js`). +- `None (no minimum guaranteed)`: a zero minimum — the swap guarantees nothing + back. It is a literal zero slippage floor on a V2/V3/V4 swap, and it also + reaches a `BALANCE_CHECK_ERC20` step: a zero `minBalance`, which once rendered + `0.0000` beside the token symbol, now reads this. Swap `Min. received` line + (`src/shared/uniswap.js`). +- ` base units (decimals unknown)`: the token's scale could not be + resolved, so the base-unit integer is shown with that caveat rather than + formatted (see Unknown token scale above). Reaches both the ERC-20 amount line + and the swap's `Amount` and `Min. received` (`unknownDecimalsAmount()` in + `src/shared/approvalAmount.js`). +- `Unknown (not named in the calldata)`: not an amount but the currency itself — + the `Token In` or `Token Out` line when nothing in the calldata established + which token, shown beside the amount and, like the strings above, a sentence + rather than a value (`src/shared/uniswap.js`). + #### Partial USD totals Prices are fetched for the top 25 tokens only, so an address can hold assets the diff --git a/TODO.md b/TODO.md index 9832711..7dcf9da 100644 --- a/TODO.md +++ b/TODO.md @@ -154,6 +154,22 @@ but the review is broader than any of them. standalone storage entry, never part of the versioned `autistmask` profile, so the state schema is untouched and no existing profile is affected. +- 2026-09-21: `README.md` now documents the approval screen's amount-slot + vocabulary and no longer contradicts itself + ([#369](https://git.eeqj.de/sneak/AutistMask/issues/369)). The stale claim + that a genuine zero always renders `0.0000` is corrected: a zero with a known + scale does, except where the swap screen states it in words first — + `Min. received` always, and the `Amount` line only when a V4 exact-in of zero + is the step that sets it. A Permit2 permit sets that line whenever one is + present, so a zero permit, a zero V2/V3 exact-in `amountIn` or a zero + `WRAP_ETH` still reads `0.0000`. The amount-display section now names every + string a slot can show and when — a formatted quantity (a known-scale zero + included), `Unlimited` (on a swap also the router's whole-balance value), + `All available (V4 open delta)`, `None (no minimum guaranteed)`, base units + with decimals unknown, and `Unknown (not named in the calldata)` — and records + that a zero `minBalance` on a `BALANCE_CHECK_ERC20` step now reads + `None (no minimum guaranteed)` where it once read `0.0000`. Docs only. + - 2026-08-30: An address no longer wraps, or is shortened to fit, in any of the common views ([#380](https://git.eeqj.de/sneak/AutistMask/issues/380)). The wallet list was the reported case: the address shared one row with the