I posted a thread on twitter giving a high-level overview of how this EIP will be used in practice: https://twitter.com/lightclients/status/1371911245561917441?s=20
No problem, I’ll update it now…
I’ve written a document to discuss some different threat models EIP-3074 should be considered under and how they compare to EOAs and smart contract wallets today: https://hackmd.io/@matt/BknnAnyNu
EIP-191 specifies a safe format for signed messages, which already contains a subformat for messages of the type
(ID || validator || payload). Could you use that rather than reinventing the wheel?
Per @timbeiko’s request, here’s a link to a twitter thread I’ve written on this EIP.
Probably my most important comments from the thread are:
Okay, so top question this is going to provoke, especially for “should we commit to shipping this tomorrow?”: IS IT SECURE? I believe the answer is YES, and for a simple reason:
EIP-3074 signatures always have a 0x3 prefix, which currently no Ethereum wallet will sign (at least without a warning that you may be signing everything away). For this simple reason, we can already safely say “no user can become vulnerable to this without accepting the risk.”
Fun challenge: What other features could you implement for any account with this pattern? While these invokers all derive their power from a signature, they can have state, and are replay-strategy agnostic! You could have a cold wallet that delegates to an m-of-n multisig!
191 is just a draft while 2918 is in review and will almost certainly be included in Berlin (brining it to final). Also (probably a better discussion for 191 discussion), it is unclear to me why 191 is so prescriptive about the layout of the bytes after the version, and why the first byte is wasted on always being 0x19 instead of just having the first byte be a version (constrained to not compatible with legacy transactions).
To be fair EIP-191 has been in production for about 5 years now. I think EIP-191 is a more proper standard to use for non-tx signing and commonly supported by most wallets. We can introduce a version explicitly for this EIP so there is no change of signature collision and wallets must opt-in support. I don’t really see a downside to switching to EIP-191.
Assuming the authors of 191 decide to move forward with the standardization process, what benefits does it provide over 2718 transaction types?
IMO 2718 = transaction types, where 191 = message signing format. This EIP is not a transaction, so 191 seems to be a better fit.
Assuming multiple protocol allow a similar invoker, it can open a gate for users to sign as many functions thereby spamming until one trx get successfully mined. Similar to opensea spam bots which keep bidding even if they dont have the equivalent assets in wallets
Someone’s gotta pay for that gas, and if the gas price is too low, the transactions won’t propagate, so I don’t think this EIP introduces any more risk of spam than normal transactions.
Congrats to @SamWilsn on a great presentation of EIP-3074 today on the All-Core Devs call. I think you provided the correct answer to most challenges that were presented, and I hope you’re not discouraged by the sentiment to take more time to prove its safety. (1/x thread)
This call made me think of a theme that has become tragically common in my mind in the last few years, as Chip Morningstar says, “You can’t tell people anything” (we might need to demonstrate the value to get the actual buy-in)
In violation of that advice, I’m now going to take a shot at explaining the safety again, in response to a repeated misunderstanding on the call.
I was pretty disappointed to see multiple smart people, (and every objector!) comparing this proposal to SUDO. It’s a catchy objection, but I think it’s pretty easy to demonstrate why that equivalence is dramatically off, and I think drilling into exactly why it’s different might help others build an intuition for how this EIP works.
This is Alice. She has lots of different valuable things in her account.
In actuality, her account is just a metaphor for control, and each of these assets is defined by a different smart contract that obeys her account to control her assets. These arrows represent a flow of control from their fundamental source of truth to an intended recipient.
Today, when interacting with a smart contract like an exchange that needs one of Alice’s coins, she has to first ask that contract for permission, and then inform the other contract (like BobDEX), she first needs to tell the token’s contract to grant an allowance to this new contract, and if this is granted to a malicious contract, guess what happens? (Follow the arrow!)
As we can see from this new “allowance” arrow, Alice used the allowance function to symbolically delegate control of one of her tokens to this new dex. If Bob is evil, he can now steal all of her BlueCoin. People sometimes grant their whole token balance to an untrustworthy contract, and that’s a form of phishing that is real and people do it.
There are different approaches to solving that problem, and they are rooted in multiple problems that are at play:
- The user got phished into wanting to use an exchange that was malicious.
- For convenience the user delegated their whole token balance, when “just enough” would be safer.
Fundamentally, if a user wants to engage with a smart contract, they need to deposit assets into its trust. Even platforms that are prioritizing “offer safety” like Agoric’s Zoe (we guarantee you will receive at least X in exchange for Y) requires that you trust the offer-safety contract itself. Without that initial risk, there is no contract to be had.
This is the tension of a smart contracting platform: Squeezed between letting the user do whatever they want, and keeping them safe. It is natural to want to avoid introducing new insecurity, even at the benefit of new features, and so we should strive to prove that a new mechanism introduces no new insecurity to the platform, and I think this can be proven.
Coming back to EIP-3074. An invoker contract allows for a user to delegate FULL CONTROL OF THEIR ACCOUNT. The most concerned people say this sounds like SUDO, and probably imagine it looks like this to interact with an application:
But actually, this new proposal never suggests delegating messages to new applications. It’s not a tool for that at all, and its “invokers” are better understood as part of the wallet’s own code.
While the addition of an invoker is sensitive, and should be treated as carefully as an infinite allowance permission, this risk is not for regular interactions with new applications, and most wallets probably won’t even allow users to perform this delegation (and at least should never without extreme caution).
Once a wallet trusts an Invoker, it is able to perform batching operations with the user’s keys, or whatever other features the invokers offer and the wallets feel is worth the risk of adding. Exactly like the risks that wallet developers already take every day when evaluating and adding new features.
One of the reasons of infinite allowances today is that gas is expensive, and a user might want to avoid an increased-approval transaction later by approving a higher allowance now. If we had support for batching, wallets would actually have tools to facilitate fewer, cheaper user approvals that allow them to delegate LESS authority to outside parties.
When invoking SUDO, a UNIX user grants the highest authority of the entire system to an application they are invoking. Heck, in UNIX, every invocation grants your full user account authority to any program you run.
In UNIX, every time you run a program you’re basically handing it your private key, and no one is more concerned about those kinds of unintentional delegation risks than wallet developers, and that’s why at MetaMask we’re building tools to allow running scripts with reduced system access:
Unlike the unix permissions model, A 3074 invoker adds a system for wallets to add new trusted modules that can allow for new ways of key-managed accounts to delegate authority.
Once delegated, the most those invokers can do is send messages from the user’s account, meaning if a contract is secure against current user behavior today, it should continue to be secure regardless of any delegation actions the user performs outside of that contract’s system. If another account’s behavior can put a contract you care about at risk, then that contract is not secure.
It was compared not to Unix
sudo, but to
SUDO opcode proposal, which was April fool’s joke, of course. I think comparison with
SUDO opcode is actually quite useful to understand what EIP-3074 does. As I mentioned on the call, it does it with restrictions, and I also explained what these restrictions are, from my point of view.
I am sorry for not engaging into the discussion on this topic on the call (simply because I was engaging into discussion in the Discord channel, and I also I had to leave the call earlier), but I did want to voice my objection because, as it happens, objectors have to object on every single call for the objections to be heard (and this is unfortunate). I am Ok with you being disappointed, but I wanted to say that I was not trying to be difficult. I was willing to put work in understand what the EIP was, pretty early on, and go against the “community sentiment” to voice my concerns. Consider this as a contribution and not as trolling please.
I do understand that this may be necessary security compromise for better usability, but I think I correctly judge that most people don’t really understand what is being changed, and why this is a compromise.
For the record, the joke proposal is here, and allows anyone to send messages from any account without any proof:
I think comparing these is ludicrous, as one lets anyone do anything, and the other allows key holders to delegate their own powers, and no more.
I disagree that this proposal makes security compromises. If we assume two security properties, it is safe:
- Users and wallets do not sign invoker messages without intending to delegate account powers.
- Existing smart contracts are secure under unrestricted behavior of other accounts.
I was not disappointed that you expressed concerns (and I agree they should not need presenting on every call), but it’s pretty shocking to me that you’re still insisting 3074 is anything like SUDO.
On the All Core Devs Call, @vitalikbuterin mentioned that long term all accounts should be tending towards being contract accounts anyways, and I think this was maybe a point for why this EIP isn’t needed.
I think we all agree that from a feature perspective, this is a desirable future, but from an implementation perspective, this introduces lots of complexity related to the migration. EIP 3074 provides a concrete migration path from a private key controlled account to a contract account, so that existing EOAs can continue operating even if its original keys are no longer on hot wallets, and they are transitioned to a mostly contract-style use
I disagree that it is ludicrous. When I myself tried to understand what EIP-3074 actually does, one of the iterations of my understanding was the same functionality as
SUDO opcode, a completely unrestricted version of
AUTHCALL. Then, of course, I realised that such opcode is dangerous, and how exactly EIP-3074 restricts this.
I also insists that it does make security compromise, which needs to be acknowledged, if this EIP goes in (which, of course, may happen despite my opposition). The main problematic thing I see in this EIP is that it creates a possibility of a very lucrative scam, which does need to involve wallet providers, willingly or not, and which is not really possible with today’s meaning of signatures. If someone manages to inject code into wallet provider’s release in some way, and introduce a “sleeper bug”, which will not attack users straight away, but work as expected, but harvest signatures to an upgradeable invoker contract. Once the time is right (enough signatures are harvested, containing enough value to steal), the attacker upgrades the contract and sweeps the tokens, at the time of their choosing. I know you would say this is unlikely, but, given the reward, such scheme is not outside of realm of possibility. And, as far as I know, such scheme would not work today, because one signature cannot give access to arbitrary number of operations in the future, and also the signature can be made invalid by issuing a transaction with the same nonce. In the harvesting signatures scenario, the only revocation possible is to create new address and issue lots of transactions to move tokens over.
And to conclude, there is alternative to this, which I unfortunately could not put a lot of work in. It is through the new transaction type allowing multiple signatures. I do posit that transaction relay is not the use case where we HAVE to introduce the property that one signature authorises unlimited number of future actions. Such property may be required for other things, but not for sponsored transactions. From my point of view, it is overshooting, i.e., a more security-conservative solution would be enough.
Is the attack vector that you’re concerned about here that the wallet UI could be modified into allowing signatures to an untrusted invoker then the signatures could be reused later once the invoker is modified?
Regardless, once you can inject code into a wallet, you can encrypt and exfiltrate the account’s private key as extra bytes in calldata. Yes, I know hardware wallets exist, but they should prevent signing EIP-3074 messages anyway.
I always use hardware wallets for signing anything of value. But checking what you are signing is not easy, perhaps unless you have something like Grid lattice. That’s why I do not usually like working with tokens
This is exactly why wallets won’t leave it to users to hopefully review which EIP-3074 invokers they’re signing over. It will be hard coded that the wallet only supports these specific invokers that the wallet team has reviewed and that have community trust/support.
Thanks for sharing a concrete example.
Thanks in part to
CREATE2, I think you’re right that an invoker could be changed at the same address. There are simple ways to completely avoid this, like only trusting invokers that are published with
CREATE, since their address generation cannot be reproduced.
This is a good example of a serious consideration that needs to be taken when delegating to an invoker, but I don’t think this is new. Wallets are effectively already constantly exposed to this kind of attack (new code could silently undermine user trust at a later date), it’s just that it’s client-side, not always on-chain (although contract-based wallets are basically already vulnerable to the exact scenario you describe). I don’t think this changes the threat model of wallet development in any way.
Fortunately, no one is exposed to these risks by 3074 without someone at a later date making a deliberate choice to integrate the invoker into a wallet, or to sign a delegation message, and even then, the risk is limited to the negligent parties (or that wallet’s users).
Fortunately, this conversation would not end at the inclusion of EIP-3074, instead it would represent the beginning of the design of secure invokers. I have no doubt that good invokers can be built that are widely vetted and easy to trust, and will leave this particular concern comfortably to rest.