Operation Specifications

This section details the structure and rules for the core BRC-20 operations encoded in the OP_RETURN payload.

Deploy

The deploy operation registers a new BRC-20 token and sets its initial parameters.

{"p":"brc-20","op":"deploy","tick":"OPQT","m":"21000000","l":"1000"}
  • p: protocol identifier (MUST be "brc-20").
  • op: operation type (MUST be deploy).
  • tick: unique ticker symbol (MUST be a string of at least 4 characters. The maximum length is constrained by the overall 80-byte OP_RETURN size limit for the entire JSON payload).
  • m: maximum total supply for the token (MUST be a string representing an integer ≤ 2⁶⁴–1).
  • l: limit on the amount of tokens that can be minted or transferred in a single operation (OPTIONAL string representing an integer). If present, mint and transfer amounts cannot exceed this limit.

Indexer Validation:

A deploy operation using this OP_RETURN extension is only valid if the specified tick (as an exact string) has not already been validly deployed by any prior valid deploy transaction seen on-chain. This includes deploys made using the original Ordinals-based BRC-20 standard (which only supports 4-character tickers) and other deploys using this OP_RETURN method (which support tickers >= 4 characters). This creates a shared global ticker namespace. Indexers MUST enforce this uniqueness by prioritizing the first valid deploy transaction seen on-chain for any given unique ticker string, regardless of the method used. Subsequent deploys for the same ticker string are invalid and MUST be ignored by indexers.

Calculating Maximum Ticker Length

All BRC-20 deploy payloads must fit within the 80-byte OP_RETURN limit on Bitcoin.

A valid minified JSON deploy payload with "m" (max supply) and "l" (limit per mint) looks like this:

{"p":"brc-20","op":"deploy","tick":"<TICKER>","m":"<MAX_SUPPLY>","l":"<LIMIT>"}

Fixed Overhead

Everything except <TICKER>, <MAX_SUPPLY>, <LIMIT>, and their quotes:

ComponentBytes
{"p":"brc-20"}13
,"op":"deploy"15
,"tick":""10
,"m":""8
,"l":""8
Total overhead54 bytes

The quotes around the values are included in the fixed overhead for empty strings ("").

Available Bytes for Data

80 (OP_RETURN limit)
− 54 (fixed overhead)
= 26 bytes remaining

You must divide the 26 bytes between:

  • <TICKER> (token ticker)
  • <MAX_SUPPLY> (value for "m")
  • <LIMIT> (value for "l")

Examples

Example 1 — 21,000,000 tokens, mint limit = 1000

  • "m":"21000000" → 8 bytes
  • "l":"1000" → 4 bytes
  • Remaining for ticker: 26 − 8 − 4 = 14 bytes
{"p":"brc-20","op":"deploy","tick":"ABCDEFGHIJKLMN","m":"21000000","l":"1000"}

✅ Valid — 14-character ticker fits in 80 bytes.

Example 2 — 1,000,000,000 tokens, mint limit = 10000

  • "m":"1000000000" → 10 bytes
  • "l":"10000" → 5 bytes
  • Remaining for ticker: 26 − 10 − 5 = 11 bytes
{"p":"brc-20","op":"deploy","tick":"ABCDEFGHIJK","m":"1000000000","l":"10000"}

✅ Valid — 11-character ticker fits.

Example Raw Transaction (Illustrative):

# This is a conceptual example. Actual data string would be the hex of the minified JSON.
# 'data' field value must be the hex of the OP_RETURN script (e.g., 6a...<hex_payload>)
bitcoin-cli createrawtransaction   '[{"txid":"<UTXO_providing_BTC>","vout":0}]'   '{"data":"6a4c...<hex_of_minified_deploy_json>","1DeployAddr":0.00000546,"1ChangeAddr":0.00999}'

Developers and users should always verify the transaction structure and the OP_RETURN payload content and size using tools like decoderawtransaction before signing and broadcasting. Be mindful that longer tickers consume more bytes, potentially impacting the ability to include other data fields within the 80-byte limit.

Mint

The mint operation creates new units of a deployed BRC-20 token.

{"p":"brc-20","op":"mint","tick":"OPQT","amt":"500"}
  • p: brc-20.
  • op: mint.
  • tick: the ticker symbol of the token being minted. MUST correspond to a validly deployed token (either via Ordinals or a valid OP_RETURN deploy). The ticker string MUST exactly match the deployed ticker.
  • amt: the amount of tokens to mint in this operation (MUST be a string representing an integer). This amount MUST be less than or equal to the l limit specified in the token's deploy operation, if l was defined. The total minted supply (sum of all valid mints) plus this amt MUST NOT exceed the token's maximum supply m.

A mint operation is valid only if the tick corresponds to a valid deploy, the amt respects the l limit (if set), and the operation does not cause the total minted supply to exceed the m limit. The minted tokens are allocated to the standard outputs based on the Proportional Distribution rule.

Simple Mint (Tokens allocated to one address)

# The output amount (e.g., 0.00000546 BTC) satisfies dust limit.
# The indexer allocates the token amount based on the OP_RETURN data to the recipient of this output.
bitcoin-cli createrawtransaction \
  '[{"txid":"<UTXO_providing_BTC>","vout":1}]' \
  '{"data":"6a3b...<hex_of_minified_mint_json>","destAddr":0.00000546,"changeAddr":0.00999}'

Transfer

The transfer operation moves existing units of a BRC-20 token from one holder to another.

{"p":"brc-20","op":"transfer","tick":"OPQT","amt":"250"}
  • p: brc-20.
  • op: transfer.
  • tick: the ticker symbol of the token being transferred. MUST correspond to a validly deployed token. The ticker string MUST exactly match the deployed ticker.
  • amt: the amount of tokens to transfer in this operation (MUST be a string representing an integer).

A transfer operation is valid only if the tick corresponds to a valid deploy, AND the sender (identified by the input UTXO(s) being spent) has an available balance (as tracked by the indexer) greater than or equal to the amt specified in the OP_RETURN. If l was defined in the deploy, the amt MUST also be less than or equal to l. The transferred tokens are allocated to the standard outputs based on the Proportional Distribution rule.

Simple Transfer (Tokens allocated to one receiver)

# The input UTXO(s) must be recognized by the indexer as holding the sender's balance.
# The output amounts (e.g., 0.00000546 BTC) satisfy dust limit.
# The indexer allocates the token amount based on the OP_RETURN data to the recipient of receiverAddr.
bitcoin-cli createrawtransaction \
  '[{"txid":"<UTXO_carrying_sender_balance>","vout":0}]' \
  '{"data":"6a3f...<hex_of_minified_transfer_json>","senderAddr":0.00000546,"receiverAddr":0.00000546,"changeAddr":0.00998}'

Note: Indexer policy determines how tokens are distributed among sender and receiver outputs based on satoshi values and intent.