feat(core): group EIP-712 domain confirmations
What changed, and why it matters
This commit changes how Trezor devices ask the user to confirm details for EIP-712 typed Ethereum signatures. Instead of showing each piece of the 'EIP712Domain' section one by one, it groups them into a single screen on newer devices. It also adds a warning when the dApp provides an empty EIP712Domain, which means the app did not identify itself. The change is a user-experience improvement with a small defensive-security side effect, not a fix for an active vulnerability.
No urgent action. Treat as a normal firmware update. Users benefit from clearer warnings when dApps omit EIP712Domain metadata. Reviewers may verify that the new warning is shown and that rejecting nested EIP712Domain members does not break legitimate use cases.
Security signals we found
New user-visible warning when EIP712Domain is empty
EIP712Domain nested member rejected as unexpected per EIP-712 spec
Domain fields grouped into single confirmation screen, reducing confirmation fatigue
No cryptographic changes to hashing or signing logic
Evidence from the diff
The patch refactors EIP-712 domain confirmation in core/src/apps/ethereum/sign_typed_data.py. For primary_type == ‘EIP712Domain’, it now rejects nested/array struct members (raising DataError), collects each member’s decoded value via the new extract_properties() helper, and presents them all in one confirm_properties() layout. If the domain has no members, it shows a new warning string ‘dApp did not identify itself!’ instead of silently signing. Translation keys and generated Rust translation tables are updated accordingly. The change reduces tap-through on Bolt/Delizia/Eckhart and makes an empty domain visible to the user.
Changed components
core/src/apps/ethereum/sign_typed_data.pycore/src/apps/ethereum/layout.pycore/translations/en.jsoncore/embed/rust/src/translations/generated/translated_string.rscore/mocks/trezortranslate_keys.pyiInspect captured patch +493 / −398
diff --git a/core/embed/rust/librust_qstr.h b/core/embed/rust/librust_qstr.h
index 429c7637..ea849c67 100644
--- a/core/embed/rust/librust_qstr.h
+++ b/core/embed/rust/librust_qstr.h
@@ -1293,6 +1293,7 @@ static void _librust_qstrs(void) {
MP_QSTR_ethereum__delegating;
MP_QSTR_ethereum__deposit_amount;
MP_QSTR_ethereum__deposit_to;
+ MP_QSTR_ethereum__eip_712_empty_domain;
MP_QSTR_ethereum__gas_limit;
MP_QSTR_ethereum__gas_price;
MP_QSTR_ethereum__interaction_contract;
diff --git a/core/embed/rust/src/translations/generated/translated_string.rs b/core/embed/rust/src/translations/generated/translated_string.rs
index a73da3d9..a1392cae 100644
--- a/core/embed/rust/src/translations/generated/translated_string.rs
+++ b/core/embed/rust/src/translations/generated/translated_string.rs
@@ -1623,45 +1623,47 @@ pub enum TranslatedString {
#[cfg(feature = "universal_fw")]
tron__owner_address = 1238, // "Owner address"
#[cfg(feature = "universal_fw")]
- ethereum__all_evms = 1239, // "All EVMs"
+ ethereum__eip_712_empty_domain = 1239, // "dApp did not identify itself!"
#[cfg(feature = "universal_fw")]
- ethereum__auth_done = 1240, // {"Bolt": "", "Caesar": "", "Delizia": "EIP-7702 authorization signed.", "Eckhart": "EIP-7702 authorization signed."}
+ ethereum__all_evms = 1240, // "All EVMs"
#[cfg(feature = "universal_fw")]
- ethereum__auth_title = 1241, // "EIP-7702 Authorization"
+ ethereum__auth_done = 1241, // {"Bolt": "", "Caesar": "", "Delizia": "EIP-7702 authorization signed.", "Eckhart": "EIP-7702 authorization signed."}
#[cfg(feature = "universal_fw")]
- ethereum__auth_warn = 1242, // "Authorize your account to a third-party contract using EIP-7702?"
+ ethereum__auth_title = 1242, // "EIP-7702 Authorization"
#[cfg(feature = "universal_fw")]
- ethereum__delegate_done = 1243, // {"Bolt": "", "Caesar": "", "Delizia": "EIP-7702 delegation signed.", "Eckhart": "EIP-7702 delegation signed."}
+ ethereum__auth_warn = 1243, // "Authorize your account to a third-party contract using EIP-7702?"
#[cfg(feature = "universal_fw")]
- ethereum__delegate_title = 1244, // "EIP-7702 Delegation"
+ ethereum__calldata_digest = 1244, // "ERC-8213 digest"
#[cfg(feature = "universal_fw")]
- ethereum__delegate_warn = 1245, // "Delegate your account to a third-party contract?"
+ ethereum__delegate_done = 1245, // {"Bolt": "", "Caesar": "", "Delizia": "EIP-7702 delegation signed.", "Eckhart": "EIP-7702 delegation signed."}
#[cfg(feature = "universal_fw")]
- ethereum__delegating = 1246, // "Delegating"
+ ethereum__delegate_title = 1246, // "EIP-7702 Delegation"
#[cfg(feature = "universal_fw")]
- ethereum__network = 1247, // "Network"
+ ethereum__delegate_warn = 1247, // "Delegate your account to a third-party contract?"
#[cfg(feature = "universal_fw")]
- ethereum__revoke_done = 1248, // {"Bolt": "", "Caesar": "", "Delizia": "EIP-7702 revocation signed.", "Eckhart": "EIP-7702 revocation signed."}
+ ethereum__delegating = 1248, // "Delegating"
#[cfg(feature = "universal_fw")]
- ethereum__revoke_title = 1249, // "EIP-7702 Revocation"
+ ethereum__network = 1249, // "Network"
#[cfg(feature = "universal_fw")]
- ethereum__revoke_warn = 1250, // "Revoke {0} from smart account delegation?"
+ ethereum__revoke_done = 1250, // {"Bolt": "", "Caesar": "", "Delizia": "EIP-7702 revocation signed.", "Eckhart": "EIP-7702 revocation signed."}
#[cfg(feature = "universal_fw")]
- ethereum__smart_info = 1251, // "Smart account contract info"
+ ethereum__revoke_title = 1251, // "EIP-7702 Revocation"
#[cfg(feature = "universal_fw")]
- ethereum__to = 1252, // "To"
+ ethereum__revoke_warn = 1252, // "Revoke {0} from smart account delegation?"
#[cfg(feature = "universal_fw")]
- ethereum__calldata_digest = 1253, // "ERC-8213 digest"
- pin__reenter_new_description = 1254, // {"Bolt": "", "Caesar": "", "Delizia": "Re-enter new PIN.", "Eckhart": ""}
+ ethereum__smart_info = 1253, // "Smart account contract info"
#[cfg(feature = "universal_fw")]
- stellar__ext_auth = 1255, // "External Authorizations"
+ ethereum__to = 1254, // "To"
+ pin__reenter_new_description = 1255, // {"Bolt": "", "Caesar": "", "Delizia": "Re-enter new PIN.", "Eckhart": ""}
#[cfg(feature = "universal_fw")]
- stellar__ext_auth_message = 1256, // "Transaction contains additional invocations authorized by external means."
+ stellar__ext_auth = 1256, // "External Authorizations"
#[cfg(feature = "universal_fw")]
- stellar__invoke_contract = 1257, // "Invoke Contract"
- words__arguments = 1258, // "Arguments"
- words__authorization = 1259, // "Authorization"
- words__function = 1260, // "Function"
+ stellar__ext_auth_message = 1257, // "Transaction contains additional invocations authorized by external means."
+ #[cfg(feature = "universal_fw")]
+ stellar__invoke_contract = 1258, // "Invoke Contract"
+ words__arguments = 1259, // "Arguments"
+ words__authorization = 1260, // "Authorization"
+ words__function = 1261, // "Function"
}
impl TranslatedString {
@@ -2908,10 +2910,12 @@ impl TranslatedString {
"Claim voting rewards?",
"",
"Owner address",
+ "dApp did not identify itself!",
"All EVMs",
"",
"EIP-7702 Authorization",
"Authorize your account to a third-party contract using EIP-7702?",
+ "ERC-8213 digest",
"",
"EIP-7702 Delegation",
"Delegate your account to a third-party contract?",
@@ -2922,7 +2926,6 @@ impl TranslatedString {
"Revoke {0} from smart account delegation?",
"Smart account contract info",
"To",
- "ERC-8213 digest",
"",
"External Authorizations",
"Transaction contains additional invocations authorized by external means.",
@@ -4174,28 +4177,29 @@ impl TranslatedString {
18608,
18608,
18621,
- 18629,
- 18629,
- 18651,
- 18715,
- 18715,
- 18734,
- 18782,
- 18792,
- 18799,
- 18799,
- 18818,
- 18859,
- 18886,
- 18888,
- 18903,
+ 18650,
+ 18658,
+ 18658,
+ 18680,
+ 18744,
+ 18759,
+ 18759,
+ 18778,
+ 18826,
+ 18836,
+ 18843,
+ 18843,
+ 18862,
18903,
- 18926,
- 18999,
- 19014,
- 19023,
- 19036,
- 19044,
+ 18930,
+ 18932,
+ 18932,
+ 18955,
+ 19028,
+ 19043,
+ 19052,
+ 19065,
+ 19073,
];
#[cfg(all(feature = "debug", not(feature = "universal_fw")))]
@@ -5439,10 +5443,12 @@ impl TranslatedString {
"Claim voting rewards?",
"",
"Owner address",
+ "dApp did not identify itself!",
"All EVMs",
"",
"EIP-7702 Authorization",
"Authorize your account to a third-party contract using EIP-7702?",
+ "ERC-8213 digest",
"",
"EIP-7702 Delegation",
"Delegate your account to a third-party contract?",
@@ -5453,7 +5459,6 @@ impl TranslatedString {
"Revoke {0} from smart account delegation?",
"Smart account contract info",
"To",
- "ERC-8213 digest",
"",
"External Authorizations",
"Transaction contains additional invocations authorized by external means.",
@@ -6705,28 +6710,29 @@ impl TranslatedString {
18608,
18608,
18621,
- 18629,
- 18629,
- 18651,
- 18715,
- 18715,
- 18734,
- 18782,
- 18792,
- 18799,
- 18799,
- 18818,
- 18859,
- 18886,
- 18888,
- 18903,
+ 18650,
+ 18658,
+ 18658,
+ 18680,
+ 18744,
+ 18759,
+ 18759,
+ 18778,
+ 18826,
+ 18836,
+ 18843,
+ 18843,
+ 18862,
18903,
- 18926,
- 18999,
- 19014,
- 19023,
- 19036,
- 19044,
+ 18930,
+ 18932,
+ 18932,
+ 18955,
+ 19028,
+ 19043,
+ 19052,
+ 19065,
+ 19073,
];
#[cfg(all(not(feature = "debug"), feature = "universal_fw"))]
@@ -7970,10 +7976,12 @@ impl TranslatedString {
"Claim voting rewards?",
"",
"Owner address",
+ "dApp did not identify itself!",
"All EVMs",
"",
"EIP-7702 Authorization",
"Authorize your account to a third-party contract using EIP-7702?",
+ "ERC-8213 digest",
"",
"EIP-7702 Delegation",
"Delegate your account to a third-party contract?",
@@ -7984,7 +7992,6 @@ impl TranslatedString {
"Revoke {0} from smart account delegation?",
"Smart account contract info",
"To",
- "ERC-8213 digest",
"",
"External Authorizations",
"Transaction contains additional invocations authorized by external means.",
@@ -9236,28 +9243,29 @@ impl TranslatedString {
18608,
18608,
18621,
- 18629,
- 18629,
- 18651,
- 18715,
- 18715,
- 18734,
- 18782,
- 18792,
- 18799,
- 18799,
- 18818,
- 18859,
- 18886,
- 18888,
- 18903,
+ 18650,
+ 18658,
+ 18658,
+ 18680,
+ 18744,
+ 18759,
+ 18759,
+ 18778,
+ 18826,
+ 18836,
+ 18843,
+ 18843,
+ 18862,
18903,
- 18926,
- 18999,
- 19014,
- 19023,
- 19036,
- 19044,
+ 18930,
+ 18932,
+ 18932,
+ 18955,
+ 19028,
+ 19043,
+ 19052,
+ 19065,
+ 19073,
];
#[cfg(all(not(feature = "debug"), not(feature = "universal_fw")))]
@@ -10501,10 +10509,12 @@ impl TranslatedString {
"Claim voting rewards?",
"",
"Owner address",
+ "dApp did not identify itself!",
"All EVMs",
"",
"EIP-7702 Authorization",
"Authorize your account to a third-party contract using EIP-7702?",
+ "ERC-8213 digest",
"",
"EIP-7702 Delegation",
"Delegate your account to a third-party contract?",
@@ -10515,7 +10525,6 @@ impl TranslatedString {
"Revoke {0} from smart account delegation?",
"Smart account contract info",
"To",
- "ERC-8213 digest",
"",
"External Authorizations",
"Transaction contains additional invocations authorized by external means.",
@@ -11767,28 +11776,29 @@ impl TranslatedString {
18608,
18608,
18621,
- 18629,
- 18629,
- 18651,
- 18715,
- 18715,
- 18734,
- 18782,
- 18792,
- 18799,
- 18799,
- 18818,
- 18859,
- 18886,
- 18888,
- 18903,
+ 18650,
+ 18658,
+ 18658,
+ 18680,
+ 18744,
+ 18759,
+ 18759,
+ 18778,
+ 18826,
+ 18836,
+ 18843,
+ 18843,
+ 18862,
18903,
- 18926,
- 18999,
- 19014,
- 19023,
- 19036,
- 19044,
+ 18930,
+ 18932,
+ 18932,
+ 18955,
+ 19028,
+ 19043,
+ 19052,
+ 19065,
+ 19073,
];
} else if #[cfg(feature = "layout_caesar")] {
@@ -13033,10 +13043,12 @@ impl TranslatedString {
"Claim voting rewards?",
"",
"Owner address",
+ "dApp did not identify itself!",
"All EVMs",
"",
"EIP-7702 Authorization",
"Authorize your account to a third-party contract using EIP-7702?",
+ "ERC-8213 digest",
"",
"EIP-7702 Delegation",
"Delegate your account to a third-party contract?",
@@ -13047,7 +13059,6 @@ impl TranslatedString {
"Revoke {0} from smart account delegation?",
"Smart account contract info",
"To",
- "ERC-8213 digest",
"",
"External Authorizations",
"Transaction contains additional invocations authorized by external means.",
@@ -14299,28 +14310,29 @@ impl TranslatedString {
16399,
16399,
16412,
- 16420,
- 16420,
- 16442,
- 16506,
- 16506,
- 16525,
- 16573,
- 16583,
- 16590,
- 16590,
- 16609,
- 16650,
- 16677,
- 16679,
- 16694,
+ 16441,
+ 16449,
+ 16449,
+ 16471,
+ 16535,
+ 16550,
+ 16550,
+ 16569,
+ 16617,
+ 16627,
+ 16634,
+ 16634,
+ 16653,
16694,
- 16717,
- 16790,
- 16805,
- 16814,
- 16827,
- 16835,
+ 16721,
+ 16723,
+ 16723,
+ 16746,
+ 16819,
+ 16834,
+ 16843,
+ 16856,
+ 16864,
];
#[cfg(all(feature = "debug", not(feature = "universal_fw")))]
@@ -15564,10 +15576,12 @@ impl TranslatedString {
"Claim voting rewards?",
"",
"Owner address",
+ "dApp did not identify itself!",
"All EVMs",
"",
"EIP-7702 Authorization",
"Authorize your account to a third-party contract using EIP-7702?",
+ "ERC-8213 digest",
"",
"EIP-7702 Delegation",
"Delegate your account to a third-party contract?",
@@ -15578,7 +15592,6 @@ impl TranslatedString {
"Revoke {0} from smart account delegation?",
"Smart account contract info",
"To",
- "ERC-8213 digest",
"",
"External Authorizations",
"Transaction contains additional invocations authorized by external means.",
@@ -16830,28 +16843,29 @@ impl TranslatedString {
16399,
16399,
16412,
- 16420,
- 16420,
- 16442,
- 16506,
- 16506,
- 16525,
- 16573,
- 16583,
- 16590,
- 16590,
- 16609,
- 16650,
- 16677,
- 16679,
- 16694,
+ 16441,
+ 16449,
+ 16449,
+ 16471,
+ 16535,
+ 16550,
+ 16550,
+ 16569,
+ 16617,
+ 16627,
+ 16634,
+ 16634,
+ 16653,
16694,
- 16717,
- 16790,
- 16805,
- 16814,
- 16827,
- 16835,
+ 16721,
+ 16723,
+ 16723,
+ 16746,
+ 16819,
+ 16834,
+ 16843,
+ 16856,
+ 16864,
];
#[cfg(all(not(feature = "debug"), feature = "universal_fw"))]
@@ -18095,10 +18109,12 @@ impl TranslatedString {
"Claim voting rewards?",
"",
"Owner address",
+ "dApp did not identify itself!",
"All EVMs",
"",
"EIP-7702 Authorization",
"Authorize your account to a third-party contract using EIP-7702?",
+ "ERC-8213 digest",
"",
"EIP-7702 Delegation",
"Delegate your account to a third-party contract?",
@@ -18109,7 +18125,6 @@ impl TranslatedString {
"Revoke {0} from smart account delegation?",
"Smart account contract info",
"To",
- "ERC-8213 digest",
"",
"External Authorizations",
"Transaction contains additional invocations authorized by external means.",
@@ -19361,28 +19376,29 @@ impl TranslatedString {
16399,
16399,
16412,
- 16420,
- 16420,
- 16442,
- 16506,
- 16506,
- 16525,
- 16573,
- 16583,
- 16590,
- 16590,
- 16609,
- 16650,
- 16677,
- 16679,
- 16694,
+ 16441,
+ 16449,
+ 16449,
+ 16471,
+ 16535,
+ 16550,
+ 16550,
+ 16569,
+ 16617,
+ 16627,
+ 16634,
+ 16634,
+ 16653,
16694,
- 16717,
- 16790,
- 16805,
- 16814,
- 16827,
- 16835,
+ 16721,
+ 16723,
+ 16723,
+ 16746,
+ 16819,
+ 16834,
+ 16843,
+ 16856,
+ 16864,
];
#[cfg(all(not(feature = "debug"), not(feature = "universal_fw")))]
@@ -20626,10 +20642,12 @@ impl TranslatedString {
"Claim voting rewards?",
"",
"Owner address",
+ "dApp did not identify itself!",
"All EVMs",
"",
"EIP-7702 Authorization",
"Authorize your account to a third-party contract using EIP-7702?",
+ "ERC-8213 digest",
"",
"EIP-7702 Delegation",
"Delegate your account to a third-party contract?",
@@ -20640,7 +20658,6 @@ impl TranslatedString {
"Revoke {0} from smart account delegation?",
"Smart account contract info",
"To",
- "ERC-8213 digest",
"",
"External Authorizations",
"Transaction contains additional invocations authorized by external means.",
@@ -21892,28 +21909,29 @@ impl TranslatedString {
16399,
16399,
16412,
- 16420,
- 16420,
- 16442,
- 16506,
- 16506,
- 16525,
- 16573,
- 16583,
- 16590,
- 16590,
- 16609,
- 16650,
- 16677,
- 16679,
- 16694,
+ 16441,
+ 16449,
+ 16449,
+ 16471,
+ 16535,
+ 16550,
+ 16550,
+ 16569,
+ 16617,
+ 16627,
+ 16634,
+ 16634,
+ 16653,
16694,
- 16717,
- 16790,
- 16805,
- 16814,
- 16827,
- 16835,
+ 16721,
+ 16723,
+ 16723,
+ 16746,
+ 16819,
+ 16834,
+ 16843,
+ 16856,
+ 16864,
];
} else if #[cfg(feature = "layout_delizia")] {
@@ -23158,10 +23176,12 @@ impl TranslatedString {
"Claim voting rewards?",
"",
"Owner address",
+ "dApp did not identify itself!",
"All EVMs",
"EIP-7702 authorization signed.",
"EIP-7702 Authorization",
"Authorize your account to a third-party contract using EIP-7702?",
+ "ERC-8213 digest",
"EIP-7702 delegation signed.",
"EIP-7702 Delegation",
"Delegate your account to a third-party contract?",
@@ -23172,7 +23192,6 @@ impl TranslatedString {
"Revoke {0} from smart account delegation?",
"Smart account contract info",
"To",
- "ERC-8213 digest",
"Re-enter new PIN.",
"External Authorizations",
"Transaction contains additional invocations authorized by external means.",
@@ -24424,28 +24443,29 @@ impl TranslatedString {
18396,
18396,
18409,
- 18417,
- 18447,
- 18469,
- 18533,
- 18560,
- 18579,
- 18627,
- 18637,
- 18644,
+ 18438,
+ 18446,
+ 18476,
+ 18498,
+ 18562,
+ 18577,
+ 18604,
+ 18623,
18671,
- 18690,
- 18731,
- 18758,
- 18760,
+ 18681,
+ 18688,
+ 18715,
+ 18734,
18775,
- 18792,
- 18815,
- 18888,
- 18903,
- 18912,
- 18925,
- 18933,
+ 18802,
+ 18804,
+ 18821,
+ 18844,
+ 18917,
+ 18932,
+ 18941,
+ 18954,
+ 18962,
];
#[cfg(all(feature = "debug", not(feature = "universal_fw")))]
@@ -25689,10 +25709,12 @@ impl TranslatedString {
"Claim voting rewards?",
"",
"Owner address",
+ "dApp did not identify itself!",
"All EVMs",
"EIP-7702 authorization signed.",
"EIP-7702 Authorization",
"Authorize your account to a third-party contract using EIP-7702?",
+ "ERC-8213 digest",
"EIP-7702 delegation signed.",
"EIP-7702 Delegation",
"Delegate your account to a third-party contract?",
@@ -25703,7 +25725,6 @@ impl TranslatedString {
"Revoke {0} from smart account delegation?",
"Smart account contract info",
"To",
- "ERC-8213 digest",
"Re-enter new PIN.",
"External Authorizations",
"Transaction contains additional invocations authorized by external means.",
@@ -26955,28 +26976,29 @@ impl TranslatedString {
18396,
18396,
18409,
- 18417,
- 18447,
- 18469,
- 18533,
- 18560,
- 18579,
- 18627,
- 18637,
- 18644,
+ 18438,
+ 18446,
+ 18476,
+ 18498,
+ 18562,
+ 18577,
+ 18604,
+ 18623,
18671,
- 18690,
- 18731,
- 18758,
- 18760,
+ 18681,
+ 18688,
+ 18715,
+ 18734,
18775,
- 18792,
- 18815,
- 18888,
- 18903,
- 18912,
- 18925,
- 18933,
+ 18802,
+ 18804,
+ 18821,
+ 18844,
+ 18917,
+ 18932,
+ 18941,
+ 18954,
+ 18962,
];
#[cfg(all(not(feature = "debug"), feature = "universal_fw"))]
@@ -28220,10 +28242,12 @@ impl TranslatedString {
"Claim voting rewards?",
"",
"Owner address",
+ "dApp did not identify itself!",
"All EVMs",
"EIP-7702 authorization signed.",
"EIP-7702 Authorization",
"Authorize your account to a third-party contract using EIP-7702?",
+ "ERC-8213 digest",
"EIP-7702 delegation signed.",
"EIP-7702 Delegation",
"Delegate your account to a third-party contract?",
@@ -28234,7 +28258,6 @@ impl TranslatedString {
"Revoke {0} from smart account delegation?",
"Smart account contract info",
"To",
- "ERC-8213 digest",
"Re-enter new PIN.",
"External Authorizations",
"Transaction contains additional invocations authorized by external means.",
@@ -29486,28 +29509,29 @@ impl TranslatedString {
18396,
18396,
18409,
- 18417,
- 18447,
- 18469,
- 18533,
- 18560,
- 18579,
- 18627,
- 18637,
- 18644,
+ 18438,
+ 18446,
+ 18476,
+ 18498,
+ 18562,
+ 18577,
+ 18604,
+ 18623,
18671,
- 18690,
- 18731,
- 18758,
- 18760,
+ 18681,
+ 18688,
+ 18715,
+ 18734,
18775,
- 18792,
- 18815,
- 18888,
- 18903,
- 18912,
- 18925,
- 18933,
+ 18802,
+ 18804,
+ 18821,
+ 18844,
+ 18917,
+ 18932,
+ 18941,
+ 18954,
+ 18962,
];
#[cfg(all(not(feature = "debug"), not(feature = "universal_fw")))]
@@ -30751,10 +30775,12 @@ impl TranslatedString {
"Claim voting rewards?",
"",
"Owner address",
+ "dApp did not identify itself!",
"All EVMs",
"EIP-7702 authorization signed.",
"EIP-7702 Authorization",
"Authorize your account to a third-party contract using EIP-7702?",
+ "ERC-8213 digest",
"EIP-7702 delegation signed.",
"EIP-7702 Delegation",
"Delegate your account to a third-party contract?",
@@ -30765,7 +30791,6 @@ impl TranslatedString {
"Revoke {0} from smart account delegation?",
"Smart account contract info",
"To",
- "ERC-8213 digest",
"Re-enter new PIN.",
"External Authorizations",
"Transaction contains additional invocations authorized by external means.",
@@ -32017,28 +32042,29 @@ impl TranslatedString {
18396,
18396,
18409,
- 18417,
- 18447,
- 18469,
- 18533,
- 18560,
- 18579,
- 18627,
- 18637,
- 18644,
+ 18438,
+ 18446,
+ 18476,
+ 18498,
+ 18562,
+ 18577,
+ 18604,
+ 18623,
18671,
- 18690,
- 18731,
- 18758,
- 18760,
+ 18681,
+ 18688,
+ 18715,
+ 18734,
18775,
- 18792,
- 18815,
- 18888,
- 18903,
- 18912,
- 18925,
- 18933,
+ 18802,
+ 18804,
+ 18821,
+ 18844,
+ 18917,
+ 18932,
+ 18941,
+ 18954,
+ 18962,
];
} else if #[cfg(feature = "layout_eckhart")] {
@@ -33283,10 +33309,12 @@ impl TranslatedString {
"Claim voting rewards?",
"This is NOT your address",
"Owner address",
+ "dApp did not identify itself!",
"All EVMs",
"EIP-7702 authorization signed.",
"EIP-7702 Authorization",
"Authorize your account to a third-party contract using EIP-7702?",
+ "ERC-8213 digest",
"EIP-7702 delegation signed.",
"EIP-7702 Delegation",
"Delegate your account to a third-party contract?",
@@ -33297,7 +33325,6 @@ impl TranslatedString {
"Revoke {0} from smart account delegation?",
"Smart account contract info",
"To",
- "ERC-8213 digest",
"",
"External Authorizations",
"Transaction contains additional invocations authorized by external means.",
@@ -34549,28 +34576,29 @@ impl TranslatedString {
19750,
19774,
19787,
- 19795,
- 19825,
- 19847,
- 19911,
- 19938,
- 19957,
- 20005,
- 20015,
- 20022,
+ 19816,
+ 19824,
+ 19854,
+ 19876,
+ 19940,
+ 19955,
+ 19982,
+ 20001,
20049,
- 20068,
- 20109,
- 20136,
- 20138,
+ 20059,
+ 20066,
+ 20093,
+ 20112,
20153,
- 20153,
- 20176,
- 20249,
- 20264,
- 20273,
- 20286,
- 20294,
+ 20180,
+ 20182,
+ 20182,
+ 20205,
+ 20278,
+ 20293,
+ 20302,
+ 20315,
+ 20323,
];
#[cfg(all(feature = "debug", not(feature = "universal_fw")))]
@@ -35814,10 +35842,12 @@ impl TranslatedString {
"Claim voting rewards?",
"This is NOT your address",
"Owner address",
+ "dApp did not identify itself!",
"All EVMs",
"EIP-7702 authorization signed.",
"EIP-7702 Authorization",
"Authorize your account to a third-party contract using EIP-7702?",
+ "ERC-8213 digest",
"EIP-7702 delegation signed.",
"EIP-7702 Delegation",
"Delegate your account to a third-party contract?",
@@ -35828,7 +35858,6 @@ impl TranslatedString {
"Revoke {0} from smart account delegation?",
"Smart account contract info",
"To",
- "ERC-8213 digest",
"",
"External Authorizations",
"Transaction contains additional invocations authorized by external means.",
@@ -37080,28 +37109,29 @@ impl TranslatedString {
19750,
19774,
19787,
- 19795,
- 19825,
- 19847,
- 19911,
- 19938,
- 19957,
- 20005,
- 20015,
- 20022,
+ 19816,
+ 19824,
+ 19854,
+ 19876,
+ 19940,
+ 19955,
+ 19982,
+ 20001,
20049,
- 20068,
- 20109,
- 20136,
- 20138,
- 20153,
+ 20059,
+ 20066,
+ 20093,
+ 20112,
20153,
- 20176,
- 20249,
- 20264,
- 20273,
- 20286,
- 20294,
+ 20180,
+ 20182,
+ 20182,
+ 20205,
+ 20278,
+ 20293,
+ 20302,
+ 20315,
+ 20323,
];
#[cfg(all(not(feature = "debug"), feature = "universal_fw"))]
@@ -38345,10 +38375,12 @@ impl TranslatedString {
"Claim voting rewards?",
"This is NOT your address",
"Owner address",
+ "dApp did not identify itself!",
"All EVMs",
"EIP-7702 authorization signed.",
"EIP-7702 Authorization",
"Authorize your account to a third-party contract using EIP-7702?",
+ "ERC-8213 digest",
"EIP-7702 delegation signed.",
"EIP-7702 Delegation",
"Delegate your account to a third-party contract?",
@@ -38359,7 +38391,6 @@ impl TranslatedString {
"Revoke {0} from smart account delegation?",
"Smart account contract info",
"To",
- "ERC-8213 digest",
"",
"External Authorizations",
"Transaction contains additional invocations authorized by external means.",
@@ -39611,28 +39642,29 @@ impl TranslatedString {
19750,
19774,
19787,
- 19795,
- 19825,
- 19847,
- 19911,
- 19938,
- 19957,
- 20005,
- 20015,
- 20022,
+ 19816,
+ 19824,
+ 19854,
+ 19876,
+ 19940,
+ 19955,
+ 19982,
+ 20001,
20049,
- 20068,
- 20109,
- 20136,
- 20138,
+ 20059,
+ 20066,
+ 20093,
+ 20112,
20153,
- 20153,
- 20176,
- 20249,
- 20264,
- 20273,
- 20286,
- 20294,
+ 20180,
+ 20182,
+ 20182,
+ 20205,
+ 20278,
+ 20293,
+ 20302,
+ 20315,
+ 20323,
];
#[cfg(all(not(feature = "debug"), not(feature = "universal_fw")))]
@@ -40876,10 +40908,12 @@ impl TranslatedString {
"Claim voting rewards?",
"This is NOT your address",
"Owner address",
+ "dApp did not identify itself!",
"All EVMs",
"EIP-7702 authorization signed.",
"EIP-7702 Authorization",
"Authorize your account to a third-party contract using EIP-7702?",
+ "ERC-8213 digest",
"EIP-7702 delegation signed.",
"EIP-7702 Delegation",
"Delegate your account to a third-party contract?",
@@ -40890,7 +40924,6 @@ impl TranslatedString {
"Revoke {0} from smart account delegation?",
"Smart account contract info",
"To",
- "ERC-8213 digest",
"",
"External Authorizations",
"Transaction contains additional invocations authorized by external means.",
@@ -42142,28 +42175,29 @@ impl TranslatedString {
19750,
19774,
19787,
- 19795,
- 19825,
- 19847,
- 19911,
- 19938,
- 19957,
- 20005,
- 20015,
- 20022,
+ 19816,
+ 19824,
+ 19854,
+ 19876,
+ 19940,
+ 19955,
+ 19982,
+ 20001,
20049,
- 20068,
- 20109,
- 20136,
- 20138,
- 20153,
+ 20059,
+ 20066,
+ 20093,
+ 20112,
20153,
- 20176,
- 20249,
- 20264,
- 20273,
- 20286,
- 20294,
+ 20180,
+ 20182,
+ 20182,
+ 20205,
+ 20278,
+ 20293,
+ 20302,
+ 20315,
+ 20323,
];
}
@@ -42707,6 +42741,8 @@ impl TranslatedString {
#[cfg(feature = "universal_fw")]
(Qstr::MP_QSTR_ethereum__deposit_to, Self::ethereum__deposit_to),
#[cfg(feature = "universal_fw")]
+ (Qstr::MP_QSTR_ethereum__eip_712_empty_domain, Self::ethereum__eip_712_empty_domain),
+ #[cfg(feature = "universal_fw")]
(Qstr::MP_QSTR_ethereum__gas_limit, Self::ethereum__gas_limit),
#[cfg(feature = "universal_fw")]
(Qstr::MP_QSTR_ethereum__gas_price, Self::ethereum__gas_price),
diff --git a/core/mocks/trezortranslate_keys.pyi b/core/mocks/trezortranslate_keys.pyi
index 7e966bdd..e1e1ed35 100644
--- a/core/mocks/trezortranslate_keys.pyi
+++ b/core/mocks/trezortranslate_keys.pyi
@@ -349,6 +349,7 @@ class TR:
ethereum__delegating: str = "Delegating"
ethereum__deposit_amount: str = "Deposit amount"
ethereum__deposit_to: str = "Deposit to"
+ ethereum__eip_712_empty_domain: str = "dApp did not identify itself!"
ethereum__gas_limit: str = "Gas limit"
ethereum__gas_price: str = "Gas price"
ethereum__interaction_contract: str = "Interaction contract"
diff --git a/core/src/apps/ethereum/layout.py b/core/src/apps/ethereum/layout.py
index 9cf5d3f8..38fe10ba 100644
--- a/core/src/apps/ethereum/layout.py
+++ b/core/src/apps/ethereum/layout.py
@@ -542,6 +542,21 @@ async def confirm_typed_value(
)
+def extract_properties(
+ name: str,
+ value: AnyBytes,
+ field: EthereumFieldType,
+) -> StrPropertyType:
+
+ from .helpers import get_type_name
+
+ type_name = get_type_name(field)
+ key = f"{name} ({type_name})"
+ data = decode_typed_data(value, type_name)
+
+ return (key, data, True)
+
+
def limit_str(s: str, limit: int = 16) -> str:
"""Shortens string to show the last <limit> characters."""
if len(s) <= limit + 2:
diff --git a/core/src/apps/ethereum/sign_typed_data.py b/core/src/apps/ethereum/sign_typed_data.py
index e4f8fa90..23684d9e 100644
--- a/core/src/apps/ethereum/sign_typed_data.py
+++ b/core/src/apps/ethereum/sign_typed_data.py
@@ -277,12 +277,26 @@ class TypedDataEnvelope:
i.e. the concatenation of the encoded member values in the order that they appear in the type.
Each encoded member value is exactly 32-byte long.
"""
- from .layout import confirm_typed_value, should_show_array
+ from trezor.enums import ButtonRequestType
+ from trezor.ui.layouts import confirm_properties
+
+ from .layout import confirm_typed_value, extract_properties, should_show_array
type_members = self.types[primary_type].members
members_count = len(type_members)
member_value_path = member_path + [0]
current_parent_objects = parent_objects + [""]
+
+ _NESTED = (EthereumDataType.ARRAY, EthereumDataType.STRUCT)
+
+ if primary_type == "EIP712Domain":
+ if any(member.type.data_type in _NESTED for member in type_members):
+ # https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator
+ raise DataError("Unexpected member in EIP712Domain")
+ combined_props = [] # all items will be confirmed using a single layout
+ else:
+ combined_props = None # items will be confirmed separately
+
for member_index, member in enumerate(type_members):
if report_progress:
report_progress(member_index / members_count)
@@ -377,12 +391,38 @@ class TypedDataEnvelope:
value = await get_value(field_type, member_value_path)
encode_field(w, field_type, value)
if show_data:
- await confirm_typed_value(
- field_name,
- value,
- parent_objects,
- field_type,
- )
+ if combined_props is None:
+ await confirm_typed_value(
+ field_name,
+ value,
+ parent_objects,
+ field_type,
+ )
+ else:
+ combined_props.append(
+ extract_properties(field_name, value, field_type)
+ )
+
+ if show_data and combined_props is not None:
+ if combined_props:
+ # Confirm all EIP712Domain items at once:
+ await confirm_properties(
+ "confirm_typed_value",
+ primary_type,
+ combined_props,
+ br_code=ButtonRequestType.Other,
+ )
+ else:
+ from trezor import TR
+ from trezor.ui.layouts import show_warning
+
+ # Show a warning if no EIP712Domain items:
+ await show_warning(
+ content=TR.ethereum__eip_712_empty_domain,
+ button=TR.buttons__continue,
+ br_name="confirm_typed_value",
+ br_code=ButtonRequestType.Warning,
+ )
def encode_field(
diff --git a/core/translations/en.json b/core/translations/en.json
index 8c36a116..ab3283cc 100644
--- a/core/translations/en.json
+++ b/core/translations/en.json
@@ -836,6 +836,7 @@
"ethereum__delegating": "Delegating",
"ethereum__deposit_amount": "Deposit amount",
"ethereum__deposit_to": "Deposit to",
+ "ethereum__eip_712_empty_domain": "dApp did not identify itself!",
"ethereum__gas_limit": "Gas limit",
"ethereum__gas_price": "Gas price",
"ethereum__interaction_contract": {
diff --git a/core/translations/order.json b/core/translations/order.json
index 853b8d4e..d01e9486 100644
--- a/core/translations/order.json
+++ b/core/translations/order.json
@@ -1238,26 +1238,27 @@
"1236": "tron__claim_voting_rewards",
"1237": "address__warning_not_yours",
"1238": "tron__owner_address",
- "1239": "ethereum__all_evms",
- "1240": "ethereum__auth_done",
- "1241": "ethereum__auth_title",
- "1242": "ethereum__auth_warn",
- "1243": "ethereum__delegate_done",
- "1244": "ethereum__delegate_title",
- "1245": "ethereum__delegate_warn",
- "1246": "ethereum__delegating",
- "1247": "ethereum__network",
- "1248": "ethereum__revoke_done",
- "1249": "ethereum__revoke_title",
- "1250": "ethereum__revoke_warn",
- "1251": "ethereum__smart_info",
- "1252": "ethereum__to",
- "1253": "ethereum__calldata_digest",
- "1254": "pin__reenter_new_description",
- "1255": "stellar__ext_auth",
- "1256": "stellar__ext_auth_message",
- "1257": "stellar__invoke_contract",
- "1258": "words__arguments",
- "1259": "words__authorization",
- "1260": "words__function"
+ "1239": "ethereum__eip_712_empty_domain",
+ "1240": "ethereum__all_evms",
+ "1241": "ethereum__auth_done",
+ "1242": "ethereum__auth_title",
+ "1243": "ethereum__auth_warn",
+ "1244": "ethereum__calldata_digest",
+ "1245": "ethereum__delegate_done",
+ "1246": "ethereum__delegate_title",
+ "1247": "ethereum__delegate_warn",
+ "1248": "ethereum__delegating",
+ "1249": "ethereum__network",
+ "1250": "ethereum__revoke_done",
+ "1251": "ethereum__revoke_title",
+ "1252": "ethereum__revoke_warn",
+ "1253": "ethereum__smart_info",
+ "1254": "ethereum__to",
+ "1255": "pin__reenter_new_description",
+ "1256": "stellar__ext_auth",
+ "1257": "stellar__ext_auth_message",
+ "1258": "stellar__invoke_contract",
+ "1259": "words__arguments",
+ "1260": "words__authorization",
+ "1261": "words__function"
}
diff --git a/core/translations/signatures.json b/core/translations/signatures.json
index 359f9393..1f9ab3fc 100644
--- a/core/translations/signatures.json
+++ b/core/translations/signatures.json
@@ -1,8 +1,8 @@
{
"current": {
- "merkle_root": "3b24a185c7289802d17ba03e35c097b81ef50a9f50b089beaf6c092269d9d5bf",
- "datetime": "2026-07-23T14:12:43.060131+00:00",
- "commit": "05344ecdd7938701c805cf9964566c3f5af959c4"
+ "merkle_root": "22aafe9516200002c46444bb5e0705a362eb32793aed6e8b530ea0592fa534d0",
+ "datetime": "2026-07-23T16:07:56.601237+00:00",
+ "commit": "40244ab7c769b4390a35df2ee8fd714a7a1b7cbf"
},
"history": [
{
Why this scored 18/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.