cast/
lib.rs

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