cast/
args.rs

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