Skip to main content

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