@@ -279,91 +279,49 @@ TEST(Ethereum, ThorchainNativeAssetUsesOnlyItsZeroAddressSentinel) {
279279 EXPECT_FALSE (thor_assetIsNative (nullptr ));
280280}
281281
282- // transformERC20(address,address,uint256,uint256,(uint32,bytes)[]) — the two
283- // address words carry the token in their low 20 bytes.
284- static void MakeTransformErc20 (EthereumSignTx* msg, const char * in_token,
285- const char * out_token ) {
282+ // A canonical transformERC20 call with one transformation whose data is one
283+ // byte. The transformation byte is deliberately outside the four static words
284+ // that the retired decoder displayed.
285+ static void MakeTransformErc20 (EthereumSignTx* msg, uint8_t transform_byte ) {
286286 *msg = EthereumSignTx{};
287287 msg->has_to = true ;
288288 msg->to .size = 20 ;
289289 std::memcpy (msg->to .bytes , ZXSWAP_ADDRESS , msg->to .size );
290290 msg->has_chain_id = true ;
291291 msg->chain_id = 1 ;
292292 msg->has_data_initial_chunk = true ;
293- msg->data_initial_chunk .size = 4 + 4 * 32 ;
293+ msg->data_initial_chunk .size = 4 + 11 * 32 ;
294294 std::memcpy (msg->data_initial_chunk .bytes , " \x41\x55\x65\xb0 " , 4 );
295- if (in_token)
296- std::memcpy (msg->data_initial_chunk .bytes + 4 + 12 , in_token, 20 );
297- if (out_token)
298- std::memcpy (msg->data_initial_chunk .bytes + 4 + 32 + 12 , out_token, 20 );
295+ std::memcpy (msg->data_initial_chunk .bytes + 4 + 12 , kTUSD , 20 );
296+ std::memcpy (msg->data_initial_chunk .bytes + 4 + 32 + 12 , kTGBP , 20 );
297+ msg->data_initial_chunk .bytes [4 + 3 * 32 - 1 ] = 1 ; // input amount
298+ msg->data_initial_chunk .bytes [4 + 4 * 32 - 1 ] = 1 ; // minimum output
299+ msg->data_initial_chunk .bytes [4 + 5 * 32 - 1 ] = 0xa0 ; // array offset
300+ msg->data_initial_chunk .bytes [4 + 6 * 32 - 1 ] = 1 ; // array length
301+ msg->data_initial_chunk .bytes [4 + 7 * 32 - 1 ] = 0x20 ; // element offset
302+ msg->data_initial_chunk .bytes [4 + 8 * 32 - 1 ] = 1 ; // deployment nonce
303+ msg->data_initial_chunk .bytes [4 + 9 * 32 - 1 ] = 0x40 ; // data offset
304+ msg->data_initial_chunk .bytes [4 + 10 * 32 - 1 ] = 1 ; // data length
305+ msg->data_initial_chunk .bytes [4 + 10 * 32 ] = transform_byte;
299306}
300307
301- TEST (Ethereum, TransformErc20RequiresCompleteCalldataForClearSigning) {
302- EthereumSignTx msg;
303- MakeTransformErc20 (&msg, kTUSD , kTGBP );
308+ TEST (Ethereum, TransformErc20AlwaysRequiresAdvancedMode) {
309+ EthereumSignTx first, second;
310+ MakeTransformErc20 (&first, 0x41 );
311+ MakeTransformErc20 (&second, 0x42 );
304312
305- EXPECT_TRUE (
306- ethereum_contractHandled (msg.data_initial_chunk .size , &msg, nullptr ));
307- EXPECT_FALSE (
308- ethereum_contractHandled (msg.data_initial_chunk .size + 1 , &msg, nullptr ));
309- }
310-
311- TEST (Ethereum, TransformErc20RejectsAmountsThatDoNotFitTheDisplay) {
312- EthereumSignTx msg;
313- MakeTransformErc20 (&msg, kTUSD , kTGBP );
314-
315- std::memset (msg.data_initial_chunk .bytes + 4 + 2 * 32 , 0xff , 32 );
316- EXPECT_FALSE (zx_confirmZxTransERC20 (msg.data_initial_chunk .size , &msg));
317-
318- MakeTransformErc20 (&msg, kTUSD , kTGBP );
319- std::memset (msg.data_initial_chunk .bytes + 4 + 3 * 32 , 0xff , 32 );
320- EXPECT_FALSE (zx_confirmZxTransERC20 (msg.data_initial_chunk .size , &msg));
321- }
313+ ASSERT_EQ (first.data_initial_chunk .size , second.data_initial_chunk .size );
314+ ASSERT_EQ (0 , std::memcmp (first.data_initial_chunk .bytes ,
315+ second.data_initial_chunk .bytes ,
316+ first.data_initial_chunk .size - 32 ));
317+ ASSERT_NE (0 , std::memcmp (first.data_initial_chunk .bytes ,
318+ second.data_initial_chunk .bytes ,
319+ first.data_initial_chunk .size ));
322320
323- // The decoder shows four values and hides the transformations[] body. That is
324- // only defensible because the input amount and minimum output amount bound the
325- // outcome — and ethereumFormatAmount() renders the literal "Unknown token
326- // value" whenever tokenByChainAddress() misses, so an unresolved token turns
327- // the bound into nothing while the calldata still executes.
328- //
329- // Gating on the lookup rather than on a chain allowlist keeps this correct
330- // however the tables change. It matters in practice: the generated table
331- // carries ~1924 entries for chain 1, three each for BSC and Polygon, and NONE
332- // for Base, Arbitrum or Avalanche, so on those chains every pair fails here.
333- TEST (Ethereum, TransformErc20RequiresBothTokensResolvable) {
334- EthereumSignTx msg;
335-
336- // Both known -> the device can name what it is showing.
337- MakeTransformErc20 (&msg, kTUSD , kTGBP );
338- EXPECT_TRUE (
339- ethereum_contractHandled (msg.data_initial_chunk .size , &msg, nullptr ));
340-
341- // Either side unknown -> refuse to claim it, so ethereum.c falls through to
342- // the raw-calldata path (AdvancedMode-gated, bytes shown).
343- MakeTransformErc20 (&msg, nullptr , kTGBP );
344- EXPECT_FALSE (
345- ethereum_contractHandled (msg.data_initial_chunk .size , &msg, nullptr ))
346- << " unknown INPUT token must not clear-sign" ;
347-
348- MakeTransformErc20 (&msg, kTUSD , nullptr );
349321 EXPECT_FALSE (
350- ethereum_contractHandled (msg.data_initial_chunk .size , &msg, nullptr ))
351- << " unknown OUTPUT token must not clear-sign" ;
352-
353- MakeTransformErc20 (&msg, nullptr , nullptr );
354- EXPECT_FALSE (
355- ethereum_contractHandled (msg.data_initial_chunk .size , &msg, nullptr ));
356-
357- // A chain with no token table entries at all cannot name either asset, so it
358- // must refuse even though 0x deploys the same proxy there. This is what the
359- // chain allowlist was previously being asked to approximate.
360- for (uint32_t cid : {8453u , 42161u , 43114u }) {
361- MakeTransformErc20 (&msg, kTUSD , kTGBP );
362- msg.chain_id = cid;
363- EXPECT_FALSE (
364- ethereum_contractHandled (msg.data_initial_chunk .size , &msg, nullptr ))
365- << " chain " << cid << " has no token entries; nothing is nameable" ;
366- }
322+ ethereum_contractHandled (first.data_initial_chunk .size , &first, nullptr ));
323+ EXPECT_FALSE (ethereum_contractHandled (second.data_initial_chunk .size , &second,
324+ nullptr ));
367325}
368326
369327TEST (Ethereum, Eip712ChainIdRequiresCanonicalUint32) {
0 commit comments