cast/
lib.rs

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