Gas Pricing and Transaction Fees
The IOTA gas pricing mechanism determines how transaction fees are computed and plays a central role in ensuring efficient network operation. It serves two primary objectives:
- Delivering low, predictable transaction fees.
- Preventing denial-of-service (DoS) attacks.
To achieve these goals, every IOTA transaction pays fees for computation, required to execute the transaction, and storage, required to persist data on-chain. Hence, transaction fees decompose into:
net gas fees = Computation fee + Storage fee − Storage rebate
where:
- Computation fee =
computation_units * gas_price - Storage fee (deposit) =
storage_units * storage_price - Storage rebate is the amount refunded when previously stored data is deleted.
Equivalently, the total gas fees are:
gas_fees = computation_units * gas_price + storage_units * storage_price - storage_rebate
This formulation separates the cost of execution from the cost of storage, while ensuring that users only pay for the net storage they consume over time.
Computation Fees
The computation fee captures the cost of executing a transaction:
computation_fee = computation_units * gas_price
Computation Units
Different IOTA transactions require varying amounts of computational time for processing and execution. IOTA translates these varying operational loads into transaction fees by measuring each transaction in terms of computation units. In general, more complex transactions require more computation units.
Importantly, though, the IOTA computation gas schedule is built with a bucketing/step approach. Two reasonably similar transactions translate into the exact same amount of computation units if they are in the same bucket, whereas two relatively different transactions translate into different amounts of computation units if they fall in separate buckets. The smallest bucket maps into 1,000 computation units, meaning that all transactions that fall into the smallest bucket cost 1,000 computation units. The step between buckets is 1,000 and the largest bucket maps into 5,000,000 computation units; if a transaction requires more computation units, it aborts.
Using bucketing accomplishes two important goals:
- Frees users from optimizing their smart contracts to deliver marginal gains in gas costs via "gas golfing" — instead, they can focus on step-function improvements in their products and services.
- Gives users the freedom to adjust per-instruction gas costs and experiment with new gas metering schemes without creating significant development disruption. This can happen frequently, so it is important that they do not rely on per-instruction gas costs remaining stable over time.
Gas Price
The gas price is specified by the user and must be at least a protocol-defined baseline:
gas_price = reference_gas_price + tip
- The reference gas price is defined by the protocol (currently set to 1,000 NANOS) and acts as a baseline for transaction inclusion. All transactions must pay at least this amount, and fees up to this level are burned.
- The tip is an optional additional fee paid by users to prioritize their transactions. Any amount above the reference gas price is transferred to validators as part of their rewards.
During normal network conditions, most transactions use the reference gas price with no tip, ensuring predictable and stable fees. However, during periods of congestion, users can request an estimated minimum gas price for successful execution through a transaction dry run. This estimation is computed using a predictive gas pricing algorithm, which helps users determine an appropriate tip. The algorithm leverages historical congestion data and dynamically adjusts weights for shared objects accessed by transactions using an online gradient descent method.
Storage Fees
The storage fee captures the cost of storing data on-chain:
storage_fee = storage_units * storage_price
Storage Units
Similarly, IOTA transactions vary depending on the amount of new data written into on-chain storage. The variable storage units capture these differences by mapping the number of bytes held in storage into storage units. The current IOTA schedule is linear and maps each byte into 100 storage units. So, for example, a transaction that stores 25 bytes costs 2,500 storage units, while a transaction that stores 75 bytes costs 7,500 units.
Importantly, in IOTA's storage model, users pay storage deposit fees for storing data in perpetuity but can also get a full rebate on previously stored data if that data is deleted. Hence, the amount of storage fees that users pay is 100% rebateable. This storage deposit mechanism incentivizes users to minimize the storage burden they place on all nodes by reducing their storage requirements and cleaning up unused objects.
Storage Price
- The storage price is fixed and shared across all transactions. It is set through governance proposals and updated infrequently.
- Storage fees act as a deposit: users pay upfront for storing data, but receive a 100% rebate when that data is deleted.
The storage price is set exogenously with the goal of targeting the real-world cost of data storage. Over time, governance can adjust this value to reflect changes in hardware costs and the market value of the IOTA token.
This design ensures that users internalize the long-term cost of storage while retaining strong incentives to minimize and clean up on-chain data.
Gas Budgets
Every transaction on IOTA must include a gas budget, which sets the maximum amount the user is willing to pay for computation and storage.
The gas budget can be set between 1,000,000 NANOS (0.001 IOTA) and 50,000,000,000 NANOS (50 IOTA). This range protects the network against spam and denial-of-service attacks.
Transactions are successfully executed if:
gas_budget >= max{computation_fees, net_gas_fees}
If the gas budget does not satisfy this condition, the transaction fails and a portion of the gas budget is charged. The charging rules are as follows:
- If the gas budget is insufficient to cover both computation fees and storage fees, then the entire gas budget is charged.
- If the gas budget is sufficient for computation fees but not enough for net gas fees, then a portion of the gas budget is charged corresponding to:
- the computation fees, and
- the fees associated with mutating the transaction's input objects.
Ultimately, a successful transaction requires the end user to pay the transaction's net gas fees.
However, since it is difficult to perfectly forecast computation time before the transaction is processed, the gas budget must also cover at least the computation fees in case the transaction aborts.
Additionally, in some cases — especially when there are high storage rebates leading to negative net storage fees — the total gas fees the user pays (net_gas_fees) might be lower than the computation fees.
As mentioned previously, the storage rebate is 100% of the originally paid storage fees. This mechanism ensures that users are reimbursed for previously stored data that is deleted, which encourages efficient use of on-chain storage.
Examples
The following table provides examples of gas accounting on the IOTA network.
- In the first two and last two rows, computation units are the same because transactions fall within the same bucket.
- The last two transactions are more complex than the first two, so they fall into a higher computation bucket.
- In the last transaction, the storage rebate is large enough to fully offset the transaction gas fees, effectively giving the user a positive net balance.
These examples highlight the importance of the gas budget:
- The minimum gas budget is the smallest amount a transaction can specify to execute successfully.
- When there is a storage rebate, the minimum gas budget is often larger than the net gas fees a user ultimately pays.
- This is particularly evident in the last example, where the user receives a positive amount back after executing the transaction, because the minimum gas budget must still cover the computation fees.
| Reference Gas Price | Computation Units | Storage Price | Storage Units | Storage Rebate | Minimum Gas Budget | Net Gas Fees | |
|---|---|---|---|---|---|---|---|
| Simple transaction storing 10 bytes | 1,000 NANOS | 1,000 | 75 NANOS | 1,000 | 0 NANOS | 1,075,000 NANOS | 1,075,000 NANOS |
| Simple transaction storing 10 bytes and deleting data | 500 NANOS | 1,000 | 75 NANOS | 1,000 | 100,000 NANOS | 500,000 NANOS | 475,000 NANOS |
| Complex transaction storing 120 bytes | 1,000 NANOS | 5,000 | 200 NANOS | 12,000 | 0 NANOS | 7,400,000 NANOS | 7,400,000 NANOS |
| Complex transaction storing 120 bytes and deleting data | 500 NANOS | 5,000 | 200 NANOS | 12,000 | 5,000,000 NANOS | 2,500,000 NANOS | -100,000 NANOS |
Gas Price Prediction During Dry Run
When you execute a dry run or dev inspect transaction, the IOTA network provides a suggested_gas_price in the response.
This value helps users estimate an appropriate gas price for transactions that interact with shared objects, particularly during periods of network congestion.
If your transaction touches popular shared objects (e.g., a DEX pool), the suggested gas price reflects the current level of congestion on those objects and helps reduce the probability that the transaction will be cancelled. For transactions that only use owned objects, no additional tip is required.
The network maintains a congestion tracker that monitors shared-object access patterns across checkpoints. For each mutable shared object, the tracker computes a hotness value that reflects how congested that object is based on recent transaction history. This hotness value is updated using an online gradient-descent-based mechanism driven by checkpoint statistics (e.g., cancelled transactions, successfully scheduled transactions).
During a dry run, the suggested gas price is calculated as:
suggested_gas_price = reference_gas_price + max_hotness
where max_hotness is the highest hotness value among all mutable shared objects accessed by the transaction.
If the transaction does not access any tracked shared objects, the suggested gas price falls back to the current reference_gas_price.
By using the suggested_gas_price from a dry-run response, users can adapt their gas price to current network conditions.
This reduces the risk of underbidding during congestion while avoiding unnecessary overpayment during periods of low activity.