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