Posted in
Bundler

EIP-7702 simplifies the integration of EOAs into ERC-4337

July 1, 2024
value
read time
EIP-7702 simplifies the integration of EOAs into ERC-4337

A solution to the challenges faced during integration of 3074 into 4337 Infrastructure, for bundlers to trustlessly relay transactions to empower the next generation of EOAs.

EIP-7702 is the latest entry to the long list of EIPs proposed to empower EOAs while the core devs at the Ethereum Foundation work on polishing the long-term vision and implementation of Full Native Account Abstraction. The EIP was announced almost out of nowhere by Vitalik Buterin as an alternative to EIP-3074 and has been steadily gaining widespread community approval over the last few days. While the EIP is yet to be fully cooked, it has been widely accepted as the most promising alternative to EIP-3074, reasons for which we’ll touch upon shortly.

To provide some context of the recent events, EIP-3074 was announced during the first week of April 2024 to be cleared for inclusion in the upcoming Pectra Hardfork. Many AA Community members were unaware of the discussions following up on this and were taken by surprise, prompting rapid discussions around the future of AA on Ethereum and its compatibility (or lack thereof) with ERC-4337-based infrastructure. I would give EIP-3074 the credit for pulling the AA Mafia (formerly 4337 Mafia) community out of deep slumber with discussions rivalling the intensity of pre-4337 days.

Challenges with EIP-3074

Much has already been said about the merits (and demerits) and practical challenges associated with bringing EIP-3074-based enhancements to the masses without inhibiting open innovation and maintaining the trustlessness of the infrastructure. The series of blogs by @rhinestonewtf gives an excellent overview, feel free to read the context.

On a high level,

1. EIP-3074 as a standard is highly generic and does not by itself enforce a separation between validation and execution - something which is essential for bundlers to protect themselves from being griefed by an un-trusted Smart Account implementation.

2. Once an EIP-3074 AUTH is signed, the EOA hands over controls fully to the signed invoker contract. While it’s debatable whether the threat model in this situation is the same as trusting a Smart Account implementation, this forces Wallet providers to maintain a whitelist of trusted invoker addresses, acting as gatekeepers to what can and cannot act as an invoker.

EIP-7702 does not attempt to solve the second problem. As for the first, the authors of EIP-3074 and ERC-4337 recommend a combination of both standards as a way for the existing ERC-4337 Infrastructure to support EOAs powered by EIP-3074 Invokers. An early proposal for the same from Yoav can be found here.

The Need for Trustless Bundling with 4337 for Self Sponsorship

The widely accepted solution to integrate both standards is to build a multi-tenant invoker that conforms to the 4337 Standard for Accounts. The invoker would act as the sender in the UserOperation and do calls on behalf of the EOA via AUTHCALL by taking AUTH during the execution phase.

At first glance, this appears to be a great solution - EOAs can benefit from all the batching and sponsorship infrastructure built around 4337. This setup works well for operations sponsored by entities other than authorizing EOA, however, we run into a few challenges when trying to implement the self-sponsored flows.

Before addressing those challenges - let’s take a moment to think about why dependence on an external relaying infrastructure is even needed in the first place. After all, if the EOA wishes to sponsor its transaction, it can simply sign its transaction as the origin and call the invoker directly to execute its transaction.

While this works for the most basic case of self-sponsorship, we miss a few quality-of-life features:

1. Every transaction will require two signatures from the EOA - one to sign the AUTH to authorize the invoker and the other to sign the transaction. While AUTH could be re-usable in certain cases depending upon the invoker design, the onus of replay protection is shifted to the invoker/dapp.

2. The user will need to manage their transaction themselves when a relayer/bundler can automatically bump up the transaction gas fee (up to a specific limit) if the transaction takes too long to confirm.

3. The EOA cannot pay for the transaction in an ERC20 token in this setup.

I hope this establishes the need for a relaying infrastructure in the self-sponsorship case, if the infra is to remain permissionless it must follow a standard that enforces a separation between validation and execution, similar to ERC4337.

Challenges with ERC-4337 Integration in the Self-Sponsorship Case

We spent some time working on potential designs for the integration, and the following are some of our learnings from this process.

The ERC-4337 Entrypoint on a high level works as follows:

  1. Perform the validation phase. For each User Operation:
    1. Ask the Smart Account if it’s willing to pay the fee. If it is, accept payment for the missing funds from the Smart Account.
    2. If a paymaster has been specified, deduct the fee from the paymaster deposit and ask if it’s willing to pay for the UserOperation.
  2. Perform the execution phase. For each User Operation, execute the call data on the Smart Account.

Additionally, before sending the UserOperation(s) on-chain to the Entrypoint, the bundler simulates the validation phase of each UserOperation to ensure that it’s deterministic and can only depend upon the Smart Account state and other states that are associated with it, as defined in ERC-7562. If an unsafe operation is detected, the UserOperation is rejected due to it being prone to invalidation outside the control of the Smart Account or Bundler.

Let’s assume the EOA wishes to pay for its UserOperation in native tokens. We build a UserOperation with the Multi-Tenant Invoker as sender, and a signature granting AUTH to the invoker for the duration of the UserOperation. Other fields of the UserOperation are populated as usual.

During validation, the Multi-Tenant Invoker is expected to do two things:

  1. Verify that the UserOperation is signed by the controlling address which in this case is the EOA.
  2. Pay for the UserOperation using funds from the EOA’s native balance.

No problem - one might say that all the invoker needs to do is to take AUTH to verify that the signature is correct, AUTHCALL to transfer funds from the EOA to the Entrypoint.

Except that AUTH and AUTHCALL are unsafe to call during validation 😭.

  1. AUTH requires accessing the EOA’s nonce and there’s no clear 1-1 associativity between the EOA and its invoker (since it’s multi-tenant) and can therefore be used to invalidate multiple UserOps sharing a single authorizer to be invalidated by incrementing the authrozier’s nonce.
  2. AUTHCALL is unsafe because it presents the same challenges as accessing an EOA’s balance and the BALANCE opcode is banned by ERC-7562 during validation.

This is the crux of the problem that leads to complicated design choices and forces tradeoffs resulting in a subpar experience for at least one of the entities depending on the tradeoffs taken.

So how do we solve this problem?

1. One option is to have a paymaster front the cost of the UserOp during validation from its deposit, and (possibly attempt to) recover the cost from the EOA during postOp. If the recovery is successful, the paymaster’s deposit is restored and can be used for other UserOperations.

2. Another is to build a Multi-Tenant Deposit Paymaster to which EOAs can deposit a small amount of Native Tokens (enough to sponsor 1 transaction). The paymaster uses the user’s deposit to pay for the UserOperation during validation, and attempts to recover and replenish the deposit during postOp. Note that this logic cannot live inside the invoker due to it not receiving information about the actual gas used from the Entrypoint post-execution.

Note that it’s relatively safe for the bundler to allow AUTH and AUTHCALL during postOp. Any reverts during postOp while still causing the bundle to revert, will cause the staked paymaster to be banned, acting as a protection mechanism for the bundler against mass invalidations. These two solutions effectively shift the risk from the bundler to the paymaster, which must now ensure that postOp doesn’t revert or else risk itself getting banned.

So what are the tradeoffs with each solution?

(1) Shared Deposit Paymaster with Refund during postOp

The general flow would be as follows

1. A paymaster is deployed with a minimal deposit to the EP (say 20$ on Arbitrum).

2. During validation, the Paymaster pays for the op with its deposit.

3. During postOp, the paymaster asks the invoker to reimburse it from the EOA’s funds.

Challenges

1. If the user does not have enough funds left after execution, postOp will revert and the bundlers will blacklist this paymaster. The paymaster here has two options

  • Bubble up the revert and cause the bundle to revert. This will prevent the paymaster from losing its deposit but will lose its reputation and be banned by the bundler network.
  • Do not bubble up the revert and take a loss.

2. Both situations can be exploited to cause a service disruption by either causing the paymaster to be banned or losing its deposit in the Entrypoint.

3. One possible method to counter this is to have an off-chain paymasterService perform detailed simulations on the UserOperation to determine whether enough funds will remain to reimburse the paymaster during postOp. Note that it is theoretically impossible to prevent 100% of these cases (since this is equivalent to predicting execution which is impossible 100% of the time), but the probability can be brought down significantly depending on the amount of effort we wish to put in the simulation.

(2) Per-User Deposit Paymaster with Auto-Topup during postOp

Sample Implementation

The general flow is as follows:

1. Require each EOA to create a one-time deposit in the paymaster with an amount sufficient to sponsor a single-user operation (say 1$ on Arbtirum). This is done via a non-4337 flow BUT is a one-time operation.

2. EOA references the paymaster while creating a UserOperation, and signs an AUTH over the UserOp.

3. During validation, the paymaster pays for the UserOperation from the user’s deposit. If a deposit is insufficient, reject the UserOperation.

4. During postOp, the paymaster instructs the invoker to reimburse the min(actualGasCost, balance(EOA)) from the EOA’s native balance and restore the EOA’s deposit for subsequent UserOp execution. Note that this would require the earlier signed AUTH to be reused for this operation, for which we’ll have to implement some form of a permissions system.

5. Even if the funds are not recovered during postOp, do not revert the bundle. Instead, do not replenish the User’s deposit which they’ll have to top up again.

6. Steps 2-4 can be repeated for subsequent UserOperations as long as sufficient deposit is maintained in the paymaster.

The benefit of this approach is that it can run without an external paymaster service since there’s no risk to the paymaster. However, the obvious downside is that the User needs to separately deposit funds into the paymaster (even if only once) which degrades the onboarding UX.

Hopefully, this is convincing of the non-straightforward nature of the integration, but please reach out to me if you have a better solution.

EIP-7702 to the rescue

EIP-7702 is the new EIP in town written by Vitalik Buterin and co-authored by 3074 authors that aims to give SmartAccount like functionality to EOA accounts for the duration of the transaction. In simple terms, while the transaction is being executed, the EOA has SmartAccount code at the same address and after execution, it becomes an EOA again with no code.

This is done by introducing a new transaction type. It adds an array of tuples, each consisting of:

1. contract_code Code deployed at signing address (can be different than tx.origin) before transaction execution begins and is removed after execution is finished.

2. signature Signature provided by EOA address where contract_code is to be deployed temporarily.

Since the EOA’s address now has code deployed at the same address, the Smart Account implementation is free to manipulate funds in the EOA during the validation phase, removing the need for complicated paymaster flow to the front fee for the user in the self-sponsored case. This will result in a much cleaner integration.

Even though both EIPs’ main goal is to give SmartAccount functionality to EOA accounts, both take different approaches.

Why new transaction type is better than new opcodes?

Post EOA to SA migration, these opcodes introduced by EIP-3074 will be of no use and will remain in the EVM codebase as stale opcodes hence creating technical debt for the future.

The new transaction type does not impact the EVM code, as the transaction is generated off-chain and it does not depend on the smart contract code.

If tomorrow these transaction types are not supported then the only change needed to remove them will be off-chain changes while removing opcodes will require on-chain changes which is a very hard thing to do as seen in the past when the SELFDESTRUCT code was removed.

Compatibility with AA Roadmap

EIP-7702 is forward compatible with the AA roadmap as it fits really well with existing 4337 infra without reinventing the wheel or finding hacky ways to reuse it.

Full Account Abstraction features

EIP-3074 only implements execution abstraction which is just one part of Account Abstraction. You can read more about this in this article by Yoav. On the other hand, EIP-7702 can be used to easily implement all features of Account Abstraction as you can directly use the SmartAccount code with EOA addresses.

Compatible with 4337 Infra

It’s also worth mentioning that the sender in UserOp can return to being the actual account (ie. the EOA) instead of a multi-tenant invoker, removing the need for a lot of hacks done to work around UserOps from different EOAs having the same sender (such as EOA addresses being a part of the 2D nonce of the Op). The EntryPoint wasn’t built with this assumption and it’s better if we don’t have to work around it.

Codebase fragmentation

3074 creates a new development of the “invoker contract” ecosystem that is separate from the “Smart Account” ecosystem, leading to possible fragmentation of effort. While 7702 uses the same SmartAccount code (with slight changes related to SA storage). In 7702, smart account code can’t write to its own storage, so all persistent storage needs to stay in external storage contracts.

Forward compatible with Account Migration

While 3074 doesn’t talk about permanent migration of EOA to SA and it requires new EIPs focussing on account migration, EIP-7702 may add the capability to permanently convert EOA to SA. It just needs to disable the contract-code removal at the end of transaction execution. Since the spec is not yet finalised, discussions around how to enable these features via flags are being considered.

Unsolved issues with EIP-7702

Revocations

Both EIPs allow users to give control of their EOA account to smart contract code and it needs to be trusted. So we also need to ensure that if a user signs a malicious code, there is a way for the user to revert the delegation without trusting any smart contract code. That’s why in-protocol revocation is important. A simple way to enable this is to use EOA nonce as a part of the signature provided by the user, but then we can’t have long-standing signatures as any transaction done directly by EOA can invalidate the last signature. That’s why this nonce has to be different than EOA nonce.

There are different suggestions like maxNonce, nonceManager but the final adopted solution is yet to be seen. But we think the revocation should be in-protocol to always have a way to allow users to revoke delegations without trusting the smart contract implementation.

Storage Access

Whether to allow storage modification for EOA accounts during transaction execution is still being debated. Since EIP-7702 is inspired by EIP-5806 where usage of SSTORE opcode is prohibited, the same restrictions should also be applied to EIP-7702 because allowing storage changes may lead to problems of the EOA state being corrupted by malicious contracts which may lead to unwanted behaviour and later user would need to interact with other contracts to clear the storage which is not a nice UX.

Chain Agnostic Signatures

Adding chainId to the signature has been debated a lot in EIP-3074 and it ended up being included there. It might not be required in EIP-7702 as the user is signing a contract code and not a contract address which might be deployed on other chains at the same address but with a different bytecode. If anyone wants to implement chain-specific signatures, they can always make it a part of the contract code. Chain agnostic signature also allows you to reuse the signature on multiple chains to delegate the same code without worrying about different implementations on multiple chains.

Closing Thoughts

It’s clear that EIP-3074 intentions were right but major problems with it was future incompatibility with the AA roadmap and lack of validation and execution separation. EIP-7702 solves the same problems as EIP-3074 but without the above weaknesses.

The concerns around trusting the bytecode and requirements for whitelisting remain valid with EIP-7702, and it will be interesting to see how the community tackles them. At Biconomy, we’re committed to improving the UX of using DApps and are thrilled to onboard EOAs to the world of Smart Accounts and commit to fully supporting them with our infrastructure once EIP7702 is finalized and goes live.

--------------------------------------

This piece was authored by Sachin Tomar & Ankur Dubey

Subscribe to the Biconomy Academy

Building a decentralised ecosystem is a grind. That’s why education is a core part of our ethos. Benefit from our research and accelerate your time to market.

You're in! Thank you for subscribing to Biconomy.
Oops! Something went wrong while submitting the form.
By subscribing you agree to with our Privacy Policy
Copied link

Heading

This is some text inside of a div block.
value
read time

What’s a Rich Text element?

What’s a Rich Text element?

The rich text element allows you to create and format headings, paragraphs, blockquotes, images, and video all in one place instead of having to add and format them individually. Just double-click and easily create content.

The rich text element allows you to create and format headings, paragraphs, blockquotes, images, and video all in one place instead of having to add and format them individually. Just double-click and easily create content.

Static and dynamic content editing

Static and dynamic content editing

A rich text element can be used with static or dynamic content. For static content, just drop it into any page and begin editing. For dynamic content, add a rich text field to any collection and then connect a rich text element to that field in the settings panel. Voila!

A rich text element can be used with static or dynamic content. For static content, just drop it into any page and begin editing. For dynamic content, add a rich text field to any collection and then connect a rich text element to that field in the settings panel. Voila!

How to customize formatting for each rich text

How to customize formatting for each rich text

Headings, paragraphs, blockquotes, figures, images, and figure captions can all be styled after a class is added to the rich text element using the "When inside of" nested selector system.

Headings, paragraphs, blockquotes, figures, images, and figure captions can all be styled after a class is added to the rich text element using the "When inside of" nested selector system.
Subscribe to the Biconomy Academy

Building a decentralised ecosystem is a grind. That’s why education is a core part of our ethos. Benefit from our research and accelerate your time to market.

You're in! Thank you for subscribing to Biconomy.
Oops! Something went wrong while submitting the form.
By subscribing you agree to with our Privacy Policy
Read next
Copied link