fix: sign the ERC-20 amount the confirmation screen displayed (closes #305)
All checks were successful
check / check (push) Successful in 27s
e2e / e2e-chrome (push) Successful in 1m10s
e2e / e2e-firefox (push) Successful in 22s

The send screen was built from the indexer's decimals while the transfer was
encoded from the contract's decimals() read at signing time, with nothing
comparing them. A token whose scales disagree moved 10^12 times the approved
amount.

The displayed scale is now carried on pendingTx from the same tokenBalances
entry the amount, balance and symbol were rendered from, and both encode sites
use it. transferAmount.js refuses rather than falling back when the two scales
disagree or either is unusable.

Adds the first end-to-end coverage of the popup's own Send -> ConfirmTx ->
Sign & Send path; #btn-confirm-send had never been clicked by any test.
This commit was merged in pull request #314.
This commit is contained in:
2026-08-20 12:31:28 +02:00
parent ff3387d8cf
commit 2f80a9bdb4
8 changed files with 570 additions and 16 deletions

View File

@@ -220,6 +220,11 @@ function init(_ctx) {
let tokenSymbol = null;
let tokenBalance = null;
// The scale the amount and the balance below are rendered at, carried
// forward so the transfer is encoded with the number the user read
// rather than with whatever the contract answers at signing time. See
// src/shared/transferAmount.js.
let tokenDecimals = null;
if (token !== "ETH") {
const tb = (addr.tokenBalances || []).find(
(t) => t.address.toLowerCase() === token.toLowerCase(),
@@ -230,6 +235,7 @@ function init(_ctx) {
state.trackedTokens,
);
tokenBalance = tb ? tb.balance || "0" : "0";
tokenDecimals = tb ? tb.decimals : null;
}
ctx.showConfirmTx({
@@ -241,6 +247,7 @@ function init(_ctx) {
balance: addr.balance,
tokenSymbol: tokenSymbol,
tokenBalance: tokenBalance,
tokenDecimals: tokenDecimals,
});
});