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