EIP-7702: Set EOA account code for one transaction

Non revocable, replayable signatures delegating an EOA to a contract is functionally equivalent to the security concerns with EIP 3074 invokers. Given how likely it is to work, the only way the scenario you outlined doesn’t happen is if wallets whitelist what code you can sign with extreme prejudice. Back to permissioned innovation.

IMHO, we should not be be passing an address to sign, we should be passing code. Yes it costs 30 extra bytes for some use cases, but as others have pointed it it makes the design more expressive and also more secure in that you don’t need to trust code that you delegate to as much because you can drop permissions first. You can let some provider sponsor your gas without your wallet having to whitelist them because the wallet only calls that code in the context of a spending limit. Giving that up to squeeze a few bytes out is a case of premature optimization.

1 Like

It makes it more expressive in a way which is not compatible with smart accounts. It is also not possible to let users sign arbitrary code. There still needs to be a whitelist in the wallet, otherwise the user may be convinced to sign code that allows an attacker control of the account.

No, if there is still broad disagreement it really isn’t. That was mishandled.

  1. I try explaining why giving special governance powers to client devs is dangerous and ultimately incongruous with our values here:
  1. Saying it’s ok if the client teams agree is self serving given that you can leverage the authority of the majority client in that circle and other participants can’t. Doesn’t mean your arguments have any more merit.

  2. Client devs should not be in the role of Solomonic kings that pass judgement and settle important disagreements. That’s not how the de-facto emergent consensus governance model we had worked before and I hope ACD calling for the inclusion of 3074 was the first and last time it happens.

I still hope to be convinced of that. This ongoing dispute around AA is the dumbest waste of super scarce smarts I’ve ever seen in this space. You and Yoav cancel each other out. I suspect your beef was misdirected up until recently because you thought he wrote my protecting governance from special interests post, and maybe by now it’s just a habit. They die hard

That is one thing we can agree on. Let’s move forward and focus on the technical merit of 7702 and the open questions. I have written a very detailed rationale for why the decisions made in the EIP are safe. I would like to see more discourse on why those points are wrong or why there is a better approach.

And fwiw I thought it was a troll post from someone else in ACD long ago.

The code for dropping privileges can be embedded in the wallet itself just like the code for encoding any transaction. Then you don’t have to trust the code you’re signing as much. Ideally if you authorize a contract to pay for your gas it can steal at most your max gas budget. Since the privilege drop would be encoded as part of the transaction, hardware wallets or other WalletConnect like solutions that separate transaction encoding from signing could parse the transaction and show you what you’re signing.

Before replying any message, I’d like to clarify an important point. My personal objection to the current form of 7702 due to bad security trade offs for EOA users, seem to have raised concerns that ERC-4337 will not support it. I want to reassure everyone - that is not the case.

My current objections are not related to AA. As long as 7702 is compatible with the AA roadmap and doesn’t degrade 4337, we intend to support it. The current version is not great for EOA users but will work fine with 4337, so the protocol will support it.

Not trying to publicly vilify you, just to show that what you wrote is inconsistent with something you wrote in the past. Something you have done yourself in past debates we had - taking an older message out of its original context and trying to show that it’s inconsistent with what’s being said in a different context. It’s strange that you take personal offense, given that trying to prove inconsistency is a method you often apply yourself.

Anyway, my intent is not to vilify anyone so let’s move on.

Neither are other ways we tried. Any argument not consistent with 3074 gets brushed off.

As I wrote many messages ago in this thread, I already made my case and debated the trade offs of every point in 7702, so I meant to stop debating and let the community decide based on that. I had to jump back in because you didn’t wait for the community to reach consensus and just edited the EIP to match your preference. Had you not done that, you wouldn’t have heard another word from me about revocation, etc.

We both made our case and it seems that further debate won’t get us anywhere. We should both take a step back, let the community debate it, and only jump in when something is misunderstood and requires clarification. But you editing the EIP before consensus is reached, is incompatible with that.

I noted the same thing myself on a 3074 breakout call, long before it was included. Using the nonce directly is too restrictive and kills many good use cases. Therefore I proposed maxNonce+bumpNonce during that call. It never made it to the proposal so no one had a chance to evaluate it as an alternative to nonce or to no revocation. Those external people you’re talking about didn’t object to revocation in general, they objected to the restrictive revocation method you chose to include in 3074 despite having a less restrictive option.

That’s why I suspected from the start that there will be an attempt to remove it later. If the intention was to really have revocation in the final version, you would have chosen one that doesn’t restrict use cases. The “chip away” message just confirmed what I assumed earlier.

In the current thread you stated that your preference for 7702 is no revocation > max nonce > current nonce. Since max nonce was also proposed for 3074, choosing current nonce seems strange if you intended for it to get included that way.

In the scenario I described, the wallet is the attacker preparing a rugpull. Therefore it will prompt the user to sign whatever contract it wants. This hypothetical wallet lets you connect your Ledger, sponsors your transactions for the first month to incentivize you to use it, and keeps the authorization you signed - for a perfectly legit contract that just happens to be deployed via a CREATE3 factory. After a month it stops sponsoring gas and you move to a different wallet, not realizing that your account is no longer safe. A year letter, your assets on other chains start getting drained on other chains. The first wallet effectively stole the private key from your Ledger, despite having never seen the actual key.

An address is fine as an optimization, if the signature is over keccak(address+code). The code doesn’t need to be in the transaction if it can be read on-chain. The problem in the new version is that code was replaced with address rather than a signature over both.

I believe I have done that. And the rationale is still incorrect IMHO. To take just one example, I have yet to see a flow in which clients will need to perform a database lookup on the account’s code but not to also load the code for execution. Transaction propagation doesn’t require that, and block validation requires the entire code anyway. Another thing is that the rationale makes a false assumption that the EIP will only be used in one way - each EOA only ever signs one contract. That is inconsistent with how people have been building invokers so we have no reason to believe this time will be different. If the only safe way to use the EIP is “as intended” then the EIP should not make other, unsafe ways possible.

The rationale you added is just… rationalizing why the pre-inclusion 3074 is the right model. Everything is written in support of that, and any contradicting evidence is ignored. This may work on those who aren’t that deep in the weeds and may not understand the nuances above. But you are smart and very familiar with the topic so I assume you do understand. You just choose to ignore it.

Rationale:

I believe that in the long term (3-4 years) - most EOAs will be using a single smart contract implementation (per account).

In the short and even medium term (1-2 years) there will be multiple smart contract accounts being used, and so we will be living in a diverse special-purpose contract world for some time.

One of the great powers of 7702 (inherited from 3074) is the ability to adopt smart contract paradigms gradually.

If every decision we make on 7702 adoption becomes a life long decision - that prohibits us from making these kinds of decisions at all - waiting endlessly for the optimal option. I don’t trust EIP-6900 and EIP-7579 yet, they haven’t been battle tested, but I will want to trust one of them someday. Deciding now if I adopt some intermediate smart contract without modularity or wait until these protocols mature and one of them prevails does not make sense to me. I want to be able to add some gasless/batching contract now and over time graduate myself to possibly also supporting some session keys, and some new capabilities people will invent next year but eventually to adopt a full blow AA smart account towards a transition to full AA.

So I believe there is meaningful value in things like flexible in-protocol revocation and replay protection. It will actually make innovation faster for wallets - because it allows us to do better risk management. Risk management and mitigation is a way to enable faster progress with putting less implications on each decision.

The risk we perceive is that once you sign a 7702 message - you create smart contract risk on your EOA. Having that risk limited/bounded, allows you to innovate more freely. There is a big difference between temporary and indefinite risk.

With all of this in mind, the current opinion on the 6 features is:

  1. Should the contract_code signature also sign over the account’s nonce? Yes, flexible nonce with ability to do both “single transaction authorization” and “indefinite revocable authorization” (e.g. maxNonce+bumpNonce or similar solution)
  2. Should the contract_code signature also sign over the CHAINID? Yes, we (as everyone) currently only sign transactions that can run on a single chain with some protection of cross-chain replay attacks. We like that situation. It is a valuable security measure. Given the use case for cross-chain is limited to very very specific use cases and risk to all actions is not great - we like this protection.
  3. Should the contract_code instead be an address? Unopinionated. But as mentioned in #2, should have some cross chain protection if possible.
  4. Should SSTORE inside the “temporarily contract-ified EOAs’’ be prohibited, like it is in EIP-5806? No. But our opinion on this is not strongly held. It seems like a meaningful limitation for a small edge case already solved by 4337 SCWs.
  5. Should we have initcode and not just contract_code? Unopinionated.
  6. Should we just add a flag to NOT set the code back to zero at the end? Thereby making this EIP also supersede EIP-5003? No. Not in Pectra, due to risk of delays and the learning we will get from seeing this EIP in the real world before fully understanding this transition. It’s good preparation for the future.

This feels as striking the right balance between capabilities and protection and hope it will bring back the conversation to the protocol and get it ready for approval for inclusion.

I just want to reiterate that:

  • I think @matt shouldn’t have opened the PR for EIP-7702 that mostly only reflects his personal takes, when most of the takes are still highly controversial as can be seen in this thread. The PR is misleading for the community at large, most of whom haven’t had the time to review this whole thread and might think that “we” (whatever that means) have already made certain decisions when we really haven’t.

  • I don’t believe it’s productive for @yoavw or anyone else to post screenshots or otherwise take this thread to a non-technical direction. There’s a time and place for governance convos but it’s not in this thread.

Again, I feel both @yoavw and @matt have made their points and preferences clear, and at this point it’s most helpful for others to chime in. The next step should be to collect these arguments and discuss them in person in the next ACDE call. How we break the ties after the call if there are further disagreements (which there will likely be), I don’t know, but personally I’d be fine with @vbuterin making the final decisions as the primary author of this EIP.

2 Likes

I’m not sure this is easy to check for? Even if the contract was deployed with CREATE2, it can be made to have arbitrary code. To rule that out you need static analysis of the deployment code, and it seems more difficult than checking for DELEGATECALL opcodes (another way of having arbitrary behavior).

Signing over contract address without also the chain id seems risky.

2 Likes

Which is why you should sign over the code hash instead.

2 Likes

Yet another way to do this could be to sign the code_hash, but specify the code_address in the transaction, so that nodes don’t have to index code by hash.

As I warm up my debate muscles, I was wondering if it be too naive to propose a block and/or time-based revocation mechanism?

Essentially users would specify the max time that the signed contract_code would be valid. This can be in addition to another set of revocation steps but time is always a constant increasing regardless of your account’s executions on-chain. I’m definitely aware that this doesn’t fully de-risk malicious contract code from being used before the time-based revocation triggers, but this at least provides a solution for not fully “bricking” your account after (unintentionally) max-nonce signing malicious contract code.

Also, would like to say that I support the maximal flexible implementation of what gives EOAs super powers, which is the aura of what we’re trying to accomplish here whether it’s 3074 or 7702.

1 Like

I’m all for additional safeguards, but note that a sane implementation of Yoav’s max nonce proposal would guarantee at the protocol level that it is possible for users to revoke the permission they gave for a contract to act on their behalf.

Unfortunately, this is not currently what is being proposed in the open PR. If this reckless, insecure version of 7702 is accepted it means we max out the risk of signing a buggy or malicious contract. That in turn strengthens the argument for whitelisting which contracts users can authorize. This won’t be great for new wallets and innovation.

The non-revocable version of 7702 also maxes out the risk from malware that can mess with the operation of even the most trusted wallets . Those who have opposed revocation at the protocol level argue that wallet interfaces have to be trusted anyway, but currently this is not true. The best practice for EOA security is to use secure signing solutions, so you don’t have to trust the integrity of the entire stack from the operating system to the extension running in your browser. Enabling protocol level revocation preserves some of the security guarantees you can get from secure signing solutions (e.g hardware wallets / wallet connect). Signing over a contract becomes less like giving up your private key forever and more like using another interface.

This reduces the risk from your computer getting hacked and also the risk of experimenting with new wallet interfaces. For extra security, we should consider standardizing how privileges are dropped so that secure signing solutions give user visibility into what risks they’re taking by authorizing a transaction. There’s a difference between signing over unlimited power to drain your wallet and signing over the power to pay your gas, or interact on your behalf with a specific DEX contract.

Sometimes users may still want to give wallet interfaces the power to drain their assets, but even then there seems to be a meaningful difference in the kind of attacks irrevocable, unlimited authorizations enable. With revocable authorizations, rugpulls will only effect current users. With irrevocable authorizations, rugpulls effect current and past users.

Note that an insecure version of 7702 will open up a kind of rugpull that wasn’t possible before: the risk of malware injecting code into a wallet interface to backdoor the EOA, even when the user is using a hardware wallet. This should be taken seriously. With a more secure version of 7702 , security conscious users would be to use their hardware wallets to enforce the principle of least privilege and bump up the nonce every time they start using a new computer or a new wallet interface, so that the previous wallet interface doesn’t stay “logged in” to your EOA. Unfortunately, signing 7702 transactions will almost always expose users to considerable risk. Unless you’re using a hardware wallet and manually verifying the authenticity of the addresses of the contracts you’re signing, the main reason for believing your account is still safe is that is hasn’t been drained - yet.

1 Like