cast/cmd/
estimate.rs
1use crate::tx::{CastTxBuilder, SenderKind};
2use alloy_ens::NameOrAddress;
3use alloy_primitives::U256;
4use alloy_provider::Provider;
5use alloy_rpc_types::BlockId;
6use clap::Parser;
7use eyre::Result;
8use foundry_cli::{
9 opts::{EthereumOpts, TransactionOpts},
10 utils::{self, parse_ether_value, LoadConfig},
11};
12use std::str::FromStr;
13
14#[derive(Debug, Parser)]
16pub struct EstimateArgs {
17 #[arg(value_parser = NameOrAddress::from_str)]
19 to: Option<NameOrAddress>,
20
21 sig: Option<String>,
23
24 args: Vec<String>,
26
27 #[arg(long, short = 'B')]
31 block: Option<BlockId>,
32
33 #[arg(long)]
37 cost: bool,
38
39 #[command(subcommand)]
40 command: Option<EstimateSubcommands>,
41
42 #[command(flatten)]
43 tx: TransactionOpts,
44
45 #[command(flatten)]
46 eth: EthereumOpts,
47}
48
49#[derive(Debug, Parser)]
50pub enum EstimateSubcommands {
51 #[command(name = "--create")]
53 Create {
54 code: String,
56
57 sig: Option<String>,
59
60 args: Vec<String>,
62
63 #[arg(long, value_parser = parse_ether_value)]
69 value: Option<U256>,
70 },
71}
72
73impl EstimateArgs {
74 pub async fn run(self) -> Result<()> {
75 let Self { to, mut sig, mut args, mut tx, block, cost, eth, command } = self;
76
77 let config = eth.load_config()?;
78 let provider = utils::get_provider(&config)?;
79 let sender = SenderKind::from_wallet_opts(eth.wallet).await?;
80
81 let code = if let Some(EstimateSubcommands::Create {
82 code,
83 sig: create_sig,
84 args: create_args,
85 value,
86 }) = command
87 {
88 sig = create_sig;
89 args = create_args;
90 if let Some(value) = value {
91 tx.value = Some(value);
92 }
93 Some(code)
94 } else {
95 None
96 };
97
98 let (tx, _) = CastTxBuilder::new(&provider, tx, &config)
99 .await?
100 .with_to(to)
101 .await?
102 .with_code_sig_and_args(code, sig, args)
103 .await?
104 .build_raw(sender)
105 .await?;
106
107 let gas = provider.estimate_gas(tx).block(block.unwrap_or_default()).await?;
108 if cost {
109 let gas_price_wei = provider.get_gas_price().await?;
110 let cost = gas_price_wei * gas as u128;
111 let cost_eth = cost as f64 / 1e18;
112 sh_println!("{cost_eth}")?;
113 } else {
114 sh_println!("{gas}")?;
115 }
116 Ok(())
117 }
118}
119
120#[cfg(test)]
121mod tests {
122 use super::*;
123
124 #[test]
125 fn parse_estimate_value() {
126 let args: EstimateArgs = EstimateArgs::parse_from(["foundry-cli", "--value", "100"]);
127 assert!(args.tx.value.is_some());
128 }
129}