Skip to content

cast tx --raw and --lane panic on Arbitrum Nitro internal transactions (0x6a) #16483

Description

@mattsse

cast tx --raw and cast tx --lane panic on any transaction type the strict Ethereum envelope does not model. On Arbitrum One and Arbitrum Orbit chains such as Robinhood Chain, every block opens with a Nitro internal transaction (0x6a), so this is reachable on ordinary blocks rather than an edge case.

Repro

cast tx 0x07b2dbc7d0cbecfe5cc23eff19b03b245d6dabc7739699bfc5f3af2f7b9fdb82 --raw --rpc-url https://arbitrum.gateway.tenderly.co
The application panicked (crashed).
Message:  Attempted to encode unknown transaction type 0x6a. This is not a bug in alloy. To encode
          or decode unknown transaction types, use a custom Transaction type and a custom Network
          implementation.
Location: alloy-network-2.4.1/src/any/either.rs:472

This is a bug. Consider reporting it at https://github.com/foundry-rs/foundry

--lane panics identically on the same transaction. Both controls behave: --raw on a 0x2 transaction from the same block succeeds, and cast tx without --raw on the 0x6a prints the transaction fine, so only the 2718 encoding path is affected.

Cause

crates/cast/src/lib.rs:1256 calls encoded_2718() straight on the alloy transaction:

Ok(if raw {
    let encoded = tx.as_ref().encoded_2718();
    format!("0x{}", hex::encode(encoded))
} else if lane {
    let encoded = tx.as_ref().encoded_2718();

AnyTxEnvelope::Unknown has no encoding, and alloy resolves that by panicking rather than erroring — encode_2718 and encode_2718_len both call panic_unknown_transaction_encoding (alloy-network/src/any/either.rs:472 and :480). A CLI reaching that path turns a normal query into a crash that tells the user to file a bug against Foundry.

Either branch should surface a normal error for a type that cannot be re-encoded, or go through FoundryTxEnvelope so the supported types are encoded and the rest are rejected cleanly. Note the lane branch already decodes into FoundryTxEnvelope on the next line — it just does so after the panic has already happened.

Related

#16465 fixes the equivalent panic on anvil's debug_getRawTransaction, but does not touch this call site. The Celo CIP-64 receipt gap in #16482 and the Arbitrum receipt gap are the same underlying shape: a strict envelope meeting a type it does not model.

Coverage

The cast network read-command matrix in #16472 deliberately leaves --raw out rather than encoding the crash as expected behaviour. It should join the matrix once this is fixed — the tests already cover Arbitrum and Robinhood Chain, where every block carries a reproducing transaction.

Metadata

Metadata

Assignees

Labels

C-castCommand: castT-bugType: bug

Type

No type

Projects

Status
Backlog

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions