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