chore(ethereum): precomputed approve/transfer sig
What changed, and why it matters
This commit replaces runtime computation of two Ethereum function signatures with hard-coded byte values, then adds debug-only assertions to verify those values still match the original computation. It is a minor code cleanup with no apparent security impact. The change does not alter what the device signs, displays, or accepts.
No action required. Treat as routine refactoring.
Security signals we found
No security-relevant behavior change
Constants match previously computed values (verified by added assertions)
Removal of unconditional cryptographic import reduces attack surface negligibly
Evidence from the diff
In core/src/apps/ethereum/clear_signing_definitions.py, the code previously computed the ERC-20 approve(address,uint256) and transfer(address,uint256) function selectors at import time using base58.keccak_32(). The patch replaces those calls with the precomputed 4-byte selectors 0x095ea7b3 and 0xa9059cbb, removes the unconditional import of trezor.crypto.base58, and adds an debug-guarded block with assertions that the constants equal the keccak outputs. The functional behavior is unchanged; only import-time computation is avoided.
Changed components
core/src/apps/ethereum/clear_signing_definitions.pyInspect captured patch +12 / −4
diff --git a/core/src/apps/ethereum/clear_signing_definitions.py b/core/src/apps/ethereum/clear_signing_definitions.py
index f16e44ca..8adfca14 100644
--- a/core/src/apps/ethereum/clear_signing_definitions.py
+++ b/core/src/apps/ethereum/clear_signing_definitions.py
@@ -1,8 +1,6 @@
from micropython import const
from ubinascii import unhexlify
-from trezor.crypto import base58
-
from .clear_signing import (
AddressNameFormatter,
AmountFormatter,
@@ -29,7 +27,7 @@ from .clear_signing import (
APPROVE_DISPLAY_FORMAT = DisplayFormat(
binding_context=None,
- func_sig=base58.keccak_32(b"approve(address,uint256)"),
+ func_sig=b"\x09\x5e\xa7\xb3", # approve(address,uint256)
intent="Approve",
parameter_definitions=[
Atomic(parse_address), # _spender
@@ -51,7 +49,7 @@ SC_FUNC_APPROVE_REVOKE_AMOUNT = const(0)
TRANSFER_DISPLAY_FORMAT = DisplayFormat(
binding_context=None,
- func_sig=base58.keccak_32(b"transfer(address,uint256)"),
+ func_sig=b"\xa9\x05\x9c\xbb", # transfer(address,uint256)
intent="Send",
parameter_definitions=[
Atomic(parse_address), # _to
@@ -65,6 +63,16 @@ TRANSFER_DISPLAY_FORMAT = DisplayFormat(
],
)
+if __debug__:
+ from trezor.crypto import base58
+
+ assert APPROVE_DISPLAY_FORMAT.func_sig == base58.keccak_32(
+ b"approve(address,uint256)"
+ )
+ assert TRANSFER_DISPLAY_FORMAT.func_sig == base58.keccak_32(
+ b"transfer(address,uint256)"
+ )
+
ALL_DISPLAY_FORMATS = [APPROVE_DISPLAY_FORMAT, TRANSFER_DISPLAY_FORMAT]
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.