feat(clear_signing): show chain name or number in all flows
What changed, and why it matters
This commit is a user-interface improvement for Trezor hardware wallets when approving Ethereum transactions. It makes sure the wallet always shows which blockchain network (for example Ethereum mainnet, Polygon, or an unknown chain ID) is being used during 'clear signing' flows. There is no security vulnerability here; it is a defensive feature that helps users avoid mistakes.
No security action required. Treat as a normal feature/UI improvement during review and testing.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change adds a chain_info parameter through the Ethereum clear-signing confirmation pipeline and passes it to the four device UI layout implementations (bolt, caesar, delizia, eckhart). In clear_signing.py it derives the chain display value from defs.network.name when the network is known, otherwise falls back to the raw chain_id. The UI layouts now include this value in the contract-address info menu. The rename of recipient_str to contract_name is cosmetic and clarifies that the value shown is the dApp/provider name, not a transaction recipient.
Changed components
core/src/apps/ethereum/clear_signing.pycore/src/apps/ethereum/layout.pycore/src/trezor/ui/layouts/bolt/__init__.pycore/src/trezor/ui/layouts/caesar/__init__.pycore/src/trezor/ui/layouts/delizia/__init__.pycore/src/trezor/ui/layouts/eckhart/__init__.pyInspect captured patch +52 / −23
### core/src/apps/ethereum/clear_signing.py
@@ -1559,6 +1559,7 @@ async def _handle_generic_ui(
from . import tokens
from .helpers import bytes_from_address
from .layout import require_confirm_clear_signing
+ from .networks import UNKNOWN_NETWORK
from .sc_constants import lookup_known_address
# Surface the native ETH value in the summary when non-zero - unless one of
@@ -1589,20 +1590,28 @@ async def _handle_generic_ui(
)
properties_to_confirm.append(token_address_property)
- recipient_str = (
+ contract_name = (
(lookup_known_address(msg.chain_id, bytes_from_address(msg.to)) or msg.to)
if display_format.provider_name is None
else display_format.provider_name
)
account, account_path = get_account_and_path(msg.address_n)
+ # Name the chain when we recognize it, otherwise fall back to the bare chain ID.
+ chain_info: StrPropertyType = (
+ (TR.ethereum__approve_chain_id, str(msg.chain_id), None)
+ if defs.network is UNKNOWN_NETWORK
+ else (TR.words__chain, defs.network.name, None)
+ )
+
await require_confirm_clear_signing(
- recipient_str=recipient_str,
+ contract_name=contract_name,
intent=display_format.intent,
properties=properties_to_confirm,
maximum_fee=maximum_fee,
contract_address=address_from_bytes(address_bytes, defs.network),
+ chain_info=chain_info,
amount=None if value_shown_as_field else amount,
account=account,
account_path=account_path,
### core/src/apps/ethereum/layout.py
@@ -86,26 +86,28 @@ async def require_confirm_approve(
async def require_confirm_clear_signing(
- recipient_str: str,
+ contract_name: str,
intent: str,
properties: list[StrPropertyType],
maximum_fee: str,
contract_address: str,
+ chain_info: StrPropertyType,
amount: str | None = None,
account: str | None = None,
account_path: str | None = None,
) -> None:
from trezor.ui.layouts import confirm_ethereum_clear_signing
await confirm_ethereum_clear_signing(
- recipient_str,
- intent,
- properties,
- maximum_fee,
- contract_address,
- amount,
- account,
- account_path,
+ contract_name=contract_name,
+ intent=intent,
+ properties=properties,
+ maximum_fee=maximum_fee,
+ contract_address=contract_address,
+ chain_info=chain_info,
+ amount=amount,
+ account=account,
+ account_path=account_path,
)
### core/src/trezor/ui/layouts/bolt/__init__.py
@@ -1273,11 +1273,12 @@ async def confirm_ethereum_approve(
)
async def confirm_ethereum_clear_signing(
- recipient_str: str,
+ contract_name: str,
intent: str,
properties: list[StrPropertyType],
maximum_fee: str,
contract_address: str,
+ chain_info: StrPropertyType,
amount: str | None = None,
account: str | None = None,
account_path: str | None = None,
@@ -1292,6 +1293,7 @@ async def confirm_ethereum_clear_signing(
info_items.append((TR.words__account, account, None))
info_items.append((TR.address_details__derivation_path, account_path, None))
info_items.append((TR.ethereum__contract_address, contract_address, None))
+ info_items.append(chain_info)
info_items = with_colon(info_items)
def _info_ctx() -> trezorui_api.LayoutContext[ui.UiResult]:
@@ -1300,7 +1302,7 @@ def _info_ctx() -> trezorui_api.LayoutContext[ui.UiResult]:
items=info_items,
)
- await confirm_action(f"{br_name}/provider", TR.words__provider, recipient_str)
+ await confirm_action(f"{br_name}/provider", TR.words__provider, contract_name)
await confirm_action(f"{br_name}/intent", TR.words__intent, intent)
if properties:
props_ctx = trezorui_api.confirm_properties(
### core/src/trezor/ui/layouts/caesar/__init__.py
@@ -1249,11 +1249,12 @@ async def confirm_ethereum_approve(
)
async def confirm_ethereum_clear_signing(
- recipient_str: str,
+ contract_name: str,
intent: str,
properties: list[StrPropertyType],
maximum_fee: str,
contract_address: str,
+ chain_info: StrPropertyType,
amount: str | None = None,
account: str | None = None,
account_path: str | None = None,
@@ -1272,6 +1273,11 @@ async def confirm_ethereum_clear_signing(
(TR.address_details__derivation_path, account_path, None)
)
+ contract_properties: list[StrPropertyType] = [
+ (TR.words__address, contract_address, None),
+ chain_info,
+ ]
+
def _menu() -> Menu[None]:
menu_items: list[MenuLeaf[None]] = []
if account_properties:
@@ -1282,11 +1288,13 @@ def _menu() -> Menu[None]:
)
)
menu_items.append(
- create_info_menu_leaf(TR.ethereum__contract_address, contract_address)
+ create_info_menu_leaf(
+ TR.ethereum__contract_address, with_colon(contract_properties)
+ )
)
return Menu(menu_items)
- await confirm_action(f"{br_name}/provider", TR.words__provider, recipient_str)
+ await confirm_action(f"{br_name}/provider", TR.words__provider, contract_name)
await confirm_action(f"{br_name}/intent", TR.words__intent, intent)
if properties:
with trezorui_api.confirm_properties(
### core/src/trezor/ui/layouts/delizia/__init__.py
@@ -1248,11 +1248,12 @@ async def confirm_ethereum_approve(
)
async def confirm_ethereum_clear_signing(
- recipient_str: str,
+ contract_name: str,
intent: str,
properties: list[StrPropertyType],
maximum_fee: str,
contract_address: str,
+ chain_info: StrPropertyType,
amount: str | None = None,
account: str | None = None,
account_path: str | None = None,
@@ -1269,7 +1270,8 @@ async def confirm_ethereum_clear_signing(
(TR.address_details__derivation_path, account_path, None)
)
contract_properties: list[StrPropertyType] = [
- (TR.ethereum__contract_address, contract_address, None)
+ (TR.words__address, contract_address, None),
+ chain_info,
]
def _menu() -> Menu[None]:
@@ -1285,14 +1287,14 @@ def _menu() -> Menu[None]:
menu_items.append(
create_info_menu_leaf(
TR.ethereum__contract_address,
- contract_address,
+ contract_properties,
TR.ethereum__contract_address,
)
)
return Menu(menu_items)
for screen, title, value in (
- ("provider", TR.words__provider, recipient_str),
+ ("provider", TR.words__provider, contract_name),
("intent", TR.words__intent, intent),
):
with trezorui_api.confirm_action(
### core/src/trezor/ui/layouts/eckhart/__init__.py
@@ -1301,11 +1301,12 @@ async def confirm_ethereum_approve(
)
async def confirm_ethereum_clear_signing(
- recipient_str: str,
+ contract_name: str,
intent: str,
properties: list[StrPropertyType],
maximum_fee: str,
contract_address: str,
+ chain_info: StrPropertyType,
amount: str | None = None,
account: str | None = None,
account_path: str | None = None,
@@ -1314,6 +1315,11 @@ async def confirm_ethereum_clear_signing(
br_name = "ethereum/clear_signing"
+ contract_properties: list[StrPropertyType] = [
+ (TR.words__address, contract_address, None),
+ chain_info,
+ ]
+
def _menu() -> Menu[None]:
menu_items: list[MenuLeaf[None]] = []
account_properties = _get_account_info_items(account, account_path)
@@ -1329,15 +1335,15 @@ def _menu() -> Menu[None]:
menu_items.append(
create_info_menu_leaf(
TR.ethereum__contract_address,
- contract_address,
+ contract_properties,
title=TR.ethereum__contract_address,
)
)
menu_items.append(cancel_leaf(TR.buttons__cancel))
return Menu(menu_items)
for screen, title, value in (
- ("provider", TR.words__provider, recipient_str),
+ ("provider", TR.words__provider, contract_name),
("intent", TR.words__intent, intent),
):
with trezorui_api.confirm_action(Why this scored 15/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.