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