Some concerns were recently raised about EIP-3074 and it’s compatibility with the future goal of eradicating EOAs from the protocol. I’ve spent some time thinking about this, and I think EIP-3074 actually provides an interesting alternative upgrade path.
If we’re going to replace EOAs, we should think carefully about what will replace them.
Smart contract wallets today are generally implemented top down. In the simple case, the wallet acts as a bouncer. It validates the call to it and then forwards the message to the target contract. In more complicated cases, it is a collection of functions that are used in different ways to create complex access policies.
A simple bouncer contract is the natural replacement for EOAs. But although it has feature parity with existing EOAs, it has none of the benefits of smart contract wallets that Vitalik outlined.
There are alternatives to this, but they fail to provide two attributes that are desirable for a protocol wallet:
- Agnostic to tooling of today. Solidity and current ABIs should not leak into the protocol.
- Extensible without requiring on-chain initialization.
To meet these requirements, we’ll need to rethink how smart contract wallets are designed.
At their core, smart contract wallets just enforce access policies for the address they’re deployed at. Actually instantiating the
CALL or performing replay protection in the smart contract wallet is just an implementation detail.
If we focus on this property, we can build a smart contract wallet that is unopinionated and extensible.
In this paradigm, the migration from EOAs to protocol smart contracts would look something like this:
- deploy EIP-3074, mostly as-is
- deploy EIP-3540 (EOF)
- add a new EOF section
- convert all EOAs to bouncer smart contracts that also implement the
validatesection which checks that
ecrecover(msg, sig) == address()
- if no AA yet, make a special allocation in clients that allows accounts with
code_hashequal to the EOA contract to initiate a transaction
- modify the behavior of
AUTHto call the
validatesection on the recovered address, and only set
authorizedif the account’s
AUTH2which takes a
validatesection is immediately called upon invokation and only sets
targetreturns true (alternatively, we could immediately ship
AUTH2in EIP-3074 and require
target == recovered addressuntil the EOF section
This would give us all the benefits Vitalik outlined, while also i) not enshrining Solidity / a certain ABI encoding into the core protocol and ii) allowing anyone to enjoy those benefits (and new ones) without first interacting on-chain.
This also gives us some nice new benefits to EIP-3074. Instead of “signing a blank check forever”, users can modify their own
validate function to block certain invokers. This is much nicer than doing it in the invoker itself, because only users who wish to block an invoker must pay the storage costs to check if the invoker is blocked.
I’m curious to know other’s thoughts on this.