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