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