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