ICRC-1 Account Human Readable Format

The features you took out is what makes it interesting and valuable.

I am application developer, we are the ones that do the explanation and marketing to non-technical users.

I think the ICRC-1 account change is not solving a problem as @bitbruce pointed out.

  1. Determination of Principal and Subaccount, was never a problem, its the job of Smart Contract Developer to figure it out.

The best people to have a voice in this ICRC spec, Is Application Developers for Wallet apps, Defi Apps.

Look at what @quinto and @bitbruce said.

In Other chains e.g Ethereum.

1 address is used for all ERC-20 transactions.

In ICP 1 Account Identifier should be used in all ICRC Transactions, the End User don’t care about the Principal/Subaccount Determination(imaginary problems)

Its halting development, Users are confused the ICRC-1 format cannot be used on any wallet, NNS or IC explorer, they can’t even use it to view their balance publicly.

The best approach is to accept Account Identifier.

1 Like

If you don’t need to use subaccounts (which is a feature that leads to simpler and robust payment protocols e.g. you can segregate distinct usecase/purpose using these subaccounts), you can unify ICP & ICRC ledger transfers by using the principal and therefore the default subaccount everywhere. The ICP ledger does support the ICRC-1 standard which allows using the principal as an address. In this case you have to track the transfers using the corresponding default identifier.

Happy to help you with this. Can you provide some more information? I suppose you are doing something with the ICP token or is it for some other ICRC-1 token?

I am surprised to see that the dashboard indeed does not support searching for ICRC-1 account identifiers such as the one you provided: h5boe-vqaaa-aaaam-ac36q-cai-ckw43vy.6867bf53ffcaa0cd11f3bb59be8e4d9e71b20d096cc822a5dffecc7561b026ce.
That is a shortcoming of the dashboard. However, ICP is the exception here. For all other tokens the dashboard supports searching for ICRC-1 account identifiers. So this is something that needs to be fixed in the dashboard.

I suppose the same is true for the NNS wallet. ICP is probably an exception when compared to all other ICRC-1 tokens. And this should be fixed as well.

If this is indeed specifically about ICP tokens then you can convert the ICRC-1 account identifier to the legacy identifier (aka “original account id”). In your case h5boe-vqaaa-aaaam-ac36q-cai-ckw43vy.6867bf53ffcaa0cd11f3bb59be8e4d9e71b20d096cc822a5dffecc7561b026ce converts to 4d986d218bf8eb0473e002caf8b6de660e2ce580834190c71bfc6d7f5e82b78d. Your frontend can convert it for the user.

But some wallets actually support the ICRC-1 account identifier even for ICP transfers. If the NNS wallet does not then it is a shortcoming and should be fixed. The wallet we developed here does support sending any token to ICRC-1 account identifiers including ICP.

I suppose he does need subaccounts because his example ICRC-1 account of h5boe-vqaaa-aaaam-ac36q-cai-ckw43vy.6867bf53ffcaa0cd11f3bb59be8e4d9e71b20d096cc822a5dffecc7561b026ce already included one.

No, this will not help him. The dashboard for example does not support searching for ICP transactions based on principal either (even with default subaccount). It only supports searching for legacy account ids (for the ICP token, that is).

I am working on a app that leverages Chain Fusion. Where a user can use one Account Identifier to pay and receive in various token(ICP,SNS,ICRC)

In Ethereum, 1 generated address can be used for all ERC-20 transactions.

We are talking of UX here and easy of use.

Exchanges don’t use Human format
NNS don’t support it
IC explorer don’t support it.

The group have created a Solution that has no Problem, they have single headed kicked themselves out from actual usage and adoption.

No exchange will support human format narrative.

Exchanges will not be like “Oh mate this is ICRC token transaction, ask the user for human format and if this is ICP itself ask for account identifier”

From Exchange perspective, they assume all ICP and its Derivatives should accept one Account Identifier.

The idea is Account Identifier should be used accross all ICRC tokens

The human format should be used for aesthetics only, the implementing wallet/app can convert to account identifier and query the token(icrc) directly.

From “dumb” user perspective they cannot differenciate ICP and Its Derivative Token(ICRC).

If this is impossible, then i think I and the community in support should create legacy ICRC specifications ledger that uses account identifier(not human format) only like ICP.

I think we can build a resolving protocol to allow people custom his/her subaccounts.

For example

icrc://{human_readable_name}:{subaccount_identifier}@{canister_id}

  • human_readable_name is resolved as Blob<29> Principal Id, user can set it to his/her nickname string, for example alice
  • subaccount_identifier is resolved to Bytes32 as Subaccounts, people can set it to default or hot_wallet as String.
  • canister_id is the resolver canister with standard resolving and register function.
  • icrc is the token standard.

then we might have:
icrc://alice:coin_base@aaaa-aa

I can provide a little bit of background here.

What I call “legacy account id” is the type of account identifier that has been used by the ICP ledger since the beginning. It looks like this 4d986d218bf8eb0473e002caf8b6de660e2ce580834190c71bfc6d7f5e82b78d. It is the hash of the principal who controls it plus a subaccount identifier. The differences to an Ethereum address are:

  • Ethereum addresses come from public keys without any subaccounts, so Ethereum addresses are more like principals than they are like legacy account ids
  • Ethereum addresses are 20 bytes while legacy account ids are 32 bytes

A risk with these account identifiers is that you may lose access to your funds if you forget the subaccount that you used to create it. This is not a problem for short subaccount ids like 1,2,3,… but is for long subaccount ids. For example the account id 4d986d218bf8eb0473e002caf8b6de660e2ce580834190c71bfc6d7f5e82b78d was created from principal h5boe-vqaaa-aaaam-ac36q-cai and subaccount id 6867bf53ffcaa0cd11f3bb59be8e4d9e71b20d096cc822a5dffecc7561b026ce. If you somehow forget the value 6867bf53ffcaa0cd11f3bb59be8e4d9e71b20d096cc822a5dffecc7561b026ce, even if you still have control of the principal h5boe-vqaaa-aaaam-ac36q-cai then you can’t acces the funds on 4d986d218bf8eb0473e002caf8b6de660e2ce580834190c71bfc6d7f5e82b78d anymore.

If Ethereum had subaccounts then I doubt they would hash the Ethereum address and the subaccount id together to produce something that looks again like an Ethereum address. They would probably just created an “extended Ethereum address” which is an Ethereum address plus a subaccount id.

What I call “ICRC-1 account identifier” is the one that looks like this h5boe-vqaaa-aaaam-ac36q-cai-ckw43vy.6867bf53ffcaa0cd11f3bb59be8e4d9e71b20d096cc822a5dffecc7561b026ce. It contains a principal and a subaccount id. I think calling it “human readable” is a little bit misleading. It is true that we can identify the two components principal and subaccount, but no other information can be read from it. Like the hypothetical “extended Etherum address” I would call it an “extended principal”. The analogy is really principal ↔ Ethereum address and not legacy account id ↔ Ethereum address.

All tokens on the IC are ICRC-1 tokens and support sending to ICRC-1 accounts, including the ICP token. The ICP token supports both, legacy account ids and ICRC-1 accounts. The same ICRC-1 account id can be used across all tokens on the IC. With one ICRC-1 account id the user can handle all tokens. That is a property that you wanted.

The ICRC-1 account id for the default account is equal to the principal. So principals can be used directly to hold all tokens on the IC. So here is the analogy with Ethereum that you wanted: Ethereum address = principal = single identifier which can be used across all tokens on the IC.

The fact that a principal looks different than an Ethereum address (h5boe-vqaaa-aaaam-ac36q-cai vs 20 bytes hex) should not have any impact on anything. Exchanges supoprt all kinds of tokens and certainly not all those tokens’ account identifiers have the same format as an Ethereum key.

Exchanges don’t care about what an “address” means. They care that there is a Rosetta node for the token. Currently, no token on the IC other than ICP is supported by centralized exchanges, or is it? But that doesn’t have to be the fault of how the account identifiers look. The IC tokens other than ICP simply weren’t interesting enough for the exchanges add. If a token had enough demand and provided a Rosetta node then they would probably support it regardless of how the account identifier looks.

The easiest path forward is probably to fix the holes that you have identified. If dashboard and NNS wallet don’t support ICRC-1 account identifiers for ICP then that should be fixed.

It is unfortunate that ICP launched with a different identifier initially so now we have two kinds of identifiers for the ICP token. It is a source of confusion for sure.

2 Likes

A risk with these account identifiers is that you may lose access to your funds if you forget the subaccount that you used to create it.

This risk sounds very much superfluous. It is the same as using HD wallet to derive a publickey/address and later forgot the derivation path, which didn’t seem to prevent HD wallet from getting adopted widely.

In fact, I would argue that a public account identifier in the form of “principal.subaccount” is a risk of exposing canister-held assets to the public and inviting attackers. Suppose there is a canister managing token assets, with “principal.subaccount” anyone is able to lookup and sum up all assets held by this canister, and it becomes public knowledge. But with a public identifier computed from “hash(principal, subaccount)” it is a lot more difficult to know if a canister holds high-value assets. I would not view this kind of protection the same as security-by-obscurity because one-way hash function is a sound cryptographic concept.

It was short-sighted to re-engineer the account id format when designing ICRC-1, and I don’t recall any application developer asked for it (some did go ahead with principal id only, but it was too rigid to be considered a viable solution). It was a result of some committee postulating a superfluous risk.

2 Likes

I think i, @quinto and @bitbruce and other wallet developers, we should create another Token Specification.

DRC-20 (Dfinity Request Comment).

A token that mirrors ICP ledger itself. no added sugars, or comfort, no solutions for imaginary problems.

I think this ICRC group will not understand your point of view, because their application is not a User-facing Project, they are a Developer-Facing Projects

We that know, because we are the ones to market our apps to the end user. its up to us to create a standard.

We are on our own, as @infu Said “The Ship has sailed”

There is a huge problem on the canister development side. The subaccount is necessary for canisters to hold user assets in separate accounts for security and transparency reasons. Without the subaccount all assets were having to be held together which complicates contract development and opens it to an entire set of bugs where all assets can be drained much more easily.

There is an initiative to work on derived canister IDs that @frederikrothenberger has been looking into. If we had these then subaccounts would be much less necessary.

A number of tokens including OGY are on centralized exchanges using the ICRC version of the rosetta node. Unfortunately, it still doesn’t support ICRC3 ledgers so things like the cycle ledger or non-SNS ICRC tokens won’t work with it. We would need to ask @mariop where that is slotted in order of importance.

Everything is Ok and perfect.

We just want Legacy id as Account Identifier.

We dont want to see Principal and Subaccount. We are ok with Hash of Principal + Subaccount

The risk about losing funds that I mentioned was to my knowledge not one of the reasons that the ICRC-1 initiative was started. The thing users and developers complained about was that it was confusing to have two different things as addresses, account ids and principals. And people liked to have only one. So the task was to design a standard that embeds principals into it, so that it is always possible to use a principal as a destination address. But that also allows the use of subaccount because they are needed. And that is what was done, ICRC-1 has principals as addresses and “extended principals” which are principals plus subaccount. To my knowledge, and we can figure this out by looking at the working group minutes, the reason ICRC-1 started was user demand and people were not happy with account ids.

HD wallets like Ledger Live etc. operate in the following way. They let you use one specific path only, up to the last index. Meaning there is one path which is fixed except for the last index and only the last index can change. Then they first let you open your first subaccount only, meaning that last index has to be 0. Only after the wallet detects that you have received funds in that first account with index 0 does it let you open the subaccount 1. It does not even show you the public key or address of the index 1 account before you have received funds in index 0. That way the wallet can make sure it can always detect by looking at the on-chain history how many indices have been used. So the HD wallets are very much aware of the risk and take counter-measures. Hence, they could get adopted widely. The counter-measures are:

  • make the subaccounts enumerable
  • make sure there are no gaps in the enumeration

In our case we have an unenumerable subaccount space of 32 arbitrary bytes.

The risk is real, not superfluous, both for end users as well as for canisters.

The “privacy” aspect is a red herring. Using “hash(principal, subaccount)” hides the principal and subaccount for some time until the first time when you access those funds. The first time you transfer out of that account you have to reveal principal and subaccount. At least to everyone reading the network and to all node providers and boundary nodes. Privacy based on that should not be relied on.

I would suggest instead that we work on fixing the problems you have identified. They seem to be a small list of fixable problems. You said some pieces of software don’t support ICRC-1 account identifiers:

  • the NNS wallet for the ICP token
  • the dashboard for the ICP token

The ICP ledger by the way fully supports the ICRC-1 standard. The ICP ledger also has an index canister compatible with the index canisters for all other ICRC-1 tokens. @skilesare said that some CEX already support ICRC-1 tokens and that there is an ICRC-1 Rosetta node. So exchange shouldn’t be a problem. With ICRC-1 interface, index canister and Rosetta node I really don’t see anything missing except that some app software pieces need to be updated. This is a much shorter path forward than coming up with a new standard.

Is there anything else I am missing? I am happy to go through this list and fix pain points one by one. Could you elaborate for me one more time why exactly you want the legacy account ids back? I see you write

But why exactly? Because principal.subaccount isn’t supported in some places (-> can be fixed and should have been fixed a long time ago). Or you prefer the aesthetics of legacy account over principal.subaccount? Or the privacy issue?

I am working full time on user-facing DeFI products on the IC and it is my mission to remove as much friction as possible for the users.

1 Like

Can ICRC support both?

If yes, then perfect.

If No, a new specification has to be created with same API with ICRC Specs but with different Implementation that uses Legacy Id(Account identifier)

I personally like the Legacy id

  1. Because of its Aesthetics
  2. Privacy
  3. Ease of Use.

We Work in parallel lets give the community a choice. Lets see the adoption rate.

@bitbruce @quinto What do you think?

IC was appealing to me because it didn’t make the assumption such data would always remain public. There are hopes that more work towards data privacy will fix the shortcoming you listed. At least that was the way such dreams (of data privacy) was sold to us initially by the IC marketing campaign. Designing for the future should be the principle. Revealing “principal.subaccount” in a public address wasn’t adhering to such principles, and is just creating tech debt.

There was never such confusion until some people started designing their own token standards using principal only, and it was BAD idea and THE reason for confusion. Instead of fixing the root of the problem (i.e. get rid of those bad community standards), The ICRC standard erects it further more and now we have to live with such confusions forever! I don’t see a chance that legacy AccountId ever being phased out.

1 Like

I’m not optimistic about this. There were plenty community proposed token standards before ICRC-1. Whole thing was fragmented until the foundation finally did something with SNS and ICRC-1. Bad design decision in adopted standard was one thing, a dysfunctional community (due to fragmentation) was quite another. Not sure which one is “worse” :crazy_face:

1 Like

I can give you one more example on “why exactly”, and this example is even DFINITY’s own! I was looking at ckETH minter, and noticed it does not support minting directly to a canister’s subaccount. Think it is an easy problem to fix? Better think again! If I’m not mistaken, it will require upgrading the minter’s EVM contract (which is non-upgradable, duh!) to emit events with an additional field. All because “principal+subaccount” does not fit into 32 byte! Nice 32-byte long account ids are not just a “nice to have” or “convenient” feature, but it can also prevent months or even years of manpower from being wasted.

As more developers are making use of canisters to hold assets, they will start to notice and demand ckETH/ckERC20 minter to support subaccounts. Good luck! If it ever will be supported…

1 Like

The privacy is fake. The principal is known to the boundary nodes. That is one of the reasons it was moved away from. Until we have some kind of zk transaction or secure enclave encryption you won’t be able to keep the account identifier private.

If you don’t like sub-accounts then build your app to not use them. Just use the principal. As @timo mentioned, there are likely some infrastructure pieces to shore up to make principle IDs searchable as account ids, but that is really the only hurdle. If you never give a user a sub account then a principal operates the same way.

A decent first step would be for Plug, Bitfinity, NFTID, etc to move account id off of the main wallet interface and behind an advanced tab and push everyone toward using just principal ids and having Users just use default accounts.

The NNS should remove the account ID from the ICP tab as well and switch it to the ICRC1 human readable format.

If you really think you need a new standard for some reason I’d encourage you to explore a revised infrastructure set that uses ETH based addresses instead.

There is also the option that people don’t like to speak about but is completely do able which is to incrementally fork the ICP ledger over time so that as funds move out of legacy ledger accounts they get moved to ICRC-1 accounts and the blockchain begins to accommodate both kinds of transactions. Yes, this would require a good bit of effort, but may be worth it in the long run. Unfortunately we can’t just deprecate the legacy transfer functions or really ever get completely rid of the legacy account registry because of existing blackholed and non-maintained services, but we can move to a place where the ICRC-1 account is the dominant format used for go-forward transactions.

For example, the NNS client knows your sub-accounts, so it could, upon loading and asking permission from the user call and upgrade function and submit the mappings between accounts and neuron accounts to the ledger for an upgrade.

The ledger can serve up a get_upgraded_accounts(vec Account) → async vec ICRC1.Account; that serves translated and upgraded accounts to front ends for swap out from the legacy ledger. Over time there will be fewer and fewer non-upgraded accounts.

1 Like

Interesting point. Does the ckBTC minter support minting to subaccounts? Only the ckETH minter does not? I will have to look into this more.

Principals are 29 bytes. So in 32 bytes you can encode a principal plus 16.7 million subaccounts. Not the whole subaccount space but still sufficiently many if you are ok with “the first” 16.7 million from the entire space. Canister principals are only 10 bytes.

You can easily build a ledger that can support both if you design it like that from the beginning. On any legacy ledger implementation you can easily add an ICRC-1 interface on top of it, even when it already has state. Conversely, if you have code for a native ICRC-1 ledger then it will require some code changes to the legacy interface to it. And if it’s an already running ICRC-1 ledger canister with state in it then will be hard to do, then you have to do what @skilesare described.

Yes to both.

Unfortunately the ckETH/ckERC20 minter (or anything that wants to support deposit into ICRC-1 Account) can’t do this trick because the length of subaccount is specified as 32 bytes.

1 Like