1use crate::{
2 opts::{Cast as CastArgs, CastSubcommand, ToBaseArgs},
3 traces::identifier::SignaturesIdentifier,
4 Cast, SimpleCast,
5};
6use alloy_consensus::transaction::Recovered;
7use alloy_dyn_abi::{DynSolValue, ErrorExt, EventExt};
8use alloy_primitives::{eip191_hash_message, hex, keccak256, Address, B256};
9use alloy_provider::Provider;
10use alloy_rpc_types::{BlockId, BlockNumberOrTag::Latest};
11use clap::{CommandFactory, Parser};
12use clap_complete::generate;
13use eyre::Result;
14use foundry_cli::{handler, utils, utils::LoadConfig};
15use foundry_common::{
16 abi::{get_error, get_event},
17 ens::{namehash, ProviderEnsExt},
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 SelectorType,
24 },
25 shell, stdin,
26};
27use foundry_config::Config;
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 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 } => {
199 sh_println!("{}", SimpleCast::calldata_encode(sig, &args)?)?;
200 }
201 CastSubcommand::DecodeString { data } => {
202 let tokens = SimpleCast::calldata_decode("Any(string)", &data, true)?;
203 print_tokens(&tokens);
204 }
205 CastSubcommand::DecodeEvent { sig, data } => {
206 let decoded_event = if let Some(event_sig) = sig {
207 get_event(event_sig.as_str())?.decode_log_parts(None, &hex::decode(data)?, false)?
208 } else {
209 let data = data.strip_prefix("0x").unwrap_or(data.as_str());
210 let selector = data.get(..64).unwrap_or_default();
211 let identified_event =
212 SignaturesIdentifier::new(Config::foundry_cache_dir(), false)?
213 .write()
214 .await
215 .identify_event(&hex::decode(selector)?)
216 .await;
217 if let Some(event) = identified_event {
218 let _ = sh_println!("{}", event.signature());
219 let data = data.get(64..).unwrap_or_default();
220 get_event(event.signature().as_str())?.decode_log_parts(
221 None,
222 &hex::decode(data)?,
223 false,
224 )?
225 } else {
226 eyre::bail!("No matching event signature found for selector `{selector}`")
227 }
228 };
229 print_tokens(&decoded_event.body);
230 }
231 CastSubcommand::DecodeError { sig, data } => {
232 let error = if let Some(err_sig) = sig {
233 get_error(err_sig.as_str())?
234 } else {
235 let data = data.strip_prefix("0x").unwrap_or(data.as_str());
236 let selector = data.get(..8).unwrap_or_default();
237 let identified_error =
238 SignaturesIdentifier::new(Config::foundry_cache_dir(), false)?
239 .write()
240 .await
241 .identify_error(&hex::decode(selector)?)
242 .await;
243 if let Some(error) = identified_error {
244 let _ = sh_println!("{}", error.signature());
245 error
246 } else {
247 eyre::bail!("No matching error signature found for selector `{selector}`")
248 }
249 };
250 let decoded_error = error.decode_error(&hex::decode(data)?)?;
251 print_tokens(&decoded_error.body);
252 }
253 CastSubcommand::Interface(cmd) => cmd.run().await?,
254 CastSubcommand::CreationCode(cmd) => cmd.run().await?,
255 CastSubcommand::ConstructorArgs(cmd) => cmd.run().await?,
256 CastSubcommand::Artifact(cmd) => cmd.run().await?,
257 CastSubcommand::Bind(cmd) => cmd.run().await?,
258 CastSubcommand::PrettyCalldata { calldata, offline } => {
259 let calldata = stdin::unwrap_line(calldata)?;
260 sh_println!("{}", pretty_calldata(&calldata, offline).await?)?;
261 }
262 CastSubcommand::Sig { sig, optimize } => {
263 let sig = stdin::unwrap_line(sig)?;
264 match optimize {
265 Some(opt) => {
266 sh_println!("Starting to optimize signature...")?;
267 let start_time = Instant::now();
268 let (selector, signature) = SimpleCast::get_selector(&sig, opt)?;
269 sh_println!("Successfully generated in {:?}", start_time.elapsed())?;
270 sh_println!("Selector: {selector}")?;
271 sh_println!("Optimized signature: {signature}")?;
272 }
273 None => sh_println!("{}", SimpleCast::get_selector(&sig, 0)?.0)?,
274 }
275 }
276
277 CastSubcommand::AccessList(cmd) => cmd.run().await?,
279 CastSubcommand::Age { block, rpc } => {
280 let config = rpc.load_config()?;
281 let provider = utils::get_provider(&config)?;
282 sh_println!(
283 "{} UTC",
284 Cast::new(provider).age(block.unwrap_or(BlockId::Number(Latest))).await?
285 )?
286 }
287 CastSubcommand::Balance { block, who, ether, rpc, erc20 } => {
288 let config = rpc.load_config()?;
289 let provider = utils::get_provider(&config)?;
290 let account_addr = who.resolve(&provider).await?;
291
292 match erc20 {
293 Some(token) => {
294 let balance =
295 Cast::new(&provider).erc20_balance(token, account_addr, block).await?;
296 sh_println!("{}", format_uint_exp(balance))?
297 }
298 None => {
299 let value = Cast::new(&provider).balance(account_addr, block).await?;
300 if ether {
301 sh_println!("{}", SimpleCast::from_wei(&value.to_string(), "eth")?)?
302 } else {
303 sh_println!("{value}")?
304 }
305 }
306 }
307 }
308 CastSubcommand::BaseFee { block, rpc } => {
309 let config = rpc.load_config()?;
310 let provider = utils::get_provider(&config)?;
311 sh_println!(
312 "{}",
313 Cast::new(provider).base_fee(block.unwrap_or(BlockId::Number(Latest))).await?
314 )?
315 }
316 CastSubcommand::Block { block, full, field, rpc } => {
317 let config = rpc.load_config()?;
318 let provider = utils::get_provider(&config)?;
319 sh_println!(
320 "{}",
321 Cast::new(provider)
322 .block(block.unwrap_or(BlockId::Number(Latest)), full, field)
323 .await?
324 )?
325 }
326 CastSubcommand::BlockNumber { rpc, block } => {
327 let config = rpc.load_config()?;
328 let provider = utils::get_provider(&config)?;
329 let number = match block {
330 Some(id) => {
331 provider
332 .get_block(id)
333 .await?
334 .ok_or_else(|| eyre::eyre!("block {id:?} not found"))?
335 .header
336 .number
337 }
338 None => Cast::new(provider).block_number().await?,
339 };
340 sh_println!("{number}")?
341 }
342 CastSubcommand::Chain { rpc } => {
343 let config = rpc.load_config()?;
344 let provider = utils::get_provider(&config)?;
345 sh_println!("{}", Cast::new(provider).chain().await?)?
346 }
347 CastSubcommand::ChainId { rpc } => {
348 let config = rpc.load_config()?;
349 let provider = utils::get_provider(&config)?;
350 sh_println!("{}", Cast::new(provider).chain_id().await?)?
351 }
352 CastSubcommand::Client { rpc } => {
353 let config = rpc.load_config()?;
354 let provider = utils::get_provider(&config)?;
355 sh_println!("{}", provider.get_client_version().await?)?
356 }
357 CastSubcommand::Code { block, who, disassemble, rpc } => {
358 let config = rpc.load_config()?;
359 let provider = utils::get_provider(&config)?;
360 let who = who.resolve(&provider).await?;
361 sh_println!("{}", Cast::new(provider).code(who, block, disassemble).await?)?
362 }
363 CastSubcommand::Codesize { block, who, rpc } => {
364 let config = rpc.load_config()?;
365 let provider = utils::get_provider(&config)?;
366 let who = who.resolve(&provider).await?;
367 sh_println!("{}", Cast::new(provider).codesize(who, block).await?)?
368 }
369 CastSubcommand::ComputeAddress { address, nonce, rpc } => {
370 let config = rpc.load_config()?;
371 let provider = utils::get_provider(&config)?;
372
373 let address = stdin::unwrap_line(address)?;
374 let computed = Cast::new(provider).compute_address(address, nonce).await?;
375 sh_println!("Computed Address: {}", computed.to_checksum(None))?
376 }
377 CastSubcommand::Disassemble { bytecode } => {
378 let bytecode = stdin::unwrap_line(bytecode)?;
379 sh_println!("{}", SimpleCast::disassemble(&hex::decode(bytecode)?)?)?
380 }
381 CastSubcommand::Selectors { bytecode, resolve } => {
382 let bytecode = stdin::unwrap_line(bytecode)?;
383 let functions = SimpleCast::extract_functions(&bytecode)?;
384 let max_args_len = functions.iter().map(|r| r.1.len()).max().unwrap_or(0);
385 let max_mutability_len = functions.iter().map(|r| r.2.len()).max().unwrap_or(0);
386
387 let resolve_results = if resolve {
388 let selectors_it = functions.iter().map(|r| &r.0);
389 let ds = decode_selectors(SelectorType::Function, selectors_it).await?;
390 ds.into_iter().map(|v| v.unwrap_or_default().join("|")).collect()
391 } else {
392 vec![]
393 };
394 for (pos, (selector, arguments, state_mutability)) in functions.into_iter().enumerate()
395 {
396 if resolve {
397 let resolved = &resolve_results[pos];
398 sh_println!("{selector}\t{arguments:max_args_len$}\t{state_mutability:max_mutability_len$}\t{resolved}")?
399 } else {
400 sh_println!("{selector}\t{arguments:max_args_len$}\t{state_mutability}")?
401 }
402 }
403 }
404 CastSubcommand::FindBlock(cmd) => cmd.run().await?,
405 CastSubcommand::GasPrice { rpc } => {
406 let config = rpc.load_config()?;
407 let provider = utils::get_provider(&config)?;
408 sh_println!("{}", Cast::new(provider).gas_price().await?)?;
409 }
410 CastSubcommand::Index { key_type, key, slot_number } => {
411 sh_println!("{}", SimpleCast::index(&key_type, &key, &slot_number)?)?;
412 }
413 CastSubcommand::IndexErc7201 { id, formula_id } => {
414 eyre::ensure!(formula_id == "erc7201", "unsupported formula ID: {formula_id}");
415 let id = stdin::unwrap_line(id)?;
416 sh_println!("{}", foundry_common::erc7201(&id))?;
417 }
418 CastSubcommand::Implementation { block, beacon, who, rpc } => {
419 let config = rpc.load_config()?;
420 let provider = utils::get_provider(&config)?;
421 let who = who.resolve(&provider).await?;
422 sh_println!("{}", Cast::new(provider).implementation(who, beacon, block).await?)?;
423 }
424 CastSubcommand::Admin { block, who, rpc } => {
425 let config = rpc.load_config()?;
426 let provider = utils::get_provider(&config)?;
427 let who = who.resolve(&provider).await?;
428 sh_println!("{}", Cast::new(provider).admin(who, block).await?)?;
429 }
430 CastSubcommand::Nonce { block, who, rpc } => {
431 let config = rpc.load_config()?;
432 let provider = utils::get_provider(&config)?;
433 let who = who.resolve(&provider).await?;
434 sh_println!("{}", Cast::new(provider).nonce(who, block).await?)?;
435 }
436 CastSubcommand::Codehash { block, who, slots, rpc } => {
437 let config = rpc.load_config()?;
438 let provider = utils::get_provider(&config)?;
439 let who = who.resolve(&provider).await?;
440 sh_println!("{}", Cast::new(provider).codehash(who, slots, block).await?)?;
441 }
442 CastSubcommand::StorageRoot { block, who, slots, rpc } => {
443 let config = rpc.load_config()?;
444 let provider = utils::get_provider(&config)?;
445 let who = who.resolve(&provider).await?;
446 sh_println!("{}", Cast::new(provider).storage_root(who, slots, block).await?)?;
447 }
448 CastSubcommand::Proof { address, slots, rpc, block } => {
449 let config = rpc.load_config()?;
450 let provider = utils::get_provider(&config)?;
451 let address = address.resolve(&provider).await?;
452 let value = provider
453 .get_proof(address, slots.into_iter().collect())
454 .block_id(block.unwrap_or_default())
455 .await?;
456 sh_println!("{}", serde_json::to_string(&value)?)?;
457 }
458 CastSubcommand::Rpc(cmd) => cmd.run().await?,
459 CastSubcommand::Storage(cmd) => cmd.run().await?,
460
461 CastSubcommand::Call(cmd) => cmd.run().await?,
463 CastSubcommand::Estimate(cmd) => cmd.run().await?,
464 CastSubcommand::MakeTx(cmd) => cmd.run().await?,
465 CastSubcommand::PublishTx { raw_tx, cast_async, rpc } => {
466 let config = rpc.load_config()?;
467 let provider = utils::get_provider(&config)?;
468 let cast = Cast::new(&provider);
469 let pending_tx = cast.publish(raw_tx).await?;
470 let tx_hash = pending_tx.inner().tx_hash();
471
472 if cast_async {
473 sh_println!("{tx_hash:#x}")?;
474 } else {
475 let receipt = pending_tx.get_receipt().await?;
476 sh_println!("{}", serde_json::json!(receipt))?;
477 }
478 }
479 CastSubcommand::Receipt { tx_hash, field, cast_async, confirmations, rpc } => {
480 let config = rpc.load_config()?;
481 let provider = utils::get_provider(&config)?;
482 sh_println!(
483 "{}",
484 Cast::new(provider)
485 .receipt(tx_hash, field, confirmations, None, cast_async)
486 .await?
487 )?
488 }
489 CastSubcommand::Run(cmd) => cmd.run().await?,
490 CastSubcommand::SendTx(cmd) => cmd.run().await?,
491 CastSubcommand::Tx { tx_hash, field, raw, rpc } => {
492 let config = rpc.load_config()?;
493 let provider = utils::get_provider(&config)?;
494
495 let raw = raw || field.as_ref().is_some_and(|f| f == "raw");
497
498 sh_println!("{}", Cast::new(&provider).transaction(tx_hash, field, raw).await?)?
499 }
500
501 CastSubcommand::FourByte { selector } => {
503 let selector = stdin::unwrap_line(selector)?;
504 let sigs = decode_function_selector(&selector).await?;
505 if sigs.is_empty() {
506 eyre::bail!("No matching function signatures found for selector `{selector}`");
507 }
508 for sig in sigs {
509 sh_println!("{sig}")?
510 }
511 }
512
513 CastSubcommand::FourByteCalldata { calldata } => {
514 let calldata = stdin::unwrap_line(calldata)?;
515
516 if calldata.len() == 10 {
517 let sigs = decode_function_selector(&calldata).await?;
518 if sigs.is_empty() {
519 eyre::bail!("No matching function signatures found for calldata `{calldata}`");
520 }
521 for sig in sigs {
522 sh_println!("{sig}")?
523 }
524 return Ok(());
525 }
526
527 let sigs = decode_calldata(&calldata).await?;
528 sigs.iter().enumerate().for_each(|(i, sig)| {
529 let _ = sh_println!("{}) \"{sig}\"", i + 1);
530 });
531
532 let sig = match sigs.len() {
533 0 => eyre::bail!("No signatures found"),
534 1 => sigs.first().unwrap(),
535 _ => {
536 let i: usize = prompt!("Select a function signature by number: ")?;
537 sigs.get(i - 1).ok_or_else(|| eyre::eyre!("Invalid signature index"))?
538 }
539 };
540
541 let tokens = SimpleCast::calldata_decode(sig, &calldata, true)?;
542 print_tokens(&tokens);
543 }
544
545 CastSubcommand::FourByteEvent { topic } => {
546 let topic = stdin::unwrap_line(topic)?;
547 let sigs = decode_event_topic(&topic).await?;
548 if sigs.is_empty() {
549 eyre::bail!("No matching event signatures found for topic `{topic}`");
550 }
551 for sig in sigs {
552 sh_println!("{sig}")?
553 }
554 }
555 CastSubcommand::UploadSignature { signatures } => {
556 let signatures = stdin::unwrap_vec(signatures)?;
557 let ParsedSignatures { signatures, abis } = parse_signatures(signatures);
558 if !abis.is_empty() {
559 import_selectors(SelectorImportData::Abi(abis)).await?.describe();
560 }
561 if !signatures.is_empty() {
562 import_selectors(SelectorImportData::Raw(signatures)).await?.describe();
563 }
564 }
565
566 CastSubcommand::Namehash { name } => {
568 let name = stdin::unwrap_line(name)?;
569 sh_println!("{}", namehash(&name))?
570 }
571 CastSubcommand::LookupAddress { who, rpc, verify } => {
572 let config = rpc.load_config()?;
573 let provider = utils::get_provider(&config)?;
574
575 let who = stdin::unwrap_line(who)?;
576 let name = provider.lookup_address(&who).await?;
577 if verify {
578 let address = provider.resolve_name(&name).await?;
579 eyre::ensure!(
580 address == who,
581 "Reverse lookup verification failed: got `{address}`, expected `{who}`"
582 );
583 }
584 sh_println!("{name}")?
585 }
586 CastSubcommand::ResolveName { who, rpc, verify } => {
587 let config = rpc.load_config()?;
588 let provider = utils::get_provider(&config)?;
589
590 let who = stdin::unwrap_line(who)?;
591 let address = provider.resolve_name(&who).await?;
592 if verify {
593 let name = provider.lookup_address(&address).await?;
594 eyre::ensure!(
595 name == who,
596 "Forward lookup verification failed: got `{name}`, expected `{who}`"
597 );
598 }
599 sh_println!("{address}")?
600 }
601
602 CastSubcommand::Keccak { data } => {
604 let bytes = match data {
605 Some(data) => data.into_bytes(),
606 None => stdin::read_bytes(false)?,
607 };
608 match String::from_utf8(bytes) {
609 Ok(s) => {
610 let s = SimpleCast::keccak(&s)?;
611 sh_println!("{s}")?
612 }
613 Err(e) => {
614 let hash = keccak256(e.as_bytes());
615 let s = hex::encode(hash);
616 sh_println!("0x{s}")?
617 }
618 };
619 }
620 CastSubcommand::HashMessage { message } => {
621 let message = stdin::unwrap_line(message)?;
622 sh_println!("{}", eip191_hash_message(message))?
623 }
624 CastSubcommand::SigEvent { event_string } => {
625 let event_string = stdin::unwrap_line(event_string)?;
626 let parsed_event = get_event(&event_string)?;
627 sh_println!("{:?}", parsed_event.selector())?
628 }
629 CastSubcommand::LeftShift { value, bits, base_in, base_out } => sh_println!(
630 "{}",
631 SimpleCast::left_shift(&value, &bits, base_in.as_deref(), &base_out)?
632 )?,
633 CastSubcommand::RightShift { value, bits, base_in, base_out } => sh_println!(
634 "{}",
635 SimpleCast::right_shift(&value, &bits, base_in.as_deref(), &base_out)?
636 )?,
637 CastSubcommand::Source {
638 address,
639 directory,
640 explorer_api_url,
641 explorer_url,
642 etherscan,
643 flatten,
644 } => {
645 let config = etherscan.load_config()?;
646 let chain = config.chain.unwrap_or_default();
647 let api_key = config.get_etherscan_api_key(Some(chain));
648 match (directory, flatten) {
649 (Some(dir), false) => {
650 SimpleCast::expand_etherscan_source_to_directory(
651 chain,
652 address,
653 api_key,
654 dir,
655 explorer_api_url,
656 explorer_url,
657 )
658 .await?
659 }
660 (None, false) => sh_println!(
661 "{}",
662 SimpleCast::etherscan_source(
663 chain,
664 address,
665 api_key,
666 explorer_api_url,
667 explorer_url
668 )
669 .await?
670 )?,
671 (dir, true) => {
672 SimpleCast::etherscan_source_flatten(
673 chain,
674 address,
675 api_key,
676 dir,
677 explorer_api_url,
678 explorer_url,
679 )
680 .await?;
681 }
682 }
683 }
684 CastSubcommand::Create2(cmd) => {
685 cmd.run()?;
686 }
687 CastSubcommand::Wallet { command } => command.run().await?,
688 CastSubcommand::Completions { shell } => {
689 generate(shell, &mut CastArgs::command(), "cast", &mut std::io::stdout())
690 }
691 CastSubcommand::GenerateFigSpec => clap_complete::generate(
692 clap_complete_fig::Fig,
693 &mut CastArgs::command(),
694 "cast",
695 &mut std::io::stdout(),
696 ),
697 CastSubcommand::Logs(cmd) => cmd.run().await?,
698 CastSubcommand::DecodeTransaction { tx } => {
699 let tx = stdin::unwrap_line(tx)?;
700 let tx = SimpleCast::decode_raw_transaction(&tx)?;
701
702 if let Ok(signer) = tx.recover_signer() {
703 let recovered = Recovered::new_unchecked(tx, signer);
704 sh_println!("{}", serde_json::to_string_pretty(&recovered)?)?;
705 } else {
706 sh_println!("{}", serde_json::to_string_pretty(&tx)?)?;
707 }
708 }
709 CastSubcommand::DecodeEof { eof } => {
710 let eof = stdin::unwrap_line(eof)?;
711 sh_println!("{}", SimpleCast::decode_eof(&eof)?)?
712 }
713 CastSubcommand::TxPool { command } => command.run().await?,
714 };
715
716 fn print_tokens(tokens: &[DynSolValue]) {
721 if shell::is_json() {
722 let tokens: Vec<String> = format_tokens_raw(tokens).collect();
723 let _ = sh_println!("{}", serde_json::to_string_pretty(&tokens).unwrap());
724 } else {
725 let tokens = format_tokens(tokens);
726 tokens.for_each(|t| {
727 let _ = sh_println!("{t}");
728 });
729 }
730 }
731
732 Ok(())
733}