Skip to content

Instantly share code, notes, and snippets.

@digitaldrreamer
Last active June 21, 2026 10:40
Show Gist options
  • Select an option

  • Save digitaldrreamer/382a99898a44f4b2db2266b5b5c1c9c6 to your computer and use it in GitHub Desktop.

Select an option

Save digitaldrreamer/382a99898a44f4b2db2266b5b5c1c9c6 to your computer and use it in GitHub Desktop.
The Self-enforcing Treasury: A New Financial Patternon CKB [FINAL]

The Self-Enforcing Treasury: A New Financial Pattern on CKB

There is a class of financial coordination problem that always comes back to the same wall: someone has to hold the keys.

Multisig helps. DAOs help. But at the end of the chain there is always a person — or a committee — whose cooperation you need to move money. Governance stalls. Keys get lost. Committees get captured. The whole thing devolves into "trust us, we're the committee."

I stumbled onto a different approach while building a governance system on CKB. I want to document it because it's more general than the thing I built it for — and because CKB makes it possible in a way that other chains don't.

The problem that forced the insight

CKB's storage model is explicit about costs. Every on-chain cell must hold capacity proportional to its byte size — typically 61 CKB or more just to exist. That capacity is locked for the life of the cell. When the cell is deleted, you get it back.

This is good design. It prevents state bloat by making storage economically bounded. But it creates a participation tax for any system that needs to create and rotate on-chain state regularly.

In my governance system, every proposal required creating an anchor cell on-chain. Someone had to front that capacity. If that someone was the proposer, I was asking governance participants to lock personal capital indefinitely for the public good. That's not a governance system. That's a donor programme with extra steps.

The question I kept coming back to was: whose money should this be, and why does it have to be anyone's in particular?


The insight

Instead of asking who controls the funds, ask under what conditions should capacity be allowed to move.

CKB type scripts are arbitrary programs that run every time a cell they govern appears in a transaction. A type script on a pool cell can inspect the entire transaction context — what inputs are present, what their type scripts say, what their data contains. You can write a rule: "this capacity may only leave if a specific kind of proof cell also appears in this transaction." No signature. No key. The condition is the authorization.

This is the self-enforcing treasury pattern:

Treasury cell   →   only spendable when a proof cell appears in the same TX
Proof cell      →   governed by its own type script that enforces the real conditions

No one controls the treasury. Anyone can trigger a valid spend. No one can trigger an invalid one.


The pattern

Three components, two transactions.

Treasury cells hold the pool. They are plain CKB cells locked by the treasury type script. Anyone can donate by sending capacity to the treasury address. The address encodes which proof type is authorised — nothing else.

Proof cells are the on-chain claims. Creating one requires satisfying whatever conditions the proof type script enforces: a valid payload, the right target, minimum capacity. The proof cell is the key.

The time constraint lives in CKB's native since field on transaction inputs. Setting it to a relative median-time-past (MTP) value means the transaction cannot be included by miners until that duration of real time has elapsed — enforced by every node independently, with no oracle, no contract-level timestamp check, no manipulation window.

The two transactions are simple:

Anchor TX (create proof):
  inputs:  [ treasury_cell ]          ← treasury type script runs, checks outputs
  outputs: [ proof_cell, treasury_change ]
  witnesses: [ "0x" ]                 ← no signature

Execute TX (consume proof, after delay):
  inputs:  [ proof_cell (since: Nh MTP), ... ]
  outputs: [ result_cell, treasury_change ]

In the anchor TX, the treasury type script scans the outputs looking for a valid proof cell. If it finds one, the spend is permitted. If not, rejected.

In the execute TX, the treasury type script scans the inputs looking for a proof cell being consumed. Once a valid proof cell appears as an input, the treasury knows the proof type script already validated all the conditions — because both scripts run against the same transaction in the same consensus evaluation. There is no inter-contract call, no return value to trust, no ordering dependency. Mutual validation in one atomic context.

Capacity that leaves the treasury for the proof cell returns when the proof is consumed. The system replenishes itself on every cycle, net of transaction fees.

graph LR
    D[Donate] -->|CKB| T[Treasury]
    T -->|Anchor TX\nno signature| P[Proof cell]
    P -->|Execute TX\nafter delay| R[Result]
    P -->|capacity - fee| T
Loading

Why CKB specifically

Three properties of CKB combine to make this clean. On other chains, you get one or two but not all three together.

The closest analogue is Ergo. Ergo's box model and ErgoScript allow scripts to inspect the full spending transaction — inputs, outputs, data fields — which is the same property that makes the treasury/proof mutual-validation work. Ergo's ZK Treasury (deployed 2020) lets groups authorize spending without a single controlling key, using composable sigma protocols. It is the right comparison and worth being precise about the gap: Ergo's sigma-protocol authorization still requires a cryptographically generated human artifact as a witness. The CKB pattern requires none — the proof cell is the authorization, not evidence that someone signed off on it. The other gap is property one below: Ergo has no explicit recoverable storage costs. The self-replenishing loop does not follow from Ergo's economic model the way it follows from CKB's.

Recoverable storage costs. Capacity flows out when state is created and back when it is deleted. The treasury replenishment on every cycle is not a clever trick — it is what the model naturally produces. On Ethereum, storage costs gas on write but there is no native concept of value that flows back when state is deleted.

Type scripts as transaction-level spending conditions. A type script on the treasury cell can inspect the full transaction without calling into another contract. Both the treasury script and the proof script run against the same transaction simultaneously — each independently validates the structure, and CKB consensus requires all of them to pass. This is what eliminates reentrancy risk and inter-contract trust.

Consensus-enforced time constraints. The since field is part of the CKB transaction wire format, not a smart contract feature. Miners physically cannot include a transaction whose since constraint has not been met. The delay is enforced at inclusion, not at application logic. Bitcoin has nSequence which is similar in principle, but Bitcoin's scripts cannot read cell data to construct dynamic spending conditions. Cardano's validity intervals are the closest equivalent, but Cardano's execution model requires every UTxO to be pre-declared, making the mutual-reference pattern between treasury and proof cells more cumbersome to wire up.


It works — the governance treasury

I deployed this in the CKB Transaction Firewall, a governance system for an on-chain blacklist registry. The treasury funds proposal anchor cells. Validators vote. After a 72-hour review window enforced by the since field, a threshold of validator signatures authorises execution. The anchor cell is consumed, the new registry cell is created, and the anchor capacity flows back to the treasury.

The treasury has been running on CKB testnet since May 2026. Each governance cycle costs approximately 1 CKB in transaction fees. Everything else returns.

The important property: no one needed to manage the treasury. No one was designated to pay for anchors. Anyone could create a proposal and the treasury funded it — as long as the proposal was valid.


The general form

The treasury type script and proof type script are independently parameterisable. Change the proof type and you get a different application. The treasury itself stays almost unchanged.

Application Proof conditions Time constraint
Governance treasury Valid proposal payload + committee signatures Review window
Crowdfund Contribution receipts + target amount Refund deadline
Vesting Beneficiary identity + cycle index Cliff and intervals
Bounty Hash preimage Optional deadline
Recurring salary Payroll cycle cell Period duration
Savings vault Owner key + balance target Maturity date

The pattern is: describe the conditions precisely, write them into a type script, and let the network enforce them.


Building it: a trustless crowdfund

A crowdfund with automatic refund is the clearest demonstration. The creator sets a target and a deadline. Contributions accumulate in a pool. If the target is reached, the creator claims — and anyone can trigger this, not just the creator. If the deadline passes without reaching the target, every contributor can reclaim their own funds individually. The creator has no special access at any stage.

This is three new type scripts: the pool, the contribution receipt, and the time-gated claim.

Pool cell

version(1) | creator_pubkey_hash(20) | target_shannons(8 LE) | deadline_ms(8 LE) | accumulated_shannons(8 LE)

The pool type script enforces two spending modes:

Successful claimaccumulated_shannons ≥ target_shannons, funds go to creator_pubkey_hash. Anyone can submit this transaction — the creator's lock address is readable from the pool cell data on-chain, so no cooperation from the creator is required to construct the output.

Refundsince field encodes time past deadline_ms (relative MTP, seconds on the wire multiplied by 1000 to compare against the millisecond deadline), contributor's receipt cell consumed in the same transaction, exactly contributed_shannons returns to the contributor.

Receipt cell

version(1) | pool_type_id(32) | contributor_pubkey_hash(20) | contributed_shannons(8 LE)

Created when someone contributes. Consumed when they claim a refund. Binds the contribution to a specific pool so receipts from one campaign cannot be used to claim from another.

One property of CKB's UTXO model worth noting: because accumulated_shannons is a mutable field in the pool cell, every contribution consumes the pool cell and recreates it. Contributions are therefore sequential — two contributors cannot contribute in the same block. This is a meaningful constraint for campaigns that receive concurrent interest. A frontend must serialize contributions, and under load, contributors will experience queuing delays. It is not a fundamental limitation of the pattern but it is a real implementation cost that a crowdfunding UX must address explicitly, not paper over.

The transaction structure

Contribute:
  inputs:  [ contributor_wallet_cell ]
  outputs: [ pool_cell (updated), receipt_cell, contributor_change ]

Claim (success):
  inputs:  [ pool_cell ]
  outputs: [ creator_wallet_cell ]

Refund (deadline passed):
  inputs:  [ pool_cell (since: past deadline), receipt_cell ]
  outputs: [ pool_cell (updated), contributor_wallet_cell ]
graph TD
    C1[Contributor 1] -->|CKB + receipt| P[Pool]
    C2[Contributor 2] -->|CKB + receipt| P
    C3[Contributor 3] -->|CKB + receipt| P
    P --> Q{Target reached?}
    Q -->|Yes| S[Creator claims\nanyone can trigger]
    Q -->|No — deadline passed| R[Each contributor\nreclaims via receipt]
    style S fill:#2D6B3F,color:#fff
    style R fill:#B97B0F,color:#fff
Loading

What this changes

On any existing crowdfund platform, the platform holds the money and enforces the rules. The rules are contractual, not technical. In this system the type scripts are the platform — enforced by every CKB node independently, with no company to lobby, no terms of service to dispute, and no platform fee beyond the CKB transaction fee.

The creator cannot take funds before the target is met. The contract rejects the transaction. A contributor cannot block a successful claim. The contract permits it regardless. These are not policies. They are the consensus rules of the chain.


What this unlocks

The self-enforcing treasury is a pattern built on CKB's primitives — type scripts, cells, the since field. The pattern is what is new, not the underlying tools. The governance system that produced it uses it to fund proposals without a privileged payer. The crowdfund uses it to hold pooled contributions without a privileged custodian. The mechanics are the same.

The underlying reason goes back to the cell model. On CKB, "holding value in a contract" and "paying for on-chain storage" are the same operation. Capacity is not a metaphor for value — it is value, and it flows back when storage is released. This means the economic incentives and the technical rules are expressed in the same terms. There is no separate incentive layer that needs to be kept in sync with the protocol. The protocol is the incentive layer.

That property is what makes the conditions you write into type scripts so powerful. Within the real constraints — sequential UTXO contention under concurrent load, script execution costs, the permanence of bugs in deployed type scripts — the ceiling on what you can build is set less by what the VM can do than by how precisely you can describe the conditions under which capacity should move.


The CKB Transaction Firewall — the governance system that produced the treasury pattern — is at github.com/digitaldrreamer/ckb-transaction-firewall. The crowdfund implementation is in progress.

@digitaldrreamer

digitaldrreamer commented Jun 12, 2026

Copy link
Copy Markdown
Author

Research Notes — Comparative Landscape (June 2026)

These are notes on whether anything comparable to the Self-enforcing Treasury pattern described here has been built before. Short answer: not in this combination, and not on a live system.


What was searched

  • Autonomous / keyless treasury patterns across blockchain ecosystems
  • Bitcoin covenant proposals (CTV, OP_VAULT, OP_CAT)
  • Cardano eUTXO / Plutus validator treasury patterns
  • Ergo box model / ErgoScript / ZK Treasury
  • Ethereum DAO treasury (Governor + Timelock + Safe)
  • Academic literature on UTXO-based condition spending and proof-conditional treasuries
  • CKB since field as consensus-enforced time primitive

The closest prior art

Bitcoin covenants (CTV / OP_VAULT / OP_CAT)

Closest in spirit. OP_CHECKTEMPLATEVERIFY lets a UTXO commit to a specific spending transaction structure without a signature. OP_VAULT adds a mandatory delay before funds can move — conceptually similar to the since field usage here.

Gap: Not deployed (still proposals as of mid-2026). More importantly, Bitcoin scripts cannot read cell data to construct dynamic spending conditions. CTV commits to a fixed transaction template; it cannot inspect a proof cell's payload, validate a receipt, or enforce arbitrary logical conditions. The expressiveness gap is large. Also, Bitcoin has no concept of recoverable storage costs — the self-replenishing treasury loop has no analogue.

References:

Ergo (ErgoScript / eUTXO box model)

Technically the closest chain overall. ErgoScript is Turing-limited (by design) but can inspect the full spending transaction — inputs, outputs, data fields — which is the same property that makes the treasury/proof mutual-validation work on CKB. Ergo also has a ZK Treasury concept (announced 2020) where groups authorize spending using composable sigma protocols (ring signatures) without a single controlling key.

Gap: Ergo's ZK Treasury still requires a cryptographically generated human artifact (a ring signature or sigma proof) as the authorization mechanism. The CKB pattern eliminates that layer: the proof cell is the authorization, governed purely by a type script. No human needs to generate a cryptographic witness. Additionally, Ergo does not have CKB's explicit recoverable storage costs — the self-replenishing loop (capacity out on proof creation → capacity in on proof consumption, net fees only) is a direct product of CKB's capacity model. Ergo has no equivalent economic mechanic.

References:

Cardano (Plutus / eUTXO)

The document already notes this. Plutus validators can inspect transaction inputs and outputs and enforce complex spending conditions. The execution model is semantically similar.

Gap: Cardano requires every UTXO being referenced to be pre-declared in the transaction. Wiring up mutual-reference patterns — where treasury validator and proof validator simultaneously validate each other against the same transaction — is architecturally more cumbersome. No native consensus-enforced time constraint equivalent to CKB's since field exists; time logic must go through validity intervals with off-chain coordination. No recoverable storage cost model.

References:

Ethereum DAOs (Governor + Timelock + Safe)

Standard infrastructure for on-chain treasuries. Governor contract, Timelock, Safe multisig, module ecosystems (Allowance, Zodiac, etc.).

Gap: Always terminates in a human-controlled key or multisig. The Timelock queues transactions but requires a proposer with authority to queue them. The committee/key problem described in the opening of this document is precisely what Ethereum DAO tooling cannot escape. No UTXO model, no recoverable storage, no mutual transaction-level validation. Reentrancy is a live concern in inter-contract calls.

References:

Academic literature

A 2024 paper (arXiv:2406.07700) specifically addresses scalable UTXO smart contracts via fine-grained distributed state and evaluates crowdfund, registry, and multisig wallet contracts in UTXO-based models — noting that UTXO-based models face specific attack surfaces (adversarial output injection) not present in account-based models. No prior work found describing the specific treasury+proof mutual-validation pattern or the capacity-recovery loop.


What is genuinely novel in the combination

Three properties combine that have not been combined on a live system:

1. Condition-as-authorization with no cryptographic artifact.
The proof cell is the key. Anyone who constructs a valid proof cell (per the type script rules) can trigger a treasury spend. Nobody can without one. There is no private key path to the funds at all. This is not "keyless" in the MPC/TSS wallet sense (which still uses cryptographic key shares). The authorization is purely structural/logical.

2. The self-replenishing economic loop.
On CKB, value and storage are the same concept. Capacity that leaves the treasury to create a proof cell returns when the proof cell is consumed. Net cost per cycle = transaction fees only. This isn't a design trick — it's what the model naturally produces. No other major chain has this property in the same form.

3. Simultaneous mutual validation without inter-contract calls.
The treasury type script and proof type script run against the same transaction in the same consensus evaluation — neither calls the other, neither trusts a return value. No reentrancy surface exists. The mutual guarantee emerges from the CKB execution model. This is structurally different from Ethereum (msg.call, delegatecall) and from Cardano (each validator is local to its UTxO, requiring explicit reference input wiring).


Honest qualifications

  • Ergo is the narrowest gap. If you have read this document and know ErgoScript well, Ergo is where you'd look for the closest prior art. The ZK Treasury is sophisticated; the main delta is that it still uses sigma-protocol authorization and lacks the capacity recovery loop.
  • The pattern isn't deployed yet (as of the time of writing); it's been prototyped on CKB testnet within the Transaction Firewall governance system. The crowdfund implementation referenced at the end is in progress.
  • The "no one controls it" property applies to the operational layer. Whoever deploys the type scripts sets the rules. Trustlessness is about ongoing operation, not inception.
  • If Bitcoin gets OP_CAT + full transaction introspection, a significant subset of this pattern becomes expressible on Bitcoin — but the capacity recovery loop would still be absent.

Notes compiled June 2026. Searches covered: Bitcoin covenant proposals, Ergo ZK Treasury, Cardano Plutus eUTXO, Ethereum DAO infrastructure, CKB type script documentation, UTXO smart contract academic literature.

@digitaldrreamer

Copy link
Copy Markdown
Author

This is a great initiative. So far, I have a few questions I think the read doesn't answer. Formal specification of financial conditions is hard, and the cost of getting it wrong is permanent and unrecoverable. The piece gestures at power without sitting with that weight. This sounds fun, yeah.

If the proof type script has a bug, there's no key to rotate and no owner to fix it. The piece's "no one controls it" property becomes a liability the moment there's a logic error. 🤔🤔

You should do some more good researches and get building. I'm rooting for you.

@RobaireTH, you have a point.

The answer is that the mitigation is the same as it is anywhere in smart contract development: you do formal specification, thorough testing, and testnet deployment before any mainnet funds go in. The governance system (and your Pckt project) has been running on testnet specifically for this same reason: to surface logic errors before you use mainnet funds.

You're right that "no one controls it", but it goes both ways. The same property that removes the trusted party also removes the escape hatch. On Ethereum you can build in an upgrade proxy or an owner pause, but here, any post-deployment recovery mechanism reintroduces a trusted party and undermines the point of using the pattern. So the risk isn't different in kind from any immutable contract, but it's that the pre-deployment diligence bar is higher in degree, because there's less you can do after the fact. In short, one needs to be careful before deploying to mainnet.

I suppose its a real point to address, and the document should probably say it more directly than it does. The permanence of bugs is the cost of the trustlessness. The response to that cost is to not deploy underbaked scripts, because the pattern is only worth building because the diligence goes one-time into the scripts, and there's no ongoing trust management/maintenance. At the very least the energy that would have been used in multisig and runtime maintenance can be applied to the scripts instead.

@digitaldrreamer

Copy link
Copy Markdown
Author

I further abstracted the pattern into a more reusable pattern (Structural Authorization), basically to demonstrate how to build autonomous economic coordination without custodians. See https://github.com/digitaldrreamer/ckb-structural-authorization

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment