fuel_vm/interpreter/
gas.rs1use super::Interpreter;
2use crate::{
3 constraints::reg_key::*,
4 error::SimpleResult,
5 prelude::{
6 Bug,
7 BugVariant,
8 },
9};
10
11use fuel_asm::{
12 PanicReason,
13 RegId,
14};
15use fuel_tx::DependentCost;
16use fuel_types::Word;
17
18#[cfg(test)]
19mod tests;
20
21impl<M, S, Tx, Ecal, V> Interpreter<M, S, Tx, Ecal, V> {
22 pub fn remaining_gas(&self) -> Word {
24 self.registers[RegId::GGAS]
25 }
26
27 pub(crate) fn set_gas(&mut self, gas: Word) {
31 self.registers[RegId::GGAS] = gas;
32 self.registers[RegId::CGAS] = gas;
33 }
34
35 pub(crate) fn dependent_gas_charge(
36 &mut self,
37 gas_cost: DependentCost,
38 arg: Word,
39 ) -> SimpleResult<()> {
40 let SystemRegisters { ggas, cgas, .. } = split_registers(&mut self.registers).0;
41 dependent_gas_charge(cgas, ggas, gas_cost, arg)
42 }
43
44 pub(crate) fn dependent_gas_charge_without_base(
45 &mut self,
46 gas_cost: DependentCost,
47 arg: Word,
48 ) -> SimpleResult<()> {
49 let SystemRegisters { ggas, cgas, .. } = split_registers(&mut self.registers).0;
50 dependent_gas_charge_without_base(cgas, ggas, gas_cost, arg)
51 }
52
53 pub fn gas_charge(&mut self, gas: Word) -> SimpleResult<()> {
55 let SystemRegisters { ggas, cgas, .. } = split_registers(&mut self.registers).0;
56
57 gas_charge(cgas, ggas, gas)
58 }
59}
60
61pub(crate) fn dependent_gas_charge_without_base(
62 mut cgas: RegMut<CGAS>,
63 ggas: RegMut<GGAS>,
64 gas_cost: DependentCost,
65 arg: Word,
66) -> SimpleResult<()> {
67 let cost = gas_cost.resolve_without_base(arg);
68 gas_charge(cgas.as_mut(), ggas, cost)
69}
70
71pub(crate) fn dependent_gas_charge(
72 mut cgas: RegMut<CGAS>,
73 ggas: RegMut<GGAS>,
74 gas_cost: DependentCost,
75 arg: Word,
76) -> SimpleResult<()> {
77 let cost = gas_cost.resolve(arg);
78 gas_charge(cgas.as_mut(), ggas, cost)
79}
80
81pub(crate) fn gas_charge(
82 mut cgas: RegMut<CGAS>,
83 mut ggas: RegMut<GGAS>,
84 gas: Word,
85) -> SimpleResult<()> {
86 if *cgas > *ggas {
87 Err(Bug::new(BugVariant::GlobalGasLessThanContext).into())
88 } else if gas > *cgas {
89 *ggas = (*ggas)
90 .checked_sub(*cgas)
91 .ok_or_else(|| Bug::new(BugVariant::GlobalGasUnderflow))?;
92 *cgas = 0;
93
94 Err(PanicReason::OutOfGas.into())
95 } else {
96 *cgas = (*cgas)
97 .checked_sub(gas)
98 .ok_or_else(|| Bug::new(BugVariant::ContextGasUnderflow))?;
99 *ggas = (*ggas)
100 .checked_sub(gas)
101 .ok_or_else(|| Bug::new(BugVariant::GlobalGasUnderflow))?;
102
103 Ok(())
104 }
105}