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