chore(ethereum): payment request just for transfers
What changed, and why it matters
This commit tightens a security rule in Trezor's Ethereum signing code: payment requests can now only be used with plain ERC-20 token transfers. Previously, the code may have allowed payment requests with other smart-contract calls, which could let a malicious app or service trick a user into approving a different transaction than expected while still showing a familiar payment-request screen.
Treat this as a security hardening fix and include it in release notes. Review whether any other display formats or transaction types can still be combined with payment requests in unintended ways, and add regression tests for non-transfer calls with payment requests.
Security signals we found
Input validation gap being closed
Scope restriction for a privileged signing flow
Potential user-confusion / spoofing vector addressed
No changelog entry despite security-relevant behavior change
Evidence from the diff
The patch adds a guard in core/src/apps/ethereum/clear_signing.py inside try_confirm(). If a payment_request_verifier is active and the decoded call’s display format signature does not match the standard ERC-20 transfer signature, the device now raises DataError('Payment Requests only supported for ERC-20 transfers.'). This prevents payment-request flows from being combined with arbitrary contract calls such as approvals, transfersFrom, or other methods that could alter token ownership in unexpected ways.
Changed components
core/src/apps/ethereum/clear_signing.pyEthereum payment request signing flowERC-20 transaction confirmation UIInspect captured patch +7 / −0
diff --git a/core/src/apps/ethereum/clear_signing.py b/core/src/apps/ethereum/clear_signing.py
index 530fc33d..129d2367 100644
--- a/core/src/apps/ethereum/clear_signing.py
+++ b/core/src/apps/ethereum/clear_signing.py
@@ -2,6 +2,7 @@ from micropython import const
from typing import TYPE_CHECKING
from trezor import TR
+from trezor.wire import DataError
from .definitions import Definitions
from .helpers import (
@@ -846,6 +847,12 @@ async def try_confirm(
if display_format is None:
return False
+ if (
+ payment_request_verifier is not None
+ and display_format.func_sig != TRANSFER_DISPLAY_FORMAT.func_sig
+ ):
+ raise DataError("Payment Requests only supported for ERC-20 transfers.")
+
calldata = memoryview(data)[SC_FUNC_SIG_BYTES:]
# custom treatment of certain functions (APPROVE, TRANSFER)
Why this scored 58/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.