Cashtoken Request for Comments 20 (CRC-20)

With the May 2023 upgrade of Bitcoin Cash, the Cashtoken protocol will be activated. This protocol introduces native support for fungible and non-fungible tokens on Bitcoin Cash, marking a significant advancement from previous Layer-2 token issuance protocols such as the Simple Ledger Protocol.

However, in comparison to popular existing protocols like ERC20, the Cashtoken protocol still lacks certain features. Most notably, it does not specify the token's symbol, name, and decimals.

The CRC20 protocol is an extension to the Cashtoken protocol. It specifies three metadata fields for tokens: symbol, name, and decimals, applicable to both fungible and non-fungible tokens. It adopts a two-stage registration process similar to ENS: first committing the hash of the metadata onto the blockchain, then revealing the metadata itself. This process prevents attackers from maliciously rushing to register metadata through block reorgs.

The first token to register a specific symbol defines the "canonical category" for that symbol. This protocol provides a procedure to help clients identify the canonical category of a symbol. The query process does not need new indexing services. Instead, it uses the existing Electrum protocol in the Bitcoin Cash ecosystem.

CRC20 Specification

This protocol requires that the Genesis Output must be a covenant implemented with following code:

contract GenesisOutput(pubkey recipientPK, bytes metadata, int symbolLength) {
    function reveal(sig recipientSig) {
        require(checkSig(recipientSig, recipientPK));
        bytes20 symbolHash = hash160(metadata.split(symbolLength)[0]);
        bytes25 outLockingBytecode = new LockingBytecodeP2PKH(symbolHash);
        require(tx.outputs[0].lockingBytecode == outLockingBytecode);

The symbol, decimals and name are metadata[:symbolLength], metadata[symbolLength] and metadata[symbolLength+1:], respectively.

First, create a Genesis Output with a transaction, and after this transaction has enough confirmations, send the Genesis Transaction. When the Genesis Output is spent, it will reveal the symbol, decimals, and name metadata.

This covenant also requires that the first output of the Genesis Transaction is a P2PKH output, but here the hash of the symbol replaces the Pubkey's Hash. In other words, this UTXO cannot be spent by anyone and is referred to as a Symbol UTXO. Its purpose is to be indexed by the Electrum protocol.

Query a Symbol's Canonical Category

Next, we will discuss how to use the Electrum protocol to query what a symbol's canonical category is.

The Fair Genesis Height of a token is defined as MAX(H_commit, H_reveal-20), where H_commit (H_reveal) is the height of the transaction committing (revealing) the metadata, respectively. It is strongly discouraged to separate committing and revealing with too many blocks.

Given a symbol, calculate the address of the Symbol UTXO. Then we use blockchain.address.listunspent to find this address's UTXO list, sort them according to the Fair Genesis Height and the genesis transaction's hash ID, and then filter them:

  1. If this UTXO has not been packaged into a block, filter it out.
  2. If this UTXO is not the first output of the transaction, filter it out.
  3. If this UTXO is not an output of the Genesis Transaction, filter it out. This requires checking whether other outputs have the token category attribute, and the Symbol UTXO itself does not need to have the token category attribute.
  4. Search for the Target Input among the inputs of this Genesis Transaction. If the Target Input cannot be found, the UTXO should be filtered out. The Target Input must satisfy the following three conditions:
    1. It is a Genesis Input.
    2. It spends a covenant whose code is specified above.
    3. The symbol it reveals is the one we're querying.

The canonical category is the token category defined by the first UTXO in this filtered list.

When a reorg occurs in the Bitcoin Cash blockchain, the canonical category corresponding to a certain symbol may change.