A case for a simpler alternative to EIP 3074

Introduction

Thank you so much for the in-depth review! This is incredibly valuable, and you raise excellent points. I’ve understood a couple different criticisms that I’d like to summarize and discuss separately, before diving into your alternative proposal:

  • Principle of Least Privilege: once an invoker has an authorization, it has complete control over the signing account.
  • Buggy or Malicious Invokers: invokers may be complex pieces of software, and may contain bugs or even be malicious.
  • Eternal Authorizations: once signed, without a cooperating invoker, an authorization lasts forever.
  • Chain Id and Clever Contract Creation: an invoker on one chain (testnet, Ethereum fork, etc.) seems secure and checks the chain id, but a malicious invoker is deployed at the same address on another chain which does not check the chain id.

Criticisms

Principle of Least Privilege

Once an invoker has a signed package, it has complete control over the signing account.

This is absolutely a concern shared by all of us authors. At first glance, it might seem like signing an EIP-3074 package is strictly worse than an infinite ERC-20 allowance. Instead of granting access to one token, you’re granting access to all of them, forever. Oh, and it’s irrevocable.

As @danfinlay pointed out in his excellent comment, many people have compared EIP-3074 to unix’s sudo command: signing a 3074 transaction is like giving up complete control over your account.

Both of these comparisons (to ERC-20 allowances, and to sudo) are true, to some extent, but they lack a lot of nuance.

An ERC-20 allowance has two components: what address is authorized, and an amount that address has access to (which may be infinite.) The owner has zero control over what the authorized address does with their allotment. A malicious contract could look safe, but when authorized, it transfers all the tokens away. On the other hand, an EIP-3074 authorization can set incredibly specific rules through the invoker for what can be done with the tokens.

To bring this back into the unix analogy, I believe EIP-3074 is a lot more like the setuid bit than sudo itself. An executable which has the setuid permission assumes the identity of its owner rather than the identity of the executing user. Oftentimes, the owner will be root, allowing non-root users to execute specific tasks with elevated permissions.

My central theme here is that while an EIP-3074 authorization grants the invoker full power over the signing account, the fact that the invoker is programmable enables extremely fine-grained control over exactly what can be done with that power.

EIP-3074 is not sudo. It’s setuid.

Buggy Invokers

Invokers may be complex pieces of software, and may contain bugs or even be malicious.

This is unequivocally true. There will be buggy invokers. There will be invokers designed to scam. There will be trojan invokers who try to collect authorizations over time and eventually topple DAOs.

I still believe EIP-3074 is worth pursuing in its current flexible form. With UI mitigation, good security messaging, and carefully built code we can keep the majority of people (and their assets) safe.

This comparison has come up several times while socializing EIP-3074, and I’ll defer once again to @danfinlay. He summed up why we shouldn’t compare EIP-3074 authorizations to traditional transactions more eloquently than I can in his comment. I’ll quickly paraphrase it here:

EIP-3074 allows a user to delegate full control of their account, and therefore invokers are better understood as part of the wallet’s own code and not as a separate contract.

In other words, we shouldn’t compare signing an EIP-3074 package to a traditional transaction, but to installing an extension for a wallet. Few wallets do this today, and none of them do it lightly. EIP-3074’s security proposition is very similar: install a malicious wallet/extension and get pwned; sign an authorization to a bad/buggy invoker and get pwned.

If I rewrite your paragraph replacing “EIP-3074” with “wallet” (and I mean zero disrespect here, I just couldn’t come up with a better way to convey my point), your criticism is equally valid:

[Using an Ethereum wallet] requires the user to sign a blank cheque and assume that the [wallet] is honest and not buggy. A malicious/buggy [wallet] could do anything on behalf of the user - access any asset owned by the user, vote on behalf of the user, take ownership of any contract owned by the user, etc.

I think, therefore, it’s reasonable to draw the conclusion that invokers have a similar security profile as wallet software.

Wallets are already complex pieces of software, attached to browsers as often as not. The fact that they are not compromised on a daily basis gives me a little hope that we can write safe and solid code.

I would be remiss not to point out that wallets never transfer your private key, and EIP-3074 authorizations would necessarily be public, so there is that added risk. I would argue that invokers will be much simpler than wallets in general, so I think that balances out somewhat.

Buggy invokers would have to be seriously and obviously broken to be compromised to the level you suggest. Obviously the more complex the invoker is, the more opportunity for issues, but we can structure invokers in such a way that the more bug-prone/complex sections happen after the easy-to-verify sections. Essentially, check nonces before running batched transactions.

On-chain replay protection is putting a nonce in the commit, comparing a storage slot, then incrementing it. Screwing that up is difficult (not impossible, of course :rofl:.) To change the authorization’s target you’d basically need to omit it from the signed commit, and same with the calldata. Also somewhat difficult to screw up.

I don’t think it’s outside of the realm of possibility for wallets to reject invokers which haven’t been formally verified and extensively audited. Combine that with strong best practices, and an attitude of abundant caution, and I think we can be reasonably certain that even the buggiest of whitelisted invokers won’t allow attackers to obtain permanent access to an account.

Malicious invokers are a completely different beast. Audits and formal verification can only go so far here. Instead we have to rely on social mechanisms, like whitelists and reputation. A huge part of the security proposition of EIP-3074 requires that wallets:

  • Ban, generally, any signature which might look like an EIP-3074 authorization; and
  • Allow a limited number of “trusted invokers” that have met some acceptance criteria.

Initially, for example, we expect wallets to whitelist their own sponsored transaction invokers. These invokers will likely only allow transactions originating from one of their official sponsor addresses, limiting the damage they can cause.

Further, wallets have extreme pressure to maintain stringent standards for their invoker whitelists. Users are free to move from one wallet to another, so even a hint of insecurity could destroy their reputation, and decimate their entire business model.

Eternal Authorizations

Once signed, without a cooperating invoker, an authorization lasts forever.

This is certainly a departure from other authorization patterns, like ERC-20 allowances. Similarly to the principle of least authority, however, EIP-3074 gives invokers the ability to define exactly how revocation (or expiry) will work.

At the simplest, an invoker can reuse nonce replacement to implement revocation, which should be simple enough to implement with some confidence. You could also limit validity to specific block number ranges, which is also trivial to implement.

Chain Id and Clever Contract Creation

We’ve went back and forth on chain id several times, and I think this seals it as necessary. Are you convinced @MicahZoltu?

Alternatives

Nested Transactions

This seems pretty similar to other approaches to batched transactions like EIP-2711, or EIP-3005 except with the execution controlled by a contract. It’s actually quite similar to the original EIP-3074 design.

One potential issue with your proposal is that a transaction from the signer’s account can invalidate a sponsored transaction bundle, wasting the sponsor’s funds.

Do Nothing

There are a couple use cases that EIP-3074 enables, which I don’t think can be implemented without some change. Synthetic EOAs, which are useful for state channels, are a really interesting unique feature of EIP-3074.

Contract wallets have a lot of the same issues as EIP-3074 invokers, so I don’t think they’re a better solution.

The End

Thanks again for your comments, and for catching the issue with chain id! We all really appreciate the thorough review.

5 Likes