arbos/burn/
burner.rs

1use arb_primitives::multigas::{MultiGas, ResourceKind};
2
3use crate::util::TracingInfo;
4
5/// Gas burning abstraction for ArbOS operations.
6///
7/// Tracks multi-dimensional gas usage during ArbOS state modifications.
8/// `SystemBurner` is used for internal ArbOS operations that don't have
9/// a notion of remaining gas.
10pub trait Burner {
11    fn burn(&mut self, kind: ResourceKind, amount: u64) -> Result<(), BurnError>;
12    fn burn_multi_gas(&mut self, amount: MultiGas) -> Result<(), BurnError>;
13    fn burned(&self) -> u64;
14    fn gas_left(&self) -> u64;
15    fn burn_out(&mut self) -> Result<(), BurnError>;
16    fn restrict(&mut self, err: BurnError);
17    fn handle_error(&self, err: BurnError) -> Result<(), BurnError>;
18    fn read_only(&self) -> bool;
19    fn tracing_info(&self) -> Option<&TracingInfo>;
20}
21
22/// Error from a burn operation.
23#[derive(Debug, Clone, thiserror::Error)]
24pub enum BurnError {
25    #[error("out of gas")]
26    OutOfGas,
27    #[error("restricted: {0}")]
28    Restricted(String),
29    #[error("{0}")]
30    Other(String),
31}
32
33/// A burner for internal ArbOS system operations.
34///
35/// Has no concept of "gas left" — only tracks total gas burned.
36/// Panics if `gas_left()` is called.
37#[derive(Debug, Clone)]
38pub struct SystemBurner {
39    gas_burnt: MultiGas,
40    tracing_info: Option<TracingInfo>,
41    read_only: bool,
42}
43
44impl SystemBurner {
45    pub fn new(tracing_info: Option<TracingInfo>, read_only: bool) -> Self {
46        Self {
47            gas_burnt: MultiGas::zero(),
48            tracing_info,
49            read_only,
50        }
51    }
52}
53
54impl Burner for SystemBurner {
55    fn burn(&mut self, kind: ResourceKind, amount: u64) -> Result<(), BurnError> {
56        self.gas_burnt.saturating_increment_into(kind, amount);
57        Ok(())
58    }
59
60    fn burn_multi_gas(&mut self, amount: MultiGas) -> Result<(), BurnError> {
61        self.gas_burnt.saturating_add_into(amount);
62        Ok(())
63    }
64
65    fn burned(&self) -> u64 {
66        self.gas_burnt.total()
67    }
68
69    fn gas_left(&self) -> u64 {
70        unreachable!("SystemBurner has no notion of gas left")
71    }
72
73    fn burn_out(&mut self) -> Result<(), BurnError> {
74        Err(BurnError::OutOfGas)
75    }
76
77    fn restrict(&mut self, _err: BurnError) {
78        // SystemBurner ignores restrictions
79    }
80
81    fn handle_error(&self, err: BurnError) -> Result<(), BurnError> {
82        Err(err)
83    }
84
85    fn read_only(&self) -> bool {
86        self.read_only
87    }
88
89    fn tracing_info(&self) -> Option<&TracingInfo> {
90        self.tracing_info.as_ref()
91    }
92}