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