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