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