Skip to content

Commit

Permalink
Merge pull request #3608 from dfinity/gas-cost-revise
Browse files Browse the repository at this point in the history
revise: gas cost page
  • Loading branch information
jessiemongeon1 authored Oct 17, 2024
2 parents 3813d56 + fb8d7c2 commit efa9590
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 104 deletions.
135 changes: 70 additions & 65 deletions docs/developer-docs/gas-cost.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,37 +10,27 @@ import { MarkdownChipRow } from "/src/components/Chip/MarkdownChipRow";

## Overview

Canisters pay for consumed resources by burning cycles. These resources include storage, messaging, and execution. To obtain cycles, ICP tokens can be converted into cycles.

- [Replication](#replication)
- [Local development](#local-development)
- [Mainnet development](#mainnet-development)
- [Units and fiat value](#units-and-fiat-value)
- [The ICP reverse gas model](#the-reverse-gas-model)
- [Canister calls](#canister-operations-and-resources)
- [Canister creation](#canister-creation)
- [Messaging](#messaging)
- [Execution](#execution)
- [Storage](#storage)
- [Special features](#special-features)
- [Who is responsible for paying cycles?](#who-is-responsible-for-paying-cycles)
- [Cycles price breakdown](#cycles-price-breakdown)
- [Further readings](#further-readings)
Canister smart contracts pay for consumed resources (storage, messaging, execution, and special features) by burning **cycles**. Developers can obtain cycles by converting ICP tokens into cycles using [`dfx`](/docs/current/developer-docs/defi/cycles/converting_icp_tokens_into_cycles).

## Replication
For pricing estimations, you can use the [pricing calculator](/docs/current/developer-docs/cost-estimations-and-examples).

This page will provide details about how costs are calculated.

Replication refers to the number of times a canister is replicated, which is dependant on the canister's subnet.
## The reverse gas model

### Local development
ICP charges each canister smart contract for the resources that it consumes. It's the developer's responsibility to load each of their canisters with adequate cycles to pay for these resources. This cost model is known as ICP's **reverse gas model**.

When a canister is deployed to a local development environment, the canister is deployed to a single node. Cycles charged to locally deployed canisters have a cost that is 1/13th the cost when deployed to a 13-node subnet. In local development environments, cycles can be fabricated using dfx.
The reverse gas model allows dapp developers to provide their users a smooth experience, since end users don't need to obtain tokens, configure wallets, or sign and approve every transaction they perform when interacting with a dapp on ICP.

### Mainnet development
You can learn more about the [reverse gas model](https://internetcomputer.org/capabilities/reverse-gas).

On a 13-node subnet, the canister is running on 13 nodes and is replicated 13 times. On a 34-node subnet, the canister is running on 34 nodes and is replicated 34 times. The cost of resources on a 13-node subnet is different than the cost of resources on a 34-node subnet.
One downside of the ICP reverse gas model is that it requires prerequisite steps and ongoing maintenance for developers. Canisters must have their cycles balances maintained and regularly topped up as they continuously use resources. The canister will be removed from the network if it runs out of cycles.

If you intend to deploy canisters on high-replication subnets, your canister should be prepared for an increase in cycles prices. It is recommended to attach more cycles to a call than the current price for a high-replication subnet.
Learn how to query a [canister's cycles balance](/docs/current/developer-docs/smart-contracts/topping-up/topping-up-canister#checking-the-cycles-balance-of-a-canister).

Learn how to [top up a canister](/docs/current/developer-docs/smart-contracts/topping-up/topping-up-canister).

A [freezing threshold](/docs/current/developer-docs/smart-contracts/maintain/settings/#freezing-threshold) can be set that pauses a canister's executions if the cycles amount is expected to fall below a certain amount. There are several community tools that have been developed to automate managing a canister's cycles, such as [CycleOps](https://cycleops.dev/).

## Units and fiat value

Expand All @@ -56,42 +46,33 @@ The following table shows units of cycles and the respective fiat values:
| k | Thousand | 1_000 | 0.000000001 | 0.000000001336610 |


## The reverse gas model

ICP charges the canister smart contract for the resources it consumes. This allows developers to provide a smoother user experience, as end users are free from tedious tasks such as signing and approving every transaction they perform. This cost model is known as ICP's 'reverse gas model'.

:::info
ICP does not use the term 'gas', it uses the term 'cycles'.
:::

You can learn more about the [reverse gas model](/capabilities/reverse-gas).
## Replication

One downside of the ICP reverse gas model is that it requires prerequisite steps and ongoing maintenance for developers. Canisters must have their cycles balances maintained and regularly topped up as they continuously use resources. The canister will be removed from the network if it runs out of cycles. However, a [freezing threshold](/docs/current/tutorials/developer-journey/level-1/1.6-managing-canisters#setting-the-canisters-freezing-threshold) can be set that pauses a canister's executions if the cycles amount is expected to fall below a certain amount. There are several community tools that have been developed to automate managing a canister's cycles, such as [CycleOps](https://cycleops.dev/).
When a canister is deployed to a subnet, it is automatically replicated on every node within that subnet. The amount of cycles that a canister is charged will vary based on the amount of times the canister is replicated:

Learn how to query a [canister's cycles balance](/docs/current/tutorials/developer-journey/level-1/1.6-managing-canisters#checking-the-cycles-balance-of-a-canister).
- Canisters deployed **locally** are deployed on a single node and therefore are replicated once. Cycles charged to locally deployed canisters have a cost that is `1 / 13` the cost when deployed to a 13-node subnet. In local development environments, cycles can be fabricated using `dfx`.

Learn how to [top up a canister](/docs/current/tutorials/developer-journey/level-1/1.6-managing-canisters#topping-up-a-canisters-cycles-balance).
- Canisters deployed to a **13-node subnet** are replicated 13 times. Cycle cost amounts are based on a 13-node subnet, i.e., there is no calculation needed to determine the cost based on the subnet's replication factor.

- Canisters deployed to a **34-node subnet** are replicated 34 times. If you intend to deploy canisters on high-replication subnets (greater than 13 nodes), your canister should be prepared for an increase in cycles prices. Calls made to high-replication subnets will also require more cycles. Cycles costs on 34-node subnets can be calculated as `cost / 13 * 34`.

## Canister operations and resources
## Cost details: canister operations and resources

Canisters pay for consumed resources and performed operations using features such as HTTPS outcalls, ECDSA signing, and the Bitcoin integration API. At a high level this can be visualized using the following diagram:
Canisters are charged for the resources they consume and any operations they perform using features such as HTTPS outcalls, ECDSA signing, and the Bitcoin integration API. At a high level this can be visualized using the following diagram:

![Canister calls overview](./_attachments/transaction-overview.svg)

Each type of canister operation and resource has a different cycles cost associated with it. The canister responsible for paying the cycles varies based on the type of operation.

The following subsections explain the pricing for the different operation and resource types for a 13 node subnet. The same operations and resources cost linearly more on subnets with more nodes.
The following subsections explain the pricing for the different operation and resource types for a canister deployed on a 13 node subnet. The same operations and resources cost linearly more on subnets with more nodes.

### Canister creation

Canister creation costs 100B cycles or approximately $0.13 USD. Canisters can be created by users or other canisters.

### Messaging

A canister can receive messages from users and other canisters. In canister-to-canister messages, the sending canister pays message transmission costs. In user-to-canister messages, the receiving canister covers the message transmission costs (see [reverse gas model](#the-icp-reverse-gas-model)). User-to-canister messages are also referred to as ingress messages.

The message transmission cost consists of a fixed baseline fee and per-byte-fee charged for each byte of the message: `base-fee` + `per-byte-fee` * `size-in-bytes`.
A canister can receive messages from users and other canisters. In canister-to-canister messages, the sending canister pays the message transmission costs. In user-to-canister messages, the receiving canister covers the message transmission costs. User-to-canister messages are also referred to as **ingress messages**.

The current fees are:

Expand All @@ -101,19 +82,15 @@ The current fees are:
| Canister-to-canister | 260K | 1K |
| User-to-canister (ingress) | 1.2M | 2K |

[View the cost calculation formula for more information about how costs are calculated](#cost-calculation-formulas).

:::info
Note that query messages are currently free, but this may change in the future.
:::

### Execution

To handle an incoming message or task such as a timer or heartbeat, the canister executes the function specified in the message. The execution cost consists of a fixed execution fee and per-instruction fee (on application subnets (13 nodes), 10 instructions cost 4 cycles) that is charged for each executed WebAssembly instruction:

`base-fee` + `per-instruction-fee` * `number-of-instructions`

The current values of fees are `base-fee` = 590K cycles (or $0.0000007885999 USD), `per-instruction-fee` = 0.4 cycles (or $0.0053 USD for 1B instructions).
### Execution and compute allocation

### Compute allocation
To handle an incoming message or task such as a timer or heartbeat, the canister executes the function specified in the message.

By default, canisters are scheduled for execution in a "best-effort" manner. Canisters that require guaranteed execution can get a share of compute capacity by setting `compute_allocation` in their canister settings. Compute allocation is expressed in percents and denotes the percentage of an execution core reserved for the canister.

Expand All @@ -131,11 +108,15 @@ The allocatable compute capacity is 299% **per subnet**. Compute allocation is g

Compute is a finite resource and is priced as such. The current fee for 1% compute allocation per second is 10M cycles (or $0.0000133661 USD). Therefore, a canister that requests 100% compute allocation would be charged 10M * 100 cycles per second.

[View the cost calculation formula for more information about how costs are calculated](#cost-calculation-formulas).

### Storage
Canisters pay for storage consumed by their [Wasm memory](/docs/current/developer-docs/smart-contracts/maintain/storage#heap-memory) and [stable memory](/docs/current/developer-docs/smart-contracts/maintain/storage#stable-memory) per time. Storing 1 GiB for 1 second costs 127k cycles, which amounts to ~4T cycles (or $5.35 USD) for storing 1 GiB for 1 year.

Canisters can reserve storage on a subnet through the `memory_allocation` setting. However, the canister will be charged as if the entire amount of allocated storage is being used.

#### Resource reservation mechanism

In order to encourage long-term usage and discourage spiky usage patterns, the Internet Computer uses a *resource reservation mechanism* that was adopted by the community in [NNS proposal 12604](https://dashboard.internetcomputer.org/proposal/126094).

When a canister allocates new storage bytes, the system sets aside some number of cycles from the main balance of the canister that are used to cover future payments for the newly allocated bytes. The reserved cycles are not transferable, and the number of reserved cycles depends on how full the subnet is. It may cover days, months, or even years of payments.
Expand All @@ -147,7 +128,7 @@ The operations that allocate new bytes are:
- Increasing the `memory_allocation` in canister settings.

These operations reserve some cycles by moving them from the main balance of the canister to the reserved cycles balance.
The amount of reserved cycles depends on how many bytes are allocated and on the current subnet usage:
The amount of reserved cycles depends on how many bytes are allocated and on the current subnet usage.

- If subnet usage is below `450GiB`, then the amount of reserved cycles per allocated byte is `0`.
- If subnet usage is above `450GiB`, then the amount of reserved cycles per allocated byte grows linearly depending on the subnet usage, from `0` to `10` years worth of storage payments at the subnet capacity (which is currently `750GiB`).
Expand All @@ -159,7 +140,7 @@ Such opted-out canisters would not be able to allocate if the subnet usage is ab

Special features have different costs since they use special infrastructure to provide the feature's functionality. These special features include:

- **HTTPS outcalls**: The cost for an HTTPS outcall is calculated using the formula `(3_000_000 + 60_000 * n) * n` for the base fee and `400 * n` each request byte and `800 * n` for each response byte, where `n` is the number of nodes in the subnet. These costs are included in the chart found below.
- **HTTPS outcalls**: These costs are included in the chart found below. [View the cost calculation formula for more information about how this cost is calculated](#cost-calculation-formulas).

- **Bitcoin API**: Pricing for the **Bitcoin API** is available in the [Bitcoin API documentation](/docs/current/references/bitcoin-how-it-works).

Expand All @@ -171,14 +152,16 @@ Special features have different costs since they use special infrastructure to p

Canisters are responsible for paying cycles for their own canister creation, compute resources, storage resources, and execution resources. For certain canister calls, the canister responsible for paying the cycles may vary.

- Ingress messages: The receiving canister is responsible for paying.
- Inter-canister calls: Each canister pays for the calls that it sends.
- Local processing: Each canister pays for local processing.
- Child canisters: Responsible for paying for themselves.
- **Ingress messages**: The receiving canister is responsible for paying.
- **Inter-canister calls**: Each canister pays for the calls that it sends.
- **Local processing**: Each canister pays for local processing.
- **Child canisters**: Responsible for paying for themselves.

## Cycles price breakdown

The table below details the cost of compute, storage transmissions and canister calls. The ICP [pricing calculator](https://3d5wy-5aaaa-aaaag-qkhsq-cai.icp0.io/) can be used to get a comprehensive estimate of what a dapp may cost based on the number of canisters, calls, and features used.
The table below details the cost of compute, storage transmissions and canister calls.

You can use the [pricing calculator](https://3d5wy-5aaaa-aaaag-qkhsq-cai.icp0.io/) to estimate the cost for your dapp.

| Canister transmission | Description | Who is responsible for paying the cycles fee? | 13-node subnets cycles cost | 13-node subnets USD cost | 34-node subnets | 34-node subnets USD cost |
| ----------------- | ------------------------------- | -------------------------------------------------- | ----------------------------------------------- | --------------------------------------- | ------------------------------------- | --------------------------- | ------------------------------------ |
Expand All @@ -204,19 +187,41 @@ The following table shows the calculated storage cost per GiB for a 30-day month
|----------------------|------------------------------------|-----------------------------|-----------------------------|
| GiB Storage Per Month | For storing a GiB of data per month | $0.446150495 | $1.70 |

## Cost calculation formulas

A detailed, mathematical example of how the cost of running a canister on a 13-node subnet is computed can be found [on the wiki](https://wiki.internetcomputer.org/wiki/Comparing_Canister_Cycles_vs_Performance_Counter).

Specific mathematical formulas used for different types of costs can be found below for reference.

### Message transmissions

A fixed baseline fee and per-byte-fee charged for each byte of the message: `base-fee` + `per-byte-fee` * `size-in-bytes`.

### Execution

The execution cost consists of a fixed execution fee and per-instruction fee (on application subnets (13 nodes), 10 instructions cost 4 cycles) that is charged for each executed WebAssembly instruction:

`base-fee` + `per-instruction-fee` * `number-of-instructions`

The current values of fees are `base-fee` = 590K cycles (or $0.0000007885999 USD), `per-instruction-fee` = 0.4 cycles (or $0.0053 USD for 1B instructions).

### HTTPS outcalls

The cost for an HTTPS outcall is calculated using the formula `(3_000_000 + 60_000 * n) * n` for the base fee and `400 * n` each request byte and `800 * n` for each response byte, where `n` is the number of nodes in the subnet.

## Errors related to cycles

Common errors related to cycles include:

- [Insufficient cycles in memory grow](/docs/current/references/execution-errors#insufficient-cycles-in-memory-grow)
- [Reserved cycles limit exceeded in memory grow](/docs/current/references/execution-errors#reserved-cycles-limit-exceeded-in-memory-grow)
- [Insufficient cycles in message memory grow](/docs/current/references/execution-errors#insufficient-cycles-in-message-memory-grow)
- [Insufficient cycles in compute allocation](/docs/current/references/execution-errors#insufficient-cycles-in-compute-allocation)
- [Insufficient cycles in memory allocation](/docs/current/references/execution-errors#insufficient-cycles-in-memory-allocation)
- [Insufficient cycles in memory grow](/docs/current/references/execution-errors#insufficient-cycles-in-memory-grow-1)
- [Reserved cycles limit exceeded in memory allocation](/docs/current/references/execution-errors#reserved-cycles-limit-exceeded-in-memory-allocation)
- [Install code not enough cycles](/docs/current/references/execution-errors#install-code-not-enough-cycles)
- [Create canister not enough cycles](/docs/current/references/execution-errors#create-canister-not-enough-cycles)
- [Insufficient cycles in memory grow](/docs/current/references/execution-errors#insufficient-cycles-in-memory-grow).
- [Reserved cycles limit exceeded in memory grow](/docs/current/references/execution-errors#reserved-cycles-limit-exceeded-in-memory-grow).
- [Insufficient cycles in message memory grow](/docs/current/references/execution-errors#insufficient-cycles-in-message-memory-grow).
- [Insufficient cycles in compute allocation](/docs/current/references/execution-errors#insufficient-cycles-in-compute-allocation).
- [Insufficient cycles in memory allocation](/docs/current/references/execution-errors#insufficient-cycles-in-memory-allocation).
- [Insufficient cycles in memory grow](/docs/current/references/execution-errors#insufficient-cycles-in-memory-grow-1).
- [Reserved cycles limit exceeded in memory allocation](/docs/current/references/execution-errors#reserved-cycles-limit-exceeded-in-memory-allocation).
- [Install code not enough cycles](/docs/current/references/execution-errors#install-code-not-enough-cycles).
- [Create canister not enough cycles](/docs/current/references/execution-errors#create-canister-not-enough-cycles).

## Further readings

Expand Down
Loading

0 comments on commit efa9590

Please sign in to comment.