Install
cargo install --path .
Write Cell contracts as typed transitions, not raw wire format.
1module cellscript::fungible_token2// ... invariant and MintAuthority omitted3resource Token has store, create, consume, replace, burn, relock {4 amount: u64,5 symbol: [u8; 8],6}78action transfer_token(token: Token, to: Address) -> next_token: Token9where10 consume token11 create next_token = Token { amount: token.amount, symbol: token.symbol } with_lock(to)1213action burn(token: Token)14where15 assert(token.amount > 0, "cannot burn zero")16 destroy token
1module cellscript::nft2// ... constants and Metadata struct omitted3resource NFT has store, create, consume, replace, burn, relock, read_ref {4 token_id: u64,5 owner: Address,6 metadata_hash: Hash,7 royalty_recipient: Address,8 royalty_bps: u16,9}1011// ... listing and offer receipts omitted12action transfer(nft_before: NFT, to: Address) -> nft_after: NFT13where14 assert(nft_before.owner != to, "Cannot transfer to self")15 preserve nft_after from nft_before {16 token_id17 metadata_hash18 royalty_recipient19 royalty_bps20 }21 require nft_after.owner == to
1module cellscript::amm_pool2use cellscript::fungible_token::Token3// ... LPReceipt omitted4shared Pool has store, create, replace {5 token_a_symbol: [u8; 8],6 token_b_symbol: [u8; 8],7 reserve_a: u64,8 reserve_b: u64,9 total_lp: u64,10 fee_rate_bps: u16,11}1213action swap_a_for_b(pool_before: Pool, input: Token, min_output: u64, to: Address) -> (pool_after: Pool, token_out: Token)14where15 assert(input.symbol == pool_before.token_a_symbol, "wrong input token")16 let fee = input.amount * pool_before.fee_rate_bps as u64 / 1000017 let net_input = input.amount - fee18 let amount_out = pool_before.reserve_b * net_input / (pool_before.reserve_a + net_input)19 // ... preserve, require, consume, create omitted20 assert(amount_out >= min_output, "slippage exceeded")
1module cellscript::vesting2use cellscript::fungible_token::Token3// ... VestingConfig and VestingGrant fields omitted4flow VestingGrant.state {5 Granted -> Claimable;6 Granted -> FullyClaimed;7 Claimable -> FullyClaimed;8}910action claim_vested(grant: VestingGrant) -> (tokens: Token, updated_grant: VestingGrant)11 transition grant.state: Claimable -> updated_grant.state: FullyClaimed12where13 let now = env::current_timepoint()14 assert(now >= grant.cliff_timepoint, "cliff not reached")15 // ... vesting arithmetic omitted16 consume grant17 create tokens = Token { amount: claimable, symbol: grant.token_symbol } with_lock(grant.beneficiary)
cargo install --path .
cellc examples/token.cell --target riscv64-elf --target-profile ckb
cellc check --target-profile ckb
Syntax, types, effects
Typed model & assurance info
ckb-vm codegen & optimisations
RISC-V artefacts for ckb-vm
CellScript keeps the contract model visible: Cell shapes, effects, locks, flows, and review metadata stay in one typed surface.
Narrow by design: not a general-purpose runtime, not a new VM, not account storage in disguise.
Owned Cell state with explicit lifecycle effects.
// examples/token.cell
resource Token has store, create, consume, replace, burn, relock {
amount: u64,
symbol: [u8; 8],
} Shared state whose reads and replacements stay scheduler-visible.
// examples/amm_pool.cell
shared Pool has store, create, replace {
token_a_symbol: [u8; 8],
token_b_symbol: [u8; 8],
// ... reserves, LP supply, fee rate omitted
} Deferred proof Cells for listings, grants, proposals, and claims.
// examples/nft.cell
receipt Listing has create, consume, burn {
token_id: u64,
seller: Address,
price: u64,
// ... created_at and state omitted
} Transaction entry points with explicit consume/create/destroy effects.
// examples/vesting.cell
action claim_vested(grant: VestingGrant) -> (tokens: Token, updated_grant: VestingGrant)
transition grant.state: Claimable -> updated_grant.state: FullyClaimed
where
// ... timepoint checks and vesting arithmetic omitted
consume grant Boundary checks for protected Cells, script args, witnesses, and env reads.
// examples/language/canonical_style.cell
lock vault_owner(protected vault: Vault, lock_args owner: Address, witness claimed_owner: Address) -> bool {
let input = source::group_input(0)
let witness_lock = witness::lock(input)
// ... digest and ownership checks omitted
} Allowed state edges for Cells with lifecycle-dependent validity.
// examples/vesting.cell
flow VestingGrant.state {
Granted -> Claimable;
Granted -> FullyClaimed;
Claimable -> FullyClaimed;
} Scoped aggregate claims with trigger, scope, reads, and known gaps.
// examples/language/v0_15_scoped_invariant.cell
invariant token_amount_conservation {
trigger: type_group
scope: group
reads: group_inputs<Token>.amount, group_outputs<Token>.amount
assert_sum(group_outputs<Token>.amount) == assert_sum(group_inputs<Token>.amount)
} Typed support data for metadata records and finite protocol states.
// examples/nft.cell
struct Metadata {
name: String,
description: String,
image_uri: String,
attributes: Vec<(String, String)>,
} Type-id and field-keyed identity patterns for unique Cells.
// examples/language/v0_15_identity_lifecycle.cell
action mint_unique_nft(recipient: Address, tid: u64) -> UniqueNFT
where
create_unique<UniqueNFT>(identity = field(token_id)) { token_id: tid, owner: recipient } with_lock(recipient) A local build emits review metadata. Treat the sidecar as useful evidence, not an authenticated proof outside the build boundary.
current compiler metadata schema
shared + receipt + flow
validated; provenance required when shared
Use before review or integration.
OutputSchema, effects, source hashes, target profile.
cellc metadata examples/vesting.cell --target-profile ckb --json Use when checking builder obligations.
OutputInputs, outputs, proof branches, runtime requirements.
cellc constraints examples/vesting.cell --target-profile ckb Use before handing work to an auditor.
OutputSource, assumptions, metadata, ProofPlan.
cellc audit-bundle examples/token.cell --target-profile ckb --out audit/ Use while authoring .cell files.
OutputSyntax, diagnostics, and local language feedback.
cellc lsp End-to-end contract examples with Cells, actions, and constraints.
More ExamplesMint, transfer, burn, merge, and amount invariant.
Collection state, listing receipts, transfer, royalty payment.
Shared reserves, LP receipts, swap and liquidity actions.
Grant flow, timepoint checks, claim and revoke paths.
Launch state, settlement, and sale lifecycle.
Name ownership and registry-style state transitions.
Focused examples for locks, witness input, ownership, and capacity/time behaviour.
More ExamplesThreshold witness checks and signer validation.
Time-bound spend conditions over Cell state.
Protected inputs, lock args, witness fields, and digest checks.
Capacity-aware and timepoint-aware language surface.
Source and witness access patterns for boundary checks.
Delegated verification shape for reusable checks.
Language feature samples used to pin parser, lowering, and metadata behaviour.
More ExamplesType-id and field-keyed create/replace/destroy forms.
Aggregate assertions over type-group and group scope.
Order-style matching surface and state movement.
Registry shape used for language-level checks.
Hash helper usage through the language surface.
Larger benchmark-style protocol logic.