Fungible Token Covenant Specification (KCC20)

The KCC20 spec is maturing and reaching finalization. I am working on the final reference implementation, which would mark this effort as complete.

One subtle subject that I am discussing nowadays with Michael and IzioDev is if and how to allow tokens to declare metadata information, such as decimal notation, symbol, name, etc., on-chain.

I started by claiming that this kind of information should not live on-chain. A token should represent its own local state, and it’s redundant to force each local UTXO to carry global, read-only information about itself.

On the other hand, I do feel there is a benefit in allowing this information to be declared on-chain and tied directly to the token covenant. This can make it clearer and more definite what the covenant itself is claiming, while the meaning and correctness of that metadata still ultimately rely on off-chain social consensus and verification.

After a few iterations, I think that a solution could take shape as a new convention that allows covenant deployers to declare social-consensus metadata related to their token in the genesis deployment transaction.

A possible solution could have been to utilize the transaction payload field. Instead, I prefer a solution that inscribes this information into the covenant ID itself by creating a new actor/UTXO that holds this state. Such a metadata actor would be constrained so that it cannot interfere with the normal operation of the other covenant actors. It could be unspendable, or its internal logic could allow it to be consumed, so its KAS value could eventually be returned to the creator while revealing the metadata it holds.

Either way, the covenant ID itself is forever left as a verifiable commitment, with a matching preimage proving that this metadata was part of the original deployment.

Note that this is not an integral part of KCC20. Its only purpose is to optionally allow token deployers to declare token-related information on-chain. KCC20 remains the standard for the actual token shape and interaction interface.

3 Likes

Question on the default 3/3 slot limit and settlement batching

I may be missing something here, so please correct me if this is off.

From what we measured, the slot limits are compiled into the token program, and since the whole program is pushed in every token input’s sigscript, the limit chosen at issuance seems to be paid by every later transfer, including a simple 1→1 payment. Our numbers in rusty-kaspa v2.1.0’s TxScriptEngine:

| Program | Redeem | 1→1 | 16 orders settled in one tx |

| Reference 3/3 | 3,090 B | 0.00702 KAS | not possible |

| 8/8 | 6,820 B | 0.01448 KAS | not possible |

| 16/16 | 12,788 B | 0.02642 KAS | 0.471 KAS |

| 3/3 + batch leader (below) | 3,090 B | 0.00702 KAS | 0.173 KAS |

3/3 looks right for payments, but for settlement (a matcher filling several orders against one taker, or a holder merging a fragmented balance) it takes several transactions. Raising the default would make every holder pay for capacity they rarely use, so we were hesitant to suggest that.

While testing, we noticed something that might already solve this, though I’d appreciate a check on our reading. As we understand §2, a delegator validates only its own owner and leaves the transition to the leader, and the leader’s template isn’t checked; its presence is bounded by the covenant lineage (KCC-1). If that’s correct, a token whose genesis also creates an amount-0 batch-leader UTXO can settle up to 16 holder inputs and outputs in one transaction with the holder program unchanged. In our tests the leader enforces conservation, canonical successor states and the same `extension_commitment`, and never authorizes a holder (each holder input still signs as a delegator). Leaders can be cloned permissionlessly from the genesis seed.

If this reading holds, two humble suggestions before Final:

1. If a “leader must be my own template” check is being considered for the delegator path, could it also accept one standard batch-leader template? Otherwise batching would only be possible with a larger N×N per token.

2. It might be worth considering a standard optional batch leader, so wallets and indexers see one holder template and one leader template rather than one program per issuer.

For issuers who’d like holders to name the leader they accept, we also tried a holder variant with an optional leader commitment (all zeros = disabled). It’s 15–19 B larger and passes the 62 conformance vectors in both settings.

Everything is in a public repo and has not been audited, so there may well be mistakes: `contracts/kcc20/p2/` and `crates/kob-tests/tests/kcc20_opt_tests.rs`, `kcc20_p2_tests.rs` in GitHub - RossKU/kob · GitHub

Happy to be corrected on any of this, and thanks for all the work on the spec.

I don’t see this as the standard’s role. The contract is obligated to make sure delegation is always used with a correct leader.

In the current reference code:

we indeed verify the specific leader. Likewise you can add additional delegate entries that forward to other actors/templates in the app, but then it’s your obligation to verify that all entries of that leader are consistent with the delegation (it also becomes a custom way to transfer the token).

Adding a batch leader to the standard itself requires justification and would also complicate the std and make it a multi-contract app. If anything, I think it should only be an optional addition/extension (ie in a different KCC).

I might be missing details or usage context you already have, so I’m happy to be corrected with more info.

3 Likes

Thanks, that makes sense. What it adds is doing it in one transaction, i.e. atomicity, and I can’t think of a standard use case that needs that right now. So I’ll withdraw the extension idea. Thanks for taking the time to explain.

The KCC-20 specification has been finalized.
Thank you to everyone who participated, tested, commented, and took part in its creation.

1 Like