iota_sdk_types/
gas.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2025 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5/// Summary of gas charges.
6///
7/// Storage is charged independently of computation.
8/// There are 3 parts to the storage charges:
9/// `storage_cost`: it is the charge of storage at the time the transaction is
10/// executed.                 The cost of storage is the number of bytes of the
11/// objects being mutated                 multiplied by a variable storage cost
12/// per byte `storage_rebate`: this is the amount a user gets back when
13/// manipulating an object.                   The `storage_rebate` is the
14/// `storage_cost` for an object minus fees. `non_refundable_storage_fee`: not
15/// all the value of the object storage cost is                               
16/// given back to user and there is a small fraction that                       
17/// is kept by the system. This value tracks that charge.
18///
19/// When looking at a gas cost summary the amount charged to the user is
20/// `computation_cost + storage_cost - storage_rebate`
21/// and that is the amount that is deducted from the gas coins.
22/// `non_refundable_storage_fee` is collected from the objects being
23/// mutated/deleted and it is tracked by the system in storage funds.
24///
25/// Objects deleted, including the older versions of objects mutated, have the
26/// storage field on the objects added up to a pool of "potential rebate". This
27/// rebate then is reduced by the "nonrefundable rate" such that:
28/// `potential_rebate(storage cost of deleted/mutated objects) =
29/// storage_rebate + non_refundable_storage_fee`
30///
31/// # BCS
32///
33/// The BCS serialized form for this type is defined by the following ABNF:
34///
35/// ```text
36/// gas-cost-summary = u64 ; computation-cost
37///                    u64 ; storage-cost
38///                    u64 ; storage-rebate
39///                    u64 ; non-refundable-storage-fee
40/// ```
41#[derive(Clone, Debug, Default, PartialEq, Eq)]
42#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
43#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
44#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
45pub struct GasCostSummary {
46    /// Cost of computation/execution
47    #[cfg_attr(feature = "serde", serde(with = "crate::_serde::ReadableDisplay"))]
48    #[cfg_attr(feature = "schemars", schemars(with = "crate::_schemars::U64"))]
49    pub computation_cost: u64,
50    /// The burned component of the computation/execution costs
51    #[cfg_attr(feature = "serde", serde(with = "crate::_serde::ReadableDisplay"))]
52    #[cfg_attr(feature = "schemars", schemars(with = "crate::_schemars::U64"))]
53    pub computation_cost_burned: u64,
54    /// Storage cost, it's the sum of all storage cost for all objects created
55    /// or mutated.
56    #[cfg_attr(feature = "serde", serde(with = "crate::_serde::ReadableDisplay"))]
57    #[cfg_attr(feature = "schemars", schemars(with = "crate::_schemars::U64"))]
58    pub storage_cost: u64,
59    /// The amount of storage cost refunded to the user for all objects deleted
60    /// or mutated in the transaction.
61    #[cfg_attr(feature = "serde", serde(with = "crate::_serde::ReadableDisplay"))]
62    #[cfg_attr(feature = "schemars", schemars(with = "crate::_schemars::U64"))]
63    pub storage_rebate: u64,
64    /// The fee for the rebate. The portion of the storage rebate kept by the
65    /// system.
66    #[cfg_attr(feature = "serde", serde(with = "crate::_serde::ReadableDisplay"))]
67    #[cfg_attr(feature = "schemars", schemars(with = "crate::_schemars::U64"))]
68    pub non_refundable_storage_fee: u64,
69}
70
71impl GasCostSummary {
72    /// Create a new gas cost summary.
73    ///
74    /// # Arguments
75    /// * `computation_cost` - Cost of computation cost/execution.
76    /// * `storage_cost` - Storage cost, it's the sum of all storage cost for
77    ///   all objects created or mutated.
78    /// * `storage_rebate` - The amount of storage cost refunded to the user for
79    ///   all objects deleted or mutated in the transaction.
80    /// * `non_refundable_storage_fee` - The fee for the rebate. The portion of
81    ///   the storage rebate kept by the system.
82    pub fn new(
83        computation_cost: u64,
84        computation_cost_burned: u64,
85        storage_cost: u64,
86        storage_rebate: u64,
87        non_refundable_storage_fee: u64,
88    ) -> GasCostSummary {
89        GasCostSummary {
90            computation_cost,
91            computation_cost_burned,
92            storage_cost,
93            storage_rebate,
94            non_refundable_storage_fee,
95        }
96    }
97
98    /// The total gas used, which is the sum of computation and storage costs.
99    pub fn gas_used(&self) -> u64 {
100        self.computation_cost + self.storage_cost
101    }
102
103    /// The net gas usage, which is the total gas used minus the storage rebate.
104    /// A positive number means used gas; negative number means refund.
105    pub fn net_gas_usage(&self) -> i64 {
106        self.gas_used() as i64 - self.storage_rebate as i64
107    }
108}
109
110impl std::fmt::Display for GasCostSummary {
111    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
112        write!(f, "computation_cost: {}, ", self.computation_cost)?;
113        write!(f, "storage_cost: {}, ", self.storage_cost)?;
114        write!(f, "storage_rebate: {}, ", self.storage_rebate)?;
115        write!(
116            f,
117            "non_refundable_storage_fee: {}",
118            self.non_refundable_storage_fee
119        )
120    }
121}
122
123#[cfg(test)]
124mod tests {
125    #[cfg(target_arch = "wasm32")]
126    use wasm_bindgen_test::wasm_bindgen_test as test;
127
128    use super::*;
129
130    #[test]
131    #[cfg(feature = "serde")]
132    fn formats() {
133        let actual = GasCostSummary {
134            computation_cost: 42,
135            computation_cost_burned: 24,
136            storage_cost: u64::MAX,
137            storage_rebate: 0,
138            non_refundable_storage_fee: 9,
139        };
140
141        println!("{}", serde_json::to_string(&actual).unwrap());
142        println!("{:?}", bcs::to_bytes(&actual).unwrap());
143    }
144}