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}
28
29/// A burner for internal ArbOS system operations.
30///
31/// Has no concept of "gas left" — only tracks total gas burned.
32/// Panics if `gas_left()` is called.
33#[derive(Debug, Clone)]
34pub struct SystemBurner {
35    gas_burnt: MultiGas,
36    tracing_info: Option<TracingInfo>,
37    read_only: bool,
38}
39
40impl SystemBurner {
41    pub fn new(tracing_info: Option<TracingInfo>, read_only: bool) -> Self {
42        Self {
43            gas_burnt: MultiGas::zero(),
44            tracing_info,
45            read_only,
46        }
47    }
48}
49
50impl Burner for SystemBurner {
51    fn burn(&mut self, kind: ResourceKind, amount: u64) -> Result<(), BurnError> {
52        self.gas_burnt.saturating_increment_into(kind, amount);
53        Ok(())
54    }
55
56    fn burn_multi_gas(&mut self, amount: MultiGas) -> Result<(), BurnError> {
57        self.gas_burnt.saturating_add_into(amount);
58        Ok(())
59    }
60
61    fn burned(&self) -> u64 {
62        self.gas_burnt.total()
63    }
64
65    fn gas_left(&self) -> u64 {
66        unreachable!("SystemBurner has no notion of gas left")
67    }
68
69    fn burn_out(&mut self) -> Result<(), BurnError> {
70        Err(BurnError::OutOfGas)
71    }
72
73    fn restrict(&mut self, _err: BurnError) {
74        // SystemBurner ignores restrictions
75    }
76
77    fn handle_error(&self, err: BurnError) -> Result<(), BurnError> {
78        Err(err)
79    }
80
81    fn read_only(&self) -> bool {
82        self.read_only
83    }
84
85    fn tracing_info(&self) -> Option<&TracingInfo> {
86        self.tracing_info.as_ref()
87    }
88}