State changes are explicit
Actions say which Cells are consumed, created, replaced, burned, or relocked, so reviewers can follow transaction shape.
Describe CKB contracts as readable state changes. The compiler checks them, lowers them to on-chain artifacts, and keeps the metadata reviewers need — all from one source.
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: Token {9 verification10 consume token11 create next_token = Token { amount: token.amount, symbol: token.symbol } with_lock(to)12}1314action burn(token: Token) {15 verification16 require token.amount > 0, "cannot burn zero"17 destroy token18}
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: NFT {13 transition nft_before -> nft_after14 verification15 require nft_before.owner != to, "Cannot transfer to self"16 preserve nft_after from nft_before {17 token_id18 metadata_hash19 royalty_recipient20 royalty_bps21 }22 require nft_after.owner == to23}
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) {14 transition pool_before -> pool_after15 verification16 require input.symbol == pool_before.token_a_symbol, "wrong input token"17 let fee = input.amount * pool_before.fee_rate_bps as u64 / 1000018 let net_input = input.amount - fee19 let amount_out = pool_before.reserve_b * net_input / (pool_before.reserve_a + net_input)20 // ... preserve, require, consume, create omitted21 require amount_out >= min_output, "slippage exceeded"22}
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: FullyClaimed12 verification13 let now = env::current_timepoint()14 require 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)18}
CellScript is for teams that want CKB contract intent to stay readable while iteration stays fast enough to keep editing in flow.
Actions say which Cells are consumed, created, replaced, burned, or relocked, so reviewers can follow transaction shape.
Type, lifecycle, policy, and target checks run before generated code reaches a builder, deployment process, or VM harness.
The compiler emits metadata for actions, types, hashes, effects, and CKB warnings that tools and reviewers can read.
The homepage keeps the pipeline high level. Detailed language concepts, generated metadata, and registry policy belong in Docs and Registry flows.
Define Cell data, locks, and allowed transaction actions.
Catch invalid fields, state changes, and Cell lifecycles early.
Write JSON for actions, types, hashes, and policy checks.
Turn the checked model into ckb-vm RISC-V code.
Produce assembly or ELF plus matching metadata.
The Playground opens real example sources and compiles them in the browser. Test the contract shape first, then move to local CKB target builds.
Use the local compiler when you want the fast path from source to CKB target output plus inspectable metadata.
cargo install --path .
cellc examples/token.cell --target riscv64-elf --target-profile ckb
cellc check --target-profile ckb