feat(clear_signing): update defs with providers
What changed, and why it matters
This commit updates the Trezor Ethereum 'clear signing' feature so that when a known DeFi contract (like 1inch or Uniswap) is recognized, the device screen shows the provider's human-readable name (e.g., '1inch Aggregation Router V6') instead of just a raw address or a generic vault label. It also updates some URL comments to point to the community ERC-7730 registry rather than Ledger's copy. There is no obvious security vulnerability in the change; it is a user-experience improvement for transaction clarity.
No security action required. Treat as a normal feature/UX commit. If reviewing for release, verify that the new `provider_name` strings are accurate and that the `DisplayFormat` constructor change does not break other callers.
Security signals we found
UI label change only: no transaction validation logic altered
No new external inputs parsed; provider_name is hardcoded in definitions
No memory-unsafe operations or buffer size changes
No privilege escalation, key handling, or signing flow changes
URL comment updates do not affect runtime behavior
Evidence from the diff
The patch adds a new optional provider_name field to the DisplayFormat data class used in Ethereum clear signing. In clear_signing.py, the _handle_approve helper now prefers display_format.provider_name over lookup_known_address() when a provider name is set. The definitions file populates provider_name for 1inch and Uniswap display formats, sets it to None for generic ERC-4626/WETH formats, and updates registry URL comments from LedgerHQ/clear-signing-erc7730-registry to ethereum/clear-signing-erc7730-registry. Tests are updated to include the new field. No cryptographic, parsing, or access-control changes are present.
Changed components
core/src/apps/ethereum/clear_signing.pycore/src/apps/ethereum/clear_signing_definitions.pycore/src/apps/ethereum/yielding.pycore/tests/test_apps.ethereum.clear_signing.pyInspect captured patch +42 / −10
diff --git a/core/src/apps/ethereum/clear_signing.py b/core/src/apps/ethereum/clear_signing.py
index cd1e1541..ab30d18d 100644
--- a/core/src/apps/ethereum/clear_signing.py
+++ b/core/src/apps/ethereum/clear_signing.py
@@ -1130,7 +1130,14 @@ async def _handle_approve(
assert isinstance(arg1_raw_value, int)
- recipient_str = lookup_known_address(msg.chain_id, arg0_raw_value)
+ recipient_str = (
+ lookup_known_address(msg.chain_id, arg0_raw_value)
+ if display_format.provider_name is None
+ else display_format.provider_name
+ )
+
+ # Ideally our vault name and definition should also be added in the ERC-7730 registry
+ # Until that is verified, we'll keep our vault information hardcoded.
if recipient_str is None:
vault = lookup_vault(defs.network, arg0_raw_value)
if vault is not UNKNOWN_VAULT:
diff --git a/core/src/apps/ethereum/clear_signing_definitions.py b/core/src/apps/ethereum/clear_signing_definitions.py
index 9b69d308..6cbcbfc1 100644
--- a/core/src/apps/ethereum/clear_signing_definitions.py
+++ b/core/src/apps/ethereum/clear_signing_definitions.py
@@ -11,7 +11,7 @@ from .clear_signing import (
parse_uint256,
)
-# https://github.com/LedgerHQ/clear-signing-erc7730-registry/blob/master/ercs/calldata-erc20-tokens.json#L27
+# https://github.com/ethereum/clear-signing-erc7730-registry/blob/master/ercs/calldata-erc20-tokens.json#L27
APPROVE_DISPLAY_FORMAT = DisplayFormat(
binding_context=None,
@@ -75,7 +75,7 @@ def all_display_formats() -> Generator[DisplayFormat, None, None]:
yield APPROVE_DISPLAY_FORMAT
yield TRANSFER_DISPLAY_FORMAT
- # https://github.com/LedgerHQ/clear-signing-erc7730-registry/blob/master/registry/1inch/calldata-AggregationRouterV6.json#L9
+ # https://github.com/ethereum/clear-signing-erc7730-registry/blob/master/registry/1inch/calldata-AggregationRouterV6.json#L9
ONEINCH_ADDRESS = b"\x11\x11\x11\x12\x54\x21\xca\x6d\xc4\x52\xd2\x89\x31\x42\x80\xa0\xf8\x84\x2a\x65"
ONEINCH_CHAINS = [
1,
@@ -119,6 +119,7 @@ def all_display_formats() -> Generator[DisplayFormat, None, None]:
binding_context=ONEINCH_CONTEXT,
func_sig=_FUNC_SIG,
intent="Swap",
+ provider_name="1inch Aggregation Router V6",
parameter_definitions=[
Atomic(parse_address), # executor
Tuple(
@@ -165,6 +166,7 @@ def all_display_formats() -> Generator[DisplayFormat, None, None]:
binding_context=ONEINCH_CONTEXT,
func_sig=_FUNC_SIG,
intent="Swap",
+ provider_name="1inch Aggregation Router V6",
parameter_definitions=[
Atomic(parse_bytes32), # token
Atomic(parse_uint256), # amount
@@ -200,6 +202,7 @@ def all_display_formats() -> Generator[DisplayFormat, None, None]:
binding_context=ONEINCH_CONTEXT,
func_sig=_FUNC_SIG,
intent="Swap",
+ provider_name="1inch Aggregation Router V6",
parameter_definitions=[
Atomic(parse_bytes32), # to
Atomic(parse_bytes32), # token
@@ -236,6 +239,7 @@ def all_display_formats() -> Generator[DisplayFormat, None, None]:
binding_context=ONEINCH_CONTEXT,
func_sig=_FUNC_SIG,
intent="Swap",
+ provider_name="1inch Aggregation Router V6",
parameter_definitions=[
Atomic(parse_bytes32), # token
Atomic(parse_uint256), # amount
@@ -272,6 +276,7 @@ def all_display_formats() -> Generator[DisplayFormat, None, None]:
binding_context=ONEINCH_CONTEXT,
func_sig=_FUNC_SIG,
intent="Swap",
+ provider_name="1inch Aggregation Router V6",
parameter_definitions=[
Atomic(parse_bytes32), # token
Atomic(parse_uint256), # amount
@@ -309,6 +314,7 @@ def all_display_formats() -> Generator[DisplayFormat, None, None]:
binding_context=ONEINCH_CONTEXT,
func_sig=_FUNC_SIG,
intent="Swap",
+ provider_name="1inch Aggregation Router V6",
parameter_definitions=[
Atomic(parse_bytes32), # to
Atomic(parse_bytes32), # token
@@ -346,6 +352,7 @@ def all_display_formats() -> Generator[DisplayFormat, None, None]:
binding_context=ONEINCH_CONTEXT,
func_sig=_FUNC_SIG,
intent="Swap",
+ provider_name="1inch Aggregation Router V6",
parameter_definitions=[
Atomic(parse_bytes32), # to
Atomic(parse_bytes32), # token
@@ -384,6 +391,7 @@ def all_display_formats() -> Generator[DisplayFormat, None, None]:
binding_context=ONEINCH_CONTEXT,
func_sig=_FUNC_SIG,
intent="Swap",
+ provider_name="1inch Aggregation Router V6",
parameter_definitions=[
Atomic(parse_uint256), # minReturn
Atomic(parse_bytes32), # dex
@@ -414,6 +422,7 @@ def all_display_formats() -> Generator[DisplayFormat, None, None]:
binding_context=ONEINCH_CONTEXT,
func_sig=_FUNC_SIG,
intent="Swap",
+ provider_name="1inch Aggregation Router V6",
parameter_definitions=[
Atomic(parse_uint256), # minReturn
Atomic(parse_uint256), # dex
@@ -445,6 +454,7 @@ def all_display_formats() -> Generator[DisplayFormat, None, None]:
binding_context=ONEINCH_CONTEXT,
func_sig=_FUNC_SIG,
intent="Swap",
+ provider_name="1inch Aggregation Router V6",
parameter_definitions=[
Atomic(parse_uint256), # minReturn
Atomic(parse_uint256), # dex
@@ -477,6 +487,7 @@ def all_display_formats() -> Generator[DisplayFormat, None, None]:
binding_context=ONEINCH_CONTEXT,
func_sig=_FUNC_SIG,
intent="Swap",
+ provider_name="1inch Aggregation Router V6",
parameter_definitions=[
Atomic(parse_bytes32), # to
Atomic(parse_uint256), # minReturn
@@ -508,6 +519,7 @@ def all_display_formats() -> Generator[DisplayFormat, None, None]:
binding_context=ONEINCH_CONTEXT,
func_sig=_FUNC_SIG,
intent="Swap",
+ provider_name="1inch Aggregation Router V6",
parameter_definitions=[
Atomic(parse_bytes32), # to
Atomic(parse_uint256), # minReturn
@@ -540,6 +552,7 @@ def all_display_formats() -> Generator[DisplayFormat, None, None]:
binding_context=ONEINCH_CONTEXT,
func_sig=_FUNC_SIG,
intent="Swap",
+ provider_name="1inch Aggregation Router V6",
parameter_definitions=[
Atomic(parse_bytes32), # to
Atomic(parse_uint256), # minReturn
@@ -567,11 +580,11 @@ def all_display_formats() -> Generator[DisplayFormat, None, None]:
)
)
- # https://github.com/LedgerHQ/clear-signing-erc7730-registry/blob/master/registry/uniswap/calldata-UniswapV3Router02.json#L6
+ # https://github.com/ethereum/clear-signing-erc7730-registry/blob/master/registry/uniswap/calldata-UniswapV3Router02.json#L6
UNISWAP_V3_ROUTER_ADDRESS = b"\x68\xb3\x46\x58\x33\xfb\x72\xa7\x0e\xcd\xf4\x85\xe0\xe4\xc7\xbd\x86\x65\xfc\x45"
UNISWAP_V3_ROUTER_CHAINS = [1]
- # https://github.com/LedgerHQ/clear-signing-erc7730-registry/blob/master/registry/uniswap/calldata-UniswapV3Router02.json
+ # https://github.com/ethereum/clear-signing-erc7730-registry/blob/master/registry/uniswap/calldata-UniswapV3Router02.json
UNISWAP_CONTEXT = BindingContext(
[(chain, UNISWAP_V3_ROUTER_ADDRESS) for chain in UNISWAP_V3_ROUTER_CHAINS],
@@ -583,6 +596,7 @@ def all_display_formats() -> Generator[DisplayFormat, None, None]:
binding_context=UNISWAP_CONTEXT,
func_sig=_FUNC_SIG,
intent="Swap",
+ provider_name="Uniswap V3 Router",
parameter_definitions=[
Tuple(
(
@@ -624,6 +638,7 @@ def all_display_formats() -> Generator[DisplayFormat, None, None]:
binding_context=UNISWAP_CONTEXT,
func_sig=_FUNC_SIG,
intent="Swap",
+ provider_name="Uniswap V3 Router",
parameter_definitions=[
Tuple(
(
@@ -673,6 +688,7 @@ def all_display_formats() -> Generator[DisplayFormat, None, None]:
binding_context=UNISWAP_CONTEXT,
func_sig=_FUNC_SIG,
intent="Swap",
+ provider_name="Uniswap V3 Router",
parameter_definitions=[
Tuple(
(
@@ -714,6 +730,7 @@ def all_display_formats() -> Generator[DisplayFormat, None, None]:
binding_context=UNISWAP_CONTEXT,
func_sig=_FUNC_SIG,
intent="Swap",
+ provider_name="Uniswap V3 Router",
parameter_definitions=[
Tuple(
(
@@ -771,6 +788,7 @@ def all_display_formats() -> Generator[DisplayFormat, None, None]:
binding_context=WETH_CONTEXT,
func_sig=b"\xd0\xe3\x0d\xb0", # deposit()
intent="Wrap ETH to WETH",
+ provider_name=None,
parameter_definitions=[], # no arguments, the amount is the tx value
field_definitions=[
FieldDefinition(
@@ -785,6 +803,7 @@ def all_display_formats() -> Generator[DisplayFormat, None, None]:
binding_context=WETH_CONTEXT,
func_sig=b"\x2e\x1a\x7d\x4d", # withdraw(uint256)
intent="Unwrap WETH to ETH",
+ provider_name=None,
parameter_definitions=[
Atomic(parse_uint256), # wad
],
@@ -818,6 +837,7 @@ def all_display_formats() -> Generator[DisplayFormat, None, None]:
binding_context=TREZOR_TEST_CONTEXT,
func_sig=b"\x7e\x57\x7e\x01", # synthetic selector (dummy contract)
intent="Trezor Test Scalars. DO NOT USE",
+ provider_name="Trezor Test. DO NOT USE",
parameter_definitions=[
Atomic(parse_address), # 0 recipient
Atomic(parse_uint256), # 1 nativeAmount
@@ -853,6 +873,7 @@ def all_display_formats() -> Generator[DisplayFormat, None, None]:
binding_context=TREZOR_TEST_CONTEXT,
func_sig=b"\x7e\x57\x7e\x02", # synthetic selector (dummy contract)
intent="Trezor Test Token. DO NOT USE",
+ provider_name="Trezor Test. DO NOT USE",
parameter_definitions=[
Atomic(parse_address), # 0 token (target of token_path below)
Atomic(parse_uint256), # 1 tokenAmount
@@ -875,6 +896,7 @@ def all_display_formats() -> Generator[DisplayFormat, None, None]:
binding_context=TREZOR_TEST_CONTEXT,
func_sig=b"\x7e\x57\x7e\x03", # synthetic selector (dummy contract)
intent="Trezor Test Arrays. DO NOT USE",
+ provider_name="Trezor Test. DO NOT USE",
parameter_definitions=[
Array(Atomic(parse_uint256)), # 0 amounts (multi-value array)
Array(
@@ -903,6 +925,7 @@ def all_display_formats() -> Generator[DisplayFormat, None, None]:
binding_context=TREZOR_TEST_CONTEXT,
func_sig=b"\x7e\x57\x7e\x04", # synthetic selector (dummy contract)
intent="Trezor Test Paths. DO NOT USE",
+ provider_name="Trezor Test. DO NOT USE",
parameter_definitions=[
Atomic(parse_uint256), # 0 amount (reused by both slice fields)
DynamicLeaf(parse_bytes), # 1 packedPath (sliced for token addresses)
diff --git a/core/src/apps/ethereum/yielding.py b/core/src/apps/ethereum/yielding.py
index 0d378f3a..adc69971 100644
--- a/core/src/apps/ethereum/yielding.py
+++ b/core/src/apps/ethereum/yielding.py
@@ -29,6 +29,7 @@ _MERKL_XYZ_CLAIM_DISTRIBUTOR_ADDR = (
DEPOSIT_DISPLAY_FORMAT = DisplayFormat(
binding_context=None,
func_sig=FUNC_SIG_DEPOSIT,
+ provider_name=None,
intent="Deposit",
parameter_definitions=[
Atomic(parse_uint256), # assets
@@ -41,6 +42,7 @@ DEPOSIT_DISPLAY_FORMAT = DisplayFormat(
WITHDRAW_DISPLAY_FORMAT = DisplayFormat(
binding_context=None,
func_sig=FUNC_SIG_WITHDRAW,
+ provider_name=None,
intent="Withdraw",
parameter_definitions=[
Atomic(parse_uint256), # assets
@@ -54,6 +56,7 @@ WITHDRAW_DISPLAY_FORMAT = DisplayFormat(
REDEEM_DISPLAY_FORMAT = DisplayFormat(
binding_context=None,
func_sig=FUNC_SIG_REDEEM,
+ provider_name=None,
intent="Redeem",
parameter_definitions=[
Atomic(parse_uint256), # shares
@@ -70,6 +73,7 @@ REDEEM_DISPLAY_FORMAT = DisplayFormat(
CLAIM_DISPLAY_FORMAT = DisplayFormat(
binding_context=None,
func_sig=FUNC_SIG_CLAIM,
+ provider_name=None,
intent="Claim",
parameter_definitions=[
Array(Atomic(parse_address)), # users
diff --git a/core/tests/test_apps.ethereum.clear_signing.py b/core/tests/test_apps.ethereum.clear_signing.py
index 83daf496..0f7208c8 100644
--- a/core/tests/test_apps.ethereum.clear_signing.py
+++ b/core/tests/test_apps.ethereum.clear_signing.py
@@ -7,11 +7,7 @@ if not utils.BITCOIN_ONLY:
from ethereum_common import *
from trezor.enums import EthereumERC7730FieldFormatterType as FT
- from trezor.messages import (
- EthereumERC7730FieldInfo,
- EthereumERC7730Path,
- EthereumTokenInfo,
- )
+ from trezor.messages import EthereumERC7730FieldInfo, EthereumERC7730Path
from apps.ethereum.clear_signing import (
AddressNameFormatter,
@@ -652,6 +648,7 @@ class TestEthereumClearSigning(unittest.TestCase):
display_format = DisplayFormat(
binding_context=None,
func_sig=b"\x00\x00\x00\x00",
+ provider_name=None,
intent="Test",
parameter_definitions=[Array(Atomic(parse_uint256))],
field_definitions=[FieldDefinition((0,), "Values", RawFormatter)],
@@ -697,6 +694,7 @@ class TestEthereumClearSigning(unittest.TestCase):
display_format = DisplayFormat(
binding_context=None,
func_sig=b"\x00\x00\x00\x00",
+ provider_name=None,
intent="Test",
parameter_definitions=[],
field_definitions=[
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.