1mod calc;
4mod constants;
5
6pub use calc::*;
7pub use constants::*;
8
9#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
11#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
12pub struct Gas {
13 limit: u64,
15 remaining: u64,
17 remaining_nomem: u64,
19 memory: u64,
21 refunded: i64,
23}
24
25impl Gas {
26 #[inline]
28 pub const fn new(limit: u64) -> Self {
29 Self {
30 limit,
31 remaining: limit,
32 remaining_nomem: limit,
33 memory: 0,
34 refunded: 0,
35 }
36 }
37
38 #[inline]
40 pub const fn limit(&self) -> u64 {
41 self.limit
42 }
43
44 #[inline]
46 pub const fn memory(&self) -> u64 {
47 self.memory
48 }
49
50 #[inline]
52 pub const fn refunded(&self) -> i64 {
53 self.refunded
54 }
55
56 #[inline]
58 pub const fn spent(&self) -> u64 {
59 self.limit - self.remaining
60 }
61
62 #[doc(hidden)]
63 #[inline]
64 #[deprecated(note = "use `spent` instead")]
65 pub const fn spend(&self) -> u64 {
66 self.spent()
67 }
68
69 #[inline]
71 pub const fn remaining(&self) -> u64 {
72 self.remaining
73 }
74
75 #[inline]
77 pub fn erase_cost(&mut self, returned: u64) {
78 self.remaining_nomem += returned;
79 self.remaining += returned;
80 }
81
82 #[inline]
87 pub fn record_refund(&mut self, refund: i64) {
88 self.refunded += refund;
89 }
90
91 #[inline]
97 pub fn set_final_refund(&mut self, is_london: bool) {
98 let max_refund_quotient = if is_london { 5 } else { 2 };
99 self.refunded = (self.refunded() as u64).min(self.spent() / max_refund_quotient) as i64;
100 }
101
102 #[inline]
104 pub fn set_refund(&mut self, refund: i64) {
105 self.refunded = refund;
106 }
107
108 #[inline]
112 pub fn record_cost(&mut self, cost: u64) -> bool {
113 let (remaining, overflow) = self.remaining.overflowing_sub(cost);
114 if overflow {
115 return false;
116 }
117
118 self.remaining_nomem -= cost;
119 self.remaining = remaining;
120 true
121 }
122
123 #[inline]
127 pub fn record_memory(&mut self, gas_memory: u64) -> bool {
128 if gas_memory > self.memory {
129 let (remaining, overflow) = self.remaining_nomem.overflowing_sub(gas_memory);
130 if overflow {
131 return false;
132 }
133 self.memory = gas_memory;
134 self.remaining = remaining;
135 }
136 true
137 }
138}