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

ERC: Token Registries #22

Closed
frozeman opened this issue Nov 19, 2015 · 27 comments
Closed

ERC: Token Registries #22

frozeman opened this issue Nov 19, 2015 · 27 comments
Labels

Comments

@frozeman
Copy link
Contributor

ERC: 22
Title: Token standard
Status: Draft
Type: Informational
Created: 19-11.2015
Resolution: https://github.com/ethereum/wiki/wiki/Standardized_Contract_APIs

Abstract

Registries allow listing and searching of tokens and can serve as connector between tokens.

Specification

Token Registries

Token registries contain information about tokens. There is at least one global registry (though other may create more like the global Registry) to which you can add your token. Adding your token to it would increase the experience of the user that the GUI Client can use or not.

symbol

function setSymbol(string _s)
function symbol(address _token) constant returns (string)

Sets or returns a short sequence of letters that are used to represent the unit of the coin. When setting, it assumes the msg.sender is the token. Solidity string is on UTF-8 format so this should support any character supported by UTF-8. Symbols are chosen by the contract and it's up to the client to decide how to handle different currencies with similar or identical symbols.

Examples or symbols: USDX, BOB$, Ƀ, % of shares.

name

function setName(string _s)
function name(address _token) constant returns (string)

Sets or returns the name of a token. Solidity string is on UTF-8 format so this should support any character supported by UTF-8. Names are chosen by the contract and it's up to the client to decide how to handle different currencies with similar or identical names.

Examples of names: e-Dollar, BobToken, Bitcoin-Eth.

baseUnit

function setBaseUnit(uint _s)
function baseUnit(address _token) constant returns (uint256)

Sets or returns the base unit of a token. Although most tokens are displayed to the final user as containing decimal points, token values are unsigned integers counting in the smallest possible unit. The client should always display the total units divided by baseUnit. Base units can be any integer but we suggest only using powers of 10. At the moment there is no support for multiple sub-units.

Example: Bob has a balance of 100000 BobTokens, whose base unit is 100. His balance will be displayed on the client as BOB$100.00

Also see #20

@alexvandesande
Copy link

As I've voiced that concern before I'm vehemently against using baseUnit and instead think we should use decimals. For these reasons:

  • Decimals allow to use a lower bytes variable: uint8 will allow up to 255 decimal places. As a reference, if a unit of 1 represents the size of the observable universe, then in order to count the size of a planck length (smallest possible size physics allows) then you would need about 80 decimal places.
  • Having a division unit that is not a power of 10 would create confusion to the user. For example a baseUnit of 7 means that you can only send values that are multiples of 0.142857.. The purpose of client is to make transactions clearer to the user and representing a token transfer of 10 units as 1.42857.. is simply a misrepresentation of reality.
  • Also baseUnit is ambiguous with the base of the number representation (base 10, binary etc). Having a base unit of 16 does not means that a token is supposed to be represented as a hexadecimal, just that the smallest possible divisible unit is 0.0625. The wallet would still represent it using the decimal system (while no user ever asked that, the wallet could display all numbers in binary, hexadecimal or base58 but even if did that would it make sense to do that per coin??)
  • It's how users communicate. "Bitcoin is divisible by 8 decimal points" is a more common and easily understandable comment than "Bitcoin is divisible by 10000000". Actually how many 0s did I just type? Can you tell the difference without counting the 0s in your head?
  • Contracts should never deal with either as it's just for display purposes but If for some reason a contract needs to have a conversion from baseUnit to decimals, then it's a single simple solidity command: 10**decimals.

@alexvandesande
Copy link

I have one counter argument to my own point for weirder units: 12 pence per shillings, 24 hours per day, 7 days per week, 3 foot per yard etc. In that case I would argue that the representation of baseUnit and Symbol is also insufficient as what would actually be required would be a full array of multiples denominations.

In that case the best would be to have a named array on the registry:

{ 1: 'second',
60: 'minute',
360: 'hour',
86400: 'day' }

etc..

@frozeman frozeman added the ERC label Nov 23, 2015
@nmushegian
Copy link

Bump. This ERC is critical for most token-related dapps.
I agree with avsa, decimals makes more sense than baseunit. Though I do disagree with one argument:

Contracts should never deal with either

I think you need to deal with it when dealing with prices/ratios. Ideally a consumer should not need to know the baseunit of tokens hidden inside your system, they should just say "I want to trade 2.5 units of this for one unit of that", where "2.5" is expressed with a consistent fixed-point representation.

@tgerring
Copy link

tgerring commented Jan 8, 2016

Very nice arguments for decimals, @alexvandesande. Beyond your own are there other counterpoints for baseUnit that would make it "better" in some use cases? Perhaps @frozeman can provide some rationale as to the reason for going with baseUnit in the initial proposal to make sure we don't miss some important historical reasoning.

@nmushegian
Copy link

I'm wondering why the setters should be part of the spec. They seem very much like an "admin" function. End users likely never call them. No such functions were public for the token standard. I can think of registries whose setting rules would make these setters dummies anyway.

@nmushegian
Copy link

Another concern, contracts can't yet read arbitrary-length return values like strings! There are some dirty hacks you can do if you can ensure the strings are under one word size, but it's a band-aid until we get new Serenity opcodes.

For now I propose using bytes32 for symbols and names in the actual spec. It should require little refactoring unless you're using push or iteration or something.

@caktux
Copy link

caktux commented Jan 13, 2016

I'm glad to agree with @alexvandesande with those arguments. I was surprised to see baseUnit instead of the already much discussed decimals. Since this is for tokens and not yards, I think it would be much better to stick to decimals, so even in the case of an eShillings, it would be easy enough to present the decimals in their imperial glory. Same goes for time units but without the sarcasm.

I think setters are very important for this standard, so contracts that register themselves don't have to implement and know which registry implements which method. Most methods in the token standard were implicitly setters (approve() is most obvious, but so are transfer() and transferFrom(); they all alter the state [when successful].)

I also agree that both symbols and names should be bytes32, especially if there are issues with strings when returning values between contracts. Having a hard limit on the length of those (and using a single storage slot) also seem more sound.

@coder5876
Copy link

@frozeman

When setting, it assumes the msg.sender is the token.

So token contracts need to support setter functions for setting their name etc in registries? And it would be up to the implementation of the token contract itself to supply the proper authentication methods for who is allowed to set the name etc?

@coder5876
Copy link

I think the most important thing about this, and the hardest to get right is the economics of how to properly allocate the names and symbols for the tokens, i.e. name squatting. The moment the first registry launches people are immediately going to register (Dollar, $), (Euro, €), (Bitcoin, Ƀ) etc. So I fear that even if we have a good standard here this will still remain a problem.

I guess for private and semi-private registries with access control to only approved tokens this standard will still be valuable. So the above might be out of scope for this discussion and can be deferred to when more public registries launch.

@caktux
Copy link

caktux commented Jan 13, 2016

Also thought about msg.sender being the token but forgot to mention. Not only would contracts have to implement support for the registry standard, but it would mean we can't really use the Token standard until this one is also finalized...

Having to set each property separately also seems inefficient. Setting all of those in a single transaction would make a lot more sense, while allowing to pass a contract address to solve the msg.sender issue. Otherwise each setter would also need a contract parameter. In any case, setters should take a contract address and not just use msg.sender.

Proposed single-method setter:

setToken(address _contract, bytes32 _symbol, bytes32 _name, uint256 _decimals) returns (bool success)

If we do stick with separate setters, inputs should probably be more descriptive than _s

I think there should also be methods for getting the contract address by name and symbol:

tokenByName(bytes32 _name) constant returns (address)
tokenBySymbol(bytes32 _symbol) constant returns (address)

@christianlundkvist has a very good point about the economics, especially for global registries. If we agree that this standard is ok as a first-come-first-serve basis then fine, but it might not be the best standard to use for any global registry.

@frozeman
Copy link
Contributor Author

I agree with all of this. besides i would like to keep names string type, as we will improve this type in solidly in the future. Also should token names not be too long, we can add a max to the standard.

I agree that registering a token should be done from the token contract itself. Ideally this is done in the constructor function of the token contract.

@nmushegian
Copy link

I still don't see why we should care how registry entries are set. Each system has its own logic to decide which tokens to allow or not. End users do not call those functions often, do you expect a registry writer to care about supporting GUI setters? The difference between this and the "setters" in the token standard is that here there is a clear "user" vs "admin" feature distinction.

That said, @caktux setter makes the most sense so far, if we are to include one.

as we will improve this type in solidly in the future

It's not just solidity, you need a VM change to use strings properly. Does this standard really need to wait until Serenity? Or do you mean there should be a sort of "try get string return value with length N" in Solidity?

@nmushegian
Copy link

I agree that registering a token should be done from the token contract itself. Ideally this is done in the constructor function of the token contract.

I don't see anything to gain from this (any contract can pretend to be a token so you must curate them anyway), but plenty to lose: you can't register tokens into registries if the token was made with no knowledge of the registry standard and with no generic "exec" capabilities. Again supporting @caktux's setter if we must use one at all.

@frozeman
Copy link
Contributor Author

@chriseth can you comment on string support in solidity?

@caktux
Copy link

caktux commented Jan 13, 2016

@frozeman we do not agree about where this should be called from; the token creator should be able to call setToken and not have to implement it in the token's constructor.

@nmushegian has a really good point about VM limitations, and bytes32 seems plenty of characters for both a token name and its symbol.

Pushing the single-method setter idea, I think a single-method getter would also be better:

token(address _contract) returns (bytes32 _symbol, bytes32 _name, uint256 _decimals)

@frozeman
Copy link
Contributor Author

So the setToken, uses msg.sender to determine that the contract itself is trying to set its registry, right?
Or how would you prevent anybody from registering anything? (Or overwriting)

@nmushegian
Copy link

  • Tokens do not have a unique registry, I bet any token DAO will curate its own registries and point to existing tokens
  • Tokens might not want to be part of a registry when written, but later decide they do
  • There is no mention of any "hidden behavior" your token needs to have in ERC20

My proposed alternative is to leave the behavior up to the user. Any authorization pattern (have an owner or a DOUG-like or Authority) will do the trick. Up to you. It doesn't affect the signature. That's almost the same as saying its undefined, which makes me want to argue we should drop the setters again.

@caktux
Copy link

caktux commented Jan 15, 2016

@frozeman No, that's what I keep saying. It's already too late to require tokens to implement this. Digix is live, the Token Standard is now set in stone and existing contracts simply can't register themselves to a global registry. Not only that, but passing a contract address doesn't change anything as to who or what can register names and symbols; you'd only prevent legitimate existing tokens from getting registered. What you're pointing out is the issue @christianlundkvist mentioned. If we want to allow changes to a registry entry, you just check if (msg.sender == entry.contract || msg.sender == entry.creator) where entry.creator was set from the initial msg.sender.

I see your point about setters @nmushegian but I still think it should be part of the standard, so that developers won't have to call a different method for every registry they might need to use. "Is that a Standard Token Registry? Yes, but here's the setter method for this one..."

@larspensjo
Copy link

I think it is problematic to create an official registry of tokens, mostly because of the economics. It can be assumed that there is no model of economics that is perfect. Instead, we should expect there to be many registries, all based on their own economics. E.g. some may simply be "first grab", while other have intricate ways of managing fees.

If so, it means that creators of tokens will have to decide where they want to register, which can be more than one place. There will most probably be a network effect, with preferred solutions. This can be problematic from the user point of view. They will have to manage what registries they trust.Ultimately, this should be supported in a user friendly way by the UI. The same goes for exchanges.

This way would mean management of registries is completely decentralized, except for the protocol. Maybe this was already obvious to everyone except me...

@juanfranblanco
Copy link

Bumping this, it will be ideal together with the token standard as it would allow any contract to use any asset as opposed to a single one. It will also simplify the creation of apis as they only need to worry about the token names as opposed the contract addresses.

I agreed that there can be many registries, as a registry can be part of a wider application. IE specific "wallet" for a dapp.

@clowestab
Copy link

Is there any updated insight to be shared on this?

Given the progress of the ENS (EIP 162) can we not ignore the Economics of token naming here and rather consider it from the ENS.

To clarify. A token registers a 'token-name.token' name which points to a contract implementing EIP 20. The Economics/allocation issues are handled within the name registration functionality. You can name your token whatever you like - it is essentially a 'Display name'. As such multiple tokens might be called 'Bitcoin' or 'USD', yet only one will be referred to by 'usd.token'.

My point being to attempt to focus our 'Economics brain power' to the development of a perfect ENS - abstract all the Economics to the ENS.

@realcodywburns
Copy link
Contributor

I think that it would be beneficial for common contract types to be able to reliably register and be found via the ens system. For the tokens specifically, assuming they are EIP 20 compliant, the ability to find locate and us a token would only require knowing its name.

@MicahZoltu
Copy link
Contributor

@frozeman I'm confused by this example, it doesn't seem to align with the description above it:

Bob has a balance of 100000 BobTokens, whose base unit is 100. His balance will be displayed on the client as BOB$100.00

100000 / 100 = 1000

The description above states:

The client should always display the total units divided by baseUnit.

@jooray
Copy link

jooray commented Jul 10, 2017

@realcodywburns This is still not good enough for wallets that want to display all standard tokens that the user owns. You need an easy way to iterate through all the tokens. Also a lookup by address is very useful.

@Arachnid
Copy link
Contributor

It's possible to iterate over all the subdomains of a domain using the events emitted by the ENS registry. I expect in the long run that the complete list of tokens will be so long as to make enumerating them all for each user impractical, however.

@github-actions
Copy link

There has been no activity on this issue for two months. It will be closed in a week if no further activity occurs. If you would like to move this EIP forward, please respond to any outstanding feedback or add a comment indicating that you have addressed all required feedback and are ready for a review.

@github-actions github-actions bot added the stale label Jan 19, 2022
@github-actions
Copy link

github-actions bot commented Feb 2, 2022

This issue was closed due to inactivity. If you are still pursuing it, feel free to reopen it and respond to any feedback or request a review in a comment.

@github-actions github-actions bot closed this as completed Feb 2, 2022
bumblefudge pushed a commit to bumblefudge/EIPs that referenced this issue Feb 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests