cast/
args.rs

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