Skip to main content

cast/
opts.rs

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