anvil_zksync_core/node/
fee_model.rs

1use crate::node::fork::ForkDetails;
2use anvil_zksync_config::constants::{
3    DEFAULT_ESTIMATE_GAS_PRICE_SCALE_FACTOR, DEFAULT_ESTIMATE_GAS_SCALE_FACTOR,
4    DEFAULT_FAIR_PUBDATA_PRICE, DEFAULT_L1_GAS_PRICE, DEFAULT_L2_GAS_PRICE,
5};
6use anvil_zksync_config::BaseTokenConfig;
7use zksync_multivm::utils::derive_base_fee_and_gas_per_pubdata;
8use zksync_multivm::VmVersion;
9use zksync_types::fee_model::{
10    BaseTokenConversionRatio, BatchFeeInput, FeeModelConfigV2, FeeParams, FeeParamsV2,
11};
12
13#[derive(Debug, Clone)]
14pub struct TestNodeFeeInputProvider {
15    /// L1 Gas Price Scale Factor for gas estimation.
16    pub estimate_gas_price_scale_factor: f64,
17    /// The factor by which to scale the gasLimit.
18    pub estimate_gas_scale_factor: f32,
19
20    fee_params: FeeParamsV2,
21    forced_base_fee: Option<u64>,
22}
23
24// TODO: Derive PartialEq for `FeeParamsV2` in upstream
25impl PartialEq for TestNodeFeeInputProvider {
26    fn eq(&self, other: &Self) -> bool {
27        fn eq_config(a: FeeModelConfigV2, b: FeeModelConfigV2) -> bool {
28            a.minimal_l2_gas_price == b.minimal_l2_gas_price
29                && a.compute_overhead_part == b.compute_overhead_part
30                && a.pubdata_overhead_part == b.pubdata_overhead_part
31                && a.batch_overhead_l1_gas == b.batch_overhead_l1_gas
32                && a.max_gas_per_batch == b.max_gas_per_batch
33                && a.max_pubdata_per_batch == b.max_pubdata_per_batch
34        }
35
36        self.estimate_gas_price_scale_factor == other.estimate_gas_price_scale_factor
37            && self.estimate_gas_scale_factor == other.estimate_gas_scale_factor
38            && self.fee_params.l1_gas_price() == other.fee_params.l1_gas_price()
39            && self.fee_params.l1_pubdata_price() == other.fee_params.l1_pubdata_price()
40            && eq_config(self.fee_params.config(), other.fee_params.config())
41    }
42}
43
44impl TestNodeFeeInputProvider {
45    pub fn from_fork(fork: Option<&ForkDetails>, base_token_config: &BaseTokenConfig) -> Self {
46        if let Some(fork) = fork {
47            TestNodeFeeInputProvider::from_fee_params_and_estimate_scale_factors(
48                fork.fee_params,
49                fork.estimate_gas_price_scale_factor,
50                fork.estimate_gas_scale_factor,
51            )
52        } else {
53            let ratio = base_token_config.ratio;
54            let l1_gas_price = ((DEFAULT_L1_GAS_PRICE as u128)
55                * u128::from(ratio.denominator.get())
56                / u128::from(ratio.numerator.get()))
57            .try_into()
58            .expect("L1 gas price exceeded 2^64; base token ratio is too large");
59            let fair_pubdata_price = ((DEFAULT_FAIR_PUBDATA_PRICE as u128)
60                * u128::from(ratio.denominator.get())
61                / u128::from(ratio.numerator.get()))
62            .try_into()
63            .expect("pubdata gas price exceeded 2^64; base token ratio is too large");
64            Self {
65                estimate_gas_price_scale_factor: DEFAULT_ESTIMATE_GAS_PRICE_SCALE_FACTOR,
66                estimate_gas_scale_factor: DEFAULT_ESTIMATE_GAS_SCALE_FACTOR,
67                fee_params: FeeParamsV2::new(
68                    FeeModelConfigV2 {
69                        minimal_l2_gas_price: DEFAULT_L2_GAS_PRICE,
70                        compute_overhead_part: 0.0,
71                        pubdata_overhead_part: 1.0,
72                        batch_overhead_l1_gas: 800000,
73                        max_gas_per_batch: 200000000,
74                        max_pubdata_per_batch: 500000,
75                    },
76                    l1_gas_price,
77                    fair_pubdata_price,
78                    ratio,
79                ),
80                forced_base_fee: None,
81            }
82        }
83    }
84
85    pub fn from_fee_params_and_estimate_scale_factors(
86        fee_params: FeeParams,
87        estimate_gas_price_scale_factor: f64,
88        estimate_gas_scale_factor: f32,
89    ) -> Self {
90        match fee_params {
91            FeeParams::V1(_) => todo!(),
92            FeeParams::V2(fee_params) => Self {
93                estimate_gas_price_scale_factor,
94                estimate_gas_scale_factor,
95                fee_params,
96                forced_base_fee: None,
97            },
98        }
99    }
100
101    pub fn from_estimate_scale_factors(
102        estimate_gas_price_scale_factor: f64,
103        estimate_gas_scale_factor: f32,
104    ) -> Self {
105        Self {
106            estimate_gas_price_scale_factor,
107            estimate_gas_scale_factor,
108            ..Default::default()
109        }
110    }
111
112    pub fn get_fee_model_config(&self) -> FeeModelConfigV2 {
113        self.fee_params.config()
114    }
115
116    fn get_params(&self) -> FeeParams {
117        // TODO: consider using old fee model for the olds blocks, when forking
118        FeeParams::V2(self.fee_params)
119    }
120
121    fn enforce_base_fee(&self, mut fee_input: BatchFeeInput) -> BatchFeeInput {
122        if let Some(base_fee) = self.forced_base_fee {
123            let mut pubdata_fee_input = fee_input.into_pubdata_independent();
124            pubdata_fee_input.fair_l2_gas_price = base_fee;
125            fee_input = BatchFeeInput::PubdataIndependent(pubdata_fee_input);
126        }
127        fee_input
128    }
129
130    pub(crate) fn get_batch_fee_input(&self) -> BatchFeeInput {
131        let fee_input = self.get_params().scale(1.0, 1.0);
132        self.enforce_base_fee(fee_input)
133    }
134
135    pub(crate) fn get_batch_fee_input_scaled(&self) -> BatchFeeInput {
136        let scale_factor = self.estimate_gas_price_scale_factor;
137        let fee_input = self.get_params().scale(scale_factor, scale_factor);
138        self.enforce_base_fee(fee_input)
139    }
140
141    pub fn gas_price(&self) -> u64 {
142        let (base_fee, _) = derive_base_fee_and_gas_per_pubdata(
143            self.get_batch_fee_input_scaled(),
144            VmVersion::latest(),
145        );
146        base_fee
147    }
148
149    pub fn fair_pubdata_price(&self) -> u64 {
150        self.get_batch_fee_input_scaled().fair_pubdata_price()
151    }
152
153    pub fn set_base_fee(&mut self, base_fee: u64) {
154        self.forced_base_fee = Some(base_fee);
155    }
156}
157
158impl Default for TestNodeFeeInputProvider {
159    fn default() -> Self {
160        Self {
161            estimate_gas_price_scale_factor: DEFAULT_ESTIMATE_GAS_PRICE_SCALE_FACTOR,
162            estimate_gas_scale_factor: DEFAULT_ESTIMATE_GAS_SCALE_FACTOR,
163            fee_params: FeeParamsV2::new(
164                FeeModelConfigV2 {
165                    minimal_l2_gas_price: DEFAULT_L2_GAS_PRICE,
166                    compute_overhead_part: 0.0,
167                    pubdata_overhead_part: 1.0,
168                    batch_overhead_l1_gas: 800000,
169                    max_gas_per_batch: 200000000,
170                    max_pubdata_per_batch: 500000,
171                },
172                DEFAULT_L1_GAS_PRICE,
173                DEFAULT_FAIR_PUBDATA_PRICE,
174                BaseTokenConversionRatio::default(),
175            ),
176            forced_base_fee: None,
177        }
178    }
179}