[Looking for feedback] iCKB: a tokenization of NervosDAO deposits


Listenable Introduction

If you would like to listen to an introduction of the project before diving in, Jordan Mack explains iCKB in less than 7 minutes during an episode of Hashing it Out.


NervosDAO Illiquidity

The NervosDAO is possibly the most important smart-contract of Nervos Layer 1 (L1). A CKB holder can lock his CKB in the NervosDAO in exchange for a receipt of that specific deposit. Every 180 epochs (~30 days) the depositor has the option of exchanging his receipt to unlock his initial deposit plus accrued interest. This creates an illiquidity for the depositor while the CKB is locked.

Untapped Potential

There exists untapped potential in the Nervos ecosystem for a protocol that can liquify NervosDAO accrued interest and bridge it from L1 to L2. This protocol could enable CKB-based Initial Stake Pool Offerings (ISPO), where users can lock CKB to support new early stage projects without losing their original CKB deposit.

The protocol could also be used to enable a community voting mechanism with funds locked in the NervosDAO, as well as a multitude more L1 & L2 applications!

Looking far away, this protocol could also enable Godwoken switch from pCKB to a new native token that protects every Godwoken user from CKB issuance.

dCKB (Unmaintained)

In the past there has been an effort to tackle this challenge by NexisDAO with dCKB. Their approach is to tokenize the holder receipt, which in turn becomes tradeable and so the holder keeps being liquid. The issue with their approach is that only the original owner can unlock the deposit. Judging by their GitHub repository’s issues, dCKB does not appear to be actively maintained.


Enter iCKB

iCKB is the name for a SUDT token that represents deposits in the protocol. As with dCKB, iCKB’s approach is to tokenize NervosDAO receipts, but with a twist: the protocol owns all the CKB deposits and maintains a pool of them. This means that all the deposits and withdrawals are shared, so anyone can use anyone else’s deposit to exit once it’s mature.

This protocol aims to solve two problems with NervosDAO:

  • CKB locked in the NervosDAO remains liquid as iCKB can truly be used as a normal currency.
  • iCKB can be converted back to CKB quickly at any time without having to wait for maturity.

Water Mill Analogy

As a water mill has many distinct buckets, each at different wheel positions, in which the water is:

  • Collected
  • Maintained
  • Released

In the same way, the protocol can have many distinct deposits, each of them constantly moving at different stages of maturity:

  • Collected: Users deposit CKB and receive iCKB.
  • Maintained: Deposits accrue interest in the NervosDAO.
  • Released: If a user wants to exchange iCKB for CKB, they can use any deposit that is at maturity.


Jordan Mack’s comments on Nervos L1 & iCKB:

In a more abstract sense, this doesn’t violate any of intentions of the platform. The CKB that is staked is still out of circulation. iCKB does not grant the holder the ability to store data on the blockchain. In the most pure sense, iCKB is enabling the functionality that dCKB was trying to achieve. It better solves the problem because anyone can unlock the original CKB from the NervosDAO using iCKB instead of requiring the original owner to unlock it as with dCKB.



I’m the the ideas baker and solidity developer behind Opthy, 3° among peers at August 2021 Hackathon! Phroi as pseudonym exists since that Hackathon, here you can find the code I wrote in that occasion: core, tests and ui. Later on I continued working with Hexmate on Opthy until May 2022, when I left for becoming a solo Indie Hacker. Since then I’m working on a few projects under different pseudonyms.

Discovering iCKB

During February 2022, while testing the ground for a NervosDAO based ISPO, I discovered the untapped need for a token that liquefies and bridges interests from L1 to L2 and so with Jordan Macks’s help I started researching its feasibility.

Diving Into The Protocol

On-Chain, Trust-Less and Decentralized

This protocol defines a solid way to exchange between CKB and iCKB. The design aim is to make iCKB as simple, robust and neutral as possible, making it capable of meeting the current and future needs of Nervos users.

This protocol lives completely on Nervos Layer 1. Once deployed no entity have control over it, so it’s not upgradable.

It works by wrapping NervosDAO transactions: a deposit is first tracked by its protocol receipt and later on it’s converted in its equivalent amount of iCKB.

iCKB/CKB Exchange Rate Idea

The iCKB mechanism for wrapping interest is similar to Compound’s cTokens. The CKB to iCKB exchange rate is determined by block number. At the genesis block 1 CKB is equal to 1 iCKB. As time passes 1 CKB is slowly worth less than 1 iCKB at a rate that matches the issuance from the NervosDAO. This is because iCKB is gaining value. An easier way to understand this is to think of:

  • CKB as inflationary
  • iCKB as non-inflationary

Jordan Mack’s comment on this method:

That’s a clever approach. Thinking of it as iCKB being the base and CKB being what is moving makes it much easier to understand.

The inflation rate of CKB is well defined by the NervosDAO compensation rate and only depends on:

Therefore, the iCKB/CKB exchange rate will always be precise as determined by the formula and the current block. The only risk to this deterministic peg would be a smart contract exploit to the deposit pool or minting contract. These kinds of attack vectors are greatly mitigated by external audits.

iCKB-Equivalent Deposit Size

As in real life bricks can be used to build houses of any size, in the same way seems natural to establish a reasonably small standard deposit size that can be used to construct deposits of any size.

In this way a few goals are achieved:

  • Big deposits increase the overall protocol liquidity.
  • No size mismatch means anybody can use anybody else deposit to withdraw.

This deposit standard size could be defined in CKB terms or in iCKB terms:

  • Defining it in CKB terms means that as deposits are made in time, every deposit would have a different size due to the NervosDAO interests, so it’s not working as intended.
  • Defining it in iCKB terms means that at every block the standard deposit would have the same size both in CKB and iCKB. Of course as time passes, the deposit size would be fixed in iCKB-equivalent terms but gradually increasing in CKB terms.

Let’s define 10000 iCKB as the standard deposit size.

iCKB/CKB Exchange Rate Calculation

Excluding deposit cell occupied capacity, per definition 10000 iCKB are equal to 10000 CKB staked in NervosDAO at the genesis block, let’s calculate what this means.

From the last formula from NervosDAO RFC Calculation section:

Nervos DAO compensation can be calculated for any deposited cell. Assuming a Nervos DAO cell is deposited at block m, i.e. the deposit cell is included at block m. One initiates withdrawal and gets phase 1 withdrawing cell included at block n. The total capacity of the deposit cell is c_t, the occupied capacity for the deposit cell is c_o. […] The maximum withdrawable capacity one can get from this Nervos DAO input cell is:

( c_t - c_o ) * AR_n / AR_m + c_o

AR_n is defined in the NervosDAO RFC Calculation section:

CKB’s block header has a particular field named dao containing auxiliary information for Nervos DAO’s use. Specifically […] AR_i: the current accumulated rate at block i. AR_j / AR_i reflects the CKByte amount if one deposit 1 CKB to Nervos DAO at block i, and withdraw at block j.

Let’s fix a few constants:

  • c_o = 82 CKB (occupied cell capacity of a standard deposit cell)
  • c_t = 10082 CKB (total cell capacity equals the iCKB-equivalent deposit size plus its occupied capacity)
  • m = 0 (deposit block is the genesis block)
  • AR_m = AR_0 = 10 ^ 16 (genesis accumulated rate)

So at block n:
10000 iCKB = 10000 CKB * AR_n / 10 ^ 16 + 82 CKB

This shows that the iCKB/CKB exchange rate only depends on a few constants and AR_n, the block n accumulated rate.


In NervosDAO a CKB holder can lock his CKB in exchange for a NervosDAO receipt of that specific deposit in a single transaction.

In the proposed protocol a user cannot deposit to NervosDAO and mint iCKB in a single transaction due to a Nervos L1 technical choice: to mint the iCKB equivalent for a deposit the protocol needs to access the current accumulated rate, which is defined in the block header, but the current block header cannot be accessed while validating a transaction.

Thus the protocol is forced to split a deposit in two transactions:

  1. In the first transaction one or more CKB cells are transformed into NervosDAO standard deposit cells, locked by a protocol lock script. Each deposit cell is followed by either:
    • Another deposit cell with its exact same unoccupied CKB capacity.
    • A protocol receipt, which respectfully to the preceding contiguous deposits, just contains their count and single deposit unoccupied CKB capacity.
  2. In the second transaction receipts cells are transformed in iCKB. This is now possible because the header of the first transaction is now available.

This two step approach works around the header technical hurdle, but opens a Pandora Box: in the first transaction the protocol can’t invalidate non-standard deposits because it has no way to calculate their iCKB equivalent size.

On one side, even in an ideal world the original definition had a subtle flaw: the amount of CKB withdrawable from two standard deposit cells made at different blocks would likely never be the same down to the last bit, as the user making a deposit cannot forecast the actual inclusion block of the deposit transaction.

On the other, defining a standard deposit improves protocol liquidity and prevents a certain type of DoS, so this concept cannot be eliminated.

The solution is to add an incentivization structure:

  • Smaller deposits are disincentivized by CKB intrinsic dynamics: smaller deposits incur in bigger relative CKB expenses for cell creation.
  • Bigger deposits on the other side must be actively disincentivized by the protocol proportionally to the amount of iCKB per receipt exceeding a standard deposit.

A good way to disincentivize deposits bigger than the standard deposit size is to apply a fee: the user receives only 90% of the iCKB amount exceeding a standard deposit. The remaining 10% is offered as a discount to whoever is willing to withdraw from the oversized deposit.

Using this incentivization, only close approximations of Standard Deposits ultimately remain in the protocol deposit pool.


Withdrawals are a bit more complicated in NervosDAO, time is slotted in batches of 180 epochs depending on the initial deposit timing, so a withdrawal goes like this:

  1. With the first transaction the user requests the withdrawal.
  2. With the second transaction the user withdraws the deposit plus interests. Must be after the end of the 180 epoch batch in which the first transaction happened.

As seen in NervosDAO RFC Calculation section the actual withdrawn CKB amount depends on the deposit block and on the withdrawal request block.

The proposed protocol instead proceed by un-wrapping iCKB transactions into base NervosDAO transactions:

  1. With the first transaction the user sends to the protocol the equivalent amount of iCKB and chooses the specific deposits to withdraw from, while the protocol in turn requests to NervosDAO the withdrawal of these specific deposits, assigns them to the user and burns the received iCKB.
  2. With the second transaction the user withdraws the equivalent CKB amount. Same constraints as with the second NervosDAO transaction.


Once iCKB is deployed, it will enable:

  • CKB-based Initial Stake Pool Offerings.
  • The official Nervos DAO community voting mechanism.
  • Godwoken switch from pCKB to iCKB, protecting users from CKB issuance.
  • A multitude more L1 & L2 applications!

Useful Resources


This proposal is licensed under the terms of the Creative Commons Attribution Share Alike 4.0 International License.


Thanks for such a well-considered proposal.

Clever. A constant size requirement could save cell capacity management.

Each deposit has a constant size in iCKB but their CKB value would differ. Different amount of CKB is required on a deposit cell at different block height. But no matter which deposit cells a user chooses on withdrawal, the accrued interest he gets always equals to the amount he would get by depositing into NervosDAO directly.

It seems the core component of iCKB is completed? Do you have a plan to build a frontend and make it a dapp?

1 Like

Congratulations on being the first to comment!! :tada:

A constant size requirement could save cell capacity management.

That was the original idea before discovering in the hard way that Nervos L1 is Offchain Deterministic, so the protocol can’t refuse to validate non-standard deposits, but it can only disincentivize them, so we get close enough!

Ultimately putting this requirement enable higher fungibility and prevent the following form of DoS.

Let’s assume we don’t implement any requirement on deposit size, so as in NervosDAO users can choose the deposit size they prefer. Then an attacker who can borrow a big enough capital can simply attack by repeating the following two steps:

  • Deposit CKB for iCKB in deposits as big as the entirety of his capital.
  • Exchange iCKB for smaller CKB deposits.

This would greatly reduce the quality of the service for everyone, as the only remaining deposits would be as big or bigger than the attacker capital and since it’s impossible to withdraw partially from a NervosDAO deposit, this would greatly hamper the protocol fruition.

Each deposit has a constant size in iCKB but their CKB value would differ. Different amount of CKB is required on a deposit cell at different block height.


But no matter which deposit cells a user chooses on withdrawal, the accrued interest he gets always equals to the amount he would get by depositing into NervosDAO directly.

99.19% correct!! Before the occupied capacity per NervosDAO deposit was 102 CKB no matter the deposit size, in this protocol the occupied capacity is around 82 CKB every 10082 CKB, so this 0.81% (decreasing over time) of capital will not accrue interests, differently from directly using NervosDAO.

It seems the core component of iCKB is completed?

Sometimes I still wake up at night wondering… Jokes apart, right now is only a prototype, I’ll need to test it for good before anything else!!

Staying in the back-end side, I’m still in the process of evaluating if makes sense to aggregate transactions. Jordan and I already discussed multiple times the aggregation of transactions: he proposed the open transaction approach, while I proposed a Limit Order Lock.

While an open transaction approach would likely to miss the nominal 3-6 months deadline for iCKB deployment (by any means if anybody can prove me wrong, please do so!! :rofl: ), a Limit Order Lock could do the trick:

  • The user creates a new cell with this Lock, similar to ACP, but which specify an exchange rate between iCKB and CKB.
  • A service bot takes care of interacting directly with NervosDAO protocol

In this way:

  1. The service bot cannot adversely select intermediate representations like:
  • make overgrown deposits which incur in a 10% fee on the exceeding capital.
  • select deposits to withdraw from which have a far away maturity date.
  1. Since the service bot cannot assign intermediate representations to a Limit Order Lock, it needs to have a small capital that uses to operate, so it has skin in the game.

As fall back the user should always be able to interact with the protocol directly and the UI monitors the state of the transaction and its inputs.

Switching to the Godwoken back-end side, I want to bring depositing and withdrawing from iCKB protocol directly to Godwoken users by using a Balancer’s meta-stable pool coupled with a service bot that arbitrage differences between L1 and L2 iCKB/CKB exchange rate.

Do you have a plan to build a frontend and make it a dapp?

Yup that and possibly even integrate it directly in the Neuron Wallet!