dfinity / ICRC-1

A fungible token standard developed by the Ledger & Tokenization working group for the IC.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

About data structures

iclighthouse opened this issue · comments

  1. Account
type Account = record { of: principal; subaccount: opt Subaccount; };
icrc1_balance_of : (record { of: principal; subaccount: opt SubAccount; }) -> (nat) query;

type Account = blob might be a better choice.
It is only necessary to specify the SubAccount when calculating Caller's Account.

  1. Timestamp
type TransferArgs = record {
    from_subaccount: opt Subaccount;
    to: Account;
    amount: nat;
    fee: opt nat;
    memo: opt nat64;
    created_at_time: opt Timestamp;
};

If Timestamp is of type Nat64, which means nanoseconds, then after 500 years the data will overflow.

  1. TransferError
type TransferError = variant {
    BadFee : record { expected_fee : nat };
    BadBurn : record { min_burn_amount : nat };
    InsufficientFunds : record { balance : nat };
    TooOld : record { allowed_window_nanos : Duration };
    CreatedInFuture;
    Duplicate : record { duplicate_of : nat };
    GenericError: text;
};

Token and ICP Ledger have different usage scenarios and require careful definition of the Error data structure.

Hi @iclighthouse!

Thanks for the constructive feedback!

type Account = blob might be a better choice.

What will the blob contain? Why do you think packing the principal and the subaccount into a blob might be a better choice?

Token and ICP Ledger have different usage scenarios and require careful definition of the Error data structure.

I full-heartedly agree that we need to think hard about the error type definition.
I have a preliminary implementation of the standard in both Motoko and Rust, and the proposed error type seems to work well (except that GenericError should be GenericError : record { error_code : nat; error_message : text }; otherwise, it's no better than a reject).
Which error variants do you think we should remove or add?

What will the blob contain? Why do you think packing the principal and the subaccount into a blob might be a better choice?

"principal+sub" => account-id
Account-id can be calculated outside the canister, unless the caller role. So, when entering the entity's account as a parameter (except for the caller), you can directly enter the Blob type account-id.
ICP Ledger is implemented in the same way. This allows for a cleaner interface. More importantly, privacy can be protected.

GenericError : record { error_code : nat; error_message : text } I agree that this is a better solution.
The difference between Tokens and ICP is that Tokens has multiple implementations of different entities and ICP has only one on IC.

memo: opt nat64; memo using the Blob type will meet more needs.

In addition, I make one more suggestion.
icrc1_metadata : () -> (vec { record { text; Value } }) query;
Recommended metadata entries include icrc1:symbol, icrc1:name, icrc1:decimals. Suggest adding icrc1:fee, or adding icrc1_fee() method.

ICP Ledger is implemented in the same way. This allows for a cleaner interface. More importantly, privacy can be protected.

We voted on that matter, and the majority agreement was that we don't want to keep AccountId in the new standard; we decided to use separate fields for principals and subaccounts instead. I'm a maintainer of the ICP ledger at the moment, and even I wouldn't say I like AccountIds very much.

The difference between Tokens and ICP is that Tokens has multiple implementations of different entities, and ICP has only one on IC.

That's clear, but it's hard to predict what other implementors need. I'd love to hear more opinions on what type of errors they want to report.

memo: opt nat64; memo using the Blob type will meet more needs.

We discussed this in one of the working groups; there was a proposal to make memos into 32-byte blobs. The main issue with this is that this will be the only standard feature that will be impossible to implement in the ICP ledger because it already relies on 8-byte memos. It would be great if we could make the ICP ledger comply with the new standard while preserving all the data.

Suggest adding icrc1:fee, or adding icrc1_fee() method.

That's a great point; I'll make a PR.

We voted on that matter, and the majority agreement was that we don't want to keep AccountId in the new standard; we decided to use separate fields for principals and subaccounts instead. I'm a maintainer of the ICP ledger at the moment, and even I wouldn't say I like AccountIds very much.

This looks more intuitive. But in some scenarios it can cost the user his privacy and he has to tell others about the principal and subaccount. I think that principal and subaccount need to be protected at some point.

Using a scheme that is consistent with the ICP Ledger's Account-id will make it easier for developers to avoid getting confused.

We discussed this in one of the working groups; there was a proposal to make memos into 32-byte blobs. The main issue with this is that this will be the only standard feature that will be impossible to implement in the ICP ledger because it already relies on 8-byte memos. It would be great if we could make the ICP ledger comply with the new standard while preserving all the data.

The blob type is compatible with nat64, which can be converted to blob.

Closing this issue: the Working Group addressed most of the feedback, and the community accepted the standard in its current form.