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