Discussion on the regulatory extension to sUDT

Background

For some scenarios, such as stablecoin with regulatory compliance, token issuer needs to have the privilege to protect the users’ assets from malicious attack under specific critical circumstance, including fraud, money laundering and so on. The sUDT protocol only defines the fundamental functionalities of UDT, but not includes the regulation parts. So we need to figure out a way to extend the sUDT standard to meet such purpose.

There are at least two main ways to realize these features. On the one hand, we could create a new xUDT protocol which is the superset of sUDT with the same data structure definition and more functionalities. On the other hand, we could create a new xAcp lock, which allows the issuer directly take over specific assets if necessary.

The UDT standard is one of the most fundamental protocols in the application layer of blockchain. A reasonable UDT proposal has to cover the consideration of technology, user experience, and application universality. This post discusses the two possible solution to the regulation UDT preliminarily, and gives the pros and cons.

xUDT as a new Typescript

xUDT is almost the same as sUDT standard except it needs some transfer constrain cells in deps during the token transfer process.

deps:
    status cell
    blacklist cell
    ...
inputs:
    xUDT cell
outputs:
    xUDT cell

The xUDT Typescript will not only verify the token amount consistency but also verify input and output cells following the address rules.

xUDT cell structure & transfer rules

The data structure of xUDT cell is similar to that of sUDT, with a slight change in type args.

// xUDT cell
Capacity:
Data:
    uint128 amount
Type:
    code_hash = xUDT
    hash_type = type
    args = issuer_lock_hash_160bit | regulation_byte
Lock:
    any

The variable regulation_byte is an one-byte parameter with the following definition.

regulation_byte: 0b 0 0 0 0 0 0 0 0
                    |         | | └- Global control
                    |         | └--- Blacklist
                    |         └----- Whitelist
                    |                Reserved
                    └--------------- 1: Definition / 0: Usage

The issuer firstly deploy some regulation cells to define the global control cell, blacklist cell, and the whitelist cell. Later, all the transfer transactions must include such cells as deps to match the rules. Here follows the creation of the global control cell and the blacklist cell.

# create a global control cell
input:
    ordinary cell:
        lock: issuer_lock
output:
    xUDT cell:
        data:
            uint128 amount = 0  // the amount must equals to zero
            control_params: {
                "transfer":"enable",
                "mint":"enable",
                "burn":"enable",
                ...
            }
        Type:
            code_hash = xUDT
            hash_type = type
            args = issuer_lock_hash_160bit | regulation_byte = 0b10000001
        lock:
            any
# create a blacklist cell
input:
    ordinary cell:
        lock: issuer_lock
output:
    xUDT cell:
        data:
            uint128 amount = 0  // the amount must equals to zero
            blacklist_data
        Type:
            code_hash = xUDT
            hash_type = type
            args = issuer_lock_hash_160bit | regulation_byte = 0b10000010
        lock:
            any
# transfer
deps:
    global cell
    blacklist cell
    script code cell
input:
    xUDT cell:
        data:
            uint128 amount
        Type:
            code_hash = xUDT
            hash_type = type
            args = issuer_lock_hash_160bit | regulation_byte = 0b00000011
        lock:
            any
output:
    xUDT cell:
        data:
            uint128 amount
        Type:
            code_hash = xUDT
            hash_type = type
            args = issuer_lock_hash_160bit | regulation_byte = 0b00000011
        lock:
            any

User experience & application immigration

For the token issuer, they need to create the right regulation cells before their tokens could be accepted by the end users. But it won’t be a big obstacle. For the end users, they just use their own lock script (address) to hold the token, same as sUDT.

The wallet and exchange developers have to add the new xUDT transfer support, which is a bit more work on transaction generator. Another good news is the ckb-indexer has already supported the prefix indexing mode, which could handle the xUDT typescript well.

If this xUDT standard could be accepted as the default standard. It’s better to upgrade the current sUDT script to the new xUDT script by typeid method directly, instead of deploying a new xUDT script. Because the xUDT is backward compatible, if you done’t need the regulation features, just leave the regulation_byte empty.

Drawbacks of xUDT

It cannot support the directly control to the user’s assets, because the constrains only work during the transfer process. The illegal assets can be froze, but can not be slashed or confiscated. The users’ cell is always controlled by themselves, even it may be bannd by the issuer.

xAcp as a new Lockscript

Acp lock(a.k.a. anyone can pay lock) is used to assist sUDT cell to provide a better udt transfer user experience. It is reasonable to modify the Acp lock to add issuer privileges to control the users assets under some critical circumstance.

xAcp rules

Compared with xUDT scheme, xACP is much easier to be implemented. What we need to do is 1) delegate the ownership to the token minter, 2) make sure the token transfer among the same xAcp locks. To achieve this, we need to add an additional byte/marker to the Acp lock args to identify its regulation features.

sUDT cell:
    data:
        uint128 amount
    type:
        sUDT type
    lock:
        code_hash = xAcp code hash
        args = user_pkhash160 | <2 bytes minimum> | 1 byte regulation_byte = 0xFF

When the regulation_byte presents, the xAcp code will enforce the extra ownership and transfer logics mentioned above.

User experience & application immigration

We could upgrade the Acp lock to make it support xAcp features. So the users won’t realize what really happens. And the same as the suffixal minimal transfer amount bytes, applications like wallets will automatically handle the regulation byte during the transaction assembly period. Both the minimum and regulation byte are absent in the acp address.

Drawbacks of xAcp

The most important drawback of xAcp is obvious, that the users cannot change their locks. Which means most of the dApp interactions cannot be processed, because most of them require the assets to use some specific dApp related locks. Like the DEX, it uses a order lock to manage exchange orders.

The second drawback or a notable feature of xAcp is that the issuer has to mint the tokens to an xAcp address first. If the issuer accidentally mints the tokens to a normal address, then that portion of tokens won’t follow the regulation rules until they are transfered to an xAcp address with regulation byte enabled.

6 Likes

I’m strongly in favor of xUDT over xACP. Any time a specific lock is required for an asset type it creates a severe interoperability limitation for the underlying asset. A stablecoin using xACP would be useless in many DeFi scenarios because of this limitation.

The design of regulation_byte is super cool. It is just like extension pack, you can add more rules to the basic logic of sUDT. We can add the meta info, issue rules, white/black list and some other rules.

Is it possible to standardize the regulation_byte, and build a feature library, so we can add skills to sUDT or any other basic things as easy as possible.

2 Likes