Skip to content

Commit 36bc792

Browse files
committed
test(ethereum): pin native pseudo-address isolation
1 parent 90ddd76 commit 36bc792

3 files changed

Lines changed: 97 additions & 5 deletions

File tree

scripts/generate-test-report.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1168,19 +1168,29 @@ def junit_cases(path):
11681168
'ERC-20 transfer chain-ID width binding',
11691169
'TRANSFER review scopes token metadata to the complete chain ID.',
11701170
['Chain 1 and chain 257 transfer sequences']),
1171-
('R20', 'test_msg_osmosis_validation',
1171+
('R20', 'test_msg_ethereum_signtx',
1172+
'test_ethereum_native_pseudo_address_is_unknown_off_mainnet',
1173+
'ERC-20 native pseudo-address isolation',
1174+
'Chain 257 transfer and approve calls render the exact unknown-token frame.',
1175+
['Transfer and approve unknown-token sequences']),
1176+
('R21', 'test_msg_ethereum_signtx_xfer',
1177+
'test_native_pseudo_address_transfer_is_unknown_off_mainnet',
1178+
'ERC-20 TRANSFER pseudo-address isolation',
1179+
'TRANSFER review renders 0xeeee..eeee as unknown outside chain 1.',
1180+
['Exact unknown-token transfer sequence']),
1181+
('R22', 'test_msg_osmosis_validation',
11721182
'test_present_but_empty_amount_is_rejected_before_review',
11731183
'Osmosis empty amount refusal', 'Present-but-empty is not displayed as zero.', []),
1174-
('R21', 'test_msg_osmosis_validation',
1184+
('R23', 'test_msg_osmosis_validation',
11751185
'test_ibc_omitted_amount_and_receiver_are_rejected_before_review',
11761186
'Osmosis IBC required fields', 'Omitted value and receiver are refused.', []),
1177-
('R22', 'test_msg_recoverydevice_cipher',
1187+
('R24', 'test_msg_recoverydevice_cipher',
11781188
'test_unknown_word_count_failure_aborts_recovery',
11791189
'Recovery Failure is terminal', 'A stale CharacterAck cannot resume the ceremony.', []),
1180-
('R23', 'test_msg_signing_boundaries',
1190+
('R25', 'test_msg_signing_boundaries',
11811191
'test_multisig_signature_over_72_bytes_is_rejected',
11821192
'Multisig serialization bound', 'Oversized host signatures are refused.', []),
1183-
('R24', 'test_msg_signing_boundaries',
1193+
('R26', 'test_msg_signing_boundaries',
11841194
'test_clear_session_aborts_active_bitcoin_signing',
11851195
'ClearSession ends signing', 'A stale TxAck cannot resume the signer.', []),
11861196
]),

tests/test_msg_ethereum_signtx.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import unittest
2222
import common
2323
import binascii
24+
import hashlib
2425

2526
import keepkeylib.messages_pb2 as proto
2627
import keepkeylib.messages_ethereum_pb2 as eth_proto
@@ -31,6 +32,49 @@
3132

3233

3334
class TestMsgEthereumSigntx(common.KeepKeyTest):
35+
def test_ethereum_native_pseudo_address_is_unknown_off_mainnet(self):
36+
"""0xeeee..eeee must render as unknown for chain-257 token calls."""
37+
self.requires_firmware("7.14.2")
38+
self.requires_fullFeature()
39+
self.setup_mnemonic_nopin_nopassphrase()
40+
self.client.apply_policy("AdvancedMode", 1)
41+
common.reset_screenshot_capture(self.client)
42+
43+
recipient = self.client.ethereum_get_address([0, 0])
44+
pseudo_address = b"\xee" * 20
45+
calls = (
46+
(
47+
"transfer",
48+
binascii.unhexlify("a9059cbb" + "00" * 12) +
49+
recipient + int_to_big_endian(1).rjust(32, b"\x00"),
50+
"85d9054ee56836c1784c90dd777fc89444bf82b840d0818a59c73aa5b57ee35d",
51+
),
52+
(
53+
"approve",
54+
binascii.unhexlify("095ea7b3" + "00" * 12) +
55+
recipient + int_to_big_endian(1).rjust(32, b"\x00"),
56+
"ab30156ff400957ffa9146ea827318bf878614e6ab4ae7dd731824e285fa5da6",
57+
),
58+
)
59+
60+
try:
61+
for label, data, expected_frame_sha256 in calls:
62+
with ScreenRecorder(
63+
self.client,
64+
screenshot_group="pseudo-%s" % label) as recorder:
65+
self.client.ethereum_sign_tx(
66+
n=[0, 0], nonce=0, gas_price=20, gas_limit=60000,
67+
to=pseudo_address, value=0, chain_id=257, data=data,
68+
)
69+
self.assertGreaterEqual(len(recorder.screens), 2)
70+
self.assertEqual(
71+
hashlib.sha256(recorder.screens[0]).hexdigest(),
72+
expected_frame_sha256,
73+
)
74+
finally:
75+
self.client.apply_policy("AdvancedMode", 0)
76+
common.reset_screenshot_capture(self.client)
77+
3478
def test_ethereum_erc20_high_chain_id_does_not_alias_mainnet(self):
3579
"""Chain 257 must not borrow chain-1 token labels or decimals."""
3680
self.requires_firmware("7.14.2")

tests/test_msg_ethereum_signtx_xfer.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import unittest
2222
import common
2323
import binascii
24+
import hashlib
2425
import struct
2526

2627
import keepkeylib.messages_pb2 as proto
@@ -29,7 +30,44 @@
2930
from keepkeylib.tools import int_to_big_endian
3031
from test_msg_display_disclosure import ScreenRecorder
3132

33+
3234
class TestMsgEthereumSigntx(common.KeepKeyTest):
35+
def test_native_pseudo_address_transfer_is_unknown_off_mainnet(self):
36+
"""TRANSFER must show the exact unknown-token frame on chain 257."""
37+
self.requires_firmware("7.14.2")
38+
self.requires_fullFeature()
39+
self.setup_mnemonic_nopin_nopassphrase()
40+
self.client.apply_policy('ShapeShift', 1)
41+
self.client.apply_policy('AdvancedMode', 1)
42+
common.reset_screenshot_capture(self.client)
43+
44+
destination_n = [0x8000002c, 0x8000003c, 0x80000001, 0, 0]
45+
recipient = self.client.ethereum_get_address(destination_n)
46+
erc20_data = (
47+
binascii.unhexlify("a9059cbb" + "00" * 12) +
48+
recipient + int_to_big_endian(1).rjust(32, b"\x00")
49+
)
50+
51+
try:
52+
with ScreenRecorder(
53+
self.client,
54+
screenshot_group="pseudo-transfer") as recorder:
55+
self.client.ethereum_sign_tx(
56+
n=[0, 0], nonce=0, gas_price=20, gas_limit=60000,
57+
value=0, to=b"\xee" * 20, to_n=destination_n,
58+
address_type=proto_types.TRANSFER,
59+
data=erc20_data, chain_id=257,
60+
)
61+
self.assertGreaterEqual(len(recorder.screens), 2)
62+
self.assertEqual(
63+
hashlib.sha256(recorder.screens[0]).hexdigest(),
64+
"b0a3026e7af1778ebd71a968ace25c03945cccf2d8abc951e5dd65abc04e914e",
65+
)
66+
finally:
67+
self.client.apply_policy('AdvancedMode', 0)
68+
self.client.apply_policy('ShapeShift', 0)
69+
common.reset_screenshot_capture(self.client)
70+
3371
def test_transfer_review_uses_signing_chain_asset(self):
3472
"""The first transfer approval must change with the signed chain."""
3573
self.requires_firmware("7.14.2")

0 commit comments

Comments
 (0)