Skip to main content

cast/
opts.rs

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