Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rfc(0040): add sudt info #290

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
184 changes: 184 additions & 0 deletions rfcs/0000-sudt-info/0000-sudt info.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
---
Number: "0000"
janx marked this conversation as resolved.
Show resolved Hide resolved
Category: Standards Track
Status: Proposal
Author: Xiang Cheng
Organization: Lay2dev
Created: 2021-12-25
---

# sudt info
janx marked this conversation as resolved.
Show resolved Hide resolved

## 1.Overview
janx marked this conversation as resolved.
Show resolved Hide resolved

sudt is a very simple udt standard. With the udt deployed by this standard, we can only get the balance from the chain, but not the token name, token symbol, decimals and other parameters.
janx marked this conversation as resolved.
Show resolved Hide resolved
janx marked this conversation as resolved.
Show resolved Hide resolved

To extend the existing sudt standard, it is necessary to design a scheme to store token information and bind it to the corresponding sudt, but does not destroy any compatibility with the existing sudt.

## 2. sudt Info format

In sudt info, the most basic information that must be included is token_name, token_symbol, and decimals. As for total supply and balance, they can all be obtained by indexing the cell.

A sudt Info in specification looks like following:

```
decimals: uint8
name: Common knowledge Byte
symbol: CKB
extra: {website:"https://nervos.org"} // optional
```

The serialization format of sudt info should be json.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are 2 drawbacks to use json:

  1. waste of space
  2. the smart contracts will need a json library, which will introduce security issue.

I think molecule is OK.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious if Molecule can be used here as it's more space-efficient and a default on CKB. If I remember correctly, the reason for using JSON than Molecule was the ease of use for application developers? Not sure if Molecule's javascript support renders the reason obsolete?

Copy link
Member

@janx janx Jan 12, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xcshuan any thoughts on this one?

cc @CipherWang @louzhixian @Keith-CY

Copy link
Author

@xcshuan xcshuan Jan 13, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can use the simplest format, which is repeated length+content.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A simple format is consistent with sUDT indeed. But sUDT info data consists of several key/value pairs rather than a single number in sUDT data. Use length+content format here basically reinvents Molecule, with the drawback of lacking deserialization tools.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there is a library for molecule available, I think it should be better to use molecule.

There are libraries for C, Rust, go and JavaScript: https://github.com/nervosnetwork/molecule.

At least we need to verify in the script whether the data of the info cell is a valid SUDT Info. I don't know if using json will make this troublesome.

It will. Use JSON in on-chain contract is hard, expensive and may bring security risks as Jindong mentions. Do we really need to verify sudt info format in scripts? It doesn't make sense in my opinion.

If we skip the verification, we can stick to the original method.

If we do need that, I recommend use the format below:

vector Bytes <byte>;

table SudtInfo {
    decimals: byte,
    name: Bytes,
    symbol: Bytes,
    extra: Bytes,
}

The extra may be a problem in real world cases. Since molecule needs schema to parse data, but different user may use different fields here. The best solution for this field I can find is to use an embedded JSON string. In this case, on-chain contracts will only verify the fixed fields with molecule, and we have to develop some tools for users in the SDK to parse the whole struct.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer not to verify format in CKB script. It simplifies the script/standard a lot. If someone creates an ill-formated SUDT info cell intentionally or accidentally, applications can simply ignore the bad info cell and the result is the same as no SUDT info cell.

Copy link
Member

@janx janx Jan 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary: we're considering JSON vs. Molecule, while JSON is simple and widely used, its drawback is more difficult to parse/validate on chain. However it seems unnecessary to include SUDT info parse/validation in on-chain script, which basically avoids the problem.

In this case I suggest to go with JSON and skip on-chain format validation, to keep things simple.

Copy link
Member

@janx janx Jan 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xcshuan I suggest adding @huwenchao as 2nd author because it's his analysis and suggestions and having him complete the RFC, if you agree.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

adding @huwenchao as 2nd author

Ok, I think it's fine.


**Data:**

- **decimals:** the number of decimal digits used by the token, if decimals are 8 it means that the token can be divided to 0.00000001 at least, uint8 type.
- **token name:** name of the token, an array of characters encoded in UTF8.
- **symbol:** identifier of the token, such as “HIX”, an array of characters encoded in UTF8.
- extra: Anything you want to write, such as the website, the hash value of a certain picture, etc.

The first three items are parameters that must be filled in, and information can be added as required.

If info is placed in a cell, the cell should look like this:

````
Data:
sudt info
Type:
code_hash: sudt_info typescript
args: sudt type script hash or type_ID
Lock:
...
````

## 3. Info data in Cell

### 3.1. For Single Owner sudt

The issuance of sudt on CKB is controlled by lockscript, so the simplest sudt is issued by an individual or organization using a lockscript controlled by a private key, such as USDC and other stable coins.

For this type of sudt, you can construct an info_cell while minting sudt, whose typescript's code_hash is info_cell typescript, its args is sudt's type_script hash. Info_cell will check whether the transaction meets the conditions.

````
// Issue new Sudt/Sudt_Info
Inputs:
<... one of the input cells must have owner lock script as lock>
Outputs:
Sudt_Cell:
Data:
amount: uint128
Type:
code_hash: simple_udt type script
args: owner lock script hash (...)
Lock:
<user defined>
Sudt_Info_Cell:
Data:
sudt info
Type:
code_hash: sudt_info type script
args: sudt type script hash
Lock:
sudt creator defined
````

The following rules should be met in a Sudt Info Cell (typescript):

- **Rule 1:** In this transaction, at least one sudt cell must exist in the output cell, and the hash of its typescript matches the args of Info_cell.
- **Rule 2:** In this transaction, at least one cell must exist in the input cell, and its lockscript is the owner lockscript of sudt.
- **Rule 3:** the lockscript of info_cell should be set to deadlock by default, in some cases, developers can choose other lockscript.
- **Rule 4:** If there are multiple Info_cells, choose the info_cell with the smallest block height at the time of generation. If it is at the same block height, choose the info_cell with the smallest transaction index. The same transaction cannot generate two info_cells.
janx marked this conversation as resolved.
Show resolved Hide resolved

janx marked this conversation as resolved.
Show resolved Hide resolved
### 3.2. For Script-drive sudt

However, there is another type of sudt on CKB, which is not issued by a lockscript controlled by a private key but follows a specific script logic. Such as NexisDAO's dCKB and Tai, and the previous Info_cell design is no longer suitable for this situation.

Since anyone can mint sudt while following the script logic, if we continue to use the previous logic, anyone can generate the corresponding info_cell. So we need to add new logic on the basis of the previous design.

Since it is impossible to distinguish whether an owner lockscript is script-driven from the outside, it should be checked first according to the script-driven logic.

````
// Issue new Sudt/Sudt_Info
Inputs:
...
Outputs:
Sudt_Info_Cell:
Data:
sudt info
Type:
code_hash: sudt_info type script
args: type_id
Lock:
sudt creator defined
````

The following rules should be met in a Sudt Info Cell (typescript):

- **Rule1**: The cell data conforms to the format.
- **Rule2**: The args conform to the rules of type id.
- **Rule 3:** The lockscript of info_cell should be set to deadlock by default, in some cases, developers can choose other lockscript.
- **Rule 4:** After constructing this Info cell, use the hash of info_cell's type_script as the first 32 bytes of the args of the lockscript of sudt owner.
janx marked this conversation as resolved.
Show resolved Hide resolved

The type script of the info cell checks whether the transaction satisfies one of the two logics(single-owner or script-driven) above.

## 4. info data in witness

The above describes a solution to put info data in the cell, but if we don’t change info often, we can treat sudt Info as static data and put it in witness. This solution is an additional solution to info_cell and does not conflict with info_cell.

The advantage is that it can reduce the state occupation on the chain. When sudt is useless, no state will be occupied, and there will be no situation where the state is still occupied on the chain after the EOS fundraising ends. The disadvantage is that if the blockchain of ckb is to be prune in the future, the information may be lost.

### 4.1. For Single Owner sudt

````
// Issue new sudt Info
Inputs:
<... one of the input cells must have owner lock script as lock>
Outputs:
udt_Cell:
Data:
amount: uint128
Type:
code_hash: simple_udt typescript
args: owner lock script hash (...)
Lock:
sudt creator defined
Witnesses:
...
<Corresponding to owner cell>lock:signature,input_type:...,output_type:udt_info_data
...
````

For a single-owner-controlled sudt, info_data satisfies the following rules:

- **Rule 1**: First, check according to the rules of info_cell, if there is a corresponding info_cell, use info_cell.
janx marked this conversation as resolved.
Show resolved Hide resolved
- **Rule 2**: When there is no corresponding info_cell, scan the entire chain to find the first sudt issuance transaction that has data in the sudt info format in the output_type of the witness corresponding to owner_lock, and use the sudt info.

### 4.2. For Script-drive sudt

Script-driven sudt stands for, the owner_lock of sudt is not a lock controlled by a private key, but a special script.

Since it is impossible to distinguish whether an owner lockscript is script-driven from the outside, it should be checked first according to the script-driven logic.

````
// Issue new Sudt/Sudt_Info
Inputs:
<... one of the input cells must have owner lock script as lock>
Outputs:
udt_Cell:
Data:
amount: uint128
Type:
code_hash: simple_udt typescript
args: owner lock script hash (...)
Lock:
<user defined>
Witnesses:
...
<Corresponding to owner cell>lock:signature,input_type:...,output_type:udt_info_data
...
````

For a script-drive sudt, info_data satisfies the following rules:

- **Rule 1**: First, check according to the rules of info_cell, if there is a corresponding info_cell, use info_cell.
- **Rule 2**: When there is no corresponding info_cell, scan the entire chain to find the first issuance transaction corresponding to sudt with data in the sudt info format in the output_type of the witness corresponding to the owner lockscript, and the hash of info_data is equal to the first 32 bytes of the owner lockscript args.
janx marked this conversation as resolved.
Show resolved Hide resolved