Skip to content

Commit 90ddd76

Browse files
committed
test(ethereum): cover full-width token chain IDs
1 parent 8b7f445 commit 90ddd76

3 files changed

Lines changed: 84 additions & 5 deletions

File tree

scripts/generate-test-report.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,19 +1158,29 @@ def junit_cases(path):
11581158
'Ethereum transfer chain/asset binding',
11591159
'The first asset approval changes between Ethereum, BNB Chain and Polygon.',
11601160
['ETH, BNB and MATIC approval sequences']),
1161-
('R18', 'test_msg_osmosis_validation',
1161+
('R18', 'test_msg_ethereum_signtx',
1162+
'test_ethereum_erc20_high_chain_id_does_not_alias_mainnet',
1163+
'ERC-20 chain-ID width binding',
1164+
'Chain 257 cannot borrow chain-1 token labels or decimals.',
1165+
['Chain 1 and chain 257 approval sequences']),
1166+
('R19', 'test_msg_ethereum_signtx_xfer',
1167+
'test_erc20_transfer_high_chain_id_does_not_alias_mainnet',
1168+
'ERC-20 transfer chain-ID width binding',
1169+
'TRANSFER review scopes token metadata to the complete chain ID.',
1170+
['Chain 1 and chain 257 transfer sequences']),
1171+
('R20', 'test_msg_osmosis_validation',
11621172
'test_present_but_empty_amount_is_rejected_before_review',
11631173
'Osmosis empty amount refusal', 'Present-but-empty is not displayed as zero.', []),
1164-
('R19', 'test_msg_osmosis_validation',
1174+
('R21', 'test_msg_osmosis_validation',
11651175
'test_ibc_omitted_amount_and_receiver_are_rejected_before_review',
11661176
'Osmosis IBC required fields', 'Omitted value and receiver are refused.', []),
1167-
('R20', 'test_msg_recoverydevice_cipher',
1177+
('R22', 'test_msg_recoverydevice_cipher',
11681178
'test_unknown_word_count_failure_aborts_recovery',
11691179
'Recovery Failure is terminal', 'A stale CharacterAck cannot resume the ceremony.', []),
1170-
('R21', 'test_msg_signing_boundaries',
1180+
('R23', 'test_msg_signing_boundaries',
11711181
'test_multisig_signature_over_72_bytes_is_rejected',
11721182
'Multisig serialization bound', 'Oversized host signatures are refused.', []),
1173-
('R22', 'test_msg_signing_boundaries',
1183+
('R24', 'test_msg_signing_boundaries',
11741184
'test_clear_session_aborts_active_bitcoin_signing',
11751185
'ClearSession ends signing', 'A stale TxAck cannot resume the signer.', []),
11761186
]),

tests/test_msg_ethereum_signtx.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,42 @@
2727
import keepkeylib.types_pb2 as proto_types
2828
from keepkeylib.client import CallException
2929
from keepkeylib.tools import int_to_big_endian
30+
from test_msg_display_disclosure import ScreenRecorder
3031

3132

3233
class TestMsgEthereumSigntx(common.KeepKeyTest):
34+
def test_ethereum_erc20_high_chain_id_does_not_alias_mainnet(self):
35+
"""Chain 257 must not borrow chain-1 token labels or decimals."""
36+
self.requires_firmware("7.14.2")
37+
self.requires_fullFeature()
38+
self.setup_mnemonic_nopin_nopassphrase()
39+
self.client.apply_policy("AdvancedMode", 1)
40+
41+
recipient = self.client.ethereum_get_address([0, 0])
42+
erc20_data = (
43+
binascii.unhexlify("a9059cbb" + "00" * 12) +
44+
recipient + int_to_big_endian(1).rjust(32, b"\x00")
45+
)
46+
contract = binascii.unhexlify(
47+
"d0d6d6c5fe4a677d343cc433536bb717bae167dd"
48+
)
49+
50+
first_screens = {}
51+
try:
52+
for chain_id in (1, 257):
53+
with ScreenRecorder(self.client) as recorder:
54+
self.client.ethereum_sign_tx(
55+
n=[0, 0], nonce=0, gas_price=20, gas_limit=60000,
56+
to=contract, value=0, chain_id=chain_id,
57+
data=erc20_data,
58+
)
59+
self.assertGreaterEqual(len(recorder.screens), 2)
60+
first_screens[chain_id] = recorder.screens[0]
61+
finally:
62+
self.client.apply_policy("AdvancedMode", 0)
63+
64+
self.assertNotEqual(first_screens[1], first_screens[257])
65+
3366
def test_ethereum_unrenderable_amounts_are_rejected(self):
3467
"""Neither a native nor ERC-20 amount may reach an approval blank."""
3568
self.requires_firmware("7.14.2")

tests/test_msg_ethereum_signtx_xfer.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,42 @@ def test_transfer_review_uses_signing_chain_asset(self):
6262

6363
self.client.apply_policy('ShapeShift', 0)
6464

65+
def test_erc20_transfer_high_chain_id_does_not_alias_mainnet(self):
66+
"""TRANSFER review must not borrow chain-1 token metadata."""
67+
self.requires_firmware("7.14.2")
68+
self.requires_fullFeature()
69+
self.setup_mnemonic_nopin_nopassphrase()
70+
self.client.apply_policy('ShapeShift', 1)
71+
self.client.apply_policy('AdvancedMode', 1)
72+
73+
destination_n = [0x8000002c, 0x8000003c, 0x80000001, 0, 0]
74+
recipient = self.client.ethereum_get_address(destination_n)
75+
erc20_data = (
76+
binascii.unhexlify("a9059cbb" + "00" * 12) +
77+
recipient + int_to_big_endian(1).rjust(32, b"\x00")
78+
)
79+
contract = binascii.unhexlify(
80+
"d0d6d6c5fe4a677d343cc433536bb717bae167dd"
81+
)
82+
83+
first_screens = {}
84+
try:
85+
for chain_id in (1, 257):
86+
with ScreenRecorder(self.client) as recorder:
87+
self.client.ethereum_sign_tx(
88+
n=[0, 0], nonce=0, gas_price=20, gas_limit=60000,
89+
value=0, to=contract, to_n=destination_n,
90+
address_type=proto_types.TRANSFER,
91+
data=erc20_data, chain_id=chain_id,
92+
)
93+
self.assertGreaterEqual(len(recorder.screens), 2)
94+
first_screens[chain_id] = recorder.screens[0]
95+
finally:
96+
self.client.apply_policy('AdvancedMode', 0)
97+
self.client.apply_policy('ShapeShift', 0)
98+
99+
self.assertNotEqual(first_screens[1], first_screens[257])
100+
65101
def test_ethereum_tx_xfer_acc1(self):
66102
self.requires_fullFeature()
67103
self.setup_mnemonic_nopin_nopassphrase()

0 commit comments

Comments
 (0)