Decentralized exchanges, or DEXs, have become increasingly popular recently, as users are skipping centralized platforms in favor of permissionless, trustless and composable alternatives. While Ethereum continues to be the blockchain of choice with popular offerings such as Uniswap, Curve, and Balancer, gas prices have risen dramatically over the last few months, which has negatively impacted users.
Many users are coming to the realization that they are spending an increasing portion of their holdings ensuring transactions get confirmed, while others no longer have a way of interacting with DeFi products that makes sense financially.
The sentiment of “when Layer 2?” is being mentioned with increasing urgency in the community, but fortunately Nervos has been designed with an ideal architecture to support a scalable Layer 2 DEX, which can bring sustainable transaction fees and predictable confirmation times. You can read more about the design philosophy and layered architecture of Nervos in the positioning paper.
In this article, we’ll share details about the two types of Layer 2 DEXs you can design on Nervos, but first, let’s outline the different categories of DEX infrastructure.
The DEX possibilities on CKB
With the evolution of DeFi and on-chain exchange services, we can divide a DEX as an infrastructure into several broad types at present. One is the orderbook type, represented by Etherdelta and 0x, which can be further subdivided into on-chain and off-chain order matching. The second is the AMM type represented by Uniswap, which provides infinite depth by automatically setting the price through a mathematical equation. The third is the market maker type represented by Kyber, which automatically quotes the best prices from several external reserve pools.
The unifying feature of all three models is that the user’s assets are self-custodied, as there is no trust placed in the service provider. As a result, DEXs are substantially safer than traditional centralized exchanges. More recently, with the development of rollup technology, attempts have been made to use this technology and its improvements, zk-rollup and optimistic rollup, to optimize DEXs. This is accomplished by introducing an off-chain aggregator that clears large numbers of trades off-chain and then settles them periodically on Layer 1. This approach also significantly improves Layer 1 transaction throughput and reduces the average cost of transactions.
The Cell model adopted on CKB is very different from the account model on Ethereum in terms of product and protocol design, which poses a challenge to the implementation of a DEX on CKB. However, rollup uses an off-chain aggregation/on-chain settlement model, which only needs to verify that the off-chain clearing results are correct rather than continually updating user account state through transactions. The rollup model is very much in line with the business logic of CKB, so in this article we’ll discuss the design of a CKB DEX based on a Layer 2 Order Aggregation Model.
Basic business processes
Deposit & Withdrawal
In deposit, the user delegates the right to operate an asset to the DEX contract. This operation can be compared to the deposit process of a traditional centralized exchange, but the asset is non-custodial, which means the ownership of the asset remains with the user.
In the deposit process, the user authorizes a contract to manage his assets and generates an Account Cell that records the deposited assets. The logic of the Account Cell is insured by the corresponding DEX clearing type script, which records the user’s public key hash used to authenticate actions. It also allows the contract to modify its balance according to the predefined rules.
The Data field of the Account Cell records the balance of the user’s various assets, and depending on the type of DEX, the user’s order book may also be stored here.
The withdrawal operation is the reverse of the deposit operation. In this process, the user combines their Account Cell with one or more Deposit Cells and generates one or more Asset Cells. There is one situation that needs to be noted here. If the user has not ended their business in the Layer 2 aggregator, the aggregator may send an aggregated transaction that references the user’s Account Cell, however, this Account Cell may also be referenced by a withdrawal transaction. To prevent this from happening, we need to impose additional restrictions on withdrawals. For example, the user needs to announce a pre-withdrawal cell before a formal withdrawal. A formal withdrawal needs to reference this pre-withdrawal cell, and if the aggregator sees this pre-withdrawal cell, it will automatically exclude the user’s Account Cell from the state.
Transaction order and matchmaking
We refer to the user’s Account Cell as the initial state, and for an AMM DEX, there will be additional initial state recorded in an ‘asset pool cell.’ The user establishes a connection with the Layer 2 aggregator, obtains the current price quote and order information, and then sends transaction orders. The transaction order includes the description of the transaction (order), such as “0.1 cBTC for 1000 cUSD” and the transaction signature. After the aggregator collects the user’s order, it immediately feeds information back to the user, so they can see that their transaction has been accepted.
After that, the aggregator matches the received orders in real time and updates the status of each Account Cell involved (new states) and then regularly commits the new Account Cell to the chain for on-chain settlement. Each on-chain transaction consists of the initial state, the new state, and the user’s digital signature. The type script of the Account Cell is responsible for verifying the validity of settlement.
AMM DEX and its matchmaking process
Similar to Uniswap, an AMM DEX on CKB also needs an asset pool set up for liquidity providers. In this section, we’ll use the CKB-sUDT trading pair as an example, demonstrating how to add a trading pair and how to provide liquidity.
Add trading pair and inject initial liquidity
In order to prevent duplicate addition of the same trading pairs, a mechanism for pair registration needs to be introduced here.
When the user registers a new trading pair, he needs to check if it already exists in the Registry Cell. If not, he can register it successfully and use the hash of the token id as the trading pair identifier. The new pair will add a new record to the registry. Currently there is no method designed to unregister a token pair.
In order for the pool to begin facilitating trades, someone must seed it with an initial deposit of each token when registering the pair. This first liquidity provider will set the initial price of the pool. They are incentivized to deposit an equal value of both tokens into the pool. For example, if 1 CKB = 0.01 USDT, the user needs to inject 50k CKB and 500 USDT in the initial deposit. These two assets generate a single Asset Pool Cell to be used for subsequent transactions.
Whenever liquidity is deposited into a pool, special tokens known as liquidity tokens are minted to the liquidity provider’s address in proportion to how much liquidity they are contributing to the pool. These tokens are a representation of a liquidity provider’s contribution to a pool. To receive the underlying liquidity back (plus any fees that were accrued while their liquidity was locked), liquidity providers must burn their liquidity tokens. The business logic here is basically identical to that of Uniswap.
The Liquidity Token is an extended UDT which conforms to the sUDT standard. The difference between this extended UDT and the standard sUDT is that their contract code is slightly different, and the asset tag of Liquidity Token is the hash of the trading pair.
Anyone can become a liquidity provider for a pool by depositing an equivalent value of each underlying token in return for liquidity tokens. These tokens track pro-rata liquidity shares of the total pool and can be redeemed for the underlying assets at any time.
In order to prevent transaction conflicts or DDoS issues due to frequent interactions with an asset pool, some restrictions may need to be introduced. For example, adding threshold requirements, withdrawal fee requirements, etc.
Transaction matching and fee calculation
The aggregation server collects user orders over a period of time and aggregates them together. These orders include: buy orders, sell orders, add liquidity or remove liquidity orders. Taking into account the fairness of transaction ordering, the aggregated orders are executed according to the following rules (order). This approach can minimize transaction slippage.
- Process add liquidity orders
- All buy and sell orders are directly matched according to the current price.
- Then, the rest of buy and sell orders can be cleared according to the predetermined price curve. (These can be processed on demand according to the slippage requirements of the order.)
- Process remove liquidity orders
Whenever a trade occurs, a certain fee (e.g. 0.3%) needs to be paid by users. Part of this fee (e.g. 0.2%) goes directly into the asset pool as a benefit to the liquidity provider, and the other part (e.g. 0.1%) is paid to a designated address as an aggregator operating fee.
Orderbook DEX and its matchmaking process
Compared to the AMM model, the orderbook model has two major differences: one is that its orders are generally limited orders rather than market orders, meaning that the trader controls the transaction price; the second is that it does not provide unlimited liquidity and the user must wait for matching orders. In terms of data structure, the orderbook model adds more order data to the chain than the AMM model and removes liquidity tokens and pools of funds.
Update Limit orders
After the trader “deposits” the asset into the DEX, they can place a limit order. The content of the limit order includes: requested asset, transaction price, transaction quantity, etc. In order to facilitate tracking, each limit order will generate a unique identifier ‘oid’ (This can be achieved using the outpoint hash of the first input cell.).
Transaction matching and fee calculation
Note that the trader’s limit order will first be sent to the aggregator. An aggregator will match part of the orders directly and submit the temporarily unfilled orders to the chain, updating the on-chain orderbook. In the next aggregation cycle, these unfilled orders will participate in the next round of matchmaking as inputs, and traders will not be required to submit a new transaction signature again.
The matchmaking engine follows the following logic:
- All new orders added through witness data are processed along with old orders stored in cell data.
- Divide orders into two queues according to buying and selling orders and arrange them in descending and ascending order according to price.
- Match the head orders of the two queues. In turn, if the prices match, the transaction will be executed at the average price, and the order quantity information and user account balance information will be updated.
- Continue to process the next head order until it cannot be matched.
The transaction fee is charged in proportion to the transaction quantity (for example, 0.1%) and is collected by the aggregator operator.
In this article, we designed two types of Layer 2 DEXs on CKB. They have both made full use of the aggregation characteristics of the UTXO model, completed transaction aggregation and matching off-chain, and reduced the on-chain transaction volume, as well as the users’ cognitive costs. And most importantly, these designs ensure the decentralization and trustlessness of asset custody.
Compared to the rollup solution, the transaction aggregation solution in this article does not use zero-knowledge proofs or optimistic assumptions plus challenges to reduce the computational complexity of transaction verification. Therefore, the actual throughput — which is expected to be ~200–300 TPS — is related to the ratio of the upper bound of computation cycles in a block to the cycle cost of a single signature verification.
Although in the orderbook model old orders do not require signature verification a second time, the improvement in throughput related to this is limited. However we believe, in the future, we can greatly increase transaction throughput through cryptographic solutions such as zero-knowledge proof technology and aggregate signature technology.
To stay updated on all things Nervos: