Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion protocol/accounts-contracts/access-keys.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,11 @@ When a transaction is signed with a gas key:
- Any **attached NEAR** (deposits, transfers) is still paid from the **account's main balance**
- **Gas refunds** for unspent gas return to the **gas key's balance**, so the key sustains itself between top-ups, while balance refunds go to the account

If the gas key's balance cannot cover a transaction's gas, the transaction is rejected. If the gas is covered but the account cannot pay the attached deposit at execution time, the transaction fails **and the burned gas is still charged** to the gas key.
If the gas key's balance cannot cover a transaction's gas, the transaction is rejected. If the gas is covered but the account cannot pay the attached deposit at execution time, the transaction fails and **the gas burned to process it is still charged** to the gas key. The gas that was attached to the receipt is refunded.

<Note>
Gas is [bought at a price that can be higher than the price it burns at](/protocol/transactions/gas#buying-vs-burning-gas), so a gas key has to hold more than its transactions finally cost. The difference comes back to the key as a refund, but it has to be on the key upfront.
</Note>

### Using Nonce Lanes

Expand Down Expand Up @@ -172,6 +176,8 @@ The `allowance` field defines how much NEAR the key can spend on gas fees:
- If set to a specific amount and fully consumed → the key becomes **unusable** and no new transactions can be signed
- If set to `0` or omitted → **unlimited** allowance (the key has no gas budget restriction)

The allowance is charged at the [buy price](/protocol/transactions/gas#buying-vs-burning-gas) and credited back when the gas refund arrives, so a key needs more allowance than the final transaction cost.

<Warning>
If an account has only function-call keys and the allowance runs out, the account is permanently locked from initiating any transaction. Either use unlimited allowance (`0`) or ensure the account is topped up with NEAR before the allowance is exhausted.
</Warning>
Expand Down
4 changes: 4 additions & 0 deletions protocol/storage/storage-staking.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ Storage staking is priced in an amount set by the network, which is set to **1E1

NEAR's JSON RPC API provides [a way to query this initial setting](/api/rpc/protocol#genesis-config) as well as a [a way to query the live config / recent blocks](/api/rpc/protocol#protocol-config).

<Note>
An account can occupy up to `770` bytes without staking anything. That allowance is paid for once, with the fixed `0.007Ⓝ` charged when [creating the account](/protocol/transactions/gas#creating-an-account).
</Note>

## Example cost breakdown

Let's walk through an example.
Expand Down
69 changes: 47 additions & 22 deletions protocol/transactions/gas.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ On every transaction the NEAR network charges a tiny fee known as **gas**. This
1. **Prevent** bad actors from **spamming** the network with useless transactions
2. **Burn** a minuscule fraction of the **token supply** on each transaction
3. **Incentivize developers** by giving contracts 30% of the gas they burn while executing
4. Implement a **wall time** by capping transactions to `300Tgas` (~`300ms` of compute time)
4. Implement a **wall time** by capping how much gas each chunk can burn to `1000Tgas` (~`1000ms` of compute time)

Gas in NEAR is computed on [**gas units**](/protocol/transactions/gas#gas-units) and charged using `$NEAR` tokens based on the network's [**gas price**](/protocol/transactions/gas#gas-price).

Expand All @@ -33,7 +33,9 @@ Every action in NEAR costs a fixed amount of **gas units**, meaning that the sam

Gas units were engineered in such a way that they can be translated into compute resources, where `1Tgas` gets you approx. `1ms` of compute time.

Transactions can use a maximum of `300Tgas`, meaning they should be processed in less than `300ms`, allowing the network to produce a new block approximately **every second**.
Each chunk can burn at most `1000Tgas`, i.e. about `1000ms` of compute, which is what allows the network to produce a new block approximately **every second**.

A single transaction can also attach at most `1000Tgas`. It may spend that gas in one receipt or spread it over the receipts it spawns across several blocks.

<Tip>
Gas units encapsulate not only compute/CPU time but also bandwidth/network time and storage/IO time
Expand All @@ -55,17 +57,32 @@ Right now, 1 Tgas costs: <GasPrice /> Ⓝ

</Accordion>

### Buying vs. Burning Gas

Gas is **bought** at one price and **burned** at another. There's `min_gas_purchase_price = 0.001Ⓝ per Tgas`.

- **Buy price**: `max(current_gas_price, min_gas_purchase_price)`. This is what is deducted from your account upfront for the gas attached to the transaction
- **Burn price**: `min(buy_price, current_gas_price)` - This is what the gas actually costs while executing. The gas price at the moment of execution, but never higher than the buy price.

You buy gas at a price that can be higher than the price it burns at, and **the difference is always refunded to you**. The cost of a transaction is therefore the same as if there were a single price - you just need the larger amount in your account at the moment you send it.

<Tip>
At the minimum gas price (`0.0001Ⓝ` per `Tgas`), buying `100Tgas` deducts `0.1Ⓝ` from your balance. If the transaction burns `50Tgas`, you get `0.095Ⓝ` back: `0.05Ⓝ` for the gas you didn't use, and `0.045Ⓝ` for the price difference on the gas you did. You paid `0.005Ⓝ`, exactly what those `50Tgas` are worth at the gas price.
</Tip>

The point of buying above the burn price is that it leaves the protocol a refund it can charge from **after** it has seen what a transaction actually did. That is how [creating an account](#creating-an-account) is priced.

### Cost for Common Actions

Knowing that actions have a fixed cost in gas units, we can calculate the cost of common operations at the minimum gas price of `1Tgas = 0.0001Ⓝ`.

| Action | TGas | Fee (Ⓝ) |
|------------------------------|----------------|----------|
| Create Account | 0.42 | 0.000042 |
| Create Account*** | 7.92 | 0.00707 |
| Transfer NEAR | 0.45 | 0.000045 |
| Add Full Access Key | 0.42 | 0.000042 |
| Delete Key | 0.41 | 0.000041 |
| Function Call* | ≤ 300 | ≤ 0.03 |
| Function Call* | ≤ 1000 | ≤ 0.1 |
| Deploying a `16`kb contract | 2.65 | 0.000265 |
| Deploying a `X`kb contract** | 0.58 + 0.13`X` | |

Expand All @@ -81,6 +98,11 @@ The cost of calling a function will depend on how complex the function is, but w
Note that this covers the gas cost of uploading and writing bytes to storage, but does **not** cover the cost of holding them in storage (which is `1Ⓝ ~ 100kb`).
</Tip>

<Tip>
**Creating an Account\*\*\***
Most of this fee is not gas: creating an account costs a fixed `0.007Ⓝ` that pays for the state the account permanently occupies. See [below](#creating-an-account).
</Tip>

<Accordion title="Where do these numbers come from?">

NEAR is [configured](https://github.com/near/nearcore/blob/master/core/primitives/res/runtime_configs/parameters.yaml) with base costs. An example:
Expand Down Expand Up @@ -113,54 +135,57 @@ The appropriate amount for creating this receipt is also immediately deducted fr

The "transfer" action won't be finalized until the next block. At this point, the `execution` amount for each of these actions will be deducted from your account.

Although gas prices can change between the time of purchase and time of execution, the gas price per transaction is fixed since protocol version 78.
Gas prices can change between the time of purchase and the time of execution, but a transaction is not affected by that. The `execution` part is bought at the [buy price](#buying-vs-burning-gas) and burned at `gas_price`, with the difference refunded, so what you end up paying is:

```text
(
transfer_cost.send_not_sir + action_receipt_creation_config.send_not_sir + transfer_cost.execution + action_receipt_creation_config.execution
) * gas_price
```

Prior to protocol version 78, the gas prices of each block was used for the work done at that height.
</Accordion>

### Creating an Account

```text
(
transfer_cost.send_not_sir + action_receipt_creation_config.send_not_sir
) * gas_price_at_block_1 +
(
transfer_cost.execution + action_receipt_creation_config.execution
) * gas_price_at_block_2
```
Creating an account costs a **fixed `0.007Ⓝ`**, which is burned.

</Accordion>
This is not a gas fee. The protocol charges it by **making the refund smaller**: when a receipt creates an account, it keeps back enough of the [price difference refund](#buying-vs-burning-gas) to bring the total cost of the creation up to `0.007Ⓝ`. You don't pay an extra fee, you simply get less back.

If the gas burned while creating the account is already worth more than `0.007Ⓝ` - which happens when the network's gas price is high - nothing is kept back and you just pay the gas.

The charge applies however the account is created: a `CreateAccount` action, a transfer to a [not-yet-existing implicit account](/protocol/accounts-contracts/account-id#implicit-address), a `DeterministicStateInit` action, or a contract creating a sub-account.

<Note>
**Why does creating an account cost extra?**

Every account occupies state that the nodes running its shard have to keep forever. An account can occupy up to `770` bytes without a [storage deposit](/protocol/storage/storage-staking), and at the storage price of `1Ⓝ` per `100kb` that space is worth about `0.0077Ⓝ`. The charge makes sure that space is paid for. It lands slightly below `0.0077Ⓝ` because the protocol can only hold back as much as the price difference on the gas burned while creating the account.
</Note>

---

## How Do I Buy Gas?

You don't buy gas, instead, the gas fee is automatically removed from your account's balance when the transaction [is first processed](./transaction-execution#block-1-the-transaction-arrives) based on the action's gas cost and the network's gas price.
You don't buy gas, instead, the gas fee is automatically removed from your account's balance when the transaction [is first processed](./transaction-execution#block-1-the-transaction-arrives) based on the action's gas cost and the [buy price](#buying-vs-burning-gas).

<Note>
Transactions signed with a [gas key](/protocol/accounts-contracts/access-keys#gas-keys) instead pay their gas fee from the key's own prepaid balance, and gas refunds return to the key.
</Note>

The only exception to this rule is when you make a function call to a contract. In this case, you need to define how many gas units to use, up to a maximum value of `300Tgas`. This amount will be converted to NEAR using the network's gas price and deducted from your account's balance.
The only exception to this rule is when you make a function call to a contract. In this case, you need to define how many gas units to use, up to a maximum value of `1000Tgas`. This amount will be converted to NEAR using the [buy price](#buying-vs-burning-gas) and deducted from your account's balance.

If the transaction ends up using less gas than the amount deducted, the difference will simply be **refunded to your account**. However, the network subtracts a **gas refund fee** of at least 1 Tgas or up to 5% of the unspent gas.
Anything you overpaid is **refunded to your account** one block later. This covers both the gas you attached but did not use, and the difference between the buy price and the burn price. Because of that second part, **almost every transaction gets a refund**, even one that attached exactly the right amount of gas.

<Accordion title="Gas Refund Fee">

Since protocol version 78, the unspent gas at the end of receipt execution is subject to a gas refund fee. The fee is still at 0 while we give projects time to adapt. The plan is to move to a fee calculated as `max(1 Tgas, 0.05 * unspent_gas) * gas_price`. The gas price is from the time of purchase.
Since protocol version 78, the unspent gas at the end of receipt execution is subject to a gas refund fee. The fee is still at 0 while we give projects time to adapt. The plan is to move to a fee calculated as `max(1 Tgas, 0.05 * unspent_gas) * gas_price`. The gas price used is the burn price.

_But why introducing such a fee instead of refunding all gas?_

The reason is that attaching too much gas to function calls makes the network less efficient.

Congestion control between shards gets tricky when transactions have much more gas attached than they actually use. The network limits how many cross contract calls can target a single shard per chunk, to avoid huge queues of incoming receipts on a shard. This limit sees the attached gas as an upper boundary for how much work the receipt causes on the receiving shard. Attaching too much gas can cause this limit to become too restrictive, which stalls shards unnecessarily.

The other inefficiency comes from the refund receipts that prior to version 78 have been created for essentially every function call. While each of them is relatively cheap to execute, in the sum they were a significant part of the global traffic on NEAR Protocol.

To read more about the decision to introduce this fee, please take a look at the [NEP-536](https://github.com/near/NEPs/pull/536)
The other inefficiency comes from the refund receipts that are created for essentially every function call. While each of them is relatively cheap to execute, in the sum they are a significant part of the global traffic on NEAR Protocol. Note that a refund receipt is needed for essentially every function call anyway, to return the price difference, so the fee only helps with congestion control.

</Accordion>

Expand Down
16 changes: 10 additions & 6 deletions protocol/transactions/meta-tx.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -197,12 +197,16 @@ explanation it makes sense now!

## Gas refunds in meta transactions

Gas refund receipts work exactly like for normal transaction. At every step, the
difference between the pessimistic gas price and the actual gas price at that
height is computed and refunded. At the end of the last step, additionally all
remaining gas is also refunded at the original purchasing price. The gas refunds
go to the signer of the original transaction, in this case the relayer. This is
only fair, since the relayer also paid for it.
Gas refund receipts work exactly like for normal transactions. At every step, the
difference between the price at which the gas was bought and the price at which it
was burned is refunded. At the end of the last step, all remaining gas is also
refunded at the buy price. The gas refunds go to the signer of the original
transaction, in this case the relayer. This is only fair, since the relayer also
paid for it.

Note that the relayer has to hold more NEAR upfront than the meta transaction
finally costs, because gas is
[bought at a price that can be higher than the price it burns at](/protocol/transactions/gas#buying-vs-burning-gas).

---

Expand Down
4 changes: 2 additions & 2 deletions protocol/transactions/transaction-execution.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ During this process a `FunctionCall` could span a **cross-contract call**, creat
Each `Receipt` created from the function call take an additional block to be processed. Notice that, if those `Receipts` are `FunctionCall` they could spawn new `Receipts` and so on.

#### Final Block: Gas is Refunded
A final `Receipt` is processed in a new block, refunding any extra gas paid by the user.
A final `Receipt` is processed in a new block, refunding any extra gas paid by the user. Almost every transaction ends with one of these, since the [buy price](./gas#buying-vs-burning-gas) is usually higher than the burn price.

### Waiting for a Transaction

Expand All @@ -61,7 +61,7 @@ Notice that `ExecutedOptimistic` and `IncludedFinal` are not ordered relative to

#### Refund receipts

When a receipt executes with leftover gas, NEAR generates a refund receipt to return the unused payment to the sender. These always succeed and don’t affect application logic, so `ExecutedOptimistic` and `Executed` don’t wait for them — only `Final` does.
When a receipt executes, NEAR generates a refund receipt to return the unused payment to the sender: the gas that was attached but not used, plus the difference between the price the gas was bought at and the price it was burned at. These always succeed and don’t affect application logic, so `ExecutedOptimistic` and `Executed` don’t wait for them — only `Final` does.

<Tip>
Most transactions will just spawn a receipt to process the actions, and a receipt to refund the gas, being final in 1-3 blocks (~1-3 seconds):
Expand Down
4 changes: 4 additions & 0 deletions smart-contracts/anatomy/actions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,10 @@ Accounts do **NOT** have control over their sub-accounts, since they have their

Sub-accounts are simply useful for organizing your accounts (e.g. `dao.project.near`, `token.project.near`).

<Note>
Creating an account costs a fixed [`0.007Ⓝ`](/protocol/transactions/gas#creating-an-account), or about `0.00707Ⓝ` in total once the send fees are added. That `0.007Ⓝ` already includes the gas burned while creating the account, and it is taken out of the transaction's gas refund, not out of the deposit you attach for storage.
</Note>

<Tabs>
<Tab title="🦀 Rust">

Expand Down
2 changes: 1 addition & 1 deletion web3-apps/tutorials/data-types.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ fn main() {

When calling a contract method, you can specify how much gas you want to attach to the call. Within the network, the `Gas` is represented as a `u64`, which is encoded as a `string` (since JSON cannot handle more than 52 bit integers).

As a rule of thumb, functions that consume little computation can be called with `30 Tgas` or less, while more complex functions may require up to `300 Tgas`.
As a rule of thumb, functions that consume little computation can be called with `30 Tgas` or less, while more complex functions may require up to `1000 Tgas`.

<Tabs>

Expand Down