arbos/features/
mod.rs

1use std::marker::PhantomData;
2
3use alloy_primitives::U256;
4use arb_storage::{StorageBackedBigUint, StorageBackend, SystemStateBackend};
5
6mod error;
7pub use error::FeaturesError;
8
9const INCREASED_CALLDATA: usize = 0;
10
11/// Feature flags backed by a storage BigUint used as a bitmask.
12pub struct Features<'a, D> {
13    features: StorageBackedBigUint,
14    _phantom: PhantomData<&'a mut revm::database::State<D>>,
15}
16
17pub fn open_features<'a, D>(base_key: alloy_primitives::B256, offset: u64) -> Features<'a, D> {
18    Features {
19        features: StorageBackedBigUint::new(base_key, offset),
20        _phantom: PhantomData,
21    }
22}
23
24impl<D> Features<'_, D> {
25    /// Sets the calldata-pricing feature bit, returning the resulting bitmask
26    /// so callers can price the write by value.
27    pub fn set_calldata_price_increase<B: StorageBackend>(
28        &self,
29        backend: &mut B,
30        enabled: bool,
31    ) -> Result<U256, FeaturesError> {
32        self.set_bit(backend, INCREASED_CALLDATA, enabled)
33    }
34
35    pub fn is_increased_calldata_price_enabled<B: SystemStateBackend>(
36        &self,
37        backend: &mut B,
38    ) -> Result<bool, FeaturesError> {
39        self.is_set(backend, INCREASED_CALLDATA)
40    }
41
42    fn set_bit<B: StorageBackend>(
43        &self,
44        backend: &mut B,
45        index: usize,
46        enabled: bool,
47    ) -> Result<U256, FeaturesError> {
48        let mut val = self.features.get(backend)?;
49        if enabled {
50            val |= U256::from(1) << index;
51        } else {
52            val &= !(U256::from(1) << index);
53        }
54        self.features.set(backend, val)?;
55        Ok(val)
56    }
57
58    fn is_set<B: SystemStateBackend>(
59        &self,
60        backend: &mut B,
61        index: usize,
62    ) -> Result<bool, FeaturesError> {
63        let val = self.features.get(backend)?;
64        Ok((val >> index) & U256::from(1) != U256::ZERO)
65    }
66}