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