cast/
args.rs

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