Skip to content

Tokenomics

This page covers the economics of the Ootle layer specifically:

  • The L2 native token: what resource it is and the constants that name it.
  • The burn-to-mint bridge from the base layer, and why it is one-way.
  • The claim mechanism that mints L2 value from a base-layer burn.
  • How transaction fees are split between the burn and the validator.

Ootle’s native token is a stealth resource. Its identity is a fixed resource address constant:

crates/template_lib_types/src/constants.rs
/// The Tari network native resource address. ... fungible resource with a divisibility of 6.
pub const STEALTH_TARI_RESOURCE_ADDRESS: ResourceAddress =
ResourceAddress::new(ObjectKey::from_array([1u8; ObjectKey::LENGTH]));
/// Shorthand version of the `STEALTH_TARI_RESOURCE_ADDRESS` constant
pub const TARI_TOKEN: ResourceAddress = STEALTH_TARI_RESOURCE_ADDRESS;
PropertyValue
SymbolTARI (tTARI on testnet, $TARI on mainnet)
Resource constantTARI_TOKEN (alias of STEALTH_TARI_RESOURCE_ADDRESS)
TypeStealth — amounts and owners hidden
Divisibility6
Base unitmicrotari: 1 TARI = 1_000_000 microtari (const TARI: u64 = 1_000_000)

Being a stealth resource, TARI does not live in vaults — it exists as UTXOs with hidden amounts and one-time addresses, which is why network fees are paid via a revealed output (see Privacy).


Value enters Ootle along a single, one-way path: burn on the base layer, claim on Ootle.

burn XTML1  ⟶  mint TARIL2\text{burn } \text{XTM}_{L1} \;\longrightarrow\; \text{mint } \text{TARI}_{L2}

There is no peg-out. You cannot burn TARI on Ootle to recreate base-layer coins. The asymmetry is deliberate:

The burn-to-mint bridge, and its missing return legValue crosses one way. The claim is the only door, and it only opens inward.Minotari (L1)a coin is burnedburned outputgone from L1 supplyMinotariBurnClaimProofMerkle proof vs outputsOotle (L2) — one atomic claim1. Verify the burn proof against the base layer’s outputs2. Tombstone the commitment — blocks a second claim of it3. Mint the stealth UTXO at UtxoAddress::new(TARI_TOKEN, commitment)no peg-out — TARI cannot be burned to recreate a base-layer coin
  • Base-layer supply stays under base-layer control. Ootle can never inflate the base-layer coin, because it only ever consumes it.
  • Ootle’s supply is anchored, not invented. Every unit of TARI on the L2 corresponds to a burned L1 output; the bridge can only move value inward.
  • Demand for TARI is tied to the fee market. Because the only route in is a burn, holding TARI is a claim on Ootle’s execution, not on the base layer.

Moving value across the bridge is a claim: the holder proves that a base-layer output was burned to them, and the engine mints the matching L2 value. The claim carries a MinotariBurnClaimProof (crates/engine_types/src/confidential/claim.rs) — a commitment, an ownership proof, the burn output, and a Merkle proof of that output against the base layer block it was mined in.

The engine executes a claim in three steps, atomically (crates/engine/src/runtime/impl.rs):

// 1. verify the claim proof against the base-layer burn
// 2. Create a tombstone
let address = ClaimedOutputTombstoneAddress::from_commitment(claim.commitment);
state_mut.new_substate(address, ClaimedOutputTombstone { value: claim.value })?;
// 3. Create the stealth UTXO.
let address = UtxoAddress::new(TARI_TOKEN, claim.commitment.into());
state_mut.new_substate(address, utxo)?;
  1. Verify the burn proof.
  2. Tombstone the commitment. The tombstone’s address is derived from the commitment itself (ClaimedOutputTombstoneAddress::from_commitment), so a second claim of the same commitment would collide with the existing tombstone and be rejected. This is what makes the claim double-spend-proof.
  3. Mint the stealth UTXO at UtxoAddress::new(TARI_TOKEN, commitment).

Because the claim is Output → Utxo and writes both the tombstone and the UTXO in one substate diff, it either completes entirely or not at all.

The claim mints a stealth UTXO with no matching increase_total_supply. That is sound only because the genesis TARI resource disables total supply tracking and denies Burn — so no other path can increase or decrease the tracked supply, and the mint cannot create a discrepancy. A resource that enabled supply tracking or allowed burns would need a matching supply update here. See Privacy in Applications for how supply tracking interacts with mint and burn for ordinary stealth resources.


Every transaction pays a fee for the metered work it performs (see State and Execution). The fee is then split between a burn and the validator.

The split is governed by exhaust_burn_rate, a per-network constant expressed in basis points:

crates/consensus/src/consensus_constants.rs
pub exhaust_burn_rate: ExhaustBurnRate, // 500 bps on every network here
// ...
exhaust_burn_rate: ExhaustBurnRate::new(500), // 5%

The burn is a floor share of everything collected — overcharge included — and the validator receives the remainder:

crates/engine/src/runtime/working_state.rs
/// The share of `paid` that is burned at `rate`: `⌊paid × rate / 10_000⌋`.
fn exhaust_burn_share(paid: u64, rate: ExhaustBurnRate) -> u64 {
(u128::from(paid) * u128::from(rate.as_bps()) / 10_000) as u64
}

With the network rate of 500 bps:

burn=⌊fee×50010,000⌋\text{burn} = \left\lfloor \frac{\text{fee} \times 500}{10{,}000} \right\rfloor

The configured rate is 5%, but the result is rounded down to a whole base unit. The validator that produced the block receives fee - burn, which can therefore be slightly more than 95%; for fees smaller than 20 base units the burn rounds to zero. The validator’s share is held in a ValidatorFeePool substate and withdrawn later via ClaimValidatorFees.

Where a fee goesA fixed 500 bps is destroyed; the remainder funds whoever produced the block.fee paida deterministic metered cost5% rate, rounded downremoved from L2 supplythe remainder to the validatorheld in a ValidatorFeePoolThe ruleburn = floor(paid × 500 / 10,000)paid = everything collected,overcharge included.The rate is a per-networkconstant — 500 bps on everynetwork in this repository.There is no priority or throttle layer: a fee is a function of work done, never of a bid for ordering.

There is no priority or throttle layer. Fees are a deterministic function of metered execution — a transaction pays for the work it performs, and there is no market for ordering beyond the protocol’s own sequencing. Searching the codebase for a fee-priority or throttle concept returns nothing; the only rate limiting present is an unrelated wallet API-key limit.


  • The L2 native token is TARI, a stealth resource addressed by TARI_TOKEN / STEALTH_TARI_RESOURCE_ADDRESS; XTR/ONE_XTR are deprecated aliases.
  • Divisibility is 6; 1 TARI = 1_000_000 microtari.
  • Value enters by burning a base-layer coin and claiming an L2 UTXO — a strictly one-way bridge with no peg-out.
  • A claim verifies a burn proof, writes a commitment-derived tombstone (double-claim proof), and mints a stealth UTXO — atomically.
  • Fees use a 500 bps burn rate rounded down to a whole base unit; the remainder accrues to the validator.
  • There is no fee priority/throttle concept; fees are deterministic metering.

Next: the A–Z of terms used across this section — Glossary.