ethereum / EIPs

The Ethereum Improvement Proposal repository

Home Page:https://eips.ethereum.org/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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

alexvandesande opened this issue · comments

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)

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

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.

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

@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.

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 ?

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.

@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?

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.

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.

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.

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.

@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).

@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.

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

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.

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

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.

@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.

@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?

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.

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.

@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.

@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).

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.

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

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.

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.

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.

@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 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...

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.

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.

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.

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.

@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.

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>]

commented

I'm also very much in favor of being very explicit with function name, function parameters etc in the URL, rather than using a data field. The data field is inscrutable for the user, and I don't think there is ever a situation where the data field would signify anything else than a function call or a contract creation.

I would like to propose adding an optional callback_url parameter. This allows mobile wallets to integrate with dApps. I'm calling it callback_url as it's similar to what is used in OAuth2 flow.

Once a transaction is signed, the wallet can ask the user if he wants to return to the dApp. At this point the user is redirected with the full hex encoded transaction in a URL parameter tx.

I would recommend in this case that the wallet sends it to the network first, but it is out of scope I think to require that.

I have implemented this in a not yet public IOS app and it works very well.

callback_url would be a great addition, I agree

On Mon, May 23, 2016 at 7:08 PM, Pelle Braendgaard <notifications@github.com

wrote:

I would like to propose adding an optional callback_url parameter. This
allows mobile wallets to integrate with dApps. I'm calling it callback_url
as it's similar to what is used in OAuth2 flow.

Once a transaction is signed, the wallet can ask the user if he wants to
return to the dApp. At this point the user is redirected with the full hex
encoded transaction in a URL parameter tx.

I would recommend in this case that the wallet sends it to the network
first, but it is out of scope I think to require that.

I have implemented this in a not yet public IOS app and it works very well.


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub
#67 (comment)

Alex Van de Sande
UX Designer

Great idea!

I like the idea. I don't need a callback_url tough, because I can wait for an event to be triggered - hope I am not mistaken there...

Question: Is there any progress ever since on that?

Instead of callback_url check Web Payment API:

https://w3c.github.io/browser-payment-api/

It provides much richer interaction than URI handlers or callback, leading ultimately very smooth user experience. The downside is that browsers must offer specific API support.

Chrome is the first browser to support this for some credits card (?) https://developers.google.com/web/updates/2016/07/payment-request

A little warning about QR Code and the size of the data expanding greatly with the bytecode:
While they offer redundancy, the size of the data that can be encoded in a QRCode is limited for a given redundancy level. At lowest redundancy, the max size is 4,296 alphanum chars.

This is usually not a limitation for (even complex but reasonable) urls but adding bytecode may fo over this limit.

Some QR Code generators will allow you going over the limit and will automagically increase the number of rows/columns in the QR Code. While this allows storing the data you wished to store, this will end up with a QR Code harder to read for the low end devices.

Normal/common size
static_qr_code_without_logo 2

Additional data (an extract of the DAO bytecode)
static_qr_code_without_logo 4

Is this still the latest on achieving a QR code standard? We need to use a QR code for easier payments. We see some wallets have started doing QR codes, but are different from each other. What's holding this standard up? this should be pushed or we'll have a fragmented space that's frustrating to deal with (for products and users).

@jbenet I would actually really appreciate a dedicated issue / eip / pre eip / whatever specifically to discuss qr code specifics. We haven't finalized any decisions on MyEtherWallet but would love to discuss specs specifically relating to qr codes Bc there are a couple other considerations.

@tayvano yeah-- i would be interested as well. I think solidifying the URI scheme should proceed in parallel and can probably happen now-- as most people are familiar with the uses/use cases.

I agree 100%. Not sure if that final push will happen in this thread tho. 😉

+1 to dedicated QR code standardization. I think a cap on size of data would be acceptable, but would like to hear others' thoughts.

@frankiebee Did the QR research at MetaMask, and found a pretty compatible solution for us. Care to chime in?

I'll just say that currently on MEW for the "URIs" we accept the following params on send TX page:

  • to=[address]
  • value=[int]
  • sendMode=[ether | token]
    • Deprecated - was used for ETH vs ETC vs Token originally. May re-do for ETH vs ETC vs Testnet node later? Defaults to ETH, you have to provide a token symbol for token anyways
  • tokenSymbol=[MLN | ICN | MKR | ....]
    • these match our also non-standardized method of loading popular tokens - would advise looking at Parity's token adder/explorer contract as a better way of handling?
  • gasLimit=[int] OR gas=[int]
    • (gas is already long deprecated due to ambiguity between gas gasLimit and gasPrice - we don't accept gasPrice at this time.)`
  • data=[hex data]

Notes re: MEW

  1. Whenever someone uses a URL like this, we let them know that fields are pre-filled because they clicked a URL with information included and they should review it.

  2. We don't promote this feature a lot and it's not widely used, but helps for specific cases when you need someone to send some data or increase the gas or whatever (was more helpful before estimateGas was a thing).

  3. I do not think that our above "choices" should be considered when determining final implementation for URI/QR-Codes. I would rather decide upon a strong standard as efficiently as possible than do circles with arguments like, "but MyEtherWallet does...". We will implement whatever the standard is and provide fallbacks for the deprecated ones for our users.

  4. Our existing QR codes are pretty raw - just address and just private key, no params. We hope to make one that users can easily scan in order to auto-fill a TX. Our private key QR codes will be updated to look different than TX/address ones.

Notes re: The broader standard

  1. Having a way for a user to send a specified ERC-20 token via QR code/URI without it all being hidden in data is probably a good thing. As noted at the start of this thread, users should take data seriously when they see it. Including it with every token TX will cause users to normalize it. This also allows the UI to provide their standard Token UI, Token confirmation screens, and other info easily, rather than making these TXs look like contract execution TXs.

  2. If 4, I would strongly recommend against using the value field as a value for both tokens and ETH (as we currently do), as clients that don't fully implement token stuff would likely fallback and generate a tx for 10k ETH instead of 10k GLM. If I want to send 10k GLM and the wallet/UI doesn't has GLM support, it should be tx with no value (+ a msg explaining what happened, if we are lucky 😉)

  3. All fields should be optional so user can fill in fields themselves, and reduces size of QR code. e.g. "Send me ETH public QR code" vs "Send 0.235234 ETH to this address with your ref # 0x0934 in the data field.

  4. Regardless of anything, the data field needs to be included in the standard. I feel strongly about this. If you don't include it in the standard, wallet providers will implement it anyways, and now they do so without security considerations or in a standardized way. I would propose to stop discussions on whether or not it should be included, and create a separate document that covers (1) what wallets / UIs should be aware of regarding the data field, (2) security implications, (3) best practices & recommendations on how to handle data when a user provides it. (ps: Sending hex data as a reference string (not in regards to a contract) is used and should be considered.)

K. Those are all my thoughts for now. 😉 Keep in mind, we're just a wallet so our experiences are different than yours.

@tayvano I don't think, as a payload, tokenSymbol and sendMode fields are necessary, as the wallet can decode them from address and data (data containing ERC20.transfer() payload). They are nice features user experience wise. However, adding extra fields to standard is always a risky move, as it is harder to get rid of those in long run than adding them in.

All good points @miohtama.

I hope that wallets / UIs choose to decode and show what that TX is doing as clearly as possible. Looking at a standard transfer tx in address / value / to / data format gives the end user no real information about what is about to happen. And when that "happening" is sending a bunch of tokens that could be as valuable as ETH...well...yeah.

@tayvano This is what my nose tell me is going to happen: When it becomes standard to include Swarm ABI uploads with the compile, wallets can fetch this information and decode it to have better UX. For example, a token transfer would show to the user:

 ERC-20 contract name: MyToken symbol: MY address: 0x00000000000
 transfer(0x00000000000, 5000)

More information about Swarm metadata can be found here:

http://solidity.readthedocs.io/en/develop/miscellaneous.html#contract-metadata

commented
  1. Our existing QR codes are pretty raw - just address and just private key, no params. We hope to make one that users can easily scan in order to auto-fill a TX. Our private key QR codes will be updated to look different than TX/address ones.

Is there a consensus if ERC-67 is only intended for transactions or should it also cover other use-cases in the ethereum space. The private key you mentioned is one example. Another one would be RLP raw data to relay (e.g. from a hardware wallet). I think there will be many more use-cases in the future. Currently these barcodes are often plain - so the user has to know and add the context. Would love to see ERC-67 cover more use-cases so we can allow other flows. This is also important for intent-filters on android to e.g. allow just scanning a barcode without going in the correct app first.

Just read through all of the comments and I didn't see any arguments for using data instead of function name and parameter types. I see a lot of debate around the topic in general, but can someone give an argument for how raw data is better than function name and parameter types? I believe the only other type of transaction besides a function call is a contract upload... do we see the ability to support contract uploads as a necessary thing? Perhaps it should have a separate URI from a function call URI?

What about changing the scheme so it will work as an android intent filter pattern:
https://developer.android.com/guide/components/intents-filters.html#DataTest

This would mean:
ethereum://0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7?gas=100000&data=0xa9059cbb00000000000000000000000000000000000000000000000000000000deadbeef0000000000000000000000000000000000000000000000000000000000000005
Would probably work

commented

What about changing the scheme so it will work as an android intent filter pattern:

You can build android intent-filters for ERC-67 like this:

https://github.com/walleth/walleth/blob/49318d1f995e0c7a9db09b1986c3b8858c7def0e/app/src/main/AndroidManifest.xml#L52

But I clearly know where you are coming from with this question - been there before: ligi/IPFSDroid#5 (comment)

That said - there are disadvantages. E.g. they are often not automatically linked from sending apps and e.g. create the need for PRs like this one.

Also you cannot match to the pathPattern - which is not really a problem here that much I think - but e.g. a problem for IPFS: https://stackoverflow.com/questions/36994704/intent-filters-with-pathpattern-for-authority-less-uris

You can have a deeper about this topic here:

I think this is correct here and we should not change it and live with the draw-backs of this on android (and potentially other OSes) - also maybe @jbenet might ship in here as he has strong opinions on this topic AFAIR

That said we might perhaps discuss a proxy URI scheme for some use-cases on android like ethereumandroidcompat://sameasERC67 otherwise - with this one we could sometimes (e.g. when never exposed to user or outside) work around the issue.

Just read through all of the comments and I didn't see any arguments for using data instead of function name and parameter types. I see a lot of debate around the topic in general, but can someone give an argument for how raw data is better than function name and parameter types? I believe the only other type of transaction besides a function call is a contract upload... do we see the ability to support contract uploads as a necessary thing? Perhaps it should have a separate URI from a function call URI?

For a low level URI scheme, 'data' as a parameter better specifies the transaction being constructed, and requires less sophistication from implementers. It also makes fewer assumptions about the encoding of the transaction data, and won't require upgrades as the ABI is improved over time.

Finally, specifying function parameters also requires providing additional metadata - either the solidity-style function signature, or the ABI specification for that function.

@Arachnid Thanks, those are some good arguments.

That being said, I'm not particularly convinced that the value in future-proofing is worth the negative security risk of using raw data. In particular, I really think there is a lot of value in providing verifiable transaction metadata along with each request. I would like to get away from the current pattern that requires users to often sign opaque data because the current patterns are so low level that all of the human-readable metadata has been lost.

You can see me making this same argument in multiple EIPs for those that are following along. :)

Hello everybody

Our company is working on several products, including webwallet for ERC20 tokens.
Therefore, we needed a good QR code generator that supports ETH sending, as well as ERC20 tokens.
And we created it: https://github.com/jibrelnetwork/ethereum-qr-code
You can try to use it, docs and demo are available.
Feel free to use it in your projects :)

We had to implement a URI scheme that supports the transmission of ETH, as well as the calls to contracts.
Obviously, to call a contract, either the data parameter or the function signature is required.
We choose the second one because the purpose of the QR code is to transfer the TX details to the user's GUI app.
And the function signature helps to generate a good interface to call a contract.
I.e. we can name input fields in the UI, we can check the input data based on types of arguments etc.
With binary data, it's difficult to provide a really good interface for token transfers and even more for other custom use cases.
We considered all other factors as technical details that are not relevant to end users and decided to use function signature.

Below is the URI scheme that we used in our QR-generator
Any feedback is highly appreciated

URI schemes

This QR code generator supports URI across three different use-cases:

  1. Sending ETH
  2. Invoking function of a contract
  3. Sending ERC20 tokens

We cover these 3 different cases using a parameter called 'mode'. The details are outlined below.

1. Sending ETH

URI scheme used to send ETH between accounts conforms early EIP67 proposals and Bitcoin scheme.
This is built to be backward compatible.

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

Parameters:

  1. to | String | required - The address of the recipient account

  2. from | String | optional - Address of the tx sender. Defaults to current active account of the sender app

  3. value | Number | optional - Amount of ETH to send. Measured in wei. Defaults to 0.

  4. gas | Number | optional - Recommended amount of gas. Defaults to 21000.

These are the only parameters needed for this use-case.

For the other use-cases, the mode field allows for defining the structure of the resulting JSON. The URI scheme to invoke the contract's function uses JSON to encode the parameters specified.

Possible inputs for the mode field:

  • contract_function
  • erc20__transfer
  • erc20__approve
  • erc20__transferFrom

These are explored in more detail below.

2. Invoke function of a contract

That mode is utilized by specifying "mode: "contract_function".

Example of the transfer method using an ERC20 token:

{
  "to": "0xcontractaddress",
  "from": "0xsenderaddress",
  "value": 0,
  "gas": 100000,
  "mode": "contract_function",
  "functionSignature": {
    "name": "transfer",
    "payable": false,
    "args": [
      {
        "name": "to",
        "type": "address"
      },
      {
        "name": "value",
        "type": "uint"
      }
    ]
  },
  "argsDefaults": [
    {
      "name": "to",
      "value": "0xtokensrecipient"
    },
    {
      "name": "value",
      "value": 1000000000000000000
    }
  ]
}

Parameters:

  1. to | String | required - Recipient address

  2. from | String | optional - Sender address. Defaults to current active user account

  3. value | Number | optional - Amount of ETH to send. Measured in wei. Defaults to 0.

  4. gas | Number | optional - Recommended amount of gas. Defaults to 21000.

  5. mode | String | required - Mode of invocation. Expected value: contract_function

  6. functionSignature | Object | required - Object that defines signature of invoked function. It is used only if "mode" == "function"

    1. name | String | required - Name of the invoked function

    2. payable | Boolean | required - Defines whether function is able to receive ETH or not. (value should be zero if false)

    3. args | Array | optional - Contains list of function`s arguments. If this parameter is present - it must contain at least one element. If this parameter is not present - we assume that function do not have arguments.

      1. type | String | required - Type of the argument: uint, uint8, int32, address, bool and so on.

      2. name | String | required - Name of the argument. Used to generate GUI for the transaction.
        In fact, argument of Solidity function can be unnamed - this is OK if you develop a smart contract.
        But QR codes are used to pass tx details between different wallets and GUI must be nice.
        Therefore unnamed input fields in GUI are not possible. Therefore this parameter is required.

  7. argsDefaults | Array | optional - Array with default values for function arguments. If this parameter is present - it must contain at least one element. We do not require to provide defaults of all args.

    1. name | String | required - Name of the argument. Should be equal to the name of one of arguments from functionSignature

    2. value | Any | required - Default value for the function argument

3. Template for ERC20 tokens

The 3 extra subtypes were added since ERC20 tokens are very popular.

To make it easier to send tokens between accounts we predefine function signatures for the methods from ERC20 specification:

  1. "mode": "erc20__transfer" will result in function transfer(address to, uint value) returns (bool success)
  2. "mode": "erc20__approve" => function approve(address spender, uint value) returns (bool success)
  3. "mode": "erc20__transferFrom" => function transferFrom(address from, address to, uint value) returns (bool success)

Example for transfer method:

{
  "to": "0xcontractaddress",
  "from": "0xsenderaddress",
  "gas": 100000,
  "mode": "erc20__transfer",
  "argsDefaults": [
    {
      "name": "to",
      "value": "0xtokensrecipient"
    }
  ]
}

Functionally, this is similar to the previous example.

Parameters:

  1. to | String | required - Recipient address

  2. from | String | optional - Sender address. Defaults to current active account of the sender user

  3. gas | Number | optional - Recommended amount of gas. Defaults to 21000.

  4. mode | String | required - Mode of invocation. Expected value: erc20__transfer, erc20__approve, erc20__transferFrom

  5. argsDefaults | Array | optional - Array with default values for function arguments.

    1. name | String | required - Name of the argument. Should be equal to the name of one of arguments from functionSignature

    2. value | Any | required - Default value for the function argument

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.

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).

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.

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.

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.

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.

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.

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

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.

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.

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.

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?

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.

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.

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

@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.

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)

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

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.

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

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.

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

@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?

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.

commented

@johnda98 please have a look at ERC-681

This proposal has been superseded by #681

Thanks Ligi and Alex :-)

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

@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.

commented

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