Status: Draft
Type: Standards Track
Category: Core
Created: 2025-11-14
Updated: 2026-01-18
Abstract
CIP-20 defines Cowboy’s native fungible token standard. Tokens are first-class runtime primitives—not actor contracts—enabling maximum efficiency while supporting institutional requirements like pause, blacklist, and compliance controls through optional validation hooks. Key design choices:- Platform-native: Tokens managed by runtime, not individual actors
- Validation hooks: Optional actor that can block transfers (for pause/blacklist/KYC)
- No modification hooks: Hooks cannot change amounts (no fee-on-transfer at platform level)
- Solana-level efficiency: 50-100x cheaper than actor-based tokens
Motivation
A standard fungible token interface is critical for ecosystem growth. Every wallet, DEX, and application needs to interact with tokens predictably.Why Platform-Native?
Implementing tokens as actors (like Ethereum’s ERC-20) has significant drawbacks:
Solana’s SPL Token program demonstrates that platform-native tokens achieve 50-100x better performance.
Why Validation Hooks?
Institutional tokens (stablecoins, securities, RWAs) require compliance controls:- Pause: Halt all transfers during security incidents
- Blacklist: Block sanctioned addresses (OFAC compliance)
- KYC: Restrict transfers to verified addresses
- Freeze: Lock individual accounts
Specification
Token Data Structures
TokenMint
Each token type has a mint record stored in the runtime:TokenAccount
Each holder has a token account per token:Validation Hook Interface
Tokens MAY specify atransfer_hook—an actor that validates transfers. The hook interface:
Hook Constraints
- Cannot modify amounts: Hooks validate, they don’t transform
- Cannot add transfers: No fee-on-transfer via hooks
- Gas limit: Hook calls capped at 50,000 Cycles and 50,000 Cells. For the pre-hook
can_transfer, exceeding the cap fails (reverts) the transfer. For the post-hookon_transfer, exceeding the cap is treated like any other post-hook failure: logged and ignored, and the transfer is NOT reverted. - Failure = revert: If
can_transferreturns False, transfer reverts - No recursion: Hooks cannot trigger transfers of the same token
Example: USDC Compliance Hook
Host Functions
System Opcode Assignments
Each host function is aSystemInstruction variant with a fixed opcode (allocated in cowboy-protocol-codec and pinned by the opcode-uniqueness test):
Opcodes 21–23 (allowance-delta ops + permit) exist in code but were previously undocumented in this CIP.
The Cowboy runtime exposes these native functions for token operations:
Token Creation
Transfers
Approvals
Queries
Minting and Burning
Administration
Events
Platform tokens emit standardized events:Storage Layout
Platform tokens are stored in a dedicated runtime state section:Actor Token Interface
For tokens requiring custom transfer logic (fee-on-transfer, rebasing, complex vesting), implement as an actor. Actor tokens SHOULD implement this interface for ecosystem compatibility:Transfer and Approval events matching the platform token format.
When to Use Actor Tokens
SDK Usage
The Cowboy SDK provides a Pythonic wrapper:Worked example — tokens in a DEX: for a full deploy-token → seed-pool → swap → harvest-fees walkthrough with concrete amounts and expected balances, see CIP-21 §2.4 “Worked Example: CIP-20 token ↔ V2 pool”.
Security Considerations
Approval Race Condition
Theapprove function has a known race condition (inherited from ERC-20). If Alice approves Bob for 100, then changes to 50, Bob can front-run and spend 100 + 50.
Mitigation: Use increase_allowance / decrease_allowance patterns (not specified in this CIP but recommended for SDK).
Hook Security
- Gas limits: Hooks are capped at 50,000 Cycles and 50,000 Cells to prevent DoS
- No reentrancy: Hooks cannot trigger transfers of the same token
- Determinism: Hooks MUST be deterministic; non-deterministic hooks break consensus
- Upgrades: Changing the hook address affects all future transfers; use timelocks for critical tokens
Freeze Authority
Thefreeze_authority is a powerful privilege. For decentralized tokens, consider:
- Setting
freeze_authority = None(no freezing) - Using a multisig or governance contract as freeze authority
- Implementing timelock delays for freeze operations
Integer Handling
Python integers have arbitrary precision, preventing overflow. However:- Implementations MUST check
balance >= amountbefore transfers - Implementations MUST check
allowance >= amountbefore transferFrom - Implementations MUST check
total_supply + amount <= max_supplybefore minting - Independent of the per-token
max_supply,total_supplyis hard-capped at the protocol constantMAX_TOKEN_SUPPLY = 1e30 wei(node/types/src/constants.rs); create and mint reject any supply that would exceed it, so “None = unlimited” means “bounded only by the protocol cap”
Rationale
Why Not Dual-Mode?
Earlier drafts of CIP-20 proposed two parallel token standards (platform and actor). This was rejected because:- Ecosystem fragmentation: Every tool must support both types
- Developer confusion: Which mode should I use?
- Composability friction: Mixing token types in one protocol
Why Validation-Only Hooks?
Hooks that can modify transfer amounts (like Uniswap V4) add complexity:- Unpredictable final amounts
- Complex gas estimation
- Potential for hidden fees
- Transfer succeeds or fails, no surprises
- Gas is predictable (hook cost is bounded)
- Covers institutional requirements (pause, blacklist, KYC)
Why Not EVM Compatibility?
Cowboy is a Python-first chain. True ERC-20 compatibility would require running EVM bytecode, adding significant complexity. Instead, CIP-20 provides:- Familiar method names for Ethereum developers
- Similar mental model (balances, allowances, events)
- Canonical bridge for wrapping Cowboy tokens as ERC-20s on Ethereum (separate CIP)
Backwards Compatibility
This is a new standard. No backwards compatibility concerns.Reference Implementation
Seenode/execution/src/token/ (core.rs, admin.rs, query.rs, events.rs) for the Rust implementation of platform tokens.
See sdk/python/cowboy_sdk/token.py for the Python SDK wrapper.
