Skip to main content

cast/
opts.rs

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