Tokens
Anybody can make one. It is a module built into the protocol, not code uploaded to the chain — and nothing about holding one touches who votes.
Making one
./baklava token -keystore wallet.json -symbol BAK -name "Baklava Points" -supply 21000000Or /token BAK 21000000 Baklava Points from the console. The whole supply is credited to you in the transaction that creates it, and the id comes back straight away — it is derived from your address and the nonce that made it, so nobody picks it, including the command you just ran.
| The supply is final | There is no mint transition and no owner field. A holder never has to wonder what the creator might do next, because there is nothing they can do. That is a smaller module than most chains ship and the omission is the point: a mint function makes a token's value a claim about somebody's intentions, and a chain can show balances, not intentions. |
|---|---|
| It costs 10 BKLV | Paid to the treasury, on top of the fee, and it does not come back. A token is a leaf that never goes away and every holder of it is another leaf that never goes away — the retention window prunes block bodies, never state. A fee prices the block space a transaction occupies for a moment; this prices the row every node carries for the life of the chain. |
| Fees stay in BKLV | Moving a token costs a BKLV fee like everything else, so a wallet holding a token and no BKLV cannot move it. Fees are what pays the committee, and a fee market across assets anybody can print would make what a block is worth a question about exchange rates the chain has no way to answer. |
| A token buys nothing | It does not enter weight, does not open the registry and is not collateral. Weight is maturity times reliability, and even the registration stake stays out of it — a unit somebody printed for 10 BKLV certainly does. |
The id is the identity. The symbol is a label.
Symbols and names are not unique and the chain does not check them against each other. Two tokens may both call themselves BAKLAVA and neither is the real one — there is no such thing.
That is deliberate, and it is the safer of two bad options: unique names mean a land rush and a squatting market the chain would have to police for ever. So anything that shows you a symbol without the id is showing you something anybody can copy in one transaction. This is where every fake-token scam on every chain has come from.
A logo, and why it is a commitment rather than a link
From rule version 4 a token record carries a 32-byte commitment to its metadata — its logo, most of the time. It is the same field a collection has carried since NFTs were built, which is the point: an NFT's picture could be checked against the chain and a token's could not.
sha256sum logo.png # the commitment is just its hash
./baklava token -keystore wallet.json -symbol BAK -supply 21000000 -meta <the 32 bytes, in hex>Or --meta on /token from the console. There is no URI, for the reason a collection has none: a URI is a promise about another server that the chain has no way to keep and no way to check. Zero means no commitment rather than a commitment to nothing.
It is written once, with the supply, and there is no way to change it.
That is this module's own argument applied to itself. A token is worth holding here because there is nothing the creator can do next — the supply is fixed and there is no mint. A metadata field they could rewrite puts that straight back: a token could be one thing when it was bought and another when it was sold.
It matters most where a stranger's token is put in front of somebody and the picture is most of what they see. A logo a website can change without leaving a trace is a logo that can be swapped for a well-known project's the day before a sale.
Moving one, and looking one up
./baklava send-token -keystore wallet.json -token <id> -to bkx1... -amount 500000
./baklava token-info -holder bkx1... <id>token-info checks the proof rather than printing what it was told: the token leaf folds to a token root, which folds with the account root, the registry root and the parameter digest into the state root the header carries. An absent balance is a balance of zero and is proved as one — an address nobody has ever paid in a token holds none of it.
Where the balances live
In a third sparse merkle tree, beside the accounts and the participant registry, and this is the one design decision worth knowing about. A balance is keyed by a pair — which token, whose balance — and the cheap answer is to put it in the account table at a derived key.
That is disqualified by an attack. The account tree's key is the address, so a leaf at H(token ‖ holder) sits at a perfectly valid address that anybody can derive — and anybody can send BKLV to any address. A stranger could pay one Krumb into your token balance and mint with it, and no check can stop them: telling whether twenty bytes are H(token ‖ holder) for some pair means inverting a hash.
So state_root folds four things from rule version 3 rather than three, and the fold takes the rule version — a binary that always folded four would compute a root that no version 1 or version 2 chain ever had. Same problem as a registry entry's width, one level up.
Rule version 3, and baklava-testnet-5 scheduled it itself.
Tokens add a state table, so they change what state_root commits to, so they are a new rule version. What is new is that this no longer meant a new chain: the readiness threshold appended the activation to the schedule while the chain ran, and it took effect at height 2500. See Upgrades and readiness — this is the first rule that mechanism was built for, and the first one it carried.
The reasoning in full, including what a mint transition would have cost and why names are not unique, is under Tokens in the protocol document.