Guides

Gamma

Dollar-valued service credits minted by burning a subnet's alpha, held in deposits keyed by API-key hotkeys and spent by each deposit's spender.

View as Markdown

Gamma is a credit a subnet can accept as payment for its service, valued in US dollars. Once gamma is enabled network-wide and on a subnet, a coldkey mints that subnet's gamma by burning its alpha, bought with TAO or taken from stake. One gamma is minted for each dollar the burned alpha is worth.

Gamma is held in deposits. Each deposit belongs to a coldkey and is keyed by a hotkey, which signs the customer's requests to the service, so the hotkey works as an API key. The deposit's spender spends it as it serves those requests.

Before opening a deposit, associate the API-key hotkey with the minting coldkey using try_associate_hotkey (or register the hotkey). Only that coldkey can open a deposit at the hotkey, including by moving gamma into a new deposit.

Gamma cannot be transferred to another coldkey or converted back into alpha or TAO. Amounts are in gamma, with 10^9 units per gamma.

RoleCan
Coldkeymint into its deposits, move gamma between them, set each deposit's spender and daily spend cap, close empty deposits
Hotkeynothing on chain; it signs requests to the service
Validator or subnet owner hotkeypublish a service and its spender on its subnet, signed by its coldkey
Spenderspend the deposits that name it, directly or through a GammaSpend proxy
Subnet ownerenable gamma on its subnet with gamma_enabled; spender of the deposits a mint opens while it owns the subnet, unless its hotkey's service names another or a lease owns it
Lease beneficiaryenable gamma through its SubnetLeaseBeneficiary proxy; spender of the deposits a mint opens while its lease owns the subnet, unless the subnet owner hotkey's service, which it publishes through that proxy, names another
Rootenable gamma network-wide and on any subnet but root, and set the TAO/USD price oracle
Oraclefeed the TAO/USD price

Minting

Minting needs gamma enabled on the subnet and a fresh TAO/USD price. Mint with TAO into a deposit at a fresh hotkey, for a service the subnet lists with services:

btcli wallet new-hotkey -H API_KEY
btcli wallet associate-hotkey --hotkey API_KEY
btcli query services --netuid 51
btcli gamma mint --netuid 51 --hotkey API_KEY --amount-tao 10 --service-hotkey SERVICE_HOTKEY
quote = await client.gamma.quote_mint_gamma(netuid=51, amount_tao=10)
await client.execute(bt.AssociateHotkey(hotkey_ss58=api_key), wallet)
await client.execute(
    bt.MintGamma(netuid=51, hotkey_ss58=api_key, amount_tao=10, service_hotkey_ss58=service), wallet
)

--service-hotkey names the spender the service publishes, so the service can spend the deposit.

mint-gamma buys alpha with the TAO and burns it, with the same pool and flow accounting as stake-burn, and creates no stake position. mint-gamma-with-stake burns stake you already hold instead:

btcli gamma mint-with-stake --netuid 51 --hotkey API_KEY --origin-hotkey VALIDATOR --amount-alpha 100 --service-hotkey SERVICE_HOTKEY

--amount-alpha all burns the whole stake.

The burned alpha is valued at the lower of two prices:

TAO value = alpha × min(gamma price, spot price)
gamma     = TAO value × TAO/USD price

Every subnet but root keeps a gamma price, whether or not gamma is enabled. Registration sets it to the median subnet alpha price, which the new pool is created at; a subnet registered before gamma starts at its spot price. Each block it falls to the spot price at once and rises toward it by ln 2 / 600 of the gap, so the gap halves every 600 blocks, about 2 hours. A rise is at most ln 2 / 600 of the gamma price itself, so however far spot jumps, the gamma price at most doubles every 600 blocks. The spot price is read before the mint trades. Alpha is valued at these prices, not at what selling it would return, so a burn that is large for the pool is worth more than its sale.

The SDK quotes the mint first and fails it if the minted gamma would fall more than rate_tolerance (5% by default) below the quote. The with-stake quote assumes the whole amount is burned; the SDK quotes no more than the stake you hold. Once the mint runs, result.data["minted"] holds the deposit's hotkey_ss58, spender_ss58 and daily_spend_cap_gamma, and the alpha_burned, tao_value and gamma minted, as exact decimal strings.

A mint fails with GammaDisabled while gamma is off network-wide or on the subnet. No other call checks these switches, so turning one off stops new mints only, and existing deposits can still be spent, moved and closed. A mint also fails with AmountTooLow below 0.1 gamma, with SubtokenDisabled on a subnet whose subtoken is not enabled, and with SlippageTooHigh below its minimum. A TAO mint above the add-stake swap input limit fails with InsufficientLiquidity. Minting or moving into a hotkey whose deposit belongs to another coldkey fails with NonAssociatedColdKey.

Through a proxy, minting and moving need an Any or NonCritical proxy. Setting a deposit's spender or daily spend cap and closing it also take a NonTransfer proxy.

Deposits and API keys

Any account can be a deposit's hotkey, and it needs no registration or funds. A hotkey holds at most one deposit per subnet, owned by the coldkey that opened it, so create a fresh hotkey for each deposit. Requests signed with it are paid from the deposit, so never use a staking hotkey or a coldkey. A coldkey holds at most 64 deposits per subnet.

btcli gamma list
btcli gamma show --netuid 51 --hotkey API_KEY

To give someone gamma, open a deposit with their hotkey. The deposit stays yours: move the gamma back at any time.

btcli gamma move --netuid 51 --origin-hotkey THEIR_KEY --destination-hotkey API_KEY --amount-gamma all

move-gamma to a hotkey with no deposit opens one with the origin's spender and daily spend cap. A move that empties the origin closes it. A deposit spent to zero stays open with its terms, so it can be refilled, until it is closed with close-gamma-deposit:

btcli gamma close --netuid 51 --hotkey API_KEY

Spenders and daily spend caps

The spender stays the same if the subnet changes hands. Name another account with set-gamma-deposit-spender and --spender SPENDER, a service's spender with --service-hotkey SERVICE_HOTKEY, or --default-spender for the spender of the subnet owner's service, otherwise the subnet's current owner, or its lease's beneficiary:

btcli gamma set-spender --netuid 51 --hotkey API_KEY --service-hotkey SERVICE_HOTKEY

A daily spend cap, set with set-gamma-deposit-daily-spend-cap, bounds what the spender can take. What it allows refills linearly at the cap per 7200 blocks, up to the cap. A cap set where there was none starts full, and a changed cap keeps what it allows now, up to the new cap, so ending a pause refills from nothing. A cap of zero pauses the deposit, and --remove-cap removes the cap.

While a deposit has a cap, a spender takes at most the highest cap plus its refill over any period. A deposit opened with a cap starts full.

btcli gamma set-cap --netuid 51 --hotkey API_KEY --daily-spend-cap-gamma 20

A mint can name a new deposit's terms with --spender SPENDER or --service-hotkey SERVICE_HOTKEY, and --daily-spend-cap-gamma 20, so the deposit never opens on others. A deposit that already has other terms fails the mint with GammaDepositSpenderMismatch or GammaDepositDailySpendCapMismatch.

Spending

The spender spends many deposits in one spend-gamma call, up to 512 entries of a hotkey, an amount and a reference:

btcli gamma spend --netuid 51 --spend API_KEY=0.25:0xREFERENCE --spend OTHER_KEY=1.5
result = await client.execute(
    bt.SpendGamma(
        netuid=51,
        spends=[{"hotkey_ss58": api_key, "amount_gamma": 0.25, "reference": reference}],
    ),
    spender,
)

Each entry spends its whole amount, and the spent gamma is destroyed. Entries whose hotkey has no deposit, whose deposit names another spender, or whose amount is zero or above the deposit's balance or what its daily spend cap allows now, are skipped, and cost less as they write nothing. spendable_gamma in gamma-deposit is what an entry can spend now. Once the spend runs, result.data["spent"] lists each entry that spent, with its hotkey_ss58, amount_gamma as an exact decimal string, and reference, and result.data["skipped"] lists each entry that was skipped, with the chain error that skipped it as reason, such as InsufficientGammaBalance.

A reference is any 32 bytes, all zero when omitted. The chain repeats it in the entry's GammaSpent or GammaSpendSkipped event and reads it nowhere else, so an entry sent twice spends twice. By convention it is the service's own 32-byte id for the request the entry pays for, returned with its response, so the customer can match each spend to its own request.

Since the coldkey can change the spender or pause the deposit at any time, a service spends ahead: it spends what it is about to serve, and serves what was spent. The spender can hand this right to a GammaSpend proxy, which can make no other call and spends with --proxy-for (proxy_for= in Python):

btcli proxy add --delegate BILLING_KEY --proxy-type GammaSpend -w SERVICE
btcli gamma spend --netuid 51 --spend API_KEY=0.25 -w BILLING_KEY --proxy-for SERVICE

The TAO/USD price

An oracle set by root feeds the TAO/USD price in gamma units, 10^9 per US dollar, so 400 dollars per TAO is fed as 400000000000. The accepted price falls to a lower feed at once and rises toward a higher one by at most 0.0066% (66 ppm) per block, about 2% per hour. A mint values TAO at the accepted price and needs a feed at most 300 blocks (one hour) old; otherwise it fails with TaoUsdPriceUnavailable. Setting or removing the oracle clears the price, so no gamma can be minted until an oracle feeds. Read it with tao-usd-price:

btcli query tao-usd-price

Limitations

  • Gamma confers no claim on any party and cannot be redeemed. A subnet decides whether, and at what prices, it accepts its gamma.
  • Dissolving or pruning a subnet destroys all of its gamma, and holders receive nothing.
  • Spent gamma pays its spender nothing: the burned alpha's value accrues to the subnet's alpha holders.
  • While a coldkey swap is announced, the coldkey's gamma calls are refused, but its spenders keep spending. A spender whose own swap is announced cannot spend.
  • A coldkey swap adds the coldkey's deposits to the new coldkey's. It fails if the new coldkey would hold more than 64 on a subnet, and is refused when the two coldkeys hold more than 128 together.
  • A spender's coldkey swap does not change any deposit's or service's spender. After a subnet owner or lease beneficiary swaps its coldkey, the deposits and the owner's service that name the old coldkey keep it. The owner republishes its service, and a deposit's coldkey re-points it with btcli gamma set-spender --default-spender. An owner whose service names a spender that never needs a swap, such as a multisig, needs neither.
  • The oracle is trusted: its accepted price can rise at most about 61% per day, until root replaces or removes it.