Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

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

Closed
alexvandesande opened this issue Feb 17, 2016 · 92 comments
Closed

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

alexvandesande opened this issue Feb 17, 2016 · 92 comments

Comments

@alexvandesande
Copy link

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
Copy link

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

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

@axic
Copy link
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
Copy link
Author

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

@axic
Copy link
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
Copy link

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 ?

@Smithgift
Copy link

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
Copy link
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
Copy link

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
Copy link

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
Copy link

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
Copy link

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
Copy link
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
Copy link

@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
Copy link
Author

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
Copy link

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
Copy link
Author

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
Copy link

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
Copy link

@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
Copy link
Author

@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
Copy link

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
Copy link
Author

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
Copy link

@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
Copy link
Author

@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
Copy link
Contributor

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
Copy link
Author

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

@axic
Copy link
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.

@ligi
Copy link
Member

ligi commented Feb 8, 2018

@johnda98 please have a look at ERC-681

@alexvandesande
Copy link
Author

This proposal has been superseded by #681

@johnda98
Copy link

Thanks Ligi and Alex :-)

@fulldecent
Copy link
Contributor

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

@BelfordZ
Copy link

@alexvandesande could you please help me find an example of eip 681 that includes sending arbitrary transactions? I find the spec to be very unclear.

@ligi
Copy link
Member

ligi commented Jul 20, 2019

I wonder if we should introduce an important flag
means the wallet should not allow the user to edit the value
in the context of efdevcon/pretix-eth-payment-plugin#69

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests