Skip to main content
Sui’s gas mechanism is designed to be transparent, predictable, and sustainable. It separates computation costs from storage costs and implements a storage rebate system for long-term sustainability.

Gas Model Overview

Sui uses a two-dimensional gas model:

Computation Gas

Pay for CPU and network resources used during execution

Storage Gas

Pay for on-chain storage of data

Gas Cost Formula

pub struct GasCostSummary {
    /// Cost of computation/execution
    pub computation_cost: u64,
    /// Storage cost, it's the sum of all storage cost for all objects created or mutated
    pub storage_cost: u64,
    /// The amount of storage cost refunded to the user for all objects deleted or mutated
    pub storage_rebate: u64,
    /// The fee for the rebate. The portion of the storage rebate kept by the system
    pub non_refundable_storage_fee: u64,
}
Total cost:
Total = computation_cost + storage_cost - storage_rebate

Computation Gas

Charged for:
  • Move bytecode execution
  • Native function calls
  • Object reads and writes
  • Event emissions
  • Transaction processing overhead

Gas Units

Typical operations:
pub const TEST_ONLY_GAS_UNIT_FOR_TRANSFER: u64 = 10_000;
pub const TEST_ONLY_GAS_UNIT_FOR_OBJECT_BASICS: u64 = 50_000;
pub const TEST_ONLY_GAS_UNIT_FOR_PUBLISH: u64 = 70_000;
pub const TEST_ONLY_GAS_UNIT_FOR_STAKING: u64 = 50_000;
pub const TEST_ONLY_GAS_UNIT_FOR_GENERIC: u64 = 50_000;
pub const TEST_ONLY_GAS_UNIT_FOR_SPLIT_COIN: u64 = 10_000;

Storage Gas

Storage Pricing

Storage cost is calculated as:
storage_cost = object_size_bytes × storage_price_per_byte
The storage price per byte is set by the protocol and adjusts based on network conditions.

Storage Rebate

When you delete or modify an object:
public(package) fun advance_epoch(
    self: &mut StorageFund,
    storage_charges: Balance<SUI>,
    storage_fund_reinvestment: Balance<SUI>,
    leftover_staking_rewards: Balance<SUI>,
    storage_rebate_amount: u64,
    non_refundable_storage_fee_amount: u64,
): Balance<SUI> {
    // Process epoch storage economics
    self.non_refundable_balance.join(storage_fund_reinvestment);
    self.non_refundable_balance.join(leftover_staking_rewards);
    self.total_object_storage_rebates.join(storage_charges);

    // Split out non-refundable portion
    let non_refundable_storage_fee = self
        .total_object_storage_rebates
        .split(non_refundable_storage_fee_amount);
    
    self.non_refundable_balance.join(non_refundable_storage_fee);

    // Return refundable portion
    let storage_rebate = self.total_object_storage_rebates.split(storage_rebate_amount);
    storage_rebate
}
The storage rebate is not a full refund. A small percentage (non-refundable fee) is kept by the system to fund long-term storage.

Gas Smearing

Gas costs are “smeared” to prevent MEV opportunities:
pub trait SuiGasStatusAPI {
    fn bucketize_computation(&mut self, aborted: Option<bool>) -> Result<(), ExecutionError>;
    // ...
}
This rounds gas costs to prevent micro-optimizations that could create unfair advantages.

Reference Gas Price (RGP)

Validators vote on the reference gas price each epoch:
pub const DEFAULT_VALIDATOR_GAS_PRICE: u64 = 1000;
Transactions must have gas_price >= RGP:
pub fn new(
    gas_budget: u64,
    gas_price: u64,
    reference_gas_price: u64,
    config: &ProtocolConfig,
) -> SuiResult<Self> {
    if gas_price < reference_gas_price {
        return Err(UserInputError::GasPriceUnderRGP {
            gas_price,
            reference_gas_price,
        }
        .into());
    }
    // ...
}

Gas Budget

Every transaction specifies a maximum gas budget:
const tx = new Transaction();
tx.setGasBudget(10_000_000); // 10M gas units

Budget Enforcement

  • Transaction aborts if gas budget is exceeded
  • Gas used up to abort point is still charged
  • Prevents runaway computation

Gas Optimizations

Coin-Specific Optimizations

/// Return the `value: u64` field of a `Coin<T>` type.
/// Useful for reading the coin without deserializing the object into a Move value
pub fn get_coin_value_unsafe(&self) -> u64 {
    debug_assert!(self.type_.is_coin());
    // 32 bytes for object ID, 8 for balance
    debug_assert!(self.contents.len() == 40);
    u64::from_le_bytes(<[u8; 8]>::try_from(&self.contents[ID_END_INDEX..]).unwrap())
}

/// Update the `value: u64` field of a `Coin<T>` type.
pub fn set_coin_value_unsafe(&mut self, value: u64) {
    debug_assert!(self.type_.is_coin());
    self.contents.splice(ID_END_INDEX.., value.to_le_bytes());
}
Coins have fixed 40-byte layout enabling direct balance access without full deserialization.

Storage Read Charges

pub trait SuiGasStatusAPI {
    fn charge_storage_read(&mut self, size: usize) -> Result<(), ExecutionError>;
    fn charge_publish_package(&mut self, size: usize) -> Result<(), ExecutionError>;
}
Reading objects incurs a small gas cost based on size.

Economic Incentives

For Users

Recover storage rebates by cleaning up:
public fun cleanup(temp: TempObject) {
    let TempObject { id, .. } = temp;
    id.delete(); // Get storage rebate
}
// Bad: Large object
public struct BadNFT has key {
    id: UID,
    full_image: vector<u8>, // 10 MB!
}

// Good: Lean object
public struct GoodNFT has key {
    id: UID,
    image_url: String, // Just URL
}
// One transaction with multiple operations is cheaper
const tx = new Transaction();
recipients.forEach(r => {
    const [coin] = tx.splitCoins(tx.gas, [amount]);
    tx.transferObjects([coin], r);
});

For Validators

Validators earn:
  • Gas fees from transactions
  • Storage fees from object creation
  • Staking rewards

Gas Pricing

Gas pricing details

Storage Fund

Storage economics

SUI Token

Learn about SUI

Build docs developers (and LLMs) love