EIP-7702: Set EOA account code for one transaction

Thanks, I’ve edited my above comment so include this option so it’s comprehensive. I don’t feel strongly on the approach used to support deterministic deployments.

To support deterministic deployments though, you’d have to only sign over code hash and not an additional address. If signing over an address you cannot rely on Nick’s Method to specify an arbitrary signature that recovers to a fixed authority, because the address containing the required code hash might differ per chain.

1 Like

Yes, this is why you only sign over the code hash and not the address. The address with the corresponding codehash is supplied to the top-level transaction instead of the codehash. So to be explicit, the codehash is only part of the 0x05 (auth) signature and the code address would only be part of the 0x04 (tx) signature. Thereby, the code location can be different on different chains, but the authentication is tied to the codehash.

2 Likes
  1. If nonce list item is length one, verify the nonce of authority is equal to nonce.

does it mean that the nonce of the authority will be increased?

Can anyone who knows please explain the justification for

It will In the case of multiple tuples for the same authority, set the code specified by the address in the first occurrence.

from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-7702.md#behavior?

The most impactful improvement will be the ability to do multicall writes, e.g. doing WETH.approve() and Pool.swap() in a single TX.

Presumably the way this is supposed to work in EIP-7702 is that you set your contract code to some contract that enables this.

  1. Does this work out of the box with existing wallets (e.g. gnosis safe)?
  2. If not 1, then what does an implementation of this look like?

FWIW, definitely agree that non-chain-replay protected authorizations are important. We would want to use the chain id 0 that is currently proposed to support chain abstraction, and having the option at the application level is nice. Invalidation/revokability seems less clear, I could see an argument for having time based expiration instead of nonces. If users have to actively revoke to be protected from contracts that collect authorizations for years and then suddenly steal assets, it doesn’t seem like they’ll be all that much more protected in practice.

Oh nice! Yes I had missed this proposal, and yes it does solve the issue of implementing a permissionless CREATE2 deployer which is awesome. Not to mention, it helps with some x-chain issues around “is this code the same on all chains” which is a nice side-effect.

It still doesn’t solve the usecase I described in:

Notably, users would need two signatures to turn their EOA into an initialized smart account, but this is acceptable. We’ve cooked up some clever ideas on making 7702 work with Nick’s method (by encoding context in the r value of the signature), so really the “two signatures for using an EOA as a smart account” is the only downside left.

All in all, I much prefer signing code hashes to addresses as you suggested. That being said, I still very slightly prefer signing code as it is more expressive and may enable use cases that we haven’t thought about yet, but would be very happy if there was a decision to sign code hash instead of addresses.

To update my meme:
image

1 Like

Seriously, is there any reference implementation yet? This EIP is concerningly far along without any example using contract_code to do a batched TX / multicall write, when that is stated to be the first issue it aims to solve:

Batching: allowing multiple operations from the same user in one atomic transaction. One common example is an ERC-20 approval followed by spending that approval, a common workflow in DEXes that requires two transactions today. Advanced use cases of batching occasionally involve dependencies: the output of the first operation is part of the input to the second operation.

The Otim team is almost done with the 7702 Reth implementation and is working on all necessary base case contract reference implementations in parallel. They are built with the current spec in mind (hence contract_address ). We will be posting about this all soonTM.

2 Likes

I think the argument is slightly different. It’s not the signature that is like the private key, it’s making the signature that is similar to handling a private key. You won’t just throw you private key into some random text box, just like you wouldn’t sign some random 7702 sig request that comes your way (and wallets shouldn’t even allow you to make such a sig).

This is certainly possible if smart wallets are designed to support it or if you are sure to always sign over revocable signatures.

Fortunately we’ve seen wallets and infra providers ban together to do the “safe” thing with chain id. Today it is very difficult to include an non EIP-155 tx on chain. I don’t see why providers would do something considered unsafe to “simplify UX”. I think not signing the chain ID is certainly simpler than thinking about which network you’re on.

It’s also worth noting again that signing an unrevocable 7702 auth is not neccessarily unsafe, it depends what the EOA delegates to.

1 Like

I think the argument is slightly different. It’s not the signature that is like the private key, it’s making the signature that is similar to handling a private key. You won’t just throw you private key into some random text box, just like you wouldn’t sign some random 7702 sig request that comes your way (and wallets shouldn’t even allow you to make such a sig).

Let the “authority code” which user authorizes be called template. The wallet providers/products are under much more scrutiny from rest of the ecosystem to be safe and provide the “right” safety measures (as it should be). The template ecosystem on the other hand is more widely open, it is the wild west similar to the general smart contract ecosystem on Ethereum today. Even if wallets whitelist safe templates, and present warnings to user when signing a non-whitelisted template, users can (and will!) sign such templates. If an attacker owning an upgradeable proxy template manages to get a user’s authorization to such a template, the attacker can practically do anything by then swapping the implementation. This grants the malicious implementation power to CALL any other smart contract with (msg.sender = EOA).

The mental model seems to be that if user does such a mistake, they have to bear the consequences. But IMO account abstraction is a lot about providing safer, error-recoverable experiences to user, and it should extend to stopping users from shooting their own foots in cases they inadvertently expose themselves to risk.

The caveat here is that I might be assuming certain things about who owns the templates and if the user can interact with templates outside the purview of wallets. I would like to know your thoughts on that.

This is certainly possible if smart wallets are designed to support it or if you are sure to always sign over revocable signatures.

In general I’ve become fine with the idea to trust my wallet (not forever though). I can trust the wallet to provide a “revoke previous authorizations” feature. Without in-protocol revocation, it means I’ve to depend on the template code having appropriate logic to respect such a revocation. If the template codes are minimal proxy or an implementation (as it probably would be) + template code has revocation mechanism, this is fine.

As for “always sign over revocable signatures”, if the method is optional nonce, I responded to that in the my next comment.

Fortunately we’ve seen wallets and infra providers ban together to do the “safe” thing with chain id. Today it is very difficult to include an non EIP-155 tx on chain. I don’t see why providers would do something considered unsafe to “simplify UX”. I think not signing the chain ID is certainly simpler than thinking about which network you’re on.

It’s also worth noting again that signing an unrevocable 7702 auth is not neccessarily unsafe, it depends what the EOA delegates to.

The issue with optional nonce stems from the feedback we got from wallet providers — i) accounts will be used as both EOA and smart accounts, and ii) most of AA use cases rely on long-standing authorizations. So with a nonce-based-revocable-signature, an EOA tx might inadvertently end up revoking an authorization. It seems to me that because of this wallet design space would be pushed to a scenario where revocable signatures are second-class citizen, as nonce revocability is not compatible with AA use cases.

Ultimately I don’t see a safe way to allow users to sign untrusted templates, even with substantial friction in UI. This is similar to today where almost no wallets allow blind signing arbitrary signatures (yes, they allow blind signing, but it is scoped to a 191 message or tx data – this is an important distinction).

If users may sign arbitrary templates then I agree with you completely and there will funds lost.

Yes it’s possible with nonce-based-revocable-signature you may inadvertently end up revoking an authorization. However, there are many application-layer mechanisms which could be used to avoid such cases. This is actually a similar issue that smart accounts have today, which is syncing the authorization scheme across networks. A proposed solution is a simple keystore rollup which stores the authorization logic for user account and it can be pulled in efficiently on all networks. This concept could be extended to notify other EOA wallets that a user has an outstanding 7702 signature.

I don’t think I would go so far to say that nonce revocability is not compatible with AA though. In the happy case, your wallets should be able to use your account exactly as an AA wallet via 4337 or a centralized tx bundler. There is no need for the EOA to send a tx in this scenario (except to revoke).

My concern is that if revocation is stored in the account itself it’s difficult to ensure a template stays revoked forever. It’s not a property one can verify for a template, it’s a property that has to hold for all of the templates the EOA will ever authorize. Undoing a revocation can be done quietly if it only takes an SSTORE.

By storing revocation status in another contract it would be possible to avoid this issue, but I don’t know if this can be made compatible with ERC-4337/7562 validation rules.

Another approach to avoid this issue is to only ever sign one authorization, for a proxy. If this will be the recommendation, I don’t know why EIP-7702 is so general, let’s just hardcode this into the protocol.

Additionally, there is no “true revocability” because the ability to load the code into the account will remain, even if the code can be made to reliably revert. Whether this has practical consequences is debatable, but it doesn’t feel right.

I don’t want in-protocol revocability to be too heavy-handed, but I’m not a fan of the current compromise either.

I proposed an alternative revocation mechanism that I think has better properties: Update EIP-7702: Add system contract for revocations by frangio · Pull Request #8631 · ethereum/EIPs · GitHub. Please review and leave comments (cc @matt in particular).

What you’re proposing can (and I think should) be done by an ERC. For that reason I don’t see a reason to introduce the complexity into the protocol.

1 Like

Yes I believe that’s mostly true, except for preventing revoked template code from being loaded into the account.

1 Like

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.

How do you envision dapps communicating 7702-style authorization tuples to the Ledger? I think the only standard interface being discussed right now (bear in mind that I’ve been out of the loop for a while :sweat_smile:) is EIP-5792. Ledger would need to pick the bytecode to use anyway, so no different than a whitelist.

How’s this for a revocation mechanism:

  1. Use initcode (either in the transaction or by referencing a deployed contract.)
  2. Transaction reverts if any of the initcodes don’t begin with a specific bytecode prefix, implementing “call into well-known nonce manager, propagate revert.”
  3. Nonces are handled by EVM.

This gives us the maximum amount of future flexibility (revocation is handled purely by the EVM), and mandatory revocations today.