cast/
args.rs

1use crate::{
2    Cast, SimpleCast,
3    cmd::erc20::IERC20,
4    opts::{Cast as CastArgs, CastSubcommand, ToBaseArgs},
5    traces::identifier::SignaturesIdentifier,
6};
7use alloy_consensus::transaction::{Recovered, SignerRecoverable};
8use alloy_dyn_abi::{DynSolValue, ErrorExt, EventExt};
9use alloy_eips::eip7702::SignedAuthorization;
10use alloy_ens::{ProviderEnsExt, namehash};
11use alloy_primitives::{Address, B256, eip191_hash_message, hex, keccak256};
12use alloy_provider::Provider;
13use alloy_rpc_types::{BlockId, BlockNumberOrTag::Latest};
14use clap::{CommandFactory, Parser};
15use clap_complete::generate;
16use eyre::Result;
17use foundry_cli::{utils, utils::LoadConfig};
18use foundry_common::{
19    abi::{get_error, get_event},
20    fmt::{format_tokens, format_uint_exp, serialize_value_as_json},
21    fs,
22    selectors::{
23        ParsedSignatures, SelectorImportData, SelectorKind, decode_calldata, decode_event_topic,
24        decode_function_selector, decode_selectors, import_selectors, parse_signatures,
25        pretty_calldata,
26    },
27    shell, stdin,
28};
29use std::time::Instant;
30
31/// Run the `cast` command-line interface.
32pub fn run() -> Result<()> {
33    setup()?;
34
35    let args = CastArgs::parse();
36    args.global.init()?;
37    args.global.tokio_runtime().block_on(run_command(args))
38}
39
40/// Setup the global logger and other utilities.
41pub fn setup() -> Result<()> {
42    utils::common_setup();
43    utils::subscriber();
44
45    Ok(())
46}
47
48/// Run the subcommand.
49pub async fn run_command(args: CastArgs) -> Result<()> {
50    match args.cmd {
51        // Constants
52        CastSubcommand::MaxInt { r#type } => {
53            sh_println!("{}", SimpleCast::max_int(&r#type)?)?;
54        }
55        CastSubcommand::MinInt { r#type } => {
56            sh_println!("{}", SimpleCast::min_int(&r#type)?)?;
57        }
58        CastSubcommand::MaxUint { r#type } => {
59            sh_println!("{}", SimpleCast::max_int(&r#type)?)?;
60        }
61        CastSubcommand::AddressZero => {
62            sh_println!("{:?}", Address::ZERO)?;
63        }
64        CastSubcommand::HashZero => {
65            sh_println!("{:?}", B256::ZERO)?;
66        }
67
68        // Conversions & transformations
69        CastSubcommand::FromUtf8 { text } => {
70            let value = stdin::unwrap(text, false)?;
71            sh_println!("{}", SimpleCast::from_utf8(&value))?
72        }
73        CastSubcommand::ToAscii { hexdata } => {
74            let value = stdin::unwrap(hexdata, false)?;
75            sh_println!("{}", SimpleCast::to_ascii(value.trim())?)?
76        }
77        CastSubcommand::ToUtf8 { hexdata } => {
78            let value = stdin::unwrap(hexdata, false)?;
79            sh_println!("{}", SimpleCast::to_utf8(&value)?)?
80        }
81        CastSubcommand::FromFixedPoint { value, decimals } => {
82            let (value, decimals) = stdin::unwrap2(value, decimals)?;
83            sh_println!("{}", SimpleCast::from_fixed_point(&value, &decimals)?)?
84        }
85        CastSubcommand::ToFixedPoint { value, decimals } => {
86            let (value, decimals) = stdin::unwrap2(value, decimals)?;
87            sh_println!("{}", SimpleCast::to_fixed_point(&value, &decimals)?)?
88        }
89        CastSubcommand::ConcatHex { data } => {
90            if data.is_empty() {
91                let s = stdin::read(true)?;
92                sh_println!("{}", SimpleCast::concat_hex(s.split_whitespace()))?
93            } else {
94                sh_println!("{}", SimpleCast::concat_hex(data))?
95            }
96        }
97        CastSubcommand::FromBin => {
98            let hex = stdin::read_bytes(false)?;
99            sh_println!("{}", hex::encode_prefixed(hex))?
100        }
101        CastSubcommand::ToHexdata { input } => {
102            let value = stdin::unwrap_line(input)?;
103            let output = match value {
104                s if s.starts_with('@') => hex::encode(std::env::var(&s[1..])?),
105                s if s.starts_with('/') => hex::encode(fs::read(s)?),
106                s => s.split(':').map(|s| s.trim_start_matches("0x").to_lowercase()).collect(),
107            };
108            sh_println!("0x{output}")?
109        }
110        CastSubcommand::ToCheckSumAddress { address, chain_id } => {
111            let value = stdin::unwrap_line(address)?;
112            sh_println!("{}", value.to_checksum(chain_id))?
113        }
114        CastSubcommand::ToUint256 { value } => {
115            let value = stdin::unwrap_line(value)?;
116            sh_println!("{}", SimpleCast::to_uint256(&value)?)?
117        }
118        CastSubcommand::ToInt256 { value } => {
119            let value = stdin::unwrap_line(value)?;
120            sh_println!("{}", SimpleCast::to_int256(&value)?)?
121        }
122        CastSubcommand::ToUnit { value, unit } => {
123            let value = stdin::unwrap_line(value)?;
124            sh_println!("{}", SimpleCast::to_unit(&value, &unit)?)?
125        }
126        CastSubcommand::ParseUnits { value, unit } => {
127            let value = stdin::unwrap_line(value)?;
128            sh_println!("{}", SimpleCast::parse_units(&value, unit)?)?;
129        }
130        CastSubcommand::FormatUnits { value, unit } => {
131            let value = stdin::unwrap_line(value)?;
132            sh_println!("{}", SimpleCast::format_units(&value, unit)?)?;
133        }
134        CastSubcommand::FromWei { value, unit } => {
135            let value = stdin::unwrap_line(value)?;
136            sh_println!("{}", SimpleCast::from_wei(&value, &unit)?)?
137        }
138        CastSubcommand::ToWei { value, unit } => {
139            let value = stdin::unwrap_line(value)?;
140            sh_println!("{}", SimpleCast::to_wei(&value, &unit)?)?
141        }
142        CastSubcommand::FromRlp { value, as_int } => {
143            let value = stdin::unwrap_line(value)?;
144            sh_println!("{}", SimpleCast::from_rlp(value, as_int)?)?
145        }
146        CastSubcommand::ToRlp { value } => {
147            let value = stdin::unwrap_line(value)?;
148            sh_println!("{}", SimpleCast::to_rlp(&value)?)?
149        }
150        CastSubcommand::ToHex(ToBaseArgs { value, base_in }) => {
151            let value = stdin::unwrap_line(value)?;
152            sh_println!("{}", SimpleCast::to_base(&value, base_in.as_deref(), "hex")?)?
153        }
154        CastSubcommand::ToDec(ToBaseArgs { value, base_in }) => {
155            let value = stdin::unwrap_line(value)?;
156            sh_println!("{}", SimpleCast::to_base(&value, base_in.as_deref(), "dec")?)?
157        }
158        CastSubcommand::ToBase { base: ToBaseArgs { value, base_in }, base_out } => {
159            let (value, base_out) = stdin::unwrap2(value, base_out)?;
160            sh_println!("{}", SimpleCast::to_base(&value, base_in.as_deref(), &base_out)?)?
161        }
162        CastSubcommand::ToBytes32 { bytes } => {
163            let value = stdin::unwrap_line(bytes)?;
164            sh_println!("{}", SimpleCast::to_bytes32(&value)?)?
165        }
166        CastSubcommand::Pad { data, right, left: _, len } => {
167            let value = stdin::unwrap_line(data)?;
168            sh_println!("{}", SimpleCast::pad(&value, right, len)?)?
169        }
170        CastSubcommand::FormatBytes32String { string } => {
171            let value = stdin::unwrap_line(string)?;
172            sh_println!("{}", SimpleCast::format_bytes32_string(&value)?)?
173        }
174        CastSubcommand::ParseBytes32String { bytes } => {
175            let value = stdin::unwrap_line(bytes)?;
176            sh_println!("{}", SimpleCast::parse_bytes32_string(&value)?)?
177        }
178        CastSubcommand::ParseBytes32Address { bytes } => {
179            let value = stdin::unwrap_line(bytes)?;
180            sh_println!("{}", SimpleCast::parse_bytes32_address(&value)?)?
181        }
182
183        // ABI encoding & decoding
184        CastSubcommand::DecodeAbi { sig, calldata, input } => {
185            let tokens = SimpleCast::abi_decode(&sig, &calldata, input)?;
186            print_tokens(&tokens);
187        }
188        CastSubcommand::AbiEncode { sig, packed, args } => {
189            if !packed {
190                sh_println!("{}", SimpleCast::abi_encode(&sig, &args)?)?
191            } else {
192                sh_println!("{}", SimpleCast::abi_encode_packed(&sig, &args)?)?
193            }
194        }
195        CastSubcommand::AbiEncodeEvent { sig, args } => {
196            let log_data = SimpleCast::abi_encode_event(&sig, &args)?;
197            for (i, topic) in log_data.topics().iter().enumerate() {
198                sh_println!("[topic{}]: {}", i, topic)?;
199            }
200            if !log_data.data.is_empty() {
201                sh_println!("[data]: {}", hex::encode_prefixed(log_data.data))?;
202            }
203        }
204        CastSubcommand::DecodeCalldata { sig, calldata, file } => {
205            let raw_hex = if let Some(file_path) = file {
206                let contents = fs::read_to_string(&file_path)?;
207                contents.trim().to_string()
208            } else {
209                calldata.unwrap()
210            };
211
212            let tokens = SimpleCast::calldata_decode(&sig, &raw_hex, true)?;
213            print_tokens(&tokens);
214        }
215        CastSubcommand::CalldataEncode { sig, args, file } => {
216            let final_args = if let Some(file_path) = file {
217                let contents = fs::read_to_string(file_path)?;
218                contents
219                    .lines()
220                    .map(str::trim)
221                    .filter(|line| !line.is_empty())
222                    .map(String::from)
223                    .collect()
224            } else {
225                args
226            };
227            sh_println!("{}", SimpleCast::calldata_encode(sig, &final_args)?)?;
228        }
229        CastSubcommand::DecodeString { data } => {
230            let tokens = SimpleCast::calldata_decode("Any(string)", &data, true)?;
231            print_tokens(&tokens);
232        }
233        CastSubcommand::DecodeEvent { sig, data } => {
234            let decoded_event = if let Some(event_sig) = sig {
235                let event = get_event(event_sig.as_str())?;
236                event.decode_log_parts(core::iter::once(event.selector()), &hex::decode(data)?)?
237            } else {
238                let data = crate::strip_0x(&data);
239                let selector = data.get(..64).unwrap_or_default();
240                let selector = selector.parse()?;
241                let identified_event =
242                    SignaturesIdentifier::new(false)?.identify_event(selector).await;
243                if let Some(event) = identified_event {
244                    let _ = sh_println!("{}", event.signature());
245                    let data = data.get(64..).unwrap_or_default();
246                    get_event(event.signature().as_str())?
247                        .decode_log_parts(core::iter::once(selector), &hex::decode(data)?)?
248                } else {
249                    eyre::bail!("No matching event signature found for selector `{selector}`")
250                }
251            };
252            print_tokens(&decoded_event.body);
253        }
254        CastSubcommand::DecodeError { sig, data } => {
255            let error = if let Some(err_sig) = sig {
256                get_error(err_sig.as_str())?
257            } else {
258                let data = crate::strip_0x(&data);
259                let selector = data.get(..8).unwrap_or_default();
260                let identified_error =
261                    SignaturesIdentifier::new(false)?.identify_error(selector.parse()?).await;
262                if let Some(error) = identified_error {
263                    let _ = sh_println!("{}", error.signature());
264                    error
265                } else {
266                    eyre::bail!("No matching error signature found for selector `{selector}`")
267                }
268            };
269            let decoded_error = error.decode_error(&hex::decode(data)?)?;
270            print_tokens(&decoded_error.body);
271        }
272        CastSubcommand::Interface(cmd) => cmd.run().await?,
273        CastSubcommand::CreationCode(cmd) => cmd.run().await?,
274        CastSubcommand::ConstructorArgs(cmd) => cmd.run().await?,
275        CastSubcommand::Artifact(cmd) => cmd.run().await?,
276        CastSubcommand::Bind(cmd) => cmd.run().await?,
277        CastSubcommand::B2EPayload(cmd) => cmd.run().await?,
278        CastSubcommand::PrettyCalldata { calldata, offline } => {
279            let calldata = stdin::unwrap_line(calldata)?;
280            sh_println!("{}", pretty_calldata(&calldata, offline).await?)?;
281        }
282        CastSubcommand::Sig { sig, optimize } => {
283            let sig = stdin::unwrap_line(sig)?;
284            match optimize {
285                Some(opt) => {
286                    sh_println!("Starting to optimize signature...")?;
287                    let start_time = Instant::now();
288                    let (selector, signature) = SimpleCast::get_selector(&sig, opt)?;
289                    sh_println!("Successfully generated in {:?}", start_time.elapsed())?;
290                    sh_println!("Selector: {selector}")?;
291                    sh_println!("Optimized signature: {signature}")?;
292                }
293                None => sh_println!("{}", SimpleCast::get_selector(&sig, 0)?.0)?,
294            }
295        }
296
297        // Blockchain & RPC queries
298        CastSubcommand::AccessList(cmd) => cmd.run().await?,
299        CastSubcommand::Age { block, rpc } => {
300            let config = rpc.load_config()?;
301            let provider = utils::get_provider(&config)?;
302            sh_println!(
303                "{} UTC",
304                Cast::new(provider).age(block.unwrap_or(BlockId::Number(Latest))).await?
305            )?
306        }
307        CastSubcommand::Balance { block, who, ether, rpc, erc20 } => {
308            let config = rpc.load_config()?;
309            let provider = utils::get_provider(&config)?;
310            let account_addr = who.resolve(&provider).await?;
311
312            match erc20 {
313                Some(token) => {
314                    let balance = IERC20::new(token, &provider)
315                        .balanceOf(account_addr)
316                        .block(block.unwrap_or_default())
317                        .call()
318                        .await?;
319
320                    sh_warn!("--erc20 flag is deprecated, use `cast erc20 balance` instead")?;
321                    sh_println!("{}", format_uint_exp(balance))?
322                }
323                None => {
324                    let value = Cast::new(&provider).balance(account_addr, block).await?;
325                    if ether {
326                        sh_println!("{}", SimpleCast::from_wei(&value.to_string(), "eth")?)?
327                    } else {
328                        sh_println!("{value}")?
329                    }
330                }
331            }
332        }
333        CastSubcommand::BaseFee { block, rpc } => {
334            let config = rpc.load_config()?;
335            let provider = utils::get_provider(&config)?;
336            sh_println!(
337                "{}",
338                Cast::new(provider).base_fee(block.unwrap_or(BlockId::Number(Latest))).await?
339            )?
340        }
341        CastSubcommand::Block { block, full, fields, raw, rpc } => {
342            let config = rpc.load_config()?;
343            let provider = utils::get_provider(&config)?;
344            // Can use either --raw or specify raw as a field
345            let raw = raw || fields.contains(&"raw".into());
346
347            sh_println!(
348                "{}",
349                Cast::new(provider)
350                    .block(block.unwrap_or(BlockId::Number(Latest)), full, fields, raw)
351                    .await?
352            )?
353        }
354        CastSubcommand::BlockNumber { rpc, block } => {
355            let config = rpc.load_config()?;
356            let provider = utils::get_provider(&config)?;
357            let number = match block {
358                Some(id) => {
359                    provider
360                        .get_block(id)
361                        .await?
362                        .ok_or_else(|| eyre::eyre!("block {id:?} not found"))?
363                        .header
364                        .number
365                }
366                None => Cast::new(provider).block_number().await?,
367            };
368            sh_println!("{number}")?
369        }
370        CastSubcommand::Chain { rpc } => {
371            let config = rpc.load_config()?;
372            let provider = utils::get_provider(&config)?;
373            sh_println!("{}", Cast::new(provider).chain().await?)?
374        }
375        CastSubcommand::ChainId { rpc } => {
376            let config = rpc.load_config()?;
377            let provider = utils::get_provider(&config)?;
378            sh_println!("{}", Cast::new(provider).chain_id().await?)?
379        }
380        CastSubcommand::Client { rpc } => {
381            let config = rpc.load_config()?;
382            let provider = utils::get_provider(&config)?;
383            sh_println!("{}", provider.get_client_version().await?)?
384        }
385        CastSubcommand::Code { block, who, disassemble, rpc } => {
386            let config = rpc.load_config()?;
387            let provider = utils::get_provider(&config)?;
388            let who = who.resolve(&provider).await?;
389            sh_println!("{}", Cast::new(provider).code(who, block, disassemble).await?)?
390        }
391        CastSubcommand::Codesize { block, who, rpc } => {
392            let config = rpc.load_config()?;
393            let provider = utils::get_provider(&config)?;
394            let who = who.resolve(&provider).await?;
395            sh_println!("{}", Cast::new(provider).codesize(who, block).await?)?
396        }
397        CastSubcommand::ComputeAddress { address, nonce, salt, init_code, init_code_hash, rpc } => {
398            let address = stdin::unwrap_line(address)?;
399            let computed = {
400                // For CREATE2, init_code_hash is needed to compute the address
401                if let Some(init_code_hash) = init_code_hash {
402                    address.create2(salt.unwrap_or(B256::ZERO), init_code_hash)
403                } else if let Some(init_code) = init_code {
404                    address.create2(salt.unwrap_or(B256::ZERO), keccak256(hex::decode(init_code)?))
405                } else {
406                    // For CREATE, rpc is needed to compute the address
407                    let config = rpc.load_config()?;
408                    let provider = utils::get_provider(&config)?;
409                    Cast::new(provider).compute_address(address, nonce).await?
410                }
411            };
412            sh_println!("Computed Address: {}", computed.to_checksum(None))?
413        }
414        CastSubcommand::Disassemble { bytecode } => {
415            let bytecode = stdin::unwrap_line(bytecode)?;
416            sh_println!("{}", SimpleCast::disassemble(&hex::decode(bytecode)?)?)?
417        }
418        CastSubcommand::Selectors { bytecode, resolve } => {
419            let bytecode = stdin::unwrap_line(bytecode)?;
420            let functions = SimpleCast::extract_functions(&bytecode)?;
421            let max_args_len = functions.iter().map(|r| r.1.len()).max().unwrap_or(0);
422            let max_mutability_len = functions.iter().map(|r| r.2.len()).max().unwrap_or(0);
423
424            let resolve_results = if resolve {
425                let selectors = functions
426                    .iter()
427                    .map(|&(selector, ..)| SelectorKind::Function(selector))
428                    .collect::<Vec<_>>();
429                let ds = decode_selectors(&selectors).await?;
430                ds.into_iter().map(|v| v.join("|")).collect()
431            } else {
432                vec![]
433            };
434            for (pos, (selector, arguments, state_mutability)) in functions.into_iter().enumerate()
435            {
436                if resolve {
437                    let resolved = &resolve_results[pos];
438                    sh_println!(
439                        "{selector}\t{arguments:max_args_len$}\t{state_mutability:max_mutability_len$}\t{resolved}"
440                    )?
441                } else {
442                    sh_println!("{selector}\t{arguments:max_args_len$}\t{state_mutability}")?
443                }
444            }
445        }
446        CastSubcommand::FindBlock(cmd) => cmd.run().await?,
447        CastSubcommand::GasPrice { rpc } => {
448            let config = rpc.load_config()?;
449            let provider = utils::get_provider(&config)?;
450            sh_println!("{}", Cast::new(provider).gas_price().await?)?;
451        }
452        CastSubcommand::Index { key_type, key, slot_number } => {
453            sh_println!("{}", SimpleCast::index(&key_type, &key, &slot_number)?)?;
454        }
455        CastSubcommand::IndexErc7201 { id, formula_id } => {
456            eyre::ensure!(formula_id == "erc7201", "unsupported formula ID: {formula_id}");
457            let id = stdin::unwrap_line(id)?;
458            sh_println!("{}", foundry_common::erc7201(&id))?;
459        }
460        CastSubcommand::Implementation { block, beacon, who, rpc } => {
461            let config = rpc.load_config()?;
462            let provider = utils::get_provider(&config)?;
463            let who = who.resolve(&provider).await?;
464            sh_println!("{}", Cast::new(provider).implementation(who, beacon, block).await?)?;
465        }
466        CastSubcommand::Admin { block, who, rpc } => {
467            let config = rpc.load_config()?;
468            let provider = utils::get_provider(&config)?;
469            let who = who.resolve(&provider).await?;
470            sh_println!("{}", Cast::new(provider).admin(who, block).await?)?;
471        }
472        CastSubcommand::Nonce { block, who, rpc } => {
473            let config = rpc.load_config()?;
474            let provider = utils::get_provider(&config)?;
475            let who = who.resolve(&provider).await?;
476            sh_println!("{}", Cast::new(provider).nonce(who, block).await?)?;
477        }
478        CastSubcommand::Codehash { block, who, slots, rpc } => {
479            let config = rpc.load_config()?;
480            let provider = utils::get_provider(&config)?;
481            let who = who.resolve(&provider).await?;
482            sh_println!("{}", Cast::new(provider).codehash(who, slots, block).await?)?;
483        }
484        CastSubcommand::StorageRoot { block, who, slots, rpc } => {
485            let config = rpc.load_config()?;
486            let provider = utils::get_provider(&config)?;
487            let who = who.resolve(&provider).await?;
488            sh_println!("{}", Cast::new(provider).storage_root(who, slots, block).await?)?;
489        }
490        CastSubcommand::Proof { address, slots, rpc, block } => {
491            let config = rpc.load_config()?;
492            let provider = utils::get_provider(&config)?;
493            let address = address.resolve(&provider).await?;
494            let value = provider
495                .get_proof(address, slots.into_iter().collect())
496                .block_id(block.unwrap_or_default())
497                .await?;
498            sh_println!("{}", serde_json::to_string(&value)?)?;
499        }
500        CastSubcommand::Rpc(cmd) => cmd.run().await?,
501        CastSubcommand::Storage(cmd) => cmd.run().await?,
502
503        // Calls & transactions
504        CastSubcommand::Call(cmd) => cmd.run().await?,
505        CastSubcommand::Estimate(cmd) => cmd.run().await?,
506        CastSubcommand::MakeTx(cmd) => cmd.run().await?,
507        CastSubcommand::PublishTx { raw_tx, cast_async, rpc } => {
508            let config = rpc.load_config()?;
509            let provider = utils::get_provider(&config)?;
510            let cast = Cast::new(&provider);
511            let pending_tx = cast.publish(raw_tx).await?;
512            let tx_hash = pending_tx.inner().tx_hash();
513
514            if cast_async {
515                sh_println!("{tx_hash:#x}")?;
516            } else {
517                let receipt = pending_tx.get_receipt().await?;
518                sh_println!("{}", serde_json::json!(receipt))?;
519            }
520        }
521        CastSubcommand::Receipt { tx_hash, field, cast_async, confirmations, rpc } => {
522            let config = rpc.load_config()?;
523            let provider = utils::get_provider(&config)?;
524            sh_println!(
525                "{}",
526                Cast::new(provider)
527                    .receipt(tx_hash, field, confirmations, None, cast_async)
528                    .await?
529            )?
530        }
531        CastSubcommand::Run(cmd) => cmd.run().await?,
532        CastSubcommand::SendTx(cmd) => cmd.run().await?,
533        CastSubcommand::Tx { tx_hash, from, nonce, field, raw, rpc, to_request } => {
534            let config = rpc.load_config()?;
535            let provider = utils::get_provider(&config)?;
536
537            // Can use either --raw or specify raw as a field
538            let raw = raw || field.as_ref().is_some_and(|f| f == "raw");
539
540            sh_println!(
541                "{}",
542                Cast::new(&provider)
543                    .transaction(tx_hash, from, nonce, field, raw, to_request)
544                    .await?
545            )?
546        }
547
548        // 4Byte
549        CastSubcommand::FourByte { selector } => {
550            let selector = stdin::unwrap_line(selector)?;
551            let sigs = decode_function_selector(selector).await?;
552            if sigs.is_empty() {
553                eyre::bail!("No matching function signatures found for selector `{selector}`");
554            }
555            for sig in sigs {
556                sh_println!("{sig}")?
557            }
558        }
559
560        CastSubcommand::FourByteCalldata { calldata } => {
561            let calldata = stdin::unwrap_line(calldata)?;
562
563            if calldata.len() == 10 {
564                let sigs = decode_function_selector(calldata.parse()?).await?;
565                if sigs.is_empty() {
566                    eyre::bail!("No matching function signatures found for calldata `{calldata}`");
567                }
568                for sig in sigs {
569                    sh_println!("{sig}")?
570                }
571                return Ok(());
572            }
573
574            let sigs = decode_calldata(&calldata).await?;
575            sigs.iter().enumerate().for_each(|(i, sig)| {
576                let _ = sh_println!("{}) \"{sig}\"", i + 1);
577            });
578
579            let sig = match sigs.len() {
580                0 => eyre::bail!("No signatures found"),
581                1 => sigs.first().unwrap(),
582                _ => {
583                    let i: usize = prompt!("Select a function signature by number: ")?;
584                    sigs.get(i - 1).ok_or_else(|| eyre::eyre!("Invalid signature index"))?
585                }
586            };
587
588            let tokens = SimpleCast::calldata_decode(sig, &calldata, true)?;
589            print_tokens(&tokens);
590        }
591
592        CastSubcommand::FourByteEvent { topic } => {
593            let topic = stdin::unwrap_line(topic)?;
594            let sigs = decode_event_topic(topic).await?;
595            if sigs.is_empty() {
596                eyre::bail!("No matching event signatures found for topic `{topic}`");
597            }
598            for sig in sigs {
599                sh_println!("{sig}")?
600            }
601        }
602        CastSubcommand::UploadSignature { signatures } => {
603            let signatures = stdin::unwrap_vec(signatures)?;
604            let ParsedSignatures { signatures, abis } = parse_signatures(signatures);
605            if !abis.is_empty() {
606                import_selectors(SelectorImportData::Abi(abis)).await?.describe();
607            }
608            if !signatures.is_empty() {
609                import_selectors(SelectorImportData::Raw(signatures)).await?.describe();
610            }
611        }
612
613        // ENS
614        CastSubcommand::Namehash { name } => {
615            let name = stdin::unwrap_line(name)?;
616            sh_println!("{}", namehash(&name))?
617        }
618        CastSubcommand::LookupAddress { who, rpc, verify } => {
619            let config = rpc.load_config()?;
620            let provider = utils::get_provider(&config)?;
621
622            let who = stdin::unwrap_line(who)?;
623            let name = provider.lookup_address(&who).await?;
624            if verify {
625                let address = provider.resolve_name(&name).await?;
626                eyre::ensure!(
627                    address == who,
628                    "Reverse lookup verification failed: got `{address}`, expected `{who}`"
629                );
630            }
631            sh_println!("{name}")?
632        }
633        CastSubcommand::ResolveName { who, rpc, verify } => {
634            let config = rpc.load_config()?;
635            let provider = utils::get_provider(&config)?;
636
637            let who = stdin::unwrap_line(who)?;
638            let address = provider.resolve_name(&who).await?;
639            if verify {
640                let name = provider.lookup_address(&address).await?;
641                eyre::ensure!(
642                    name == who,
643                    "Forward lookup verification failed: got `{name}`, expected `{who}`"
644                );
645            }
646            sh_println!("{address}")?
647        }
648
649        // Misc
650        CastSubcommand::Keccak { data } => {
651            let bytes = match data {
652                Some(data) => data.into_bytes(),
653                None => stdin::read_bytes(false)?,
654            };
655            match String::from_utf8(bytes) {
656                Ok(s) => {
657                    let s = SimpleCast::keccak(&s)?;
658                    sh_println!("{s}")?
659                }
660                Err(e) => {
661                    let hash = keccak256(e.as_bytes());
662                    let s = hex::encode(hash);
663                    sh_println!("0x{s}")?
664                }
665            };
666        }
667        CastSubcommand::HashMessage { message } => {
668            let message = stdin::unwrap(message, false)?;
669            sh_println!("{}", eip191_hash_message(message))?
670        }
671        CastSubcommand::SigEvent { event_string } => {
672            let event_string = stdin::unwrap_line(event_string)?;
673            let parsed_event = get_event(&event_string)?;
674            sh_println!("{:?}", parsed_event.selector())?
675        }
676        CastSubcommand::LeftShift { value, bits, base_in, base_out } => sh_println!(
677            "{}",
678            SimpleCast::left_shift(&value, &bits, base_in.as_deref(), &base_out)?
679        )?,
680        CastSubcommand::RightShift { value, bits, base_in, base_out } => sh_println!(
681            "{}",
682            SimpleCast::right_shift(&value, &bits, base_in.as_deref(), &base_out)?
683        )?,
684        CastSubcommand::Source {
685            address,
686            directory,
687            explorer_api_url,
688            explorer_url,
689            etherscan,
690            flatten,
691        } => {
692            let config = etherscan.load_config()?;
693            let chain = config.chain.unwrap_or_default();
694            let api_key = config.get_etherscan_api_key(Some(chain));
695            match (directory, flatten) {
696                (Some(dir), false) => {
697                    SimpleCast::expand_etherscan_source_to_directory(
698                        chain,
699                        address,
700                        api_key,
701                        dir,
702                        explorer_api_url,
703                        explorer_url,
704                    )
705                    .await?
706                }
707                (None, false) => sh_println!(
708                    "{}",
709                    SimpleCast::etherscan_source(
710                        chain,
711                        address,
712                        api_key,
713                        explorer_api_url,
714                        explorer_url
715                    )
716                    .await?
717                )?,
718                (dir, true) => {
719                    SimpleCast::etherscan_source_flatten(
720                        chain,
721                        address,
722                        api_key,
723                        dir,
724                        explorer_api_url,
725                        explorer_url,
726                    )
727                    .await?;
728                }
729            }
730        }
731        CastSubcommand::Create2(cmd) => {
732            cmd.run()?;
733        }
734        CastSubcommand::Wallet { command } => command.run().await?,
735        CastSubcommand::Completions { shell } => {
736            generate(shell, &mut CastArgs::command(), "cast", &mut std::io::stdout())
737        }
738        CastSubcommand::Logs(cmd) => cmd.run().await?,
739        CastSubcommand::DecodeTransaction { tx } => {
740            let tx = stdin::unwrap_line(tx)?;
741            let tx = SimpleCast::decode_raw_transaction(&tx)?;
742
743            if let Ok(signer) = tx.recover_signer() {
744                let recovered = Recovered::new_unchecked(tx, signer);
745                sh_println!("{}", serde_json::to_string_pretty(&recovered)?)?;
746            } else {
747                sh_println!("{}", serde_json::to_string_pretty(&tx)?)?;
748            }
749        }
750        CastSubcommand::RecoverAuthority { auth } => {
751            let auth: SignedAuthorization = serde_json::from_str(&auth)?;
752            sh_println!("{}", auth.recover_authority()?)?;
753        }
754        CastSubcommand::TxPool { command } => command.run().await?,
755        CastSubcommand::Erc20Token { command } => command.run().await?,
756        CastSubcommand::DAEstimate(cmd) => {
757            cmd.run().await?;
758        }
759    };
760
761    /// Prints slice of tokens using [`format_tokens`] or [`serialize_value_as_json`] depending
762    /// whether the shell is in JSON mode.
763    ///
764    /// This is included here to avoid a cyclic dependency between `fmt` and `common`.
765    fn print_tokens(tokens: &[DynSolValue]) {
766        if shell::is_json() {
767            let tokens: Vec<serde_json::Value> = tokens
768                .iter()
769                .cloned()
770                .map(|t| serialize_value_as_json(t, None))
771                .collect::<Result<Vec<_>>>()
772                .unwrap();
773            let _ = sh_println!("{}", serde_json::to_string_pretty(&tokens).unwrap());
774        } else {
775            let tokens = format_tokens(tokens);
776            tokens.for_each(|t| {
777                let _ = sh_println!("{t}");
778            });
779        }
780    }
781
782    Ok(())
783}