1use alloy_consensus::BlockHeader;
4use alloy_network::{BlockResponse, Ethereum, Network, eip2718::Encodable2718};
5use alloy_provider::Provider;
6use alloy_rpc_types::BlockId;
7use clap::Parser;
8use eyre::Result;
9use foundry_cli::{opts::RpcOpts, utils::LoadConfig};
10use foundry_common::provider::ProviderBuilder;
11use foundry_config::Config;
12use foundry_evm_networks::NetworkVariant;
13
14#[cfg(feature = "base")]
15use base_common_network::Base;
16
17#[cfg(feature = "optimism")]
18use op_alloy_network::Optimism;
19
20#[derive(Debug, Parser)]
22pub struct DAEstimateArgs {
23 pub block: BlockId,
25 #[command(flatten)]
26 pub rpc: RpcOpts,
27 #[arg(long, short, num_args = 1, value_name = "NETWORK")]
29 network: Option<NetworkVariant>,
30}
31
32impl DAEstimateArgs {
33 pub async fn run(self) -> Result<()> {
34 let Self { block, rpc, network } = self;
35 let config = rpc.load_config()?;
36 let network = match network {
37 Some(n) => n,
38 None => super::resolve_transaction_network(&config, false).await?,
39 };
40 match network {
41 #[cfg(feature = "base")]
42 NetworkVariant::Base => da_estimate::<Base>(&config, block).await,
43 #[cfg(feature = "optimism")]
44 NetworkVariant::Optimism => da_estimate::<Optimism>(&config, block).await,
45 NetworkVariant::Ethereum => da_estimate::<Ethereum>(&config, block).await,
46 other => eyre::bail!(
47 "DA estimation is not supported for {other:?}: EIP-4844 blob transactions are not available on this network"
48 ),
49 }
50 }
51}
52
53async fn da_estimate<N: Network>(config: &Config, block_id: BlockId) -> Result<()> {
54 let provider = ProviderBuilder::<N>::from_config(config)?.build()?;
55 let block =
56 provider.get_block(block_id).full().await?.ok_or_else(|| eyre::eyre!("Block not found"))?;
57
58 let block_number = block.header().number();
59 let tx_count = block.transactions().len();
60 let da_estimate = block
61 .transactions()
62 .txns()
63 .map(|tx| op_alloy_flz::tx_estimated_size_fjord(&tx.as_ref().encoded_2718()))
64 .sum::<u64>();
65 sh_status!(
66 "Estimated data availability size for block {block_number} with {tx_count} transactions:"
67 )?;
68 sh_println!("{da_estimate}")?;
69 Ok(())
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75
76 #[tokio::test]
77 async fn rejects_networks_without_blob_transactions() {
78 let args = DAEstimateArgs {
79 block: BlockId::latest(),
80 rpc: RpcOpts::default(),
81 network: Some(NetworkVariant::Tempo),
82 };
83 let err = args.run().await.unwrap_err().to_string();
84 assert!(err.contains("Tempo"), "{err}");
85 assert!(err.contains("EIP-4844"), "{err}");
86 }
87}