Skip to main content

cast/
opts.rs

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