Skip to main content

cast/
opts.rs

1use crate::cmd::{
2    access_list::AccessListArgs,
3    artifact::ArtifactArgs,
4    b2e_payload::B2EPayloadArgs,
5    bal::BalArgs,
6    batch_mktx::BatchMakeTxArgs,
7    batch_send::BatchSendArgs,
8    bind::BindArgs,
9    call::CallArgs,
10    call_overrides::CallOverrideOpts,
11    constructor_args::ConstructorArgsArgs,
12    create2::Create2Args,
13    creation_code::CreationCodeArgs,
14    erc20::Erc20Subcommand,
15    erc4626::Erc4626Subcommand,
16    estimate::EstimateArgs,
17    events::EventsArgs,
18    find_block::FindBlockArgs,
19    interface::InterfaceArgs,
20    keychain::{KeyAuthorizationSubcommand, KeychainSubcommand},
21    logs::LogsArgs,
22    mktx::MakeTxArgs,
23    receive_policy::ReceivePolicySubcommand,
24    rpc::RpcArgs,
25    run::RunArgs,
26    safe::SafeSubcommand,
27    send::SendTxArgs,
28    storage::StorageArgs,
29    storage_credits::StorageCreditsSubcommand,
30    tempo::TempoArgs,
31    tip20::Tip20Subcommand,
32    tip403::Tip403Subcommand,
33    trace::TraceArgs,
34    txpool::TxPoolSubcommands,
35    vaddr::VaddrSubcommand,
36    wallet::WalletSubcommands,
37};
38use alloy_ens::NameOrAddress;
39use alloy_primitives::{Address, B256, Selector, U256};
40use alloy_rpc_types::BlockId;
41use clap::{ArgAction, Parser, Subcommand, ValueHint};
42use eyre::Result;
43use foundry_cli::opts::{EtherscanOpts, GlobalArgs, RpcOpts};
44use foundry_common::version::{LONG_VERSION, SHORT_VERSION};
45use foundry_evm_networks::NetworkVariant;
46use std::{path::PathBuf, str::FromStr};
47
48#[cfg(any(feature = "base", feature = "optimism"))]
49use crate::cmd::da_estimate::DAEstimateArgs;
50
51/// A Swiss Army knife for interacting with Ethereum applications from the command line.
52#[derive(Parser)]
53#[command(
54    name = "cast",
55    version = SHORT_VERSION,
56    long_version = LONG_VERSION,
57    after_help = "Find more information in the book: https://getfoundry.sh/cast/overview",
58    next_display_order = None,
59)]
60pub struct Cast {
61    /// Include the global arguments.
62    #[command(flatten)]
63    pub global: GlobalArgs,
64
65    #[command(subcommand)]
66    pub cmd: CastSubcommand,
67}
68
69/// The `cast` subcommands.
70///
71/// Subcommands are declared across several flattened enums because clap's derive generates one
72/// `augment_subcommands` function per enum, and in debug builds a single enum holding every
73/// subcommand produced a stack frame that overflowed the 2 MiB stack of test threads.
74#[derive(Subcommand)]
75#[allow(clippy::large_enum_variant, reason = "parsed once per process")]
76pub enum CastSubcommand {
77    #[command(flatten)]
78    Conversion(ConversionSubcommand),
79
80    #[command(flatten)]
81    Transaction(TransactionSubcommand),
82
83    #[command(flatten)]
84    Abi(AbiSubcommand),
85
86    #[command(flatten)]
87    Query(QuerySubcommand),
88
89    #[command(flatten)]
90    Misc(MiscSubcommand),
91}
92
93/// Constant and conversion subcommands.
94#[derive(Subcommand)]
95pub enum ConversionSubcommand {
96    /// Prints the maximum value of the given integer type.
97    #[command(visible_aliases = &["--max-int", "maxi"])]
98    MaxInt {
99        /// The integer type to get the maximum value of.
100        #[arg(default_value = "int256")]
101        r#type: String,
102    },
103
104    /// Prints the minimum value of the given integer type.
105    #[command(visible_aliases = &["--min-int", "mini"])]
106    MinInt {
107        /// The integer type to get the minimum value of.
108        #[arg(default_value = "int256")]
109        r#type: String,
110    },
111
112    /// Prints the maximum value of the given integer type.
113    #[command(visible_aliases = &["--max-uint", "maxu"])]
114    MaxUint {
115        /// The unsigned integer type to get the maximum value of.
116        #[arg(default_value = "uint256")]
117        r#type: String,
118    },
119
120    /// Prints the zero address.
121    #[command(visible_aliases = &["--address-zero", "az"])]
122    AddressZero,
123
124    /// Prints the zero hash.
125    #[command(visible_aliases = &["--hash-zero", "hz"])]
126    HashZero,
127
128    /// Convert UTF8 text to hex.
129    #[command(
130        visible_aliases = &[
131        "--from-ascii",
132        "--from-utf8",
133        "from-ascii",
134        "fu",
135        "fa"]
136    )]
137    FromUtf8 {
138        /// The text to convert.
139        text: Option<String>,
140    },
141
142    /// Concatenate hex strings.
143    #[command(visible_aliases = &["--concat-hex", "ch"])]
144    ConcatHex {
145        /// The data to concatenate.
146        data: Vec<String>,
147    },
148
149    /// Convert binary data into hex data.
150    #[command(visible_aliases = &["--from-bin", "from-binx", "fb"])]
151    FromBin,
152
153    /// Normalize the input to lowercase, 0x-prefixed hex.
154    ///
155    /// The input can be:
156    /// - mixed case hex with or without 0x prefix
157    /// - 0x prefixed hex, concatenated with a ':'
158    /// - an absolute path to file
159    /// - @tag, where the tag is defined in an environment variable
160    #[command(visible_aliases = &["--to-hexdata", "thd", "2hd"])]
161    ToHexdata {
162        /// The input to normalize.
163        input: Option<String>,
164    },
165
166    /// Convert an address to a checksummed format (EIP-55).
167    #[command(
168        visible_aliases = &["--to-checksum-address",
169        "--to-checksum",
170        "to-checksum",
171        "ta",
172        "2a"]
173    )]
174    ToCheckSumAddress {
175        /// The address to convert.
176        address: Option<Address>,
177        /// EIP-155 chain ID to encode the address using EIP-1191.
178        chain_id: Option<u64>,
179    },
180
181    /// Convert hex data to an ASCII string.
182    #[command(visible_aliases = &["--to-ascii", "tas", "2as"])]
183    ToAscii {
184        /// The hex data to convert.
185        hexdata: Option<String>,
186    },
187
188    /// Convert hex data to a utf-8 string.
189    #[command(visible_aliases = &["--to-utf8", "tu8", "2u8"])]
190    ToUtf8 {
191        /// The hex data to convert.
192        hexdata: Option<String>,
193    },
194
195    /// Convert a fixed point number into an integer.
196    #[command(visible_aliases = &["--from-fix", "ff"])]
197    FromFixedPoint {
198        /// The number of decimals to use.
199        decimals: Option<String>,
200
201        /// The value to convert.
202        #[arg(allow_hyphen_values = true)]
203        value: Option<String>,
204    },
205
206    /// Right-pads hex data to 32 bytes.
207    #[command(visible_aliases = &["--to-bytes32", "tb", "2b"])]
208    ToBytes32 {
209        /// The hex data to convert.
210        bytes: Option<String>,
211    },
212
213    /// Convert hex data to the word-aligned layout of a Solidity `bytes memory` value.
214    ///
215    /// The output contains a 32-byte length prefix followed by the data, right-padded with zeros
216    /// to a whole number of 32-byte words.
217    #[command(visible_alias = "tbm")]
218    ToBytesMemory {
219        /// The hex data to convert.
220        data: Option<String>,
221    },
222
223    /// Pads hex data to a specified length.
224    #[command(visible_aliases = &["pd"])]
225    Pad {
226        /// The hex data to pad.
227        data: Option<String>,
228
229        /// Right-pad the data (instead of left-pad).
230        #[arg(long)]
231        right: bool,
232
233        /// Left-pad the data (default).
234        #[arg(long, conflicts_with = "right")]
235        left: bool,
236
237        /// Target length in bytes (default: 32).
238        #[arg(long, default_value = "32")]
239        len: usize,
240    },
241
242    /// Convert an integer into a fixed point number.
243    #[command(visible_aliases = &["--to-fix", "tf", "2f"])]
244    ToFixedPoint {
245        /// The number of decimals to use.
246        decimals: Option<String>,
247
248        /// The value to convert.
249        #[arg(allow_hyphen_values = true)]
250        value: Option<String>,
251    },
252
253    /// Convert a number to a hex-encoded uint256.
254    #[command(name = "to-uint256", visible_aliases = &["--to-uint256", "tu", "2u"])]
255    ToUint256 {
256        /// The value to convert.
257        value: Option<String>,
258    },
259
260    /// Convert a number to a hex-encoded int256.
261    #[command(name = "to-int256", visible_aliases = &["--to-int256", "ti", "2i"])]
262    ToInt256 {
263        /// The value to convert.
264        value: Option<String>,
265    },
266
267    /// Convert an ETH amount into another unit (ether, gwei or wei)
268    ///
269    /// Examples:
270    /// - 1ether wei
271    /// - "1 ether" wei
272    /// - 1ether
273    /// - 1 gwei
274    /// - 1gwei ether
275    #[command(verbatim_doc_comment, visible_aliases = &["--to-unit", "tun", "2un"])]
276    ToUnit {
277        /// The value to convert.
278        value: Option<String>,
279
280        /// The unit to convert to (ether, gwei, wei).
281        #[arg(default_value = "wei")]
282        unit: String,
283    },
284
285    /// Convert a number from decimal to smallest unit with arbitrary decimals
286    ///
287    /// Examples:
288    /// - 1.0 6    (for USDC, result: 1000000)
289    /// - 2.5 12   (for 12 decimals token, result: 2500000000000)
290    /// - 1.23 3   (for 3 decimals token, result: 1230)
291    #[command(verbatim_doc_comment, visible_aliases = &["--parse-units", "pun"])]
292    ParseUnits {
293        /// The value to convert.
294        value: Option<String>,
295
296        /// The unit to convert to.
297        #[arg(default_value = "18")]
298        unit: u8,
299    },
300
301    /// Format a number from smallest unit to decimal with arbitrary decimals
302    ///
303    /// Examples:
304    /// - 1000000 6       (for USDC, result: 1.0)
305    /// - 2500000000000 12 (for 12 decimals, result: 2.5)
306    /// - 1230 3          (for 3 decimals, result: 1.23)
307    #[command(verbatim_doc_comment, visible_aliases = &["--format-units", "fun"])]
308    FormatUnits {
309        /// The value to format.
310        value: Option<String>,
311
312        /// The unit to format to.
313        #[arg(default_value = "18")]
314        unit: u8,
315    },
316
317    /// Convert an ETH amount to wei.
318    ///
319    /// Consider using --to-unit.
320    #[command(visible_aliases = &["--to-wei", "tw", "2w"])]
321    ToWei {
322        /// The value to convert.
323        #[arg(allow_hyphen_values = true)]
324        value: Option<String>,
325
326        /// The unit to convert from (ether, gwei, wei).
327        #[arg(default_value = "eth")]
328        unit: String,
329    },
330
331    /// Convert wei into an ETH amount.
332    ///
333    /// Consider using --to-unit.
334    #[command(visible_aliases = &["--from-wei", "fw"])]
335    FromWei {
336        /// The value to convert.
337        #[arg(allow_hyphen_values = true)]
338        value: Option<String>,
339
340        /// The unit to convert from (ether, gwei, wei).
341        #[arg(default_value = "eth")]
342        unit: String,
343    },
344
345    /// RLP encodes hex data, or an array of hex data
346    ///
347    /// Accepts a hex-encoded string, or an array of hex-encoded strings.
348    /// Can be arbitrarily recursive.
349    ///
350    /// Examples:
351    /// - `cast to-rlp "[]"` -> `0xc0`
352    /// - `cast to-rlp "0x22"` -> `0x22`
353    /// - `cast to-rlp "[\"0x61\"]"` -> `0xc161`
354    /// - `cast to-rlp "[\"0xf1\", \"f2\"]"` -> `0xc481f181f2`
355    #[command(verbatim_doc_comment, visible_aliases = &["--to-rlp"])]
356    ToRlp {
357        /// The value to convert.
358        ///
359        /// This is a hex-encoded string, or an array of hex-encoded strings.
360        /// Can be arbitrarily recursive.
361        value: Option<String>,
362    },
363
364    /// Decodes RLP hex-encoded data.
365    #[command(visible_aliases = &["--from-rlp"])]
366    FromRlp {
367        /// The RLP hex-encoded data.
368        value: Option<String>,
369
370        /// Decode the RLP data as int
371        #[arg(long, alias = "int")]
372        as_int: bool,
373    },
374
375    /// Converts a number of one base to another
376    #[command(visible_aliases = &["--to-hex", "th", "2h"])]
377    ToHex(ToBaseArgs),
378
379    /// Converts a number of one base to decimal
380    #[command(visible_aliases = &["--to-dec", "td", "2d"])]
381    ToDec(ToBaseArgs),
382
383    /// Converts a number of one base to another
384    #[command(
385        visible_aliases = &["--to-base",
386        "--to-radix",
387        "to-radix",
388        "tr",
389        "2r"]
390    )]
391    ToBase {
392        #[command(flatten)]
393        base: ToBaseArgs,
394
395        /// The output base.
396        #[arg(value_name = "BASE")]
397        base_out: Option<String>,
398    },
399
400    /// Formats a string into bytes32 encoding.
401    #[command(name = "format-bytes32-string", visible_aliases = &["--format-bytes32-string"])]
402    FormatBytes32String {
403        /// The string to format.
404        string: Option<String>,
405    },
406
407    /// Parses a string from bytes32 encoding.
408    #[command(name = "parse-bytes32-string", visible_aliases = &["--parse-bytes32-string"])]
409    ParseBytes32String {
410        /// The string to parse.
411        bytes: Option<String>,
412    },
413
414    #[command(name = "parse-bytes32-address", visible_aliases = &["--parse-bytes32-address"])]
415    #[command(about = "Parses a checksummed address from bytes32 encoding.")]
416    ParseBytes32Address {
417        #[arg(value_name = "BYTES")]
418        bytes: Option<String>,
419    },
420}
421
422/// Call and transaction subcommands.
423#[derive(Subcommand)]
424pub enum TransactionSubcommand {
425    /// Perform a call on an account without publishing a transaction
426    ///
427    /// Examples:
428    /// - cast call $TOKEN "balanceOf(address)(uint256)" vitalik.eth
429    /// - cast call $TOKEN "transfer(address,uint256)" vitalik.eth 100 --trace
430    #[command(verbatim_doc_comment, visible_alias = "c")]
431    Call(CallArgs),
432
433    /// Build and sign a transaction
434    ///
435    /// Examples:
436    /// - cast mktx vitalik.eth --value 0.1ether --private-key $PK
437    /// - cast mktx $TOKEN "transfer(address,uint256)" vitalik.eth 100 --account dev
438    #[command(verbatim_doc_comment, name = "mktx", visible_alias = "m")]
439    MakeTx(MakeTxArgs),
440
441    /// Classify a raw transaction as Tempo T5 payment/general lane.
442    Classify {
443        /// The raw signed transaction.
444        raw_tx: Option<String>,
445    },
446
447    /// Get information about a transaction
448    ///
449    /// Examples:
450    /// - cast tx $TX_HASH
451    /// - cast tx $TX_HASH blockNumber (only print the blockNumber field)
452    /// - cast tx $TX_HASH --raw
453    #[command(verbatim_doc_comment, visible_alias = "t")]
454    Tx {
455        /// The transaction hash.
456        tx_hash: Option<String>,
457
458        /// The sender of the transaction.
459        #[arg(long, value_parser = NameOrAddress::from_str)]
460        from: Option<NameOrAddress>,
461
462        /// Nonce of the transaction.
463        #[arg(long)]
464        nonce: Option<u64>,
465
466        /// If specified, only get the given field of the transaction. If "raw", the RLP encoded
467        /// transaction will be printed.
468        field: Option<String>,
469
470        /// Print the raw RLP encoded transaction.
471        #[arg(long, conflicts_with = "field")]
472        raw: bool,
473
474        /// Classify the transaction as Tempo T5 payment/general lane.
475        #[arg(long, conflicts_with_all = ["field", "raw", "to_request"])]
476        lane: bool,
477
478        #[command(flatten)]
479        rpc: RpcOpts,
480
481        /// If specified, the transaction will be converted to a TransactionRequest JSON format.
482        #[arg(long)]
483        to_request: bool,
484
485        /// Specify the Network for correct encoding.
486        #[arg(long, short, num_args = 1, value_name = "NETWORK")]
487        network: Option<NetworkVariant>,
488    },
489
490    /// Get the transaction receipt for a transaction
491    ///
492    /// Examples:
493    /// - cast receipt $TX_HASH
494    /// - cast receipt $TX_HASH status (only print the status field)
495    #[command(verbatim_doc_comment, visible_alias = "re")]
496    Receipt {
497        /// The transaction hash.
498        tx_hash: String,
499
500        /// If specified, only get the given field of the transaction.
501        field: Option<String>,
502
503        /// The number of confirmations until the receipt is fetched
504        #[arg(long, default_value = "1")]
505        confirmations: u64,
506
507        /// Exit immediately if the transaction was not found.
508        #[arg(id = "async", long = "async", env = "CAST_ASYNC", alias = "cast-async")]
509        cast_async: bool,
510
511        #[command(flatten)]
512        rpc: RpcOpts,
513    },
514
515    /// Sign and publish a transaction
516    ///
517    /// Examples:
518    /// - cast send vitalik.eth --value 0.1ether --private-key $PK (transfer ETH)
519    /// - cast send $TOKEN "transfer(address,uint256)" vitalik.eth 100 --account dev
520    /// - cast send --private-key $PK --create $BYTECODE (deploy a contract)
521    #[command(verbatim_doc_comment, name = "send", visible_alias = "s")]
522    SendTx(SendTxArgs),
523
524    /// Build and sign a batch transaction (Tempo).
525    #[command(name = "batch-mktx", visible_alias = "bm")]
526    BatchMakeTx(BatchMakeTxArgs),
527
528    /// Sign and publish a batch transaction (Tempo).
529    #[command(name = "batch-send", visible_alias = "bs")]
530    BatchSend(BatchSendArgs),
531
532    /// Publish a raw transaction to the network.
533    #[command(name = "publish", visible_alias = "p")]
534    PublishTx {
535        /// The raw transaction
536        raw_tx: String,
537
538        /// Only print the transaction hash and exit immediately.
539        #[arg(id = "async", long = "async", env = "CAST_ASYNC", alias = "cast-async")]
540        cast_async: bool,
541
542        #[command(flatten)]
543        rpc: RpcOpts,
544    },
545
546    /// Estimate the gas cost of a transaction
547    ///
548    /// Examples:
549    /// - cast estimate vitalik.eth --value 0.1ether
550    /// - cast estimate $CONTRACT "deposit()" --value 1ether
551    #[command(verbatim_doc_comment, visible_alias = "e")]
552    Estimate(EstimateArgs),
553
554    /// Runs a published transaction in a local environment and prints the trace
555    ///
556    /// If the node serves an EIP-7928 block access list (BAL) for the transaction's block, the
557    /// transaction's prestate is read from it instead of replaying the earlier transactions of
558    /// the block. Pass `--no-bal` to always replay the block.
559    ///
560    /// Examples:
561    /// - cast run $TX_HASH
562    /// - cast run $TX_HASH --quick (only use the state from the previous block)
563    /// - cast run $TX_HASH --debug (open the transaction in the debugger)
564    #[command(verbatim_doc_comment, visible_alias = "r")]
565    Run(RunArgs),
566}
567
568/// ABI encoding and decoding, selector and contract artifact subcommands.
569#[derive(Subcommand)]
570pub enum AbiSubcommand {
571    /// ABI-encode a function with arguments.
572    #[command(name = "calldata", visible_alias = "cd")]
573    CalldataEncode {
574        /// The function signature in the format `<name>(<in-types>)(<out-types>)`
575        sig: String,
576
577        /// The arguments to encode.
578        #[arg(allow_hyphen_values = true)]
579        args: Vec<String>,
580
581        // Path to file containing arguments to encode.
582        #[arg(long, value_name = "PATH")]
583        file: Option<PathBuf>,
584    },
585
586    /// Decode ABI-encoded input data
587    ///
588    /// Similar to `abi-decode --input`, but function selector MUST be prefixed in `calldata`.
589    ///
590    /// Examples:
591    /// - cast decode-calldata "transfer(address,uint256)" $CALLDATA
592    /// - cast decode-calldata --json "transfer(address,uint256)" $CALLDATA
593    #[command(verbatim_doc_comment, visible_aliases = &["calldata-decode", "--calldata-decode", "cdd"])]
594    DecodeCalldata {
595        /// The function signature in the format `<name>(<in-types>)(<out-types>)`.
596        sig: String,
597
598        /// The ABI-encoded calldata.
599        #[arg(required_unless_present = "file", index = 2)]
600        calldata: Option<String>,
601
602        /// Load ABI-encoded calldata from a file instead.
603        #[arg(long = "file", short = 'f', conflicts_with = "calldata")]
604        file: Option<PathBuf>,
605    },
606
607    /// Decode ABI-encoded string.
608    ///
609    /// Similar to `calldata-decode --input`, but the function argument is a `string`
610    #[command(visible_aliases = &["string-decode", "--string-decode", "sd"])]
611    DecodeString {
612        /// The ABI-encoded string.
613        data: String,
614    },
615
616    /// Decode event data
617    ///
618    /// Parameters marked `indexed` in the supplied signature are emitted as log topics rather than
619    /// data, so they are ignored when decoding. With `--sig`, DATA must contain only the encoded
620    /// non-indexed event data, without topics.
621    ///
622    /// Examples:
623    /// - cast decode-event --sig "Transfer(address indexed from, address indexed to, uint256
624    ///   value)" $DATA
625    /// - cast decode-event $DATA (topic0-prefixed data; looks up the signature)
626    #[command(verbatim_doc_comment, visible_aliases = &["event-decode", "--event-decode", "ed"])]
627    DecodeEvent {
628        /// The event signature. If none provided then tries to decode from local cache or <https://4byte.sourcify.dev>.
629        #[arg(long, visible_alias = "event-sig")]
630        sig: Option<String>,
631        /// The event data to decode.
632        data: String,
633    },
634
635    /// Decode custom error data.
636    #[command(visible_aliases = &["error-decode", "--error-decode", "erd"])]
637    DecodeError {
638        /// The error signature. If none provided then tries to decode from local cache or <https://4byte.sourcify.dev>.
639        #[arg(long, visible_alias = "error-sig")]
640        sig: Option<String>,
641        /// The error data to decode.
642        data: String,
643    },
644
645    /// Decode ABI-encoded input or output data
646    ///
647    /// Defaults to decoding output data. To decode input data pass --input.
648    ///
649    /// When passing `--input`, function selector must NOT be prefixed in `calldata` string.
650    ///
651    /// Examples:
652    /// - cast decode-abi "balanceOf(address)(uint256)" $DATA
653    /// - cast decode-abi --input "transfer(address,uint256)" $CALLDATA
654    #[command(verbatim_doc_comment, name = "decode-abi", visible_aliases = &["abi-decode", "--abi-decode", "ad"])]
655    DecodeAbi {
656        /// The function signature in the format `<name>(<in-types>)(<out-types>)`.
657        sig: String,
658
659        /// The ABI-encoded calldata.
660        calldata: String,
661
662        /// Whether to decode the input or output data.
663        #[arg(long, short, help_heading = "Decode input data instead of output data")]
664        input: bool,
665    },
666
667    /// ABI encode the given function argument, excluding the selector
668    ///
669    /// Examples:
670    /// - cast abi-encode "transfer(address,uint256)" $ADDRESS 100
671    /// - cast abi-encode --packed "f(string,uint64)" hello 100
672    #[command(verbatim_doc_comment, visible_alias = "ae")]
673    AbiEncode {
674        /// The function signature.
675        sig: String,
676
677        /// Whether to use packed encoding.
678        #[arg(long)]
679        packed: bool,
680
681        /// The arguments of the function.
682        #[arg(allow_hyphen_values = true)]
683        args: Vec<String>,
684    },
685
686    /// ABI encode an event and its arguments to generate topics and data.
687    #[command(visible_alias = "aee")]
688    AbiEncodeEvent {
689        /// The event signature.
690        sig: String,
691
692        /// The arguments of the event.
693        #[arg(allow_hyphen_values = true)]
694        args: Vec<String>,
695    },
696
697    /// Get the function signatures for the given selector from <https://4byte.sourcify.dev>.
698    #[command(name = "4byte", visible_aliases = &["4", "4b"])]
699    FourByte {
700        /// The function selector.
701        selector: Option<Selector>,
702    },
703
704    /// Decode ABI-encoded calldata using <https://4byte.sourcify.dev>.
705    #[command(name = "4byte-calldata", aliases = &["4byte-decode", "4d", "4bd"], visible_aliases = &["4c", "4bc"])]
706    FourByteCalldata {
707        /// The ABI-encoded calldata.
708        calldata: Option<String>,
709    },
710
711    /// Get the event signature for a given topic 0 from <https://4byte.sourcify.dev>.
712    #[command(name = "4byte-event", visible_aliases = &["4e", "4be", "topic0-event", "t0e"])]
713    FourByteEvent {
714        /// Topic 0
715        #[arg(value_name = "TOPIC_0")]
716        topic: Option<B256>,
717    },
718
719    /// Upload the given signatures to <https://4byte.sourcify.dev>.
720    ///
721    /// Example inputs:
722    /// - "transfer(address,uint256)"
723    /// - "function transfer(address,uint256)"
724    /// - "function transfer(address,uint256)" "event Transfer(address,address,uint256)"
725    /// - "./out/Contract.sol/Contract.json"
726    #[command(visible_aliases = &["ups"])]
727    UploadSignature {
728        /// The signatures to upload.
729        ///
730        /// Prefix with 'function', 'event', or 'error'. Defaults to function if no prefix given.
731        /// Can also take paths to contract artifact JSON.
732        signatures: Vec<String>,
733    },
734
735    /// Pretty print calldata.
736    ///
737    /// Tries to decode the calldata using <https://4byte.sourcify.dev> unless --offline is passed.
738    #[command(visible_alias = "pc")]
739    PrettyCalldata {
740        /// The calldata.
741        calldata: Option<String>,
742
743        /// Skip the <https://4byte.sourcify.dev> lookup.
744        #[arg(long, short)]
745        offline: bool,
746    },
747
748    /// Download a contract creation code from Etherscan and RPC.
749    #[command(visible_alias = "cc")]
750    CreationCode(CreationCodeArgs),
751
752    /// Generate an artifact file, that can be used to deploy a contract locally.
753    #[command(visible_alias = "ar")]
754    Artifact(ArtifactArgs),
755
756    /// Display constructor arguments used for the contract initialization.
757    #[command(visible_alias = "cra")]
758    ConstructorArgs(ConstructorArgsArgs),
759
760    /// Generate a Solidity interface from a given ABI
761    ///
762    /// Currently does not support ABI encoder v2.
763    ///
764    /// Examples:
765    /// - cast interface $TOKEN --etherscan-api-key $KEY (fetch the ABI from Etherscan)
766    /// - cast interface ./out/Counter.sol/Counter.json (load a local ABI file)
767    #[command(verbatim_doc_comment, visible_alias = "i")]
768    Interface(InterfaceArgs),
769
770    /// Generate a rust binding from a given ABI.
771    #[command(visible_alias = "bi")]
772    Bind(BindArgs),
773
774    /// Convert Beacon payload to execution payload.
775    #[command(visible_alias = "b2e")]
776    B2EPayload(B2EPayloadArgs),
777
778    /// Get the selector for a function
779    ///
780    /// Examples:
781    /// - cast sig "transfer(address,uint256)"
782    /// - cast sig "deposit(uint256)" 2 (optimize for 2 leading zero bytes)
783    #[command(verbatim_doc_comment, visible_alias = "si")]
784    Sig {
785        /// The function signature, e.g. transfer(address,uint256).
786        sig: Option<String>,
787
788        /// Optimize signature to contain provided amount of leading zeroes in selector.
789        #[arg(conflicts_with = "json")]
790        optimize: Option<usize>,
791    },
792}
793
794/// Blockchain, RPC and ENS query subcommands.
795#[derive(Subcommand)]
796#[allow(clippy::large_enum_variant, reason = "parsed once per process")]
797pub enum QuerySubcommand {
798    /// Create an access list for a transaction
799    ///
800    /// Examples:
801    /// - cast access-list vitalik.eth --value 0.1ether
802    /// - cast access-list $TOKEN "transfer(address,uint256)" vitalik.eth 100
803    #[command(verbatim_doc_comment, visible_aliases = &["ac", "acl"])]
804    AccessList(AccessListArgs),
805
806    /// Get information about a block
807    ///
808    /// Examples:
809    /// - cast block latest
810    /// - cast block 21000000 --field timestamp
811    /// - cast block latest --json
812    #[command(verbatim_doc_comment, visible_alias = "bl")]
813    Block {
814        /// The block height to query at.
815        ///
816        /// Can also be the tags earliest, finalized, safe, latest, or pending.
817        block: Option<BlockId>,
818
819        /// If specified, only get the given field of the block.
820        #[arg(short, long = "field", aliases = ["fields"], num_args = 0.., action = ArgAction::Append, value_delimiter = ',')]
821        fields: Vec<String>,
822
823        /// Print the raw RLP encoded block header.
824        #[arg(long, conflicts_with = "fields")]
825        raw: bool,
826
827        #[arg(long, env = "CAST_FULL_BLOCK")]
828        full: bool,
829
830        #[command(flatten)]
831        rpc: RpcOpts,
832
833        /// Specify the Network for correct encoding.
834        #[arg(long, short, num_args = 1, value_name = "NETWORK")]
835        network: Option<NetworkVariant>,
836    },
837
838    /// Get the latest block number.
839    #[command(visible_alias = "bn")]
840    BlockNumber {
841        /// The hash or tag to query. If not specified, the latest number is returned.
842        block: Option<BlockId>,
843        #[command(flatten)]
844        rpc: RpcOpts,
845    },
846
847    /// Get the EIP-7928 block access list of a block
848    ///
849    /// Examples:
850    /// - cast bal latest
851    /// - cast bal 21000000 --raw
852    #[command(verbatim_doc_comment, visible_alias = "block-access-list")]
853    Bal(BalArgs),
854
855    /// Get the symbolic name of the current chain.
856    Chain {
857        #[command(flatten)]
858        rpc: RpcOpts,
859    },
860
861    /// Get the Ethereum chain ID.
862    #[command(visible_aliases = &["ci", "cid"])]
863    ChainId {
864        #[command(flatten)]
865        rpc: RpcOpts,
866    },
867
868    /// Get the current client version.
869    #[command(visible_alias = "cl")]
870    Client {
871        #[command(flatten)]
872        rpc: RpcOpts,
873    },
874
875    /// Compute the contract address from a given nonce and deployer address.
876    #[command(visible_alias = "ca")]
877    ComputeAddress {
878        /// The deployer address.
879        address: Option<Address>,
880
881        /// The nonce of the deployer address.
882        #[arg(
883            long,
884            conflicts_with = "salt",
885            conflicts_with = "init_code",
886            conflicts_with = "init_code_hash"
887        )]
888        nonce: Option<u64>,
889
890        /// The salt for CREATE2 address computation.
891        #[arg(long, conflicts_with = "nonce")]
892        salt: Option<B256>,
893
894        /// The init code for CREATE2 address computation.
895        #[arg(
896            long,
897            requires = "salt",
898            conflicts_with = "init_code_hash",
899            conflicts_with = "nonce"
900        )]
901        init_code: Option<String>,
902
903        /// The init code hash for CREATE2 address computation.
904        #[arg(long, requires = "salt", conflicts_with = "init_code", conflicts_with = "nonce")]
905        init_code_hash: Option<B256>,
906
907        #[command(flatten)]
908        rpc: RpcOpts,
909    },
910
911    /// Disassembles a hex-encoded bytecode into a human-readable representation.
912    #[command(visible_alias = "da")]
913    Disassemble {
914        /// The hex-encoded bytecode.
915        bytecode: Option<String>,
916    },
917
918    /// Calculate the ENS namehash of a name.
919    #[command(visible_aliases = &["na", "nh"])]
920    Namehash { name: Option<String> },
921
922    /// Compute the storage slot for an entry in a mapping.
923    #[command(visible_alias = "in")]
924    Index {
925        /// The mapping key type.
926        key_type: String,
927
928        /// The mapping key.
929        key: String,
930
931        /// The storage slot of the mapping.
932        slot_number: String,
933    },
934
935    /// Compute storage slots as specified by `ERC-7201: Namespaced Storage Layout`.
936    #[command(name = "index-erc7201", alias = "index-erc-7201", visible_aliases = &["index7201", "in7201"])]
937    IndexErc7201 {
938        /// The arbitrary identifier.
939        id: Option<String>,
940        /// The formula ID. Currently the only supported formula is `erc7201`.
941        #[arg(long, default_value = "erc7201")]
942        formula_id: String,
943    },
944
945    /// Fetch the EIP-1967 implementation for a contract
946    /// Can read from the implementation slot or the beacon slot.
947    #[command(visible_alias = "impl")]
948    Implementation {
949        /// The block height to query at.
950        ///
951        /// Can also be the tags earliest, finalized, safe, latest, or pending.
952        #[arg(long, short = 'B')]
953        block: Option<BlockId>,
954
955        /// Fetch the implementation from the beacon slot.
956        ///
957        /// If not specified, the implementation slot is used.
958        #[arg(long)]
959        beacon: bool,
960
961        /// The address for which the implementation will be fetched.
962        #[arg(value_parser = NameOrAddress::from_str)]
963        who: NameOrAddress,
964
965        #[command(flatten)]
966        rpc: RpcOpts,
967    },
968
969    /// Fetch the EIP-1967 admin account
970    #[command(visible_alias = "adm")]
971    Admin {
972        /// The block height to query at.
973        ///
974        /// Can also be the tags earliest, finalized, safe, latest, or pending.
975        #[arg(long, short = 'B')]
976        block: Option<BlockId>,
977
978        /// The address from which the admin account will be fetched.
979        #[arg(value_parser = NameOrAddress::from_str)]
980        who: NameOrAddress,
981
982        #[command(flatten)]
983        rpc: RpcOpts,
984    },
985
986    /// Get the timestamp of a block.
987    #[command(visible_alias = "a")]
988    Age {
989        /// The block height to query at.
990        ///
991        /// Can also be the tags earliest, finalized, safe, latest, or pending.
992        block: Option<BlockId>,
993
994        #[command(flatten)]
995        rpc: RpcOpts,
996    },
997
998    /// Get the balance of an account in wei
999    ///
1000    /// Examples:
1001    /// - cast balance vitalik.eth --ether
1002    /// - cast balance vitalik.eth --erc20 0x6B175474E89094C44Da98b954EedeAC495271d0F
1003    #[command(verbatim_doc_comment, visible_alias = "b")]
1004    Balance {
1005        /// The block height to query at.
1006        ///
1007        /// Can also be the tags earliest, finalized, safe, latest, or pending.
1008        #[arg(long, short = 'B')]
1009        block: Option<BlockId>,
1010
1011        /// The account to query.
1012        #[arg(value_parser = NameOrAddress::from_str)]
1013        who: NameOrAddress,
1014
1015        /// Format the balance in ether.
1016        #[arg(long, short)]
1017        ether: bool,
1018
1019        #[command(flatten)]
1020        rpc: RpcOpts,
1021
1022        /// erc20 address to query, with the method `balanceOf(address) return (uint256)`, alias
1023        /// with '--erc721'
1024        #[arg(long, alias = "erc721")]
1025        erc20: Option<Address>,
1026
1027        #[command(flatten)]
1028        overrides: CallOverrideOpts,
1029    },
1030
1031    /// Get the basefee of a block.
1032    #[command(visible_aliases = &["ba", "fee", "basefee"])]
1033    BaseFee {
1034        /// The block height to query at.
1035        ///
1036        /// Can also be the tags earliest, finalized, safe, latest, or pending.
1037        block: Option<BlockId>,
1038
1039        #[command(flatten)]
1040        rpc: RpcOpts,
1041    },
1042
1043    /// Get the runtime bytecode of a contract
1044    ///
1045    /// Examples:
1046    /// - cast code 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
1047    /// - cast code 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 --disassemble
1048    #[command(verbatim_doc_comment, visible_alias = "co")]
1049    Code {
1050        /// The block height to query at.
1051        ///
1052        /// Can also be the tags earliest, finalized, safe, latest, or pending.
1053        #[arg(long, short = 'B')]
1054        block: Option<BlockId>,
1055
1056        /// The contract address.
1057        #[arg(value_parser = NameOrAddress::from_str)]
1058        who: NameOrAddress,
1059
1060        /// Disassemble bytecodes.
1061        #[arg(long, short)]
1062        disassemble: bool,
1063
1064        #[command(flatten)]
1065        rpc: RpcOpts,
1066    },
1067
1068    /// Get the runtime bytecode size of a contract.
1069    #[command(visible_alias = "cs")]
1070    Codesize {
1071        /// The block height to query at.
1072        ///
1073        /// Can also be the tags earliest, finalized, safe, latest, or pending.
1074        #[arg(long, short = 'B')]
1075        block: Option<BlockId>,
1076
1077        /// The contract address.
1078        #[arg(value_parser = NameOrAddress::from_str)]
1079        who: NameOrAddress,
1080
1081        #[command(flatten)]
1082        rpc: RpcOpts,
1083    },
1084
1085    /// Get the current gas price.
1086    #[command(visible_alias = "g")]
1087    GasPrice {
1088        #[command(flatten)]
1089        rpc: RpcOpts,
1090    },
1091
1092    /// Perform an ENS lookup.
1093    #[command(visible_alias = "rn")]
1094    ResolveName {
1095        /// The name to lookup.
1096        who: Option<String>,
1097
1098        /// Perform a reverse lookup to verify that the name is correct.
1099        #[arg(long)]
1100        verify: bool,
1101
1102        #[command(flatten)]
1103        rpc: RpcOpts,
1104    },
1105
1106    /// Perform an ENS reverse lookup.
1107    #[command(visible_alias = "la")]
1108    LookupAddress {
1109        /// The account to perform the lookup for.
1110        who: Option<Address>,
1111
1112        /// Perform a normal lookup to verify that the address is correct.
1113        #[arg(long)]
1114        verify: bool,
1115
1116        #[command(flatten)]
1117        rpc: RpcOpts,
1118    },
1119
1120    /// Get the raw value of a contract's storage slot
1121    ///
1122    /// Examples:
1123    /// - cast storage 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 0
1124    /// - cast storage $TOKEN --etherscan-api-key $KEY (decode the full storage layout)
1125    #[command(verbatim_doc_comment, visible_alias = "st")]
1126    Storage(StorageArgs),
1127
1128    /// Generate a storage proof for a given storage slot.
1129    #[command(visible_alias = "pr")]
1130    Proof {
1131        /// The contract address.
1132        #[arg(value_parser = NameOrAddress::from_str)]
1133        address: NameOrAddress,
1134
1135        /// The storage slot numbers (hex or decimal).
1136        #[arg(value_parser = parse_slot)]
1137        slots: Vec<B256>,
1138
1139        /// The block height to query at.
1140        ///
1141        /// Can also be the tags earliest, finalized, safe, latest, or pending.
1142        #[arg(long, short = 'B')]
1143        block: Option<BlockId>,
1144
1145        #[command(flatten)]
1146        rpc: RpcOpts,
1147    },
1148
1149    /// Get the nonce for an account.
1150    #[command(visible_alias = "n")]
1151    Nonce {
1152        /// The block height to query at.
1153        ///
1154        /// Can also be the tags earliest, finalized, safe, latest, or pending.
1155        #[arg(long, short = 'B')]
1156        block: Option<BlockId>,
1157
1158        /// The address to get the nonce for.
1159        #[arg(value_parser = NameOrAddress::from_str)]
1160        who: NameOrAddress,
1161
1162        #[command(flatten)]
1163        rpc: RpcOpts,
1164    },
1165
1166    /// Get the codehash for an account.
1167    #[command()]
1168    Codehash {
1169        /// The block height to query at.
1170        ///
1171        /// Can also be the tags earliest, finalized, safe, latest, or pending.
1172        #[arg(long, short = 'B')]
1173        block: Option<BlockId>,
1174
1175        /// The address to get the codehash for.
1176        #[arg(value_parser = NameOrAddress::from_str)]
1177        who: NameOrAddress,
1178
1179        /// The storage slot numbers (hex or decimal).
1180        #[arg(value_parser = parse_slot)]
1181        slots: Vec<B256>,
1182
1183        #[command(flatten)]
1184        rpc: RpcOpts,
1185    },
1186
1187    /// Get the storage root for an account.
1188    #[command(visible_alias = "sr")]
1189    StorageRoot {
1190        /// The block height to query at.
1191        ///
1192        /// Can also be the tags earliest, finalized, safe, latest, or pending.
1193        #[arg(long, short = 'B')]
1194        block: Option<BlockId>,
1195
1196        /// The address to get the storage root for.
1197        #[arg(value_parser = NameOrAddress::from_str)]
1198        who: NameOrAddress,
1199
1200        /// The storage slot numbers (hex or decimal).
1201        #[arg(value_parser = parse_slot)]
1202        slots: Vec<B256>,
1203
1204        #[command(flatten)]
1205        rpc: RpcOpts,
1206    },
1207
1208    /// Compute a Tempo TIP-20 channel reserve channel ID.
1209    #[command(name = "channel-id")]
1210    ChannelId {
1211        /// Channel payer address.
1212        #[arg(value_parser = NameOrAddress::from_str)]
1213        payer: NameOrAddress,
1214
1215        /// Channel payee address.
1216        #[arg(value_parser = NameOrAddress::from_str)]
1217        payee: NameOrAddress,
1218
1219        /// TIP-20 token address locked by the channel.
1220        #[arg(value_parser = NameOrAddress::from_str)]
1221        token: NameOrAddress,
1222
1223        /// User-supplied channel salt.
1224        salt: B256,
1225
1226        /// Optional relayer allowed to submit settlements for the payee.
1227        #[arg(long, value_parser = NameOrAddress::from_str)]
1228        operator: Option<NameOrAddress>,
1229
1230        /// Optional voucher signer. Defaults to the zero address, meaning the payer signs.
1231        #[arg(long, value_parser = NameOrAddress::from_str)]
1232        authorized_signer: Option<NameOrAddress>,
1233
1234        /// Transaction-derived expiring nonce hash from ChannelOpened.
1235        #[arg(long, default_value_t = B256::ZERO)]
1236        expiring_nonce_hash: B256,
1237
1238        /// Channel reserve precompile address.
1239        #[arg(long, value_parser = NameOrAddress::from_str)]
1240        reserve: Option<NameOrAddress>,
1241
1242        /// The block height to query at.
1243        ///
1244        /// Can also be the tags earliest, finalized, safe, latest, or pending.
1245        #[arg(long, short = 'B')]
1246        block: Option<BlockId>,
1247
1248        #[command(flatten)]
1249        rpc: RpcOpts,
1250    },
1251
1252    /// Get the block number closest to the provided timestamp.
1253    #[command(visible_alias = "f")]
1254    FindBlock(FindBlockArgs),
1255
1256    /// Perform a raw JSON-RPC request
1257    ///
1258    /// Examples:
1259    /// - cast rpc eth_blockNumber
1260    /// - cast rpc eth_getBlockByNumber 0x123 false
1261    /// - cast rpc eth_getBlockByNumber '["0x123", false]' --raw
1262    #[command(verbatim_doc_comment, visible_alias = "rp")]
1263    Rpc(RpcArgs),
1264
1265    /// Extracts function selectors and arguments from bytecode
1266    #[command(visible_alias = "sel")]
1267    Selectors {
1268        /// The hex-encoded bytecode.
1269        bytecode: Option<String>,
1270
1271        /// Resolve the function signatures for the extracted selectors using <https://4byte.sourcify.dev>
1272        #[arg(long, short)]
1273        resolve: bool,
1274    },
1275}
1276
1277/// Miscellaneous subcommands.
1278#[derive(Subcommand)]
1279pub enum MiscSubcommand {
1280    /// Perform a left shifting operation
1281    #[command(name = "shl")]
1282    LeftShift {
1283        /// The value to shift.
1284        value: String,
1285
1286        /// The number of bits to shift.
1287        bits: String,
1288
1289        /// The input base.
1290        #[arg(long)]
1291        base_in: Option<String>,
1292
1293        /// The output base.
1294        #[arg(long, default_value = "16")]
1295        base_out: String,
1296    },
1297
1298    /// Perform a right shifting operation
1299    #[command(name = "shr")]
1300    RightShift {
1301        /// The value to shift.
1302        value: String,
1303
1304        /// The number of bits to shift.
1305        bits: String,
1306
1307        /// The input base,
1308        #[arg(long)]
1309        base_in: Option<String>,
1310
1311        /// The output base,
1312        #[arg(long, default_value = "16")]
1313        base_out: String,
1314    },
1315
1316    /// Get logs by signature or topic
1317    ///
1318    /// Event declarations decode matching logs in text output. Indexed parameters must be marked
1319    /// `indexed` in the declaration. JSON output remains raw.
1320    ///
1321    /// Examples:
1322    /// - cast logs "Transfer(address indexed from, address indexed to, uint256 value)"
1323    /// - cast logs --address $TOKEN --from-block 21000000 --to-block latest $TOPIC_0
1324    #[command(verbatim_doc_comment, visible_alias = "l")]
1325    Logs(LogsArgs),
1326
1327    /// Fetch and decode events from a transaction receipt or log filter.
1328    ///
1329    /// Examples:
1330    /// - cast events $TX_HASH
1331    /// - cast events --tx-hash $TX_HASH
1332    /// - cast events --address $TOKEN --from-block 21000000 --to-block latest
1333    /// - cast events --address $TOKEN "Transfer(address indexed,address indexed,uint256)"
1334    ///
1335    /// A lone 32-byte positional value is treated as a transaction hash. Qualify a raw topic with
1336    /// an address, block range, additional topic, or query size.
1337    #[command(verbatim_doc_comment, visible_alias = "ev")]
1338    Events(EventsArgs),
1339
1340    /// Generate event signatures from event string.
1341    #[command(visible_alias = "se")]
1342    SigEvent {
1343        /// The event string.
1344        event_string: Option<String>,
1345    },
1346
1347    /// Hash arbitrary data using Keccak-256
1348    ///
1349    /// Examples:
1350    /// - cast keccak "hello world"
1351    /// - cast keccak 0xdeadbeef
1352    /// - echo -n "some data" | cast keccak (hash data from stdin)
1353    #[command(verbatim_doc_comment, visible_aliases = &["k", "keccak256"])]
1354    Keccak {
1355        /// The data to hash.
1356        data: Option<String>,
1357    },
1358
1359    /// Hash a message according to EIP-191.
1360    #[command(visible_aliases = &["--hash-message", "hm"])]
1361    HashMessage {
1362        /// The message to hash.
1363        message: Option<String>,
1364    },
1365
1366    /// Get the source code of a contract from a block explorer.
1367    #[command(visible_aliases = &["et", "src"])]
1368    Source {
1369        /// The contract's address.
1370        address: String,
1371
1372        /// Whether to flatten the source code.
1373        #[arg(long, short)]
1374        flatten: bool,
1375
1376        /// The output directory/file to expand source tree into.
1377        #[arg(short, value_hint = ValueHint::DirPath, alias = "path")]
1378        directory: Option<PathBuf>,
1379
1380        #[command(flatten)]
1381        etherscan: EtherscanOpts,
1382
1383        /// Alternative explorer API URL to use that adheres to the Etherscan API. If not provided,
1384        /// defaults to Etherscan.
1385        #[arg(long, env = "EXPLORER_API_URL")]
1386        explorer_api_url: Option<String>,
1387
1388        /// Alternative explorer browser URL.
1389        #[arg(long, env = "EXPLORER_URL")]
1390        explorer_url: Option<String>,
1391    },
1392
1393    /// Wallet management utilities.
1394    #[command(visible_alias = "w")]
1395    Wallet {
1396        #[command(subcommand)]
1397        command: WalletSubcommands,
1398    },
1399
1400    /// Create, propose, and sign Safe transactions.
1401    Safe {
1402        #[command(subcommand)]
1403        command: SafeSubcommand,
1404    },
1405
1406    /// Generate a deterministic contract address using CREATE2.
1407    #[command(visible_alias = "c2")]
1408    Create2(Create2Args),
1409
1410    /// Generate shell completions script.
1411    #[command(visible_alias = "com")]
1412    Completions {
1413        #[arg(value_enum)]
1414        shell: foundry_cli::clap::Shell,
1415    },
1416
1417    /// Decodes a raw signed EIP 2718 typed transaction
1418    #[command(visible_aliases = &["dt", "decode-tx"])]
1419    DecodeTransaction {
1420        /// Encoded transaction
1421        tx: Option<String>,
1422
1423        /// Override the network used to decode the transaction.
1424        ///
1425        /// By default, cast decodes with Foundry's transaction envelope, which recognizes
1426        /// standard Ethereum txs and Foundry-supported network-specific tx types such as Tempo.
1427        #[arg(long, short, num_args = 1, value_name = "NETWORK")]
1428        network: Option<NetworkVariant>,
1429    },
1430
1431    /// Recovery an EIP-7702 authority from a Authorization JSON string.
1432    #[command(visible_aliases = &["decode-auth"])]
1433    RecoverAuthority { auth: String },
1434
1435    /// Inspect the TxPool of a node.
1436    #[command(visible_alias = "tp")]
1437    TxPool {
1438        #[command(subcommand)]
1439        command: TxPoolSubcommands,
1440    },
1441
1442    /// Estimates the data availability size of a given opstack block.
1443    #[cfg(any(feature = "base", feature = "optimism"))]
1444    #[command(name = "da-estimate")]
1445    DAEstimate(DAEstimateArgs),
1446
1447    /// ERC20 token operations.
1448    #[command(visible_alias = "erc20")]
1449    Erc20Token {
1450        #[command(subcommand)]
1451        command: Erc20Subcommand,
1452    },
1453
1454    /// ERC-4626 tokenized vault operations.
1455    #[command(name = "erc4626", visible_alias = "vault")]
1456    Erc4626 {
1457        #[command(subcommand)]
1458        command: Erc4626Subcommand,
1459    },
1460
1461    /// TIP-20 token operations (Tempo).
1462    #[command(visible_alias = "tip20")]
1463    Tip20Token {
1464        #[command(subcommand)]
1465        command: Tip20Subcommand,
1466    },
1467
1468    /// Account-level receive policy operations (Tempo).
1469    #[command(name = "receive-policy")]
1470    ReceivePolicy {
1471        #[command(subcommand)]
1472        command: ReceivePolicySubcommand,
1473    },
1474
1475    /// TIP-403 policy registry operations (Tempo).
1476    #[command(name = "tip403")]
1477    Tip403 {
1478        #[command(subcommand)]
1479        command: Tip403Subcommand,
1480    },
1481
1482    /// T7 storage credits operations (Tempo).
1483    #[command(name = "storage-credits", visible_alias = "sc")]
1484    StorageCredits {
1485        #[command(subcommand)]
1486        command: StorageCreditsSubcommand,
1487    },
1488
1489    /// Tempo keychain (access key) management.
1490    #[command(visible_alias = "kc")]
1491    Keychain {
1492        #[command(subcommand)]
1493        command: KeychainSubcommand,
1494    },
1495
1496    /// Tempo key authorization RLP helpers.
1497    #[command(name = "key-authorization", visible_alias = "key-auth")]
1498    KeyAuthorization {
1499        #[command(subcommand)]
1500        command: KeyAuthorizationSubcommand,
1501    },
1502
1503    /// Tempo wallet and zone operations.
1504    Tempo(TempoArgs),
1505
1506    /// TIP-1022 virtual address registry operations (Tempo).
1507    #[command(visible_alias = "vaddr")]
1508    VirtualAddress {
1509        #[command(subcommand)]
1510        command: VaddrSubcommand,
1511    },
1512
1513    #[command(name = "trace")]
1514    Trace(TraceArgs),
1515}
1516
1517/// CLI arguments for `cast --to-base`.
1518#[derive(Debug, Parser)]
1519pub struct ToBaseArgs {
1520    /// The value to convert.
1521    #[arg(allow_hyphen_values = true)]
1522    pub value: Option<String>,
1523
1524    /// The input base.
1525    #[arg(long, short = 'i')]
1526    pub base_in: Option<String>,
1527}
1528
1529pub fn parse_slot(s: &str) -> Result<B256> {
1530    let slot = U256::from_str(s).map_err(|e| eyre::eyre!("Could not parse slot number: {e}"))?;
1531    Ok(B256::from(slot))
1532}
1533
1534#[cfg(test)]
1535mod tests {
1536    use super::*;
1537    use clap::CommandFactory;
1538
1539    #[test]
1540    fn verify_cli() {
1541        Cast::command().debug_assert();
1542    }
1543
1544    #[test]
1545    fn parse_proof_slot() {
1546        let args: Cast = Cast::parse_from([
1547            "foundry-cli",
1548            "proof",
1549            "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
1550            "0",
1551            "1",
1552            "0x0000000000000000000000000000000000000000000000000000000000000000",
1553            "0x1",
1554            "0x01",
1555        ]);
1556        match args.cmd {
1557            CastSubcommand::Query(QuerySubcommand::Proof { slots, .. }) => {
1558                assert_eq!(
1559                    slots,
1560                    vec![
1561                        B256::ZERO,
1562                        U256::ONE.into(),
1563                        B256::ZERO,
1564                        U256::ONE.into(),
1565                        U256::ONE.into()
1566                    ]
1567                );
1568            }
1569            _ => unreachable!(),
1570        };
1571    }
1572
1573    #[test]
1574    fn parse_call_data() {
1575        let args: Cast = Cast::parse_from([
1576            "foundry-cli",
1577            "calldata",
1578            "f()",
1579            "5c9d55b78febcc2061715ba4f57ecf8ea2711f2c",
1580            "2",
1581        ]);
1582        match args.cmd {
1583            CastSubcommand::Abi(AbiSubcommand::CalldataEncode { args, .. }) => {
1584                assert_eq!(
1585                    args,
1586                    vec!["5c9d55b78febcc2061715ba4f57ecf8ea2711f2c".to_string(), "2".to_string()]
1587                )
1588            }
1589            _ => unreachable!(),
1590        };
1591    }
1592
1593    #[test]
1594    fn parse_call_data_with_file() {
1595        let args: Cast = Cast::parse_from(["foundry-cli", "calldata", "f()", "--file", "test.txt"]);
1596        match args.cmd {
1597            CastSubcommand::Abi(AbiSubcommand::CalldataEncode { sig, file, args }) => {
1598                assert_eq!(sig, "f()".to_string());
1599                assert_eq!(file, Some(PathBuf::from("test.txt")));
1600                assert!(args.is_empty());
1601            }
1602            _ => unreachable!(),
1603        };
1604    }
1605
1606    // <https://github.com/foundry-rs/book/issues/1019>
1607    #[test]
1608    fn parse_signature() {
1609        let args: Cast = Cast::parse_from([
1610            "foundry-cli",
1611            "sig",
1612            "__$_$__$$$$$__$$_$$$_$$__$$___$$(address,address,uint256)",
1613        ]);
1614        match args.cmd {
1615            CastSubcommand::Abi(AbiSubcommand::Sig { sig, .. }) => {
1616                let sig = sig.unwrap();
1617                assert_eq!(
1618                    sig,
1619                    "__$_$__$$$$$__$$_$$$_$$__$$___$$(address,address,uint256)".to_string()
1620                );
1621
1622                let selector = foundry_common::abi::get_func(&sig).unwrap().selector();
1623                assert_eq!(selector.to_string(), "0x23b872dd");
1624            }
1625            _ => unreachable!(),
1626        };
1627    }
1628}