Hi all,
Here is Ledger’s proposal regarding EIP-7702, both from a wallet provider and a hardware wallet with limited computation perspectives:
1- Signing contract code (if it’s still debated)
It would be extremely difficult for Ledger to implement EIP-7702 if we were to use signed contract code. For security reasons, we will have to implement a whitelisting mechanism, preventing the full use of the feature anyway and probably falling back on allowing an ERC-1167 minimal proxy + some known implementations.
We have no way to recognize bytecode dynamically with only the device, so our best option is to focus on the implementation address in order to make it clear and understandable at the signature stage that you would be signing a long lived authorization to transform your EOA into a Smart Account of X/Y/Z brand.
2- Revocability
It seems mandatory to us to have a revocation mechanism, and having a nonce/maxNonce based one seems impractical for everyone, from builders to users.
We want our users to have the freedom to go the AA way, but not in a way that would force them to understand some very complex protocol mechanism and where 1 signature can become a forever problem.
3- Multiple authorizations at a time
Having the possibility for software wallets, DApps or Bundlers/sponsors to keep multiple authorizations for a same EOA, making it possible for them to behave in multiple ways for a same transaction intent, is definitely something that worries us in terms of both UX and security. Since most AA implementations will make you sign personal messages or EIP-712 messages for those intents to be sponsored somehow, that means our devices will never be able to tell you exactly what you’re doing since we have no way to predict what 7702 authorization will be used once reaching the sponsor which can make that message act differently with every AA implementation.
Here is our proposal at a flow that would make sense to us in terms of UX and that might allow us to display things correctly and securely on our devices:
Our understanding is that we could have a short lived authorization message as long as it’s not expected to be added to every single type 4 transactions. If true, then the signature could be based on keccak(MAGIC_BYTE || rlp([chain_id, nonce, address]))
almost as the last version of the EIP is proposing but with a mandatory nonce.
Now a mechanism similar to ERC-1967 could then be used to fill a specific storage slot on the EOA’s storage with the implementation address signed with that authorization (something like keccak256('eip7702.transient.implementation')
) as long as the authority has no code already. The user will now have to send that authorization and an initialization calldata for that implementation as transaction type 4 in order to “activate” the AA behavior, making the nonce increase and the authorization unusable. Accepting to use SSTORE & SLOAD on the EOA is then mandatory obviously.
At the protocol level, the expected behavior when dealing with a type 4 transaction would then be to verify before any (*)CALL whether or not this slot contains an address for its target/recipient, and if it has, load it in a transient manner as its contract code just like the actual EIP is proposing.
If this brings too much complexity to do it for every recipient of a (*)CALL on the fly, then providing a simple list of address at the transaction level could be an option, just like the access list of EIP-2930 for example.
Any transaction of type < 4 would ignore that mechanism and continue acting like the account is an EOA, making the transition to AA “optional” and not forcing users to spend more gas if they’re not actively using an AA feature (like batching or delegated keys).
At the device level, it would then be possible to provide a storage proof like described in EIP-1186 for that specific slot before signing something and that could give the necessary context in order to verify that an address handled by the device should behave like an X/Y/Z implementation instead.
Good points about this proposal:
- It’s revocable anytime. Just sign a new authorization message with address(0) and you’re back to the original behavior (minus the storage used by the implementation)
- Upgradable anytime as well, and even auto upgradable directly from the implementation, just like any AA proxy
- It’s long lived, you sign an authorization once, you’re good until you decide to update that storage slot again, and it’s not up to a software wallet / DApp / Sponsor to keep those powerful messages
- Limit EOAs to 1 implementation at a time → Way easier for the context of a wallet, and can answer EIP-5792 capabilities in a clear way by checking that specific storage slot.
- “Clear signing” (ledger[dot]com/blog/securing-message-signing) is back to recognizing a simple implementation address and not recognizing bytecode, while being as little centralized as possible by relying on a storage proof in order to switch from 1 behavior to another.
More controversal:
- It’s using SSTORE & SLOAD
- Something else ?
As a last comment, this message should not be considered as an endorsement from Ledger to support 7702, but more as a lead into something that looks more manageable for us.