feat(tests,ethereum): clear signing definitions
What changed, and why it matters
This commit only adds and updates automated tests for Trezor's Ethereum 'clear signing' feature (ERC-7730 display formats). It does not change the firmware's security logic, so it is not a security patch. The tests verify that malformed or mismatched definitions are rejected, which is a normal defensive testing activity.
No action required; this is a test-only commit. Continue normal review of the related firmware clear-signing implementation separately if desired.
Security signals we found
Adds negative tests for invalid ERC-7730 definition signatures and malformed payloads
Adds positive tests for clear signing with token amount formatting
No changes to firmware parsing, validation, or signing code
Evidence from the diff
The diff extends test helpers in tests/definitions.py to build and sign EthereumERC7730DisplayFormatInfo payloads, and adds device tests in tests/device_tests/ethereum/test_definitions.py and test_definitions_bad.py. It exercises valid clear-signing flows, token resolution, and negative cases (bad signatures, type mismatches, malformed protobuf, outdated timestamps). No firmware or production code is modified.
Changed components
tests/definitions.pytests/device_tests/ethereum/test_definitions.pytests/device_tests/ethereum/test_definitions_bad.pyInspect captured patch +454 / −70
diff --git a/tests/definitions.py b/tests/definitions.py
index 2a52df43..4746ffbc 100644
--- a/tests/definitions.py
+++ b/tests/definitions.py
@@ -46,6 +46,7 @@ def make_payload(
messages.EthereumNetworkInfo
| messages.EthereumTokenInfo
| messages.SolanaTokenInfo
+ | messages.EthereumERC7730DisplayFormatInfo
| bytes
) = make_eth_network(),
) -> bytes:
@@ -157,3 +158,38 @@ def encode_solana_token(
)
proof, signature = sign_payload(payload, [])
return payload + proof + signature
+
+
+def make_eth_erc7730_display_format(
+ chain_id: int = 0,
+ address: t.AnyStr = b"",
+ func_sig: bytes = b"",
+ intent: str = "Fake intent",
+ parameter_definitions: list[messages.EthereumABIValueInfo] | None = None,
+ field_definitions: list[messages.EthereumERC7730FieldInfo] | None = None,
+) -> messages.EthereumERC7730DisplayFormatInfo:
+ if isinstance(address, str):
+ if address.startswith("0x"):
+ address = address[2:]
+ address_bytes = bytes.fromhex(address)
+ else:
+ address_bytes = address
+ return messages.EthereumERC7730DisplayFormatInfo(
+ chain_id=chain_id,
+ address=address_bytes,
+ func_sig=func_sig,
+ intent=intent,
+ parameter_definitions=parameter_definitions or [],
+ field_definitions=field_definitions or [],
+ )
+
+
+def encode_eth_erc7730_display_format(
+ display_format: messages.EthereumERC7730DisplayFormatInfo,
+) -> bytes:
+ payload = make_payload(
+ data_type=messages.DefinitionType.ETHEREUM_ERC7730_DISPLAY_FORMAT,
+ message=display_format,
+ )
+ proof, signature = sign_payload(payload, [])
+ return payload + proof + signature
diff --git a/tests/device_tests/ethereum/test_definitions.py b/tests/device_tests/ethereum/test_definitions.py
index d48ac519..7a17a3ac 100644
--- a/tests/device_tests/ethereum/test_definitions.py
+++ b/tests/device_tests/ethereum/test_definitions.py
@@ -4,7 +4,7 @@ from typing import Callable
import pytest
-from trezorlib import ethereum
+from trezorlib import ethereum, messages
from trezorlib.debuglink import DebugSession as Session
from trezorlib.exceptions import TrezorFailure
from trezorlib.tools import parse_path
@@ -268,3 +268,254 @@ def test_method_external_mismatch(session: Session, method: MethodType) -> None:
network = definitions.encode_eth_network(slip44=77777)
with pytest.raises(TrezorFailure, match="Network definition mismatch"):
method(session, 66666, network)
+
+
+# ERC-7730 clear signing tests
+# These require core models and a transaction that triggers the clear signing path.
+
+# Uniswap V3 SwapRouter02 on Ethereum mainnet
+UNISWAP_V3_ROUTER2 = "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45"
+
+FUNC_SIG_FAKE_STR = "11111111"
+FUNC_SIG_FAKE = bytes.fromhex(FUNC_SIG_FAKE_STR)
+
+# `exactInputSingle((address,address,uint24,address,uint256,uint256,uint160))`
+# Inspired from https://etherscan.io/tx/0xebe95b6b3222b9eacbf40a02947ebbc83761ee526879d0ba99fd46f54217e5db
+# but set `amountOutMinimum` to a non-zero value and using another func_sig.
+UNISWAP_EXACT_INPUT_SINGLE_CALLDATA = bytes.fromhex(
+ FUNC_SIG_FAKE_STR
+ + "000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" # tokenIn: WETH
+ + "000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7" # tokenOut: USDT
+ + "0000000000000000000000000000000000000000000000000000000000000bb8" # fee: 3000
+ + "00000000000000000000000051117eb63623aee74a39b63bd9efa3a728800dbb" # recipient
+ + "000000000000000000000000000000000000000000000000002386f26fc10000" # amountIn
+ + "0000000000000000000000000000000000000000000000000000000000000010" # amountOutMinimum
+ + "0000000000000000000000000000000000000000000000000000000000000000" # sqrtPriceLimitX96
+)
+
+# WETH on Ethereum mainnet needed by TokenAmountFormatter to display amounts.
+WETH_TOKEN_DEFINITION = {
+ "address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
+ "chain_id": 1,
+ "symbol": "FAKE WETH",
+ "decimals": 18,
+ "name": "FAKE Wrapped Ether",
+}
+
+# USDT on Ethereum mainnet (tokenOut in the Uniswap WETH/USDT swap calldata).
+USDT_TOKEN_DEFINITION = {
+ "address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
+ "chain_id": 1,
+ "symbol": "FAKE USDT",
+ "decimals": 6,
+ "name": "FAKE Tether USD",
+}
+
+# Fake second WETH variant (tokenOut in the Uniswap WETH/WETH2 swap calldata).
+WETH2_TOKEN_DEFINITION = {
+ "address": "0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+ "chain_id": 1,
+ "symbol": "FAKE WETH2",
+ "decimals": 18,
+ "name": "FAKE Wrapped Ether 2",
+}
+
+UNISWAP_WETH_WETH2_CALLDATA = bytes.fromhex(
+ FUNC_SIG_FAKE_STR
+ + "000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" # tokenIn: WETH
+ + "000000000000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" # tokenOut: WETH2
+ + "0000000000000000000000000000000000000000000000000000000000000bb8" # fee: 3000
+ + "00000000000000000000000051117eb63623aee74a39b63bd9efa3a728800dbb" # recipient
+ + "000000000000000000000000000000000000000000000000002386f26fc10000" # amountIn
+ + "0000000000000000000000000000000000000000000000000000000000000010" # amountOutMinimum
+ + "0000000000000000000000000000000000000000000000000000000000000000" # sqrtPriceLimitX96
+)
+
+
+def get_clear_signing_sign_tx_params(
+ data: bytes = UNISWAP_EXACT_INPUT_SINGLE_CALLDATA,
+) -> dict:
+ return dict(
+ n=parse_path("m/44h/60h/0h/0/1"),
+ nonce=0x0,
+ gas_price=0x14,
+ gas_limit=0x14,
+ to=UNISWAP_V3_ROUTER2,
+ value=0x0,
+ data=data,
+ chain_id=1,
+ )
+
+
+# ERC-7730 display format for Uniswap V3 `exactInputSingle`.
+# `exactInputSingle` takes one struct parameter with 7 fields.
+UNISWAP_EXACT_INPUT_SINGLE_DISPLAY_FORMAT = definitions.make_eth_erc7730_display_format(
+ chain_id=1,
+ address=UNISWAP_V3_ROUTER2,
+ func_sig=FUNC_SIG_FAKE,
+ parameter_definitions=[
+ messages.EthereumABIValueInfo(
+ tuple=messages.EthereumABITupleInfo(
+ fields=[
+ messages.EthereumABIValueInfo(
+ atomic=messages.EthereumABIType.ABI_ADDRESS
+ ), # tokenIn
+ messages.EthereumABIValueInfo(
+ atomic=messages.EthereumABIType.ABI_ADDRESS
+ ), # tokenOut
+ messages.EthereumABIValueInfo(
+ atomic=messages.EthereumABIType.ABI_UINT24
+ ), # fee
+ messages.EthereumABIValueInfo(
+ atomic=messages.EthereumABIType.ABI_ADDRESS
+ ), # recipient
+ messages.EthereumABIValueInfo(
+ atomic=messages.EthereumABIType.ABI_UINT256
+ ), # amountIn
+ messages.EthereumABIValueInfo(
+ atomic=messages.EthereumABIType.ABI_UINT256
+ ), # amountOutMinimum
+ messages.EthereumABIValueInfo(
+ atomic=messages.EthereumABIType.ABI_UINT160
+ ), # sqrtPriceLimitX96
+ ],
+ is_dynamic=False,
+ )
+ )
+ ],
+ field_definitions=[
+ messages.EthereumERC7730FieldInfo(
+ path=messages.EthereumERC7730Path(path=[0, 4]),
+ label="FAKE Amount",
+ token_path=messages.EthereumERC7730Path(path=[0, 0]),
+ formatter=messages.EthereumERC7730FieldFormatterType.FORMATTER_TOKEN_AMOUNT,
+ ),
+ messages.EthereumERC7730FieldInfo(
+ path=messages.EthereumERC7730Path(path=[0, 5]),
+ label="FAKE Minimum to Receive",
+ token_path=messages.EthereumERC7730Path(path=[0, 1]),
+ formatter=messages.EthereumERC7730FieldFormatterType.FORMATTER_TOKEN_AMOUNT,
+ ),
+ messages.EthereumERC7730FieldInfo(
+ path=messages.EthereumERC7730Path(path=[0, 2]),
+ label="FAKE fee",
+ formatter=messages.EthereumERC7730FieldFormatterType.FORMATTER_UNIT,
+ ),
+ messages.EthereumERC7730FieldInfo(
+ path=messages.EthereumERC7730Path(path=[0, 3]),
+ label="FAKE recipient",
+ decimals=4,
+ base="%",
+ prefix=False,
+ formatter=messages.EthereumERC7730FieldFormatterType.FORMATTER_ADDRESS_NAME,
+ ),
+ ],
+)
+
+
+def _sign_tx_with_display_format(
+ session: Session,
+ display_format: messages.EthereumERC7730DisplayFormatInfo,
+ tokens: list[dict] | None = None,
+ sign_tx_params: dict | None = None,
+) -> None:
+ if sign_tx_params is None:
+ sign_tx_params = get_clear_signing_sign_tx_params()
+ with session.test_ctx as client:
+ if not session.debug.legacy_debug:
+ client.set_input_flow(InputFlowConfirmAllWarnings(session).get())
+ ethereum.sign_tx(
+ session,
+ **sign_tx_params,
+ definitions=messages.EthereumDefinitions(
+ 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 []
+ ),
+ ),
+ )
+
+
+@pytest.mark.models("core")
+def test_clear_signing_with_definition_and_token(session: Session) -> None:
+ # With WETH provided, TokenAmountFormatter can resolve the token symbol.
+ _sign_tx_with_display_format(
+ session,
+ UNISWAP_EXACT_INPUT_SINGLE_DISPLAY_FORMAT,
+ tokens=[WETH_TOKEN_DEFINITION],
+ )
+
+
+@pytest.mark.models("core")
+def test_clear_signing_with_definition_and_both_tokens(session: Session) -> None:
+ # With both WETH (tokenIn) and USDT (tokenOut) provided.
+ # Note however that we still render it as "USDT" (built in token)
+ # rather than "FAKE USDT"!
+
+ _sign_tx_with_display_format(
+ session,
+ UNISWAP_EXACT_INPUT_SINGLE_DISPLAY_FORMAT,
+ tokens=[WETH_TOKEN_DEFINITION, USDT_TOKEN_DEFINITION],
+ )
+
+
+@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.
+ _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),
+ )
+
+
+@pytest.mark.models("core")
+def test_clear_signing_weth_weth2_without_tokens(session: Session) -> None:
+ # Without token definitions, amounts are shown as UNKNOWN tokens.
+ _sign_tx_with_display_format(
+ session,
+ UNISWAP_EXACT_INPUT_SINGLE_DISPLAY_FORMAT,
+ sign_tx_params=get_clear_signing_sign_tx_params(UNISWAP_WETH_WETH2_CALLDATA),
+ )
+
+
+@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.
+ _sign_tx_with_display_format(session, UNISWAP_EXACT_INPUT_SINGLE_DISPLAY_FORMAT)
+
+
+@pytest.mark.models("core")
+def test_clear_signing_with_mismatched_definition(session: Session) -> None:
+ # A definition whose tuple claims an extra field causes the firmware to fail
+ # parsing the calldata and fall back to blind signing.
+ assert (
+ UNISWAP_EXACT_INPUT_SINGLE_DISPLAY_FORMAT.parameter_definitions[0].tuple
+ is not None
+ )
+ bad_tuple = messages.EthereumABITupleInfo(
+ fields=[
+ *UNISWAP_EXACT_INPUT_SINGLE_DISPLAY_FORMAT.parameter_definitions[
+ 0
+ ].tuple.fields,
+ # extra field — causes OutOfBounds during clear signing
+ messages.EthereumABIValueInfo(atomic=messages.EthereumABIType.ABI_UINT256),
+ ],
+ is_dynamic=False,
+ )
+ bad_display_format = definitions.make_eth_erc7730_display_format(
+ chain_id=UNISWAP_EXACT_INPUT_SINGLE_DISPLAY_FORMAT.chain_id,
+ address=UNISWAP_EXACT_INPUT_SINGLE_DISPLAY_FORMAT.address,
+ func_sig=UNISWAP_EXACT_INPUT_SINGLE_DISPLAY_FORMAT.func_sig,
+ intent=UNISWAP_EXACT_INPUT_SINGLE_DISPLAY_FORMAT.intent,
+ parameter_definitions=[messages.EthereumABIValueInfo(tuple=bad_tuple)],
+ field_definitions=list(
+ UNISWAP_EXACT_INPUT_SINGLE_DISPLAY_FORMAT.field_definitions
+ ),
+ )
+ _sign_tx_with_display_format(session, bad_display_format)
diff --git a/tests/device_tests/ethereum/test_definitions_bad.py b/tests/device_tests/ethereum/test_definitions_bad.py
index 220a8f9d..046ef408 100644
--- a/tests/device_tests/ethereum/test_definitions_bad.py
+++ b/tests/device_tests/ethereum/test_definitions_bad.py
@@ -4,25 +4,29 @@ from hashlib import sha256
import pytest
-from trezorlib import ethereum
+from trezorlib import ethereum, messages, models
from trezorlib.debuglink import DebugSession as Session
from trezorlib.exceptions import TrezorFailure
from trezorlib.messages import DefinitionType
from trezorlib.tools import parse_path
from ...definitions import (
- make_eth_defs,
+ make_eth_erc7730_display_format,
make_eth_network,
make_eth_token,
make_payload,
sign_payload,
)
-from .test_definitions import DEFAULT_ERC20_PARAMS, ERC20_FAKE_ADDRESS
+from .test_definitions import (
+ DEFAULT_ERC20_PARAMS,
+ ERC20_FAKE_ADDRESS,
+ get_clear_signing_sign_tx_params,
+)
pytestmark = [pytest.mark.altcoin, pytest.mark.ethereum]
-def fails(session: Session, network: bytes, match: str) -> None:
+def _fails_network(session: Session, network: bytes, match: str) -> None:
with pytest.raises(TrezorFailure, match=match):
ethereum.get_address(
session,
@@ -32,108 +36,201 @@ def fails(session: Session, network: bytes, match: str) -> None:
)
+def _fails_token(session: Session, token: bytes, match: str) -> None:
+ with pytest.raises(TrezorFailure, match=match):
+ params = DEFAULT_ERC20_PARAMS.copy()
+ params.update(to=ERC20_FAKE_ADDRESS)
+ ethereum.sign_tx(
+ session,
+ **params,
+ definitions=messages.EthereumDefinitions(encoded_tokens=[token]),
+ )
+
+
+def _fails_erc7730_display_format(
+ session: Session, erc7730_display_format: bytes, match: str
+) -> None:
+ with pytest.raises(TrezorFailure, match=match):
+ ethereum.sign_tx(
+ session,
+ **get_clear_signing_sign_tx_params(),
+ definitions=messages.EthereumDefinitions(
+ encoded_erc7730_display_format=erc7730_display_format,
+ ),
+ )
+
+
+def _make_erc7730_payload(
+ timestamp: int = 0xFFFF_FFFF,
+ message: messages.EthereumERC7730DisplayFormatInfo | bytes | None = None,
+) -> bytes:
+ if message is None:
+ message = make_eth_erc7730_display_format()
+ return make_payload(
+ data_type=DefinitionType.ETHEREUM_ERC7730_DISPLAY_FORMAT,
+ message=message,
+ timestamp=timestamp,
+ )
+
+
+def _cases(session: Session) -> list[tuple]:
+ cases: list[tuple] = [(make_payload, _fails_network)]
+ if session.model in models.CORE_MODELS:
+ cases.append((_make_erc7730_payload, _fails_erc7730_display_format))
+ return cases
+
+
def test_short_message(session: Session) -> None:
- fails(session, b"\x00", "Invalid definition")
+ for _, check in _cases(session):
+ check(session, b"\x00", "Invalid definition")
def test_mangled_signature(session: Session) -> None:
- payload = make_payload()
- proof, signature = sign_payload(payload, [])
- bad_signature = signature[:-1] + b"\xff"
- fails(session, payload + proof + bad_signature, "Invalid definition signature")
+ for make, check in _cases(session):
+ payload = make()
+ proof, signature = sign_payload(payload, [])
+ bad_signature = signature[:-1] + b"\xff"
+ check(session, payload + proof + bad_signature, "Invalid definition signature")
def test_not_enough_signatures(session: Session) -> None:
- payload = make_payload()
- proof, signature = sign_payload(payload, [], threshold=1)
- fails(session, payload + proof + signature, "Invalid definition signature")
+ for make, check in _cases(session):
+ payload = make()
+ proof, signature = sign_payload(payload, [], threshold=1)
+ check(session, payload + proof + signature, "Invalid definition signature")
def test_missing_signature(session: Session) -> None:
- payload = make_payload()
- proof, _ = sign_payload(payload, [])
- fails(session, payload + proof, "Invalid definition")
+ for make, check in _cases(session):
+ payload = make()
+ proof, _ = sign_payload(payload, [])
+ check(session, payload + proof, "Invalid definition")
def test_mangled_payload(session: Session) -> None:
- payload = make_payload()
- proof, signature = sign_payload(payload, [])
- bad_payload = payload[:-1] + b"\xff"
- fails(session, bad_payload + proof + signature, "Invalid definition signature")
+ for make, check in _cases(session):
+ payload = make()
+ proof, signature = sign_payload(payload, [])
+ bad_payload = payload[:-1] + b"\xff"
+ check(session, bad_payload + proof + signature, "Invalid definition signature")
def test_proof_length_mismatch(session: Session) -> None:
- payload = make_payload()
- _, signature = sign_payload(payload, [])
- bad_proof = b"\x01"
- fails(session, payload + bad_proof + signature, "Invalid definition")
+ for make, check in _cases(session):
+ payload = make()
+ _, signature = sign_payload(payload, [])
+ bad_proof = b"\x01"
+ check(session, payload + bad_proof + signature, "Invalid definition")
def test_bad_proof(session: Session) -> None:
- payload = make_payload()
- proof, signature = sign_payload(payload, [sha256(b"x").digest()])
- bad_proof = proof[:-1] + b"\xff"
- fails(session, payload + bad_proof + signature, "Invalid definition signature")
+ for make, check in _cases(session):
+ payload = make()
+ proof, signature = sign_payload(payload, [sha256(b"x").digest()])
+ bad_proof = proof[:-1] + b"\xff"
+ check(session, payload + bad_proof + signature, "Invalid definition signature")
def test_trimmed_proof(session: Session) -> None:
- payload = make_payload()
- proof, signature = sign_payload(payload, [])
- bad_proof = proof[:-1]
- fails(session, payload + bad_proof + signature, "Invalid definition")
+ for make, check in _cases(session):
+ payload = make()
+ proof, signature = sign_payload(payload, [])
+ bad_proof = proof[:-1]
+ check(session, payload + bad_proof + signature, "Invalid definition")
def test_bad_prefix(session: Session) -> None:
- payload = make_payload()
- payload = b"trzd2" + payload[5:]
- proof, signature = sign_payload(payload, [])
- fails(session, payload + proof + signature, "Invalid definition")
+ for make, check in _cases(session):
+ payload = make()
+ payload = b"trzd2" + payload[5:]
+ proof, signature = sign_payload(payload, [])
+ check(session, payload + proof + signature, "Invalid definition")
def test_bad_type(session: Session) -> None:
- # assuming we expect a network definition
- payload = make_payload(
- data_type=DefinitionType.ETHEREUM_TOKEN, message=make_eth_token()
- )
- proof, signature = sign_payload(payload, [])
- fails(session, payload + proof + signature, "Definition type mismatch")
+ cases = [
+ (DefinitionType.ETHEREUM_TOKEN, make_eth_token(), _fails_network),
+ (DefinitionType.ETHEREUM_NETWORK, make_eth_network(), _fails_token),
+ ]
+ if session.model in models.CORE_MODELS:
+ cases += [
+ (
+ DefinitionType.ETHEREUM_ERC7730_DISPLAY_FORMAT,
+ make_eth_erc7730_display_format(),
+ _fails_network,
+ ),
+ (
+ DefinitionType.ETHEREUM_ERC7730_DISPLAY_FORMAT,
+ make_eth_erc7730_display_format(),
+ _fails_token,
+ ),
+ (
+ DefinitionType.ETHEREUM_TOKEN,
+ make_eth_token(),
+ _fails_erc7730_display_format,
+ ),
+ (
+ DefinitionType.ETHEREUM_NETWORK,
+ make_eth_network(),
+ _fails_erc7730_display_format,
+ ),
+ ]
+ for data_type, message, check in cases:
+ payload = make_payload(data_type=data_type, message=message)
+ proof, signature = sign_payload(payload, [])
+ check(session, payload + proof + signature, "Definition type mismatch")
def test_outdated(session: Session) -> None:
- payload = make_payload(timestamp=0)
- proof, signature = sign_payload(payload, [])
- fails(session, payload + proof + signature, "Definition is outdated")
+ for make, check in _cases(session):
+ payload = make(timestamp=0)
+ proof, signature = sign_payload(payload, [])
+ check(session, payload + proof + signature, "Definition is outdated")
def test_malformed_protobuf(session: Session) -> None:
- payload = make_payload(message=b"\x00")
- proof, signature = sign_payload(payload, [])
- fails(session, payload + proof + signature, "Invalid definition")
+ for make, check in _cases(session):
+ payload = make(message=b"\x00")
+ proof, signature = sign_payload(payload, [])
+ check(session, payload + proof + signature, "Invalid definition")
def test_protobuf_mismatch(session: Session) -> None:
- payload = make_payload(
- data_type=DefinitionType.ETHEREUM_NETWORK, message=make_eth_token()
- )
- proof, signature = sign_payload(payload, [])
- fails(session, payload + proof + signature, "Invalid definition")
-
- payload = make_payload(
- data_type=DefinitionType.ETHEREUM_TOKEN, message=make_eth_network()
- )
- proof, signature = sign_payload(payload, [])
- # have to do this manually to invoke a method that eats token definitions
- with pytest.raises(TrezorFailure, match="Invalid definition"):
- params = DEFAULT_ERC20_PARAMS.copy()
- params.update(to=ERC20_FAKE_ADDRESS)
- ethereum.sign_tx(
- session,
- **params,
- definitions=make_eth_defs(None, payload + proof + signature),
- )
+ cases = [
+ (DefinitionType.ETHEREUM_NETWORK, make_eth_token(), _fails_network),
+ (DefinitionType.ETHEREUM_TOKEN, make_eth_network(), _fails_token),
+ ]
+ if session.model in models.CORE_MODELS:
+ cases += [
+ (
+ DefinitionType.ETHEREUM_NETWORK,
+ make_eth_erc7730_display_format(),
+ _fails_network,
+ ),
+ (
+ DefinitionType.ETHEREUM_TOKEN,
+ make_eth_erc7730_display_format(),
+ _fails_token,
+ ),
+ (
+ DefinitionType.ETHEREUM_ERC7730_DISPLAY_FORMAT,
+ make_eth_token(),
+ _fails_erc7730_display_format,
+ ),
+ (
+ DefinitionType.ETHEREUM_ERC7730_DISPLAY_FORMAT,
+ make_eth_network(),
+ _fails_erc7730_display_format,
+ ),
+ ]
+ for data_type, message, check in cases:
+ payload = make_payload(data_type=data_type, message=message)
+ proof, signature = sign_payload(payload, [])
+ check(session, payload + proof + signature, "Invalid definition")
def test_trailing_garbage(session: Session) -> None:
- payload = make_payload()
- proof, signature = sign_payload(payload, [])
- fails(session, payload + proof + signature + b"\x00", "Invalid definition")
+ for make, check in _cases(session):
+ payload = make()
+ proof, signature = sign_payload(payload, [])
+ check(session, payload + proof + signature + b"\x00", "Invalid definition")
Why this scored 12/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.