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