# Gas & fees

> How NeuroChain fees work — uNRO units, gas per operation, the EIP-1559 style base fee, the 50% burn, block gas budget and mempool rules, with the exact constants from the node.

Source: https://docs.nro.world/learn/gas

Every amount on chain is an integer in **uNRO**: `1 NRO = 1 000 000 uNRO`.

A fee is **gas units × gas price**, where the gas price is in uNRO per gas unit:

```
fee (uNRO) = gas_units × gas_price
```

## Gas per operation

| Operation | Gas units | Constant |
|-----------|-----------|----------|
| Transfer | 21 | `GAS_BASE_TRANSFER` |
| Contract call (`.app` address with call data) | 50 prepaid, then settled by actual use — see below | `GAS_CONTRACT_CALL` |
| Contract deploy | 10 000, flat | `DEPLOY_GAS_UNITS` |
| Paid name transfer (`.node`, `.vault`, `.agent`) | flat **100 uNRO** fee | `NFT_TRANSFER_FEE` |
| System operations (staking, registrations, faucet, governance markers) | 0 | — |

At the minimum gas price of 1 uNRO, a transfer costs **21 uNRO = 0.000021 NRO**.

### Contract calls

A call is charged 50 gas units up front. The contract then runs in the WASM interpreter with a budget of **1 000 000 fuel** (`MAX_CONTRACT_GAS`). After it finishes, the node converts the fuel actually burned into gas units — `ceil(fuel / 20 000)`, at least 1 — and refunds or charges the difference.

The conversion rate is `NEUROCHAIN_FUEL_PER_GAS_UNIT` (default 20 000), chosen so a call that exhausts its fuel costs exactly the 50 units prepaid. Host functions such as storage reads and writes burn extra fuel; see [NeuroWASM gas & limits](/neurowasm/gas-limits).

If the contract traps or runs out of fuel, its storage changes are rolled back and the value is not transferred — but the **nonce and the fee are still consumed**, so a failing call cannot be replayed for free.

## Base fee

The protocol keeps a **base fee** that moves with demand, in the style of Ethereum's EIP-1559:

- It starts at 1 uNRO per gas unit and never drops below that floor (`MIN_GAS_PRICE`).
- After each block, it moves towards a target of half the block gas budget (5 000 units): up when the block used more, down when it used less, by at most 12.5% per block. It always moves by at least 1 uNRO when it moves, so after congestion it returns all the way to the floor.
- **A transaction whose `gas_price` is below the current base fee is rejected on every validator.** This is enforced in consensus, not only by the mempool, so a proposer cannot slip an underpriced transaction past the others.

Read the current value before sending:

```bash
curl -s "$NODE_RPC/api/v1/gas/estimate"
```

```json
{
  "base_fee": 1,
  "gas_base_transfer": 21,
  "gas_contract_call": 50,
  "estimated_transfer": 21,
  "estimated_contract": 50,
  "estimated_transfer_human": "0.000021",
  "estimated_contract_human": "0.00005",
  "total_burned": 0,
  "nft_transfer_fee": 100,
  "nft_transfer_fee_human": "0.0001"
}
```

The gateway serves the same data at `$GATEWAY/api/v1/gas/estimate`. The web wallet sends `gas_price = base_fee × 1.5` to stay ahead of a rising base fee.

## Where fees go

![Fee flow: the fee from each transaction is split, 50% burned and 50% credited to the block proposer; the base fee sets the minimum gas price](/diagrams/fee-flow.svg)

After each block, the sum of its fees is split:

- **50% is burned** (`BURN_RATE_BPS = 5000`) and added to the running `total_burned`.
- **50% goes to the block's proposer.**

Registration fees for `.app` and `.vault` names are burned in full; a `.node` registration becomes stake instead. See [Addresses](./addresses).

## Block budget and the mempool

| Rule | Default | Override | Notes |
|------|---------|----------|-------|
| Gas per block | 10 000 units | governance `max_block_gas` | 1 to 1 000 000 000; read when the node starts |
| Transactions per block | 500 | — | `MAX_BLOCK_TXS` |
| Mempool size | 10 000 | `NEUROCHAIN_MAX_MEMPOOL` | When full, a new transaction pushes out the lowest-priced pending one — only if it pays more |
| Time in the mempool | 60 seconds | — | A pending transaction not included by then is dropped |
| Pending per sender | 64 | `NEUROCHAIN_MAX_PENDING_PER_ACCOUNT` | Further transactions from the same address are refused |
| Replace by fee | +10% | `NEUROCHAIN_RBF_MIN_BUMP_PCT` | Re-sending the same `(from, nonce)` replaces the pending one only with a gas price at least this much higher |
| Mempool price floor | 0 (off) | `NEUROCHAIN_MIN_FEE_PER_GAS` | Optional ingress floor on top of the base fee |

The proposer takes pending transactions in fee order (same-sender transactions stay in nonce order), skips any below the base fee, and stops adding once the block budget is full. While choosing, it counts every transfer as 21 units and every `.app` call as 50.

## Constants at a glance

| Constant | Default | Meaning |
|----------|---------|---------|
| `UNRO_PER_NRO` | 1 000 000 | uNRO in one NRO |
| `GAS_BASE_TRANSFER` | 21 | Gas units for a transfer |
| `GAS_CONTRACT_CALL` | 50 | Gas units prepaid for a contract call |
| `DEPLOY_GAS_UNITS` | 10 000 | Gas units for a deploy |
| `MAX_CONTRACT_GAS` | 1 000 000 | Fuel budget per contract call |
| `NEUROCHAIN_FUEL_PER_GAS_UNIT` | 20 000 | Fuel per gas unit when settling a call |
| `MIN_GAS_PRICE` | 1 | Base fee floor, uNRO per gas unit |
| `MAX_BLOCK_GAS` | 10 000 | Gas units per block |
| `BURN_RATE_BPS` | 5 000 | Share of fees burned, in basis points (50%) |
| `NFT_TRANSFER_FEE` | 100 | Flat fee for transferring a paid name, uNRO |
