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.
Protocol Smart Contract Wallets
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.
Validation Focused Wallets
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
validate
- convert all EOAs to bouncer smart contracts that also implement the
validate
section which checks thatecrecover(msg, sig) == address()
- if no AA yet, make a special allocation in clients that allows accounts with
code_hash
equal to the EOA contract to initiate a transaction - modify the behavior of
AUTH
to call thevalidate
section on the recovered address, and only setauthorized
if the account’svalidate
returnstrue
- add
AUTH2
which takes atarget
parameter whosevalidate
section is immediately called upon invokation and only setsauthorized
if thetarget
returns true (alternatively, we could immediately shipAUTH2
in EIP-3074 and requiretarget == recovered address
until the EOF sectionvalidate
is added.)
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.