chore(ethereum): revert to single token up-front
What changed, and why it matters
This commit reverts an earlier design change in Trezor's Ethereum message handling. It changes the protocol so that only a single token definition can be passed up-front with a transaction, instead of a list of multiple tokens. The change is described as a routine cleanup ('chore') to restore a previous simpler design. There is no direct evidence in the commit that this fixes an active security bug, but it removes complexity that could in principle reduce the attack surface for malformed or conflicting token definitions.
Treat as a low-risk design cleanup. Reviewers may want to confirm that the single-token limit does not break legitimate multi-token workflows and that the removed multi-token tests are adequately replaced by single-token coverage. No urgent security response is indicated by the commit itself.
Security signals we found
Reduction of externally controlled input complexity (single token vs. list)
Removal of multi-token parsing loop in firmware
No explicit security claim or CVE reference in commit
No changelog entry, consistent with routine refactor
Tests updated to reflect single-token behavior, including removal of multi-token test cases
Evidence from the diff
The commit reverts the EthereumDefinitions protobuf message from a repeated encoded_tokens field back to a single optional encoded_token field. Corresponding changes are made across core firmware, legacy firmware, Python client, Rust client, and test suites. The firmware logic now only decodes and stores one externally supplied token, falling back to built-in definitions otherwise. The commit message frames this as a return to the pre-e059db59 design and explicitly marks it ‘[no changelog]’.
Changed components
common/protob/messages-ethereum.protocore/src/apps/ethereum/definitions.pycore/src/apps/ethereum/keychain.pycore/src/trezor/messages.pylegacy/firmware/ethereum_definitions.hlegacy/firmware/fsm_msg_ethereum.hlegacy/firmware/protob/messages-ethereum.optionspython/src/trezorlib/cli/ethereum.pypython/src/trezorlib/messages.pyrust/trezor-client/src/protos/generated/messages_ethereum.rstests/definitions.pytests/device_tests/ethereum/test_definitions.pytests/device_tests/ethereum/test_definitions_bad.pyInspect captured patch +103 / −94
diff --git a/common/protob/messages-ethereum.proto b/common/protob/messages-ethereum.proto
index 31c06c9e..44ad1c4f 100644
--- a/common/protob/messages-ethereum.proto
+++ b/common/protob/messages-ethereum.proto
@@ -187,11 +187,11 @@ message EthereumTypedDataSignature {
}
/**
- * Contains encoded network, tokens and ERC-7730 display format definitions. See external-definitions.md for details.
+ * Contains encoded network, token and ERC-7730 display format definitions. See external-definitions.md for details.
* @embed
*/
message EthereumDefinitions {
optional bytes encoded_network = 1; // encoded ethereum network
- repeated bytes encoded_tokens = 2; // encoded ethereum tokens
+ optional bytes encoded_token = 2; // encoded ethereum token
optional bytes encoded_erc7730_display_format = 3; // encoded ERC-7730 display format
}
diff --git a/core/src/apps/ethereum/definitions.py b/core/src/apps/ethereum/definitions.py
index 0fc92328..d106470c 100644
--- a/core/src/apps/ethereum/definitions.py
+++ b/core/src/apps/ethereum/definitions.py
@@ -24,7 +24,7 @@ class Definitions:
def from_encoded(
cls,
encoded_network: AnyBytes | None,
- encoded_tokens: list[AnyBytes],
+ encoded_token: AnyBytes | None,
chain_id: int | None = None,
slip44: int | None = None,
) -> Self:
@@ -56,10 +56,12 @@ class Definitions:
if slip44 is not None and network.slip44 != slip44:
raise DataError("Network definition mismatch")
- # get token definitions
- for encoded_token in encoded_tokens:
+ # get token definition
+ if encoded_token is not None:
token = decode_definition(encoded_token, EthereumTokenInfo)
# Ignore token if it doesn't match the network instead of raising an error.
+ # This might help us in the future if we allow multiple networks/tokens
+ # in the same message.
if token.chain_id == network.chain_id:
tokens[bytes(token.address)] = token
diff --git a/core/src/apps/ethereum/keychain.py b/core/src/apps/ethereum/keychain.py
index 0ad796a6..c59cc157 100644
--- a/core/src/apps/ethereum/keychain.py
+++ b/core/src/apps/ethereum/keychain.py
@@ -80,19 +80,19 @@ def _defs_from_message(
msg: Any, chain_id: int | None = None, slip44: int | None = None
) -> definitions.Definitions:
encoded_network = None
- encoded_tokens: list = []
+ encoded_token = None
# try to get both from msg.definitions
if hasattr(msg, "definitions"):
if msg.definitions is not None:
encoded_network = msg.definitions.encoded_network
- encoded_tokens = list(msg.definitions.encoded_tokens)
+ encoded_token = msg.definitions.encoded_token
elif hasattr(msg, "encoded_network"):
encoded_network = msg.encoded_network
return definitions.Definitions.from_encoded(
- encoded_network, encoded_tokens, chain_id, slip44
+ encoded_network, encoded_token, chain_id, slip44
)
diff --git a/core/src/trezor/messages.py b/core/src/trezor/messages.py
index e8a10800..dca3e154 100644
--- a/core/src/trezor/messages.py
+++ b/core/src/trezor/messages.py
@@ -4173,14 +4173,14 @@ if TYPE_CHECKING:
class EthereumDefinitions(protobuf.MessageType):
encoded_network: "AnyBytes | None"
- encoded_tokens: "list[AnyBytes]"
+ encoded_token: "AnyBytes | None"
encoded_erc7730_display_format: "AnyBytes | None"
def __init__(
self,
*,
- encoded_tokens: "list[AnyBytes] | None" = None,
encoded_network: "AnyBytes | None" = None,
+ encoded_token: "AnyBytes | None" = None,
encoded_erc7730_display_format: "AnyBytes | None" = None,
) -> None:
pass
diff --git a/core/tests/test_apps.ethereum.definitions.py b/core/tests/test_apps.ethereum.definitions.py
index 965ad689..1f191cb9 100644
--- a/core/tests/test_apps.ethereum.definitions.py
+++ b/core/tests/test_apps.ethereum.definitions.py
@@ -38,25 +38,25 @@ class TestEthereumDefinitions(unittest.TestCase):
def test_empty(self) -> None:
# no slip44 nor chain_id -- should short-circuit and always be unknown
- defs = Definitions.from_encoded(None, [])
+ defs = Definitions.from_encoded(None, None)
self.assertUnknown(defs.network)
self.assertFalse(defs._tokens)
self.assertUnknown(defs.get_token(TETHER_ADDRESS))
# chain_id provided, no definition
- defs = Definitions.from_encoded(None, [], chain_id=100_000)
+ defs = Definitions.from_encoded(None, None, chain_id=100_000)
self.assertUnknown(defs.network)
self.assertFalse(defs._tokens)
self.assertUnknown(defs.get_token(TETHER_ADDRESS))
def test_builtin(self) -> None:
- defs = Definitions.from_encoded(None, [], chain_id=1)
+ defs = Definitions.from_encoded(None, None, chain_id=1)
self.assertKnown(defs.network)
self.assertFalse(defs._tokens)
self.assertKnown(defs.get_token(TETHER_ADDRESS))
self.assertUnknown(defs.get_token(b"\x00" * 20))
- defs = Definitions.from_encoded(None, [], slip44=60)
+ defs = Definitions.from_encoded(None, None, slip44=60)
self.assertKnown(defs.network)
self.assertFalse(defs._tokens)
self.assertKnown(defs.get_token(TETHER_ADDRESS))
@@ -64,38 +64,27 @@ class TestEthereumDefinitions(unittest.TestCase):
def test_external(self) -> None:
network = make_eth_network(chain_id=42)
- defs = Definitions.from_encoded(encode_eth_network(network), [], chain_id=42)
+ defs = Definitions.from_encoded(encode_eth_network(network), None, chain_id=42)
self.assertEqual(defs.network, network)
self.assertUnknown(defs.get_token(b"\x00" * 20))
token = make_eth_token(chain_id=42, address=b"\x00" * 20)
defs = Definitions.from_encoded(
- encode_eth_network(network), [encode_eth_token(token)], chain_id=42
+ encode_eth_network(network), encode_eth_token(token), chain_id=42
)
self.assertEqual(defs.network, network)
self.assertEqual(defs.get_token(b"\x00" * 20), token)
token = make_eth_token(chain_id=1, address=b"\x00" * 20)
- defs = Definitions.from_encoded(None, [encode_eth_token(token)], chain_id=1)
+ defs = Definitions.from_encoded(None, encode_eth_token(token), chain_id=1)
self.assertKnown(defs.network)
self.assertEqual(defs.get_token(b"\x00" * 20), token)
- token_a = make_eth_token(chain_id=42, address=b"\xaa" * 20)
- token_b = make_eth_token(chain_id=42, address=b"\xbb" * 20)
- defs = Definitions.from_encoded(
- encode_eth_network(network),
- [encode_eth_token(token_a), encode_eth_token(token_b)],
- chain_id=42,
- )
- self.assertEqual(defs.network, network)
- self.assertEqual(defs.get_token(b"\xaa" * 20), token_a)
- self.assertEqual(defs.get_token(b"\xbb" * 20), token_b)
-
def test_external_token_mismatch(self) -> None:
network = make_eth_network(chain_id=42)
token = make_eth_token(chain_id=43, address=b"\x00" * 20)
defs = Definitions.from_encoded(
- encode_eth_network(network), [encode_eth_token(token)]
+ encode_eth_network(network), encode_eth_token(token)
)
self.assertUnknown(defs.get_token(b"\x00" * 20))
@@ -103,50 +92,50 @@ class TestEthereumDefinitions(unittest.TestCase):
network = make_eth_network(chain_id=42)
token = make_eth_token(chain_id=42, address=b"\x00" * 20)
defs = Definitions.from_encoded(
- encode_eth_network(network), [encode_eth_token(token)], chain_id=42
+ encode_eth_network(network), encode_eth_token(token), chain_id=42
)
self.assertEqual(defs.network, network)
self.assertEqual(defs.get_token(b"\x00" * 20), token)
with self.assertRaises(wire.DataError):
Definitions.from_encoded(
- encode_eth_network(network), [encode_eth_token(token)], chain_id=333
+ encode_eth_network(network), encode_eth_token(token), chain_id=333
)
def test_external_slip44_mismatch(self) -> None:
network = make_eth_network(chain_id=42, slip44=1999)
token = make_eth_token(chain_id=42, address=b"\x00" * 20)
defs = Definitions.from_encoded(
- encode_eth_network(network), [encode_eth_token(token)], slip44=1999
+ encode_eth_network(network), encode_eth_token(token), slip44=1999
)
self.assertEqual(defs.network, network)
self.assertEqual(defs.get_token(b"\x00" * 20), token)
with self.assertRaises(wire.DataError):
Definitions.from_encoded(
- encode_eth_network(network), [encode_eth_token(token)], slip44=333
+ encode_eth_network(network), encode_eth_token(token), slip44=333
)
def test_ignore_encoded_network(self) -> None:
# when network is builtin, ignore the encoded one
network = encode_eth_network(chain_id=1, symbol="BAD")
- defs = Definitions.from_encoded(network, [], chain_id=1)
+ defs = Definitions.from_encoded(network, None, chain_id=1)
self.assertNotEqual(defs.network, network)
def test_ignore_encoded_token(self) -> None:
# when token is builtin, ignore the encoded one
token = encode_eth_token(chain_id=1, address=TETHER_ADDRESS, symbol="BAD")
- defs = Definitions.from_encoded(None, [token], chain_id=1)
+ defs = Definitions.from_encoded(None, token, chain_id=1)
self.assertNotEqual(defs.get_token(TETHER_ADDRESS), token)
def test_ignore_with_no_match(self) -> None:
network = encode_eth_network(chain_id=100_000, symbol="BAD")
# smoke test: definition is accepted
- defs = Definitions.from_encoded(network, [], chain_id=100_000)
+ defs = Definitions.from_encoded(network, None, chain_id=100_000)
self.assertKnown(defs.network)
# same definition but nothing to match it to
- defs = Definitions.from_encoded(network, [])
+ defs = Definitions.from_encoded(network, None)
self.assertUnknown(defs.network)
diff --git a/legacy/firmware/ethereum_definitions.h b/legacy/firmware/ethereum_definitions.h
index f5aa6c78..7b92964a 100644
--- a/legacy/firmware/ethereum_definitions.h
+++ b/legacy/firmware/ethereum_definitions.h
@@ -24,7 +24,7 @@
#include "messages-ethereum.pb.h"
typedef EthereumDefinitions_encoded_network_t EncodedNetwork;
-typedef EthereumDefinitions_encoded_tokens_t EncodedToken;
+typedef EthereumDefinitions_encoded_token_t EncodedToken;
typedef struct {
const EthereumNetworkInfo *network;
diff --git a/legacy/firmware/fsm_msg_ethereum.h b/legacy/firmware/fsm_msg_ethereum.h
index 811f8666..bbb26a53 100644
--- a/legacy/firmware/fsm_msg_ethereum.h
+++ b/legacy/firmware/fsm_msg_ethereum.h
@@ -41,8 +41,8 @@ static const EthereumDefinitionsDecoded *get_definitions(
if (definitions->has_encoded_network) {
encoded_network = &definitions->encoded_network;
}
- if (definitions->encoded_tokens_count > 0) {
- encoded_token = &definitions->encoded_tokens[0];
+ if (definitions->has_encoded_token) {
+ encoded_token = &definitions->encoded_token;
}
}
diff --git a/legacy/firmware/protob/messages-ethereum.options b/legacy/firmware/protob/messages-ethereum.options
index 3e3a8271..c4d119fd 100644
--- a/legacy/firmware/protob/messages-ethereum.options
+++ b/legacy/firmware/protob/messages-ethereum.options
@@ -56,5 +56,5 @@ EthereumAddress.mac type:FT_IGNORE
EthereumPublicKey.xpub max_size:113
EthereumDefinitions.encoded_network max_size:1024
-EthereumDefinitions.encoded_tokens max_count:1 max_size:1024
+EthereumDefinitions.encoded_token max_size:1024
EthereumDefinitions.encoded_erc7730_display_format type:FT_IGNORE
diff --git a/python/src/trezorlib/cli/ethereum.py b/python/src/trezorlib/cli/ethereum.py
index d8dbf21b..478d3a87 100644
--- a/python/src/trezorlib/cli/ethereum.py
+++ b/python/src/trezorlib/cli/ethereum.py
@@ -453,7 +453,7 @@ def sign_tx(
defs = EthereumDefinitions(
encoded_network=encoded_network,
- encoded_tokens=[encoded_token] if encoded_token is not None else [],
+ encoded_token=encoded_token,
)
if is_eip1559:
diff --git a/python/src/trezorlib/messages.py b/python/src/trezorlib/messages.py
index d59e30ec..661daa8a 100644
--- a/python/src/trezorlib/messages.py
+++ b/python/src/trezorlib/messages.py
@@ -5718,19 +5718,19 @@ class EthereumDefinitions(protobuf.MessageType):
MESSAGE_WIRE_TYPE = None
FIELDS = {
1: protobuf.Field("encoded_network", "bytes", repeated=False, required=False, default=None),
- 2: protobuf.Field("encoded_tokens", "bytes", repeated=True, required=False, default=None),
+ 2: protobuf.Field("encoded_token", "bytes", repeated=False, required=False, default=None),
3: protobuf.Field("encoded_erc7730_display_format", "bytes", repeated=False, required=False, default=None),
}
def __init__(
self,
*,
- encoded_tokens: Optional[Sequence["bytes"]] = None,
encoded_network: Optional["bytes"] = None,
+ encoded_token: Optional["bytes"] = None,
encoded_erc7730_display_format: Optional["bytes"] = None,
) -> None:
- self.encoded_tokens: Sequence["bytes"] = encoded_tokens if encoded_tokens is not None else []
self.encoded_network = encoded_network
+ self.encoded_token = encoded_token
self.encoded_erc7730_display_format = encoded_erc7730_display_format
diff --git a/rust/trezor-client/src/protos/generated/messages_ethereum.rs b/rust/trezor-client/src/protos/generated/messages_ethereum.rs
index 21e98976..85360b6e 100644
--- a/rust/trezor-client/src/protos/generated/messages_ethereum.rs
+++ b/rust/trezor-client/src/protos/generated/messages_ethereum.rs
@@ -4200,8 +4200,8 @@ pub struct EthereumDefinitions {
// message fields
// @@protoc_insertion_point(field:hw.trezor.messages.ethereum.EthereumDefinitions.encoded_network)
pub encoded_network: ::std::option::Option<::std::vec::Vec<u8>>,
- // @@protoc_insertion_point(field:hw.trezor.messages.ethereum.EthereumDefinitions.encoded_tokens)
- pub encoded_tokens: ::std::vec::Vec<::std::vec::Vec<u8>>,
+ // @@protoc_insertion_point(field:hw.trezor.messages.ethereum.EthereumDefinitions.encoded_token)
+ pub encoded_token: ::std::option::Option<::std::vec::Vec<u8>>,
// @@protoc_insertion_point(field:hw.trezor.messages.ethereum.EthereumDefinitions.encoded_erc7730_display_format)
pub encoded_erc7730_display_format: ::std::option::Option<::std::vec::Vec<u8>>,
// special fields
@@ -4256,6 +4256,42 @@ impl EthereumDefinitions {
self.encoded_network.take().unwrap_or_else(|| ::std::vec::Vec::new())
}
+ // optional bytes encoded_token = 2;
+
+ pub fn encoded_token(&self) -> &[u8] {
+ match self.encoded_token.as_ref() {
+ Some(v) => v,
+ None => &[],
+ }
+ }
+
+ pub fn clear_encoded_token(&mut self) {
+ self.encoded_token = ::std::option::Option::None;
+ }
+
+ pub fn has_encoded_token(&self) -> bool {
+ self.encoded_token.is_some()
+ }
+
+ // Param is passed by value, moved
+ pub fn set_encoded_token(&mut self, v: ::std::vec::Vec<u8>) {
+ self.encoded_token = ::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_encoded_token(&mut self) -> &mut ::std::vec::Vec<u8> {
+ if self.encoded_token.is_none() {
+ self.encoded_token = ::std::option::Option::Some(::std::vec::Vec::new());
+ }
+ self.encoded_token.as_mut().unwrap()
+ }
+
+ // Take field
+ pub fn take_encoded_token(&mut self) -> ::std::vec::Vec<u8> {
+ self.encoded_token.take().unwrap_or_else(|| ::std::vec::Vec::new())
+ }
+
// optional bytes encoded_erc7730_display_format = 3;
pub fn encoded_erc7730_display_format(&self) -> &[u8] {
@@ -4300,10 +4336,10 @@ impl EthereumDefinitions {
|m: &EthereumDefinitions| { &m.encoded_network },
|m: &mut EthereumDefinitions| { &mut m.encoded_network },
));
- fields.push(::protobuf::reflect::rt::v2::make_vec_simpler_accessor::<_, _>(
- "encoded_tokens",
- |m: &EthereumDefinitions| { &m.encoded_tokens },
- |m: &mut EthereumDefinitions| { &mut m.encoded_tokens },
+ fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>(
+ "encoded_token",
+ |m: &EthereumDefinitions| { &m.encoded_token },
+ |m: &mut EthereumDefinitions| { &mut m.encoded_token },
));
fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>(
"encoded_erc7730_display_format",
@@ -4332,7 +4368,7 @@ impl ::protobuf::Message for EthereumDefinitions {
self.encoded_network = ::std::option::Option::Some(is.read_bytes()?);
},
18 => {
- self.encoded_tokens.push(is.read_bytes()?);
+ self.encoded_token = ::std::option::Option::Some(is.read_bytes()?);
},
26 => {
self.encoded_erc7730_display_format = ::std::option::Option::Some(is.read_bytes()?);
@@ -4352,9 +4388,9 @@ impl ::protobuf::Message for EthereumDefinitions {
if let Some(v) = self.encoded_network.as_ref() {
my_size += ::protobuf::rt::bytes_size(1, &v);
}
- for value in &self.encoded_tokens {
- my_size += ::protobuf::rt::bytes_size(2, &value);
- };
+ if let Some(v) = self.encoded_token.as_ref() {
+ my_size += ::protobuf::rt::bytes_size(2, &v);
+ }
if let Some(v) = self.encoded_erc7730_display_format.as_ref() {
my_size += ::protobuf::rt::bytes_size(3, &v);
}
@@ -4367,9 +4403,9 @@ impl ::protobuf::Message for EthereumDefinitions {
if let Some(v) = self.encoded_network.as_ref() {
os.write_bytes(1, v)?;
}
- for v in &self.encoded_tokens {
- os.write_bytes(2, &v)?;
- };
+ if let Some(v) = self.encoded_token.as_ref() {
+ os.write_bytes(2, v)?;
+ }
if let Some(v) = self.encoded_erc7730_display_format.as_ref() {
os.write_bytes(3, v)?;
}
@@ -4391,7 +4427,7 @@ impl ::protobuf::Message for EthereumDefinitions {
fn clear(&mut self) {
self.encoded_network = ::std::option::Option::None;
- self.encoded_tokens.clear();
+ self.encoded_token = ::std::option::Option::None;
self.encoded_erc7730_display_format = ::std::option::Option::None;
self.special_fields.clear();
}
@@ -4399,7 +4435,7 @@ impl ::protobuf::Message for EthereumDefinitions {
fn default_instance() -> &'static EthereumDefinitions {
static instance: EthereumDefinitions = EthereumDefinitions {
encoded_network: ::std::option::Option::None,
- encoded_tokens: ::std::vec::Vec::new(),
+ encoded_token: ::std::option::Option::None,
encoded_erc7730_display_format: ::std::option::Option::None,
special_fields: ::protobuf::SpecialFields::new(),
};
@@ -4484,9 +4520,9 @@ static file_descriptor_proto_data: &'static [u8] = b"\
\x12!\n\x0cmessage_hash\x18\x03\x20\x01(\x0cR\x0bmessageHash\x12'\n\x0fe\
ncoded_network\x18\x04\x20\x01(\x0cR\x0eencodedNetwork\"T\n\x1aEthereumT\
ypedDataSignature\x12\x1c\n\tsignature\x18\x01\x20\x02(\x0cR\tsignature\
- \x12\x18\n\x07address\x18\x02\x20\x02(\tR\x07address\"\xaa\x01\n\x13Ethe\
+ \x12\x18\n\x07address\x18\x02\x20\x02(\tR\x07address\"\xa8\x01\n\x13Ethe\
reumDefinitions\x12'\n\x0fencoded_network\x18\x01\x20\x01(\x0cR\x0eencod\
- edNetwork\x12%\n\x0eencoded_tokens\x18\x02\x20\x03(\x0cR\rencodedTokens\
+ edNetwork\x12#\n\rencoded_token\x18\x02\x20\x01(\x0cR\x0cencodedToken\
\x12C\n\x1eencoded_erc7730_display_format\x18\x03\x20\x01(\x0cR\x1bencod\
edErc7730DisplayFormatB<\n#com.satoshilabs.trezor.lib.protobufB\x15Trezo\
rMessageEthereum\
diff --git a/tests/definitions.py b/tests/definitions.py
index 4746ffbc..8d711da3 100644
--- a/tests/definitions.py
+++ b/tests/definitions.py
@@ -129,7 +129,7 @@ def make_eth_defs(
) -> messages.EthereumDefinitions:
return messages.EthereumDefinitions(
encoded_network=network,
- encoded_tokens=[token] if token is not None else [],
+ encoded_token=token,
)
diff --git a/tests/device_tests/ethereum/test_definitions.py b/tests/device_tests/ethereum/test_definitions.py
index f7800bdf..349429e1 100644
--- a/tests/device_tests/ethereum/test_definitions.py
+++ b/tests/device_tests/ethereum/test_definitions.py
@@ -421,7 +421,7 @@ UNISWAP_EXACT_INPUT_SINGLE_DISPLAY_FORMAT_LABELS = {
def _sign_tx_with_display_format(
session: Session,
display_format: messages.EthereumERC7730DisplayFormatInfo,
- tokens: list[dict] | None = None,
+ token: dict | None = None,
sign_tx_params: dict | None = None,
on_page: Callable[[LayoutContent], None] | None = None,
) -> None:
@@ -439,10 +439,8 @@ def _sign_tx_with_display_format(
encoded_erc7730_display_format=definitions.encode_eth_erc7730_display_format(
display_format
),
- encoded_tokens=(
- [definitions.encode_eth_token(**t) for t in tokens]
- if tokens is not None
- else []
+ encoded_token=(
+ definitions.encode_eth_token(**token) if token is not None else None
),
),
)
@@ -482,49 +480,32 @@ def test_clear_signing_with_definition_and_token(session: Session) -> None:
_sign_tx_with_display_format(
session,
UNISWAP_EXACT_INPUT_SINGLE_DISPLAY_FORMAT,
- tokens=[WETH_TOKEN_DEFINITION],
+ token=WETH_TOKEN_DEFINITION,
on_page=on_page,
)
assert_all_seen()
@pytest.mark.models("core")
-def test_clear_signing_with_definition_and_both_tokens(session: Session) -> None:
- # With both WETH (tokenIn) and USDT (tokenOut) provided.
+def test_clear_signing_builtin_token_no_override(session: Session) -> None:
+ # With USDT (tokenOut) provided as encoded_token.
# Note however that we still render it as "USDT" (built in token)
# rather than "FAKE USDT"!
on_page, assert_all_seen = _make_label_checker(
- expected=UNISWAP_EXACT_INPUT_SINGLE_DISPLAY_FORMAT_LABELS,
- absent={"FAKE USDT", "UNKN"},
+ expected=UNISWAP_EXACT_INPUT_SINGLE_DISPLAY_FORMAT_LABELS | {"UNKN"},
+ absent={"FAKE USDT"},
)
_sign_tx_with_display_format(
session,
UNISWAP_EXACT_INPUT_SINGLE_DISPLAY_FORMAT,
- tokens=[WETH_TOKEN_DEFINITION, USDT_TOKEN_DEFINITION],
+ token=USDT_TOKEN_DEFINITION,
on_page=on_page,
)
assert_all_seen()
@pytest.mark.models("core")
-def test_clear_signing_weth_weth2_with_both_tokens(session: Session) -> None:
- # With both WETH (tokenIn) and WETH2 (tokenOut) provided, both amounts are resolved.
- on_page, assert_all_seen = _make_label_checker(
- expected=(UNISWAP_EXACT_INPUT_SINGLE_DISPLAY_FORMAT_LABELS | {"WETH2"}),
- absent={"USDT", "UNKN"},
- )
- _sign_tx_with_display_format(
- session,
- UNISWAP_EXACT_INPUT_SINGLE_DISPLAY_FORMAT,
- tokens=[WETH_TOKEN_DEFINITION, WETH2_TOKEN_DEFINITION],
- sign_tx_params=get_clear_signing_sign_tx_params(UNISWAP_WETH_WETH2_CALLDATA),
- on_page=on_page,
- )
- assert_all_seen()
-
-
-@pytest.mark.models("core")
-def test_clear_signing_weth_weth2_without_tokens(session: Session) -> None:
+def test_clear_signing_without_token(session: Session) -> None:
# Without token definitions, amounts are shown as UNKNOWN tokens.
on_page, assert_all_seen = _make_label_checker(
expected=(UNISWAP_EXACT_INPUT_SINGLE_DISPLAY_FORMAT_LABELS | {"UNKN"}),
@@ -541,7 +522,8 @@ def test_clear_signing_weth_weth2_without_tokens(session: Session) -> None:
@pytest.mark.models("core")
def test_clear_signing_with_definition_without_token(session: Session) -> None:
- # Without a token definition, amounts are shown as UNKNOWN token.
+ # Without a token definition, amounts are shown as UNKNOWN token
+ # (but builtin USDT is resolved).
on_page, assert_all_seen = _make_label_checker(
expected=(UNISWAP_EXACT_INPUT_SINGLE_DISPLAY_FORMAT_LABELS | {"UNKN", "USDT"}),
absent={"WETH"},
diff --git a/tests/device_tests/ethereum/test_definitions_bad.py b/tests/device_tests/ethereum/test_definitions_bad.py
index 9c69d0e7..794fdeb0 100644
--- a/tests/device_tests/ethereum/test_definitions_bad.py
+++ b/tests/device_tests/ethereum/test_definitions_bad.py
@@ -43,7 +43,7 @@ def _fails_token(session: Session, token: bytes, match: str) -> None:
ethereum.sign_tx(
session,
**params,
- definitions=messages.EthereumDefinitions(encoded_tokens=[token]),
+ definitions=messages.EthereumDefinitions(encoded_token=token),
)
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.