ERC: Standard URI scheme with metadata, value and byte code #67

Closed
alexvandesande opened this Issue Feb 17, 2016 · 90 comments

Comments

Projects
None yet
@alexvandesande
Contributor

alexvandesande commented Feb 17, 2016

This proposal is inspired by BIP 21 and could apply to IBAN address format but can be extended to other proposed addresses formats. Imagine these scenarios:

  • An exchange or a instant converter like shape shift wants to create a single ethereum address for payments that will be converted into credit in their internal system or output bitcoin to an address
  • A store wants to show a QR code to a client that will pop up a payment for exactly 12.34 ethers, which contains metadata on the product being bought
  • A betting site wants to provide a link that the user can click on his site and it will open a default ethereum wallet and and execute a specific contract with given parameters
  • A dapp in Mist wants so simply ask the user to sign a transaction with a specific abi in a single call

In all these scenarios, the provider wants to set up internally a transaction, with a recipient, an associated number of ethers (or none) and optional byte code, all without requiring any fuss from the end user that is expected simply to choose a sender and authorise the transaction.

Currently implementations for this are wonky: shape shift creates tons of temporary addresses and uses an internal system to check which one correspond to which metadata, there isn't any standard way for stores that want payment in ether to put specific metadata about price on the call and any app implementing contracts will have to use different solutions depending on the client they are targeting.

I propose adding, beyond address, also optional byte code and value to any proposed address standard. Of course this would make the link longer, but it should not be something visible to the user, instead it should be shown as a visual code (QR or otherwise), a link or some other way to pass the information.

If properly implemented in all wallets, this should make execution of contracts directly from wallets much simpler as the wallet client only needs to put the byte code by reading the qr code.

If we follow the bitcoin standard, the result would be:

 ethereum:<address>[?value=<value>][?gas=<suggestedGas>][?data=<bytecode>]

Other data could be added, but ideally the client should take them from elsewhere in the blockchain, so instead of having a label or a message to be displayed to the users, these should be read from an identity system or metadata on the transaction itself.

Example:

Clicking this link would open a transaction that would try to send 5 unicorns to address deadbeef. The user would then simply to approve, based on each wallet UI.

 ethereum:0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7?gas=100000&data=0xa9059cbb00000000000000000000000000000000000000000000000000000000deadbeef0000000000000000000000000000000000000000000000000000000000000005

Without byte code

Alternatively, the byte code could be generated by the client and the request would be in plain text:

 ethereum:<address>[?value=<value>][?gas=<suggestedGas>][?function=nameOfFunction(param)]

Example:

This is the same function as above, to send 5 unicorns from he sender to deadbeef, but now with a more readable function, which the client converts to byte code.

 ethereum:0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7?gas=100000&function=transfer(address 0xdeadbeef, uint 5)
@Gustav-Simonsson

This comment has been minimized.

Show comment
Hide comment

@alexvandesande alexvandesande changed the title from ERC: Add metadata information (value and bytecode) to address standard to ERC: Standard URI scheme with metadata, value and byte code Feb 17, 2016

@alexvandesande

This comment has been minimized.

Show comment
Hide comment
@alexvandesande

alexvandesande Feb 17, 2016

Contributor

Thanks @Gustav-Simonsson , I added the reference to the main text and modified the title to reflect that!

Contributor

alexvandesande commented Feb 17, 2016

Thanks @Gustav-Simonsson , I added the reference to the main text and modified the title to reflect that!

@axic

This comment has been minimized.

Show comment
Hide comment
@axic

axic Feb 17, 2016

Member

Why call the data field bytecode? It is less likely to be bytecode in such a transaction (although it could be), more likely to be arguments to a method.

Perhaps suggestedgas / mingas could be a useful optional field in that case.

Member

axic commented Feb 17, 2016

Why call the data field bytecode? It is less likely to be bytecode in such a transaction (although it could be), more likely to be arguments to a method.

Perhaps suggestedgas / mingas could be a useful optional field in that case.

@alexvandesande

This comment has been minimized.

Show comment
Hide comment
@alexvandesande

alexvandesande Feb 17, 2016

Contributor

I just don't want to call the variable data. All variables hold data, it's as specific as calling it stuff.. ;-)

Contributor

alexvandesande commented Feb 17, 2016

I just don't want to call the variable data. All variables hold data, it's as specific as calling it stuff.. ;-)

@axic

This comment has been minimized.

Show comment
Hide comment
@axic

axic Feb 17, 2016

Member

@alexvandesande lets call it stuff or things :)

data might sound generic, yet that is how it is called in every interface. I just don't think bytecode is a good choice. Any other ideas? How about command/commands/cmd/arguments/args?

My reasoning is it only asks as (EVM) bytecode when deploying a contract, in every other scenario it cannot be bytecode as far as I know.

Member

axic commented Feb 17, 2016

@alexvandesande lets call it stuff or things :)

data might sound generic, yet that is how it is called in every interface. I just don't think bytecode is a good choice. Any other ideas? How about command/commands/cmd/arguments/args?

My reasoning is it only asks as (EVM) bytecode when deploying a contract, in every other scenario it cannot be bytecode as far as I know.

@ethernomad

This comment has been minimized.

Show comment
Hide comment
@ethernomad

ethernomad Feb 21, 2016

In the JavaScript API the parameter is called data. Probably best just stick with that.

How should the data field be encoded? In base64 like https://en.wikipedia.org/wiki/Data_URI_scheme ?

In the JavaScript API the parameter is called data. Probably best just stick with that.

How should the data field be encoded? In base64 like https://en.wikipedia.org/wiki/Data_URI_scheme ?

@frozeman frozeman added the ERC label Feb 22, 2016

@alexvandesande alexvandesande referenced this issue in ethereum/mist Feb 23, 2016

Open

Request: deep linking/URIs #154

@Smithgift

This comment has been minimized.

Show comment
Hide comment
@Smithgift

Smithgift Mar 3, 2016

Two wei: I think we should use hexidecimal for these URIs if possible. Everywhere else we use hex, and it'll be easier to convert to and back.

Two wei: I think we should use hexidecimal for these URIs if possible. Everywhere else we use hex, and it'll be easier to convert to and back.

@axic

This comment has been minimized.

Show comment
Hide comment
@axic

axic Mar 10, 2016

Member

@Smithgift I'm all for the hexadecimal representation.

The above proposal uses the ICAP as the address. Would it make sense defining support multiple address formats? ICAP, address (incl. checksummed), etc?

Member

axic commented Mar 10, 2016

@Smithgift I'm all for the hexadecimal representation.

The above proposal uses the ICAP as the address. Would it make sense defining support multiple address formats? ICAP, address (incl. checksummed), etc?

@killerstorm

This comment has been minimized.

Show comment
Hide comment
@killerstorm

killerstorm Apr 4, 2016

Have you considered security implications of URIs with byte code?

Using an URI with a data field is akin to signing a message written by another party: you should either trust that party, or verify the message yourself.

Otherwise this can be used for CSRF-style attacks. E.g. suppose that you want to buy a donut, you get an URI from the merchant, check that value is reasonable and submit it.

But this transaction will steal your gold/shares/house, as it might encode an instruction to send your assets to someone else.

One way to address this is to segregate different assets into different addresses. If you use an address which only holds ether, nothing can be stolen. But this cannot be enforced by a wallet as a wallet might be unaware of a "special powers" an address might have.

E.g perhaps an address doesn't hold any assets, but is associated with your identity, which will give a third party to sign a petition on your behalf.

The only way to address this is to transfer funds to a fresh address first, which sounds kinda inefficient (now you need two transactions).

Other way to address this is to enable 'data' payments only to known whitelisted addresses which wallet can understand.

In principle it might be enough to display 'the meaning' of addresses which are known to the wallet. E.g. user wants to buy a donut, gets URI from a merchant and observes that it wants to do something with a gold contract. Understanding that buying a donut shouldn't in any way involve gold, user will cancel a transaction. Ideally if contract is recognized it should parse data and display details of the call being made.

But in this case there is a risk that a keypair is shared between several different wallets, and while wallet A knows that address X is a gold contract, wallet B doesn't, so it will happily sign a gold-stealing transaction thinking it's something new and harmless.

Have you considered security implications of URIs with byte code?

Using an URI with a data field is akin to signing a message written by another party: you should either trust that party, or verify the message yourself.

Otherwise this can be used for CSRF-style attacks. E.g. suppose that you want to buy a donut, you get an URI from the merchant, check that value is reasonable and submit it.

But this transaction will steal your gold/shares/house, as it might encode an instruction to send your assets to someone else.

One way to address this is to segregate different assets into different addresses. If you use an address which only holds ether, nothing can be stolen. But this cannot be enforced by a wallet as a wallet might be unaware of a "special powers" an address might have.

E.g perhaps an address doesn't hold any assets, but is associated with your identity, which will give a third party to sign a petition on your behalf.

The only way to address this is to transfer funds to a fresh address first, which sounds kinda inefficient (now you need two transactions).

Other way to address this is to enable 'data' payments only to known whitelisted addresses which wallet can understand.

In principle it might be enough to display 'the meaning' of addresses which are known to the wallet. E.g. user wants to buy a donut, gets URI from a merchant and observes that it wants to do something with a gold contract. Understanding that buying a donut shouldn't in any way involve gold, user will cancel a transaction. Ideally if contract is recognized it should parse data and display details of the call being made.

But in this case there is a risk that a keypair is shared between several different wallets, and while wallet A knows that address X is a gold contract, wallet B doesn't, so it will happily sign a gold-stealing transaction thinking it's something new and harmless.

@ShockiTV

This comment has been minimized.

Show comment
Hide comment
@ShockiTV

ShockiTV Apr 4, 2016

I dont get what has 'data' with stealing anything from your account. You specify value and gas and it can play with just these on receiving end.

ShockiTV commented Apr 4, 2016

I dont get what has 'data' with stealing anything from your account. You specify value and gas and it can play with just these on receiving end.

@killerstorm

This comment has been minimized.

Show comment
Hide comment
@killerstorm

killerstorm Apr 4, 2016

Data can specify instructions to transfer assets held using smart contracts. value is irrelevant here. Perhaps you should read more on CSRF, confused deputy attack, how Ethereum works etc.

It's basically like signing a document prepared by someone else without reading it: it can do arbitrary nasty things.

Data can specify instructions to transfer assets held using smart contracts. value is irrelevant here. Perhaps you should read more on CSRF, confused deputy attack, how Ethereum works etc.

It's basically like signing a document prepared by someone else without reading it: it can do arbitrary nasty things.

@edmundedgar

This comment has been minimized.

Show comment
Hide comment
@edmundedgar

edmundedgar Apr 5, 2016

We did a bit of this on the Reddit thread but I think the issue @killerstorm is talking about is common to any means of sharing the address of a contract, rather than being particular to sharing that address along with parameters. If you're signing what you think is a contract to sign up for a credit card and it's really a contract to give somebody your house, you're going to have a bad day.

Bringing parameters along too potentially makes it slightly easier to exploit, because if the "transfer your house" signature happened to be along a dotted line marked "function transferYourHouse()" that'll give the game away if you have to do some work to specify it, but whatever method we end up with for identifying contracts can't safely rely on everything important having an unambiguous function name.

We did a bit of this on the Reddit thread but I think the issue @killerstorm is talking about is common to any means of sharing the address of a contract, rather than being particular to sharing that address along with parameters. If you're signing what you think is a contract to sign up for a credit card and it's really a contract to give somebody your house, you're going to have a bad day.

Bringing parameters along too potentially makes it slightly easier to exploit, because if the "transfer your house" signature happened to be along a dotted line marked "function transferYourHouse()" that'll give the game away if you have to do some work to specify it, but whatever method we end up with for identifying contracts can't safely rely on everything important having an unambiguous function name.

@axic

This comment has been minimized.

Show comment
Hide comment
@axic

axic Apr 6, 2016

Member

@killerstorm wouldn't any implementation display all these details and let them be approved by the user before doing anything? Wallets could decide to reject any URL which contains bytecode. Others could display what it does if it's for a known purpose (e.g. it would be easy to parse if it is for calls on the token interface).

Member

axic commented Apr 6, 2016

@killerstorm wouldn't any implementation display all these details and let them be approved by the user before doing anything? Wallets could decide to reject any URL which contains bytecode. Others could display what it does if it's for a known purpose (e.g. it would be easy to parse if it is for calls on the token interface).

@killerstorm

This comment has been minimized.

Show comment
Hide comment
@killerstorm

killerstorm Apr 8, 2016

@axic EIP specification should cover wallet's behavior. You can't just leave it up to wallet implementors to decide. Some of them might be not aware of security concerns.

@axic EIP specification should cover wallet's behavior. You can't just leave it up to wallet implementors to decide. Some of them might be not aware of security concerns.

@alexvandesande

This comment has been minimized.

Show comment
Hide comment
@alexvandesande

alexvandesande Apr 25, 2016

Contributor

I don't think this issue is at all related to the uri scheme or bytecode but it's a general problem to any Ethereum client that works with dapps: it has to, as much as it can, display information about what the contract you are about to execute does.

There are many ways of doing those that wel be exploring on the wallet, and I hope the community comes with many others:

  • reverse engineering the bytecode to match known fiction formats and show either you are calling a "donutstore.buyDonut()" or "gold.transfer()"
  • simulate the transaction in the front end and see if it results in transfer of tokens or other common use cases
  • add a web of trust so that the user can check if a given contract has been audited by someone they trust
  • add prediction markets to predict future behavior of that particular contract

All these apply either we are talking about a transaction has been initiated by a js call in a dapp, a link or a qrcode.

On Apr 5, 2016, at 10:59, Edmund Edgar notifications@github.com wrote:

We did a bit of this on the Reddit thread but I think the issue @killerstorm is talking about is common to any means of sharing the address of a contract, rather than being particular to sharing that address along with parameters. If you're signing what you think is a contract to sign up for a credit card and it's really a contract to give somebody your house, you're going to have a bad day.

Bringing parameters along too potentially makes it slightly easier to exploit, because if the "transfer your house" signature happened to be along a dotted line marked "function transferYourHouse()" that'll give the game away if you have to do some work to specify it, but whatever method we end up with for identifying contracts can't safely rely on everything important having an unambiguous function name.


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub

Contributor

alexvandesande commented Apr 25, 2016

I don't think this issue is at all related to the uri scheme or bytecode but it's a general problem to any Ethereum client that works with dapps: it has to, as much as it can, display information about what the contract you are about to execute does.

There are many ways of doing those that wel be exploring on the wallet, and I hope the community comes with many others:

  • reverse engineering the bytecode to match known fiction formats and show either you are calling a "donutstore.buyDonut()" or "gold.transfer()"
  • simulate the transaction in the front end and see if it results in transfer of tokens or other common use cases
  • add a web of trust so that the user can check if a given contract has been audited by someone they trust
  • add prediction markets to predict future behavior of that particular contract

All these apply either we are talking about a transaction has been initiated by a js call in a dapp, a link or a qrcode.

On Apr 5, 2016, at 10:59, Edmund Edgar notifications@github.com wrote:

We did a bit of this on the Reddit thread but I think the issue @killerstorm is talking about is common to any means of sharing the address of a contract, rather than being particular to sharing that address along with parameters. If you're signing what you think is a contract to sign up for a credit card and it's really a contract to give somebody your house, you're going to have a bad day.

Bringing parameters along too potentially makes it slightly easier to exploit, because if the "transfer your house" signature happened to be along a dotted line marked "function transferYourHouse()" that'll give the game away if you have to do some work to specify it, but whatever method we end up with for identifying contracts can't safely rely on everything important having an unambiguous function name.


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub

@niran

This comment has been minimized.

Show comment
Hide comment
@niran

niran Apr 26, 2016

We probably need to add a way for apps to suggest a sending address with a from parameter. Authenticators that handle multiple accounts need a way to know which account was active in the app that generated the URL.

niran commented Apr 26, 2016

We probably need to add a way for apps to suggest a sending address with a from parameter. Authenticators that handle multiple accounts need a way to know which account was active in the app that generated the URL.

@alexvandesande

This comment has been minimized.

Show comment
Hide comment
@alexvandesande

alexvandesande Apr 26, 2016

Contributor

But the whole point was that the "from" field would be set by the client. But I suppose "from" and some custom parameters could be useful

On Apr 25, 2016, at 21:54, Niran Babalola notifications@github.com wrote:

We probably need to add a way for apps to suggest a sending address with a from parameter. Authenticators that handle multiple accounts need a way to know which account was active in the app that generated the URL.


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub

Contributor

alexvandesande commented Apr 26, 2016

But the whole point was that the "from" field would be set by the client. But I suppose "from" and some custom parameters could be useful

On Apr 25, 2016, at 21:54, Niran Babalola notifications@github.com wrote:

We probably need to add a way for apps to suggest a sending address with a from parameter. Authenticators that handle multiple accounts need a way to know which account was active in the app that generated the URL.


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub

@niran

This comment has been minimized.

Show comment
Hide comment
@niran

niran Apr 26, 2016

The client sets all the fields. They're just hints that can be ignored. from is particularly useful when keys are managed in a separate process from a running dapp, which will be a common choice for its security benefits. Simple payments don't need from, but voting for a DAO proposal needs to be done from the account that holds tokens, which the dapp already knows.

niran commented Apr 26, 2016

The client sets all the fields. They're just hints that can be ignored. from is particularly useful when keys are managed in a separate process from a running dapp, which will be a common choice for its security benefits. Simple payments don't need from, but voting for a DAO proposal needs to be done from the account that holds tokens, which the dapp already knows.

@killerstorm

This comment has been minimized.

Show comment
Hide comment
@killerstorm

killerstorm Apr 26, 2016

@alexvandesande You have been warned about security implications. If people will lose their property because of the way these URIs are handled you will be responsible for that.

@edmundedgar I think normally contracts are structured in such a way that sending ether to that contract without attached data cannot result in unexpected loss (aside from loss of the sent ether which is expected). Thus it's normally safe to sign a simple send transaction as potential risk is well understood and contained.

In other words, only an insane contract will do something destructive upon receiving ether. However, potential loss will be restricted to the value held within such an insane contract, which is normally zero.

So yes, adding an ability to attach data has serious security implication. Just because things aren't perfect from security perspectives right now doesn't mean it's OK to create new holes.

@alexvandesande You have been warned about security implications. If people will lose their property because of the way these URIs are handled you will be responsible for that.

@edmundedgar I think normally contracts are structured in such a way that sending ether to that contract without attached data cannot result in unexpected loss (aside from loss of the sent ether which is expected). Thus it's normally safe to sign a simple send transaction as potential risk is well understood and contained.

In other words, only an insane contract will do something destructive upon receiving ether. However, potential loss will be restricted to the value held within such an insane contract, which is normally zero.

So yes, adding an ability to attach data has serious security implication. Just because things aren't perfect from security perspectives right now doesn't mean it's OK to create new holes.

@alexvandesande

This comment has been minimized.

Show comment
Hide comment
@alexvandesande

alexvandesande Apr 26, 2016

Contributor

@killerstorm the security implications you are suggesting also apply to the current model where the site builds a transaction in javascript and the client just confirms it. How is it specific to this EIP?

Contributor

alexvandesande commented Apr 26, 2016

@killerstorm the security implications you are suggesting also apply to the current model where the site builds a transaction in javascript and the client just confirms it. How is it specific to this EIP?

@taoteh1221

This comment has been minimized.

Show comment
Hide comment
@taoteh1221

taoteh1221 Apr 26, 2016

I agree with @killerstorm that data / bytecode should not be a URI parameter. You'd most likely be patching newly-discovered vulnerabilities on a monthly basis until the end of time...that's a hacker's field day to be able to add executable data to a URI. That's why web2 browsers don't allow it.

I agree with @killerstorm that data / bytecode should not be a URI parameter. You'd most likely be patching newly-discovered vulnerabilities on a monthly basis until the end of time...that's a hacker's field day to be able to add executable data to a URI. That's why web2 browsers don't allow it.

@alexvandesande

This comment has been minimized.

Show comment
Hide comment
@alexvandesande

alexvandesande Apr 26, 2016

Contributor

It's not a general executable data, it's data meant to be executed only in the context of an EVM. Any vulnerability there that allow execution outside of that environment is a big issue for the ecosystem as a whole that should be patched, independently of the particular way the transaction was initiated.

Contributor

alexvandesande commented Apr 26, 2016

It's not a general executable data, it's data meant to be executed only in the context of an EVM. Any vulnerability there that allow execution outside of that environment is a big issue for the ecosystem as a whole that should be patched, independently of the particular way the transaction was initiated.

@killerstorm

This comment has been minimized.

Show comment
Hide comment
@killerstorm

killerstorm Apr 26, 2016

@alexvandesande The difference is that when a site builds a transaction, wallet knows the context. It might associate a particular account with a particular context.

It can work similarly to the same-origin policy on the web: a web site can only work with its own data. E.g. code which is executed in the context of gmail.com is able to send emails in my name, but code is executed in the context of bash.org cannot.

If one uses URIs, the origin/context is not known to the wallet, so it doesn't know what account will be safe to use. It might ask the user about the context, e.g. "Did you receive this URI from a trusted source?", but users are generally bad with that kind of stuff.

@alexvandesande The difference is that when a site builds a transaction, wallet knows the context. It might associate a particular account with a particular context.

It can work similarly to the same-origin policy on the web: a web site can only work with its own data. E.g. code which is executed in the context of gmail.com is able to send emails in my name, but code is executed in the context of bash.org cannot.

If one uses URIs, the origin/context is not known to the wallet, so it doesn't know what account will be safe to use. It might ask the user about the context, e.g. "Did you receive this URI from a trusted source?", but users are generally bad with that kind of stuff.

@alexvandesande

This comment has been minimized.

Show comment
Hide comment
@alexvandesande

alexvandesande Apr 26, 2016

Contributor

@killerstorm in that case, clients could implement variations of same origin policies. Mist will know where the link was clicked. If someone builds an ethereum extension, it would know the page origin too. If someone is building an app that accepts any external links, then it's up to that app to handle their policies.

And in all those cases it's essential for ethereum clients to show as much information as possible about the transaction as they can. A malicious app in Mist can also attempt to execute a transaction that will not do what it says it will do and we can't prevent it (if an app wants to receive payment in digix gold, it's acceptable for them to request a transaction from the digix contract, even thou they are not digix themselves).

Contributor

alexvandesande commented Apr 26, 2016

@killerstorm in that case, clients could implement variations of same origin policies. Mist will know where the link was clicked. If someone builds an ethereum extension, it would know the page origin too. If someone is building an app that accepts any external links, then it's up to that app to handle their policies.

And in all those cases it's essential for ethereum clients to show as much information as possible about the transaction as they can. A malicious app in Mist can also attempt to execute a transaction that will not do what it says it will do and we can't prevent it (if an app wants to receive payment in digix gold, it's acceptable for them to request a transaction from the digix contract, even thou they are not digix themselves).

@pelle

This comment has been minimized.

Show comment
Hide comment
@pelle

pelle Apr 26, 2016

I really like the function parameter. It's an elegant solution. I like others think it's a bad idea to even standardize a huge security hole like the bytecode parameter. The way tech journalists work once fraudsters figure out how to use it, it will unfortunately be a setback for Ethereum.

pelle commented Apr 26, 2016

I really like the function parameter. It's an elegant solution. I like others think it's a bad idea to even standardize a huge security hole like the bytecode parameter. The way tech journalists work once fraudsters figure out how to use it, it will unfortunately be a setback for Ethereum.

@alexvandesande

This comment has been minimized.

Show comment
Hide comment
@alexvandesande

alexvandesande Apr 26, 2016

Contributor

@killerstorm would replacing pure data by the function parameters (recently added) address your concerns?

Contributor

alexvandesande commented Apr 26, 2016

@killerstorm would replacing pure data by the function parameters (recently added) address your concerns?

@axic

This comment has been minimized.

Show comment
Hide comment
@axic

axic Apr 26, 2016

Member

If the bytecode field is a security risk, how are function parameters not? It surely helps a lot to show what the method name is without knowing the contract (as you cannot retrieve that from the method hash), but it wont reassure you that getBalance() is not actually a concealed transfer().

Wouldn't it make more sense having a security recommendation what wallets should and shouldn't do?

I do like having both data (bytecode) and function.

Member

axic commented Apr 26, 2016

If the bytecode field is a security risk, how are function parameters not? It surely helps a lot to show what the method name is without knowing the contract (as you cannot retrieve that from the method hash), but it wont reassure you that getBalance() is not actually a concealed transfer().

Wouldn't it make more sense having a security recommendation what wallets should and shouldn't do?

I do like having both data (bytecode) and function.

@niran

This comment has been minimized.

Show comment
Hide comment
@niran

niran Apr 26, 2016

Bytecode opens up the whole EVM and Solidity's function handling as an attack surface. I have a pretty good understanding of what can go wrong with malicious function parameters, but arbitrary malicious bytecode sent to a contract address isn't something I've ever looked into. If I were developing a key manager, I'd be doing my users a service by only signing transactions that I understand. The function interface should be the primary one, and I'd advise not supporting arbitrary bytecode until there's a use case for it. It's probably safe, but it's not just as safe as a function call.

niran commented Apr 26, 2016

Bytecode opens up the whole EVM and Solidity's function handling as an attack surface. I have a pretty good understanding of what can go wrong with malicious function parameters, but arbitrary malicious bytecode sent to a contract address isn't something I've ever looked into. If I were developing a key manager, I'd be doing my users a service by only signing transactions that I understand. The function interface should be the primary one, and I'd advise not supporting arbitrary bytecode until there's a use case for it. It's probably safe, but it's not just as safe as a function call.

@niran

This comment has been minimized.

Show comment
Hide comment
@niran

niran Apr 27, 2016

We should also consider extending the function syntax to allow nested functions. Consider the wallet contract's execute method. If my dapp wants to request approval for unicorn tokens, it can generate a URI with a function parameter of execute(address 0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7, uint 0, bytes 0x...). Authenticators can display more useful information if the nested transaction data is provided with the function syntax instead of raw bytes, like function approve(...). This doesn't improve security since arbitrary bytes will always be valid, but it allows authenticators to build a better user experience.

niran commented Apr 27, 2016

We should also consider extending the function syntax to allow nested functions. Consider the wallet contract's execute method. If my dapp wants to request approval for unicorn tokens, it can generate a URI with a function parameter of execute(address 0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7, uint 0, bytes 0x...). Authenticators can display more useful information if the nested transaction data is provided with the function syntax instead of raw bytes, like function approve(...). This doesn't improve security since arbitrary bytes will always be valid, but it allows authenticators to build a better user experience.

@tayvano

This comment has been minimized.

Show comment
Hide comment
@tayvano

tayvano Apr 27, 2016

@killerstorm

Using an URI with a data field is akin to signing a message written by another party: you should either trust that party, or verify the message yourself.

Maybe I'm confused, but how is this different than how people are handling it today? Right now if you have a contract where you want a user to send you ETH + data, or increase the gas, the contract owner posts the information and instructions on what to do. ie: Using Jaxx, do this. Using MyEtherWallet, do this. Using Mist, do this. Or command line do (eth.SendTransaction({ ... }). Paste this data. Change default gas to this. Etc.

By providing a URI you are providing a shortcut but it is not anything that isn't currently happening.

If there are security concerns with the data field, then they are concerns that should be addressed in a more broad scope than just this EIP.

tayvano commented Apr 27, 2016

@killerstorm

Using an URI with a data field is akin to signing a message written by another party: you should either trust that party, or verify the message yourself.

Maybe I'm confused, but how is this different than how people are handling it today? Right now if you have a contract where you want a user to send you ETH + data, or increase the gas, the contract owner posts the information and instructions on what to do. ie: Using Jaxx, do this. Using MyEtherWallet, do this. Using Mist, do this. Or command line do (eth.SendTransaction({ ... }). Paste this data. Change default gas to this. Etc.

By providing a URI you are providing a shortcut but it is not anything that isn't currently happening.

If there are security concerns with the data field, then they are concerns that should be addressed in a more broad scope than just this EIP.

@killerstorm

This comment has been minimized.

Show comment
Hide comment
@killerstorm

killerstorm Apr 27, 2016

@tayvano Well again, if people do it in a non-secure way now, the RIGHT thing to do is to find a way to fix it. (I.e. create UX which is both convenient and secure.) The WRONG thing to do to make it simpler to continue with non-secure practices. But that's just my opinion, feel free to ignore it. :)

@alexvandesande My gut feeling is that function parameters are much better, but the security can be assessed only in the context of wallet/browser security policies. Thus I think it will be better if URI scheme will be developed after wallet/browser developers describe their security policies in detail. Otherwise it might turn out that URI is fundamentally incompatible with security measures taken by the wallet, but users might quickly get used to such URIs so it will be hard to phase them out.

It might turn out that bytecode is actually fine if certain precautions are taken in the wallet (i.e. wallet will only allow bytecode for explicitly whitelisted contracts ABIs of which are known).

If you want to let people experiment with it and see what happens, perhaps you can add to the spec that a wallet MUST display a huge warning before signing a transaction with a provided bytecode. (i.e. wallet should ask user if URI comes from a trusted source and explain potential problems.)

But you can't let wallet developers to decide what to do, as they might simply ignore all security concerns and claim "oh, I just implemented the standard, I didn't know it enables this vulnerability".

Obviously, if the spec prescribes certain thing but wallets do another that's their problem...

@tayvano Well again, if people do it in a non-secure way now, the RIGHT thing to do is to find a way to fix it. (I.e. create UX which is both convenient and secure.) The WRONG thing to do to make it simpler to continue with non-secure practices. But that's just my opinion, feel free to ignore it. :)

@alexvandesande My gut feeling is that function parameters are much better, but the security can be assessed only in the context of wallet/browser security policies. Thus I think it will be better if URI scheme will be developed after wallet/browser developers describe their security policies in detail. Otherwise it might turn out that URI is fundamentally incompatible with security measures taken by the wallet, but users might quickly get used to such URIs so it will be hard to phase them out.

It might turn out that bytecode is actually fine if certain precautions are taken in the wallet (i.e. wallet will only allow bytecode for explicitly whitelisted contracts ABIs of which are known).

If you want to let people experiment with it and see what happens, perhaps you can add to the spec that a wallet MUST display a huge warning before signing a transaction with a provided bytecode. (i.e. wallet should ask user if URI comes from a trusted source and explain potential problems.)

But you can't let wallet developers to decide what to do, as they might simply ignore all security concerns and claim "oh, I just implemented the standard, I didn't know it enables this vulnerability".

Obviously, if the spec prescribes certain thing but wallets do another that's their problem...

@edmundedgar

This comment has been minimized.

Show comment
Hide comment
@edmundedgar

edmundedgar Apr 28, 2016

A middle way here might be to pass arbitrary data but only to a single, specially-named function. If you make the wallet pass arbitrary parameters but only to a method called callFromURLParameters() that makes this method of interacting with a contract opt-in by the contract developer.

A middle way here might be to pass arbitrary data but only to a single, specially-named function. If you make the wallet pass arbitrary parameters but only to a method called callFromURLParameters() that makes this method of interacting with a contract opt-in by the contract developer.

@hiddentao

This comment has been minimized.

Show comment
Hide comment
@hiddentao

hiddentao May 3, 2016

Let's say wallet apps ask users for confirmation when a link is clicked. At some point users will probably ask for (and thus get) an option in apps to enable auto-confirmation of such URLs. So not having the ability to do bytecode but allowing plaintext functions because the latter is less risky makes no sense to me. Even if you just had the ability to send eth to an address the onus is still on the user and their wallet app to ensure that everything is kosher.

So all in all for me the security implications are a non-issue. I could give you a standard QR code which takes you a URL which shows a webpage that takes advantage of some browser flaw and installs malware on your machine. In other words a user should only click a link if they trust it in the first place.

I say the scheme should allow for maximum flexibility, i.e. bytecode and functions. The wallet app should then deciper as much as it can from the incoming URL and display the details to the user for confirmation. If a wallet app fails to do this then it's an insecure app and one would hope users would steer clear from it. We can atleast ensure that the Mist wallet does things as securely as possible, which I think will go some way towards encouraging other app developers to do the same.

Let's say wallet apps ask users for confirmation when a link is clicked. At some point users will probably ask for (and thus get) an option in apps to enable auto-confirmation of such URLs. So not having the ability to do bytecode but allowing plaintext functions because the latter is less risky makes no sense to me. Even if you just had the ability to send eth to an address the onus is still on the user and their wallet app to ensure that everything is kosher.

So all in all for me the security implications are a non-issue. I could give you a standard QR code which takes you a URL which shows a webpage that takes advantage of some browser flaw and installs malware on your machine. In other words a user should only click a link if they trust it in the first place.

I say the scheme should allow for maximum flexibility, i.e. bytecode and functions. The wallet app should then deciper as much as it can from the incoming URL and display the details to the user for confirmation. If a wallet app fails to do this then it's an insecure app and one would hope users would steer clear from it. We can atleast ensure that the Mist wallet does things as securely as possible, which I think will go some way towards encouraging other app developers to do the same.

@alexvandesande

This comment has been minimized.

Show comment
Hide comment
@alexvandesande

alexvandesande May 3, 2016

Contributor

At some point users will probably ask for (and thus get) an option in apps to enable auto-confirmation of such URLs.

I disagree here, I don't see imagine in the future any situation where Mist would allow auto confirmations unless they were very strict (auto confirm these functions up to a certain level, but at that point this is just another way to get "pre-confirmation").

If a app developer needs to constantly sign messages and transactions (like swarm does) and this would be a burden to the user, then I would suggest them to refactor their app to create a private daemon that owns their own keys and runs autonomously, and request that the user only funds him enough.

Contributor

alexvandesande commented May 3, 2016

At some point users will probably ask for (and thus get) an option in apps to enable auto-confirmation of such URLs.

I disagree here, I don't see imagine in the future any situation where Mist would allow auto confirmations unless they were very strict (auto confirm these functions up to a certain level, but at that point this is just another way to get "pre-confirmation").

If a app developer needs to constantly sign messages and transactions (like swarm does) and this would be a burden to the user, then I would suggest them to refactor their app to create a private daemon that owns their own keys and runs autonomously, and request that the user only funds him enough.

@danfinlay

This comment has been minimized.

Show comment
Hide comment
@danfinlay

danfinlay May 4, 2016

Contributor

Hi @alexvandesande, sorry for hopping in late, I felt like the major points were being made and needed some time to mature my own perspective.

Overall I like the format, and I think long term it could be a useful tool.

However, I also agree that at this early phase, we need to establish a baseline of trustworthiness of transactions before adding extra convenience. As a wallet designer, I think my users would benefit much more from having tools to conveniently analyze a transaction before approving it, than tools to give them more transactions to approve.

I've heard a lot of good ideas on that topic, here is my own personal brain dump on contract transparency.

Until we have tools to help users know exactly what they're signing in the first place, I think it is dangerously early to make it easier to submit transactions, so I'd prefer to advance on this front slowly.

Once we have at least a class of transactions that are easily verifiable (for example, maybe exchanging EIP-20 compatible tokens), we could start considering ways to warn/inform users when clicking less-transparent transaction links, and so we could start justifying new conveniences for the safer types of transactions.

A middle ground might be to allow the link format but without a data or params field at first, to give wallet developers time to build out the UIs to establish trust with data transactions first, since a basic eth transfer is about as transparent as it gets (as transparent as the to field's owner is known).

Also, on the params note: I think params can be deceptive, since they can be named whatever, so I'm a little uncomfortable about using them as a way to demonstrate trustworthiness, I'd personally hold them to the same security criteria as a data field.

Contributor

danfinlay commented May 4, 2016

Hi @alexvandesande, sorry for hopping in late, I felt like the major points were being made and needed some time to mature my own perspective.

Overall I like the format, and I think long term it could be a useful tool.

However, I also agree that at this early phase, we need to establish a baseline of trustworthiness of transactions before adding extra convenience. As a wallet designer, I think my users would benefit much more from having tools to conveniently analyze a transaction before approving it, than tools to give them more transactions to approve.

I've heard a lot of good ideas on that topic, here is my own personal brain dump on contract transparency.

Until we have tools to help users know exactly what they're signing in the first place, I think it is dangerously early to make it easier to submit transactions, so I'd prefer to advance on this front slowly.

Once we have at least a class of transactions that are easily verifiable (for example, maybe exchanging EIP-20 compatible tokens), we could start considering ways to warn/inform users when clicking less-transparent transaction links, and so we could start justifying new conveniences for the safer types of transactions.

A middle ground might be to allow the link format but without a data or params field at first, to give wallet developers time to build out the UIs to establish trust with data transactions first, since a basic eth transfer is about as transparent as it gets (as transparent as the to field's owner is known).

Also, on the params note: I think params can be deceptive, since they can be named whatever, so I'm a little uncomfortable about using them as a way to demonstrate trustworthiness, I'd personally hold them to the same security criteria as a data field.

@alexvandesande

This comment has been minimized.

Show comment
Hide comment
@alexvandesande

alexvandesande May 4, 2016

Contributor

@FlySwatter thanks for your comments. I agree on starting slowly and not building the data field at first. Having the function + params field will allow a wallet to have a small ABI that will enable it to know exactly which function is being called, as the function name and parameters are enough to build a byte code for the transaction.

Of course, someone could build a deceptive contract, that could fit standards like tokens but not execute the same way, so for example a transfer() could do some other code completely. The wallet could avoid this by whitelisting some addresses or trying to preview which changes that transaction would make on the blockchain.

Contributor

alexvandesande commented May 4, 2016

@FlySwatter thanks for your comments. I agree on starting slowly and not building the data field at first. Having the function + params field will allow a wallet to have a small ABI that will enable it to know exactly which function is being called, as the function name and parameters are enough to build a byte code for the transaction.

Of course, someone could build a deceptive contract, that could fit standards like tokens but not execute the same way, so for example a transfer() could do some other code completely. The wallet could avoid this by whitelisting some addresses or trying to preview which changes that transaction would make on the blockchain.

@danielmcclure

This comment has been minimized.

Show comment
Hide comment
@danielmcclure

danielmcclure May 11, 2016

Found this discussion whilst looking to see if there was a Transfer URI scheme. At the very least the transfer function seems viable. For a non technical user all data interactions right now are a little daunting for independent verification. I can see why you wouldn't want to add automatic data fields just yet. Sites could just add copy/paste code alongside the URL in the meantime if they need data, which would add some friction for the average user to consider what they are doing.

ethereum:<address>[?value=<value>][?gas=<suggestedGas>]

Found this discussion whilst looking to see if there was a Transfer URI scheme. At the very least the transfer function seems viable. For a non technical user all data interactions right now are a little daunting for independent verification. I can see why you wouldn't want to add automatic data fields just yet. Sites could just add copy/paste code alongside the URL in the meantime if they need data, which would add some friction for the average user to consider what they are doing.

ethereum:<address>[?value=<value>][?gas=<suggestedGas>]

@realcodywburns

This comment has been minimized.

Show comment
Hide comment
@realcodywburns

realcodywburns Sep 9, 2017

I am with arachnid and the others on the KISS structure, I think that the uri should be a low level and as versatile as possible at minimum it would only contain the parts of a transaction the user would not have:

[foo] means optional, are placeholders

ethereum:<address>&chain=<chainid>[?value=<value>][?gas=<suggestedGas>][?data=<data>][?message=<message>

Key:

  • address: valid ethereum address or icap
  • chain: eip 155 chain id for sanity check (used for v)
  • value: amount to transfer
  • gas: gas price
  • data: bytecode for the transaction
  • message: message that describes the transaction to the user

Higher level functionality would be provided by the site creating the qr code and, for lack of a better term, black box it to the application scanning the code. As generating qr-codes is trivial on an application compared to the hazard of unlocking a private key, an application should be able to produce a URI that is functionally similar to a standard transaction without the account specific details.

realcodywburns commented Sep 9, 2017

I am with arachnid and the others on the KISS structure, I think that the uri should be a low level and as versatile as possible at minimum it would only contain the parts of a transaction the user would not have:

[foo] means optional, are placeholders

ethereum:<address>&chain=<chainid>[?value=<value>][?gas=<suggestedGas>][?data=<data>][?message=<message>

Key:

  • address: valid ethereum address or icap
  • chain: eip 155 chain id for sanity check (used for v)
  • value: amount to transfer
  • gas: gas price
  • data: bytecode for the transaction
  • message: message that describes the transaction to the user

Higher level functionality would be provided by the site creating the qr code and, for lack of a better term, black box it to the application scanning the code. As generating qr-codes is trivial on an application compared to the hazard of unlocking a private key, an application should be able to produce a URI that is functionally similar to a standard transaction without the account specific details.

@MicahZoltu

This comment has been minimized.

Show comment
Hide comment
@MicahZoltu

MicahZoltu Sep 9, 2017

Contributor

Higher level functionality would be provided by the site creating the qr code

The problem is that you cannot add security at a higher level while using a low level URI like proposed. The URI simply doesn't convey enough information to allow the signer to appropriately prompt the user for informed signing. In all cases other than the most trivial ones (ETH transfer) the signer UI can only show you a byte-array of data that you are signing. They can't tell you what that byte array means.

For well known methods like ERC20 transfer the signer can likely infer what is happening, but that is not a scalable solution (only working for well known contracts).

Contributor

MicahZoltu commented Sep 9, 2017

Higher level functionality would be provided by the site creating the qr code

The problem is that you cannot add security at a higher level while using a low level URI like proposed. The URI simply doesn't convey enough information to allow the signer to appropriately prompt the user for informed signing. In all cases other than the most trivial ones (ETH transfer) the signer UI can only show you a byte-array of data that you are signing. They can't tell you what that byte array means.

For well known methods like ERC20 transfer the signer can likely infer what is happening, but that is not a scalable solution (only working for well known contracts).

@realcodywburns

This comment has been minimized.

Show comment
Hide comment
@realcodywburns

realcodywburns Sep 10, 2017

That is what the message serves this function and is not included in the transaction signing. The user only signing messages from trusted sites is a second level of security. This is much more secure than entering private keys on websites. Phishing is rampant. Losses are avoidable by having the signing process occur in a more trusted device. Allowing a robust method to transfer the data to sign is the goal.

That is what the message serves this function and is not included in the transaction signing. The user only signing messages from trusted sites is a second level of security. This is much more secure than entering private keys on websites. Phishing is rampant. Losses are avoidable by having the signing process occur in a more trusted device. Allowing a robust method to transfer the data to sign is the goal.

@MicahZoltu

This comment has been minimized.

Show comment
Hide comment
@MicahZoltu

MicahZoltu Sep 10, 2017

Contributor

I agree, users should never be giving their private keys out to any but the most vetted of websites/applications (e.g., MEW, Local Parity Node, etc.). I also agree that having a mechanism to make it easy to transfer a transaction for signing from one app/device to another is valuable (what this EIP aims to accomplish).

What I am arguing is that we could do a whole lot better than:

  • Untrusted App A sends opaque data to be signed by Trusted App B
  • Trusted App B prompts user to sign opaque data (which may be malicious)

By using non-opaque parameters in the URI we can instead achieve:

  • Untrusted App A sends verifiable structured data to Trusted App B.
  • Trusted App B prompts the user with structured data for signing (without needing to trust App A to be non-malicious).

We already see this problem with hardware signers like the Ledger. Apps integrate with the Ledger so the user doesn't have to give their keys to the app. However, the user has to trust the app none the less because the Ledger doesn't have enough information to provide the user with an informed signing decision. The ledger just says, "The connected app wants you to sign a transaction with these bytes, confirm or deny." While the app doesn't have direct access to the private keys stored on the Ledger, because the user can't make an informed signing decision the app effectively has access to the user's private keys.

Contributor

MicahZoltu commented Sep 10, 2017

I agree, users should never be giving their private keys out to any but the most vetted of websites/applications (e.g., MEW, Local Parity Node, etc.). I also agree that having a mechanism to make it easy to transfer a transaction for signing from one app/device to another is valuable (what this EIP aims to accomplish).

What I am arguing is that we could do a whole lot better than:

  • Untrusted App A sends opaque data to be signed by Trusted App B
  • Trusted App B prompts user to sign opaque data (which may be malicious)

By using non-opaque parameters in the URI we can instead achieve:

  • Untrusted App A sends verifiable structured data to Trusted App B.
  • Trusted App B prompts the user with structured data for signing (without needing to trust App A to be non-malicious).

We already see this problem with hardware signers like the Ledger. Apps integrate with the Ledger so the user doesn't have to give their keys to the app. However, the user has to trust the app none the less because the Ledger doesn't have enough information to provide the user with an informed signing decision. The ledger just says, "The connected app wants you to sign a transaction with these bytes, confirm or deny." While the app doesn't have direct access to the private keys stored on the Ledger, because the user can't make an informed signing decision the app effectively has access to the user's private keys.

@realcodywburns

This comment has been minimized.

Show comment
Hide comment
@realcodywburns

realcodywburns Sep 10, 2017

Unfortunately, it is not possible to derive random functions from bytecode. During compiling, only the first 8 bytes of the sha3 of the function name is saved. By having a standard for moving transactions that need to be signed, it will not matter if it is a mobile phone, hardware wallet, hsm, node etc. A malicious actor will attempt to compromise any method of announcing the function.

Unfortunately, it is not possible to derive random functions from bytecode. During compiling, only the first 8 bytes of the sha3 of the function name is saved. By having a standard for moving transactions that need to be signed, it will not matter if it is a mobile phone, hardware wallet, hsm, node etc. A malicious actor will attempt to compromise any method of announcing the function.

@MicahZoltu

This comment has been minimized.

Show comment
Hide comment
@MicahZoltu

MicahZoltu Sep 10, 2017

Contributor

it is not possible to derive random functions from bytecode

That is why I believe the URI should include the signature of the method being called, so the signer can validate that the provided method name and parameter types match the first part of the sha3 of the method signature and then display the method name, contract address and parameters (as numbers, strings, addresses, etc.) to the end-user.

Contributor

MicahZoltu commented Sep 10, 2017

it is not possible to derive random functions from bytecode

That is why I believe the URI should include the signature of the method being called, so the signer can validate that the provided method name and parameter types match the first part of the sha3 of the method signature and then display the method name, contract address and parameters (as numbers, strings, addresses, etc.) to the end-user.

@realcodywburns

This comment has been minimized.

Show comment
Hide comment
@realcodywburns

realcodywburns Sep 10, 2017

It would be counter productive to include the entire abi. The amount of data transfering would go from a few bytes to several kilobytes. It is also highly likely that users would just click through in the same manner they do terms and conditions.

It would be counter productive to include the entire abi. The amount of data transfering would go from a few bytes to several kilobytes. It is also highly likely that users would just click through in the same manner they do terms and conditions.

@realcodywburns

This comment has been minimized.

Show comment
Hide comment
@realcodywburns

realcodywburns Sep 10, 2017

There is also no requirement to name functions honestly. A functions name is not indicative of its operations. To truly know what a function being signed would do you would need to decompile the bytecode at the contract address with would be far outside the scope of a simple uri.

At best, a user would send a small test transaction if they had doubts about an uri. The loss would be small and the malicious function known

There is also no requirement to name functions honestly. A functions name is not indicative of its operations. To truly know what a function being signed would do you would need to decompile the bytecode at the contract address with would be far outside the scope of a simple uri.

At best, a user would send a small test transaction if they had doubts about an uri. The loss would be small and the malicious function known

@MicahZoltu

This comment has been minimized.

Show comment
Hide comment
@MicahZoltu

MicahZoltu Sep 10, 2017

Contributor

It would be counter productive to include the entire abi.

Agreed. In this case though, the dApp needs only provide the signature for the method being called, not the entire ABI for the contract.

It is also highly likely that users would just click through in the same manner they do terms and conditions.

  • There is a demographic of users that will blindly sign anything given to them. These users cannot be helped/saved and they will eventually lose all of their funds.
  • There is another demographic of users who will read the details if provided, but if they get an opaque byte array will fallback to the "sign everything" strategy. These users can be saved from themselves.
  • There is a third demographic of users who will only sign things they understand/trust. These users, currently, can't use most dApps because they have no way to verify anything themselves. These users are already protecting themselves, but we can provide them with a much larger suite of dApps they can use.

There is also no requirement to name functions honestly.

Very true. However, when combined with ENS, a user can at a glance tell the difference between trusted.eth : deposit(100) and trusted.eth : transfer(100, 0xabcd). Even without ENS, for advanced users the method signature provides them enough information to somewhat easily verify the method call against the contract being executed (looking up the code on something like EtherScan is easy, and hopefully with Swarm verified code will become baked into Ethereum). With an opaque byte array this process becomes really hard. For middle-ground users they can ask an informed question of experts like, "Does trusted.eth : deposit(...) do what one would expect?"

I do agree with you that having the method signature baked into the URI will not solve all security problems. However, I do think it is a huge step up over the "prompt user to sign opaque data" scheme that is being pushed for in this PR.

Contributor

MicahZoltu commented Sep 10, 2017

It would be counter productive to include the entire abi.

Agreed. In this case though, the dApp needs only provide the signature for the method being called, not the entire ABI for the contract.

It is also highly likely that users would just click through in the same manner they do terms and conditions.

  • There is a demographic of users that will blindly sign anything given to them. These users cannot be helped/saved and they will eventually lose all of their funds.
  • There is another demographic of users who will read the details if provided, but if they get an opaque byte array will fallback to the "sign everything" strategy. These users can be saved from themselves.
  • There is a third demographic of users who will only sign things they understand/trust. These users, currently, can't use most dApps because they have no way to verify anything themselves. These users are already protecting themselves, but we can provide them with a much larger suite of dApps they can use.

There is also no requirement to name functions honestly.

Very true. However, when combined with ENS, a user can at a glance tell the difference between trusted.eth : deposit(100) and trusted.eth : transfer(100, 0xabcd). Even without ENS, for advanced users the method signature provides them enough information to somewhat easily verify the method call against the contract being executed (looking up the code on something like EtherScan is easy, and hopefully with Swarm verified code will become baked into Ethereum). With an opaque byte array this process becomes really hard. For middle-ground users they can ask an informed question of experts like, "Does trusted.eth : deposit(...) do what one would expect?"

I do agree with you that having the method signature baked into the URI will not solve all security problems. However, I do think it is a huge step up over the "prompt user to sign opaque data" scheme that is being pushed for in this PR.

@mezrin

This comment has been minimized.

Show comment
Hide comment
@mezrin

mezrin Sep 10, 2017

There is one more drawback of the approach with binary data.
In this case, all applications that need QR code should be able to create bytecode. In other words, they need to know how this bytecode is formed and embed packages to build the bytecode.

This is a rather difficult task for an ordinary programmer. It would be much easier to create a JSON with the ABI of the called method.

Also, packages to build bytecode are created not for all programming languages. This means that QR functionality will be available only to apps written in JS, Python and maybe a few more languages.

It is much more natural to delegate the task of ABI compilation to the wallet app that manages private keys.

mezrin commented Sep 10, 2017

There is one more drawback of the approach with binary data.
In this case, all applications that need QR code should be able to create bytecode. In other words, they need to know how this bytecode is formed and embed packages to build the bytecode.

This is a rather difficult task for an ordinary programmer. It would be much easier to create a JSON with the ABI of the called method.

Also, packages to build bytecode are created not for all programming languages. This means that QR functionality will be available only to apps written in JS, Python and maybe a few more languages.

It is much more natural to delegate the task of ABI compilation to the wallet app that manages private keys.

@realcodywburns

This comment has been minimized.

Show comment
Hide comment
@realcodywburns

realcodywburns Sep 10, 2017

Ideally a majority of users are not humans. For ethereum, an nfc tag with a uri can be handeled just as easily as a human scaning a qr code with the same uri. If the device, app, tag, api, website, etc isn't semi-trusted a priori the signer(be it human, HSM, IoT device, other) should not use a uri. The message field should be optional and only for reference.

All applications and programmers creating uri codes with data DO need a firm understanding of how bytecode is created for the evm, what rlp the encoding schema is, and how the raw transactions are structured. Anyone not comfortable in those areas should only send address and value only.

realcodywburns commented Sep 10, 2017

Ideally a majority of users are not humans. For ethereum, an nfc tag with a uri can be handeled just as easily as a human scaning a qr code with the same uri. If the device, app, tag, api, website, etc isn't semi-trusted a priori the signer(be it human, HSM, IoT device, other) should not use a uri. The message field should be optional and only for reference.

All applications and programmers creating uri codes with data DO need a firm understanding of how bytecode is created for the evm, what rlp the encoding schema is, and how the raw transactions are structured. Anyone not comfortable in those areas should only send address and value only.

@mezrin

This comment has been minimized.

Show comment
Hide comment
@mezrin

mezrin Sep 10, 2017

It is only ideally. I real life you will have a lot of cases where additional checks will save your money.

All applications and programmers creating uri codes with data DO need a firm understanding of how bytecode is created for the evm, what rlp the encoding schema is, and how the raw transactions are structured. Anyone not comfortable in those areas should only send address and value only.

So, for example, I want to receive donations in form of some ERC20 token.
Why do I need to understand RPL and all other stuff?

Your message to Ruby/PHP/c/c++/Java/C#/.. programmers:
“In order to generate QR code you need to write RPL compiler first.“
Are you serious with this?

I do not see any reason why programmer that wants to receive tokens or call any other contract have to understand RPL encoding. Really, why a PHP-dev need to know this?

mezrin commented Sep 10, 2017

It is only ideally. I real life you will have a lot of cases where additional checks will save your money.

All applications and programmers creating uri codes with data DO need a firm understanding of how bytecode is created for the evm, what rlp the encoding schema is, and how the raw transactions are structured. Anyone not comfortable in those areas should only send address and value only.

So, for example, I want to receive donations in form of some ERC20 token.
Why do I need to understand RPL and all other stuff?

Your message to Ruby/PHP/c/c++/Java/C#/.. programmers:
“In order to generate QR code you need to write RPL compiler first.“
Are you serious with this?

I do not see any reason why programmer that wants to receive tokens or call any other contract have to understand RPL encoding. Really, why a PHP-dev need to know this?

@mezrin

This comment has been minimized.

Show comment
Hide comment
@mezrin

mezrin Sep 10, 2017

Also, for example, I want to generate QR code for the web page.
To make it fast and easy - we do it in the browser, without server-side support.
With your approach, we have to load in browser several MB of code to compile the data.
In web development, we care about each 10KB of code, and now we need several MB.
It is insane.

mezrin commented Sep 10, 2017

Also, for example, I want to generate QR code for the web page.
To make it fast and easy - we do it in the browser, without server-side support.
With your approach, we have to load in browser several MB of code to compile the data.
In web development, we care about each 10KB of code, and now we need several MB.
It is insane.

@mezrin

This comment has been minimized.

Show comment
Hide comment
@mezrin

mezrin Sep 10, 2017

Also, one use case is not covered with the compiled bytecode -
when the application that generates QR code does not know the value for one of the parameters.

Let’s say, we do not know a number of tokens to send. (With the custom contract, this can be anything)
In this case, we can not generate QR code because we can not compile bytecode without that value.

But with the ABI - wallet app will generate UI for this parameter and user will be able to type needed value.

mezrin commented Sep 10, 2017

Also, one use case is not covered with the compiled bytecode -
when the application that generates QR code does not know the value for one of the parameters.

Let’s say, we do not know a number of tokens to send. (With the custom contract, this can be anything)
In this case, we can not generate QR code because we can not compile bytecode without that value.

But with the ABI - wallet app will generate UI for this parameter and user will be able to type needed value.

@realcodywburns

This comment has been minimized.

Show comment
Hide comment
@realcodywburns

realcodywburns Sep 10, 2017

So, for example, I want to receive donations in form of some ERC20 token.
Why do I need to understand RPL and all other stuff?

Yes. If a programmer does not understand how byte code for a contract is constructed, your app 100% should not use that part of the uri. In practice the only functions needed are string to hex and sha3. Bytecode is also optional and is only used if data is really needed. The only always required fields are chainid and address.

Examples:

Just the address:

ethereum:0xCe5ED529977b08f87CBc207ebC216859820461eE&chain=61

Address with name:

ethereum:0xCe5ED529977b08f87CBc207ebC216859820461eE&chain=61?label=DontPanic

Request 20.30 ETC to "DontPanic":

ethereum:0xCe5ED529977b08f87CBc207ebC216859820461eE&chain=61?amount=20.3&label=DontPanic

Request 42.30 ETC to "DontPanic" with gas:

ethereum:0xCe5ED529977b08f87CBc207ebC216859820461eE&chain=61?amount=20.3&gas=21000&label=DontPanic

Request 50 ETC with message:

ethereum:0xCe5ED529977b08f87CBc207ebC216859820461eE&chain=61?amount=50&label=DontPanic&message=Purchase%20token%20for%20project%20xyz%20ICO

Request a function call in a contract:

ethereum:0xCe5ED529977b08f87CBc207ebC216859820461eE&chain=61?amount=50&code=0x2066726f6d204a656666204761727a696b20666f7220746f6b656e206d696e74

So, for example, I want to receive donations in form of some ERC20 token.
Why do I need to understand RPL and all other stuff?

Yes. If a programmer does not understand how byte code for a contract is constructed, your app 100% should not use that part of the uri. In practice the only functions needed are string to hex and sha3. Bytecode is also optional and is only used if data is really needed. The only always required fields are chainid and address.

Examples:

Just the address:

ethereum:0xCe5ED529977b08f87CBc207ebC216859820461eE&chain=61

Address with name:

ethereum:0xCe5ED529977b08f87CBc207ebC216859820461eE&chain=61?label=DontPanic

Request 20.30 ETC to "DontPanic":

ethereum:0xCe5ED529977b08f87CBc207ebC216859820461eE&chain=61?amount=20.3&label=DontPanic

Request 42.30 ETC to "DontPanic" with gas:

ethereum:0xCe5ED529977b08f87CBc207ebC216859820461eE&chain=61?amount=20.3&gas=21000&label=DontPanic

Request 50 ETC with message:

ethereum:0xCe5ED529977b08f87CBc207ebC216859820461eE&chain=61?amount=50&label=DontPanic&message=Purchase%20token%20for%20project%20xyz%20ICO

Request a function call in a contract:

ethereum:0xCe5ED529977b08f87CBc207ebC216859820461eE&chain=61?amount=50&code=0x2066726f6d204a656666204761727a696b20666f7220746f6b656e206d696e74

@MicahZoltu

This comment has been minimized.

Show comment
Hide comment
@MicahZoltu

MicahZoltu Sep 10, 2017

Contributor

@realcodywburns I believe @mezrin was referring to if a contract function parameter is not known. For example, if you wanted to have a "donate tokens" button, the web app generating the URI would leave out the amount parameter on the transfer function for the signer (user) to fill in. With bytecode encoded URI rather than ABI, the generator of the bytecode needs to know all details up front. This is a minor concern IMO since the web app can simply prompt the user, though I do think there is some value in having the signer allow the user to change contract method call parameters.

Contributor

MicahZoltu commented Sep 10, 2017

@realcodywburns I believe @mezrin was referring to if a contract function parameter is not known. For example, if you wanted to have a "donate tokens" button, the web app generating the URI would leave out the amount parameter on the transfer function for the signer (user) to fill in. With bytecode encoded URI rather than ABI, the generator of the bytecode needs to know all details up front. This is a minor concern IMO since the web app can simply prompt the user, though I do think there is some value in having the signer allow the user to change contract method call parameters.

@mezrin

This comment has been minimized.

Show comment
Hide comment
@mezrin

mezrin Sep 10, 2017

If a programmer does not understand how byte code for a contract is constructed, your app 100% should not use that part of the uri.

You mentioned this before and not answered to a simple question - why?
Why do all devs need to know the internals of Ethereum to just receive tokens? :)

It is definitely possible to do it without knowledge of RLP and all other stuff. You just delegate the boilerplate task of encoding data to the wallet app (that definitely knows about RLP and all other) and spend on QR code 20 mins instead of several days.

Also, there is a list of questions that are still without answer:

  • who and when will implement all needed libs to prepare compiled data parameter for all most used languages like Java/C/C++/C#/PHP/Ruby/.. ?
  • what should web devs do with the very big JS packages required to compile data parameter? Load megabytes of code to the browser in order just to generate QR code?
  • What if the creator of QR code does not know one of the parameters needed for the call to the contract?
    (for example, I want to receive donations in form of ERC20 tokens. And I want to post a QR code on my static web-site or print a QR code on the piece of paper. And I want that users will adjust amount of donation on their own)

mezrin commented Sep 10, 2017

If a programmer does not understand how byte code for a contract is constructed, your app 100% should not use that part of the uri.

You mentioned this before and not answered to a simple question - why?
Why do all devs need to know the internals of Ethereum to just receive tokens? :)

It is definitely possible to do it without knowledge of RLP and all other stuff. You just delegate the boilerplate task of encoding data to the wallet app (that definitely knows about RLP and all other) and spend on QR code 20 mins instead of several days.

Also, there is a list of questions that are still without answer:

  • who and when will implement all needed libs to prepare compiled data parameter for all most used languages like Java/C/C++/C#/PHP/Ruby/.. ?
  • what should web devs do with the very big JS packages required to compile data parameter? Load megabytes of code to the browser in order just to generate QR code?
  • What if the creator of QR code does not know one of the parameters needed for the call to the contract?
    (for example, I want to receive donations in form of ERC20 tokens. And I want to post a QR code on my static web-site or print a QR code on the piece of paper. And I want that users will adjust amount of donation on their own)
@realcodywburns

This comment has been minimized.

Show comment
Hide comment
@realcodywburns

realcodywburns Sep 10, 2017

You mentioned this before and not answered to a simple question - why?

Because of the irrovacable harm that can be done in ~14 sec if it is done incorrectly. Submitting bytecode is a non-trivial event in a transaction and should only be done with an abundance of caution.

who and when will implement all needed libs to prepare compiled data parameter for all most used languages like Java/C/C++/C#/PHP/Ruby/.. ?

If you know the function you want to call, it is easy to implement the data(see below)

what should web devs do with the very big JS packages required to compile dataparameter?

Mini-fy them. But nothing complex is required

Load megabytes of code to the browser in order just to generate QR code?What if the creator of QR code does not know one of the parameters needed for the call to the contract?
(for example, I want to receive donations in form of ERC20 tokens. And I want to post a QR code on my static web-site or print a QR code on the piece of paper. And I want that users will adjust amount of donation on their own)

When in doubt do not include the bytecode.

No addational libraries are needed to compute the byte code except a crypto lib that can handle Keccak(sha3).

Events and functions in evm contracts are/can be preformatted to know the functions in the underlying contract. The first four bytes of the call data for a function call specifies the function to be called. It is the first (left, high-order in big-endian) four bytes of the Keccak (SHA-3) hash of the signature of the function. This information along, with the appropriate hex encoded data to pass, is the bytecode.

Example

Contract C is at 0xdeadbeef... and has the following psudo function:

 function getETC(){
    require(block.number-payoutDrip >= payoutRate);
    msg.sender.transfer(dropValue);   
    }

Contract C requires no inputs and only requires enough gas to preform its functions. The byte code for this function can be derived using web3 as:

web3.sha3("getETC()");

which yeilds:

0x023b88685d10d29e0bf0563e4ab1b9d8fc8333c166705be5538c4b079cdd9af0

The information that will be passed in the byte code field would then be:

code=0x023b88685d

The entire URi could be:

ethereum:0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef&id=61&code=0x023b88685d

You mentioned this before and not answered to a simple question - why?

Because of the irrovacable harm that can be done in ~14 sec if it is done incorrectly. Submitting bytecode is a non-trivial event in a transaction and should only be done with an abundance of caution.

who and when will implement all needed libs to prepare compiled data parameter for all most used languages like Java/C/C++/C#/PHP/Ruby/.. ?

If you know the function you want to call, it is easy to implement the data(see below)

what should web devs do with the very big JS packages required to compile dataparameter?

Mini-fy them. But nothing complex is required

Load megabytes of code to the browser in order just to generate QR code?What if the creator of QR code does not know one of the parameters needed for the call to the contract?
(for example, I want to receive donations in form of ERC20 tokens. And I want to post a QR code on my static web-site or print a QR code on the piece of paper. And I want that users will adjust amount of donation on their own)

When in doubt do not include the bytecode.

No addational libraries are needed to compute the byte code except a crypto lib that can handle Keccak(sha3).

Events and functions in evm contracts are/can be preformatted to know the functions in the underlying contract. The first four bytes of the call data for a function call specifies the function to be called. It is the first (left, high-order in big-endian) four bytes of the Keccak (SHA-3) hash of the signature of the function. This information along, with the appropriate hex encoded data to pass, is the bytecode.

Example

Contract C is at 0xdeadbeef... and has the following psudo function:

 function getETC(){
    require(block.number-payoutDrip >= payoutRate);
    msg.sender.transfer(dropValue);   
    }

Contract C requires no inputs and only requires enough gas to preform its functions. The byte code for this function can be derived using web3 as:

web3.sha3("getETC()");

which yeilds:

0x023b88685d10d29e0bf0563e4ab1b9d8fc8333c166705be5538c4b079cdd9af0

The information that will be passed in the byte code field would then be:

code=0x023b88685d

The entire URi could be:

ethereum:0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef&id=61&code=0x023b88685d

@MicahZoltu

This comment has been minimized.

Show comment
Hide comment
@MicahZoltu

MicahZoltu Sep 10, 2017

Contributor

Because of the irrovacable harm that can be done in ~14 sec if it is done incorrectly. Submitting bytecode is a non-trivial event in a transaction and should only be done with an abundance of caution.

To me this sounds like a strong argument against bytecode encoded data. It is far more likely that a dev setting up a payment button on their website (or similar) is going to screw up RLP encoded then they are JSON encoding.

Contributor

MicahZoltu commented Sep 10, 2017

Because of the irrovacable harm that can be done in ~14 sec if it is done incorrectly. Submitting bytecode is a non-trivial event in a transaction and should only be done with an abundance of caution.

To me this sounds like a strong argument against bytecode encoded data. It is far more likely that a dev setting up a payment button on their website (or similar) is going to screw up RLP encoded then they are JSON encoding.

@realcodywburns

This comment has been minimized.

Show comment
Hide comment
@realcodywburns

realcodywburns Sep 10, 2017

Json is actually pretty terrible for this kind of thing. Json arrays do not include data types so a function requiring a uint32 input would likely not be properly formatted. You cannot enter a json in an address bar as a query string and have it function predictably, and they inefficiently manage data in space critical applications.

A uri is used to succinctly pass and handle a uniformly formatted chunk of data to another device. If addational information is required, then a project doesn't really need to use the uri.

Bytecode is easy to use when you know how it works. It is absolutely not something that should be carelessly handeled anymore than a customer's bank information, credit cards, security numbers, etc.

For Reference

http://solidity.readthedocs.io/en/develop/abi-spec.html#examples

Json is actually pretty terrible for this kind of thing. Json arrays do not include data types so a function requiring a uint32 input would likely not be properly formatted. You cannot enter a json in an address bar as a query string and have it function predictably, and they inefficiently manage data in space critical applications.

A uri is used to succinctly pass and handle a uniformly formatted chunk of data to another device. If addational information is required, then a project doesn't really need to use the uri.

Bytecode is easy to use when you know how it works. It is absolutely not something that should be carelessly handeled anymore than a customer's bank information, credit cards, security numbers, etc.

For Reference

http://solidity.readthedocs.io/en/develop/abi-spec.html#examples

@MicahZoltu

This comment has been minimized.

Show comment
Hide comment
@MicahZoltu

MicahZoltu Sep 11, 2017

Contributor

I think at this point we need to acknowledge that the participants of this conversation are not targeting the same userbase. I believe there are (very broadly speaking) two camps of people in this discussion:

  • Those who want this protocol to be accessible, secure and easy to implement.
  • Those who want this protocol to be simple, constrained, and low level.

Further discussion of the implementation without first locking down what exact problem we are trying to solve likely isn't going to get us anywhere. So the question is:
Are we trying to author a future-proof low-level URI scheme or are we trying to author something that enables users to make more informed signing decisions than they currently can and is easy to read, use and integrate with?

Perhaps we can satisfy everyone by having the base protocol simply be ethereum:<protocol>:<version>:<the_rest> so everyone can get what they want? ethereum:low_level:1:<address>?<bytes> could be one option while ethereum:friendly:1?address=<address>&method=<method_signature>&parameters=<method_parameters> could be another.

Contributor

MicahZoltu commented Sep 11, 2017

I think at this point we need to acknowledge that the participants of this conversation are not targeting the same userbase. I believe there are (very broadly speaking) two camps of people in this discussion:

  • Those who want this protocol to be accessible, secure and easy to implement.
  • Those who want this protocol to be simple, constrained, and low level.

Further discussion of the implementation without first locking down what exact problem we are trying to solve likely isn't going to get us anywhere. So the question is:
Are we trying to author a future-proof low-level URI scheme or are we trying to author something that enables users to make more informed signing decisions than they currently can and is easy to read, use and integrate with?

Perhaps we can satisfy everyone by having the base protocol simply be ethereum:<protocol>:<version>:<the_rest> so everyone can get what they want? ethereum:low_level:1:<address>?<bytes> could be one option while ethereum:friendly:1?address=<address>&method=<method_signature>&parameters=<method_parameters> could be another.

@realcodywburns

This comment has been minimized.

Show comment
Hide comment
@realcodywburns

realcodywburns Sep 11, 2017

I think you are correct. #205 is more inline with handeling functions and abi jsons in a human friendly way.

I think you are correct. #205 is more inline with handeling functions and abi jsons in a human friendly way.

@realcodywburns realcodywburns referenced this issue in ethereumproject/ECIPs Sep 11, 2017

Open

ECIP 1037: Simple non-interactive URI Scheme #81

@jeluard jeluard referenced this issue in status-im/status-react Oct 5, 2017

Closed

[Wallet] QR code generation and parsing is incomplete #2025

@michaelScoff michaelScoff referenced this issue in TrustWallet/trust-wallet-ios Oct 20, 2017

Closed

Implement QR code parser #65

@fvictorio fvictorio referenced this issue in poanetwork/token-wizard Nov 1, 2017

Closed

(Feature) Add investment option without Metamask #319

0 of 2 tasks complete
@MidnightLightning

This comment has been minimized.

Show comment
Hide comment
@MidnightLightning

MidnightLightning Nov 14, 2017

@MicahZoltu Why require specifically calling out "I'm going to do something simple" before doing it? The simplest transactions would just leave off the additional, detailed parameters and the client could detect that easily:

  • ethereum:0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7 => "Pay address 0x8920..." (user would have to fill in a payment amount themselves before sending
  • ethereum:0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7?value=0.01 => "Pay address 0x8920... 0.01 ether"
  • ethereum:0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7?method=0xdeadbeef => "Send an advanced transaction to contract 0x8920..., triggering method 0xdeadbeef with no additional parameters" (or whatever the names of final query parameters are decided upon for doing more complex function calls.)

In this example, if the method parameter isn't set, it's a "low level" transaction. No need to specifically label it as "low level" since that's evident by the content.

Can we formalize the base parameters (address, value, and label/message) to provide basic functionality, and layer in additional complexity via additional (optional) query parameters as a separate process?

@MicahZoltu Why require specifically calling out "I'm going to do something simple" before doing it? The simplest transactions would just leave off the additional, detailed parameters and the client could detect that easily:

  • ethereum:0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7 => "Pay address 0x8920..." (user would have to fill in a payment amount themselves before sending
  • ethereum:0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7?value=0.01 => "Pay address 0x8920... 0.01 ether"
  • ethereum:0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7?method=0xdeadbeef => "Send an advanced transaction to contract 0x8920..., triggering method 0xdeadbeef with no additional parameters" (or whatever the names of final query parameters are decided upon for doing more complex function calls.)

In this example, if the method parameter isn't set, it's a "low level" transaction. No need to specifically label it as "low level" since that's evident by the content.

Can we formalize the base parameters (address, value, and label/message) to provide basic functionality, and layer in additional complexity via additional (optional) query parameters as a separate process?

@Overtorment Overtorment referenced this issue in Overtorment/Cashier-BTC Nov 16, 2017

Open

Add ETH support? #6

@friedger friedger referenced this issue in walleth/kethereum Jan 20, 2018

Closed

Clarify use of erc67 and erc681 #18

@johnda98

This comment has been minimized.

Show comment
Hide comment
@johnda98

johnda98 Feb 7, 2018

Whats the latest on this Ether team ?, is it likely ever that a SC can be called from the standard issued mobile Ethereum wallet app ? using a QR code.

johnda98 commented Feb 7, 2018

Whats the latest on this Ether team ?, is it likely ever that a SC can be called from the standard issued mobile Ethereum wallet app ? using a QR code.

@ligi

This comment has been minimized.

Show comment
Hide comment
@ligi

ligi Feb 8, 2018

Member

@johnda98 please have a look at ERC-681

Member

ligi commented Feb 8, 2018

@johnda98 please have a look at ERC-681

@alexvandesande

This comment has been minimized.

Show comment
Hide comment
@alexvandesande

alexvandesande Feb 16, 2018

Contributor

This proposal has been superseded by #681

Contributor

alexvandesande commented Feb 16, 2018

This proposal has been superseded by #681

@johnda98

This comment has been minimized.

Show comment
Hide comment
@johnda98

johnda98 Feb 19, 2018

Thanks Ligi and Alex :-)

Thanks Ligi and Alex :-)

@fulldecent

This comment has been minimized.

Show comment
Hide comment
@fulldecent

fulldecent Mar 22, 2018

Contributor

@Arachnid You nominated this as an "EIPs that should be merged". Can you please share your notes on that here?

Contributor

fulldecent commented Mar 22, 2018

@Arachnid You nominated this as an "EIPs that should be merged". Can you please share your notes on that here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment