feat(clear_signing): ERC-7730 constant (const_value) display fields
What changed, and why it matters
This commit adds a new way for Ethereum transaction definitions to include fixed text labels (called 'constant values') that are shown to the user during signing. It does not change how transaction data is parsed or signed, but it expands what untrusted display-format definitions can put on the device screen. The change is a feature addition, not a fix for a known bug, and there is no vendor statement that it is security-relevant.
Review whether `const_value` strings need length limits, character-set validation, or HTML/Unicode normalization before display, because they are supplied by host-side or downloaded ERC-7730 definitions and shown to the user during signing. Confirm that the UI layer treats them as untrusted display text and does not interpret them as commands or URLs.
Security signals we found
New untrusted input surface: `const_value` string in ERC-7730 display-format definitions is rendered to the user without length or content validation visible in the diff.
Display-only data path bypasses calldata parsing, so a malicious or compromised host-side definition could show arbitrary constant text alongside real transaction fields.
No input sanitization, escaping, or length limits are added for `const_value` in the changed code.
Renaming `hint` to `is_mono` is cosmetic and not a security signal.
No changelog entry and no vendor security disclosure language present.
Evidence from the diff
The patch extends the ERC-7730 clear-signing path type with an optional const_value string field. In clear_signing.py, FieldDefinition.from_proto now returns the literal string when const_value is set, and DisplayFormat.get_value_for_path returns it directly without walking calldata. The protobuf, generated Python/Rust message classes, and unit tests are updated accordingly. A variable rename (hint -> is_mono) is also included. The new field is rendered by the existing formatter pipeline, typically the raw formatter.
Changed components
core/src/apps/ethereum/clear_signing.pycore/src/apps/ethereum/clear_signing_definitions.pycommon/protob/messages-definitions.protocore/src/trezor/messages.pypython/src/trezorlib/messages.pyrust/trezor-client/src/protos/generated/messages_definitions.rscore/tests/test_apps.ethereum.clear_signing.pyInspect captured patch +156 / −48
diff --git a/common/protob/messages-definitions.proto b/common/protob/messages-definitions.proto
index 1ada61c9..273027e8 100644
--- a/common/protob/messages-definitions.proto
+++ b/common/protob/messages-definitions.proto
@@ -149,16 +149,19 @@ enum EthereumERC7730ContainerPath {
/**
* Path used in ERC-7730 field definitions to access values.
- * We currently support two kinds of paths:
+ * We currently support three kinds of value sources:
* * paths that access function parameters
* * container paths (starting with `@`)
+ * * constant values (a literal resolved by the parser, e.g. a `$.metadata.constants.*`
+ * reference or a literal `value`), not walked from calldata
* `$` and `#` paths are not supported.
* @embed
*/
message EthereumERC7730Path {
// Exactly one of the following should be set:
- repeated sint32 path = 1; // eg. (0,) is encoded as [0], (1, 2) is encoded as [1, 2], etc.
+ repeated sint32 path = 1; // eg. (0,) is encoded as [0], (1, 2) is encoded as [1, 2], etc.
optional EthereumERC7730ContainerPath container_path = 2;
+ optional string const_value = 3; // a literal constant value, not walked from calldata
}
/**
diff --git a/core/src/apps/ethereum/clear_signing.py b/core/src/apps/ethereum/clear_signing.py
index 49500334..9cc65386 100644
--- a/core/src/apps/ethereum/clear_signing.py
+++ b/core/src/apps/ethereum/clear_signing.py
@@ -37,7 +37,9 @@ if TYPE_CHECKING:
ListValue = list[TupleValue]
AnyValue = Value | TupleValue | list["AnyValue"]
- Path = tuple[int | tuple[int] | tuple[int, int], ...] | int
+ # A data path (tuple of steps), a container path (int enum), or a literal
+ # constant value (str, resolved by the parser — not walked from calldata).
+ Path = tuple[int | tuple[int] | tuple[int, int], ...] | int | str
PathWalker = Callable[[Path], AnyValue]
# Parses a Value from a slice of the calldata.
@@ -729,6 +731,10 @@ class FieldDefinition:
def decode_path(p: EthereumERC7730Path) -> Path:
if p.container_path is not None:
return p.container_path
+ if p.const_value is not None:
+ # A literal constant value, resolved by the parser — not walked
+ # from calldata. Rendered as-is (typically by the raw formatter).
+ return p.const_value
return tuple(p.path)
path = decode_path(info.path)
@@ -835,6 +841,9 @@ class DisplayFormat:
offset += consumed
def get_value_for_path(path: Path) -> AnyValue:
+ if isinstance(path, str):
+ # a literal constant value, not walked from calldata
+ return path
if isinstance(path, int): # ContainerPath
# standard container paths like @.from, @.value...
if path == ContainerPath.From:
@@ -1232,10 +1241,10 @@ async def _handle_generic_ui(
properties_to_confirm = []
- for (label, formatted, hint), actual_token, actual_token_address in fields:
+ for (label, formatted, is_mono), actual_token, actual_token_address in fields:
if isinstance(formatted, AboveThreshold):
formatted = formatted.message
- properties_to_confirm.append((label, formatted, hint))
+ properties_to_confirm.append((label, formatted, is_mono))
if actual_token is tokens.UNKNOWN_TOKEN:
assert actual_token_address is not None
token_address_str = address_from_bytes(actual_token_address, defs.network)
diff --git a/core/src/apps/ethereum/clear_signing_definitions.py b/core/src/apps/ethereum/clear_signing_definitions.py
index 2bdbfd14..be946778 100644
--- a/core/src/apps/ethereum/clear_signing_definitions.py
+++ b/core/src/apps/ethereum/clear_signing_definitions.py
@@ -4,10 +4,8 @@ from .clear_signing import (
AddressNameFormatter,
Atomic,
ContainerPath,
- DateFormatter,
DisplayFormat,
FieldDefinition,
- RawFormatter,
TokenAmountFormatter,
parse_address,
parse_uint256,
diff --git a/core/src/trezor/messages.py b/core/src/trezor/messages.py
index 3feeacf0..96a606da 100644
--- a/core/src/trezor/messages.py
+++ b/core/src/trezor/messages.py
@@ -3369,12 +3369,14 @@ if TYPE_CHECKING:
class EthereumERC7730Path(protobuf.MessageType):
path: "list[int]"
container_path: "EthereumERC7730ContainerPath | None"
+ const_value: "str | None"
def __init__(
self,
*,
path: "list[int] | None" = None,
container_path: "EthereumERC7730ContainerPath | None" = None,
+ const_value: "str | None" = None,
) -> None:
pass
diff --git a/core/tests/test_apps.ethereum.clear_signing.py b/core/tests/test_apps.ethereum.clear_signing.py
index 352e3d84..9dd4c665 100644
--- a/core/tests/test_apps.ethereum.clear_signing.py
+++ b/core/tests/test_apps.ethereum.clear_signing.py
@@ -610,10 +610,48 @@ class TestEthereumClearSigning(unittest.TestCase):
self.assertEqual(parameters, [[10, 20, 30]])
self.assertEqual(len(fields), 1)
- (label, formatted, hint), token, token_address = fields[0]
+ (label, formatted, _), token, token_address = fields[0]
self.assertEqual(label, "Values")
self.assertEqual(formatted, "10\n20\n30")
- self.assertIsNone(hint)
+ self.assertIsNone(token)
+ self.assertIsNone(token_address)
+
+ # --- constant (non-calldata) value fields ---
+
+ def test_from_proto_const_value_path(self):
+ # A `const_value` path decodes to the literal string — a value source
+ # that is not walked from calldata.
+ info = EthereumERC7730FieldInfo(
+ path=EthereumERC7730Path(const_value="kmgcEURC"),
+ label="Share ticker",
+ formatter=FT.FORMATTER_RAW,
+ )
+ field = FieldDefinition.from_proto(info)
+ self.assertEqual(field.path, "kmgcEURC")
+ self.assertIsInstance(field.get_formatter(), RawFormatter)
+
+ def test_const_value_end_to_end(self):
+ # A field bound to a constant renders the literal as-is, without touching
+ # calldata (empty params, empty calldata).
+ display_format = DisplayFormat(
+ binding_context=None,
+ func_sig=b"\x00\x00\x00\x00",
+ intent="Test",
+ parameter_definitions=[],
+ field_definitions=[
+ FieldDefinition("kmgcEURC", "Share ticker", RawFormatter)
+ ],
+ )
+
+ parameters, fields = await_result(
+ display_format.parse_calldata(memoryview(b""), None, None)
+ )
+
+ self.assertEqual(parameters, [])
+ self.assertEqual(len(fields), 1)
+ (label, formatted, _), token, token_address = fields[0]
+ self.assertEqual(label, "Share ticker")
+ self.assertEqual(formatted, "kmgcEURC")
self.assertIsNone(token)
self.assertIsNone(token_address)
diff --git a/python/src/trezorlib/messages.py b/python/src/trezorlib/messages.py
index 8fd087c6..9d4fa717 100644
--- a/python/src/trezorlib/messages.py
+++ b/python/src/trezorlib/messages.py
@@ -4785,6 +4785,7 @@ class EthereumERC7730Path(protobuf.MessageType):
FIELDS = {
1: protobuf.Field("path", "sint32", repeated=True, required=False, default=None),
2: protobuf.Field("container_path", "EthereumERC7730ContainerPath", repeated=False, required=False, default=None),
+ 3: protobuf.Field("const_value", "string", repeated=False, required=False, default=None),
}
def __init__(
@@ -4792,9 +4793,11 @@ class EthereumERC7730Path(protobuf.MessageType):
*,
path: Optional[Sequence["int"]] = None,
container_path: Optional["EthereumERC7730ContainerPath"] = None,
+ const_value: Optional["str"] = None,
) -> None:
self.path: Sequence["int"] = path if path is not None else []
self.container_path = container_path
+ self.const_value = const_value
class EthereumERC7730FieldInfo(protobuf.MessageType):
diff --git a/rust/trezor-client/src/protos/generated/messages_definitions.rs b/rust/trezor-client/src/protos/generated/messages_definitions.rs
index 838752f9..869ca675 100644
--- a/rust/trezor-client/src/protos/generated/messages_definitions.rs
+++ b/rust/trezor-client/src/protos/generated/messages_definitions.rs
@@ -1360,6 +1360,8 @@ pub struct EthereumERC7730Path {
pub path: ::std::vec::Vec<i32>,
// @@protoc_insertion_point(field:hw.trezor.messages.definitions.EthereumERC7730Path.container_path)
pub container_path: ::std::option::Option<::protobuf::EnumOrUnknown<EthereumERC7730ContainerPath>>,
+ // @@protoc_insertion_point(field:hw.trezor.messages.definitions.EthereumERC7730Path.const_value)
+ pub const_value: ::std::option::Option<::std::string::String>,
// special fields
// @@protoc_insertion_point(special_field:hw.trezor.messages.definitions.EthereumERC7730Path.special_fields)
pub special_fields: ::protobuf::SpecialFields,
@@ -1398,8 +1400,44 @@ impl EthereumERC7730Path {
self.container_path = ::std::option::Option::Some(::protobuf::EnumOrUnknown::new(v));
}
+ // optional string const_value = 3;
+
+ pub fn const_value(&self) -> &str {
+ match self.const_value.as_ref() {
+ Some(v) => v,
+ None => "",
+ }
+ }
+
+ pub fn clear_const_value(&mut self) {
+ self.const_value = ::std::option::Option::None;
+ }
+
+ pub fn has_const_value(&self) -> bool {
+ self.const_value.is_some()
+ }
+
+ // Param is passed by value, moved
+ pub fn set_const_value(&mut self, v: ::std::string::String) {
+ self.const_value = ::std::option::Option::Some(v);
+ }
+
+ // Mutable pointer to the field.
+ // If field is not initialized, it is initialized with default value first.
+ pub fn mut_const_value(&mut self) -> &mut ::std::string::String {
+ if self.const_value.is_none() {
+ self.const_value = ::std::option::Option::Some(::std::string::String::new());
+ }
+ self.const_value.as_mut().unwrap()
+ }
+
+ // Take field
+ pub fn take_const_value(&mut self) -> ::std::string::String {
+ self.const_value.take().unwrap_or_else(|| ::std::string::String::new())
+ }
+
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
- let mut fields = ::std::vec::Vec::with_capacity(2);
+ let mut fields = ::std::vec::Vec::with_capacity(3);
let mut oneofs = ::std::vec::Vec::with_capacity(0);
fields.push(::protobuf::reflect::rt::v2::make_vec_simpler_accessor::<_, _>(
"path",
@@ -1411,6 +1449,11 @@ impl EthereumERC7730Path {
|m: &EthereumERC7730Path| { &m.container_path },
|m: &mut EthereumERC7730Path| { &mut m.container_path },
));
+ fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>(
+ "const_value",
+ |m: &EthereumERC7730Path| { &m.const_value },
+ |m: &mut EthereumERC7730Path| { &mut m.const_value },
+ ));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<EthereumERC7730Path>(
"EthereumERC7730Path",
fields,
@@ -1438,6 +1481,9 @@ impl ::protobuf::Message for EthereumERC7730Path {
16 => {
self.container_path = ::std::option::Option::Some(is.read_enum_or_unknown()?);
},
+ 26 => {
+ self.const_value = ::std::option::Option::Some(is.read_string()?);
+ },
tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
},
@@ -1456,6 +1502,9 @@ impl ::protobuf::Message for EthereumERC7730Path {
if let Some(v) = self.container_path {
my_size += ::protobuf::rt::int32_size(2, v.value());
}
+ if let Some(v) = self.const_value.as_ref() {
+ my_size += ::protobuf::rt::string_size(3, &v);
+ }
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
self.special_fields.cached_size().set(my_size as u32);
my_size
@@ -1468,6 +1517,9 @@ impl ::protobuf::Message for EthereumERC7730Path {
if let Some(v) = self.container_path {
os.write_enum(2, ::protobuf::EnumOrUnknown::value(&v))?;
}
+ if let Some(v) = self.const_value.as_ref() {
+ os.write_string(3, v)?;
+ }
os.write_unknown_fields(self.special_fields.unknown_fields())?;
::std::result::Result::Ok(())
}
@@ -1487,6 +1539,7 @@ impl ::protobuf::Message for EthereumERC7730Path {
fn clear(&mut self) {
self.path.clear();
self.container_path = ::std::option::Option::None;
+ self.const_value = ::std::option::Option::None;
self.special_fields.clear();
}
@@ -1494,6 +1547,7 @@ impl ::protobuf::Message for EthereumERC7730Path {
static instance: EthereumERC7730Path = EthereumERC7730Path {
path: ::std::vec::Vec::new(),
container_path: ::std::option::Option::None,
+ const_value: ::std::option::Option::None,
special_fields: ::protobuf::SpecialFields::new(),
};
&instance
@@ -2808,46 +2862,47 @@ static file_descriptor_proto_data: &'static [u8] = b"\
essages.definitions.EthereumABITypeR\x07dynamic\x12J\n\x05tuple\x18\x03\
\x20\x01(\x0b24.hw.trezor.messages.definitions.EthereumABITupleInfoR\x05\
tuple\x12J\n\x05array\x18\x04\x20\x01(\x0b24.hw.trezor.messages.definiti\
- ons.EthereumABIValueInfoR\x05array\"\x8e\x01\n\x13EthereumERC7730Path\
+ ons.EthereumABIValueInfoR\x05array\"\xaf\x01\n\x13EthereumERC7730Path\
\x12\x12\n\x04path\x18\x01\x20\x03(\x11R\x04path\x12c\n\x0econtainer_pat\
h\x18\x02\x20\x01(\x0e2<.hw.trezor.messages.definitions.EthereumERC7730C\
- ontainerPathR\rcontainerPath\"\xc4\x03\n\x18EthereumERC7730FieldInfo\x12\
- G\n\x04path\x18\x01\x20\x02(\x0b23.hw.trezor.messages.definitions.Ethere\
- umERC7730PathR\x04path\x12\x14\n\x05label\x18\x02\x20\x02(\tR\x05label\
- \x12_\n\tformatter\x18\x03\x20\x02(\x0e2A.hw.trezor.messages.definitions\
- .EthereumERC7730FieldFormatterTypeR\tformatter\x12R\n\ntoken_path\x18\
- \x04\x20\x01(\x0b23.hw.trezor.messages.definitions.EthereumERC7730PathR\
- \ttokenPath\x12\x1c\n\tthreshold\x18\x05\x20\x01(\x0cR\tthreshold\x12\
- \x1a\n\x08decimals\x18\x06\x20\x01(\rR\x08decimals\x12\x12\n\x04base\x18\
- \x07\x20\x01(\tR\x04base\x12\x16\n\x06prefix\x18\x08\x20\x01(\x08R\x06pr\
- efix\x12.\n\x13const_token_address\x18\t\x20\x01(\x0cR\x11constTokenAddr\
- ess\"\xd5\x02\n\x19EthereumDisplayFormatInfo\x12\x19\n\x08chain_id\x18\
- \x01\x20\x02(\x04R\x07chainId\x12\x18\n\x07address\x18\x02\x20\x02(\x0cR\
- \x07address\x12\x19\n\x08func_sig\x18\x03\x20\x02(\x0cR\x07funcSig\x12\
- \x16\n\x06intent\x18\x04\x20\x02(\tR\x06intent\x12i\n\x15parameter_defin\
- itions\x18\x05\x20\x03(\x0b24.hw.trezor.messages.definitions.EthereumABI\
- ValueInfoR\x14parameterDefinitions\x12e\n\x11field_definitions\x18\x06\
- \x20\x03(\x0b28.hw.trezor.messages.definitions.EthereumERC7730FieldInfoR\
- \x10fieldDefinitions*i\n\x0eDefinitionType\x12\x14\n\x10ETHEREUM_NETWORK\
- \x10\0\x12\x12\n\x0eETHEREUM_TOKEN\x10\x01\x12\x10\n\x0cSOLANA_TOKEN\x10\
- \x02\x12\x1b\n\x17ETHEREUM_DISPLAY_FORMAT\x10\x03*\x86\x03\n\x0fEthereum\
- ABIType\x12\x0f\n\x0bABI_ADDRESS\x10\0\x12\x0f\n\x0bABI_UINT256\x10\x01\
- \x12\x0f\n\x0bABI_UINT248\x10\x02\x12\x0f\n\x0bABI_UINT160\x10\x03\x12\
- \x0f\n\x0bABI_UINT128\x10\x04\x12\x0f\n\x0bABI_UINT120\x10\x05\x12\x0f\n\
- \x0bABI_UINT112\x10\x06\x12\x0e\n\nABI_UINT96\x10\x07\x12\x0e\n\nABI_UIN\
- T72\x10\x08\x12\x0e\n\nABI_UINT64\x10\t\x12\x0e\n\nABI_UINT48\x10\n\x12\
- \x0e\n\nABI_UINT40\x10\x0b\x12\x0e\n\nABI_UINT32\x10\x0c\x12\x0e\n\nABI_\
- UINT24\x10\r\x12\x0e\n\nABI_UINT16\x10\x0e\x12\r\n\tABI_UINT8\x10\x0f\
- \x12\x0c\n\x08ABI_BOOL\x10\x10\x12\x0f\n\x0bABI_BYTES32\x10\x14\x12\x0f\
- \n\x0bABI_BYTES16\x10\x15\x12\x0e\n\nABI_BYTES8\x10\x16\x12\x0e\n\nABI_B\
- YTES4\x10\x17\x12\r\n\tABI_BYTES\x10\x1e\x12\x0e\n\nABI_STRING\x10\x1f*\
- \xac\x01\n!EthereumERC7730FieldFormatterType\x12\x1a\n\x16FORMATTER_ADDR\
- ESS_NAME\x10\0\x12\x14\n\x10FORMATTER_AMOUNT\x10\x01\x12\x1a\n\x16FORMAT\
- TER_TOKEN_AMOUNT\x10\x02\x12\x12\n\x0eFORMATTER_UNIT\x10\x03\x12\x11\n\r\
- FORMATTER_RAW\x10\x04\x12\x12\n\x0eFORMATTER_DATE\x10\x05*;\n\x1cEthereu\
- mERC7730ContainerPath\x12\x08\n\x04FROM\x10\x01\x12\t\n\x05VALUE\x10\x02\
- \x12\x06\n\x02TO\x10\x03B?\n#com.satoshilabs.trezor.lib.protobufB\x18Tre\
- zorMessageDefinitions\
+ ontainerPathR\rcontainerPath\x12\x1f\n\x0bconst_value\x18\x03\x20\x01(\t\
+ R\nconstValue\"\xc4\x03\n\x18EthereumERC7730FieldInfo\x12G\n\x04path\x18\
+ \x01\x20\x02(\x0b23.hw.trezor.messages.definitions.EthereumERC7730PathR\
+ \x04path\x12\x14\n\x05label\x18\x02\x20\x02(\tR\x05label\x12_\n\tformatt\
+ er\x18\x03\x20\x02(\x0e2A.hw.trezor.messages.definitions.EthereumERC7730\
+ FieldFormatterTypeR\tformatter\x12R\n\ntoken_path\x18\x04\x20\x01(\x0b23\
+ .hw.trezor.messages.definitions.EthereumERC7730PathR\ttokenPath\x12\x1c\
+ \n\tthreshold\x18\x05\x20\x01(\x0cR\tthreshold\x12\x1a\n\x08decimals\x18\
+ \x06\x20\x01(\rR\x08decimals\x12\x12\n\x04base\x18\x07\x20\x01(\tR\x04ba\
+ se\x12\x16\n\x06prefix\x18\x08\x20\x01(\x08R\x06prefix\x12.\n\x13const_t\
+ oken_address\x18\t\x20\x01(\x0cR\x11constTokenAddress\"\xd5\x02\n\x19Eth\
+ ereumDisplayFormatInfo\x12\x19\n\x08chain_id\x18\x01\x20\x02(\x04R\x07ch\
+ ainId\x12\x18\n\x07address\x18\x02\x20\x02(\x0cR\x07address\x12\x19\n\
+ \x08func_sig\x18\x03\x20\x02(\x0cR\x07funcSig\x12\x16\n\x06intent\x18\
+ \x04\x20\x02(\tR\x06intent\x12i\n\x15parameter_definitions\x18\x05\x20\
+ \x03(\x0b24.hw.trezor.messages.definitions.EthereumABIValueInfoR\x14para\
+ meterDefinitions\x12e\n\x11field_definitions\x18\x06\x20\x03(\x0b28.hw.t\
+ rezor.messages.definitions.EthereumERC7730FieldInfoR\x10fieldDefinitions\
+ *i\n\x0eDefinitionType\x12\x14\n\x10ETHEREUM_NETWORK\x10\0\x12\x12\n\x0e\
+ ETHEREUM_TOKEN\x10\x01\x12\x10\n\x0cSOLANA_TOKEN\x10\x02\x12\x1b\n\x17ET\
+ HEREUM_DISPLAY_FORMAT\x10\x03*\x86\x03\n\x0fEthereumABIType\x12\x0f\n\
+ \x0bABI_ADDRESS\x10\0\x12\x0f\n\x0bABI_UINT256\x10\x01\x12\x0f\n\x0bABI_\
+ UINT248\x10\x02\x12\x0f\n\x0bABI_UINT160\x10\x03\x12\x0f\n\x0bABI_UINT12\
+ 8\x10\x04\x12\x0f\n\x0bABI_UINT120\x10\x05\x12\x0f\n\x0bABI_UINT112\x10\
+ \x06\x12\x0e\n\nABI_UINT96\x10\x07\x12\x0e\n\nABI_UINT72\x10\x08\x12\x0e\
+ \n\nABI_UINT64\x10\t\x12\x0e\n\nABI_UINT48\x10\n\x12\x0e\n\nABI_UINT40\
+ \x10\x0b\x12\x0e\n\nABI_UINT32\x10\x0c\x12\x0e\n\nABI_UINT24\x10\r\x12\
+ \x0e\n\nABI_UINT16\x10\x0e\x12\r\n\tABI_UINT8\x10\x0f\x12\x0c\n\x08ABI_B\
+ OOL\x10\x10\x12\x0f\n\x0bABI_BYTES32\x10\x14\x12\x0f\n\x0bABI_BYTES16\
+ \x10\x15\x12\x0e\n\nABI_BYTES8\x10\x16\x12\x0e\n\nABI_BYTES4\x10\x17\x12\
+ \r\n\tABI_BYTES\x10\x1e\x12\x0e\n\nABI_STRING\x10\x1f*\xac\x01\n!Ethereu\
+ mERC7730FieldFormatterType\x12\x1a\n\x16FORMATTER_ADDRESS_NAME\x10\0\x12\
+ \x14\n\x10FORMATTER_AMOUNT\x10\x01\x12\x1a\n\x16FORMATTER_TOKEN_AMOUNT\
+ \x10\x02\x12\x12\n\x0eFORMATTER_UNIT\x10\x03\x12\x11\n\rFORMATTER_RAW\
+ \x10\x04\x12\x12\n\x0eFORMATTER_DATE\x10\x05*;\n\x1cEthereumERC7730Conta\
+ inerPath\x12\x08\n\x04FROM\x10\x01\x12\t\n\x05VALUE\x10\x02\x12\x06\n\
+ \x02TO\x10\x03B?\n#com.satoshilabs.trezor.lib.protobufB\x18TrezorMessage\
+ Definitions\
";
/// `FileDescriptorProto` object which was a source for this generated file
Why this scored 27/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.