ERC-4337: Account Abstraction via Entry Point Contract specification

Echoing a comment I made over at EIP idea: eth_signUserOperation RPC - #3 by SamWilsn : I’d really like to see a JSON Schema for all the JSON-RPC requests and responses.

What you have now is much too ambiguous for people to implement consistently.

For example, nothing in the eth_sendUserOperation section says that maxFeePerGas is optional. You have to get down to the note in eth_estimateUserOperationGas where it’s only implied:

same as eth_sendUserOperation gas limits (and prices) parameters are optional

The schema of the rpc calls are here

Can we get those in the EIP itself? Would be a huge improvement for visibility.

For IAccount in the ERC, might it be more accommodating to set the visibility of validateUserOp to public rather than external (shorter, no gas difference, more flexible)?

Can’t: its a linter issue:
Functions in interfaces must be declared external.

ah, I see, but was looking at things like EIP-20 which declare the methods public. I think my suggestion on IAccount may have confused my suggestion (which is that implementation might use public and just to clarify). This was something that came up on a recent Solady 4337 PR.

I believe nonce retrieving and validation logic should not be enshrined in the entry point and that logic should be left as in older reasons, here’s some reasons why I think this should be the case:

  1. Different wallets may want to validate nonces differently, enshrining the logic limits this.
  2. The current enshrined nonce scheme prevents wallets from taking advantage of storage packing and other optimization techniques that may decrease the cost of using and updating the nonce by >4.9k.
  3. If nonces are stored with the entry point and wallets rely on this what happens when the entry point is upgraded? Do all past user ops become re-validated again? Will the new entrypoint have to query the old one adding even more gas?

The original version had the nonce entirely in the account. But this has a drawback: a nonce can’t be enforced to be unique for the account. This also meant that userOp hash couldn’t be considered unique.
To support native account abstraction (e.g. EIP-7560), we must enforce the uniqueness at the protocol level, and not leave it to the account - or add another uniqueness mechanism at the protocol level, besides the account-based nonce.
We decided to introduce a protocol-level nonce (at the EntryPoint), but still make it flexible so the account can control how sequential or parallel it is.

In case of entry point upgrade, the nonce count resets back from zero for each key.
The hashes are still unique, since the EntryPoint address (and chain-id) are hashed into the userOpHash

(Note that unlike the sequential nonce of ethereum, which is basically the total transaction count of an account, with 4337 we have a notion of “key”, and the sequence is only within that key, and the account may introduce new keys.
When an entrypoint is upgraded, the counter for each key has to reset)

1 Like

This only seems to explain reasons why one might want to enshrine nonce invalidation into the entrypoint but not why these points are necessarily more critical than the ones I mentioned above?

1 Like

Hi everyone.

In ERC4337, verificationGasLimit on the official EIP page is explained such as:

The amount of gas to allocate for the verification step

On the following page, it’s said to be:

The VGL refers to the maximum gas available for a User Operation to
execute its validation phase. This includes:

Deploying a smart account on the first transaction. Running the
validateUserOp and validatePaymasterUserOp function on the smart
account and paymaster. Running postOp function on the paymaster after
execution.

I thought that verificationGasLimit, whatever is set to, is the total that will be used for all the validation logic + deploying the contract + running paymaster’s pre and post op. Clearly, in the code , that’s not the case. here is why:

  1. deploy contract is run with “verificationGasLimit” - i.e
senderCreator.createSender{gas : opInfo.mUserOp.verificationGasLimit}(initCode);
  1. Then:
try IAccount(sender).validateUserOp{gas : mUserOp.verificationGasLimit}(op, opInfo.userOpHash, missingAccountFunds)
  1. Then:
IPaymaster(paymaster).postOp{gas : mUserOp.verificationGasLimit}(

As one can see, the code doesn’t match the explanation. It should be written as follows: If deploy contract code is run, then only pass “verificationGasLimit - gasUsedByDeploy” to validateUserOp. and so on.
I might be completely missing something though.

  1. Is it mandatory for a paymaster to cover complete gas fee for a UserOperation if it is sponsored?
    From the existing code it need to sponsor gas completely

  2. Is it possible to retrieve the amount of funds (gas) covered by the user’s account and the paymaster for an userOperation during the validateUserOps function?
    The intention is to establish validation logic that relies on these values.

The existing signature for validateUserOps includes missingAccountFunds, but it cannot be utilized for this purpose as it returns a value after accounting for the account deposit. One approach to convey this information could involve encoding (account_share, paymaster_share, missingAccountFunds) within a uint256 variable (renaming the variable is necessary for clarity).

This don’t make sense if paymaster pay the the gas fee completely if userOperation is sponsored.

  1. The above is for v0.6 of the entrypoint. While we do pass verificationGasLimit as gas limit for the call, we later further limit the total verification gas usage (including creation) to verificationGasLimit
  2. With version v0.7, we separated the gas-limits, and now verificationGasLimit covers the creation+validation of the account, and a separate paymasterVerificationGasLimit is used to cover the cost of paymaster verification. Without this separation, paymasters become vulnerable.

There is no “split-gas-payment”: either the account pays (in full) for the transaction gas, or the paymaster.
The “max possible UserOp cost” is calculated based on the absolute maximum cost of the transaction - the maxFeePerGas multiplied by the sum of the validation and execution gas limits.
This amount is deducted from the account’s deposit (or paymaster’s) before the UserOperation, and the excess is returned afterwards.
The “missingFunds” is the minimum value the account has to transfer into the EntryPoint so that its deposit is at least “max possible gas”. If there is enough deposit from a previous UserOp, then it might not need to transfer anything.

1 Like

Hello - I wanted to point out what I think might be an incompatibility between UserOps and EIP-3540 (scheduled for Pectra). The summary is available in that EIP’s discussion, but would appreciate if the experts here could take a look.
Thank you!
reference post: EIP-7069: Revamped CALL instructions - #14 by ryley-o

Question on the definition of validateUserOp:

The spec states that

The userOpHash is a hash over the userOp (except signature), entryPoint and chainId.

and

If the account does not support signature aggregation, it MUST validate the signature is a valid signature of the userOpHash, and SHOULD return SIG_VALIDATION_FAILED (and not revert) on signature mismatch. Any other error MUST revert.

So basically it is defined that validateUserOp must simply run Verify(sig, hash, user), where hash = Hash(userop - sig, entrypoint, chainId).

I’d like to understand better why such strong requirements are made here. In particular, this disallows constructs where the userop has some variable part, that is not available to the user at the time of signing and would only later be provided by a third party.

For example, this disallows transaction flows where the validity of a transaction does depend on an additional signature from a paymaster, but the paymaster signature is not available to the user at the time of it signing the transaction.

Hi! Franck from the Waku team here.

@vbuterin mentioned that Waku could be useful for ERC-4337 in terms of DoS protection. I’d like to provide an overview on how Waku may help with the implementation of this ERC.

Waku Introduction

Waku is a family of protocol designed to enable communication with a focus on privacy, censorship-resistance and resource-restricted devices. Waku’s specs are CC0 and code Apache2.0+MIT. Waku is designed in a modular manner, enabling cherry-picking of the desired protocols and functionalities.

Keys properties are:

Scalable Libp2p setup

Waku uses libp2p protocols and libraries. Waku Relay, the backbone of message routing uses libp2p-gossipsub with specific parameters. Discovery is done via discv5.

Waku aims to serve applications with millions of users. Hence, the Waku protocols are designed to split traffic on several shards (gossipsub topics), while maintaining a single discovery layer efficient in a sharded context.

Generalized & DoS protected

Waku enables generalized communication, where specific validation rules may not be applicable (in contrast to the Ethereum mempool for example, where transaction can be validated). This means that Waku messages can contain any arbitrary payload.

This incur a risk of any actor flooding the network and DoS users who do not have the bandwidth provision to correctly participate to gossipsub.

Waku solves this problem by using RLN (Rate Limited Nullifier) [1] [2]. RLN limits the number of messages a publisher can send over an epoch. Publisher must join a zero-knowledge membership set on chain first. Then, attach a proof linked to a given epoch to their messages. If they exceed the messages rate limit over a given epoch, their messages can be rejected at gossipsub level, eventually leading to disconnection from the network. Slashing is also possible but not currently considered.

Resource-restricted devices

One of Waku’s focus is to enable access to the p2p network to resource restricted devices: mobile, browser, laptop. Instead of using centralized, and hence prone to censorship and surveillance, REST APIs.

This is done with a combination of libp2p request-response protocols that enables a device to:

  • Access specific messages, instead of routing the whole gossipsub topic content. Messages are tagged with a content topic, to enable easy filtering.
  • Publish messages without routing the gossipsub topic traffic
  • Access historical messages thanks to service nodes caching recent traffic
  • Use a libp2p request-response protocol for discovery, instead of using discv5
  • Enable several message reliability strategies, to ensure that messages are indeed sent and received. An important factor when tabs can be closed, network connection switched, devices suspended. Scenarios common for consumer devices, and not servers.

ERC-4337 Review

Below is an attempt to summarize ERC-4337 critical points in terms of network communication needs and requirements, and how Waku may assist in this context.

Network topology and discovery

The following points where extracted from the published EIP [3] and Ethereum magician thread [4].

I am making some assumptions; corrections and feedback are welcome.

Allow any bundler (think: block builder) to participate in the process of including account abstracted user operations.

Work with all activity happening over a public mempool; users do not need to know the direct communication addresses (eg. IP, onion) of any specific actors

Try to support other use cases: Privacy-preserving applications

The alt-mempool “topic” is a unique identifier. By convention, this is the IPFS hash of the document describing (in clear test and YAML file) the specifics of this alt mempool

Alt-mempools are served by the same bundlers participating in the canonical mempool, but change the rules and may introduce denial-of-service attack vectors.

In summary, the intent is to provide permissionless access to a new type of mempool.
A canonical mempool is proposed. However, different validation rules may be necessary, hence a proposal to create alternative mempools as separate gossipsub networks is proposed. Where the pubsub topic of these networks can be derived from the location of the mempool rules (IPFS CID).

There is also a future intent to help support privacy-preserving applications, a point important enough to be present in the EIP.

In Yoav’s notes [5], it is highlighted that a given mempool (gossipsub network) needs to maintain a unique set of validation rules, to avoid network fragmentation. Hence, alternative validation rules, or potential whitelisting of a smart contract, need to happen in a separate mempool/topic.

Alternative mempools are further defined in ERC-7562 [6].

Alt-mempools are served by the same bundlers participating in the canonical mempool, but change the rules and may introduce denial-of-service attack vectors.

In the bundler specs [7], a more precise description of network behaviour is proposed. I assume that a mempool topic refers to a pubsub topic of the underlying libp2p-gossipsub setup. This includes a description of discv5 usage.

In summary, all bundlers participate in the canonical mempool, forming one gossipsub network. If a bundler wishes to participate in the alt mempool, it needs to remain in the canonical mempool. ENRs do not provide any indication of the alt mempools a bundler subscribes to.

Moreover, the same discv5 network is used for Ethereum and the canonical mempool.

I am assuming that the “canonical mempool” refers to a mempool specific for user operations, and is not mixed up with the existing Ethereum mempools used for transaction and block propagation.

This means that a bundler will find nodes via discv5. These may be other nodes that may or may not participate in ERC-4337. Then, by attempting to connect to those nodes using libp2p-gossipsub, it will understand whether said node:

  • participate in ERC-4337 canonical mempool
  • participate in any alternate mempool

Meaning that in someway, libp2p-gossipsub is used as capability discovery. As the number of alt mempool increase, the Needles-In-Haystack problem will likely increase. This would longer delays to find bundlers in a specific alt mempool.

From our earlier studies [8], if 1% of the nodes in the discv5 DHT have the sought capability, then it takes on average more than 14 queries to the distributed hash table to discover a usable node on a random walk.

The official discv5 doc also estimate 1% to be the rough threshold for reasonable lookup performance, as implied by [9].

One also needs to take in account the steps to filter out a node. No ENR extension is proposed for ERC-7562 [6] [7]. Hence, to know whether a node is in the alt mempool of interest, a libp2p-gossipsub connection needs to be established to allow a SUBSCRIBE event to be emitted. Only then, would the searching node learn if this remote peer is part of the desired alt mempool. Drastically increasing the search time.

To solve this problem, Waku extended the ENR object to include shards values [10]. Enabling more efficient filtering of nodes as part of discovery.

Waku discv5 usage [11] also defines a Waku-only routing table which (for now) is smaller than the Ethereum routing table.

Note that by default Waku nodes also support some mechanisms to smoothen discovery: bootstrapping from a configured list or a DNS domain [12]. Investigation to enable parallel discovery methods such as rendezvous to improve speed of finding useful nodes are in progress.

Verification rules

In the canonical mempool, several verification steps are necessary when validating gossipsub messages [6]. Knowing that an alt mempool can define its own validation rules. A differentiation between staked and unstaked entities is made, I assume to reduce the chance of DoS by unstaked entities.

If running validation rules is resource-consuming, whether on the canonical or alt mempool, it may be worth rate limiting the number of UserOperation a given publisher can send. This can help reduce a potential DoS created by hogging node resources in running validation.

Such rate limit could be applied on all mempools, or only on alt mempools with more heavy validation requirements. In this instance, Waku RLN Relay (RLN + gossipsub) [13] can be used to rate limit any entity publish to the mempool, in a decentralized, permissionless and private manner.

End user access

@yoav [5] argues the necessity of a peer-to-peer network for the bundler to collect UserOps:

A single centralized bundler could defend itself by throttling RPC calls that cause problems. It could throttle by IP, API key, or any other common DoS protection.

However, such a bundler would be centralized so it might censor its users, or it might be taken down by network-level DDoS or by legal action

However, the expectation for wallet implementations is unclear. Are they supposed to rely on centralized RPC API, as per the status quo for standard transactions? Is the intent for the portal network [14] or similar light client focused initiative to help wallet publish UserOps long term? (I could not find any reference to this).

Waku defines a number of protocols [15] that could enable any wallet to push UserOps directly to the canonical mempol or alt mempool. These are libp2p protocols that could be implemented by any bundler. Waku Peer Exchange [16] could enable wallets to find bundlers in the right mempool, and push UserOps directly to them. Avoiding introducing centralized entities between users and bundlers.

Conclusion

In conclusion, the added value of Waku over a vanilla usage of libp2p-gossipsub may be useful to achieve the goals originally intended in EIP-4337 [3]. However, my knowledge of the current implementations effort is limited and I may have missed critical points.

I invite implementers to review this proposed value and reach out for further discussion.

References

[1] https://rate-limiting-nullifier.github.io/rln-docs/

[2] https://github.com/vacp2p/rfc-index/blob/main/waku/standards/core/17/rln-relay.md

[3] https://eips.ethereum.org/EIPS/eip-4337

[4] https://ethereum-magicians.org/t/erc-4337-account-abstraction-via-entry-point-contract-specification/7160

[5] https://notes.ethereum.org/@yoav/unified-erc-4337-mempool

[6] https://eips.ethereum.org/EIPS/eip-7562

[7] https://github.com/eth-infinitism/bundler-spec/blob/main/p2p-specs/p2p-interface.md

[8] https://vac.dev/rlog/wakuv2-apd/#random-walk-discovery

[9] https://github.com/ethereum/devp2p/blob/6b0abc3d956a626c28dce1307ee9f546db17b6bd/discv5/discv5-theory.md#ad-placement-and-topic-radius

[10] https://github.com/waku-org/specs/blob/master/standards/core/enr.md

[11] https://github.com/vacp2p/rfc-index/blob/main/waku/standards/core/33/discv5.md

[12] https://github.com/vacp2p/rfc-index/blob/main/waku/standards/core/10/waku2.md

[13] https://github.com/vacp2p/rfc-index/blob/main/waku/standards/core/17/rln-relay.md

[14] https://ethereum.org/en/developers/docs/networking-layer/portal-network/

[15] https://github.com/vacp2p/rfc-index/blob/main/waku/standards/core/64/network.md#non-relay-nodes

[16] https://github.com/waku-org/specs/blob/master/standards/core/peer-exchange.md

@dror mentioned that

paymaster must have balance to pay these values, but eventually pay only for the actual used gas

I believe that the above statement may not be completely true as the paymaster also needs to bear the cost of excess gas penalty implemented in the EntryPoint. With that, Vincent Lu, Elwin Chua and I have figured out a potential attack on Token Paymasters by exploiting the gas penalty in the EntryPoint logic. A malicious bundler can submit a user operation with a high callGasLimit that includes a paymaster. The bundler can earn from the penalty that the paymaster will have to bear.

If you want to know more in detail. you can refer to the notion document below. Hope to hear your thoughts.

lydian-fahrenheit-cc8.notion.site/Potential-Attack-on-Paymaster-69bcac8279764586a4bd941c37541395

1 Like

I suggest offloading parts of this ERC in to a separate standard, namely: user and paymaster validation interfaces.

  • Better encapsulation: Current ERC is too big, referencing another ERC allows to reduce lines of code, ease understanding this standard and allow for smaller iterations
  • Better security: Use of 7746 provisions generic security constraints for middleware hooks, this includes afterCall on user operation validation, which is not included explicitly in current ERC, as well increased security as it specifies to revert within user/paymaster contract
  • Better standardization: Middleware hooks itself are widely needed in the industry. Example for such are Firewall solutions developed by IronBlocks & Forta.