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