CellScript 0.25: More Expressive Contracts, Safer Upgrades, Stronger Verification
Short Announcement
CellScript 0.25 is out.
For contract authors, this release adds bounded non-Cell generics, Option<T>,
generic fixed arrays, full-range u128 literals, checked division and
remainder, bitwise and shift operators, recursive patterns, field-path borrows,
and labeled loop control.
For package maintainers, explicit public, public(package), and private
visibility now feeds a canonical package interface. cellc interface-diff
checks upgrades across source API, serialized layout, runtime ABI, effects,
builders, and deployment contracts.
For auditors, metadata schema 61 adds canonical typed semantics, and the
independent artifact checker binds that record through lowering to the final
RISC-V ELF with new V2419 and V2420 checks.
0.25 also fixes an unsafe bounded-collection lowering gap. Unsupported
consume_each and create_each paths now fail closed instead of compiling to
a false success. Positive runtime support remains deliberately deferred until
its consensus rules and adversarial CKB-VM evidence are complete.
For Contract Authors: More Reuse, Same Explicit Cell Ownership
Bounded generics for ordinary values
CellScript can now specialize generic value structs, enums, and pure functions
before IR lowering:
struct Pair<T: copy + drop + store + fixed + serializable + non_linear>
has copy, drop, store, fixed, serializable, non_linear
{
left: T,
right: T,
}
fn first<T: copy + drop + store + fixed + serializable + non_linear>(
pair: Pair<T>,
) -> T {
pair.left
}
The same checked path supports imported public templates. A package can use an
alias for a dependency and specialize its generic types or functions while the
specialization remains owned by the module that declared the template.
The boundary is intentionally narrow:
- generic instantiation is deterministic and budgeted;
- value abilities and phantom parameters are explicit;
- abilities such as
copy,drop, andstoredo not grant Cell lifecycle
authority; - ordinary generic containers cannot hide a
resource,shared, or other
Cell-backed value.
This gives users reusable value code without introducing an object runtime or
weakening CellScript’s linear ownership model.
Useful built-ins and complete fixed-width operations
0.25 adds or completes:
- built-in
Option<T>using the checked fixed-width generic enum path; - generic fixed arrays;
- decimal
u128literals across the fullu128range; - checked
u128division and remainder; - integer
&,|,^,<<, and>>lowering; - exact scalar and wide division-by-zero guards.
Wide operands now use a shared stack-spilled loading path, so resolving a
dynamic Molecule field cannot overwrite a live u128 limb. Constant folding
also refuses arithmetic that would wrap even though the runtime operation
would trap. Dynamic-schema CKB-VM vectors cover u128 addition, bitwise
operations, and shifts.
Patterns that work beyond the simplest case
match now supports recursive enum, tuple, and struct patterns, plus
binding-free or-patterns. Fixed tuple and array values can be materialized and
projected through the paths needed by nested payload matches.
Exhaustiveness checking uses a bounded constructor-matrix computation. Nested
and or-pattern coverage is merged instead of being approximated from the top
level, making useful matches accepted and incomplete ones rejected before
code generation.
Clearer borrowing and loop control
Read-only Cell views can borrow a field path and reborrow from the canonical
root. The compiler still rejects escaping the view, crossing a consume or
destroy operation, or using the borrow as persistent storage.
Loops now support break, continue, and label name: for/while. Valid
targets lower to explicit control-flow graph edges; an unknown or invalid
target is a compile-time error.
For Package Maintainers: Know What An Upgrade Changes
Top-level declarations can now be marked:
public
public(package)
private
Every successful compile emits a canonical
cellscript-package-interface-v2 record and interface_hash. Edition 2026
remains source compatible. If a module mixes explicit and implicit visibility,
the compiler emits W2500 instead of silently changing the default.
Generate an interface with:
cellc interface path/to/package --output target/package.interface.json
Compare two versions with:
cellc interface-diff \
--old target/old.interface.json \
--new target/new.interface.json
The report separates six kinds of compatibility:
- source API;
- serialized layout;
- runtime ABI;
- effects and capabilities;
- generated builders;
- deployment contracts.
A breaking report exits with stable diagnostic E2501. Additive exports still
change the interface hash, but they are reported as compatible.
Concrete monomorphizations are implementation evidence, not public exports.
Changing a private generic use site therefore does not create a public API
break. Registry publication signs and stores the canonical interface, the API
recomputes its hash and checks upgrade compatibility at admission, and the
standalone Registry verifier checks the stored binding again.
For Auditors: Follow Typed Intent To The Machine Artifact
0.24 introduced an independently checked four-file artifact bundle:
contract.elf
contract.elf.meta.json
contract.elf.lowering.json
contract.elf.sourcemap.json
0.25 moves that boundary closer to the programmer’s intent. Metadata schema 61
adds cellscript-typed-semantics-v2, covering:
- canonical types and layouts;
- locals and operations;
- control-flow blocks and calls;
- effects and ownership;
- borrow regions;
- owner-qualified generic instantiations.
Verified lowering record v3 accounts for each typed block and binds its
materialized hash to the entry ABI and final machine blocks. In plain language,
the evidence chain is:
typed program -> lowering blocks -> entry ABI -> final RISC-V machine ranges
The standalone cellscript-artifact-checker verifies that chain without
loading the parser, resolver, type checker, IR, optimizer, assembler, or code
generator. Its new stable rejection classes are:
V2419: malformed or inconsistent typed semantics;V2420: a broken typed-record, lowering, ABI, or machine binding.
Deterministic mutation tests cover both classes. This makes compiler drift and
artifact tampering easier to detect independently.
The claim remains precise: this is bounded structural and typed verification.
It is not a general proof of source-to-machine semantic equivalence, CKB-VM
execution, deployment, commitment, or mainnet acceptance.
One Registry For Every Executable Surface
0.25 adds a compiler-owned registry of the IR and runtime surfaces that can
reach an executable artifact. It generates both Markdown and JSON support
matrices and is exhaustively matched by the compiler.
That changes failure behavior in two important ways:
- a known but incomplete executable shape is rejected in strict production
compilation withE2105before ASM or ELF is written; - a new IR variant or runtime feature cannot silently bypass the registry—it
must be classified or compilation fails.
Fail-closed runtime helpers remain defense in depth. They are no longer used to
make an unsupported feature look production-ready.
An Important Safety Fix For Bounded Collections
During the 0.25 audit, we found a serious gap in consume_each and
create_each.
The frontend and ownership checker accepted the bounded operation, but IR
lowering replaced its body with Unit. That meant a body containing
require false could compile into an action that returned success without
scanning, checking, consuming, or creating anything.
0.25 removes that path:
- typed IR retains the predicate or create template;
- lowering inserts an explicit registered fail-closed call;
- permissive artifacts return stable runtime error 24,
collection-runtime-unsupported, in CKB-VM; --productionand--deny-fail-closedstop withE2105before producing
ASM or ELF;- the diagnostic names the operation, source location, missing ProofPlan tier,
and a concrete remediation; - entry ABI and ProofPlan metadata no longer claim supported pointers or
runtime-observed cardinality when no runtime scan exists.
This is a safety fix, not positive runtime support for bounded lifecycle
collections. The remaining work needs exact transaction-group selection,
canonical Cell and witness decoding, output order and one-to-one
correspondence, identity rules, capacity rules, and positive and adversarial
CKB-VM vectors. 0.25 does not invent those consensus semantics.
For Playground And VS Code Users
The browser Playground now understands the 0.25 authoring surface:
- generics, abilities, and visibility;
- bitwise and shift operators;
- recursive patterns;
- field-path borrows;
- labeled loop control.
The compiler returns a bounded authoring summary for the Cell Flow, action,
type, and raw-metadata panels. Full public-interface, typed-semantics,
ProofPlan, and verified-artifact records remain available through native
cellc and the VS Code workflow.
The browser compiler remains metadata-only and does not emit ELF. Omitting
native-only records and the optional browser semantic language service keeps
the default WASM bundle within its 600 KB gzip budget. The VS Code extension
retains full completion, hover, definition, and native-report workflows.
For CI And Local Development
Compiler caches and gate evidence now have bounded defaults:
- incremental caches keep the 32 most recently used identities per root;
- managed syntax, strict-backend, and CKB-acceptance streams keep three runs
per mode; - successful syntax audits discard reproducible per-case intermediates;
- production acceptance removes its transient Cargo target and stopped-node
database while retaining identifying reports and verified artifacts; - identical large files are hardlinked only after their SHA-256 identities
match; latest-<mode>.jsonrecords the exact report path, hash, size, and status;cellc clean --cachealso finds nested workspace cache roots.
Cleanup is confined to managed workspace and evidence roots. Symlinked managed
path components and non-regular cache payloads are rejected, cache entries are
created fresh rather than overwritten, and recency updates use create-new plus
rename. Operators can still override the retention bound for an external
archiver or an explicit debugging session.
Try CellScript 0.25
Install the exact release:
curl -fsSL \
https://github.com/CellScript-Labs/CellScript/releases/download/v0.25.0/install.sh | sh
cellc --version
For an existing package, start with the new review surfaces:
cellc explain generics path/to/package
cellc interface path/to/package --output target/package.interface.json
cellc check --target-profile ckb --all-targets --production
cellc build --target riscv64-elf --target-profile ckb --production
cellc verify-artifact build/main.elf --verify-sources --production
When preparing an upgrade, save the old and new interfaces and run
cellc interface-diff before publishing.