I’ve spent the recent CellScript releases working on the less visible parts of contract development: resource ownership, transaction bindings, generated verifiers, build reproducibility, and making sure the compiler’s promises survive actual CKB-VM execution.
As the syntax and core semantics settle down, I am now thinking about to put those foundations to work on a much larger application problem: making advanced, composable DeFi practical to build directly on CKB.
The tentative timeframe is late 2026 to Q1 2027, broadly around the CellScript 0.40–0.50 release series, with the aim of delivering a developer-facing capability set comparable in breadth to that of modern DeFi systems such as Uniswap v4: concentrated liquidity, programmable pool behaviour, custom fees and accounting, and multi-operation settlement.
One principle behind the whole roadmap
DeFi belongs in protocol packages, not in the CellScript compiler.
A Pool, Order, Position, or Hook should be an ordinary type defined by its author. Fees, swap formulas, LP issuance, order pricing and settlement rules are application logic. CellScript’s job is to provide sound ownership rules, checked arithmetic, typed transaction access, precise external Script identities, predictable compilation and usable builders.
This matters on CKB. A transaction can contain multiple independently verified Lock and Type Script groups, but the VM does not offer Ethereum-style synchronous contract calls or shared mutable contract storage. We need to work with the Cell model: verify the whole transaction, bind the actual Cells being spent and created, and make any temporary accounting explicit.
The objective is comparable financial functionality, not EVM bytecode or Solidity compatibility. I would rather ship a CKB-native implementation with clearly documented differences than claim compatibility that only exists in a diagram.
Roadmap at a glance
This is the tree of work. The dependency graph further below shows how the individual issues connect and in what order they can be delivered.
flowchart TB
ROOT["#43 — Composable finance on CKB"]
ROOT --> LANG["General language and runtime"]
ROOT --> BASE["Basic financial protocols"]
ROOT --> RANGE["Range liquidity and pool execution"]
ROOT --> ACCOUNT["Multi-operation asset accounting"]
ROOT --> EXT["Extensible pool behaviour"]
ROOT --> OBS["Time and price observations"]
ROOT --> DX["Developer workflows"]
ROOT --> TEST["Independent evidence"]
LANG --> L1["#49 Cell selection · #48 Nested ABI · #47 Collections"]
LANG --> L2["#28 Compatible handles · #29 Open roles"]
BASE --> B1["#52–#55 Pools, custody, LP, maths, builders"]
BASE --> B2["#56–#60 Orders, settlement, recovery, reproduction"]
RANGE --> R1["#61–#65 Pool identity, ticks, positions, cross-tick swaps"]
ACCOUNT --> A1["#66–#68 Ordered deltas, backed claims, native CKB"]
EXT --> X1["#69–#71 Hooks, fee policy, custom accounting"]
OBS --> O1["#72–#73 Time guarantees and historical prices"]
DX --> D1["#74–#77 Positions, routing, intents, indexers"]
TEST --> T1["#78–#79 Outside developers and solvency tests"]
There are two distinct kinds of work here. The language/runtime issues help any CellScript application. The FIN issues exercise those capabilities through specific, independently checkable financial protocols. Neither track should quietly absorb the other’s responsibilities.
1. Language and runtime foundations
These are open, general-purpose workstreams. They make complicated transactions easier to express without weakening what an emitted Script actually verifies.
| Issue | Work | Why a DeFi developer would care |
|---|---|---|
| #49 — Heterogeneous Cell selection | Select and match bounded Cells across different Script identities, with complete input/output correspondence. | A swap or batch settlement may touch different assets and independently governed state Cells. The verifier must know which ones are part of the operation and which are unrelated. |
| #48 — Nested dynamic ABI | Canonical, bounded decoding of nested values and variable-length records. | Richer batch plans and protocol payloads should not require ad hoc byte parsing or trust a builder’s encoding. |
| #47 — Bounded collections | Deterministic verifier-local Vec, Map and Set support within fixed resource limits. |
Useful for aggregation, duplicate detection and temporary accounting during a transaction. This is not persistent pool storage. |
| #28 — Compatible-open handles | Select an implementation through a verified interface, artifact and deployment policy. | A protocol can admit a compatible external component without trusting a package name alone. |
| #29 — Open cross-Script roles | Bind selected participants and their Script roles into one checked transaction. | A pool, token or verifier can be selected at construction time while retaining explicit identity and authority boundaries. |
Some of the hardest foundations are already present: bounded Cell lifecycle operations, typed transaction views, exact Script handles and ProtocolBundle give us a starting point. Open issues extend that accepted surface; they do not mean every subsequent application is already supported.
I don’t want to make #47–#49 or #28–#29 mandatory gates for every pool. An exact-deployment pool should be able to ship on its own terms. More general capabilities enter when a concrete transaction needs them.
2. Basic pools, orders and settlement
The first financial milestone is deliberately conventional: a real pool, holding real assets, with verifiable LP accounting. That sounds simple, but there is an important difference between checking a swap formula and protecting the funds behind it.
In the existing examples, a pool action can express reserves, fees and liquidity changes. The new programme requires the full asset lifecycle: a reserve cannot be spent without an authentic matching pool transition, LP shares cannot be forged or destroyed outside their authorised supply rules, and the generated builder must construct a transaction that passes all participating Script groups.
| Issues | Deliverable |
|---|---|
| #52 + #53 | Authentic custody, asset and LP identities, checked wide arithmetic and independently modelled rounding. |
| #54 + #55 | Complete constant-product pool and LP lifecycle, both trade directions, generated builders and a second pool reproduced by another developer. |
| #56 + #57 | Escrowed orders that support partial fills and cancellation, then settlement against a genuine pool. This is not a complete central-limit-order-book matcher. |
| #58 | Bounded multi-pool routing and separately authenticated shared-payment allocations. Pure pool routing does not depend on the order work. |
| #59 + #60 | Stale-state recovery, contention/cost measurements and independent reproduction using the documented SDK. |
One test I care about is intentionally bypassing our own builder. If someone assembles a raw transaction that spends the reserves but omits the pool transition, the on-chain policy should reject it. A successful happy-path transaction isn’t sufficient evidence.
3. Concentrated liquidity: from reserves to price ranges
A constant-product pool treats liquidity as one shared reserve curve. Concentrated liquidity lets a provider allocate liquidity to selected price ranges. That changes the state-management problem substantially: each trade may move through several ranges, and each position earns fees according to where liquidity was active.
| Issues | Work |
|---|---|
| #61 | Canonical pool identities, permissionless creation for admitted configurations, and reusable state layout. |
| #62 | Tick, square-root-price, liquidity and precisely rounded swap-step mathematics. |
| #63 | Authenticated sparse tick indexes and complete next-boundary proofs. |
| #64 | Range positions, changes in active liquidity, fee growth and donations. |
| #65 | Bounded cross-tick swaps, exact-input and exact-output amounts, price limits and genuine final state. |
#63 is an especially interesting CKB problem. Suppose a builder supplies tick 100 and tick 120, but an initialised tick exists at 110. Checking that 100 and 120 are valid Cells doesn’t prove they are the next relevant boundaries. The verifier must also prove the absence of the omitted tick. We need authenticated sparse state, not merely a list supplied by the transaction creator.
A transaction may have a measured upper bound on how many ticks it crosses. That should not turn into an arbitrary cap on how many positions the pool can hold over its lifetime.
4. Multi-operation accounting, claims and native CKB
More complex trading requires accounting for several operations before producing the final transaction outputs. For example, a user might remove liquidity, swap part of the proceeds, then deposit into another position.
There is no reason to model that as an EVM-style nested call stack. On CKB we can validate an ordered logical transition and its final authenticated Cells, provided the intermediate values and obligations are completely checked.
| Issues | Work |
|---|---|
| #66 | Ordered operation batches with explicit per-user, per-asset debits and credits; all outstanding obligations must settle. |
| #67 | Transferable claims backed by real custody balances, with correct redemption and no double counting. These claims are distinct from LP positions. |
| #68 | Native CKB trading, separating tradeable CKB, occupied Cell capacity, refunds and transaction fees. |
The important accounting question is straightforward: who owns each amount before and after the operation, and what backs every claim? A credit belonging to Alice cannot silently pay Bob’s debt. Native CKB kept alive as storage capacity cannot simultaneously be sold as available liquidity.
5. Hooks, fee policy and custom accounting
This is where I want CellScript to become genuinely useful for people building their own market mechanisms.
A hook should be an independently authored protocol component, with declared entry points and permissions. A pool can require it to run before or after selected operations. Its actual result must be bound to the correct operation and checked on chain. Merely recording a hook’s code hash is not evidence that the hook executed.
| Issues | Work |
|---|---|
| #69 | Authenticated before/after lifecycle hooks, executable return-value contracts and strict permissions. |
| #70 | Separate LP fees, protocol fees, dynamic fee updates and extension charges, with clear ownership and authority. |
| #71 | Permissioned balance adjustments and alternative pricing curves, subject to complete asset settlement. |
CKB Script groups validate a transaction independently. They don’t synchronously call one another. Hook execution and logical order need their own enforceable design, potentially using exact external verifier execution and authenticated state transitions. That’s one of the first interfaces I want to prototype rather than leave as a promise at the end.
I’m particularly interested in what an outside developer can do with this: a custom fee model, a permissioned liquidity pool, a different pricing curve, or a protocol that issues a persistent order instead of completing an immediate swap. Those examples should be possible without editing the compiler.
6. Time, observations and the developer experience
A sophisticated pool also needs reliable historical data and a practical way for users to interact with positions.
| Issues | Work |
|---|---|
| #72 | Establish which expiry, time and freshness claims are genuinely enforceable under CKB’s available chain context. |
| #73 | Optional authenticated price observations and time-weighted queries, with explicit missing-history and stale-data handling. |
| #74 | Position creation, updates, transfers, fee collection and non-custodial subscriptions. |
| #75 | Bounded command plans for swaps, liquidity changes, settlement and authorised migrations. |
| #76 | Scoped signed intents, delegation, nonces, revocation and replay protection. |
| #77 | State indexing, extension-aware quotes, route discovery and generated client workflows. |
Time is one area where we have to be careful. A historical header isn’t necessarily proof of the current time, and a wallet timeout is not automatically an on-chain expiration rule. Where the chain cannot enforce an exact guarantee, the SDK needs to say so. The same goes for quoting a pool with an extension whose financial effects the SDK cannot evaluate.
7. What counts as done
There is a difference between a feature compiling, an isolated verifier accepting a fixture, and an application that another developer can use safely.
For this roadmap, I’m looking for three kinds of evidence:
Financial correctness. Real pool reserves and positions must obey their ownership and accounting rules. A malformed transaction should fail even if it bypasses our builder. Cross-tick swaps must not skip a live price boundary. No two obligations may claim the same payment; no claim may be issued without backing; no hook may exceed its declared authority.
Complete transaction execution. The tests must run the relevant Lock and Type Script groups against the same final transaction, with exact executable and CellDep identities. CKB-VM cycles, witness sizes, occupied capacity and the behaviour under contention all matter. Where recovery is needed, the builder must preserve the user’s signed limits rather than silently relax them.
Developer reproducibility. Someone outside the implementation work should be able to instantiate a new pool, manage positions and build at least one meaningful third-party hook from the public packages and generated SDK—without touching CellScript codegen or replacing compiler-generated verifier bytes.
#78 tracks the independent extension work. #79 starts the continuous differential and solvency testing early. These are not ceremonial final checkboxes; they are how we find out whether the earlier layers actually compose.
This also sets an honest limit on the claim. Functional coverage does not prove identical EVM execution, all possible hook behaviour, a completed independent security audit, mainnet readiness or sufficient liquidity. Those require their own evidence and decisions.