fix(clear_signing): double display of amount.
What changed, and why it matters
This commit fixes a user-interface bug in Trezor's Ethereum 'clear signing' flow where the transaction's native ETH amount could be shown twice on the device screen. The old code tried to avoid duplication by checking whether an 'AmountFormatter' field was present, but that check missed cases where the same amount was rendered by other field types. The new code compares the actual rendered strings and suppresses the summary amount only when it exactly matches a field already displayed. There is no security vulnerability here; it is purely a display-quality fix.
No security action required. Treat as a normal UI/UX bug fix. If reviewing for release notes, note only the improved display deduplication and corrected test fixture name.
Security signals we found
No cryptographic, authorization, memory-safety, or input-validation changes
Change is limited to on-screen display deduplication logic
No changelog entry requested by the vendor ('[no changelog]')
No advisory, CVE, or security disclosure referenced
Evidence from the diff
In core/src/apps/ethereum/clear_signing.py, the handle_generic_ui coroutine previously computed amount (the native ETH value) and skipped adding it to the confirmation summary if any field_definition used AmountFormatter on ContainerPath.Value. That heuristic was insufficient because the same numeric value can be rendered through other formatters or paths, causing duplicate lines. The patch removes the formatter-type check, always computes amount, then iterates the parsed fields and sets value_shown_as_field = True if any formatted string equals amount. The summary amount passed to require_confirm_clear_signing is then None when a matching field was already shown. A test fixture name typo (double ‘kiln’) is also corrected.
Changed components
core/src/apps/ethereum/clear_signing.pycommon/tests/fixtures/ethereum/sign_tx_external_definitions.jsonInspect captured patch +14 / −17
diff --git a/common/tests/fixtures/ethereum/sign_tx_external_definitions.json b/common/tests/fixtures/ethereum/sign_tx_external_definitions.json
index 3cca301f..8c4e11af 100644
--- a/common/tests/fixtures/ethereum/sign_tx_external_definitions.json
+++ b/common/tests/fixtures/ethereum/sign_tx_external_definitions.json
@@ -845,7 +845,7 @@
}
},
{
- "name": "kiln_kiln_fee_splitter_factory_createSplitterAndCall",
+ "name": "kiln_fee_splitter_factory_createSplitterAndCall",
"parameters": {
"comment": "supported | https://etherscan.io/tx/0xdce02b9fb2809dd9737d3458326038dcd244970c7b69a4960a2d3d6ef65467ea",
"data": "608c54d4000000000000000000000000939ff2302c6629b6e8ed93305dddd9c4a9b2eed5be2dd7b1a324e89c4f09d03ab3d610527a613268638e96f76f6156f6bcfb51de000000000000000000000000576834cb068e677db4aff6ca245c7bde16c3867e00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000204fe37d82900000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000001bc16d674ec8000000000000000000000000000000000000000000000000000000000000000000030970d938f09801072ed1913f9a3005eb2562c18afe3523fea9de1a12ba359486c081d9e072cc840b2d4160fee3b5ff486000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020020000000000000000000000a2e2b8ea90921d3a6c5dd2ae0f497465f4a7b5c10000000000000000000000000000000000000000000000000000000000000060b60323d6baf62ca439fa5da76f509499f99dfe8b9b65c5fdf215f7287d2844120e31455dc472d19569605d349093ecda114153289c7770d3dc0690006911357a5aac96885600c04086e56c6ac58dcd819acff1a0477bd6668bccd2821de1032000000000000000000000000000000000000000000000000000000000000000013d790ab9e5b66eef87384c8ca0a3667abb351b3bcf21f19af14e754d7f98c28f00000000000000000000000000000000000000000000000000000000",
diff --git a/core/src/apps/ethereum/clear_signing.py b/core/src/apps/ethereum/clear_signing.py
index a39c0580..31ad7258 100644
--- a/core/src/apps/ethereum/clear_signing.py
+++ b/core/src/apps/ethereum/clear_signing.py
@@ -1485,30 +1485,23 @@ async def _handle_generic_ui(
from .layout import require_confirm_clear_signing
from .sc_constants import lookup_known_address
- # Surface the native ETH value in the summary when non-zero - unless the
- # display format already renders it as an `AmountFormatter` field (e.g. a
- # swap's "Amount to Send"). That field shows the same canonical string the
- # summary would, so repeating it there is pure duplication. A `@.value`
- # field formatted any other way still gets its own summary line.
+ # Surface the native ETH value in the summary when non-zero - unless one of
+ # the display format's own fields already renders it (e.g. a swap's "Amount
+ # to Send"), in which case repeating it in the summary is pure duplication.
+
value = int.from_bytes(msg.value, "big")
- value_shown_as_amount_field = any(
- fd.path == ContainerPath.Value
- and isinstance(fd.get_formatter(), AmountFormatter)
- for fd in display_format.field_definitions
- )
- amount = (
- format_ethereum_amount(value, None, defs.network)
- if value and not value_shown_as_amount_field
- else None
- )
+ amount = format_ethereum_amount(value, None, defs.network) if value else None
_, fields = await display_format.parse_calldata(calldata, msg, defs)
properties_to_confirm = []
+ value_shown_as_field = False
for (label, formatted, is_mono), actual_token, actual_token_address in fields:
if isinstance(formatted, AboveThreshold):
formatted = formatted.message
+ if amount is not None and formatted == amount:
+ value_shown_as_field = True
properties_to_confirm.append((label, formatted, is_mono))
if actual_token is tokens.UNKNOWN_TOKEN:
assert actual_token_address is not None
@@ -1527,5 +1520,9 @@ async def _handle_generic_ui(
)
await require_confirm_clear_signing(
- recipient_str, display_format.intent, properties_to_confirm, maximum_fee, amount
+ recipient_str,
+ display_format.intent,
+ properties_to_confirm,
+ maximum_fee,
+ None if value_shown_as_field else amount,
)
Why this scored 19/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.