Skip to main content

cast/
lib.rs

1//! Cast is a Swiss Army knife for interacting with Ethereum applications from the command line.
2
3#![cfg_attr(not(test), warn(unused_crate_dependencies))]
4#![cfg_attr(docsrs, feature(doc_cfg))]
5
6#[macro_use]
7extern crate foundry_common;
8#[macro_use]
9extern crate tracing;
10
11use alloy_consensus::{
12    BlockHeader,
13    transaction::{Recovered, SignerRecoverable},
14};
15use alloy_dyn_abi::{DynSolType, DynSolValue, FunctionExt};
16use alloy_eips::Encodable2718;
17use alloy_ens::NameOrAddress;
18use alloy_json_abi::Function;
19use alloy_network::{AnyNetwork, BlockResponse, Network, TransactionBuilder};
20use alloy_primitives::{
21    Address, B256, I256, Keccak256, LogData, Selector, TxHash, U64, U256, hex,
22    utils::{ParseUnits, Unit, keccak256},
23};
24use alloy_provider::{PendingTransactionBuilder, Provider, network::eip2718::Decodable2718};
25use alloy_rlp::{Decodable, Encodable};
26use alloy_rpc_types::{
27    BlockId, BlockNumberOrTag, BlockOverrides, Filter, FilterBlockOption, Log, state::StateOverride,
28};
29use base::{Base, NumberWithBase, ToBase};
30use chrono::DateTime;
31use eyre::{Context, ContextCompat, OptionExt, Result};
32use foundry_block_explorers::Client;
33use foundry_common::{
34    abi::{coerce_value, encode_function_args, encode_function_args_packed, get_event, get_func},
35    compile::etherscan_project,
36    flatten,
37    fmt::*,
38    fs, shell,
39};
40use foundry_config::Chain;
41use foundry_evm::core::bytecode::InstIter;
42use futures::{FutureExt, StreamExt, future::Either};
43#[cfg(feature = "optimism")]
44use op_alloy_consensus as _;
45
46use rayon::prelude::*;
47use serde::Serialize;
48use std::{
49    borrow::Cow,
50    fmt::Write,
51    io,
52    marker::PhantomData,
53    path::PathBuf,
54    str::FromStr,
55    sync::atomic::{AtomicBool, Ordering},
56};
57use tokio::signal::ctrl_c;
58
59pub use foundry_evm::*;
60
61pub mod args;
62pub mod cmd;
63pub mod opts;
64pub mod tempo;
65
66pub mod base;
67pub mod call_spec;
68pub(crate) mod debug;
69pub mod errors;
70mod rlp_converter;
71pub mod tx;
72
73use rlp_converter::Item;
74
75// TODO: CastContract with common contract initializers? Same for CastProviders?
76
77pub struct Cast<P, N = AnyNetwork> {
78    provider: P,
79    _phantom: PhantomData<N>,
80}
81
82impl<P: Provider<N> + Clone + Unpin, N: Network> Cast<P, N> {
83    /// Creates a new Cast instance from the provided client
84    ///
85    /// # Example
86    ///
87    /// ```
88    /// use alloy_provider::{ProviderBuilder, RootProvider, network::AnyNetwork};
89    /// use cast::Cast;
90    ///
91    /// # async fn foo() -> eyre::Result<()> {
92    /// let provider =
93    ///     ProviderBuilder::<_, _, AnyNetwork>::default().connect("http://localhost:8545").await?;
94    /// let cast = Cast::new(provider);
95    /// # Ok(())
96    /// # }
97    /// ```
98    pub const fn new(provider: P) -> Self {
99        Self { provider, _phantom: PhantomData }
100    }
101
102    /// Makes a read-only call to the specified address
103    ///
104    /// # Example
105    ///
106    /// ```
107    /// use alloy_primitives::{Address, U256, Bytes};
108    /// use alloy_rpc_types::{TransactionRequest, BlockOverrides, state::{StateOverride, AccountOverride}};
109    /// use alloy_serde::WithOtherFields;
110    /// use cast::Cast;
111    /// use alloy_provider::{RootProvider, ProviderBuilder, network::AnyNetwork};
112    /// use std::{str::FromStr, collections::HashMap};
113    /// use alloy_rpc_types::state::StateOverridesBuilder;
114    /// use alloy_sol_types::{sol, SolCall};
115    ///
116    /// sol!(
117    ///     function greeting(uint256 i) public returns (string);
118    /// );
119    ///
120    /// # async fn foo() -> eyre::Result<()> {
121    /// let alloy_provider = ProviderBuilder::<_,_, AnyNetwork>::default().connect("http://localhost:8545").await?;;
122    /// let to = Address::from_str("0xB3C95ff08316fb2F2e3E52Ee82F8e7b605Aa1304")?;
123    /// let greeting = greetingCall { i: U256::from(5) }.abi_encode();
124    /// let bytes = Bytes::from_iter(greeting.iter());
125    /// let tx = TransactionRequest::default().to(to).input(bytes.into());
126    /// let tx = WithOtherFields::new(tx);
127    ///
128    /// // Create state overrides
129    /// let mut state_override = StateOverride::default();
130    /// let mut account_override = AccountOverride::default();
131    /// account_override.balance = Some(U256::from(1000));
132    /// state_override.insert(to, account_override);
133    /// let state_override_object = StateOverridesBuilder::default().build();
134    /// let block_override_object = BlockOverrides::default();
135    ///
136    /// let cast = Cast::new(alloy_provider);
137    /// let data = cast.call(&tx, None, None, Some(state_override_object), Some(block_override_object)).await?;
138    /// println!("{}", data);
139    /// # Ok(())
140    /// # }
141    /// ```
142    pub async fn call(
143        &self,
144        req: &N::TransactionRequest,
145        func: Option<&Function>,
146        block: Option<BlockId>,
147        state_override: Option<StateOverride>,
148        block_override: Option<BlockOverrides>,
149    ) -> Result<String> {
150        let mut call = self
151            .provider
152            .call(req.clone())
153            .block(block.unwrap_or_default())
154            .with_block_overrides_opt(block_override);
155        if let Some(state_override) = state_override {
156            call = call.overrides(state_override)
157        }
158
159        let res = call.await?;
160        let decoded = if let Some(func) = func {
161            // decode args into tokens
162            match func.abi_decode_output(res.as_ref()) {
163                Ok(decoded) => decoded,
164                Err(err) => {
165                    // ensure the address is a contract
166                    if res.is_empty() {
167                        // check that the recipient is a contract that can be called
168                        if let Some(addr) = req.to() {
169                            if let Ok(code) = self
170                                .provider
171                                .get_code_at(addr)
172                                .block_id(block.unwrap_or_default())
173                                .await
174                                && code.is_empty()
175                            {
176                                eyre::bail!("contract {addr:?} does not have any code")
177                            }
178                        } else if req.to().is_none() {
179                            eyre::bail!("tx req is a contract deployment");
180                        } else {
181                            eyre::bail!("recipient is None");
182                        }
183                    }
184                    return Err(err).wrap_err(
185                        "could not decode output; did you specify the wrong function return data type?"
186                    );
187                }
188            }
189        } else {
190            vec![]
191        };
192
193        // handle case when return type is not specified
194        Ok(if decoded.is_empty() {
195            res.to_string()
196        } else if shell::is_json() {
197            let tokens = decoded
198                .into_iter()
199                .map(|value| serialize_value_as_json(value, None))
200                .collect::<eyre::Result<Vec<_>>>()?;
201            serde_json::to_string_pretty(&tokens).unwrap()
202        } else {
203            // seth compatible user-friendly return type conversions
204            decoded.iter().map(format_token).collect::<Vec<_>>().join("\n")
205        })
206    }
207
208    /// Generates an access list for the specified transaction
209    ///
210    /// # Example
211    ///
212    /// ```
213    /// use cast::{Cast};
214    /// use alloy_primitives::{Address, U256, Bytes};
215    /// use alloy_rpc_types::{TransactionRequest};
216    /// use alloy_serde::WithOtherFields;
217    /// use alloy_provider::{RootProvider, ProviderBuilder, network::AnyNetwork};
218    /// use std::str::FromStr;
219    /// use alloy_sol_types::{sol, SolCall};
220    ///
221    /// sol!(
222    ///     function greeting(uint256 i) public returns (string);
223    /// );
224    ///
225    /// # async fn foo() -> eyre::Result<()> {
226    /// let provider = ProviderBuilder::<_,_, AnyNetwork>::default().connect("http://localhost:8545").await?;;
227    /// let to = Address::from_str("0xB3C95ff08316fb2F2e3E52Ee82F8e7b605Aa1304")?;
228    /// let greeting = greetingCall { i: U256::from(5) }.abi_encode();
229    /// let bytes = Bytes::from_iter(greeting.iter());
230    /// let tx = TransactionRequest::default().to(to).input(bytes.into());
231    /// let tx = WithOtherFields::new(tx);
232    /// let cast = Cast::new(&provider);
233    /// let access_list = cast.access_list(&tx, None).await?;
234    /// println!("{}", access_list);
235    /// # Ok(())
236    /// # }
237    /// ```
238    pub async fn access_list(
239        &self,
240        req: &N::TransactionRequest,
241        block: Option<BlockId>,
242    ) -> Result<String> {
243        let access_list =
244            self.provider.create_access_list(req).block_id(block.unwrap_or_default()).await?;
245        let res = if shell::is_json() {
246            serde_json::to_string(&access_list)?
247        } else {
248            let mut s =
249                vec![format!("gas used: {}", access_list.gas_used), "access list:".to_string()];
250            for al in access_list.access_list.0 {
251                s.push(format!("- address: {}", al.address.to_checksum(None)));
252                if !al.storage_keys.is_empty() {
253                    s.push("  keys:".to_string());
254                    for key in al.storage_keys {
255                        s.push(format!("    {key:?}"));
256                    }
257                }
258            }
259            s.join("\n")
260        };
261
262        Ok(res)
263    }
264
265    pub async fn balance(&self, who: Address, block: Option<BlockId>) -> Result<U256> {
266        Ok(self.provider.get_balance(who).block_id(block.unwrap_or_default()).await?)
267    }
268
269    /// Publishes a raw transaction to the network
270    ///
271    /// # Example
272    ///
273    /// ```
274    /// use alloy_provider::{ProviderBuilder, RootProvider, network::AnyNetwork};
275    /// use cast::Cast;
276    ///
277    /// # async fn foo() -> eyre::Result<()> {
278    /// let provider =
279    ///     ProviderBuilder::<_, _, AnyNetwork>::default().connect("http://localhost:8545").await?;
280    /// let cast = Cast::new(provider);
281    /// let res = cast.publish("0x1234".to_string()).await?;
282    /// println!("{:?}", res);
283    /// # Ok(())
284    /// # }
285    /// ```
286    pub async fn publish(&self, raw_tx: String) -> Result<PendingTransactionBuilder<N>> {
287        let tx = hex::decode(strip_0x(&raw_tx))?;
288        let res = self.provider.send_raw_transaction(&tx).await?;
289
290        Ok(res)
291    }
292
293    pub async fn chain_id(&self) -> Result<u64> {
294        Ok(self.provider.get_chain_id().await?)
295    }
296
297    pub async fn block_number(&self) -> Result<u64> {
298        Ok(self.provider.get_block_number().await?)
299    }
300
301    pub async fn gas_price(&self) -> Result<u128> {
302        Ok(self.provider.get_gas_price().await?)
303    }
304
305    /// # Example
306    ///
307    /// ```
308    /// use alloy_primitives::Address;
309    /// use alloy_provider::{ProviderBuilder, RootProvider, network::AnyNetwork};
310    /// use cast::Cast;
311    /// use std::str::FromStr;
312    ///
313    /// # async fn foo() -> eyre::Result<()> {
314    /// let provider =
315    ///     ProviderBuilder::<_, _, AnyNetwork>::default().connect("http://localhost:8545").await?;
316    /// let cast = Cast::new(provider);
317    /// let addr = Address::from_str("0x7eD52863829AB99354F3a0503A622e82AcD5F7d3")?;
318    /// let nonce = cast.nonce(addr, None).await?;
319    /// println!("{}", nonce);
320    /// # Ok(())
321    /// # }
322    /// ```
323    pub async fn nonce(&self, who: Address, block: Option<BlockId>) -> Result<u64> {
324        Ok(self.provider.get_transaction_count(who).block_id(block.unwrap_or_default()).await?)
325    }
326
327    /// #Example
328    ///
329    /// ```
330    /// use alloy_primitives::{Address, FixedBytes};
331    /// use alloy_provider::{network::AnyNetwork, ProviderBuilder, RootProvider};
332    /// use cast::Cast;
333    /// use std::str::FromStr;
334    ///
335    /// # async fn foo() -> eyre::Result<()> {
336    /// let provider =
337    ///     ProviderBuilder::<_, _, AnyNetwork>::default().connect("http://localhost:8545").await?;
338    /// let cast = Cast::new(provider);
339    /// let addr = Address::from_str("0x7eD52863829AB99354F3a0503A622e82AcD5F7d3")?;
340    /// let slots = vec![FixedBytes::from_str("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")?];
341    /// let codehash = cast.codehash(addr, slots, None).await?;
342    /// println!("{}", codehash);
343    /// # Ok(())
344    /// # }
345    pub async fn codehash(
346        &self,
347        who: Address,
348        slots: Vec<B256>,
349        block: Option<BlockId>,
350    ) -> Result<String> {
351        Ok(self
352            .provider
353            .get_proof(who, slots)
354            .block_id(block.unwrap_or_default())
355            .await?
356            .code_hash
357            .to_string())
358    }
359
360    /// #Example
361    ///
362    /// ```
363    /// use alloy_primitives::{Address, FixedBytes};
364    /// use alloy_provider::{network::AnyNetwork, ProviderBuilder, RootProvider};
365    /// use cast::Cast;
366    /// use std::str::FromStr;
367    ///
368    /// # async fn foo() -> eyre::Result<()> {
369    /// let provider =
370    ///     ProviderBuilder::<_, _, AnyNetwork>::default().connect("http://localhost:8545").await?;
371    /// let cast = Cast::new(provider);
372    /// let addr = Address::from_str("0x7eD52863829AB99354F3a0503A622e82AcD5F7d3")?;
373    /// let slots = vec![FixedBytes::from_str("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")?];
374    /// let storage_root = cast.storage_root(addr, slots, None).await?;
375    /// println!("{}", storage_root);
376    /// # Ok(())
377    /// # }
378    pub async fn storage_root(
379        &self,
380        who: Address,
381        slots: Vec<B256>,
382        block: Option<BlockId>,
383    ) -> Result<String> {
384        Ok(self
385            .provider
386            .get_proof(who, slots)
387            .block_id(block.unwrap_or_default())
388            .await?
389            .storage_hash
390            .to_string())
391    }
392
393    /// # Example
394    ///
395    /// ```
396    /// use alloy_primitives::Address;
397    /// use alloy_provider::{ProviderBuilder, RootProvider, network::AnyNetwork};
398    /// use cast::Cast;
399    /// use std::str::FromStr;
400    ///
401    /// # async fn foo() -> eyre::Result<()> {
402    /// let provider =
403    ///     ProviderBuilder::<_, _, AnyNetwork>::default().connect("http://localhost:8545").await?;
404    /// let cast = Cast::new(provider);
405    /// let addr = Address::from_str("0x7eD52863829AB99354F3a0503A622e82AcD5F7d3")?;
406    /// let implementation = cast.implementation(addr, false, None).await?;
407    /// println!("{}", implementation);
408    /// # Ok(())
409    /// # }
410    /// ```
411    pub async fn implementation(
412        &self,
413        who: Address,
414        is_beacon: bool,
415        block: Option<BlockId>,
416    ) -> Result<String> {
417        let slot = match is_beacon {
418            true => {
419                // Use the beacon slot : bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)
420                B256::from_str(
421                    "0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50",
422                )?
423            }
424            false => {
425                // Use the implementation slot :
426                // bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)
427                B256::from_str(
428                    "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc",
429                )?
430            }
431        };
432
433        let value = self
434            .provider
435            .get_storage_at(who, slot.into())
436            .block_id(block.unwrap_or_default())
437            .await?;
438        let addr = Address::from_word(value.into());
439        Ok(format!("{addr:?}"))
440    }
441
442    /// # Example
443    ///
444    /// ```
445    /// use alloy_primitives::Address;
446    /// use alloy_provider::{ProviderBuilder, RootProvider, network::AnyNetwork};
447    /// use cast::Cast;
448    /// use std::str::FromStr;
449    ///
450    /// # async fn foo() -> eyre::Result<()> {
451    /// let provider =
452    ///     ProviderBuilder::<_, _, AnyNetwork>::default().connect("http://localhost:8545").await?;
453    /// let cast = Cast::new(provider);
454    /// let addr = Address::from_str("0x7eD52863829AB99354F3a0503A622e82AcD5F7d3")?;
455    /// let admin = cast.admin(addr, None).await?;
456    /// println!("{}", admin);
457    /// # Ok(())
458    /// # }
459    /// ```
460    pub async fn admin(&self, who: Address, block: Option<BlockId>) -> Result<String> {
461        let slot =
462            B256::from_str("0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103")?;
463        let value = self
464            .provider
465            .get_storage_at(who, slot.into())
466            .block_id(block.unwrap_or_default())
467            .await?;
468        let addr = Address::from_word(value.into());
469        Ok(format!("{addr:?}"))
470    }
471
472    /// # Example
473    ///
474    /// ```
475    /// use alloy_primitives::{Address, U256};
476    /// use alloy_provider::{ProviderBuilder, RootProvider, network::AnyNetwork};
477    /// use cast::Cast;
478    /// use std::str::FromStr;
479    ///
480    /// # async fn foo() -> eyre::Result<()> {
481    /// let provider =
482    ///     ProviderBuilder::<_, _, AnyNetwork>::default().connect("http://localhost:8545").await?;
483    /// let cast = Cast::new(provider);
484    /// let addr = Address::from_str("7eD52863829AB99354F3a0503A622e82AcD5F7d3")?;
485    /// let computed_address = cast.compute_address(addr, None).await?;
486    /// println!("Computed address for address {addr}: {computed_address}");
487    /// # Ok(())
488    /// # }
489    /// ```
490    pub async fn compute_address(&self, address: Address, nonce: Option<u64>) -> Result<Address> {
491        let unpacked = if let Some(n) = nonce { n } else { self.nonce(address, None).await? };
492        Ok(address.create(unpacked))
493    }
494
495    /// # Example
496    ///
497    /// ```
498    /// use alloy_primitives::Address;
499    /// use alloy_provider::{ProviderBuilder, RootProvider, network::AnyNetwork};
500    /// use cast::Cast;
501    /// use std::str::FromStr;
502    ///
503    /// # async fn foo() -> eyre::Result<()> {
504    /// let provider =
505    ///     ProviderBuilder::<_, _, AnyNetwork>::default().connect("http://localhost:8545").await?;
506    /// let cast = Cast::new(provider);
507    /// let addr = Address::from_str("0x00000000219ab540356cbb839cbe05303d7705fa")?;
508    /// let code = cast.code(addr, None, false).await?;
509    /// println!("{}", code);
510    /// # Ok(())
511    /// # }
512    /// ```
513    pub async fn code(
514        &self,
515        who: Address,
516        block: Option<BlockId>,
517        disassemble: bool,
518    ) -> Result<String> {
519        if disassemble {
520            let code =
521                self.provider.get_code_at(who).block_id(block.unwrap_or_default()).await?.to_vec();
522            SimpleCast::disassemble(&code)
523        } else {
524            Ok(format!(
525                "{}",
526                self.provider.get_code_at(who).block_id(block.unwrap_or_default()).await?
527            ))
528        }
529    }
530
531    /// Example
532    ///
533    /// ```
534    /// use alloy_primitives::Address;
535    /// use alloy_provider::{ProviderBuilder, RootProvider, network::AnyNetwork};
536    /// use cast::Cast;
537    /// use std::str::FromStr;
538    ///
539    /// # async fn foo() -> eyre::Result<()> {
540    /// let provider =
541    ///     ProviderBuilder::<_, _, AnyNetwork>::default().connect("http://localhost:8545").await?;
542    /// let cast = Cast::new(provider);
543    /// let addr = Address::from_str("0x00000000219ab540356cbb839cbe05303d7705fa")?;
544    /// let codesize = cast.codesize(addr, None).await?;
545    /// println!("{}", codesize);
546    /// # Ok(())
547    /// # }
548    /// ```
549    pub async fn codesize(&self, who: Address, block: Option<BlockId>) -> Result<String> {
550        let code =
551            self.provider.get_code_at(who).block_id(block.unwrap_or_default()).await?.to_vec();
552        Ok(code.len().to_string())
553    }
554
555    /// Perform a raw JSON-RPC request
556    ///
557    /// # Example
558    ///
559    /// ```
560    /// use alloy_provider::{ProviderBuilder, RootProvider, network::AnyNetwork};
561    /// use cast::Cast;
562    ///
563    /// # async fn foo() -> eyre::Result<()> {
564    /// let provider =
565    ///     ProviderBuilder::<_, _, AnyNetwork>::default().connect("http://localhost:8545").await?;
566    /// let cast = Cast::new(provider);
567    /// let result = cast
568    ///     .rpc("eth_getBalance", &["0xc94770007dda54cF92009BFF0dE90c06F603a09f", "latest"])
569    ///     .await?;
570    /// println!("{}", result);
571    /// # Ok(())
572    /// # }
573    /// ```
574    pub async fn rpc<V>(&self, method: &str, params: V) -> Result<String>
575    where
576        V: alloy_json_rpc::RpcSend,
577    {
578        let res = self
579            .provider
580            .raw_request::<V, serde_json::Value>(Cow::Owned(method.to_string()), params)
581            .await?;
582        Ok(serde_json::to_string(&res)?)
583    }
584
585    /// Returns the slot
586    ///
587    /// # Example
588    ///
589    /// ```
590    /// use alloy_primitives::{Address, B256};
591    /// use alloy_provider::{ProviderBuilder, RootProvider, network::AnyNetwork};
592    /// use cast::Cast;
593    /// use std::str::FromStr;
594    ///
595    /// # async fn foo() -> eyre::Result<()> {
596    /// let provider =
597    ///     ProviderBuilder::<_, _, AnyNetwork>::default().connect("http://localhost:8545").await?;
598    /// let cast = Cast::new(provider);
599    /// let addr = Address::from_str("0x00000000006c3852cbEf3e08E8dF289169EdE581")?;
600    /// let slot = B256::ZERO;
601    /// let storage = cast.storage(addr, slot, None).await?;
602    /// println!("{}", storage);
603    /// # Ok(())
604    /// # }
605    /// ```
606    pub async fn storage(
607        &self,
608        from: Address,
609        slot: B256,
610        block: Option<BlockId>,
611    ) -> Result<String> {
612        Ok(format!(
613            "{:?}",
614            B256::from(
615                self.provider
616                    .get_storage_at(from, slot.into())
617                    .block_id(block.unwrap_or_default())
618                    .await?
619            )
620        ))
621    }
622
623    pub async fn filter_logs(&self, filter: Filter) -> Result<String> {
624        let logs = self.provider.get_logs(&filter).await?;
625        Self::format_logs(logs)
626    }
627
628    /// Retrieves logs using chunked requests to handle large block ranges.
629    ///
630    /// Automatically divides large block ranges into smaller chunks to avoid provider limits
631    /// and processes them with controlled concurrency to prevent rate limiting.
632    pub async fn filter_logs_chunked(&self, filter: Filter, chunk_size: u64) -> Result<String> {
633        let logs = self.get_logs_chunked(&filter, chunk_size).await?;
634        Self::format_logs(logs)
635    }
636
637    fn format_logs(logs: Vec<Log>) -> Result<String> {
638        let res = if shell::is_json() {
639            serde_json::to_string(&logs)?
640        } else {
641            let mut s = vec![];
642            for log in logs {
643                let pretty = log
644                    .pretty()
645                    .replacen('\n', "- ", 1) // Remove empty first line
646                    .replace('\n', "\n  "); // Indent
647                s.push(pretty);
648            }
649            s.join("\n")
650        };
651        Ok(res)
652    }
653
654    fn extract_block_range(filter: &Filter) -> (Option<u64>, Option<u64>) {
655        let FilterBlockOption::Range { from_block, to_block } = &filter.block_option else {
656            return (None, None);
657        };
658
659        (from_block.and_then(|b| b.as_number()), to_block.and_then(|b| b.as_number()))
660    }
661
662    /// Retrieves logs with automatic chunking fallback.
663    ///
664    /// First tries to fetch logs for the entire range. If that fails,
665    /// falls back to concurrent chunked requests with rate limiting.
666    async fn get_logs_chunked(&self, filter: &Filter, chunk_size: u64) -> Result<Vec<Log>>
667    where
668        P: Clone + Unpin,
669    {
670        // Try the full range first
671        if let Ok(logs) = self.provider.get_logs(filter).await {
672            return Ok(logs);
673        }
674
675        // Fallback: use concurrent chunked approach
676        self.get_logs_chunked_concurrent(filter, chunk_size).await
677    }
678
679    /// Retrieves logs using concurrent chunked requests with rate limiting.
680    ///
681    /// Divides the block range into chunks and processes them with a maximum of
682    /// 5 concurrent requests. Falls back to single-block queries if chunks fail.
683    async fn get_logs_chunked_concurrent(
684        &self,
685        filter: &Filter,
686        chunk_size: u64,
687    ) -> Result<Vec<Log>>
688    where
689        P: Clone + Unpin,
690    {
691        let (from_block, to_block) = Self::extract_block_range(filter);
692        let (Some(from), Some(to)) = (from_block, to_block) else {
693            return self.provider.get_logs(filter).await.map_err(Into::into);
694        };
695
696        if from >= to {
697            return Ok(vec![]);
698        }
699
700        // Create chunk ranges using iterator
701        let chunk_ranges: Vec<(u64, u64)> = (from..to)
702            .step_by(chunk_size as usize)
703            .map(|chunk_start| (chunk_start, (chunk_start + chunk_size).min(to)))
704            .collect();
705
706        // Process chunks with controlled concurrency using buffered stream
707        let mut all_results: Vec<(u64, Vec<Log>)> = futures::stream::iter(chunk_ranges)
708            .map(|(start_block, chunk_end)| {
709                let chunk_filter = filter.clone().from_block(start_block).to_block(chunk_end - 1);
710                let provider = self.provider.clone();
711
712                async move {
713                    // Try direct chunk request with simplified fallback
714                    match provider.get_logs(&chunk_filter).await {
715                        Ok(logs) => (start_block, logs),
716                        Err(_) => {
717                            // Simple fallback: try individual blocks in this chunk
718                            let mut fallback_logs = Vec::new();
719                            for single_block in start_block..chunk_end {
720                                let single_filter = chunk_filter
721                                    .clone()
722                                    .from_block(single_block)
723                                    .to_block(single_block);
724                                if let Ok(logs) = provider.get_logs(&single_filter).await {
725                                    fallback_logs.extend(logs);
726                                }
727                            }
728                            (start_block, fallback_logs)
729                        }
730                    }
731                }
732            })
733            .buffered(5) // Limit to 5 concurrent requests to avoid rate limits
734            .collect()
735            .await;
736
737        // Sort once at the end by block number and flatten
738        all_results.sort_by_key(|(block_num, _)| *block_num);
739
740        let mut all_logs = Vec::new();
741        for (_, logs) in all_results {
742            all_logs.extend(logs);
743        }
744
745        Ok(all_logs)
746    }
747
748    /// Converts a block identifier into a block number.
749    ///
750    /// If the block identifier is a block number, then this function returns the block number. If
751    /// the block identifier is a block hash, then this function returns the block number of
752    /// that block hash. If the block identifier is `None`, then this function returns `None`.
753    ///
754    /// # Example
755    ///
756    /// ```
757    /// use alloy_primitives::fixed_bytes;
758    /// use alloy_provider::{ProviderBuilder, RootProvider, network::AnyNetwork};
759    /// use alloy_rpc_types::{BlockId, BlockNumberOrTag};
760    /// use cast::Cast;
761    /// use std::{convert::TryFrom, str::FromStr};
762    ///
763    /// # async fn foo() -> eyre::Result<()> {
764    /// let provider =
765    ///     ProviderBuilder::<_, _, AnyNetwork>::default().connect("http://localhost:8545").await?;
766    /// let cast = Cast::new(provider);
767    ///
768    /// let block_number = cast.convert_block_number(Some(BlockId::number(5))).await?;
769    /// assert_eq!(block_number, Some(BlockNumberOrTag::Number(5)));
770    ///
771    /// let block_number = cast
772    ///     .convert_block_number(Some(BlockId::hash(fixed_bytes!(
773    ///         "0000000000000000000000000000000000000000000000000000000000001234"
774    ///     ))))
775    ///     .await?;
776    /// assert_eq!(block_number, Some(BlockNumberOrTag::Number(4660)));
777    ///
778    /// let block_number = cast.convert_block_number(None).await?;
779    /// assert_eq!(block_number, None);
780    /// # Ok(())
781    /// # }
782    /// ```
783    pub async fn convert_block_number(
784        &self,
785        block: Option<BlockId>,
786    ) -> Result<Option<BlockNumberOrTag>, eyre::Error> {
787        match block {
788            Some(block) => match block {
789                BlockId::Number(block_number) => Ok(Some(block_number)),
790                BlockId::Hash(hash) => {
791                    let block = self.provider.get_block_by_hash(hash.block_hash).await?;
792                    Ok(block.map(|block| block.header().number()).map(BlockNumberOrTag::from))
793                }
794            },
795            None => Ok(None),
796        }
797    }
798
799    /// Sets up a subscription to the given filter and writes the logs to the given output.
800    ///
801    /// # Example
802    ///
803    /// ```
804    /// use alloy_primitives::Address;
805    /// use alloy_provider::{ProviderBuilder, RootProvider, network::AnyNetwork};
806    /// use alloy_rpc_types::Filter;
807    /// use alloy_transport::BoxTransport;
808    /// use cast::Cast;
809    /// use std::{io, str::FromStr};
810    ///
811    /// # async fn foo() -> eyre::Result<()> {
812    /// let provider =
813    ///     ProviderBuilder::<_, _, AnyNetwork>::default().connect("wss://localhost:8545").await?;
814    /// let cast = Cast::new(provider);
815    ///
816    /// let filter =
817    ///     Filter::new().address(Address::from_str("0x00000000006c3852cbEf3e08E8dF289169EdE581")?);
818    /// let mut output = io::stdout();
819    /// cast.subscribe(filter, &mut output).await?;
820    /// # Ok(())
821    /// # }
822    /// ```
823    pub async fn subscribe(&self, filter: Filter, output: &mut dyn io::Write) -> Result<()> {
824        // Initialize the subscription stream for logs
825        let mut subscription = self.provider.subscribe_logs(&filter).await?.into_stream();
826
827        // Check if a to_block is specified, if so, subscribe to blocks
828        let mut block_subscription = if filter.get_to_block().is_some() {
829            Some(self.provider.subscribe_blocks().await?.into_stream())
830        } else {
831            None
832        };
833
834        let format_json = shell::is_json();
835        let to_block_number = filter.get_to_block();
836
837        // If output should be JSON, start with an opening bracket
838        if format_json {
839            write!(output, "[")?;
840        }
841
842        let mut first = true;
843
844        loop {
845            tokio::select! {
846                // If block subscription is present, listen to it to avoid blocking indefinitely past the desired to_block
847                block = if let Some(bs) = &mut block_subscription {
848                    Either::Left(bs.next().fuse())
849                } else {
850                    Either::Right(futures::future::pending())
851                } => {
852                    if let (Some(block), Some(to_block)) = (block, to_block_number)
853                        && block.number()  > to_block {
854                            break;
855                        }
856                },
857                // Process incoming log
858                log = subscription.next() => {
859                    if format_json {
860                        if !first {
861                            write!(output, ",")?;
862                        }
863                        first = false;
864                        let log_str = serde_json::to_string(&log).unwrap();
865                        write!(output, "{log_str}")?;
866                    } else {
867                        let log_str = log.pretty()
868                            .replacen('\n', "- ", 1)  // Remove empty first line
869                            .replace('\n', "\n  ");  // Indent
870                        writeln!(output, "{log_str}")?;
871                    }
872                },
873                // Break on cancel signal, to allow for closing JSON bracket
874                _ = ctrl_c() => {
875                    break;
876                },
877                else => break,
878            }
879        }
880
881        // If output was JSON, end with a closing bracket
882        if format_json {
883            write!(output, "]")?;
884        }
885
886        Ok(())
887    }
888}
889
890impl<P: Provider<N>, N: Network> Cast<P, N>
891where
892    N::HeaderResponse: UIfmtHeaderExt,
893    N::BlockResponse: UIfmt,
894{
895    /// # Example
896    ///
897    /// ```
898    /// use alloy_provider::{ProviderBuilder, RootProvider, network::AnyNetwork};
899    /// use cast::Cast;
900    ///
901    /// # async fn foo() -> eyre::Result<()> {
902    /// let provider =
903    ///     ProviderBuilder::<_, _, AnyNetwork>::default().connect("http://localhost:8545").await?;
904    /// let cast = Cast::new(provider);
905    /// let block = cast.block(5, true, vec![]).await?;
906    /// println!("{}", block);
907    /// # Ok(())
908    /// # }
909    /// ```
910    pub async fn block<B: Into<BlockId>>(
911        &self,
912        block: B,
913        full: bool,
914        fields: Vec<String>,
915    ) -> Result<String> {
916        let block = block.into();
917        if fields.contains(&"transactions".into()) && !full {
918            eyre::bail!("use --full to view transactions")
919        }
920
921        let block = self
922            .provider
923            .get_block(block)
924            .kind(full.into())
925            .await?
926            .ok_or_else(|| eyre::eyre!("block {:?} not found", block))?;
927
928        Ok(if !fields.is_empty() {
929            let mut result = String::new();
930            for field in fields {
931                result.push_str(
932                    &get_pretty_block_attr::<N>(&block, &field)
933                        .unwrap_or_else(|| format!("{field} is not a valid block field")),
934                );
935
936                result.push('\n');
937            }
938            result.trim_end().to_string()
939        } else if shell::is_json() {
940            serde_json::to_value(&block).unwrap().to_string()
941        } else {
942            block.pretty()
943        })
944    }
945
946    async fn block_field_as_num<B: Into<BlockId>>(&self, block: B, field: String) -> Result<U256> {
947        Self::block(
948            self,
949            block.into(),
950            false,
951            // Select only select field
952            vec![field],
953        )
954        .await?
955        .parse()
956        .map_err(Into::into)
957    }
958
959    pub async fn base_fee<B: Into<BlockId>>(&self, block: B) -> Result<U256> {
960        Self::block_field_as_num(self, block, String::from("baseFeePerGas")).await
961    }
962
963    pub async fn age<B: Into<BlockId>>(&self, block: B) -> Result<String> {
964        let timestamp_str =
965            Self::block_field_as_num(self, block, String::from("timestamp")).await?.to_string();
966        let datetime = DateTime::from_timestamp(timestamp_str.parse::<i64>().unwrap(), 0).unwrap();
967        Ok(datetime.format("%a %b %e %H:%M:%S %Y").to_string())
968    }
969
970    pub async fn timestamp<B: Into<BlockId>>(&self, block: B) -> Result<U256> {
971        Self::block_field_as_num(self, block, "timestamp".to_string()).await
972    }
973
974    pub async fn chain(&self) -> Result<&str> {
975        let genesis_hash = Self::block(
976            self,
977            0,
978            false,
979            // Select only block hash
980            vec![String::from("hash")],
981        )
982        .await?;
983
984        Ok(match &genesis_hash[..] {
985            "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" => {
986                match &(Self::block(self, 1920000, false, vec![String::from("hash")]).await?)[..] {
987                    "0x94365e3a8c0b35089c1d1195081fe7489b528a84b22199c916180db8b28ade7f" => {
988                        "etclive"
989                    }
990                    _ => "ethlive",
991                }
992            }
993            "0xa3c565fc15c7478862d50ccd6561e3c06b24cc509bf388941c25ea985ce32cb9" => "kovan",
994            "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d" => "ropsten",
995            "0x7ca38a1916c42007829c55e69d3e9a73265554b586a499015373241b8a3fa48b" => {
996                "optimism-mainnet"
997            }
998            "0xc1fc15cd51159b1f1e5cbc4b82e85c1447ddfa33c52cf1d98d14fba0d6354be1" => {
999                "optimism-goerli"
1000            }
1001            "0x02adc9b449ff5f2467b8c674ece7ff9b21319d76c4ad62a67a70d552655927e5" => {
1002                "optimism-kovan"
1003            }
1004            "0x521982bd54239dc71269eefb58601762cc15cfb2978e0becb46af7962ed6bfaa" => "fraxtal",
1005            "0x910f5c4084b63fd860d0c2f9a04615115a5a991254700b39ba072290dbd77489" => {
1006                "fraxtal-testnet"
1007            }
1008            "0x7ee576b35482195fc49205cec9af72ce14f003b9ae69f6ba0faef4514be8b442" => {
1009                "arbitrum-mainnet"
1010            }
1011            "0x0cd786a2425d16f152c658316c423e6ce1181e15c3295826d7c9904cba9ce303" => "morden",
1012            "0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177" => "rinkeby",
1013            "0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a" => "goerli",
1014            "0x14c2283285a88fe5fce9bf5c573ab03d6616695d717b12a127188bcacfc743c4" => "kotti",
1015            "0xa9c28ce2141b56c474f1dc504bee9b01eb1bd7d1a507580d5519d4437a97de1b" => "polygon-pos",
1016            "0x7202b2b53c5a0836e773e319d18922cc756dd67432f9a1f65352b61f4406c697" => {
1017                "polygon-pos-amoy-testnet"
1018            }
1019            "0x81005434635456a16f74ff7023fbe0bf423abbc8a8deb093ffff455c0ad3b741" => "polygon-zkevm",
1020            "0x676c1a76a6c5855a32bdf7c61977a0d1510088a4eeac1330466453b3d08b60b9" => {
1021                "polygon-zkevm-cardona-testnet"
1022            }
1023            "0x4f1dd23188aab3a76b463e4af801b52b1248ef073c648cbdc4c9333d3da79756" => "gnosis",
1024            "0xada44fd8d2ecab8b08f256af07ad3e777f17fb434f8f8e678b312f576212ba9a" => "chiado",
1025            "0x6d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34" => "bsctest",
1026            "0x0d21840abff46b96c84b2ac9e10e4f5cdaeb5693cb665db62a2f3b02d2d57b5b" => "bsc",
1027            "0x31ced5b9beb7f8782b014660da0cb18cc409f121f408186886e1ca3e8eeca96b" => {
1028                match &(Self::block(self, 1, false, vec![String::from("hash")]).await?)[..] {
1029                    "0x738639479dc82d199365626f90caa82f7eafcfe9ed354b456fb3d294597ceb53" => {
1030                        "avalanche-fuji"
1031                    }
1032                    _ => "avalanche",
1033                }
1034            }
1035            "0x23a2658170ba70d014ba0d0d2709f8fbfe2fa660cd868c5f282f991eecbe38ee" => "ink",
1036            "0xe5fd5cf0be56af58ad5751b401410d6b7a09d830fa459789746a3d0dd1c79834" => "ink-sepolia",
1037            _ => "unknown",
1038        })
1039    }
1040}
1041
1042impl<P: Provider<N>, N: Network> Cast<P, N>
1043where
1044    N::Header: Encodable,
1045{
1046    /// # Example
1047    ///
1048    /// ```
1049    /// use alloy_provider::{ProviderBuilder, RootProvider, network::Ethereum};
1050    /// use cast::Cast;
1051    ///
1052    /// # async fn foo() -> eyre::Result<()> {
1053    /// let provider =
1054    ///     ProviderBuilder::<_, _, Ethereum>::default().connect("http://localhost:8545").await?;
1055    /// let cast = Cast::new(provider);
1056    /// let block = cast.block_raw(5, true).await?;
1057    /// println!("{}", block);
1058    /// # Ok(())
1059    /// # }
1060    /// ```
1061    pub async fn block_raw<B: Into<BlockId>>(&self, block: B, full: bool) -> Result<String> {
1062        let block_id = block.into();
1063
1064        let block = self
1065            .provider
1066            .get_block(block_id)
1067            .kind(full.into())
1068            .await?
1069            .ok_or_else(|| eyre::eyre!("block {:?} not found", block_id))?;
1070
1071        let encoded = alloy_rlp::encode(block.header().as_ref());
1072
1073        Ok(format!("0x{}", hex::encode(encoded)))
1074    }
1075}
1076
1077impl<P: Provider<N>, N: Network> Cast<P, N>
1078where
1079    N::TxEnvelope: Serialize + UIfmtSignatureExt,
1080    N::TransactionResponse: UIfmt,
1081{
1082    /// # Example
1083    ///
1084    /// ```
1085    /// use alloy_provider::{ProviderBuilder, RootProvider, network::AnyNetwork};
1086    /// use cast::Cast;
1087    ///
1088    /// # async fn foo() -> eyre::Result<()> {
1089    /// let provider =
1090    ///     ProviderBuilder::<_, _, AnyNetwork>::default().connect("http://localhost:8545").await?;
1091    /// let cast = Cast::new(provider);
1092    /// let tx_hash = "0xf8d1713ea15a81482958fb7ddf884baee8d3bcc478c5f2f604e008dc788ee4fc";
1093    /// let tx = cast.transaction(Some(tx_hash.to_string()), None, None, None, false, false).await?;
1094    /// println!("{}", tx);
1095    /// # Ok(())
1096    /// # }
1097    /// ```
1098    pub async fn transaction(
1099        &self,
1100        tx_hash: Option<String>,
1101        from: Option<NameOrAddress>,
1102        nonce: Option<u64>,
1103        field: Option<String>,
1104        raw: bool,
1105        to_request: bool,
1106    ) -> Result<String> {
1107        let tx = if let Some(tx_hash) = tx_hash {
1108            let tx_hash = TxHash::from_str(&tx_hash).wrap_err("invalid tx hash")?;
1109            self.provider
1110                .get_transaction_by_hash(tx_hash)
1111                .await?
1112                .ok_or_else(|| eyre::eyre!("tx not found: {:?}", tx_hash))?
1113        } else if let Some(from) = from {
1114            // If nonce is not provided, uses 0.
1115            let nonce = U64::from(nonce.unwrap_or_default());
1116            let from = from.resolve(self.provider.root()).await?;
1117
1118            self.provider
1119                .raw_request::<_, Option<N::TransactionResponse>>(
1120                    "eth_getTransactionBySenderAndNonce".into(),
1121                    (from, nonce),
1122                )
1123                .await?
1124                .ok_or_else(|| {
1125                    eyre::eyre!("tx not found for sender {from} and nonce {:?}", nonce.to::<u64>())
1126                })?
1127        } else {
1128            eyre::bail!("tx hash or from address is required")
1129        };
1130
1131        Ok(if raw {
1132            let encoded = tx.as_ref().encoded_2718();
1133            format!("0x{}", hex::encode(encoded))
1134        } else if let Some(ref field) = field {
1135            get_pretty_tx_attr::<N>(&tx, field.as_str())
1136                .ok_or_else(|| eyre::eyre!("invalid tx field: {}", field.clone()))?
1137        } else if shell::is_json() {
1138            // to_value first to sort json object keys
1139            serde_json::to_value(&tx)?.to_string()
1140        } else if to_request {
1141            serde_json::to_string_pretty(&Into::<N::TransactionRequest>::into(tx))?
1142        } else {
1143            tx.pretty()
1144        })
1145    }
1146}
1147
1148pub struct SimpleCast;
1149
1150impl SimpleCast {
1151    /// Returns the maximum value of the given integer type
1152    ///
1153    /// # Example
1154    ///
1155    /// ```
1156    /// use alloy_primitives::{I256, U256};
1157    /// use cast::SimpleCast;
1158    ///
1159    /// assert_eq!(SimpleCast::max_int("uint256")?, U256::MAX.to_string());
1160    /// assert_eq!(SimpleCast::max_int("int256")?, I256::MAX.to_string());
1161    /// assert_eq!(SimpleCast::max_int("int32")?, i32::MAX.to_string());
1162    /// # Ok::<(), eyre::Report>(())
1163    /// ```
1164    pub fn max_int(s: &str) -> Result<String> {
1165        Self::max_min_int::<true>(s)
1166    }
1167
1168    /// Returns the maximum value of the given integer type
1169    ///
1170    /// # Example
1171    ///
1172    /// ```
1173    /// use alloy_primitives::{I256, U256};
1174    /// use cast::SimpleCast;
1175    ///
1176    /// assert_eq!(SimpleCast::min_int("uint256")?, "0");
1177    /// assert_eq!(SimpleCast::min_int("int256")?, I256::MIN.to_string());
1178    /// assert_eq!(SimpleCast::min_int("int32")?, i32::MIN.to_string());
1179    /// # Ok::<(), eyre::Report>(())
1180    /// ```
1181    pub fn min_int(s: &str) -> Result<String> {
1182        Self::max_min_int::<false>(s)
1183    }
1184
1185    fn max_min_int<const MAX: bool>(s: &str) -> Result<String> {
1186        let ty = DynSolType::parse(s).wrap_err("Invalid type, expected `(u)int<bit size>`")?;
1187        match ty {
1188            DynSolType::Int(n) => {
1189                let mask = U256::from(1).wrapping_shl(n - 1);
1190                let max = (U256::MAX & mask).saturating_sub(U256::from(1));
1191                if MAX {
1192                    Ok(max.to_string())
1193                } else {
1194                    let min = I256::from_raw(max).wrapping_neg() + I256::MINUS_ONE;
1195                    Ok(min.to_string())
1196                }
1197            }
1198            DynSolType::Uint(n) => {
1199                if MAX {
1200                    let mut max = U256::MAX;
1201                    if n < 256 {
1202                        max &= U256::from(1).wrapping_shl(n).wrapping_sub(U256::from(1));
1203                    }
1204                    Ok(max.to_string())
1205                } else {
1206                    Ok("0".to_string())
1207                }
1208            }
1209            _ => Err(eyre::eyre!("Type is not int/uint: {s}")),
1210        }
1211    }
1212
1213    /// Converts UTF-8 text input to hex
1214    ///
1215    /// # Example
1216    ///
1217    /// ```
1218    /// use cast::SimpleCast as Cast;
1219    ///
1220    /// assert_eq!(Cast::from_utf8("yo"), "0x796f");
1221    /// assert_eq!(Cast::from_utf8("Hello, World!"), "0x48656c6c6f2c20576f726c6421");
1222    /// assert_eq!(Cast::from_utf8("TurboDappTools"), "0x547572626f44617070546f6f6c73");
1223    /// # Ok::<_, eyre::Report>(())
1224    /// ```
1225    pub fn from_utf8(s: &str) -> String {
1226        hex::encode_prefixed(s)
1227    }
1228
1229    /// Converts hex input to UTF-8 text
1230    ///
1231    /// # Example
1232    ///
1233    /// ```
1234    /// use cast::SimpleCast as Cast;
1235    ///
1236    /// assert_eq!(Cast::to_utf8("0x796f")?, "yo");
1237    /// assert_eq!(Cast::to_utf8("0x48656c6c6f2c20576f726c6421")?, "Hello, World!");
1238    /// assert_eq!(Cast::to_utf8("0x547572626f44617070546f6f6c73")?, "TurboDappTools");
1239    /// assert_eq!(Cast::to_utf8("0xe4bda0e5a5bd")?, "你好");
1240    /// # Ok::<_, eyre::Report>(())
1241    /// ```
1242    pub fn to_utf8(s: &str) -> Result<String> {
1243        let bytes = hex::decode(s)?;
1244        Ok(String::from_utf8_lossy(bytes.as_ref()).to_string())
1245    }
1246
1247    /// Converts hex data into text data
1248    ///
1249    /// # Example
1250    ///
1251    /// ```
1252    /// use cast::SimpleCast as Cast;
1253    ///
1254    /// assert_eq!(Cast::to_ascii("0x796f")?, "yo");
1255    /// assert_eq!(Cast::to_ascii("48656c6c6f2c20576f726c6421")?, "Hello, World!");
1256    /// assert_eq!(Cast::to_ascii("0x547572626f44617070546f6f6c73")?, "TurboDappTools");
1257    /// # Ok::<_, eyre::Report>(())
1258    /// ```
1259    pub fn to_ascii(hex: &str) -> Result<String> {
1260        let bytes = hex::decode(hex)?;
1261        if !bytes.iter().all(u8::is_ascii) {
1262            return Err(eyre::eyre!("Invalid ASCII bytes"));
1263        }
1264        Ok(String::from_utf8(bytes).unwrap())
1265    }
1266
1267    /// Converts fixed point number into specified number of decimals
1268    /// ```
1269    /// use alloy_primitives::U256;
1270    /// use cast::SimpleCast as Cast;
1271    ///
1272    /// assert_eq!(Cast::from_fixed_point("10", "0")?, "10");
1273    /// assert_eq!(Cast::from_fixed_point("1.0", "1")?, "10");
1274    /// assert_eq!(Cast::from_fixed_point("0.10", "2")?, "10");
1275    /// assert_eq!(Cast::from_fixed_point("0.010", "3")?, "10");
1276    /// # Ok::<_, eyre::Report>(())
1277    /// ```
1278    pub fn from_fixed_point(value: &str, decimals: &str) -> Result<String> {
1279        let units: Unit = Unit::from_str(decimals)?;
1280        let n = ParseUnits::parse_units(value, units)?;
1281        Ok(n.to_string())
1282    }
1283
1284    /// Converts integers with specified decimals into fixed point numbers
1285    ///
1286    /// # Example
1287    ///
1288    /// ```
1289    /// use alloy_primitives::U256;
1290    /// use cast::SimpleCast as Cast;
1291    ///
1292    /// assert_eq!(Cast::to_fixed_point("10", "0")?, "10.");
1293    /// assert_eq!(Cast::to_fixed_point("10", "1")?, "1.0");
1294    /// assert_eq!(Cast::to_fixed_point("10", "2")?, "0.10");
1295    /// assert_eq!(Cast::to_fixed_point("10", "3")?, "0.010");
1296    ///
1297    /// assert_eq!(Cast::to_fixed_point("-10", "0")?, "-10.");
1298    /// assert_eq!(Cast::to_fixed_point("-10", "1")?, "-1.0");
1299    /// assert_eq!(Cast::to_fixed_point("-10", "2")?, "-0.10");
1300    /// assert_eq!(Cast::to_fixed_point("-10", "3")?, "-0.010");
1301    /// # Ok::<_, eyre::Report>(())
1302    /// ```
1303    pub fn to_fixed_point(value: &str, decimals: &str) -> Result<String> {
1304        let (sign, mut value, value_len) = {
1305            let number = NumberWithBase::parse_int(value, None)?;
1306            let sign = if number.is_nonnegative() { "" } else { "-" };
1307            let value = format!("{number:#}");
1308            let value_stripped = value.strip_prefix('-').unwrap_or(&value).to_string();
1309            let value_len = value_stripped.len();
1310            (sign, value_stripped, value_len)
1311        };
1312        let decimals = NumberWithBase::parse_uint(decimals, None)?.number().to::<usize>();
1313
1314        let value = if decimals >= value_len {
1315            // Add "0." and pad with 0s
1316            format!("0.{value:0>decimals$}")
1317        } else {
1318            // Insert decimal at -idx (i.e 1 => decimal idx = -1)
1319            value.insert(value_len - decimals, '.');
1320            value
1321        };
1322
1323        Ok(format!("{sign}{value}"))
1324    }
1325
1326    /// Concatencates hex strings
1327    ///
1328    /// # Example
1329    ///
1330    /// ```
1331    /// use cast::SimpleCast as Cast;
1332    ///
1333    /// assert_eq!(Cast::concat_hex(["0x00", "0x01"]), "0x0001");
1334    /// assert_eq!(Cast::concat_hex(["1", "2"]), "0x12");
1335    /// # Ok::<_, eyre::Report>(())
1336    /// ```
1337    pub fn concat_hex<T: AsRef<str>>(values: impl IntoIterator<Item = T>) -> String {
1338        let mut out = String::new();
1339        for s in values {
1340            let s = s.as_ref();
1341            out.push_str(strip_0x(s))
1342        }
1343        format!("0x{out}")
1344    }
1345
1346    /// Converts a number into uint256 hex string with 0x prefix
1347    ///
1348    /// # Example
1349    ///
1350    /// ```
1351    /// use cast::SimpleCast as Cast;
1352    ///
1353    /// assert_eq!(
1354    ///     Cast::to_uint256("100")?,
1355    ///     "0x0000000000000000000000000000000000000000000000000000000000000064"
1356    /// );
1357    /// assert_eq!(
1358    ///     Cast::to_uint256("192038293923")?,
1359    ///     "0x0000000000000000000000000000000000000000000000000000002cb65fd1a3"
1360    /// );
1361    /// assert_eq!(
1362    ///     Cast::to_uint256(
1363    ///         "115792089237316195423570985008687907853269984665640564039457584007913129639935"
1364    ///     )?,
1365    ///     "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
1366    /// );
1367    /// # Ok::<_, eyre::Report>(())
1368    /// ```
1369    pub fn to_uint256(value: &str) -> Result<String> {
1370        let n = NumberWithBase::parse_uint(value, None)?;
1371        Ok(format!("{n:#066x}"))
1372    }
1373
1374    /// Converts a number into int256 hex string with 0x prefix
1375    ///
1376    /// # Example
1377    ///
1378    /// ```
1379    /// use cast::SimpleCast as Cast;
1380    ///
1381    /// assert_eq!(
1382    ///     Cast::to_int256("0")?,
1383    ///     "0x0000000000000000000000000000000000000000000000000000000000000000"
1384    /// );
1385    /// assert_eq!(
1386    ///     Cast::to_int256("100")?,
1387    ///     "0x0000000000000000000000000000000000000000000000000000000000000064"
1388    /// );
1389    /// assert_eq!(
1390    ///     Cast::to_int256("-100")?,
1391    ///     "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c"
1392    /// );
1393    /// assert_eq!(
1394    ///     Cast::to_int256("192038293923")?,
1395    ///     "0x0000000000000000000000000000000000000000000000000000002cb65fd1a3"
1396    /// );
1397    /// assert_eq!(
1398    ///     Cast::to_int256("-192038293923")?,
1399    ///     "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffd349a02e5d"
1400    /// );
1401    /// assert_eq!(
1402    ///     Cast::to_int256(
1403    ///         "57896044618658097711785492504343953926634992332820282019728792003956564819967"
1404    ///     )?,
1405    ///     "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
1406    /// );
1407    /// assert_eq!(
1408    ///     Cast::to_int256(
1409    ///         "-57896044618658097711785492504343953926634992332820282019728792003956564819968"
1410    ///     )?,
1411    ///     "0x8000000000000000000000000000000000000000000000000000000000000000"
1412    /// );
1413    /// # Ok::<_, eyre::Report>(())
1414    /// ```
1415    pub fn to_int256(value: &str) -> Result<String> {
1416        let n = NumberWithBase::parse_int(value, None)?;
1417        Ok(format!("{n:#066x}"))
1418    }
1419
1420    /// Converts an eth amount into a specified unit
1421    ///
1422    /// # Example
1423    ///
1424    /// ```
1425    /// use cast::SimpleCast as Cast;
1426    ///
1427    /// assert_eq!(Cast::to_unit("1 wei", "wei")?, "1");
1428    /// assert_eq!(Cast::to_unit("1", "wei")?, "1");
1429    /// assert_eq!(Cast::to_unit("1ether", "wei")?, "1000000000000000000");
1430    /// # Ok::<_, eyre::Report>(())
1431    /// ```
1432    pub fn to_unit(value: &str, unit: &str) -> Result<String> {
1433        let value = DynSolType::coerce_str(&DynSolType::Uint(256), value)?
1434            .as_uint()
1435            .wrap_err("Could not convert to uint")?
1436            .0;
1437        let unit = unit.parse().wrap_err("could not parse units")?;
1438        Ok(Self::format_unit_as_string(value, unit))
1439    }
1440
1441    /// Convert a number into a uint with arbitrary decimals.
1442    ///
1443    /// # Example
1444    ///
1445    /// ```
1446    /// use cast::SimpleCast as Cast;
1447    ///
1448    /// # fn main() -> eyre::Result<()> {
1449    /// assert_eq!(Cast::parse_units("1.0", 6)?, "1000000"); // USDC (6 decimals)
1450    /// assert_eq!(Cast::parse_units("2.5", 6)?, "2500000");
1451    /// assert_eq!(Cast::parse_units("1.0", 12)?, "1000000000000"); // 12 decimals
1452    /// assert_eq!(Cast::parse_units("1.23", 3)?, "1230"); // 3 decimals
1453    ///
1454    /// # Ok(())
1455    /// # }
1456    /// ```
1457    pub fn parse_units(value: &str, unit: u8) -> Result<String> {
1458        let unit = Unit::new(unit).ok_or_else(|| eyre::eyre!("invalid unit"))?;
1459
1460        Ok(ParseUnits::parse_units(value, unit)?.to_string())
1461    }
1462
1463    /// Format a number from smallest unit to decimal with arbitrary decimals.
1464    ///
1465    /// # Example
1466    ///
1467    /// ```
1468    /// use cast::SimpleCast as Cast;
1469    ///
1470    /// # fn main() -> eyre::Result<()> {
1471    /// assert_eq!(Cast::format_units("1000000", 6)?, "1"); // USDC (6 decimals)
1472    /// assert_eq!(Cast::format_units("2500000", 6)?, "2.500000");
1473    /// assert_eq!(Cast::format_units("1000000000000", 12)?, "1"); // 12 decimals
1474    /// assert_eq!(Cast::format_units("1230", 3)?, "1.230"); // 3 decimals
1475    ///
1476    /// # Ok(())
1477    /// # }
1478    /// ```
1479    pub fn format_units(value: &str, unit: u8) -> Result<String> {
1480        let value = NumberWithBase::parse_int(value, None)?.number();
1481        let unit = Unit::new(unit).ok_or_else(|| eyre::eyre!("invalid unit"))?;
1482        Ok(Self::format_unit_as_string(value, unit))
1483    }
1484
1485    // Helper function to format units as a string
1486    fn format_unit_as_string(value: U256, unit: Unit) -> String {
1487        let mut formatted = ParseUnits::U256(value).format_units(unit);
1488        // Trim empty fractional part.
1489        if let Some(dot) = formatted.find('.') {
1490            let fractional = &formatted[dot + 1..];
1491            if fractional.chars().all(|c: char| c == '0') {
1492                formatted = formatted[..dot].to_string();
1493            }
1494        }
1495        formatted
1496    }
1497
1498    /// Converts wei into an eth amount
1499    ///
1500    /// # Example
1501    ///
1502    /// ```
1503    /// use cast::SimpleCast as Cast;
1504    ///
1505    /// assert_eq!(Cast::from_wei("1", "gwei")?, "0.000000001");
1506    /// assert_eq!(Cast::from_wei("12340000005", "gwei")?, "12.340000005");
1507    /// assert_eq!(Cast::from_wei("10", "ether")?, "0.000000000000000010");
1508    /// assert_eq!(Cast::from_wei("100", "eth")?, "0.000000000000000100");
1509    /// assert_eq!(Cast::from_wei("17", "ether")?, "0.000000000000000017");
1510    /// # Ok::<_, eyre::Report>(())
1511    /// ```
1512    pub fn from_wei(value: &str, unit: &str) -> Result<String> {
1513        let value = NumberWithBase::parse_int(value, None)?.number();
1514        Ok(ParseUnits::U256(value).format_units(unit.parse()?))
1515    }
1516
1517    /// Converts an eth amount into wei
1518    ///
1519    /// # Example
1520    ///
1521    /// ```
1522    /// use cast::SimpleCast as Cast;
1523    ///
1524    /// assert_eq!(Cast::to_wei("100", "gwei")?, "100000000000");
1525    /// assert_eq!(Cast::to_wei("100", "eth")?, "100000000000000000000");
1526    /// assert_eq!(Cast::to_wei("1000", "ether")?, "1000000000000000000000");
1527    /// # Ok::<_, eyre::Report>(())
1528    /// ```
1529    pub fn to_wei(value: &str, unit: &str) -> Result<String> {
1530        let unit = unit.parse().wrap_err("could not parse units")?;
1531        Ok(ParseUnits::parse_units(value, unit)?.to_string())
1532    }
1533
1534    // Decodes RLP encoded data with validation for canonical integer representation
1535    ///
1536    /// # Examples
1537    /// ```
1538    /// use cast::SimpleCast as Cast;
1539    ///
1540    /// assert_eq!(Cast::from_rlp("0xc0", false).unwrap(), "[]");
1541    /// assert_eq!(Cast::from_rlp("0x0f", false).unwrap(), "\"0x0f\"");
1542    /// assert_eq!(Cast::from_rlp("0x33", false).unwrap(), "\"0x33\"");
1543    /// assert_eq!(Cast::from_rlp("0xc161", false).unwrap(), "[\"0x61\"]");
1544    /// assert_eq!(Cast::from_rlp("820002", true).is_err(), true);
1545    /// assert_eq!(Cast::from_rlp("820002", false).unwrap(), "\"0x0002\"");
1546    /// assert_eq!(Cast::from_rlp("00", true).is_err(), true);
1547    /// assert_eq!(Cast::from_rlp("00", false).unwrap(), "\"0x00\"");
1548    /// # Ok::<_, eyre::Report>(())
1549    /// ```
1550    pub fn from_rlp(value: impl AsRef<str>, as_int: bool) -> Result<String> {
1551        let bytes = hex::decode(value.as_ref()).wrap_err("Could not decode hex")?;
1552
1553        if as_int {
1554            return Ok(U256::decode(&mut &bytes[..])?.to_string());
1555        }
1556
1557        let item = Item::decode(&mut &bytes[..]).wrap_err("Could not decode rlp")?;
1558
1559        Ok(item.to_string())
1560    }
1561
1562    /// Encodes hex data or list of hex data to hexadecimal rlp
1563    ///
1564    /// # Example
1565    ///
1566    /// ```
1567    /// use cast::SimpleCast as Cast;
1568    ///
1569    /// assert_eq!(Cast::to_rlp("[]").unwrap(), "0xc0".to_string());
1570    /// assert_eq!(Cast::to_rlp("0x22").unwrap(), "0x22".to_string());
1571    /// assert_eq!(Cast::to_rlp("[\"0x61\"]",).unwrap(), "0xc161".to_string());
1572    /// assert_eq!(Cast::to_rlp("[\"0xf1\", \"f2\"]").unwrap(), "0xc481f181f2".to_string());
1573    /// # Ok::<_, eyre::Report>(())
1574    /// ```
1575    pub fn to_rlp(value: &str) -> Result<String> {
1576        let val = serde_json::from_str(value)
1577            .unwrap_or_else(|_| serde_json::Value::String(value.to_string()));
1578        let item = Item::value_to_item(&val)?;
1579        Ok(format!("0x{}", hex::encode(alloy_rlp::encode(item))))
1580    }
1581
1582    /// Converts a number of one base to another
1583    ///
1584    /// # Example
1585    ///
1586    /// ```
1587    /// use alloy_primitives::I256;
1588    /// use cast::SimpleCast as Cast;
1589    ///
1590    /// assert_eq!(Cast::to_base("100", Some("10"), "16")?, "0x64");
1591    /// assert_eq!(Cast::to_base("100", Some("10"), "oct")?, "0o144");
1592    /// assert_eq!(Cast::to_base("100", Some("10"), "binary")?, "0b1100100");
1593    ///
1594    /// assert_eq!(Cast::to_base("0xffffffffffffffff", None, "10")?, u64::MAX.to_string());
1595    /// assert_eq!(
1596    ///     Cast::to_base("0xffffffffffffffffffffffffffffffff", None, "dec")?,
1597    ///     u128::MAX.to_string()
1598    /// );
1599    /// // U256::MAX overflows as internally it is being parsed as I256
1600    /// assert_eq!(
1601    ///     Cast::to_base(
1602    ///         "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
1603    ///         None,
1604    ///         "decimal"
1605    ///     )?,
1606    ///     I256::MAX.to_string()
1607    /// );
1608    /// # Ok::<_, eyre::Report>(())
1609    /// ```
1610    pub fn to_base(value: &str, base_in: Option<&str>, base_out: &str) -> Result<String> {
1611        let base_in = Base::unwrap_or_detect(base_in, value)?;
1612        let base_out: Base = base_out.parse()?;
1613        if base_in == base_out {
1614            return Ok(value.to_string());
1615        }
1616
1617        let mut n = NumberWithBase::parse_int(value, Some(&base_in.to_string()))?;
1618        n.set_base(base_out);
1619
1620        // Use Debug fmt
1621        Ok(format!("{n:#?}"))
1622    }
1623
1624    /// Converts hexdata into bytes32 value
1625    ///
1626    /// # Example
1627    ///
1628    /// ```
1629    /// use cast::SimpleCast as Cast;
1630    ///
1631    /// let bytes = Cast::to_bytes32("1234")?;
1632    /// assert_eq!(bytes, "0x1234000000000000000000000000000000000000000000000000000000000000");
1633    ///
1634    /// let bytes = Cast::to_bytes32("0x1234")?;
1635    /// assert_eq!(bytes, "0x1234000000000000000000000000000000000000000000000000000000000000");
1636    ///
1637    /// let err = Cast::to_bytes32("0x123400000000000000000000000000000000000000000000000000000000000011").unwrap_err();
1638    /// assert_eq!(err.to_string(), "string >32 bytes");
1639    /// # Ok::<_, eyre::Report>(())
1640    pub fn to_bytes32(s: &str) -> Result<String> {
1641        let s = strip_0x(s);
1642        if s.len() > 64 {
1643            eyre::bail!("string >32 bytes");
1644        }
1645
1646        let padded = format!("{s:0<64}");
1647        Ok(padded.parse::<B256>()?.to_string())
1648    }
1649
1650    /// Encodes string into bytes32 value
1651    pub fn format_bytes32_string(s: &str) -> Result<String> {
1652        let str_bytes: &[u8] = s.as_bytes();
1653        eyre::ensure!(str_bytes.len() <= 32, "bytes32 strings must not exceed 32 bytes in length");
1654
1655        let mut bytes32: [u8; 32] = [0u8; 32];
1656        bytes32[..str_bytes.len()].copy_from_slice(str_bytes);
1657        Ok(hex::encode_prefixed(bytes32))
1658    }
1659
1660    /// Pads hex data to a specified length
1661    ///
1662    /// # Example
1663    ///
1664    /// ```
1665    /// use cast::SimpleCast as Cast;
1666    ///
1667    /// let padded = Cast::pad("abcd", true, 20)?;
1668    /// assert_eq!(padded, "0xabcd000000000000000000000000000000000000");
1669    ///
1670    /// let padded = Cast::pad("abcd", false, 20)?;
1671    /// assert_eq!(padded, "0x000000000000000000000000000000000000abcd");
1672    ///
1673    /// let padded = Cast::pad("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", true, 32)?;
1674    /// assert_eq!(padded, "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2000000000000000000000000");
1675    ///
1676    /// let padded = Cast::pad("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", false, 32)?;
1677    /// assert_eq!(padded, "0x000000000000000000000000C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2");
1678    ///
1679    /// let err = Cast::pad("1234", false, 1).unwrap_err();
1680    /// assert_eq!(err.to_string(), "input length exceeds target length");
1681    ///
1682    /// let err = Cast::pad("foobar", false, 32).unwrap_err();
1683    /// assert_eq!(err.to_string(), "input is not a valid hex");
1684    ///
1685    /// # Ok::<_, eyre::Report>(())
1686    /// ```
1687    pub fn pad(s: &str, right: bool, len: usize) -> Result<String> {
1688        let s = strip_0x(s);
1689        let hex_len = len * 2;
1690
1691        // Validate input
1692        if s.len() > hex_len {
1693            eyre::bail!("input length exceeds target length");
1694        }
1695        if !s.chars().all(|c| c.is_ascii_hexdigit()) {
1696            eyre::bail!("input is not a valid hex");
1697        }
1698
1699        Ok(if right { format!("0x{s:0<hex_len$}") } else { format!("0x{s:0>hex_len$}") })
1700    }
1701
1702    /// Decodes string from bytes32 value
1703    pub fn parse_bytes32_string(s: &str) -> Result<String> {
1704        let bytes = hex::decode(s)?;
1705        eyre::ensure!(bytes.len() == 32, "expected 32 byte hex-string");
1706        let len = bytes.iter().take_while(|x| **x != 0).count();
1707        Ok(std::str::from_utf8(&bytes[..len])?.into())
1708    }
1709
1710    /// Decodes checksummed address from bytes32 value
1711    pub fn parse_bytes32_address(s: &str) -> Result<String> {
1712        let s = strip_0x(s);
1713        if s.len() != 64 {
1714            eyre::bail!("expected 64 byte hex-string, got {s}");
1715        }
1716
1717        let s = if let Some(stripped) = s.strip_prefix("000000000000000000000000") {
1718            stripped
1719        } else {
1720            return Err(eyre::eyre!("Not convertible to address, there are non-zero bytes"));
1721        };
1722
1723        let lowercase_address_string = format!("0x{s}");
1724        let lowercase_address = Address::from_str(&lowercase_address_string)?;
1725
1726        Ok(lowercase_address.to_checksum(None))
1727    }
1728
1729    /// Decodes abi-encoded hex input or output
1730    ///
1731    /// When `input=true`, `calldata` string MUST not be prefixed with function selector
1732    ///
1733    /// # Example
1734    ///
1735    /// ```
1736    /// use cast::SimpleCast as Cast;
1737    /// use alloy_primitives::hex;
1738    ///
1739    ///     // Passing `input = false` will decode the data as the output type.
1740    ///     // The input data types and the full function sig are ignored, i.e.
1741    ///     // you could also pass `balanceOf()(uint256)` and it'd still work.
1742    ///     let data = "0x0000000000000000000000000000000000000000000000000000000000000001";
1743    ///     let sig = "balanceOf(address, uint256)(uint256)";
1744    ///     let decoded = Cast::abi_decode(sig, data, false)?[0].as_uint().unwrap().0.to_string();
1745    ///     assert_eq!(decoded, "1");
1746    ///
1747    ///     // Passing `input = true` will decode the data with the input function signature.
1748    ///     // We exclude the "prefixed" function selector from the data field (the first 4 bytes).
1749    ///     let data = "0x0000000000000000000000008dbd1b711dc621e1404633da156fcc779e1c6f3e000000000000000000000000d9f3c9cc99548bf3b44a43e0a2d07399eb918adc000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000";
1750    ///     let sig = "safeTransferFrom(address, address, uint256, uint256, bytes)";
1751    ///     let decoded = Cast::abi_decode(sig, data, true)?;
1752    ///     let decoded = [
1753    ///         decoded[0].as_address().unwrap().to_string().to_lowercase(),
1754    ///         decoded[1].as_address().unwrap().to_string().to_lowercase(),
1755    ///         decoded[2].as_uint().unwrap().0.to_string(),
1756    ///         decoded[3].as_uint().unwrap().0.to_string(),
1757    ///         hex::encode(decoded[4].as_bytes().unwrap())
1758    ///     ]
1759    ///     .into_iter()
1760    ///     .collect::<Vec<_>>();
1761    ///
1762    ///     assert_eq!(
1763    ///         decoded,
1764    ///         vec!["0x8dbd1b711dc621e1404633da156fcc779e1c6f3e", "0xd9f3c9cc99548bf3b44a43e0a2d07399eb918adc", "42", "1", ""]
1765    ///     );
1766    /// # Ok::<_, eyre::Report>(())
1767    /// ```
1768    pub fn abi_decode(sig: &str, calldata: &str, input: bool) -> Result<Vec<DynSolValue>> {
1769        foundry_common::abi::abi_decode_calldata(sig, calldata, input, false)
1770    }
1771
1772    /// Decodes calldata-encoded hex input or output
1773    ///
1774    /// Similar to `abi_decode`, but `calldata` string MUST be prefixed with function selector
1775    ///
1776    /// # Example
1777    ///
1778    /// ```
1779    /// use cast::SimpleCast as Cast;
1780    /// use alloy_primitives::hex;
1781    ///
1782    /// // Passing `input = false` will decode the data as the output type.
1783    /// // The input data types and the full function sig are ignored, i.e.
1784    /// // you could also pass `balanceOf()(uint256)` and it'd still work.
1785    /// let data = "0x0000000000000000000000000000000000000000000000000000000000000001";
1786    /// let sig = "balanceOf(address, uint256)(uint256)";
1787    /// let decoded = Cast::calldata_decode(sig, data, false)?[0].as_uint().unwrap().0.to_string();
1788    /// assert_eq!(decoded, "1");
1789    ///
1790    ///     // Passing `input = true` will decode the data with the input function signature.
1791    ///     let data = "0xf242432a0000000000000000000000008dbd1b711dc621e1404633da156fcc779e1c6f3e000000000000000000000000d9f3c9cc99548bf3b44a43e0a2d07399eb918adc000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000";
1792    ///     let sig = "safeTransferFrom(address, address, uint256, uint256, bytes)";
1793    ///     let decoded = Cast::calldata_decode(sig, data, true)?;
1794    ///     let decoded = [
1795    ///         decoded[0].as_address().unwrap().to_string().to_lowercase(),
1796    ///         decoded[1].as_address().unwrap().to_string().to_lowercase(),
1797    ///         decoded[2].as_uint().unwrap().0.to_string(),
1798    ///         decoded[3].as_uint().unwrap().0.to_string(),
1799    ///         hex::encode(decoded[4].as_bytes().unwrap()),
1800    ///    ]
1801    ///    .into_iter()
1802    ///    .collect::<Vec<_>>();
1803    ///     assert_eq!(
1804    ///         decoded,
1805    ///         vec!["0x8dbd1b711dc621e1404633da156fcc779e1c6f3e", "0xd9f3c9cc99548bf3b44a43e0a2d07399eb918adc", "42", "1", ""]
1806    ///     );
1807    /// # Ok::<_, eyre::Report>(())
1808    /// ```
1809    pub fn calldata_decode(sig: &str, calldata: &str, input: bool) -> Result<Vec<DynSolValue>> {
1810        foundry_common::abi::abi_decode_calldata(sig, calldata, input, true)
1811    }
1812
1813    /// Performs ABI encoding based off of the function signature. Does not include
1814    /// the function selector in the result.
1815    ///
1816    /// # Example
1817    ///
1818    /// ```
1819    /// use cast::SimpleCast as Cast;
1820    ///
1821    /// assert_eq!(
1822    ///     "0x0000000000000000000000000000000000000000000000000000000000000001",
1823    ///     Cast::abi_encode("f(uint a)", &["1"]).unwrap().as_str()
1824    /// );
1825    /// assert_eq!(
1826    ///     "0x0000000000000000000000000000000000000000000000000000000000000001",
1827    ///     Cast::abi_encode("constructor(uint a)", &["1"]).unwrap().as_str()
1828    /// );
1829    /// # Ok::<_, eyre::Report>(())
1830    /// ```
1831    pub fn abi_encode(sig: &str, args: &[impl AsRef<str>]) -> Result<String> {
1832        let func = get_func(sig)?;
1833        match encode_function_args(&func, args) {
1834            Ok(res) => Ok(hex::encode_prefixed(&res[4..])),
1835            Err(e) => eyre::bail!("Could not ABI encode the function and arguments: {e}"),
1836        }
1837    }
1838
1839    /// Performs packed ABI encoding based off of the function signature or tuple.
1840    ///
1841    /// # Examplez
1842    ///
1843    /// ```
1844    /// use cast::SimpleCast as Cast;
1845    ///
1846    /// assert_eq!(
1847    ///     "0x0000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000012c00000000000000c8",
1848    ///     Cast::abi_encode_packed("(uint128[] a, uint64 b)", &["[100, 300]", "200"]).unwrap().as_str()
1849    /// );
1850    ///
1851    /// assert_eq!(
1852    ///     "0x8dbd1b711dc621e1404633da156fcc779e1c6f3e68656c6c6f20776f726c64",
1853    ///     Cast::abi_encode_packed("foo(address a, string b)", &["0x8dbd1b711dc621e1404633da156fcc779e1c6f3e", "hello world"]).unwrap().as_str()
1854    /// );
1855    /// # Ok::<_, eyre::Report>(())
1856    /// ```
1857    pub fn abi_encode_packed(sig: &str, args: &[impl AsRef<str>]) -> Result<String> {
1858        // If the signature is a tuple, we need to prefix it to make it a function
1859        let sig =
1860            if sig.trim_start().starts_with('(') { format!("foo{sig}") } else { sig.to_string() };
1861
1862        let func = get_func(sig.as_str())?;
1863        let encoded = match encode_function_args_packed(&func, args) {
1864            Ok(res) => hex::encode(res),
1865            Err(e) => eyre::bail!("Could not ABI encode the function and arguments: {e}"),
1866        };
1867        Ok(format!("0x{encoded}"))
1868    }
1869
1870    /// Performs ABI encoding of an event to produce the topics and data.
1871    ///
1872    /// # Example
1873    ///
1874    /// ```
1875    /// use alloy_primitives::hex;
1876    /// use cast::SimpleCast as Cast;
1877    ///
1878    /// let log_data = Cast::abi_encode_event(
1879    ///     "Transfer(address indexed from, address indexed to, uint256 value)",
1880    ///     &[
1881    ///         "0x1234567890123456789012345678901234567890",
1882    ///         "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd",
1883    ///         "1000",
1884    ///     ],
1885    /// )
1886    /// .unwrap();
1887    ///
1888    /// // topic0 is the event selector
1889    /// assert_eq!(log_data.topics().len(), 3);
1890    /// assert_eq!(
1891    ///     log_data.topics()[0].to_string(),
1892    ///     "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
1893    /// );
1894    /// assert_eq!(
1895    ///     log_data.topics()[1].to_string(),
1896    ///     "0x0000000000000000000000001234567890123456789012345678901234567890"
1897    /// );
1898    /// assert_eq!(
1899    ///     log_data.topics()[2].to_string(),
1900    ///     "0x000000000000000000000000abcdefabcdefabcdefabcdefabcdefabcdefabcd"
1901    /// );
1902    /// assert_eq!(
1903    ///     hex::encode_prefixed(log_data.data),
1904    ///     "0x00000000000000000000000000000000000000000000000000000000000003e8"
1905    /// );
1906    /// # Ok::<_, eyre::Report>(())
1907    /// ```
1908    pub fn abi_encode_event(sig: &str, args: &[impl AsRef<str>]) -> Result<LogData> {
1909        let event = get_event(sig)?;
1910        let tokens = std::iter::zip(&event.inputs, args)
1911            .map(|(input, arg)| coerce_value(&input.ty, arg.as_ref()))
1912            .collect::<Result<Vec<_>>>()?;
1913
1914        let mut topics = vec![event.selector()];
1915        let mut data_tokens: Vec<u8> = Vec::new();
1916
1917        for (input, token) in event.inputs.iter().zip(tokens) {
1918            if input.indexed {
1919                let ty = DynSolType::parse(&input.ty)?;
1920                if matches!(
1921                    ty,
1922                    DynSolType::String
1923                        | DynSolType::Bytes
1924                        | DynSolType::Array(_)
1925                        | DynSolType::Tuple(_)
1926                ) {
1927                    // For dynamic types, hash the encoded value
1928                    let encoded = token.abi_encode();
1929                    let hash = keccak256(encoded);
1930                    topics.push(hash);
1931                } else {
1932                    // For fixed-size types, encode directly to 32 bytes
1933                    let mut encoded = [0u8; 32];
1934                    let token_encoded = token.abi_encode();
1935                    if token_encoded.len() <= 32 {
1936                        let start = 32 - token_encoded.len();
1937                        encoded[start..].copy_from_slice(&token_encoded);
1938                    }
1939                    topics.push(B256::from(encoded));
1940                }
1941            } else {
1942                // Non-indexed parameters go into data
1943                data_tokens.extend_from_slice(&token.abi_encode());
1944            }
1945        }
1946
1947        Ok(LogData::new_unchecked(topics, data_tokens.into()))
1948    }
1949
1950    /// Performs ABI encoding to produce the hexadecimal calldata with the given arguments.
1951    ///
1952    /// # Example
1953    ///
1954    /// ```
1955    /// use cast::SimpleCast as Cast;
1956    ///
1957    /// assert_eq!(
1958    ///     "0xb3de648b0000000000000000000000000000000000000000000000000000000000000001",
1959    ///     Cast::calldata_encode("f(uint256 a)", &["1"]).unwrap().as_str()
1960    /// );
1961    /// # Ok::<_, eyre::Report>(())
1962    /// ```
1963    pub fn calldata_encode(sig: impl AsRef<str>, args: &[impl AsRef<str>]) -> Result<String> {
1964        let func = get_func(sig.as_ref())?;
1965        let calldata = encode_function_args(&func, args)?;
1966        Ok(hex::encode_prefixed(calldata))
1967    }
1968
1969    /// Returns the slot number for a given mapping key and slot.
1970    ///
1971    /// Given `mapping(k => v) m`, for a key `k` the slot number of its associated `v` is
1972    /// `keccak256(concat(h(k), p))`, where `h` is the padding function for `k`'s type, and `p`
1973    /// is slot number of the mapping `m`.
1974    ///
1975    /// See [the Solidity documentation](https://docs.soliditylang.org/en/latest/internals/layout_in_storage.html#mappings-and-dynamic-arrays)
1976    /// for more details.
1977    ///
1978    /// # Example
1979    ///
1980    /// ```
1981    /// # use cast::SimpleCast as Cast;
1982    ///
1983    /// // Value types.
1984    /// assert_eq!(
1985    ///     Cast::index("address", "0xD0074F4E6490ae3f888d1d4f7E3E43326bD3f0f5", "2").unwrap().as_str(),
1986    ///     "0x9525a448a9000053a4d151336329d6563b7e80b24f8e628e95527f218e8ab5fb"
1987    /// );
1988    /// assert_eq!(
1989    ///     Cast::index("uint256", "42", "6").unwrap().as_str(),
1990    ///     "0xfc808b0f31a1e6b9cf25ff6289feae9b51017b392cc8e25620a94a38dcdafcc1"
1991    /// );
1992    ///
1993    /// // Strings and byte arrays.
1994    /// assert_eq!(
1995    ///     Cast::index("string", "hello", "1").unwrap().as_str(),
1996    ///     "0x8404bb4d805e9ca2bd5dd5c43a107e935c8ec393caa7851b353b3192cd5379ae"
1997    /// );
1998    /// # Ok::<_, eyre::Report>(())
1999    /// ```
2000    pub fn index(key_type: &str, key: &str, slot_number: &str) -> Result<String> {
2001        let mut hasher = Keccak256::new();
2002
2003        let k_ty = DynSolType::parse(key_type).wrap_err("Could not parse type")?;
2004        let k = k_ty.coerce_str(key).wrap_err("Could not parse value")?;
2005        match k_ty {
2006            // For value types, `h` pads the value to 32 bytes in the same way as when storing the
2007            // value in memory.
2008            DynSolType::Bool
2009            | DynSolType::Int(_)
2010            | DynSolType::Uint(_)
2011            | DynSolType::FixedBytes(_)
2012            | DynSolType::Address
2013            | DynSolType::Function => hasher.update(k.as_word().unwrap()),
2014
2015            // For strings and byte arrays, `h(k)` is just the unpadded data.
2016            DynSolType::String | DynSolType::Bytes => hasher.update(k.as_packed_seq().unwrap()),
2017
2018            DynSolType::Array(..)
2019            | DynSolType::FixedArray(..)
2020            | DynSolType::Tuple(..)
2021            | DynSolType::CustomStruct { .. } => {
2022                eyre::bail!("Type `{k_ty}` is not supported as a mapping key")
2023            }
2024        }
2025
2026        let p = DynSolType::Uint(256)
2027            .coerce_str(slot_number)
2028            .wrap_err("Could not parse slot number")?;
2029        let p = p.as_word().unwrap();
2030        hasher.update(p);
2031
2032        let location = hasher.finalize();
2033        Ok(location.to_string())
2034    }
2035
2036    /// Keccak-256 hashes arbitrary data
2037    ///
2038    /// # Example
2039    ///
2040    /// ```
2041    /// use cast::SimpleCast as Cast;
2042    ///
2043    /// assert_eq!(
2044    ///     Cast::keccak("foo")?,
2045    ///     "0x41b1a0649752af1b28b3dc29a1556eee781e4a4c3a1f7f53f90fa834de098c4d"
2046    /// );
2047    /// assert_eq!(
2048    ///     Cast::keccak("123abc")?,
2049    ///     "0xb1f1c74a1ba56f07a892ea1110a39349d40f66ca01d245e704621033cb7046a4"
2050    /// );
2051    /// assert_eq!(
2052    ///     Cast::keccak("0x12")?,
2053    ///     "0x5fa2358263196dbbf23d1ca7a509451f7a2f64c15837bfbb81298b1e3e24e4fa"
2054    /// );
2055    /// assert_eq!(
2056    ///     Cast::keccak("12")?,
2057    ///     "0x7f8b6b088b6d74c2852fc86c796dca07b44eed6fb3daf5e6b59f7c364db14528"
2058    /// );
2059    /// # Ok::<_, eyre::Report>(())
2060    /// ```
2061    pub fn keccak(data: &str) -> Result<String> {
2062        // Hex-decode if data starts with 0x.
2063        let hash = if data.starts_with("0x") {
2064            keccak256(hex::decode(data.trim_end())?)
2065        } else {
2066            keccak256(data)
2067        };
2068        Ok(hash.to_string())
2069    }
2070
2071    /// Performs the left shift operation (<<) on a number
2072    ///
2073    /// # Example
2074    ///
2075    /// ```
2076    /// use cast::SimpleCast as Cast;
2077    ///
2078    /// assert_eq!(Cast::left_shift("16", "10", Some("10"), "hex")?, "0x4000");
2079    /// assert_eq!(Cast::left_shift("255", "16", Some("dec"), "hex")?, "0xff0000");
2080    /// assert_eq!(Cast::left_shift("0xff", "16", None, "hex")?, "0xff0000");
2081    /// # Ok::<_, eyre::Report>(())
2082    /// ```
2083    pub fn left_shift(
2084        value: &str,
2085        bits: &str,
2086        base_in: Option<&str>,
2087        base_out: &str,
2088    ) -> Result<String> {
2089        let base_out: Base = base_out.parse()?;
2090        let value = NumberWithBase::parse_uint(value, base_in)?;
2091        let bits = NumberWithBase::parse_uint(bits, None)?;
2092
2093        let res = value.number() << bits.number();
2094
2095        Ok(res.to_base(base_out, true)?)
2096    }
2097
2098    /// Performs the right shift operation (>>) on a number
2099    ///
2100    /// # Example
2101    ///
2102    /// ```
2103    /// use cast::SimpleCast as Cast;
2104    ///
2105    /// assert_eq!(Cast::right_shift("0x4000", "10", None, "dec")?, "16");
2106    /// assert_eq!(Cast::right_shift("16711680", "16", Some("10"), "hex")?, "0xff");
2107    /// assert_eq!(Cast::right_shift("0xff0000", "16", None, "hex")?, "0xff");
2108    /// # Ok::<(), eyre::Report>(())
2109    /// ```
2110    pub fn right_shift(
2111        value: &str,
2112        bits: &str,
2113        base_in: Option<&str>,
2114        base_out: &str,
2115    ) -> Result<String> {
2116        let base_out: Base = base_out.parse()?;
2117        let value = NumberWithBase::parse_uint(value, base_in)?;
2118        let bits = NumberWithBase::parse_uint(bits, None)?;
2119
2120        let res = value.number().wrapping_shr(bits.number().saturating_to());
2121
2122        Ok(res.to_base(base_out, true)?)
2123    }
2124
2125    /// Fetches source code of verified contracts from etherscan.
2126    ///
2127    /// # Example
2128    ///
2129    /// ```
2130    /// # use cast::SimpleCast as Cast;
2131    /// # use foundry_config::NamedChain;
2132    /// # async fn foo() -> eyre::Result<()> {
2133    /// assert_eq!(
2134    ///     "/*
2135    ///             - Bytecode Verification performed was compared on second iteration -
2136    ///             This file is part of the DAO.....",
2137    ///     Cast::etherscan_source(
2138    ///         NamedChain::Mainnet.into(),
2139    ///         "0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413".to_string(),
2140    ///         Some("<etherscan_api_key>".to_string()),
2141    ///         None,
2142    ///         None
2143    ///     )
2144    ///     .await
2145    ///     .unwrap()
2146    ///     .as_str()
2147    /// );
2148    /// # Ok(())
2149    /// # }
2150    /// ```
2151    pub async fn etherscan_source(
2152        chain: Chain,
2153        contract_address: String,
2154        etherscan_api_key: Option<String>,
2155        explorer_api_url: Option<String>,
2156        explorer_url: Option<String>,
2157    ) -> Result<String> {
2158        let client = explorer_client(chain, etherscan_api_key, explorer_api_url, explorer_url)?;
2159        let metadata = client.contract_source_code(contract_address.parse()?).await?;
2160        Ok(metadata.source_code())
2161    }
2162
2163    /// Fetches the source code of verified contracts from etherscan and expands the resulting
2164    /// files to a directory for easy perusal.
2165    ///
2166    /// # Example
2167    ///
2168    /// ```
2169    /// # use cast::SimpleCast as Cast;
2170    /// # use foundry_config::NamedChain;
2171    /// # use std::path::PathBuf;
2172    /// # async fn expand() -> eyre::Result<()> {
2173    /// Cast::expand_etherscan_source_to_directory(
2174    ///     NamedChain::Mainnet.into(),
2175    ///     "0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413".to_string(),
2176    ///     Some("<etherscan_api_key>".to_string()),
2177    ///     PathBuf::from("output_dir"),
2178    ///     None,
2179    ///     None,
2180    /// )
2181    /// .await?;
2182    /// # Ok(())
2183    /// # }
2184    /// ```
2185    pub async fn expand_etherscan_source_to_directory(
2186        chain: Chain,
2187        contract_address: String,
2188        etherscan_api_key: Option<String>,
2189        output_directory: PathBuf,
2190        explorer_api_url: Option<String>,
2191        explorer_url: Option<String>,
2192    ) -> eyre::Result<()> {
2193        let client = explorer_client(chain, etherscan_api_key, explorer_api_url, explorer_url)?;
2194        let meta = client.contract_source_code(contract_address.parse()?).await?;
2195        let source_tree = meta.source_tree();
2196        source_tree.write_to(&output_directory)?;
2197        Ok(())
2198    }
2199
2200    /// Fetches the source code of verified contracts from etherscan, flattens it and writes it to
2201    /// the given path or stdout.
2202    pub async fn etherscan_source_flatten(
2203        chain: Chain,
2204        contract_address: String,
2205        etherscan_api_key: Option<String>,
2206        output_path: Option<PathBuf>,
2207        explorer_api_url: Option<String>,
2208        explorer_url: Option<String>,
2209    ) -> Result<()> {
2210        let client = explorer_client(chain, etherscan_api_key, explorer_api_url, explorer_url)?;
2211        let metadata = client.contract_source_code(contract_address.parse()?).await?;
2212        let Some(metadata) = metadata.items.first() else {
2213            eyre::bail!("Empty contract source code")
2214        };
2215
2216        let tmp = tempfile::tempdir()?;
2217        let project = etherscan_project(metadata, tmp.path())?;
2218        let target_path = project.find_contract_path(&metadata.contract_name)?;
2219
2220        let flattened = flatten(project, &target_path)?;
2221
2222        if let Some(path) = output_path {
2223            fs::create_dir_all(path.parent().unwrap())?;
2224            fs::write(&path, flattened)?;
2225            sh_println!("Flattened file written at {}", path.display())?
2226        } else {
2227            sh_println!("{flattened}")?
2228        }
2229
2230        Ok(())
2231    }
2232
2233    /// Disassembles hex encoded bytecode into individual / human readable opcodes
2234    ///
2235    /// # Example
2236    ///
2237    /// ```
2238    /// use alloy_primitives::hex;
2239    /// use cast::SimpleCast as Cast;
2240    ///
2241    /// # async fn foo() -> eyre::Result<()> {
2242    /// let bytecode = "0x608060405260043610603f57600035";
2243    /// let opcodes = Cast::disassemble(&hex::decode(bytecode)?)?;
2244    /// println!("{}", opcodes);
2245    /// # Ok(())
2246    /// # }
2247    /// ```
2248    pub fn disassemble(code: &[u8]) -> Result<String> {
2249        let mut output = String::new();
2250        for (pc, inst) in InstIter::new(code).with_pc() {
2251            writeln!(output, "{pc:08x}: {inst}")?;
2252        }
2253        Ok(output)
2254    }
2255
2256    /// Gets the selector for a given function signature
2257    /// Optimizes if the `optimize` parameter is set to a number of leading zeroes
2258    ///
2259    /// # Example
2260    ///
2261    /// ```
2262    /// use cast::SimpleCast as Cast;
2263    ///
2264    /// assert_eq!(Cast::get_selector("foo(address,uint256)", 0)?.0, String::from("0xbd0d639f"));
2265    /// # Ok::<(), eyre::Error>(())
2266    /// ```
2267    pub fn get_selector(signature: &str, optimize: usize) -> Result<(String, String)> {
2268        if optimize > 4 {
2269            eyre::bail!("number of leading zeroes must not be greater than 4");
2270        }
2271        if optimize == 0 {
2272            let selector = get_func(signature)?.selector();
2273            return Ok((selector.to_string(), String::from(signature)));
2274        }
2275        let Some((name, params)) = signature.split_once('(') else {
2276            eyre::bail!("invalid function signature");
2277        };
2278
2279        let num_threads = rayon::current_num_threads();
2280        let found = AtomicBool::new(false);
2281
2282        let result: Option<(u32, String, String)> =
2283            (0..num_threads).into_par_iter().find_map_any(|i| {
2284                let nonce_start = i as u32;
2285                let nonce_step = num_threads as u32;
2286
2287                let mut nonce = nonce_start;
2288                while nonce < u32::MAX && !found.load(Ordering::Relaxed) {
2289                    let input = format!("{name}{nonce}({params}");
2290                    let hash = keccak256(input.as_bytes());
2291                    let selector = &hash[..4];
2292
2293                    if selector.iter().take_while(|&&byte| byte == 0).count() == optimize {
2294                        found.store(true, Ordering::Relaxed);
2295                        return Some((nonce, hex::encode_prefixed(selector), input));
2296                    }
2297
2298                    nonce += nonce_step;
2299                }
2300                None
2301            });
2302
2303        match result {
2304            Some((_nonce, selector, signature)) => Ok((selector, signature)),
2305            None => eyre::bail!("No selector found"),
2306        }
2307    }
2308
2309    /// Extracts function selectors, arguments and state mutability from bytecode
2310    ///
2311    /// # Example
2312    ///
2313    /// ```
2314    /// use alloy_primitives::fixed_bytes;
2315    /// use cast::SimpleCast as Cast;
2316    ///
2317    /// let bytecode = "6080604052348015600e575f80fd5b50600436106026575f3560e01c80632125b65b14602a575b5f80fd5b603a6035366004603c565b505050565b005b5f805f60608486031215604d575f80fd5b833563ffffffff81168114605f575f80fd5b925060208401356001600160a01b03811681146079575f80fd5b915060408401356001600160e01b03811681146093575f80fd5b80915050925092509256";
2318    /// let functions = Cast::extract_functions(bytecode)?;
2319    /// assert_eq!(functions, vec![(fixed_bytes!("0x2125b65b"), "uint32,address,uint224".to_string(), "pure")]);
2320    /// # Ok::<(), eyre::Report>(())
2321    /// ```
2322    pub fn extract_functions(bytecode: &str) -> Result<Vec<(Selector, String, &str)>> {
2323        let code = hex::decode(bytecode)?;
2324        let info = evmole::contract_info(
2325            evmole::ContractInfoArgs::new(&code)
2326                .with_selectors()
2327                .with_arguments()
2328                .with_state_mutability(),
2329        );
2330        Ok(info
2331            .functions
2332            .expect("functions extraction was requested")
2333            .into_iter()
2334            .map(|f| {
2335                (
2336                    f.selector.into(),
2337                    f.arguments
2338                        .expect("arguments extraction was requested")
2339                        .into_iter()
2340                        .map(|t| t.sol_type_name().to_string())
2341                        .collect::<Vec<String>>()
2342                        .join(","),
2343                    f.state_mutability
2344                        .expect("state_mutability extraction was requested")
2345                        .as_json_str(),
2346                )
2347            })
2348            .collect())
2349    }
2350
2351    /// Decodes a raw EIP2718 transaction payload
2352    /// Returns details about the typed transaction and ECSDA signature components
2353    ///
2354    /// # Example
2355    ///
2356    /// ```
2357    /// use alloy_network::Ethereum;
2358    /// use cast::SimpleCast as Cast;
2359    ///
2360    /// let tx = "0x02f8f582a86a82058d8459682f008508351050808303fd84948e42f2f4101563bf679975178e880fd87d3efd4e80b884659ac74b00000000000000000000000080f0c1c49891dcfdd40b6e0f960f84e6042bcb6f000000000000000000000000b97ef9ef8734c71904d8002f8b6bc66dd9c48a6e00000000000000000000000000000000000000000000000000000000007ff4e20000000000000000000000000000000000000000000000000000000000000064c001a05d429597befe2835396206781b199122f2e8297327ed4a05483339e7a8b2022aa04c23a7f70fb29dda1b4ee342fb10a625e9b8ddc6a603fb4e170d4f6f37700cb8";
2361    /// let tx_envelope = Cast::decode_raw_transaction::<Ethereum>(&tx)?;
2362    /// # Ok::<(), eyre::Report>(())
2363    pub fn decode_raw_transaction<N: Network<TxEnvelope: SignerRecoverable + Serialize>>(
2364        tx: &str,
2365    ) -> Result<String> {
2366        let tx_hex = hex::decode(tx)?;
2367        let tx: N::TxEnvelope = Decodable2718::decode_2718(&mut tx_hex.as_slice())?;
2368        if let Ok(signer) = tx.recover_signer() {
2369            Ok(serde_json::to_string_pretty(&Recovered::new_unchecked(tx, signer))?)
2370        } else {
2371            Ok(serde_json::to_string_pretty(&tx)?)
2372        }
2373    }
2374}
2375
2376pub(crate) fn strip_0x(s: &str) -> &str {
2377    s.strip_prefix("0x").unwrap_or(s)
2378}
2379
2380fn explorer_client(
2381    chain: Chain,
2382    api_key: Option<String>,
2383    api_url: Option<String>,
2384    explorer_url: Option<String>,
2385) -> Result<Client> {
2386    let mut builder = Client::builder();
2387
2388    let deduced = chain.etherscan_urls();
2389
2390    let explorer_url = explorer_url
2391        .or(deduced.map(|d| d.1.to_string()))
2392        .ok_or_eyre("Please provide the explorer browser URL using `--explorer-url`")?;
2393    builder = builder.with_url(explorer_url)?;
2394
2395    let api_url = api_url
2396        .or(deduced.map(|d| d.0.to_string()))
2397        .ok_or_eyre("Please provide the explorer API URL using `--explorer-api-url`")?;
2398    builder = builder.with_api_url(api_url)?;
2399
2400    if let Some(api_key) = api_key {
2401        builder = builder.with_api_key(api_key);
2402    }
2403
2404    builder.build().map_err(Into::into)
2405}
2406
2407#[cfg(test)]
2408mod tests {
2409    use super::{DynSolValue, SimpleCast as Cast, serialize_value_as_json};
2410    use alloy_primitives::hex;
2411
2412    #[test]
2413    fn simple_selector() {
2414        assert_eq!("0xc2985578", Cast::get_selector("foo()", 0).unwrap().0.as_str())
2415    }
2416
2417    #[test]
2418    fn selector_with_arg() {
2419        assert_eq!("0xbd0d639f", Cast::get_selector("foo(address,uint256)", 0).unwrap().0.as_str())
2420    }
2421
2422    #[test]
2423    fn calldata_uint() {
2424        assert_eq!(
2425            "0xb3de648b0000000000000000000000000000000000000000000000000000000000000001",
2426            Cast::calldata_encode("f(uint256 a)", &["1"]).unwrap().as_str()
2427        );
2428    }
2429
2430    // <https://github.com/foundry-rs/foundry/issues/2681>
2431    #[test]
2432    fn calldata_array() {
2433        assert_eq!(
2434            "0xcde2baba0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000",
2435            Cast::calldata_encode("propose(string[])", &["[\"\"]"]).unwrap().as_str()
2436        );
2437    }
2438
2439    #[test]
2440    fn calldata_bool() {
2441        assert_eq!(
2442            "0x6fae94120000000000000000000000000000000000000000000000000000000000000000",
2443            Cast::calldata_encode("bar(bool)", &["false"]).unwrap().as_str()
2444        );
2445    }
2446
2447    #[test]
2448    fn abi_decode() {
2449        let data = "0x0000000000000000000000000000000000000000000000000000000000000001";
2450        let sig = "balanceOf(address, uint256)(uint256)";
2451        assert_eq!(
2452            "1",
2453            Cast::abi_decode(sig, data, false).unwrap()[0].as_uint().unwrap().0.to_string()
2454        );
2455
2456        let data = "0x0000000000000000000000008dbd1b711dc621e1404633da156fcc779e1c6f3e000000000000000000000000d9f3c9cc99548bf3b44a43e0a2d07399eb918adc000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000";
2457        let sig = "safeTransferFrom(address,address,uint256,uint256,bytes)";
2458        let decoded = Cast::abi_decode(sig, data, true).unwrap();
2459        let decoded = [
2460            decoded[0]
2461                .as_address()
2462                .unwrap()
2463                .to_string()
2464                .strip_prefix("0x")
2465                .unwrap()
2466                .to_owned()
2467                .to_lowercase(),
2468            decoded[1]
2469                .as_address()
2470                .unwrap()
2471                .to_string()
2472                .strip_prefix("0x")
2473                .unwrap()
2474                .to_owned()
2475                .to_lowercase(),
2476            decoded[2].as_uint().unwrap().0.to_string(),
2477            decoded[3].as_uint().unwrap().0.to_string(),
2478            hex::encode(decoded[4].as_bytes().unwrap()),
2479        ]
2480        .to_vec();
2481        assert_eq!(
2482            decoded,
2483            vec![
2484                "8dbd1b711dc621e1404633da156fcc779e1c6f3e",
2485                "d9f3c9cc99548bf3b44a43e0a2d07399eb918adc",
2486                "42",
2487                "1",
2488                ""
2489            ]
2490        );
2491    }
2492
2493    #[test]
2494    fn calldata_decode() {
2495        let data = "0x0000000000000000000000000000000000000000000000000000000000000001";
2496        let sig = "balanceOf(address, uint256)(uint256)";
2497        let decoded =
2498            Cast::calldata_decode(sig, data, false).unwrap()[0].as_uint().unwrap().0.to_string();
2499        assert_eq!(decoded, "1");
2500
2501        // Passing `input = true` will decode the data with the input function signature.
2502        // We exclude the "prefixed" function selector from the data field (the first 4 bytes).
2503        let data = "0xf242432a0000000000000000000000008dbd1b711dc621e1404633da156fcc779e1c6f3e000000000000000000000000d9f3c9cc99548bf3b44a43e0a2d07399eb918adc000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000";
2504        let sig = "safeTransferFrom(address, address, uint256, uint256, bytes)";
2505        let decoded = Cast::calldata_decode(sig, data, true).unwrap();
2506        let decoded = [
2507            decoded[0].as_address().unwrap().to_string().to_lowercase(),
2508            decoded[1].as_address().unwrap().to_string().to_lowercase(),
2509            decoded[2].as_uint().unwrap().0.to_string(),
2510            decoded[3].as_uint().unwrap().0.to_string(),
2511            hex::encode(decoded[4].as_bytes().unwrap()),
2512        ]
2513        .into_iter()
2514        .collect::<Vec<_>>();
2515        assert_eq!(
2516            decoded,
2517            vec![
2518                "0x8dbd1b711dc621e1404633da156fcc779e1c6f3e",
2519                "0xd9f3c9cc99548bf3b44a43e0a2d07399eb918adc",
2520                "42",
2521                "1",
2522                ""
2523            ]
2524        );
2525    }
2526
2527    #[test]
2528    fn calldata_decode_nested_json() {
2529        let calldata = "0xdb5b0ed700000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000006772bf190000000000000000000000000000000000000000000000000000000000020716000000000000000000000000af9d27ffe4d51ed54ac8eec78f2785d7e11e5ab100000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000000000000000000000000000000000000000000404366a6dc4b2f348a85e0066e46f0cc206fca6512e0ed7f17ca7afb88e9a4c27000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000093922dee6e380c28a50c008ab167b7800bb24c2026cd1b22f1c6fb884ceed7400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060f85e59ecad6c1a6be343a945abedb7d5b5bfad7817c4d8cc668da7d391faf700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000093dfbf04395fbec1f1aed4ad0f9d3ba880ff58a60485df5d33f8f5e0fb73188600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000aa334a426ea9e21d5f84eb2d4723ca56b92382b9260ab2b6769b7c23d437b6b512322a25cecc954127e60cf91ef056ac1da25f90b73be81c3ff1872fa48d10c7ef1ccb4087bbeedb54b1417a24abbb76f6cd57010a65bb03c7b6602b1eaf0e32c67c54168232d4edc0bfa1b815b2af2a2d0a5c109d675a4f2de684e51df9abb324ab1b19a81bac80f9ce3a45095f3df3a7cf69ef18fc08e94ac3cbc1c7effeacca68e3bfe5d81e26a659b5";
2530        let sig = "sequenceBatchesValidium((bytes32,bytes32,uint64,bytes32)[],uint64,uint64,address,bytes)";
2531        let decoded = Cast::calldata_decode(sig, calldata, true).unwrap();
2532        let json_value = serialize_value_as_json(DynSolValue::Array(decoded), None).unwrap();
2533        let expected = serde_json::json!([
2534            [
2535                [
2536                    "0x04366a6dc4b2f348a85e0066e46f0cc206fca6512e0ed7f17ca7afb88e9a4c27",
2537                    "0x0000000000000000000000000000000000000000000000000000000000000000",
2538                    0,
2539                    "0x0000000000000000000000000000000000000000000000000000000000000000"
2540                ],
2541                [
2542                    "0x093922dee6e380c28a50c008ab167b7800bb24c2026cd1b22f1c6fb884ceed74",
2543                    "0x0000000000000000000000000000000000000000000000000000000000000000",
2544                    0,
2545                    "0x0000000000000000000000000000000000000000000000000000000000000000"
2546                ],
2547                [
2548                    "0x60f85e59ecad6c1a6be343a945abedb7d5b5bfad7817c4d8cc668da7d391faf7",
2549                    "0x0000000000000000000000000000000000000000000000000000000000000000",
2550                    0,
2551                    "0x0000000000000000000000000000000000000000000000000000000000000000"
2552                ],
2553                [
2554                    "0x93dfbf04395fbec1f1aed4ad0f9d3ba880ff58a60485df5d33f8f5e0fb731886",
2555                    "0x0000000000000000000000000000000000000000000000000000000000000000",
2556                    0,
2557                    "0x0000000000000000000000000000000000000000000000000000000000000000"
2558                ]
2559            ],
2560            1735573273,
2561            132886,
2562            "0xAF9d27ffe4d51eD54AC8eEc78f2785D7E11E5ab1",
2563            "0x334a426ea9e21d5f84eb2d4723ca56b92382b9260ab2b6769b7c23d437b6b512322a25cecc954127e60cf91ef056ac1da25f90b73be81c3ff1872fa48d10c7ef1ccb4087bbeedb54b1417a24abbb76f6cd57010a65bb03c7b6602b1eaf0e32c67c54168232d4edc0bfa1b815b2af2a2d0a5c109d675a4f2de684e51df9abb324ab1b19a81bac80f9ce3a45095f3df3a7cf69ef18fc08e94ac3cbc1c7effeacca68e3bfe5d81e26a659b5"
2564        ]);
2565        assert_eq!(json_value, expected);
2566    }
2567
2568    #[test]
2569    fn concat_hex() {
2570        assert_eq!(Cast::concat_hex(["0x00", "0x01"]), "0x0001");
2571        assert_eq!(Cast::concat_hex(["1", "2"]), "0x12");
2572    }
2573
2574    #[test]
2575    fn from_rlp() {
2576        let rlp = "0xf8b1a02b5df5f0757397573e8ff34a8b987b21680357de1f6c8d10273aa528a851eaca8080a02838ac1d2d2721ba883169179b48480b2ba4f43d70fcf806956746bd9e83f90380a0e46fff283b0ab96a32a7cc375cecc3ed7b6303a43d64e0a12eceb0bc6bd8754980a01d818c1c414c665a9c9a0e0c0ef1ef87cacb380b8c1f6223cb2a68a4b2d023f5808080a0236e8f61ecde6abfebc6c529441f782f62469d8a2cc47b7aace2c136bd3b1ff08080808080";
2577        let item = Cast::from_rlp(rlp, false).unwrap();
2578        assert_eq!(
2579            item,
2580            r#"["0x2b5df5f0757397573e8ff34a8b987b21680357de1f6c8d10273aa528a851eaca","0x","0x","0x2838ac1d2d2721ba883169179b48480b2ba4f43d70fcf806956746bd9e83f903","0x","0xe46fff283b0ab96a32a7cc375cecc3ed7b6303a43d64e0a12eceb0bc6bd87549","0x","0x1d818c1c414c665a9c9a0e0c0ef1ef87cacb380b8c1f6223cb2a68a4b2d023f5","0x","0x","0x","0x236e8f61ecde6abfebc6c529441f782f62469d8a2cc47b7aace2c136bd3b1ff0","0x","0x","0x","0x","0x"]"#
2581        )
2582    }
2583
2584    #[test]
2585    fn disassemble_incomplete_sequence() {
2586        let incomplete = &hex!("60"); // PUSH1
2587        let disassembled = Cast::disassemble(incomplete).unwrap();
2588        assert_eq!(disassembled, "00000000: PUSH1\n");
2589
2590        let complete = &hex!("6000"); // PUSH1 0x00
2591        let disassembled = Cast::disassemble(complete).unwrap();
2592        assert_eq!(disassembled, "00000000: PUSH1 0x00\n");
2593
2594        let incomplete = &hex!("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // PUSH32 with 31 bytes
2595        let disassembled = Cast::disassemble(incomplete).unwrap();
2596        assert_eq!(disassembled, "00000000: PUSH32\n");
2597
2598        let complete = &hex!("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // PUSH32 with 32 bytes
2599        let disassembled = Cast::disassemble(complete).unwrap();
2600        assert_eq!(
2601            disassembled,
2602            "00000000: PUSH32 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n"
2603        );
2604    }
2605}