Overview
Cowboy has protocol-native fungible tokens (CIP-20): token state lives in the chain’s state tree and is manipulated through system instructions, not per-token smart contracts. You interact with tokens two ways:- From the CLI —
cowboy token <subcommand>for scripting and operations - From actor code —
runtime.token_*host functions, so actors can create and move tokens as part of their logic
u128); decimals is display metadata only.
From the CLI
The full command surface is specified in cowboy token. A typical lifecycle:From actor code
Actors get the same operations throughcowboy_sdk.runtime. The caller is the actor itself — the actor’s address is the token owner / sender of transfers:
Each operation has a fixed gas cost (e.g. a transfer is 1,000 Cycles + 64 Cells) — see CIP-20 for the schedule.
Transfer hooks
A token can name a hook actor at creation (transfer_hook) to enforce custom transfer policy — blocklists, pausing, compliance logic. The hook implements two handlers:
can_transfer(payload)— called before balances move. Runs read-only (state writes are not committed). The check is fail-closed: the transfer proceeds only if the hook returns"true","1", or JSONtrue; any other output (includingb"ok"or an error) rejects it, reverting withTokenHookRejected.on_transfer(payload)— called after balances move, and may update the hook actor’s own state. Best-effort: a failure here is logged but does not revert the transfer.
Worked example
examples/core/05-tokens-and-balances/ in the repo pairs a CLI walkthrough (demo.sh) with an actor that creates and transfers a token programmatically (token_actor_example.py) — a good starting template for both styles.
Further reading
- CIP-20 — Fungible Tokens — authoritative spec: storage layout, system instructions, events, authority model
- cowboy token CLI — every subcommand, flag, and edge case
- Fee model overview — how Cycles and Cells are charged

