fix: never render a nonzero approval amount as zero (closes #322)
Amounts are truncated to four decimal places per README.md's Display Consistency rule. With the token's true scale resolved, an amount below 0.0001 still printed as 0.0000 — 1 base unit of an 18-decimal token, 500 base units of an 8-decimal one. On the dApp approval screen, and on the wait/success/error screens that carry the same string forward as txInfo.amount, a real transfer, allowance or swap was therefore stated as nothing. A swap's "Min. received" is the sharper case: a slippage floor shown as 0.0000 states that the swap may return nothing. That truncation existed in three separate copies — src/popup/views/approval.js (the ERC-20 amount, the ETH value, the max fee), src/shared/uniswap.js (the swap's Amount and Min. received lines, on that same screen) and src/shared/transactions.js (history and balance lists). They now share src/shared/amountDisplay.js, which holds the rule and its one exception side by side: truncateAmount() truncates, truncateAmountNeverZero() truncates with the nonzero floor. approval.js and uniswap.js take the floored function, so every amount those screens display or hand to the confirmation screens obeys the invariant. When the truncated string would carry no digit from 1 to 9 and the value does, the amount is extended to its first significant digit: 0.000000000000000001 DAI, not 0.0000 DAI. It stays in token units, the same unit as the symbol beside it; the base-unit rendering already on this screen means "the scale is unknown", and reusing it for a known scale would blur the two. A genuine zero still renders 0.0000, an amount at or above the floor is untouched, and truncation stays truncation — 0.99999 shows as 0.9999, never rounded up. transactions.js takes the unfloored function, keeping its current behaviour exactly: balance lists and history are out of scope by the issue's definition of done, and the transaction detail view already shows exact precision there. The code path is shared; the policy is not. tests/approvalDisplayFloor.test.js drives decodeCalldata() and uniswap.decode() and asserts both the displayed line and the rawValue the confirmation screens carry. Against this tree with src/shared/uniswap.js reverted to its previous formatAmount(), its two new swap cases fail: a 50-base-unit USDT input gives "0.0000 USDT" where "0.00005 USDT" is expected, and a 1-wei amountOutMin gives "0.0000 WETH" where "0.000000000000000001 WETH" is expected. A case pinning the list rule as unfloored is included so the shared module cannot drift into one policy. make check green: 42 suites, 848 tests; verify-build 39 cases; check-censored 153 files; eslint and prettier clean in the pinned container.
This commit is contained in:
16
TODO.md
16
TODO.md
@@ -68,6 +68,22 @@ but the review is broader than any of them.
|
||||
unchanged — the README said "nothing under `dist/` that the build did not
|
||||
write", which was broader than that. Documentation only; no executable line
|
||||
changed.
|
||||
- 2026-08-23: An amount below the 4-decimal display floor no longer reads as
|
||||
zero on the approval screens
|
||||
([#322](https://git.eeqj.de/sneak/AutistMask/issues/322)). With the token's
|
||||
true scale resolved, the 4-decimal truncation still printed a small amount as
|
||||
`0.0000` — 1 base unit of an 18-decimal token, 500 of an 8-decimal one — so a
|
||||
real transfer, allowance or swap was stated as nothing on the one screen whose
|
||||
job is to say what is being authorized, and a swap's `Min. received` claimed
|
||||
the user might receive nothing. Three copies of that truncation existed; they
|
||||
now share `src/shared/amountDisplay.js`. Everything the approval and
|
||||
confirmation screens render (`src/popup/views/approval.js`,
|
||||
`src/shared/uniswap.js`) extends to the first significant digit when the
|
||||
truncated figure would otherwise read as zero, keeping the amount in token
|
||||
units rather than switching to base units mid-line. The history and balance
|
||||
lists (`src/shared/transactions.js`) keep the unfloored rule, which is out of
|
||||
scope by the issue's definition of done. `README.md`'s Display Consistency
|
||||
section records the exception.
|
||||
- 2026-08-20: A second extension page can no longer silently delete a wallet
|
||||
([#304](https://git.eeqj.de/sneak/AutistMask/issues/304)). `saveState()` wrote
|
||||
the entire state blob, and every extension page — the toolbar popup, a dApp
|
||||
|
||||
Reference in New Issue
Block a user