cast/
opts.rs

1use crate::cmd::{
2    access_list::AccessListArgs, artifact::ArtifactArgs, bind::BindArgs, call::CallArgs,
3    constructor_args::ConstructorArgsArgs, create2::Create2Args, creation_code::CreationCodeArgs,
4    da_estimate::DAEstimateArgs, estimate::EstimateArgs, find_block::FindBlockArgs,
5    interface::InterfaceArgs, logs::LogsArgs, mktx::MakeTxArgs, rpc::RpcArgs, run::RunArgs,
6    send::SendTxArgs, storage::StorageArgs, txpool::TxPoolSubcommands, wallet::WalletSubcommands,
7};
8use alloy_ens::NameOrAddress;
9use alloy_primitives::{Address, B256, Selector, U256};
10use alloy_rpc_types::BlockId;
11use clap::{Parser, Subcommand, ValueHint};
12use eyre::Result;
13use foundry_cli::opts::{EtherscanOpts, GlobalArgs, RpcOpts};
14use foundry_common::version::{LONG_VERSION, SHORT_VERSION};
15use std::{path::PathBuf, str::FromStr};
16
17/// A Swiss Army knife for interacting with Ethereum applications from the command line.
18#[derive(Parser)]
19#[command(
20    name = "cast",
21    version = SHORT_VERSION,
22    long_version = LONG_VERSION,
23    after_help = "Find more information in the book: https://getfoundry.sh/cast/overview",
24    next_display_order = None,
25)]
26pub struct Cast {
27    /// Include the global arguments.
28    #[command(flatten)]
29    pub global: GlobalArgs,
30
31    #[command(subcommand)]
32    pub cmd: CastSubcommand,
33}
34
35#[derive(Subcommand)]
36pub enum CastSubcommand {
37    /// Prints the maximum value of the given integer type.
38    #[command(visible_aliases = &["--max-int", "maxi"])]
39    MaxInt {
40        /// The integer type to get the maximum value of.
41        #[arg(default_value = "int256")]
42        r#type: String,
43    },
44
45    /// Prints the minimum value of the given integer type.
46    #[command(visible_aliases = &["--min-int", "mini"])]
47    MinInt {
48        /// The integer type to get the minimum value of.
49        #[arg(default_value = "int256")]
50        r#type: String,
51    },
52
53    /// Prints the maximum value of the given integer type.
54    #[command(visible_aliases = &["--max-uint", "maxu"])]
55    MaxUint {
56        /// The unsigned integer type to get the maximum value of.
57        #[arg(default_value = "uint256")]
58        r#type: String,
59    },
60
61    /// Prints the zero address.
62    #[command(visible_aliases = &["--address-zero", "az"])]
63    AddressZero,
64
65    /// Prints the zero hash.
66    #[command(visible_aliases = &["--hash-zero", "hz"])]
67    HashZero,
68
69    /// Convert UTF8 text to hex.
70    #[command(
71        visible_aliases = &[
72        "--from-ascii",
73        "--from-utf8",
74        "from-ascii",
75        "fu",
76        "fa"]
77    )]
78    FromUtf8 {
79        /// The text to convert.
80        text: Option<String>,
81    },
82
83    /// Concatenate hex strings.
84    #[command(visible_aliases = &["--concat-hex", "ch"])]
85    ConcatHex {
86        /// The data to concatenate.
87        data: Vec<String>,
88    },
89
90    /// Convert binary data into hex data.
91    #[command(visible_aliases = &["--from-bin", "from-binx", "fb"])]
92    FromBin,
93
94    /// Normalize the input to lowercase, 0x-prefixed hex.
95    ///
96    /// The input can be:
97    /// - mixed case hex with or without 0x prefix
98    /// - 0x prefixed hex, concatenated with a ':'
99    /// - an absolute path to file
100    /// - @tag, where the tag is defined in an environment variable
101    #[command(visible_aliases = &["--to-hexdata", "thd", "2hd"])]
102    ToHexdata {
103        /// The input to normalize.
104        input: Option<String>,
105    },
106
107    /// Convert an address to a checksummed format (EIP-55).
108    #[command(
109        visible_aliases = &["--to-checksum-address",
110        "--to-checksum",
111        "to-checksum",
112        "ta",
113        "2a"]
114    )]
115    ToCheckSumAddress {
116        /// The address to convert.
117        address: Option<Address>,
118        /// EIP-155 chain ID to encode the address using EIP-1191.
119        chain_id: Option<u64>,
120    },
121
122    /// Convert hex data to an ASCII string.
123    #[command(visible_aliases = &["--to-ascii", "tas", "2as"])]
124    ToAscii {
125        /// The hex data to convert.
126        hexdata: Option<String>,
127    },
128
129    /// Convert hex data to a utf-8 string.
130    #[command(visible_aliases = &["--to-utf8", "tu8", "2u8"])]
131    ToUtf8 {
132        /// The hex data to convert.
133        hexdata: Option<String>,
134    },
135
136    /// Convert a fixed point number into an integer.
137    #[command(visible_aliases = &["--from-fix", "ff"])]
138    FromFixedPoint {
139        /// The number of decimals to use.
140        decimals: Option<String>,
141
142        /// The value to convert.
143        #[arg(allow_hyphen_values = true)]
144        value: Option<String>,
145    },
146
147    /// Right-pads hex data to 32 bytes.
148    #[command(visible_aliases = &["--to-bytes32", "tb", "2b"])]
149    ToBytes32 {
150        /// The hex data to convert.
151        bytes: Option<String>,
152    },
153
154    /// Pads hex data to a specified length.
155    #[command(visible_aliases = &["pd"])]
156    Pad {
157        /// The hex data to pad.
158        data: Option<String>,
159
160        /// Right-pad the data (instead of left-pad).
161        #[arg(long)]
162        right: bool,
163
164        /// Left-pad the data (default).
165        #[arg(long, conflicts_with = "right")]
166        left: bool,
167
168        /// Target length in bytes (default: 32).
169        #[arg(long, default_value = "32")]
170        len: usize,
171    },
172
173    /// Convert an integer into a fixed point number.
174    #[command(visible_aliases = &["--to-fix", "tf", "2f"])]
175    ToFixedPoint {
176        /// The number of decimals to use.
177        decimals: Option<String>,
178
179        /// The value to convert.
180        #[arg(allow_hyphen_values = true)]
181        value: Option<String>,
182    },
183
184    /// Convert a number to a hex-encoded uint256.
185    #[command(name = "to-uint256", visible_aliases = &["--to-uint256", "tu", "2u"])]
186    ToUint256 {
187        /// The value to convert.
188        value: Option<String>,
189    },
190
191    /// Convert a number to a hex-encoded int256.
192    #[command(name = "to-int256", visible_aliases = &["--to-int256", "ti", "2i"])]
193    ToInt256 {
194        /// The value to convert.
195        value: Option<String>,
196    },
197
198    /// Perform a left shifting operation
199    #[command(name = "shl")]
200    LeftShift {
201        /// The value to shift.
202        value: String,
203
204        /// The number of bits to shift.
205        bits: String,
206
207        /// The input base.
208        #[arg(long)]
209        base_in: Option<String>,
210
211        /// The output base.
212        #[arg(long, default_value = "16")]
213        base_out: String,
214    },
215
216    /// Perform a right shifting operation
217    #[command(name = "shr")]
218    RightShift {
219        /// The value to shift.
220        value: String,
221
222        /// The number of bits to shift.
223        bits: String,
224
225        /// The input base,
226        #[arg(long)]
227        base_in: Option<String>,
228
229        /// The output base,
230        #[arg(long, default_value = "16")]
231        base_out: String,
232    },
233
234    /// Convert an ETH amount into another unit (ether, gwei or wei).
235    ///
236    /// Examples:
237    /// - 1ether wei
238    /// - "1 ether" wei
239    /// - 1ether
240    /// - 1 gwei
241    /// - 1gwei ether
242    #[command(visible_aliases = &["--to-unit", "tun", "2un"])]
243    ToUnit {
244        /// The value to convert.
245        value: Option<String>,
246
247        /// The unit to convert to (ether, gwei, wei).
248        #[arg(default_value = "wei")]
249        unit: String,
250    },
251
252    /// Convert a number from decimal to smallest unit with arbitrary decimals.
253    ///
254    /// Examples:
255    /// - 1.0 6    (for USDC, result: 1000000)
256    /// - 2.5 12   (for 12 decimals token, result: 2500000000000)
257    /// - 1.23 3   (for 3 decimals token, result: 1230)
258    #[command(visible_aliases = &["--parse-units", "pun"])]
259    ParseUnits {
260        /// The value to convert.
261        value: Option<String>,
262
263        /// The unit to convert to.
264        #[arg(default_value = "18")]
265        unit: u8,
266    },
267
268    /// Format a number from smallest unit to decimal with arbitrary decimals.
269    ///
270    /// Examples:
271    /// - 1000000 6       (for USDC, result: 1.0)
272    /// - 2500000000000 12 (for 12 decimals, result: 2.5)
273    /// - 1230 3          (for 3 decimals, result: 1.23)
274    #[command(visible_aliases = &["--format-units", "fun"])]
275    FormatUnits {
276        /// The value to format.
277        value: Option<String>,
278
279        /// The unit to format to.
280        #[arg(default_value = "18")]
281        unit: u8,
282    },
283
284    /// Convert an ETH amount to wei.
285    ///
286    /// Consider using --to-unit.
287    #[command(visible_aliases = &["--to-wei", "tw", "2w"])]
288    ToWei {
289        /// The value to convert.
290        #[arg(allow_hyphen_values = true)]
291        value: Option<String>,
292
293        /// The unit to convert from (ether, gwei, wei).
294        #[arg(default_value = "eth")]
295        unit: String,
296    },
297
298    /// Convert wei into an ETH amount.
299    ///
300    /// Consider using --to-unit.
301    #[command(visible_aliases = &["--from-wei", "fw"])]
302    FromWei {
303        /// The value to convert.
304        #[arg(allow_hyphen_values = true)]
305        value: Option<String>,
306
307        /// The unit to convert from (ether, gwei, wei).
308        #[arg(default_value = "eth")]
309        unit: String,
310    },
311
312    /// RLP encodes hex data, or an array of hex data.
313    ///
314    /// Accepts a hex-encoded string, or an array of hex-encoded strings.
315    /// Can be arbitrarily recursive.
316    ///
317    /// Examples:
318    /// - `cast to-rlp "[]"` -> `0xc0`
319    /// - `cast to-rlp "0x22"` -> `0x22`
320    /// - `cast to-rlp "[\"0x61\"]"` -> `0xc161`
321    /// - `cast to-rlp "[\"0xf1\", \"f2\"]"` -> `0xc481f181f2`
322    #[command(visible_aliases = &["--to-rlp"])]
323    ToRlp {
324        /// The value to convert.
325        ///
326        /// This is a hex-encoded string, or an array of hex-encoded strings.
327        /// Can be arbitrarily recursive.
328        value: Option<String>,
329    },
330
331    /// Decodes RLP hex-encoded data.
332    #[command(visible_aliases = &["--from-rlp"])]
333    FromRlp {
334        /// The RLP hex-encoded data.
335        value: Option<String>,
336
337        /// Decode the RLP data as int
338        #[arg(long, alias = "int")]
339        as_int: bool,
340    },
341
342    /// Converts a number of one base to another
343    #[command(visible_aliases = &["--to-hex", "th", "2h"])]
344    ToHex(ToBaseArgs),
345
346    /// Converts a number of one base to decimal
347    #[command(visible_aliases = &["--to-dec", "td", "2d"])]
348    ToDec(ToBaseArgs),
349
350    /// Converts a number of one base to another
351    #[command(
352        visible_aliases = &["--to-base",
353        "--to-radix",
354        "to-radix",
355        "tr",
356        "2r"]
357    )]
358    ToBase {
359        #[command(flatten)]
360        base: ToBaseArgs,
361
362        /// The output base.
363        #[arg(value_name = "BASE")]
364        base_out: Option<String>,
365    },
366    /// Create an access list for a transaction.
367    #[command(visible_aliases = &["ac", "acl"])]
368    AccessList(AccessListArgs),
369    /// Get logs by signature or topic.
370    #[command(visible_alias = "l")]
371    Logs(LogsArgs),
372    /// Get information about a block.
373    #[command(visible_alias = "bl")]
374    Block {
375        /// The block height to query at.
376        ///
377        /// Can also be the tags earliest, finalized, safe, latest, or pending.
378        block: Option<BlockId>,
379
380        /// If specified, only get the given field of the block.
381        #[arg(long, short)]
382        field: Option<String>,
383
384        /// Print the raw RLP encoded block header.
385        #[arg(long, conflicts_with = "field")]
386        raw: bool,
387
388        #[arg(long, env = "CAST_FULL_BLOCK")]
389        full: bool,
390
391        #[command(flatten)]
392        rpc: RpcOpts,
393    },
394
395    /// Get the latest block number.
396    #[command(visible_alias = "bn")]
397    BlockNumber {
398        /// The hash or tag to query. If not specified, the latest number is returned.
399        block: Option<BlockId>,
400        #[command(flatten)]
401        rpc: RpcOpts,
402    },
403
404    /// Perform a call on an account without publishing a transaction.
405    #[command(visible_alias = "c")]
406    Call(CallArgs),
407
408    /// ABI-encode a function with arguments.
409    #[command(name = "calldata", visible_alias = "cd")]
410    CalldataEncode {
411        /// The function signature in the format `<name>(<in-types>)(<out-types>)`
412        sig: String,
413
414        /// The arguments to encode.
415        #[arg(allow_hyphen_values = true)]
416        args: Vec<String>,
417
418        // Path to file containing arguments to encode.
419        #[arg(long, value_name = "PATH")]
420        file: Option<PathBuf>,
421    },
422
423    /// Get the symbolic name of the current chain.
424    Chain {
425        #[command(flatten)]
426        rpc: RpcOpts,
427    },
428
429    /// Get the Ethereum chain ID.
430    #[command(visible_aliases = &["ci", "cid"])]
431    ChainId {
432        #[command(flatten)]
433        rpc: RpcOpts,
434    },
435
436    /// Get the current client version.
437    #[command(visible_alias = "cl")]
438    Client {
439        #[command(flatten)]
440        rpc: RpcOpts,
441    },
442
443    /// Compute the contract address from a given nonce and deployer address.
444    #[command(visible_alias = "ca")]
445    ComputeAddress {
446        /// The deployer address.
447        address: Option<Address>,
448
449        /// The nonce of the deployer address.
450        #[arg(
451            long,
452            conflicts_with = "salt",
453            conflicts_with = "init_code",
454            conflicts_with = "init_code_hash"
455        )]
456        nonce: Option<u64>,
457
458        /// The salt for CREATE2 address computation.
459        #[arg(long, conflicts_with = "nonce")]
460        salt: Option<B256>,
461
462        /// The init code for CREATE2 address computation.
463        #[arg(
464            long,
465            requires = "salt",
466            conflicts_with = "init_code_hash",
467            conflicts_with = "nonce"
468        )]
469        init_code: Option<String>,
470
471        /// The init code hash for CREATE2 address computation.
472        #[arg(long, requires = "salt", conflicts_with = "init_code", conflicts_with = "nonce")]
473        init_code_hash: Option<B256>,
474
475        #[command(flatten)]
476        rpc: RpcOpts,
477    },
478
479    /// Disassembles a hex-encoded bytecode into a human-readable representation.
480    #[command(visible_alias = "da")]
481    Disassemble {
482        /// The hex-encoded bytecode.
483        bytecode: Option<String>,
484    },
485
486    /// Build and sign a transaction.
487    #[command(name = "mktx", visible_alias = "m")]
488    MakeTx(MakeTxArgs),
489
490    /// Calculate the ENS namehash of a name.
491    #[command(visible_aliases = &["na", "nh"])]
492    Namehash { name: Option<String> },
493
494    /// Get information about a transaction.
495    #[command(visible_alias = "t")]
496    Tx {
497        /// The transaction hash.
498        tx_hash: Option<String>,
499
500        /// The sender of the transaction.
501        #[arg(long, value_parser = NameOrAddress::from_str)]
502        from: Option<NameOrAddress>,
503
504        /// Nonce of the transaction.
505        #[arg(long)]
506        nonce: Option<u64>,
507
508        /// If specified, only get the given field of the transaction. If "raw", the RLP encoded
509        /// transaction will be printed.
510        field: Option<String>,
511
512        /// Print the raw RLP encoded transaction.
513        #[arg(long, conflicts_with = "field")]
514        raw: bool,
515
516        #[command(flatten)]
517        rpc: RpcOpts,
518
519        /// If specified, the transaction will be converted to a TransactionRequest JSON format.
520        #[arg(long)]
521        to_request: bool,
522    },
523
524    /// Get the transaction receipt for a transaction.
525    #[command(visible_alias = "re")]
526    Receipt {
527        /// The transaction hash.
528        tx_hash: String,
529
530        /// If specified, only get the given field of the transaction.
531        field: Option<String>,
532
533        /// The number of confirmations until the receipt is fetched
534        #[arg(long, default_value = "1")]
535        confirmations: u64,
536
537        /// Exit immediately if the transaction was not found.
538        #[arg(id = "async", long = "async", env = "CAST_ASYNC", alias = "cast-async")]
539        cast_async: bool,
540
541        #[command(flatten)]
542        rpc: RpcOpts,
543    },
544
545    /// Sign and publish a transaction.
546    #[command(name = "send", visible_alias = "s")]
547    SendTx(SendTxArgs),
548
549    /// Publish a raw transaction to the network.
550    #[command(name = "publish", visible_alias = "p")]
551    PublishTx {
552        /// The raw transaction
553        raw_tx: String,
554
555        /// Only print the transaction hash and exit immediately.
556        #[arg(id = "async", long = "async", env = "CAST_ASYNC", alias = "cast-async")]
557        cast_async: bool,
558
559        #[command(flatten)]
560        rpc: RpcOpts,
561    },
562
563    /// Estimate the gas cost of a transaction.
564    #[command(visible_alias = "e")]
565    Estimate(EstimateArgs),
566
567    /// Decode ABI-encoded input data.
568    ///
569    /// Similar to `abi-decode --input`, but function selector MUST be prefixed in `calldata`
570    /// string
571    #[command(visible_aliases = &["calldata-decode", "--calldata-decode", "cdd"])]
572    DecodeCalldata {
573        /// The function signature in the format `<name>(<in-types>)(<out-types>)`.
574        sig: String,
575
576        /// The ABI-encoded calldata.
577        #[arg(required_unless_present = "file", index = 2)]
578        calldata: Option<String>,
579
580        /// Load ABI-encoded calldata from a file instead.
581        #[arg(long = "file", short = 'f', conflicts_with = "calldata")]
582        file: Option<PathBuf>,
583    },
584
585    /// Decode ABI-encoded string.
586    ///
587    /// Similar to `calldata-decode --input`, but the function argument is a `string`
588    #[command(visible_aliases = &["string-decode", "--string-decode", "sd"])]
589    DecodeString {
590        /// The ABI-encoded string.
591        data: String,
592    },
593
594    /// Decode event data.
595    #[command(visible_aliases = &["event-decode", "--event-decode", "ed"])]
596    DecodeEvent {
597        /// The event signature. If none provided then tries to decode from local cache or <https://api.openchain.xyz>.
598        #[arg(long, visible_alias = "event-sig")]
599        sig: Option<String>,
600        /// The event data to decode.
601        data: String,
602    },
603
604    /// Decode custom error data.
605    #[command(visible_aliases = &["error-decode", "--error-decode", "erd"])]
606    DecodeError {
607        /// The error signature. If none provided then tries to decode from local cache or <https://api.openchain.xyz>.
608        #[arg(long, visible_alias = "error-sig")]
609        sig: Option<String>,
610        /// The error data to decode.
611        data: String,
612    },
613
614    /// Decode ABI-encoded input or output data.
615    ///
616    /// Defaults to decoding output data. To decode input data pass --input.
617    ///
618    /// When passing `--input`, function selector must NOT be prefixed in `calldata` string
619    #[command(name = "decode-abi", visible_aliases = &["abi-decode", "--abi-decode", "ad"])]
620    DecodeAbi {
621        /// The function signature in the format `<name>(<in-types>)(<out-types>)`.
622        sig: String,
623
624        /// The ABI-encoded calldata.
625        calldata: String,
626
627        /// Whether to decode the input or output data.
628        #[arg(long, short, help_heading = "Decode input data instead of output data")]
629        input: bool,
630    },
631
632    /// ABI encode the given function argument, excluding the selector.
633    #[command(visible_alias = "ae")]
634    AbiEncode {
635        /// The function signature.
636        sig: String,
637
638        /// Whether to use packed encoding.
639        #[arg(long)]
640        packed: bool,
641
642        /// The arguments of the function.
643        #[arg(allow_hyphen_values = true)]
644        args: Vec<String>,
645    },
646
647    /// ABI encode an event and its arguments to generate topics and data.
648    #[command(visible_alias = "aee")]
649    AbiEncodeEvent {
650        /// The event signature.
651        sig: String,
652
653        /// The arguments of the event.
654        #[arg(allow_hyphen_values = true)]
655        args: Vec<String>,
656    },
657
658    /// Compute the storage slot for an entry in a mapping.
659    #[command(visible_alias = "in")]
660    Index {
661        /// The mapping key type.
662        key_type: String,
663
664        /// The mapping key.
665        key: String,
666
667        /// The storage slot of the mapping.
668        slot_number: String,
669    },
670
671    /// Compute storage slots as specified by `ERC-7201: Namespaced Storage Layout`.
672    #[command(name = "index-erc7201", alias = "index-erc-7201", visible_aliases = &["index7201", "in7201"])]
673    IndexErc7201 {
674        /// The arbitrary identifier.
675        id: Option<String>,
676        /// The formula ID. Currently the only supported formula is `erc7201`.
677        #[arg(long, default_value = "erc7201")]
678        formula_id: String,
679    },
680
681    /// Fetch the EIP-1967 implementation for a contract
682    /// Can read from the implementation slot or the beacon slot.
683    #[command(visible_alias = "impl")]
684    Implementation {
685        /// The block height to query at.
686        ///
687        /// Can also be the tags earliest, finalized, safe, latest, or pending.
688        #[arg(long, short = 'B')]
689        block: Option<BlockId>,
690
691        /// Fetch the implementation from the beacon slot.
692        ///
693        /// If not specified, the implementation slot is used.
694        #[arg(long)]
695        beacon: bool,
696
697        /// The address for which the implementation will be fetched.
698        #[arg(value_parser = NameOrAddress::from_str)]
699        who: NameOrAddress,
700
701        #[command(flatten)]
702        rpc: RpcOpts,
703    },
704
705    /// Fetch the EIP-1967 admin account
706    #[command(visible_alias = "adm")]
707    Admin {
708        /// The block height to query at.
709        ///
710        /// Can also be the tags earliest, finalized, safe, latest, or pending.
711        #[arg(long, short = 'B')]
712        block: Option<BlockId>,
713
714        /// The address from which the admin account will be fetched.
715        #[arg(value_parser = NameOrAddress::from_str)]
716        who: NameOrAddress,
717
718        #[command(flatten)]
719        rpc: RpcOpts,
720    },
721
722    /// Get the function signatures for the given selector from <https://openchain.xyz>.
723    #[command(name = "4byte", visible_aliases = &["4", "4b"])]
724    FourByte {
725        /// The function selector.
726        selector: Option<Selector>,
727    },
728
729    /// Decode ABI-encoded calldata using <https://openchain.xyz>.
730    #[command(name = "4byte-calldata", aliases = &["4byte-decode", "4d", "4bd"], visible_aliases = &["4c", "4bc"])]
731    FourByteCalldata {
732        /// The ABI-encoded calldata.
733        calldata: Option<String>,
734    },
735
736    /// Get the event signature for a given topic 0 from <https://openchain.xyz>.
737    #[command(name = "4byte-event", visible_aliases = &["4e", "4be", "topic0-event", "t0e"])]
738    FourByteEvent {
739        /// Topic 0
740        #[arg(value_name = "TOPIC_0")]
741        topic: Option<B256>,
742    },
743
744    /// Upload the given signatures to <https://openchain.xyz>.
745    ///
746    /// Example inputs:
747    /// - "transfer(address,uint256)"
748    /// - "function transfer(address,uint256)"
749    /// - "function transfer(address,uint256)" "event Transfer(address,address,uint256)"
750    /// - "./out/Contract.sol/Contract.json"
751    #[command(visible_aliases = &["ups"])]
752    UploadSignature {
753        /// The signatures to upload.
754        ///
755        /// Prefix with 'function', 'event', or 'error'. Defaults to function if no prefix given.
756        /// Can also take paths to contract artifact JSON.
757        signatures: Vec<String>,
758    },
759
760    /// Pretty print calldata.
761    ///
762    /// Tries to decode the calldata using <https://openchain.xyz> unless --offline is passed.
763    #[command(visible_alias = "pc")]
764    PrettyCalldata {
765        /// The calldata.
766        calldata: Option<String>,
767
768        /// Skip the <https://openchain.xyz> lookup.
769        #[arg(long, short)]
770        offline: bool,
771    },
772
773    /// Get the timestamp of a block.
774    #[command(visible_alias = "a")]
775    Age {
776        /// The block height to query at.
777        ///
778        /// Can also be the tags earliest, finalized, safe, latest, or pending.
779        block: Option<BlockId>,
780
781        #[command(flatten)]
782        rpc: RpcOpts,
783    },
784
785    /// Get the balance of an account in wei.
786    #[command(visible_alias = "b")]
787    Balance {
788        /// The block height to query at.
789        ///
790        /// Can also be the tags earliest, finalized, safe, latest, or pending.
791        #[arg(long, short = 'B')]
792        block: Option<BlockId>,
793
794        /// The account to query.
795        #[arg(value_parser = NameOrAddress::from_str)]
796        who: NameOrAddress,
797
798        /// Format the balance in ether.
799        #[arg(long, short)]
800        ether: bool,
801
802        #[command(flatten)]
803        rpc: RpcOpts,
804
805        /// erc20 address to query, with the method `balanceOf(address) return (uint256)`, alias
806        /// with '--erc721'
807        #[arg(long, alias = "erc721")]
808        erc20: Option<Address>,
809    },
810
811    /// Get the basefee of a block.
812    #[command(visible_aliases = &["ba", "fee", "basefee"])]
813    BaseFee {
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        #[command(flatten)]
820        rpc: RpcOpts,
821    },
822
823    /// Get the runtime bytecode of a contract.
824    #[command(visible_alias = "co")]
825    Code {
826        /// The block height to query at.
827        ///
828        /// Can also be the tags earliest, finalized, safe, latest, or pending.
829        #[arg(long, short = 'B')]
830        block: Option<BlockId>,
831
832        /// The contract address.
833        #[arg(value_parser = NameOrAddress::from_str)]
834        who: NameOrAddress,
835
836        /// Disassemble bytecodes.
837        #[arg(long, short)]
838        disassemble: bool,
839
840        #[command(flatten)]
841        rpc: RpcOpts,
842    },
843
844    /// Get the runtime bytecode size of a contract.
845    #[command(visible_alias = "cs")]
846    Codesize {
847        /// The block height to query at.
848        ///
849        /// Can also be the tags earliest, finalized, safe, latest, or pending.
850        #[arg(long, short = 'B')]
851        block: Option<BlockId>,
852
853        /// The contract address.
854        #[arg(value_parser = NameOrAddress::from_str)]
855        who: NameOrAddress,
856
857        #[command(flatten)]
858        rpc: RpcOpts,
859    },
860
861    /// Get the current gas price.
862    #[command(visible_alias = "g")]
863    GasPrice {
864        #[command(flatten)]
865        rpc: RpcOpts,
866    },
867
868    /// Generate event signatures from event string.
869    #[command(visible_alias = "se")]
870    SigEvent {
871        /// The event string.
872        event_string: Option<String>,
873    },
874
875    /// Hash arbitrary data using Keccak-256.
876    #[command(visible_aliases = &["k", "keccak256"])]
877    Keccak {
878        /// The data to hash.
879        data: Option<String>,
880    },
881
882    /// Hash a message according to EIP-191.
883    #[command(visible_aliases = &["--hash-message", "hm"])]
884    HashMessage {
885        /// The message to hash.
886        message: Option<String>,
887    },
888
889    /// Perform an ENS lookup.
890    #[command(visible_alias = "rn")]
891    ResolveName {
892        /// The name to lookup.
893        who: Option<String>,
894
895        /// Perform a reverse lookup to verify that the name is correct.
896        #[arg(long)]
897        verify: bool,
898
899        #[command(flatten)]
900        rpc: RpcOpts,
901    },
902
903    /// Perform an ENS reverse lookup.
904    #[command(visible_alias = "la")]
905    LookupAddress {
906        /// The account to perform the lookup for.
907        who: Option<Address>,
908
909        /// Perform a normal lookup to verify that the address is correct.
910        #[arg(long)]
911        verify: bool,
912
913        #[command(flatten)]
914        rpc: RpcOpts,
915    },
916
917    /// Get the raw value of a contract's storage slot.
918    #[command(visible_alias = "st")]
919    Storage(StorageArgs),
920
921    /// Generate a storage proof for a given storage slot.
922    #[command(visible_alias = "pr")]
923    Proof {
924        /// The contract address.
925        #[arg(value_parser = NameOrAddress::from_str)]
926        address: NameOrAddress,
927
928        /// The storage slot numbers (hex or decimal).
929        #[arg(value_parser = parse_slot)]
930        slots: Vec<B256>,
931
932        /// The block height to query at.
933        ///
934        /// Can also be the tags earliest, finalized, safe, latest, or pending.
935        #[arg(long, short = 'B')]
936        block: Option<BlockId>,
937
938        #[command(flatten)]
939        rpc: RpcOpts,
940    },
941
942    /// Get the nonce for an account.
943    #[command(visible_alias = "n")]
944    Nonce {
945        /// The block height to query at.
946        ///
947        /// Can also be the tags earliest, finalized, safe, latest, or pending.
948        #[arg(long, short = 'B')]
949        block: Option<BlockId>,
950
951        /// The address to get the nonce for.
952        #[arg(value_parser = NameOrAddress::from_str)]
953        who: NameOrAddress,
954
955        #[command(flatten)]
956        rpc: RpcOpts,
957    },
958
959    /// Get the codehash for an account.
960    #[command()]
961    Codehash {
962        /// The block height to query at.
963        ///
964        /// Can also be the tags earliest, finalized, safe, latest, or pending.
965        #[arg(long, short = 'B')]
966        block: Option<BlockId>,
967
968        /// The address to get the codehash for.
969        #[arg(value_parser = NameOrAddress::from_str)]
970        who: NameOrAddress,
971
972        /// The storage slot numbers (hex or decimal).
973        #[arg(value_parser = parse_slot)]
974        slots: Vec<B256>,
975
976        #[command(flatten)]
977        rpc: RpcOpts,
978    },
979
980    /// Get the storage root for an account.
981    #[command(visible_alias = "sr")]
982    StorageRoot {
983        /// The block height to query at.
984        ///
985        /// Can also be the tags earliest, finalized, safe, latest, or pending.
986        #[arg(long, short = 'B')]
987        block: Option<BlockId>,
988
989        /// The address to get the storage root for.
990        #[arg(value_parser = NameOrAddress::from_str)]
991        who: NameOrAddress,
992
993        /// The storage slot numbers (hex or decimal).
994        #[arg(value_parser = parse_slot)]
995        slots: Vec<B256>,
996
997        #[command(flatten)]
998        rpc: RpcOpts,
999    },
1000
1001    /// Get the source code of a contract from a block explorer.
1002    #[command(visible_aliases = &["et", "src"])]
1003    Source {
1004        /// The contract's address.
1005        address: String,
1006
1007        /// Whether to flatten the source code.
1008        #[arg(long, short)]
1009        flatten: bool,
1010
1011        /// The output directory/file to expand source tree into.
1012        #[arg(short, value_hint = ValueHint::DirPath, alias = "path")]
1013        directory: Option<PathBuf>,
1014
1015        #[command(flatten)]
1016        etherscan: EtherscanOpts,
1017
1018        /// Alternative explorer API URL to use that adheres to the Etherscan API. If not provided,
1019        /// defaults to Etherscan.
1020        #[arg(long, env = "EXPLORER_API_URL")]
1021        explorer_api_url: Option<String>,
1022
1023        /// Alternative explorer browser URL.
1024        #[arg(long, env = "EXPLORER_URL")]
1025        explorer_url: Option<String>,
1026    },
1027
1028    /// Wallet management utilities.
1029    #[command(visible_alias = "w")]
1030    Wallet {
1031        #[command(subcommand)]
1032        command: WalletSubcommands,
1033    },
1034
1035    /// Download a contract creation code from Etherscan and RPC.
1036    #[command(visible_alias = "cc")]
1037    CreationCode(CreationCodeArgs),
1038
1039    /// Generate an artifact file, that can be used to deploy a contract locally.
1040    #[command(visible_alias = "ar")]
1041    Artifact(ArtifactArgs),
1042
1043    /// Display constructor arguments used for the contract initialization.
1044    #[command(visible_alias = "cra")]
1045    ConstructorArgs(ConstructorArgsArgs),
1046
1047    /// Generate a Solidity interface from a given ABI.
1048    ///
1049    /// Currently does not support ABI encoder v2.
1050    #[command(visible_alias = "i")]
1051    Interface(InterfaceArgs),
1052
1053    /// Generate a rust binding from a given ABI.
1054    #[command(visible_alias = "bi")]
1055    Bind(BindArgs),
1056
1057    /// Get the selector for a function.
1058    #[command(visible_alias = "si")]
1059    Sig {
1060        /// The function signature, e.g. transfer(address,uint256).
1061        sig: Option<String>,
1062
1063        /// Optimize signature to contain provided amount of leading zeroes in selector.
1064        optimize: Option<usize>,
1065    },
1066
1067    /// Generate a deterministic contract address using CREATE2.
1068    #[command(visible_alias = "c2")]
1069    Create2(Create2Args),
1070
1071    /// Get the block number closest to the provided timestamp.
1072    #[command(visible_alias = "f")]
1073    FindBlock(FindBlockArgs),
1074
1075    /// Generate shell completions script.
1076    #[command(visible_alias = "com")]
1077    Completions {
1078        #[arg(value_enum)]
1079        shell: foundry_common::clap::Shell,
1080    },
1081
1082    /// Generate Fig autocompletion spec.
1083    #[command(visible_alias = "fig")]
1084    GenerateFigSpec,
1085
1086    /// Runs a published transaction in a local environment and prints the trace.
1087    #[command(visible_alias = "r")]
1088    Run(RunArgs),
1089
1090    /// Perform a raw JSON-RPC request.
1091    #[command(visible_alias = "rp")]
1092    Rpc(RpcArgs),
1093
1094    /// Formats a string into bytes32 encoding.
1095    #[command(name = "format-bytes32-string", visible_aliases = &["--format-bytes32-string"])]
1096    FormatBytes32String {
1097        /// The string to format.
1098        string: Option<String>,
1099    },
1100
1101    /// Parses a string from bytes32 encoding.
1102    #[command(name = "parse-bytes32-string", visible_aliases = &["--parse-bytes32-string"])]
1103    ParseBytes32String {
1104        /// The string to parse.
1105        bytes: Option<String>,
1106    },
1107    #[command(name = "parse-bytes32-address", visible_aliases = &["--parse-bytes32-address"])]
1108    #[command(about = "Parses a checksummed address from bytes32 encoding.")]
1109    ParseBytes32Address {
1110        #[arg(value_name = "BYTES")]
1111        bytes: Option<String>,
1112    },
1113
1114    /// Decodes a raw signed EIP 2718 typed transaction
1115    #[command(visible_aliases = &["dt", "decode-tx"])]
1116    DecodeTransaction { tx: Option<String> },
1117
1118    /// Recovery an EIP-7702 authority from a Authorization JSON string.
1119    #[command(visible_aliases = &["decode-auth"])]
1120    RecoverAuthority { auth: String },
1121
1122    /// Extracts function selectors and arguments from bytecode
1123    #[command(visible_alias = "sel")]
1124    Selectors {
1125        /// The hex-encoded bytecode.
1126        bytecode: Option<String>,
1127
1128        /// Resolve the function signatures for the extracted selectors using <https://openchain.xyz>
1129        #[arg(long, short)]
1130        resolve: bool,
1131    },
1132
1133    /// Inspect the TxPool of a node.
1134    #[command(visible_alias = "tp")]
1135    TxPool {
1136        #[command(subcommand)]
1137        command: TxPoolSubcommands,
1138    },
1139    /// Estimates the data availability size of a given opstack block.
1140    #[command(name = "da-estimate")]
1141    DAEstimate(DAEstimateArgs),
1142}
1143
1144/// CLI arguments for `cast --to-base`.
1145#[derive(Debug, Parser)]
1146pub struct ToBaseArgs {
1147    /// The value to convert.
1148    #[arg(allow_hyphen_values = true)]
1149    pub value: Option<String>,
1150
1151    /// The input base.
1152    #[arg(long, short = 'i')]
1153    pub base_in: Option<String>,
1154}
1155
1156pub fn parse_slot(s: &str) -> Result<B256> {
1157    let slot = U256::from_str(s).map_err(|e| eyre::eyre!("Could not parse slot number: {e}"))?;
1158    Ok(B256::from(slot))
1159}
1160
1161#[cfg(test)]
1162mod tests {
1163    use super::*;
1164    use crate::SimpleCast;
1165    use alloy_rpc_types::{BlockNumberOrTag, RpcBlockHash};
1166    use clap::CommandFactory;
1167
1168    #[test]
1169    fn verify_cli() {
1170        Cast::command().debug_assert();
1171    }
1172
1173    #[test]
1174    fn parse_proof_slot() {
1175        let args: Cast = Cast::parse_from([
1176            "foundry-cli",
1177            "proof",
1178            "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
1179            "0",
1180            "1",
1181            "0x0000000000000000000000000000000000000000000000000000000000000000",
1182            "0x1",
1183            "0x01",
1184        ]);
1185        match args.cmd {
1186            CastSubcommand::Proof { slots, .. } => {
1187                assert_eq!(
1188                    slots,
1189                    vec![
1190                        B256::ZERO,
1191                        U256::from(1).into(),
1192                        B256::ZERO,
1193                        U256::from(1).into(),
1194                        U256::from(1).into()
1195                    ]
1196                );
1197            }
1198            _ => unreachable!(),
1199        };
1200    }
1201
1202    #[test]
1203    fn parse_call_data() {
1204        let args: Cast = Cast::parse_from([
1205            "foundry-cli",
1206            "calldata",
1207            "f()",
1208            "5c9d55b78febcc2061715ba4f57ecf8ea2711f2c",
1209            "2",
1210        ]);
1211        match args.cmd {
1212            CastSubcommand::CalldataEncode { args, .. } => {
1213                assert_eq!(
1214                    args,
1215                    vec!["5c9d55b78febcc2061715ba4f57ecf8ea2711f2c".to_string(), "2".to_string()]
1216                )
1217            }
1218            _ => unreachable!(),
1219        };
1220    }
1221
1222    #[test]
1223    fn parse_call_data_with_file() {
1224        let args: Cast = Cast::parse_from(["foundry-cli", "calldata", "f()", "--file", "test.txt"]);
1225        match args.cmd {
1226            CastSubcommand::CalldataEncode { sig, file, args } => {
1227                assert_eq!(sig, "f()".to_string());
1228                assert_eq!(file, Some(PathBuf::from("test.txt")));
1229                assert!(args.is_empty());
1230            }
1231            _ => unreachable!(),
1232        };
1233    }
1234
1235    // <https://github.com/foundry-rs/book/issues/1019>
1236    #[test]
1237    fn parse_signature() {
1238        let args: Cast = Cast::parse_from([
1239            "foundry-cli",
1240            "sig",
1241            "__$_$__$$$$$__$$_$$$_$$__$$___$$(address,address,uint256)",
1242        ]);
1243        match args.cmd {
1244            CastSubcommand::Sig { sig, .. } => {
1245                let sig = sig.unwrap();
1246                assert_eq!(
1247                    sig,
1248                    "__$_$__$$$$$__$$_$$$_$$__$$___$$(address,address,uint256)".to_string()
1249                );
1250
1251                let selector = SimpleCast::get_selector(&sig, 0).unwrap();
1252                assert_eq!(selector.0, "0x23b872dd".to_string());
1253            }
1254            _ => unreachable!(),
1255        };
1256    }
1257
1258    #[test]
1259    fn parse_block_ids() {
1260        struct TestCase {
1261            input: String,
1262            expect: BlockId,
1263        }
1264
1265        let test_cases = [
1266            TestCase {
1267                input: "0".to_string(),
1268                expect: BlockId::Number(BlockNumberOrTag::Number(0u64)),
1269            },
1270            TestCase {
1271                input: "0x56462c47c03df160f66819f0a79ea07def1569f8aac0fe91bb3a081159b61b4a"
1272                    .to_string(),
1273                expect: BlockId::Hash(RpcBlockHash::from_hash(
1274                    "0x56462c47c03df160f66819f0a79ea07def1569f8aac0fe91bb3a081159b61b4a"
1275                        .parse()
1276                        .unwrap(),
1277                    None,
1278                )),
1279            },
1280            TestCase {
1281                input: "latest".to_string(),
1282                expect: BlockId::Number(BlockNumberOrTag::Latest),
1283            },
1284            TestCase {
1285                input: "earliest".to_string(),
1286                expect: BlockId::Number(BlockNumberOrTag::Earliest),
1287            },
1288            TestCase {
1289                input: "pending".to_string(),
1290                expect: BlockId::Number(BlockNumberOrTag::Pending),
1291            },
1292            TestCase { input: "safe".to_string(), expect: BlockId::Number(BlockNumberOrTag::Safe) },
1293            TestCase {
1294                input: "finalized".to_string(),
1295                expect: BlockId::Number(BlockNumberOrTag::Finalized),
1296            },
1297        ];
1298
1299        for test in test_cases {
1300            let result: BlockId = test.input.parse().unwrap();
1301            assert_eq!(result, test.expect);
1302        }
1303    }
1304}