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 args.global.tokio_runtime().block_on(run_command(args))
37}
38
39pub 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
50pub async fn run_command(args: CastArgs) -> Result<()> {
52 match args.cmd {
53 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 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 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 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 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 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 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 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 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 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 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 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 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}