cast/
opts.rs

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