Skip to content

How to Deploy and Seed the Treasury

The treasury is not a separate account. It is an autonomous contract whose spending rules are defined by exactly which contracts govern your registry.

The treasury-lock args encode two Type IDs:

treasury-lock args = governance_lock_type_id (32 bytes)
| proposal_anchor_type_id (32 bytes)

These are the same governance_lock_type_id and proposal_anchor_type_id that you deployed in Step 1. The treasury-lock contract only permits spending when the transaction creates a valid proposal-anchor cell (typed by the matching proposal-anchor contract) or returns change to itself after a governance update. Any transaction that does not satisfy these rules cannot consume treasury funds.

The bootstrap script stores the treasury lock script (the full code_hash, hash_type, args needed to reconstruct the treasury address) inside the registry cell’s governance header. This means the CLI, the GUI, and the SDK automatically discover the treasury address by reading the registry cell — no out-of-band configuration is needed.

The bootstrap creates the treasury automatically

Section titled “The bootstrap creates the treasury automatically”

When you run the bootstrap script (Step 2 of the operator tutorial), it creates two cells in a single transaction:

  • Output 0 — the registry cell (BLKL v2 payload with a v3 governance header that embeds the treasury lock script)
  • Output 1 — the initial treasury seed cell (locked to the treasury address)

You do not need to deploy the treasury-lock separately or send a separate seeding transaction. The bootstrap records the treasury address in the governance header and creates the first treasury pool cell in the same on-chain operation.

After the bootstrap transaction is confirmed, running ckb-firewall inspect will show the treasury pool balance:

Terminal window
ckb-firewall inspect \
--rpc-url https://testnet.ckb.dev \
--registry-tx <bootstrap tx hash> \
--registry-index 0

Expected output includes:

Treasury pool: 100,000.0 CKB (available)
Donation address: ckt1...

If the pool drops below the 70% warning threshold or runs dry, any CKB holder can top it up by sending to the treasury address shown in inspect or the GUI:

Terminal window
ckb-cli --url https://testnet.ckb.dev wallet transfer \
--to-address <treasury address from inspect> \
--capacity <amount> \
--fee-rate 1000

10,000 CKB covers roughly 33 proposal anchor operations (each anchor costs ~300 CKB, returned after execute or reclaim). A higher seed is recommended for active registries.

If you need to deploy the treasury-lock binary separately

Section titled “If you need to deploy the treasury-lock binary separately”

This applies only if you are deploying a private registry without using the provided bootstrap script (for example, building your own bootstrap tooling).

Deploy the treasury-lock binary as a CKB data cell:

Terminal window
ckb-cli --url https://testnet.ckb.dev wallet transfer \
--to-address <YOUR_CKT1_ADDRESS> \
--capacity 17000 \
--to-data <treasury-lock-binary-hex> \
--fee-rate 1000

Record the tx_hash:index of the resulting cell — this is your TREASURY_LOCK_DEP.

Then pass the treasury-lock’s code hash and your contract Type IDs to your bootstrap transaction builder so it can:

  1. Compute the treasury address (hash_type = data1, args = governance_lock_type_id | proposal_anchor_type_id)
  2. Embed the full treasury lock script in the registry cell’s v3 governance header
  3. Create a treasury seed cell at the treasury address in the same bootstrap transaction
Terminal window
ckb-firewall inspect \
--registry-tx <bootstrap tx hash> \
--registry-index 0

When pool usage reaches 70%, inspect and the GUI warn and display the donation address prominently.