UDT Payment Solutions

We discuss possible solutions on the source of CKBytes for storing UDT / DOB in the context of B2C / C2C scenarios.

Instant Convert

Instant convert (service) is used in a payment / transfer workflow. A user is expected to pay UDT(e.g., USDI) to a particular third party instant convert service. In exchange, the third part service provides matching amount of CKBytes to the user, so a CKB transaction can be fulfilled. In a sense, a user can focus on their UDT, ignoring requirements for CKBytes with the help of the instant convert service.

Notice that the name “instant convert” is deliberately chosen. Some call a similar setup as flash swap, we intentionally use a different name for several reasons:

  • Flash swap is commonly used to refer to a smart contract in Ethereum. I fear that this might lead to wrong assumptions that only a smart contract can do the job. As we will see here, instant convert can simply be implemented as an off-chain module, while a more sophisticated one can choose to introduce a CKB script. Either way, the CKB script will be an optional enhancement, not a required component.
  • Binance has a convert feature, which is actually the inspiration of our design here.

To avoid confusion, we will precisely define the full workflow of the instant convert service.

Assuming a user (possibly with the help of a dapp) builds the following, incomplete CKB transaction:

One interpretation of the CKB transaction, is that a user buys a DOB with 100 USDI. The transaction is incomiplete because 288 CKBytes are required for the 2 output cell, only 144 CKBytese are available from input cells.

A user can send this incompleted transaction to an instant convert service, with additional information optionally attached:

  • The specific UDT type a user is willing to pay for required CKBytes. This is simply for current example, since the incomplete transaction only uses USDI. For more complicated cases, multiple UDT types might coexist in a single incomplete transaction. For the moment, we will assume that users will pick one type of UDT to pay.
  • The worse price a user is willing to pay for UDT-CKB trading pair, or the maximum UDT a user is willing to pay per CKByte. There are multiple options to obtain this information:
    • Like a AMM swap, a user specifies the worst-case price, and instant convert service aims to find the best price satisfying this worse-case scenario.
    • The instant conver service first gives a quote by supplementing cells making the incomplete transaction complete(we shall see in a second how this works), the user can choose to accept the quote via a signature, or reject the quote by discarding the complete transaction provided by the instant convert service.

Given the incomplete transaction, the instant convert service can add more input / output cells, the missing CKBytes will be supplement by input cells from the instant convert service. Certain output cells provided by the users will be modified by the instant convert service, so as to deduct the UDTs used to pay for the CKBytes. A complete CKB transaction will then be formed:

Cells with solid lines come from the original incomplete transaction sent by the user(bold text denotes modification part), while cells with dashed lines are inserted by the instant convert service. Here the instant convert service is willing to trade the user 144 CKBytes at a total price of 0.5 USDI. 2 input cells added by instant convert service to provide CKBytes, 2 outputs cells are also added by the instant convert service: one collects the traded USDI, one provides and collects all changed CKBytes. A more optimal service can definitely combine the 2 separate cells into a single one.

The instant convert service would sign signatures required by all input cells provided itself. A user, after receiving this complete transaction, can choose to sign his / her own input cells, assuming he / she accepts the price. The user can then send the fully signed transaction to CKB network, when committed, an instant convert action is completed.

The instant convert service can be seen as a general service suitable for many different cases. It’s just that some cases urgently need it, while others are less dependent on it.

There are variants to certain parts of the full workflow above:

Instant Convert Discussion 1: transaction fees

Transaction fees required by CKB are completed neglected in the above discussion. 2 solutions exist for it:

  • A user can provide transaction fees in his / her incomplete transaction
  • The instant convert service can provide the transaction fees by trading slightly more CKBytes for the user. In a way, one can see this as a user only pays transaction fees with UDT.

Either one suits the need, personally I feel the second one is more natural.

Instant Convert Discussion 2: parallelism in instant convert service

There is an issue of parallelism in the above describe workflow. The input cells added to a transaction by the instant convert service will effectively be “locked”, and remain unusable for a while till the transaction is commited on chain. If we don’t lock those input cells, 2 users might retrieve the same input cell in 2 separate transactions from the same instant convert service. Only one of those 2 transactions can land on chain, the other will end up with a double-spent error. There are several mitigations to this problem:

  1. In the most naive solution, a batch of cells can be provided by the instant convert service. Assuming that 3000 cells are prepared by the instant convert service, and that a user has 30 seconds after receiving to sign and submit the transaction to CKB’s P2P network(instant convert service can listen for potential transactions in the P2P network even before the transaction is commited on chain), an instant convert service will be able to process 100 convert actions per second.
  2. We can move one step forward if we can remove the assumption that a user submits the transaction: the instant convert service only returns the completed, but unsigned transaction to a user. When a user accepts the quote, the user sends signature back to the instant convert service, only at this time, the instant convert service signs its own input cells and submit the fully signed transaction to CKB’s network. In this design, an instant convert service can track submitted transactions, and further compress the locked time for a cell: assuming transaction X consumes input cell A, generate output cell B, when user 1 returns the signature for transaction X, the instant service can immediately consume cell B in transaction Y, without waiting for transaction X to be committed on chain. Given the same amount of cells, the instant convert service will be able to process more requests per second. However this solution has 2 caveats:
    • Censorship might be a concern to an extent, since the instant convert service submits a transaction to CKB.
    • A user might receive a transaction with input cells that are unknown(since the depended transaction might not be committed to CKB yet) at the time. There are mitigations(we can send a chain of transactions to the user), but it certainly requires work at the wallet side.
  3. Another assumption of the above workflow, is that a cell from the instant convert service, can be used in one instant convert action at once. In fact, a cell from the instant convert service might process enough CKBytes(e.g., 10000 CKBytes) for multiple instant convert actions at once. Assuming certain lock scripts might be used by users of the instant convert service, open transactions can be introduced, so a user submits a signed open transaction rather than an incomplete transaction. The instant convert service can batch multiple open transactions together and process their instant convert requests together. This will be a much more performant solution. But it also has its own caveats:
    • Similar to option 2, open transactions also have concerns of censorship.
    • Open transactions would require users to use a particular lock in advance. Work at wallet side is also likely required.
  4. A less popular solution also exists: instead of being a service that takes user requests, an instant convert service can simply prepares a series of cells using special lock scripts. The lock scripts can be unlocked when instant convert conditions are met(users have provided enough UDTs for the traded CKBytes). This way instant convert actions will be converted to a series of actions doable by the users alone: locating cells on chain, preparing transactions, signing and submitting to CKB. There are certain caveats in this design as well:
    • A tradeoff between the number of cells and parallelism;
    • An SDK shall be used by most users, so users pick cells in a randomized fashion. Otherwise double-spent issues might be quite common;
      *. On chain cells will not have a way to know latest price between UDT and CKBytes. So likely an oracle or other mechanisms be required to determine the price, this might further complicate the workflow.

For now, we have built an implementation that:

  • Handles transaction fee at the instant service level
  • Chooses option 2 for the parallelism issue

I do want to mention that different solutions might exist for different scenarios. And there would well be other solutions fitting different use cases. Just to take an analogy: it is useless debating whether apple or orange is more tasteful. Our current implementation only picks one of the possible designs, we hope it can bring inspiration to more solutions.

Later we shall explain more details on our first implementation. For now, let’s recap on different payment options.

Payment Options for Different Use Cases

One observation is that there is unlikely a one-size-for-all UDT payment solution for CKB, this is due to CKB’s own very nature. Different solutions might exist and suit different use cases. Here let’s do a recap of UDT payment options for different use cases, with instant convert service in mind.

B2C

When a merchant is involved, the priority should be performance, a UDT payment solution for merchants using CKB, should aim at higher level of parallelism. Since machines will handle most of the action at one end, user experience will be less of a concern.

UDT payment with invoice

Users typicall use one UDT A(e.g., USDI) to buy UDT B, DOB, or other off-chain services. CKBytes will be required to store UDT B, DOB, cells representing off-chain services, and also changes of UDT A.

For one thing, instant convert service can definitely be used. Users can just pay slightly more UDT A, in exchange for all CKByte requirement in the complete transaction.

In real world, merchants have already utilized the concept of invoices extensively. We can introduce invoice to CKB world, where each invoice is likely to contain a merchant side signature, and we can then implement the full workflow:

  • For DOB and other off-chain services, the purchased good can first be put in a cell with a special lock script. When user requires a purchase operatioin, an invoice will be generated by merchant, the user can construct an transaction with the cell containing the good, the invoice might contain signatures used to unlock the cell containing the good. This particular cell can be designed with slightly more CKBytes to supplement user-side requirement.
    • Since each individual good can be wrapped in different cells, there is less likely to be parallelism issue. In a real world, when a purchase action is initiated, the merchant is also less likely to generate invoice for the same good for another user till a timeout period is reached.
  • For UDTs, there can also be an invoice. The merchant can prepare in advance 1000 cells for example. Those cells will also utilize special locks. When a purchase action is initiated, the merchant also generates an invoice, the invoice can be utilized by users to unlock one of those 1000 cells(could be decided by the merchant, or could be randomly picked by the user), the cell can then be used to provide enough CKBytes for users of such a transaction to use.
    • In a way, one can think that the merchant also handles part of instant convert service’s job via invoices.

UDT payment with open transaction

Similar to previous discussion, if we can assume certain locks will be used by users. Open transactions can also be used as a purchase action for more performant processing. That being said, censorship and the assumption of lock scripts will still be a concern.

Invoice vs. open transaction

In a sense, invoice and open transaction are quite alike, sometimes even the same thing from an implementation perspective. Here we distinguish the 2 names in 2 different scenarios:

  • When a user creates an open transaction, we call it open transaction directly
  • When a merchant creates an open transaction, we call it an invoice

C2C

Between users, the top priority should always be user experience. We should prioritize solutions that ensure that when a user signs a transaction, the action will most likely to be succeeded. Unlike machines which can dumply sign a lot of signatures, repeated signing should be avoided at all costs.

Performance and fees are less of a concern between users.

DOB

Transferring of DOBs is quite simple, we can even see it as a solved problem: we can consider the required CKBytes to be part of the DOB. When transferring a DOB, one transfers the DOB and all the CKBytes together to the recipient. More than necessary CKBytes can be included in the initial creation phase: 1 more CKByte is typically enough for many, many transfer operations.

UDT

The transferring of UDTs between users has always been the biggest headache in CKB. Here we provide 2 solutions:

  • When possible, the instant convert service provides the simplest solution: when Alice transfers USDI to Bob, Alice should consult an instant convert service to trade enough CKBytes by paying USDI.
  • Open transaction remains another option, but it requires some strong assumptions:
    • Alice should use lock scripts that support open transaction
    • Bob should have enough CKBytes as recipent
    • Bob should commit the open transaction at receiving it.
  • Maybe fiber provides a better option

Summary

In summary:

  • Instant convert service fits all scenarios
  • Merchants can introduce invoices. It’s very likely merchants have invoices already.
  • When it’s possible to assume lock scirpts, open transaction can be viable and performant solution.
  • Transferring of UDTs between users has always been the biggest headache, we might want to just use instant convert service, or rely on fiber.
  • Transferring of DOBs between users is a solved problem. CKBytes in this case are just part of the DOB.

ckb-udt-convert-serviceensure

We have implemented an instant convert service. As mentioned above, there might be multiple different implementations of the instant convert service, each with different design priorities suiting different purposes. What we have here, is simply one of the many possible choices.

There are 3 parties for the instant convert service:

  • Convert service: our constructed instant convert service server
  • App: a wallet, or an app that will communicate with the instant convert service
  • User: actual (possibly) human user of the app or the wallet.

Public API

ckb-udt-convert-service exposes a JSONRPC 2.0 compliant API server. 2 APIs: initiate and confirm are provided for instant convert actions.

HTTP POST method must be used for the JSONRPC server.

Initiate

App side creates an instant convert action via initiate API. The request payload looks like following:

{
  "id": 42,
  "jsonrpc": "2.0",
  "method": "initiate",
  "params": [
    {
      // This JSON object contains a (incomplete) CKB transaction
      "cell_deps": ...,
      "header_deps": ...,
      "inputs": ...,
      "outputs": ...,
      "outputs_data": ...,
      "version": ...,
      "witnesses": ...,
    },
    [1, 3]
  ]
}

2 required parameters are used by the initiate JSONRPC reuqest:

  • An incomplete transaction created from user actions by the app side. The CKBytes from outputs cells will exceed the CKBytes from input cells in this transaction.
  • An array of numeric indices. This parameters marks the output cells from the incompleted transaction, which contains UDTs that can be paid for CKBytes.

PS: in our first iteration, the instant convert service only provides CKBytes, and charge a particular predefined UDT types. Later we might expand this service for more scenarios:

  • The 3rd, 4th parameters can be provided in the form of CKB scirpts, containing the UDT to pay and UDT to trade for
  • When a CKB script has full-zero code hash, data as hash_type , and an empty args, we can consider that the UDT speicifed is actually CKBYtes.

Theorecitally, an instant convert service with those additional parameters can be used to trade between any 2 token types. But it remains a question if we should need such complexity.

The instant convert service will perform the following actions for an initiate request:

  1. Calculate the required CKBytes, including the CKBytes required by output cells, and the CKBytes required for transaction fees.
  2. An external service(such as Binance API) can be consulted for the current price of UDT against CKB. The instant convert service might adjust the price with some incentive percent for itself, and then calculate the final UDTs to charge from the user for the required CKBytes.
    1. When a user does not provide enough UDTs to charge in the incomplete transaction, the instant convert service would return with an error.
  3. The instant convert service finds a usable live cell (named fund cell) in its fund pool. In our current implementation, all fund cells provide CKBytes, while at the same time, collects UDTs.
    1. In the extreme case, an instant convert service might not have an available fund cell to serve the request. In this sense, the instant convert service should return with an error. At the same time, it should also tries to notify ops team of the instant convert service for intervention.
  4. The instant convert service then fulfill the incomplete transation with the fund cell into a complete transaction. It also modifies output cells from the original incomplete transaction, charging required UDTs, and collect those UDTs in its own output fund cell.

An API response like following will be returned by the instant convert service to the app side:

{
  "id": 42,
  "jsonrpc": "2.0",
  "result": {
    "valid_until": "2025-07-24T01:42:58.100Z",
    "transaction": {
      // This JSON object contains a complete, unsigned CKB transaction
      "cell_deps": ...,
      "header_deps": ...,
      "inputs": ...,
      "outputs": ...,
      "outputs_data": ...,
      "version": ...,
      "witnesses": ...,
    },
    "ask_tokens": "0x123124",
    "bid_tokens": "0xaaffd132"
  }
}

In addition to the complete transaction(unsigned) to present to the user and sign, some more data are also returned:

  • valid_until contains an ISO8601 formatted string, containing the expiration time of the instant convert service. Each instant convert action has an expiration time due to 2 reasons:
    • Prices quoted by the instant convert service is not always valid. Prices fluctuate, a quote is only valid for some amount of time.
    • Due to parallelism concerns, locked fund cells are also valid only for some amount of time, before they will be available to use by others.
  • ask_tokens and bid_tokens are returned as a convenience so users can learn about the quote price directly. App side can also choose to deduct the quote price from the returned transaction directly. Assuming the instant convert service charges USDI, provides CKB. ask_tokens will contain the charged USDI amount, while bid_tokens will contain the provided CKBytes.

Confirm

When app side receives reply from the initiate request, it should present the whole transaction for the user to confirm. When confirmed, the app side should sign input cells it inserted for the users. The signatures should be put in the designated place in the witnesses field. The app side then send the complete, partly-signed transaction via confirm request to the instant convert service. The request payload looks like following:

{
  "id": 42,
  "jsonrpc": "2.0",
  "method": "initiate",
  "params": [
    {
      // This JSON object contains a complete, user-signed CKB transaction
      "cell_deps": ...,
      "header_deps": ...,
      "inputs": ...,
      "outputs": ...,
      "outputs_data": ...,
      "version": ...,
      "witnesses": ...,
    }
  ]
}

The instant convert service performs the following tasks for the confirm request:

  • The instant convert service first checks if the app side or the user unexpectedly changed anything from the transaction. Basically, the app side should only be able to modify witness field to insert signatures after initiate request. If any modifications are detected, errors will be returned, and the processing ends.
  • The instant convert service should check if the instant convert action times out. If so, errors will be returned, and the processing ends.
  • The instant convert service signs its own input cells, and send the complete, signed transaction to CKB network.

After processing, the instant convert service sends the complete, signed transaction back to the app side:

{
  "id": 42,
  "jsonrpc": "2.0",
  "result": {
    "transaction": {
      // This JSON object contains a complete, signed CKB transaction
      "cell_deps": ...,
      "header_deps": ...,
      "inputs": ...,
      "outputs": ...,
      "outputs_data": ...,
      "version": ...,
      "witnesses": ...,
    }
  }
}

The instant convert service will send the transaction to CKB. But for extra security and faster broadcast, the app side might also choose also to send the transaction to CKB network.

Public facing vs ACL

Theorecially, the instant convert service can be a public facing service. But essentially, we are talking about a 2-phase-commit which will lock consumable resource in the first step. A DDoS attack might be initiated on the instant convert service, where a lot of initiate requests are sent, but no confirm requests are sent. This way the instant convert service might continously be in a state that it has enough fund cells but no usable fund cells. So for the time being, our current instant convert service implementation is more safe behind an ACL, and only be invoked by authroized parties.

Internals

Here we discuss some internals of our instant convert service

Fund cells / pool

Our instant convert service will maintain a series of fund cells in the fund pool. Each fund cell is a cell holding a particular UDT type(USDI in our example), and more than enough CKBytes. At initial creation, each fund cell will hold 0 UDT. When a fund cell is used in an instant convert service, it would pay some CKBytes, and collects certain amount of UDTs. At certain time, a fund cell might hold so few CKBytes that it cannot fulfill an instant convert action, such fund cells with insufficent CKBytes will be named insufficient cells. To ensure that our instant convert service have enough CKBytes to serve requests, ops team of the instant convert service are expectedly to send CKBytes to the fund pool, this is done by creating empty CKB cells(meaning CKB cells with no type script and empty data) using the same lock script as fund cells in the ful pool. Periodically, our instant convert service will colllect insufficient cells and empty cells with only CKBytes, and use those cells to recreate new, usable fund cells. In the same process, any UDTs from insufficent cells will be moved to designated collecting addresses, for ops team to trade them back to CKBytes in Binance or other services.

Deployment

Our current instant convert service is a simple node.js server using Redis as a dependency. The deployment of the instant convert service, is actually quite simple. We will provide deployment and running steps in the README part of the repository when it has matured.

A Real Running Example

We have run the instant convert service in testnet for real with this CKB address. We can analyze the running details of our instant convert service by following the transactions in chronological order:

For now we only collect UDTs such as USDIs in insufficent cells to collecting address. This way we maximize the usefulness of all fund cells. An off-line tasks might be created in the future, so we can run a cronjob at a time that people are less likely to use the instant convert service(like 3 am on Sunday), the cronjob randomly picks 30% of all fund cells, and build a transaction to collect all USDIs inside.

12 Likes

It reads like an overdue invention that finally brings the Nervos cell system to life. This turns the first layer of Nervos-CKB into a financial computer, with programmatically formulated flow charts. Fascinating, the cells become a nervo(u)s system through their application. Without a doubt, something is created that is bigger than its individual parts.

Decentralized distribution would be desirable after tests and before the introduction of active use. For example, as an optional start flag for constantly operated full nodes. Decentralized accessibility would be desirable as a main function of CKB, which cannot be dependent on individual central operators.

1 Like

I’m just gonna state my personal opinion here, and it does not necessarily represent anyone else’s opinion, nor did it represent Cryptape or Nervos’ opinion.

I do get the full merits of a decentralized solution, and we should definitely work towards one. But one huge mistake I personally learned over the years, is that an over-focus on decentralization, would unnecessarily complicate the architecture, causing more delays and slow iteration time. We did learn this lessons quite a number of times.

Take the instant convert service for example, a truly decentralized solution would require a way to fetch current UDT/CKB price decentralized version. It is easy to say in research work that we just assume an oracle exists that provides the price, but in practice this is never that simple. If we proceed to design an oracle that might take months or even years until a mature solution arises.

These days I tend to see 2 different worlds coexist in blockchain space: a fast pacing experience focused world, and a decentralized but cumbersome world. For the first one, a centralized solution works in a sense, and not so many people care about it; there are indeed people who want a real decentralized solution(and don’t mind a worse experience), but the second group, might in fact be the minority in current world.

So I do get it and value a decentralized solution as well, but I don’t believe a centralized solution will be useless here. I’ve personally made enough mistakes in this space. It’s okay you think otherwise, I’m just sharing my blant feelings.

2 Likes

很赞成,应该想清楚,我们到底需要去中心化的什么,需要中心化的什么,两者真的就完全没办法结合吗?

1 Like

中心化在用户体验上对去中心化就是降维打击,sol就是摒弃了去中心化吸引了大批用户,先把用户搞到再说,用户都没有,是不是去中心化也没有意义

1 Like

I find a lot of understanding here, thank you for the clear explanations. For many complex applications, decentralized implementation cannot be a priority. It should be worked towards as a long-term goal because central points can be eliminated bit by bit. In the meantime, decentralized individual solutions may already be developed for other applications, which can then be adopted and used for this in the future. The already sufficient complexity should not become the victim of a complexity multiplier, to which the user ultimately attaches little or no value anyway. Decentralization is of secondary importance in complicated matters.

可以在扩展一下:为用户提供 DAO 资金的即时流动性解决方案。

deposit cell → withdraw cell phase1指定服务端lock,服务端付出ckb,收到withdraw cell phase1,最多等待180epoch之后解锁,包含收益。用户可以立即收到ckb只是没有dao收益 。可能需要注意的是:deposit cell → withdraw cell phase1限制了lock大小必须相同,服务端可能需要提供多种lock满足用户需求

This could be expanded to provide users with an instant liquidity solution for DAO funds.

The deposit cell → withdraw cell phase 1 specifies a server-side lock. The server pays CKB, receives the withdraw cell phase 1, and waits up to 180 epochs for the lock to be unlocked, including the yield. Users receive the CKB immediately, but not the DAO yield. It’s important to note that the deposit cell → withdraw cell phase 1 requires the lock size to be the same; the server may need to provide multiple locks to meet user needs.

1 Like

That’s so strange, I was so sure there was already a community project dedicated to that, what’s the name again? :thinking:

1 Like

iCKB?These are two completely different solutions that can provide the possibility of immediate unlocking of existing dao funds.

1 Like

This is the big issue when wrapping NervosDAO: it requires a lot of liquidity, potentially unbounded.

For example, what happens if a user wants to liquify a deposit worth 1B CKB?

An attacker can literally DoS the system you propose by requesting the withdrawal of a big enough deposit.

iCKB works around this by sharing the underlying deposits among userrs and by using partially matcheable orders. Conversely NervosDAO deposits are monolithic, once done you cannot split its withdrawal

What if the user deposited 4 years ago, is he not entitled to a part of his yield?

Yeah, one is an existing (albeit under appreciated) solution, the other is not really viable.

BTW this requirement is not from the DAO code itself, it was brought forward due to something I discovered when creating iCKB

In my opinion, this is a centralized solution. Liquidity is provided by the service provider, and the yield rate is also determined by the service provider. Furthermore, denial-of-service (DoS) attacks are unavoidable. I’m simply extending my thinking to the Udt payment service. Of course, Ickb is also excellent, being extremely secure and decentralized. I’m simply proposing a new possibility for DAO’s exit.

1 Like

Awesome, worship

1 Like

Ok, let me type down a couple more issues of working directly with NervosDAO:

  • Deposits are basically NFTs (it would require explicit user consent in the inteface for withdrawing from a particular deposit)
  • Depost lock cannot be changed without additionally requesting their withdrawal
  • It’s tricky to add withdrawal requests as last part of a tx (cause input deposit and output withdrawal request cell must have the same index)
  • A transaction involving NervosDAO can have at most 64 outputs

All these little issues (+ DoS) make a bit cumbersome working directly with NervosDAO deposits.

An instant service idea for iCKB

I’ll try to see if I can create some instant conversion service directly integrated with the iCKB bot, issue is usually partial matching tho :thinking:

Interestingly enough, iCKB Limit Order can be Dual Ratio Limit Orders, so basically they can Provide Liquidity to whoever matches them in both directions, similar to AMM, just the price is fixed.

If the bot keeps its funds in these Dual Ratio LO (as I initially foreseen). With high enough fees, price drifting over time between iCKB and CKB should not create issues.

We can achieve exactly the instant conversion service for iCKB:

  1. User needs some small liquidity (either iCKB to CKB or CKB to iCKB )
  2. Bot(s) already has on-chain funds wrapped in Dual Ratio LO
  3. User signs his transaction converting some liquidity using bot LO

Downsides to what’s currently offered in iCKB:

  • Fees will be much higher to offset iCKB/CKB price drift over time, if bot has no activity for a period of time.
  • Only funds actually in the Dual Ratio LO are available (1M iCKB will not be instant).
  • LO state contention may require user to resign transaction (currently unlikely tho)
  • It needs some integration in CCC, similarly to the service presented in this proposal.

I guess we’ll see :grin:

Phroi %42

2 Likes