Title: ERC_4337__Account_Abstraction_via_Entry_Point_Cont
Category: ERCs

Author: vbuterin
Date: 2021-09-29T08:59:03.146Z

An account abstraction proposal which completely avoids the need for consensus-layer protocol changes, instead relying on a separate mempool of UserOperation objects and miners running either custom code or a bundle marketplace.


github.com/ethereum/EIPs








ERC: Account Abstraction via Entry Point Contract specification


master ← vbuterin-patch-1



          opened 08:57AM - 29 Sep 21 UTC




            vbuterin
          



+331
-0






An account abstraction proposal which completely avoids the need for consensus-l…ayer protocol changes, instead relying on a separate mempool of `UserOperation` objects and miners either running custom code or connecting to a bundle marketplace.

Author: Agusx1211
Date: 2021-09-29T15:13:08.178Z

The proposal looks awesome! We worked on a very similar set of contracts under the name of “Sequence”, in short is pretty much the same system, with the key difference that handleOp and verifyUserOp are bundled together on the same execute function. The relayer has to simulate this execute function with a fixed amount of gas and see if it’s going to get paid or not before sending the transaction.
The contracts are here: https://github.com/0xsequence/wallet-contracts
The cool thing is that our system could be upgraded to support this new standard, after all wallets are upgradable, and we could split our execute function into verifyUserOp and handleOp.
The only roadblock I see is that we already have our own “Wallet factory”, it uses CREATE2 in pretty much the exact same way ERC4337 does (https://github.com/0xsequence/wallet-contracts/blob/master/src/contracts/Factory.sol) and wallets are indeed counter-factual, but afaik ERC4337 wallets must be created using the EntryPoint contract as factory. Thus our wallet addresses couldn’t benefit from the initCode property on the relayer network, because the resulting addresses would be different.
I wonder if this is an implementation detail or something by design, because by allowing contracts as wallet factories we could allow existing smart contract wallet implementations to be retrofitted without having to re-deploy all counter-factual accounts. I imagine this issue affects not only Sequence but also Gnosis, Argent, etc.
A possible solution could be to split initCode into two fields: initCode and initAddress, the creation of the wallet involves calling initAddress with initCode as data, after that EntryPoint could validate if the account address now contains code.
The trusts assumptions are the more or less the same, and any restrictions put on initCode (call external contracts, use timestamp, etc) could also be applied to initAddress.

Author: vbuterin
Date: 2021-09-29T20:41:33.854Z

Agusx1211:

ERC4337 wallets must be created using the EntryPoint contract as factory


I don’t think this is technically true; you can use ERC 4337 with wallets created in other ways, you just would not be able to create the wallet without a paymaster.

A possible solution could be to split initCode into two fields: initCode and initAddress, the creation of the wallet involves calling initAddress with initCode as data, after that EntryPoint could validate if the account address now contains code.

Interesting! Need to think about whether or not it’s safe to call into arbitrary addresses as contract creators… or if it’s a useful idea. Perhaps instead we should just agree on a chain-wide generic factory contract that everything gets created through (this would have other use cases, eg. if users using account-abstracted wallets want to create new contracts, they could do it through the factory instead of the wallet supporting a separate creation mechanism).

Author: JamesZaki
Date: 2021-09-30T00:01:55.739Z

Great write-up 
FYI, another implementation in progress (with a previous version tested on Optimism and Arbitrum testnets) can be found here, it’s focus is on using BLS signature aggregation.
“EntryPoint” is VerificationGateway (cleanup in progress), the wallet contract is BLSWallet, and “Bundler” is bls-wallet-aggregator repo.
Which will go beyond just contract wallets, introducing significant savings on L1 by reducing L2 calldata (1 instead of n BLS sigs in a “bundle”).

Perhaps instead we should just agree on a chain-wide generic factory contract that everything gets created through

This is the current design for VerificationGateway, but the indirection through aggregators and user bls keys I think rules out deterministic wallet addresses.

Author: vbuterin
Date: 2021-09-30T04:34:06.763Z

Happy to hear there’s work being done on this! Does your BLS wallet aggregate transactions across operations? That’s a feature that, while not especially useful for regular wallets because calldata costs are not that high relative to ECPAIRING costs, is a lifesaver for optimistic rollups. Would be interesting to see how it could be incorporated into the same standard.

Author: JamesZaki
Date: 2021-09-30T05:10:58.232Z

Happy to hear there’s work being done on this!

Thanks EF 

across operations

I have a card in the github project: “Consider design of single signature for multiple txs (eg exchanges frequent need of approve then transfer)”, if that is what you mean?
Currently an aggregator (server) would put together bls-signed tx data for an arbitrary set of txs (from any blswallet) that fit in an L2 tx, they could be txs from the same address with consecutive nonces, each individually signed-for though (before aggregation).

Author: vbuterin
Date: 2021-09-30T05:41:16.679Z

The bundler should be able to take all the BLS signatures in the user operations, and combine them together into a single BLS aggregate signature that goes on chain. When verifying the ops, the contract would extract the entire list of (pubkey, msghash) pairs that wallet verification execution expects, and check the aggregate signature against that whole list.
Is that what you have in mind?

Author: JamesZaki
Date: 2021-09-30T05:43:42.505Z

Yes, that’s what it does → bls-wallet-contracts/VerificationGateway.sol at main · jzaki/bls-wallet-contracts · GitHub
EDIT: bundling here

Author: rmeissner
Date: 2021-09-30T07:37:55.875Z

This sounds very similar to https://docs.opengsn.org/ Did you look into this and where there are parallels and differences? Also something like this has been attempted in the past with EIP-1077: Gas relay for contract calls. I would love to see what is different from then to now.
I also think that pushing EIP-2937: SET_INDESTRUCTIBLE opcode with that would be super helpful as it would enable more wallet to comply to this. For example the current Gnosis Safe setup would not be usable with the current proposal as it supports delegatecalls.
I would also be interested in what relation the Bundlers stand to the Miners/Validators. It sounds like these would be a complete different service. Or would you expect this to be part of a default Miner/Validator setup.

Author: vbuterin
Date: 2021-10-03T12:10:50.564Z

I would also be interested in what relation the Bundlers stand to the Miners/Validators. It sounds like these would be a complete different service. Or would you expect this to be part of a default Miner/Validator setup.

Bundlers would either be miners/validators, or they would be actors publishing bundle txs through Flashbots.

Author: StanislavBreadless
Date: 2022-02-02T08:43:54.209Z

Excuse me if I misunderstood something, but I could not find how the preVerificationGas field is handled. Or is it the responsibility of the account abstraction account to handle and use these fields correctly?
Especially what’s interesting is at what step the preVerificationGas is paid.

Author: dror
Date: 2022-02-02T19:06:01.938Z

preVerificationGas covers all the gas that can’t be checked on-chain using gasleft() deltas, but is known to be paid by both the calling user and the miner.
It covers static gas cost (e.g 21000 stipend, and little more used by handleOps other), and dynamic cost which depends on actual UserOp structure (e.g calldata cost, and memory usage/copy into the inner methods of handleOps.

Author: StanislavBreadless
Date: 2022-02-03T09:16:48.109Z

But how is it charged from the user?
Do I get it right that it is the responsibility of the user account to pay for it? The same as for the actual fee? In the specification, preVerificationGas is a part of UserOperation.
That means that there is no way to enforce that the miner (or the one who submits this bundle of UserOperations) will get paid.

Author: dror
Date: 2022-02-05T11:31:06.961Z

To summarize the complete transaction payment:

The EntryPoint calculate the total cost of the UserOp, and charges the wallet (or paymaster) for that and transfer that amount to the bundler/miner.
the payment is split into 2 parts: those we can calculate on-chain (using gasleft() wrappers), and those we can’t.
the paymaster calculates the cost of verification, target call gas (and postOp, in case a paymaster is used to pay instead of the wallet itself.)
to this value it adds the preVerificationGas, which should be set to the excess (calldata cost, and some static cost we can’t calculate on-chain)
The preVerificationGas is calculated by the user who creates and signs the request.
The bundler/miner - verifies this value before putting it on-chain, to make sure it makes profit on this transaction.

Notes:

The UserOp contains 2 other gas values, the verificationGas and callGas. The user/paymaster must have balance to pay these values, but eventually pay only for the actual used gas. The preVerificationGas is paid in full.

preVerificationGas name is misleading a little: most of its value indeed comes before the verification, but it covers also some static overhead that comes later.

Author: jacekv
Date: 2022-02-09T05:56:33.719Z

The ERC looks pretty good, yet I was wondering about adding a chainId field into the UserOperation.
Since transactions have it (EIP-155) to prevent replay attacks, I believe the same attack vector comes in play in regards the UserOperations. Or am I wrong?

Author: yoavw
Date: 2022-02-09T11:39:19.625Z

Thanks, you are right, and the implementation actually covers chainId as part of the signature.  The UserOperation struct doesn’t include a chain ID field, but it is appended before signing/verifying.  The EIP should reflect that as well.

Author: jacekv
Date: 2022-02-09T14:54:51.602Z

@yoavw Thanks for linking it to the contract. I am not sure how this is going to prevent replay attacks. The chainId is taken from the block and hashed with the UserOperation. As an attacker, I still could take the UserOperation and use it on a different chain, or not?
Is there something I am overlooking?

Author: yoavw
Date: 2022-02-09T15:35:31.976Z

The user signed userOp.hash(), address(this), block.chainid and taht’s what the wallet will verify. This signature is a part of the the UserOperation.  If someone relays the same UserOperation on another chain with a different chainid, the wallet will revert during its validateUserOp because the signature won’t match  the requestId it receives from EntryPoint.
Do you see a way to bypass that, and successfully replay the UserOperation on a chain with a different chainId?

Author: jacekv
Date: 2022-02-09T16:02:12.916Z

Alright, I get the flow know and was able to follow the steps in the code  Thanks for the explanation @yoavw

Author: tjade273
Date: 2022-03-22T19:07:11.164Z

Note that balance cannot be read in any case because of the forbidden opcode restriction. Writing balance (via value-bearing calls) to any address is not restricted.

Doesn’t allowing value-bearing called essentially allow reading the balance of an account?
For example, if the wallet includes this in validateUserOp
bool success = this.send(500);

success will contain 1 iff the contract contains at least 500 wei. If we want the exact balance, we can just binary search.
Also, what happens if the wallet has all funds removed between simulation time and run time? Is the idea that this shouldn’t be possible because the handleOps call will always be the first transaction in a block?.

Author: yoavw
Date: 2022-03-23T02:20:31.435Z

tjade273:

Doesn’t allowing value-bearing called essentially allow reading the balance of an account?


Yes, the wallet could check its own balance this way, much like it could check its own storage. The user would be able to invalidate an op that is already in the mempool by using a non-op transaction to change the wallet’s balance.
However, the wallet can only check its own value this way, so it can only be used to invalidate the op of a single wallet at a time.  The wallet could similarly use a separate transaction to update its nonce and invalidate the op.
Your question does highlight an important point - that the client should treat the value as part of the account state, and not just the storage.  I.e. if a wallet calls a function in a 3rd party contract, which doesn’t access storage but does attempt to send value, the clients shouldn’t accept it.  Otherwise this could be used to invalidate ops of multiple wallets.
The EIP specifies this condition: The first call does not access mutable state of any contract except the wallet itself and its deposit in the entry point contract.
I now edited it to clarify that mutable state includes both value and storage. Thanks for bringing it up.



 tjade273:

Also, what happens if the wallet has all funds removed between simulation time and run time? Is the idea that this shouldn’t be possible because the handleOps call will always be the first transaction in a block?.


The simulation is performed against the latest state while building the block. It is the block proposer’s responsibility to ensure that an earlier transaction in the block doesn’t invalidate an op.  The simplest way to do it is what you suggested - make the handleOps call in the first transaction in the block.  A client could simulate it against a mid-block state or use access lists to prevent conflicts, but making it first is easier.  The current client implementations already do this, but I now added a comment to the EIP to make this requirement clearer.
Thanks for highlighting these points!  Client developers need to take them into account.

Author: yoavw
Date: 2022-03-24T00:17:15.020Z

@tjade273 thinking some more about value-bearing calls, I realized that our current protection (dropping validations that change any account balance except the wallet and the entry point) is not good enough.  The value-bearing call you suggested could be a self-call by some 3rd party account, so there’s no balance change.  So the current protection won’t stop this DoS:

Wallets call EvilContract.func() during validation.
EvilContract.func() attempts to call its own receive function with 1 wei, reverting if it fails. When it has 1 wei it is not caught by the current protection because the balance remains 1 wei.
Attacker sends ops from 1000 wallets with this validation function while EvilContract has 1 wei. Validations succeed and the ops are accepted to the mempool.
Attacker tells EvilContract to send the 1 wei elsewhere.
All ops fail validation in the 2nd simulation.

We’ll update the EIP to also ban value-bearing calls during validation, except from the wallet to the entry point.
Thanks again for your valuable comments.

Author: tjade273
Date: 2022-03-24T01:36:03.846Z

@yoavw yes, this is essentially the attack I had in mind. I assumed that executing a value-bearing call in some sense triggered the

does not access mutable state of any contract except the wallet itself

in your last post but yes it bears being specific that this applies also to implicit reads via value-bearing calls.
Another interesting corner case I’ve been thinking about is:
Wallet calls C1, passing it say 500 gas. C1 attempts to call C2 (which just returns immediately). Since gas cost for first accesses is metered at a higher rate, the call to C1 succeeds exactly when C2 has been accessed before. So in simulation if the calls are simulated separately as they arrive at the mempool, they will behave differently from when they are all run together.
It seems like this can be used to form a large scale DoS, unless all the userOps are simulated together in a batch (is this the case?).

Author: yoavw
Date: 2022-03-24T02:02:46.887Z

The ops are also simulated together as eth_estimateGas of the entire handleOps transaction, but we do try to avoid cases where this simulation fails, because it creates more work.  If it does fail, the simulation returns the index of the op in the bundle as an arg of the FailedOp error, and the bundler removes this op.
The method you described would indeed pass the single-op simulation and then fail the eth_estimateGas, which will cause it to revert with a FailedOp and specify that op and retry.
It’s not as effective as the previous attack (value-bearing self calls) since it only invalidates ops in the current bundle rather than the entire mempool, and the attacker ends up paying for the first op in every bundle because this one is valid and not removed.  But it is still a nuisance to the bundler which has to eth_estimateGas multiple times and only gets paid for one valid op.
I wonder if we should mitigate.  We could require all calls during validation to provide max gas, which would prevent this vector and hopefully shouldn’t break any valid use case.  On the other hand, the attack doesn’t scale well for the attacker because it only causes some off-chain work while paying on-chain costs in each bundle.  What do you think?

Author: tjade273
Date: 2022-03-24T02:19:51.403Z

The attacker may be able to get away with less than 1 successful op per batch if they test for previous accesses to an account that is likely to be called regardless of the attacker’s userVerify activity.
For example, a common paymaster that is likely to be used early in the batch, or even the externally owned account of the bundler themselves.
I’m trying to reason through the expected burden on a bundler due to this: is there any rate-limiting we can do to prevent users from filling up the mempool with a huge number of these invalid userOps? If the attacker sends 100k requests with the same wallet but different nonces, do these all get added to the mempool and crowd out real transactions? If so, maybe some sort of wallet blacklisting is warranted.

Author: yoavw
Date: 2022-03-24T02:31:50.176Z

No, each wallet can only have one op in mempool at a time. The attacker needs to use 100k contract wallets in order to send 100k concurrent ops.
But… it may be possible to implement your attack without actually paying for these deployments.  When a new wallet is deployed via EntryPoint, its validation is immediately called and the deployment is reverted if validation fails.  You could craft a wallet that almost always reverts its own deployment op, costing the attacker nothing.
So you convinced me, we should add a max-gas rule during validation.  We already require the use of fixed gas since we ban the GAS opcode, so we might as well require it to be max.
Thanks & keep them coming!

Author: tjade273
Date: 2022-03-24T04:02:45.167Z

I think even with the max gas limitation there’s a similar issue.
The attacker just needs to calculate and set the verificationGas such that C1 runs out of gas only when address C2 is not primed. Then if the call to C1 fails, pay the EntryPoint and if it succeeds, revert. There should be enough gas left over for this due to the 63/64ths rule (we can make the leftover gas as large as necessary by burning a bunch in C1).

Author: tjade273
Date: 2022-03-24T04:10:55.247Z

One potential mitigation is to simulate the operation, then resimulate it with all of the called addresses primed, and make sure the contract pays in both cases.
Alternatively you could disallow all reverted calls, or just OOG calls, in the stack. This should work since the “real life” calls will always take at most as much gas as the simulated calls, so if no calls run out of gas in the simulation then they shouldn’t in “real life” either.

Author: yoavw
Date: 2022-03-24T16:05:16.451Z

tjade273:

There should be enough gas left over for this due to the 63/64ths rule


I’m not sure the 63/64 rule leaves enough gas to do anything in this case, since nodes won’t accept a high verificationGas op due to the risk of unpaid work. But you’re right, there’s a risk that this could be exploited, and the max gas change doesn’t mitigate it.



 tjade273:

resimulate it with all of the called addresses primed


That won’t solve the problem either, because the contract could use a combination, expecting some addresses to be primed and others not.  E.g. succeed if no addresses are primed or all addresses are primed, but fail if 2 are and 3 aren’t.



 tjade273:

you could disallow all reverted calls, or just OOG calls, in the stack.


I think this is the way to go.  The client should drop the op if there’s an OOG revert in any context.  Thanks for suggesting that.

Author: poojaranjan
Date: 2022-03-28T17:26:54.881Z

PEEPanEIP-4337: Account Abstraction via Entry Point Contract specs. with @yoavw @kristofgazso

Author: tfalencar
Date: 2022-04-27T19:04:35.968Z

Reference to another great presentation about this proposal:





Slides: ETHAmsterdam ERC 4337 - Google Presentaties
Main links from the slides:
Contract code: account-abstraction/contracts at main · eth-infinitism/account-abstraction · GitHub
Audit blog post: EIP-4337 - Ethereum Account Abstraction Audit - OpenZeppelin blog

Author: StanislavBreadless
Date: 2022-07-06T08:34:53.221Z

Do I get it right from the implementation here that:

The user is required to have a prefund of callGas + verificationGas + preVerificationGas. Link. (Let’s discuss only the case when without the paymaster).
At the same time, verification is allowed to consume the entire verification gas. Link.
Also, the execution is allowed to consume the entire callGas. Link.
The preVerificationGas is always paid entirely as it takes into account gas needed for posting calldata etc. Link.

These parameters do not take into account additional overhead for creating auxiliary variables on the stack, etc. The preGas variables carry this overhead and is taken into account when paying fees for the beneficiary.
It seems like it is possible that the user’s operation consumes the entire verificationGas and executionGas, and so the user does not pay for the overhead mentioned above (e.g. these operations are done at the expense of the EntryPoint contract).
The code is taken from the OpenZeppelin’s report.

Author: dror
Date: 2022-07-08T01:25:25.771Z

StanislavBreadless:

These parameters do not take into account additional overhead for creating auxiliary variables on the stack, etc. The preGas variables carry this overhead and is taken into account when paying fees for the beneficiary.


The preVerificationGas is supposed to cover this (yes, its name is a bit misleading)
We assume that all the variable costs are calculated using the “gas diffs” and that the overheads you describe are constants, and thus can be calculated by the bundler, to verify the preVerificationGas pays for them.

Author: StanislavBreadless
Date: 2022-07-08T08:53:52.660Z

Thank you @dror for your response. Could you please help me with what step of reasoning am I wrong here (let’s assume that the tx was successful and there is no paymaster):


Here we create UserOpInfo with preOpGas being equal to op.preVerificationGas + preGas - gasleft(). Let’s call say that preGas - gasleft() = op.verificationGas + k , where k is some constant. That means that preOpGas = op.preVerificationGas + op.verificationGas + k.

Here when actually execute the tx, the actual cost is returned. The preOpGas is added to it, and so, in the worst case, the returned actual gas is equal to at least op.callGas + preOpGas = op.callGas + op.preVerificationGas + op.verificationGas + k.

The refund that the user was required to have at the start of the transaction is op.callGas + op.preVerificationGas + op.verificationGas, but the actual gas spent was op.callGas + op.preVerificationGas + op.verificationGas + k. The question is, who pays for k? From here we subtract the actualGasCost from prefund, so if the prefund is smaller than the actual gas cost, then the transaction will revert.
Indeed, the EntryPoint will not lose any money, but the operator should always remember that the operation is never guaranteed to succeed unless the verification step took so little amount of gas that the difference is enough to compensate for the k

Author: blmalone
Date: 2022-08-03T19:26:53.378Z

The EIP states that:
To prevent replay attacks (both cross-chain and multiple EntryPoint implementations), the signature should depend on chainid and the EntryPoint address.

This makes sense given EIP-155.
Just so it’s clear for me, the reason the EIP doesn’t define how this signature is calculated over the data is because any signing and hashing algorithm (within reason) can be used?
For example, to calculate the hash of a message before creating a signature in Ethereum it is common to do the following:
Keccak256("\x19Ethereum Signed Message:\n32" + Keccak256(message))

So is the reason this ERC isn’t prescriptive like the example above due to the flexibility it offers with respect to crypto algorithms?
Therein, the validateUserOp on the wallet contract must make sure that it’s accounting for the chainId and the EntryPoint (as well as the UserOperation) when checking the signatures validity.

Author: TimDaub
Date: 2022-08-04T08:29:30.394Z

Minor comment: I think a more descriptive term for “paymaster” can be “sponsor”.

Author: dror
Date: 2022-08-22T19:51:10.563Z

blmalone:

So is the reason this ERC isn’t prescriptive like the example above due to the flexibility it offers with respect to crypto algorithms?


Exactly. The wallet is the flexibility (and responsibility) to use whatever signature scheme.
The “SampleWallet” we provide use this EIP191 “Ethereum Signed Message” signature. We also add reference implementation that uses BLS signatures

Author: Agusx1211
Date: 2022-09-23T10:46:32.254Z

Is the current draft (EIP-4337: Account Abstraction via Entry Point Contract specification) up to date? I’m working on implementing 4337, but I see some inconsistencies between the EIP and the EntryPoint implementation.
For example, the EIP states the following rule:
Any GAS opcode is followed immediately by one of { CALL, DELEGATECALL, CALLCODE, STATICCALL }.

however, in the implementation repository, the example contains the following code:
  //pay required prefund. make sure NOT to use the "gas" opcode, which is banned during validateUserOp
  // (and used by default by the "call")
  (bool success,) = payable(msg.sender).call{value : requiredPrefund, gas : type(uint).max}("");
  (success);
  //ignore failure (its EntryPoint's job to verify, not wallet.)

So is not clear if GAS is allowed or not (when used before CALL, DELECATECALL, etc.). This is an important detail because proxy contracts (see EIP-1167) use the GAS opcode when forwarding the call. If this exception to the rule doesn’t exist, then wallets that use these proxies wouldn’t be compatible.

An unrelated thing:
Also while simulating the op there are a list of rules the client must enforce, but I see CALL to external contracts is allowed as long as value = 0, I think this is not enough to stop a 3rd contract from invalidating a large set of user operations:

During validation CALL address X with value = 0 and any data, address X is a non-deployed contract so it doesn’t have code, the call doesn’t fail.
Deploy a contract at address X, the contract calls address Y and it reverts if the call doesn’t fail.
Deploy a contract at address Y, the contract calls address Z and it reverts if the call doesn’t fail.
This enables toggling an arbitrary number of operations between valid and invalid.

This can be built as an ever expanding chain of NOT gates, I think a way to mitigate this issue is adding a rule that during validation the wallet is not allowed to call addresses with empty code.

Author: yoavw
Date: 2022-09-23T14:15:43.649Z

Agusx1211:

Is the current draft (EIP-4337: Account Abstraction via Entry Point Contract specification) up to date?


The latest changes haven’t been merged to the official repo yet.  They’re mainly related to signature aggregation but contain a few other minor changes.  It’ll be merged very soon.  The place to see the latest pending changes is https://github.com/eth-infinitism/account-abstraction/blob/develop/eip/EIPS/eip-4337.md



 Agusx1211:

So is not clear if GAS is allowed or not (when used before CALL, DELECATECALL, etc.).


It is allowed.  GAS is a forbidden opcode but there’s an exception to allow it just before *CALL which immediately consume it from the stack.  The rationale is that the code should not be able to access this information and change the flow based on it, but calls are fine.  Since the GAS value is not available to the code, the only way it could affect the flow is if a function runs out of gas.  But rule 7 precludes that, by banning out-of-gas calls:

No CALL, DELEGATECALL, CALLCODE, STATICCALL results in an out-of-gas revert.

So the exception described in the EIP is the correct one.  The EntryPoint code also doesn’t enforce it since it’s handled by the bundler.  What’s wrong is the comment in the code, which doesn’t mention the *CALL exception.



 Agusx1211:

2 Deploy a contract at address X, the contract calls address Y and it reverts if the call doesn’t fail.


At that point rule 9 kicks in:

EXTCODEHASH of every address accessed (by any opcode) does not change between first and second simulations of the op.

Any op that accesses address X gets dropped from mempool without simulation.  What the EIP tries to avoid is having to resimulate a large number of ops in order to drop them.  During the first simulation, the bundler saves a list of accessed addresses.  Since any code change would trigger rule 9, these ops would be invalidated without additional work.



 Agusx1211:

I think a way to mitigate this issue is adding a rule that during validation the wallet is not allowed to call addresses with empty code.


That actually wouldn’t mitigate the issue, since the contract at address X can be selfdestructed and redeployed differently each time by using some well known constructor tricks.  The attack would start with a contract that doesn’t revert at address X, then toggle it by selfdestructing and recreating (in a single transaction) in order to invalidate a large number of ops.  But I think rule 9 above does offer sufficient mitigation.  Do you see a way around it?

Author: Agusx1211
Date: 2022-09-23T15:14:05.122Z

yoavw:

Do you see a way around it?


What’s stopping the wallet from re-broadcasting the transaction? you could mutate the transaction a bit, and re-broadcast, thus spamming the mempool without any additional costs. I assume the the client can block the wallet, but then a sort of “per-wallet reputation” starts to play out too.



 yoavw:

That actually wouldn’t mitigate the issue, since the contract at address X can be selfdestructed and redeployed differently each time by using some well known constructor tricks.


Yes, but I’m assuming that SELFDESTRUCT will get deactivated soon enough.

Author: yoavw
Date: 2022-09-23T15:52:40.378Z

Agusx1211:

What’s stopping the wallet from re-broadcasting the transaction? you could mutate the transaction a bit, and re-broadcast, thus spamming the mempool without any additional costs. I assume the the client can block the wallet, but then a sort of “per-wallet reputation” starts to play out too.


We’d rather avoid per-wallet reputation.  We only have that for paymasters.  But this attack does have a cost to the attacker, probably higher than the damage it causes.  In order to propagate through the mempool, the op must be valid at the time of propagation.  The attacker has to invalidate it after it has been propagated, by deploying a contract.  The attacker also has to deploy a large number of wallets in order to fill the mempool, because each wallet can have only one op in the mempool at any given time.
So the attacker has a one-time setup cost of O(concurrent_ops) for setting up the wallets, and then O(iterations) for deploying a new contract on each iteration. And the damage is a single off-chain simulation for each iteration of the attack, since the 2nd simulation never happens due to rule 9.
I agree it would be better to mitigate it entirely, rather than relying on the cost and unprofitability of the attack.  But how would you block it without breaking too much functionality?  Preventing calls to accounts without code is a good idea and shouldn’t break anything, but doesn’t block the attack due to selfdestruct and recreate.



 Agusx1211:

Yes, but I’m assuming that SELFDESTRUCT will get deactivated soon enough.


It’ll be deactivated, but I don’t know about “soon enough”.  We did consider having a rule where contracts touched during validation must not have the selfdestruct opcode, but it wasn’t good enough because the contract could delegatecall to an unknown address (specified in the op rather than in the code), and that address could selfdestruct.  Preventing delegatecall to unknown addresses seems too harsh.

Author: yoavw
Date: 2022-09-29T11:53:17.511Z

Agusx1211:

I think a way to mitigate this issue is adding a rule that during validation the wallet is not allowed to call addresses with empty code.


https://github.com/eth-infinitism/account-abstraction/commit/699ecca1770f7e561bbc01e4e15e30ce2a50ebcb
Thanks 



 Agusx1211:

Yes, but I’m assuming that SELFDESTRUCT will get deactivated soon enough.






Shanghai Core EIP Consideration Process Improvement


    I would like to propose EIP-4758 for inclusion into Shanghai. 
It changes the semantics of the SELFDESTRUCT opcode and turns it into a SENDALL which sends the balance of the contract to a receiver. This EIP is a prerequisite to Verkle (and a bunch of other changes). It’s very easy to implement and not hard to test, so I would love to see it in Shanghai.
  

Cautiously optimistic.

Author: randomishwalk
Date: 2022-10-12T13:30:49.609Z

vbuterin:

Bundlers would either be miners/validators, or they would be actors publishing bundle txs through Flashbots.


How would this EIP in your mind fit into the context of MEV-boost and current builder market dynamics? Could this also potentially be used to implement/augment some form of “re-staking”?

Author: fjun99
Date: 2022-10-22T16:45:00.552Z

Can the graph in the EIP be simplified to this?
image810×662 55.5 KB

Author: dror
Date: 2022-10-25T07:24:06.398Z

It can, but then you’d miss the fact these are separate calls to separate wallets

Author: StanislavBreadless
Date: 2022-11-18T09:06:35.812Z

Is there any room for adding the transaction types in this proposal? For instance, each transaction will be described as a blob of bytes, where the first byte denotes the type of the transaction. This way it will be easier to keep backward compatibility in case some new types will be added. The question is risen mostly because L2s have different fee model: the price for L1 pubdata is dynamic.
Thus, for instance, zkSync has a separate field ergs_price_per_pubdata.
Arbitrum has similar plans as well.
And the base L1 itself is far from being fully finalized. Thus, new transaction types/execution variables may still be introduced. This way it would make the protocol more future-proof.

Author: Shchepetov
Date: 2022-11-24T23:05:47.968Z

Hello there!
I’m trying to understand the motivation of the bundler to do his job.
An I correct in assuming the preVerificationGas is always paid entirely so it can be arbitrarily large and used as a tip for the bundler?

Author: dror
Date: 2022-11-25T09:18:14.185Z

Shchepetov:

I’m trying to understand the motivation of the bundler to do his job.


The motivation is equivalent for a block builder to include any transactions: gas fees premiums.
The builder pays the “outer transaction” fee (probably to itself, if it is the build), and receives from each UserOp a fee based on userOp.priorityFee (and userOp.maxFeePerGas)
preVerificationGas can be used to tip the bundler a fixed amount, but its original purpose was to cover the gas cost that can’t be computed on-chain - the calldata cost, the fixed overhead (21000) and some EntryPoint contract overhead.

Author: dror
Date: 2022-11-25T09:23:48.018Z

The whole idea of the protocol is to check as much as possible from the UserOp in the EntryPoint contract, including the actual gas calculation.
Introducing a byte blobs defeats that purpose.
There is one “placeholder” for external gas calculation per network, namely preVerificationGas. It is assumed to be a function on the data in the UserOp and some network-specific parameters (like the 21000 stipend and the zero/nonzero byte costs)

Author: Shchepetov
Date: 2022-11-25T22:11:43.914Z

Thanks you for the answer. It turns out that in order to benefit from the execution of UserOp, the value of UserOpGasPrice must exceed the gas price was used when sending the transaction (except of expenses that can’t be computed on-chain), am I understanding correctly?
Is there any calculations of the potential benefits of bundlers?

Author: alexbakers
Date: 2022-12-06T22:35:22.575Z

Hello friends.
Can you tell me what is my proof of ownership of this or that abstraction account? Isn’t my EOA private key?

Author: mudgen
Date: 2022-12-15T14:41:01.121Z

I suggest using EIP-2535 Diamonds to implement the smart contract wallet for EIP-4337.
EIP-2535 is a proxy contract standard that can use more than one implementation contract (facet). This makes it relatively easy for uses to add additional contract functionality.
For example you could have a smart contract wallet implemented as an EIP-2535 Diamond that implements all the basic functionality needed and required by ERC-4337. Now if a user wants their smart contract wallet to have additional functionality the user can approve an upgrade on their diamond to add functions from another facet or facets to their diamond that has the functionality they want. Developers can develop different facets with different functionality for smart contract wallets. Users can then pick and choose and approve which facets and functionality they want to add to their smart contract wallet.
The facets of diamonds can be deployed one time and and then reused on-chain. So for example it is possible to create a registry of safe and compatible ERC 4337 account abstraction smart contract wallet facets that are deployed once. Each user can then deploy a diamond that uses a facet that provides the standard/required smart contract wallet functionality. From there each user can then choose what other functionality he or she wants their smart contract wallet to have and add the appropriate facets from the registry to their smart contract wallet diamond. The facets are reused-on chain, not deployed over and over again.
A diamond provides unlimited smart contract functionality at a single Ethereum address. Smart contract wallets can leverage this to provide functionality needed/desired by users without hitting the max contract size limit. EIP-2535 provides other benefits such as tooling, interoperability, multi-contract transparency, gas-efficiency, and code organization, which can be utilized.
What I am describing here is not just theory. Diamonds are being used by more than 70 projects.
A user interface that uses the standard to show deployed diamonds is here: https://louper.dev/
An introduction to EIP-2535 is here: Introduction to the Diamond Standard, EIP-2535 Diamonds
More resources and information about EIP-2535 are here: Awesome Diamonds.

Author: yoavw
Date: 2022-12-16T01:21:04.441Z

alexbakers:

Can you tell me what is my proof of ownership of this or that abstraction account? Isn’t my EOA private key?


There is no EOA involved.  Your proof of ownership is whatever you set up in the account’s validateUserOp() function.  If you implement this function to ecrecover the signature (from UserOp.signature), then it works similarly to an EOA (except that you can rotate the key without changing your address.  If you use a different signature scheme, then your proof of ownership is the key of whatever signature scheme you used.  If you implement a multisig or any other complex “signature”, then your proof of ownership is whatever the logic requires.

Author: yoavw
Date: 2022-12-16T01:31:51.634Z

mudgen:

I suggest using EIP-2535 Diamonds to implement the smart contract wallet for EIP-4337.


Yes.  ERC-4337 wallets could greatly benefit from using DiamodStorage and I hope to see wallet developers use it.
The benefit goes beyond just adding functionality via new facets.  It also keeps accounts safe when switching them to a new implementation.  Wallets are likely to use proxies, and the users may want to switch implementations.  For example, a user might start with a simple wallet, and later decide to switch it to a multisig or a wallet with social recovery.  There’s a risk that the previous implementation’s storage will break the security of the new implementation by leaving unexpected storage behind.  I demonstrated it by leaving shadow signers in Gnosis Safe.
If both implementations were EIP-2535 facets that use DiamondStorage with different base positions, switching between implementations becomes safe.

Author: cliffhall
Date: 2022-12-19T18:40:16.014Z

The main concern I have is that facets used as extensions should use their own storage slot, and if using the common functionality’s slot, that it not modify the slot’s storage structure, even in a way that should be safe. It could play badly with another available facet that makes its own ‘safe’ changes to the structure.

Author: mudgen
Date: 2022-12-21T03:44:33.782Z

Yes, I agree. As @yoavw said, it makes sense for different facets to use their own Diamond Storage with their own separate slot positions.

Author: yoavw
Date: 2022-12-30T02:08:56.826Z

I wrote a new post about the ERC-4337 unified mempool: Unified ERC-4337 mempool - HackMD

Author: xinbenlv
Date: 2023-01-10T23:57:50.172Z

Was late to the conversation but here is a EIP i like to bring to awareness at this community of EIP-4337 contributors:
EIP-5453 Endorsement which takes a slightly different approach for solving signature / approval functionality than the current version of UserOps but might be interopreable with UserOps. Feedback are greatly appreciated at ERC-5453 Endorsement Standard

Author: dror
Date: 2023-01-11T20:57:06.396Z

xinbenlv:

EIP-5453 Endorsement  which takes a slightly different approach for solving signature / approval


This 5453 solves a different problem. Namely, approval of specific method calls.
This saves round trips for separate transactions so it close to batching.
But batching is only one feature of 4337 .
With 5453, You must sign with your account, so it “enshrines” eoa accounts.
EIP 4337 is about accounts, and about abstracting them, so that any account can have it’s own execution model, signing model, recovery model, replay mechanism and also different gas model.
In addition, we define the rpc and protocol used by users and nodes to communicate, and make sure UserOperations are as decentralized as normal Ethereum transactions.

Author: xinbenlv
Date: 2023-01-12T01:50:02.364Z

dror:

This 5453 solves a different problem. Namely, approval of specific method calls.
This saves round trips for separate transactions so it close to batching.
But batching is only one feature of 4337 .
With 5453, You must sign with your account, so it “enshrines” eoa accounts.
EIP 4337 is about accounts, and about abstracting them, so that any account can have it’s own execution model, signing model, recovery model, replay mechanism and also different gas model.
In addition, we define the rpc and protocol used by users and nodes to communicate, and make sure UserOperations are as decentralized as normal Ethereum transactions.


Yeah, I totally understand that ERC-4337 took a systemic approach that covers a lot of other aspects thank just about signing. That’s why I was asking about feedback for using ERC-5453 in the context of ERC-4337 in one of its aspect: the approval model.

Author: dror
Date: 2023-01-12T10:35:37.259Z

As I understand it, the purpose of the approval model is to be able to submit a single transaction which does multiple actions at once, in an atomic transaction.
While it solves the on-chain problem (atomic transaction) it is still a nuisance for the user (which has to manually approve all operations)
This is a “best practice” when using an EOA, which has no other way to approve transactions.
When working with a wallet contract, the solution is different: A wallet contract can have an “executeBatch” , which trigger a sequence operations from the contract to external entities.
The contract owner approve once this batch, and the contract execute it all.
This way, we solve both the on-chain (single-transaction) and off-chain (single approval).
Yes, it comes with a cost (using contract account).
I don’t think that batching by itself is a reason for using wallet contract, but it comes with all other benefits of account-abstraction (authorization, security, gas abstraction etc)

Author: xinbenlv
Date: 2023-01-12T18:20:52.961Z

dror:

As I understand it, the purpose of the approval model is to be able to submit a single transaction which does multiple actions at once, in an atomic transaction.


It seems you and I use the term “approval model” to refer to two different things.
What I mean when using “approval model” I mean that

Account Alice wants to approve an action, e.g. transfer 1 units of her ERC20 to Account Charlie
Account Bob gets Alice’s approval and go ahead to execute the execution on Alice’s behalf.

The modeling of this process is what I refer to as “Approval Model”.
Currently, without ERC-4337 and ERC-5453, user would probably need to do something like

Alice: call ERC20.approve(bob, 1);
Bob: then call ERC20.transferFrom(alice, charlie, 1);

The alternative is to use ERC-2612

Alice: sign an approval with ERC-2612 and send digital signature off-chain to Bob
Bob: call ERC2612.permit(alice, bob, 1, tomorrow, v, r, s)
Bob: then call ERC20.transferFrom(alice, charlie, 1);


With ERC-5453

Alice: sign an approval with ERC-5453 and send digital signature off-chain to Bob
Bob: call ERC20.transferFrom(alice, charlie, 1, endorsement); (ERC20 needs to be extended but ERC721 supports this)


The account approving an action can be different from the account executing an action, is what I am trying to discuss this.

Author: JamesZaki
Date: 2023-01-16T14:08:24.131Z

Perhaps related to delegatable from @danfinlay, and this thread with Yoav considering 4337 compatibility.

Author: xinbenlv
Date: 2023-01-16T15:33:01.573Z

Thank you, that seems quite solving the same problem with two different approach, let me take a look.

Author: xinbenlv
Date: 2023-01-16T15:40:18.360Z

Yes. it’s in that space. Took slightly different approach. Will chat with Dan and work out a summary of different and see if we can collaborate to get some solution out.

Author: danfinlay
Date: 2023-01-21T05:18:18.122Z

Looking forward to chatting, it does look like you’ve started designing the same thing, I love that! There are surely lots of ways to improve it.
I recently think I made a breakthrough for how Delegatable-4337 could be simply achieved:
I think you could use this branch of Delegatable that adds support for EIP-1271 signatures from contract accounts, and just normalize that all 4337 accounts also implement EIP-1271.


github.com/delegatable/delegatable-sol








Eip1271 Support


main ← eip1271-support



          opened 03:32AM - 21 Nov 22 UTC




            danfinlay
          



+10518
-10950






Fixes #29

Adds Support for [EIP-1271](https://eips.ethereum.org/EIPS/eip-1271…) for allowing contract accounts to give and receive delegations.

Required one additional bit to the `SignedDelegation` and `SignedInvocation` types: `signerIsContract`. If this bit is `true`, then the first 20 bytes of the `signature` field is treated as the address of a contract to treat as the intended signer, and that contract is sent the remaining `signature: bytes` along with the delegation type hash to determine for itself whether this proof should be treated as valid authorization.

I formerly was somewhat against using EIP-1271 in this way, because I had seen some contract accounts merely allow assigning a single signer as their EIP1271 recovery strategy, which completely undermines the entire point of having a contract account. My position on this has evolved a bit, to  believe that correct usage is possible, and so we shouldn't let the possibility of flawed contract accounts prevent good ones from participating in this.

For example, good usage might look like a multisig might have a custom datastructure for representing which accounts' signatures are included, and including all the signatures combined in the `signature` payload.

Larger controller sets like a token-weighted DAO might involve too many signatures to submit as a delegation/invocation as `calldata`, but I'll leave exploration for how to best support that to those contracts' owners.






At that point, you get half the benefit: Even 4337 accounts (and contract accounts) can use any Delegatable contract.
Additionally, if the account contract itself also inherits Delegatable, then it could also delegate its own ability to do anything (and so delegate capabilities from contracts that do not themselves inherit from Delegatable).

Author: Philogy
Date: 2023-01-21T16:20:38.437Z

Surprised the draft does not yet present or discuss adjusted eth_sign and eth_signTypedData RPC endpoints that allow AA wallets to also return the necessary initCode so that “sign in with web3” applications can validate the ERC-1271 signatures of undeployed AA wallets, by simulating the creation first based on the initCode data.
Without this AA wallet users would not be able to interact with certain applications until their wallets have been deployed on-chain.
ERC-4337 already allows undeployed AA wallets to receive funds by requiring factories to use CREATE2 for their creation, would be great if the standard also allowed AA wallets to interact with signature-gated frontends before they’re deployed on-chain.

Author: dror
Date: 2023-01-22T12:43:21.164Z

Philogy:

Surprised the draft does not yet present or discuss adjusted eth_sign and eth_signTypedData RPC endpoints


The Account is a contract, and thus can’t sign. it can VERIFY signatures, if it supports ERC1271, that is, exports the isValidSignature() method.
The eth_sign and eth_signTypedData are not implemented by the node, but by the wallet. This ERC defines the contracts and protocol, and the validation/authorization of the wallets, not anything that is done during execution.
Even ERC-2771 itself is not mandated by ERC-4337 (though of course, it is highly recommended)
An ERC-4337 wallet should support the above RPC calls. Note that it uses the signer to sign it, not the account itself (again, because the account is a contract, and can’t sign)
Note that ERC-4337 doesn’t even require the signer to be an ECDSA signature. In such cases, the meaning of “signing” might be completely different.

Author: Philogy
Date: 2023-01-22T19:42:14.968Z

dror:

The Account is a contract, and thus can’t sign. it can VERIFY signatures, if it supports ERC1271, that is, exports the isValidSignature() method.
The eth_sign and eth_signTypedData are not implemented by the node, but by the wallet. This ERC defines the contracts and protocol, and the validation/authorization of the wallets, not anything that is done during execution.
Even ERC-2771 itself is not mandated by ERC-4337 (though of course, it is highly recommended)
An ERC-4337 wallet should support the above RPC calls. Note that it uses the signer to sign it, not the account itself (again, because the account is a contract, and can’t sign)
Note that ERC-4337 doesn’t even require the signer to be an ECDSA signature. In such cases, the meaning of “signing” might be completely different.


You completely missed my point. I wasn’t implying that smart contract wallets are able to somehow sign in the traditional notion. Furthermore ERC-1271 already allows wallets to implement any signature scheme, providing the necessary abstraction by allowing for a bytes signature parameter with no defined length limit.
What I was saying is that I believe the ERC-4337 standard should specify how wallets are to implement the eth_sign and eth_signTypedData RPC endpoints to return the necessary initCode so that applications can VERIFY “signatures” from ERC-4337 without them having to be deployed on-chain yet.

Author: cupOJoseph
Date: 2023-02-15T17:11:02.878Z

Petition to change the nomenclature from “Account Abstraction” to “Smart Account”

Fits in with “smart contract”: run code in your contract
better description for what it actually is at the end of the day: run code in your account
will lead to much less blind men touching an elephant effect

Author: JoeyFairyproof
Date: 2023-02-17T06:38:51.066Z

Hi authors of EIP-4337
This is Joey from Fairyproof. We are a Web3.0 security company.
Thank you for this well-written proposal - It is very well-documented and well-covered.
The technical team at Fairyproof has analyzed EIP-4337 and raised some security checkpoints that we would like to share with you.
You can check out on the details here: Security Checkpoints for EIP-4337 Based Account Abstraction Implementation | Fairyproof Tech | Medium
We hope you can take a look at these considerations and share your thoughts with us 
Thank you

Author: poojaranjan
Date: 2023-02-20T19:30:13.043Z

PEEPanEIP #100: ERC-4337: Account Abstraction Using Alt Mempool with @yoavw @dror Shahaf & Tom

Author: blooda
Date: 2023-02-23T10:37:41.451Z

Greetings friends,
We have launched an initiative to promote the integration of EIP1271 into more dApps as it is vital for account abstraction.


eip1271.io



EIP1271
EIP1271 - Everything you need is 0x1626ba7e! Powered by Etherspot & Pillar

Author: pette1999
Date: 2023-03-12T02:04:28.527Z

Hi all,
This is Peter from Hexlink, our team is working on an extension of EIP-4337 to the community:
EIP-6662: AA Account Metadata for Authentication which stores authentication data on-chain to support a more user-friendly authentication model. Would love to hear feedback from this community of EIP-4337 contributors 
Thank you all

Author: editorai
Date: 2023-03-17T02:32:52.789Z

Hi, this is Pablo from PlanckerDAO. We are recently organizing a joint reading of eip4337. When we got to the part on bundling, we were confused about the sentences “In practice, restrictions (2) and (3)” and “If any of the three conditions is violated” because we didn’t find the numbered restrictions and conditions above.
One of us sunnyishere (Github) discovered another early draft of eip4337 that provides clearer explains of “In practice, restrictions (2) and (3)” and "If any of the three conditions is violated. " We would like to ask if they are parts of the legacy documentation and should be updated. @yoavw @vbuterin

Author: cejay
Date: 2023-03-19T16:16:48.347Z

Yes, we added EIP-2535 at some stage in the implementation of the first pre-alpha version, but then removed EIP-2535 for the following reasons.

If FacetCut is restricted to view/pure only, the resulting lift is limited
if arbitrary FacetCut is allowed because of the use of delegatecall, then FacetCut can destroy the institution of storage (e.g. a wrong or malicious FacetCut can modify some storage that he should not be allowed)

We are also thinking about how to securely add dynamic plug-in capabilities to a self-custody wallet,
for example:

a centralized auditing institution is required, making it necessary for users to wait more than 2 days to use plugins that are not audited by the institution
(to prevent ownerkey theft while the internal storage slot has been modified by FacetCut and can no longer be used for social recovery.)
or use segregated storage slot (split by different addresses, but this leads to higher costs)

wait for your advice

Author: mudgen
Date: 2023-03-21T16:26:26.457Z

It is really great you are working on this.


If FacetCut is restricted to view/pure only, the resulting lift is limited


FacetCut is a struct defined in the EIP-2535 standard. Saying it is view/pure only does not make sense because it is just a struct definition. Only functions can be view/pure so I don’t really understand what you are saying here. Please clarify.


if arbitrary FacetCut is allowed because of the use of delegatecall, then FacetCut can destroy the institution of storage (e.g. a wrong or malicious FacetCut can modify some storage that he should not be allowed)


I think you are referring to arbitrarily making upgrades – adding/replacing/removing functions. Is that right? Of course don’t make it completely arbitrary. Only allow the owner of a diamond to upgrade their diamond. This is the same way contracts work now. People decide to trust or not the contracts that exist on ethereum. The facets of diamonds don’t have to be any different.  Of course audited registries of facets can be created to help people decide what to use and trust.
You mentioned that the above reasons were why you removed EIP-2535 but it is doubtful to me that those reasons are related to the compliance with the standard. For example diamonds can be non-upgradeable or immutable and still be compliant diamonds.  See this article about compliance: Compliance with EIP-2535 Diamonds Standard

Author: cejay
Date: 2023-03-21T16:51:19.015Z

Thanks, I should have understood what you meant 
I would like to add background information here, our project has social recovery, meaning that even if the private key of the owner within the wallet is stolen, the user can reset the owner through a social recovery process, so we need to make sure that even if the owner is owned by someone else, no one else should destroy any storage structure within the contract for a certain period of time (e.g. 2 days) (This may cause a breakdown in social recovery).
If the owner is allowed to add FacetCut at will, it is possible that the user will never be able to use Social Recovery to retrieve his wallet.
“If FacetCut is restricted to view/pure only, the resulting lift is limited”, I originally meant to allow the user to add  FacetCut that not call sstore opcode in any way is relatively safe.
Yes, for an audited FacetCut, I think users should be able to add it at any time.And maybe we should set a 2days delay in effect (so that in extreme cases the user can do social recovery) When users want to add unaudited FacetCut

and we still want to add support for the EIP2535, which was previously removed only because we wanted to find a balance between security and ease of use

Author: mudgen
Date: 2023-03-23T02:29:21.070Z

Hey, okay.  To clarify for other people seeing this,  “add FacetCut” just means being able to add/remove/replace external functions in a diamond right?

Yes, for an audited FacetCut, I think users should be able to add it at any time.And maybe we should set a 2days delay in effect (so that in extreme cases the user can do social recovery) When users want to add unaudited FacetCut

Your plan there makes sense to me.

Author: cejay
Date: 2023-03-23T15:11:00.816Z

mudgen:

Hey, okay. To clarify for other people seeing this, “add FacetCut” just means being able to add/remove/replace external functions in a diamond right?


Yes,exactly right.

Author: Mister-EA
Date: 2023-03-27T11:37:25.898Z

@yoavw , @dror
I have a question about this ERC: In a decentralized bundler network, what would be the incentive for bundlers to propagate UserOps to the rest of the bundlers in the UserOp mempool? If a bundler can collect fees for being the first to bundle UserOps and send them to the Ethereum network then I would presume it would become advantageous for a bundler to listen for incoming UserOps but not propagate them further since they can be the first to bundle the UserOps they receive.
In the normal Ethereum mempool this is not an issue because full nodes gossip amongst themselves and with block producers/validators. The full nodes are not in any competition with each other so they have no incentive to censor transactions.
But without a concept of a full-node for the proposed UserOp mempool, with bundlers in competition with each other to be the first to bundle UserOps, and with no consensus mechanism to regulate which bundler gets to create the next bundle, I would imagine that there wouldn’t be any reason or incentive for bundlers to communicate with each other.

Author: lukasz-glen
Date: 2023-03-29T20:13:03.945Z

dror:

Even ERC-2771 itself is not mandated by ERC-4337 (though of course, it is highly recommended)


Why do you say it is highly recommended? Is this recommendation related to 4337? If yes, I am a bit confused. I thought that 4337 actually eliminates a need for 2771 for AA because gas sponsoring takes place in another layer. 2771 is still needed for EOAs, of course.
I wonder if this statement is valid: with EIP2771 a target smart contract decides on gasless tx service provider (it defines trusted forwarder), with EIP4337 a wallet provider decides on gasless tx service (if enabled, it binds tightly or loosely to a paymaster).

Author: emilebaizel
Date: 2023-04-03T15:34:58.389Z

The EIP 4337 spec describes UserOperation as: Like a transaction, it contains “sender”, “to”, “calldata”, “maxFeePerGas”... . However, I don’t see where the to field gets set in any of the examples. ERC-4337: Account Abstraction Using Alt Mempool.
Does this need to be encoded as an attribute within the calldata?

Author: jackcpku
Date: 2023-04-05T17:08:29.027Z

Hello,
I have a question about the Account Abstraction model. In the context of fully on-chain gaming, players are expected to initiate transactions. However, I’m interested in implementing a system where multiple players sign messages, which are then aggregated by a backend and uploaded to the blockchain. Ideally, users wouldn’t need to see a pop-up window each time they sign, and could set a configuration allowing them to sign messages of a specific format without permission (e.g., {from: 0x0, data: *, value: 0}). Is this possible? Thank you!

Author: dror
Date: 2023-04-09T13:50:48.411Z

Mister-EA:

what would be the incentive for bundlers to propagate UserOps to the rest of the bundlers in the UserOp mempool


The incentive is the same as normal nodes and block-builders.
A “bundler” (a node that collects UserOperations into a transaction to be placed in the next block) has to be a block-builder (or use a direct API such as MEV-boost) to the next block.
Any attempt to put a bundle into the normal mempool would result a frontrun by another bundler.
It is true that a bundler can handle ITS OWN UserOperations, where they pay no extra fee to the bundler. This way there is no risk for someone to front-run (since there is no incentive to) - and even if someone does, it will get the UserOp on chain on the expense of this other bundler, so it doesn’t even serve as a “DoS” vector.
Since a bundler is merely a functionality of a block-builder, it carries almost the same incentive model.
The “almost” is because validation of a UserOperation is slightly more complex than a transaction: it is more expensive (in cpu and gas) and thus requires a different logic to protect the bundler from spam - but you do get paid for it when it gets submitted.

Author: dror
Date: 2023-04-09T13:54:11.265Z

We recommend 2771 because it is good for Smart-Contracts ecosystem, not directly related to erc-4337 (or AA in general)
This is the de-facto standard for off-chain signing of data.



 lukasz-glen:

2771 is still needed for EOAs, of course


2771 doesn’t need an EOA, of course…
It DOES need the contract to validate the signature in the isValidSignature() method, but there is no requirement for the signature to be ECDSA, or for the signer to be an account: it can be a BLS, shnorr, zkproof, multisig or whatever signature scheme your account supports.

Author: dror
Date: 2023-04-09T13:57:30.754Z

emilebaizel:

Does the “sender” need to be encoded as an attribute within the calldata?


Yes.
In ERC-4337, the format of the inner transaction is defined by the wallet itself. We expect wallets to have the equivalent of execute(dest,value,data), but they can use different formats.
Notably, accounts are expected to have an executeBatch() method, which may carry multiple destinations and calldata

Author: dror
Date: 2023-04-09T14:02:04.424Z

jackcpku:

Ideally, users wouldn’t need to see a pop-up window each time they sign


That’s not a framework issue, but a wallet issue: you want to be able to “pre-approve” the wallet to send specific transactions without a user interaction.
This in general pose a security breach, but there is a concept of “session key”: your account supports a restricted key, which is limited to specific target contracts, specific contract methods and time-span. The user creates such a key once, and let the game “manage” this key (e.g. store it in the browser’s localStorage)
The damage such a key may cause is limited - probably to the same site or game, which is probably accepted.
So even though ERC-4337 doesn’t define such session keys by itself (or any type of key, for that matter), it is possible to create such accounts which support multiple key types. I do believe some wallet implementations already support it, or intend to, as this is a key feature for blockchain gaming.

Author: rioisreal
Date: 2023-04-10T05:29:56.057Z

Hello guys,
Could anyone give me a hint, how the signature in user operation been generated, and how it been validated in the smart contract in details, I am quite confused on this part.
Best regards

Author: dror
Date: 2023-04-10T20:04:31.865Z

Account abstraction in general (and ERC-4337 in particular) delegate the validation of the UserOperation (transaction) to the account contract itself.
That is, ERC-4337 does not verify the signature at all. it calls a method on the account (named validateUserOp), which should validate the struct - including the signature field.
The meaning of this signature is entirely up to the account.
It can be a single or multiple signatures, a zk proof blob, or anything else.

Author: cejay
Date: 2023-04-17T23:02:40.026Z

@mudgen add some additional thoughts (not limited to specific plugin eip,hope it’s a useful thought  for all): link

How to minimize security issues caused by plugins in a contract wallet

Context:

The wallet use delegatecall to implement flexible plugins.
It is not allowed for hacker(stole your private key) to add malicious plugins to destroyed the storage slot before social recovery (social recovery will never be able to run if some storage slot destroyed).


Implementation suggestions:


The wallet owner must have a 48-hour delay confirmation period for adding any new plugins (or can be immediately effective through joint signature by owner and guardian).
(This prevents the wallet from being stolen by hackers and destroying the storage, causing social recovery to not run as expected.)


The wallet contract needs to add a simulate(calldata) function, where calldata is all the operations that the user will execute (if key storage such as owner, guardian, etc. are modified after executing the user’s operation, the specific information that is modified should be reverted). The wallet UI side should call this function in advance before the user executes any operation, if key storage is not modified as expected, the user should be prompted to avoid the wallet storage being destroyed by contract wallet plugin’s bug.

Author: dbmikus
Date: 2023-04-20T22:37:59.966Z

Was there an answer to this?

Hi, this is Pablo from PlanckerDAO. We are recently organizing a joint reading of eip4337. When we got to the part on bundling, we were confused about the sentences “In practice, restrictions (2) and (3)” and “If any of the three conditions is violated” because we didn’t find the numbered restrictions and conditions above.

I was having trouble understanding this as well, since there are only 2 bullets but it talks about restrictions (2) and (3). I think when referencing restrictions and conditions, it would be nice to reference them by label, which in most cases could be done by changing unordered lists to ordered lists in the ERC.

Author: Mister-EA
Date: 2023-04-21T12:34:22.983Z

I understand that the bundled transaction opens up the opportunity for front-running in the normal transaction mempool, and that’s why it is important to have Proposer-Builder separation (through MEV-boost).
The question I have is why would bundlers participate in the UserOp mempool, where they would be sharing the UserOps they received with other bundlers who would frontrun them in bundling the UserOps.
Wouldn’t it make more sense for users to send their UserOps to multiple bundlers, and the bundlers do not need to communicate with each other because they are in direct competition with one another. Why would a bundler share the UserOps they received with other bundlers in the mempool?

Author: dror
Date: 2023-04-21T18:12:46.218Z

Mister-EA:

Wouldn’t it make more sense for users to send their UserOps to multiple bundlers


UserOperation is a new type of transaction, and it shares the same incentive model as normal transactions.
Bundlers are essentially block-builders that support this new type of transaction.
Any question about a bundler is the same about a block-builder: Users are not expected to send transactions directly to block-builders, and just the same, they are not expected to send transactions directly to bundlers.

Author: mudgen
Date: 2023-04-24T13:37:53.118Z

This is my advice:

Do not limit add/replacing/remove functions to view/pure functions.
Handle security of facets by having a facet registry which is a list of audited and approved facets for smart contract wallet diamonds. Also upgrades could require the approval of a user.  That way a user gets only what he/she approves.

You can make it so that only facets in the facet registry can be added to a diamond.  That way a malicious user who somehow gains access to a diamond cannot add malicious facets.

Author: Mister-EA
Date: 2023-04-24T16:35:29.601Z

dror:

UserOperation is a new type of transaction, and it shares the same incentive model as normal transactions.


I think there is a difference. In the normal transaction mempool there is limited competitive advantage for validators to withhold transactions from other validators:

In Proof of Work chains, even if a miner communicates transactions to another miner, the block has to be mined for the transaction to be included in the chain. So PoW mining is the competitive bottleneck.
In Proof of Stake chains, validators get chosen probabilistically so there is no competitive advantage to withholding transactions from other validators.

In the UserOp mempool however, if a bundler sends UserOps to another bundler, the other bundler could bundle the UserOps faster and you lose out on the fees you could have collected if you were the first to bundle these UserOps. This is why it seems logical to me that the bundlers would not communicate with each other.
Is the UserOp mempool just a network of normal nodes propagating UserOps in a P2P manner with each other, and certain willing block producers participate in this mempool by listening to a certain set of nodes for UserOps which they can bundle, without propagating these UserOps any further in the mempool?

Author: dror
Date: 2023-04-25T13:13:48.514Z

If a bundler withholds transactions, soon enough users will notice they get included on-chain slower, and will stop using this RPC provider, and switch to another RPC provider.
A bundler (like any other block builder) earns from transaction fees but even more so from MEV opportunities.
As we see it, a logical bundler should look at each UserOperation and decide:

No high MEV value, so it is better to send it to the public mempool. The small gas fee will be earned by the bundler attached to the next block-builder, but at least the “quality of service” offered to the user is good.
High MEV value: better pay extra through PBS/MEVboost protocols to get this UserOperation included fast, before the opportunity disappears (and again, give the user a good quality of service)

Any other tactic will soon report this bundler is a bad service, and force the users to switch to another.

Author: dror
Date: 2023-04-25T13:16:56.942Z

mudgen:

You can make it so that only facets in the facet registry can be added to a diamond


This discussion thread is about the ERC-4337 core, not about account implementation: the modular accounts architecture is discussed separately here.

Author: mudgen
Date: 2023-04-26T13:52:13.785Z

Thanks for pointing me to this!

Author: web3panther
Date: 2023-05-10T19:01:01.828Z

Hey, I was wondering what if the key contract storage (owner, selector mapping, etc.) can change its slot randomly to a new location after a transaction is executed? Imagine we make a copy of storage before executing calldata, and assign it to a new randomly generated location and we update the information about this random location post execution of calldata. This way, the calldata can execute anything, but key storage aspects will not change.
PS: Need to assess the gas implications of this.

Author: bui-duc-huy
Date: 2023-05-11T04:45:01.851Z

Multi-Entrypoint Support for Account Abstraction
I have an idea to enhance its functionality by introducing multi-entrypoint support. This enhancement would allow an account to accept multiple entrypoints, enabling seamless integration with various wallet platforms.
The current EIP-4337 proposal focuses on providing a standardized approach for composing Ethereum accounts and abstracting their underlying signatures and key management. However, it assumes a single entrypoint for interacting with the account. By expanding the proposal to support multiple entrypoints, we can significantly enhance its flexibility and usability across different wallet implementations.
My proposal suggests introducing a mechanism within EIP-4337 that allows an account to register and manage multiple entrypoints. This way, users can interact with the account using different wallet platforms, each utilizing its own entrypoint, while still benefiting from the underlying features provided by account abstraction.
The benefits of this enhancement include:

Improved interoperability: Supporting multiple entrypoints would foster interoperability between different wallet platforms, empowering users to choose their preferred method of interacting with the account while maintaining a consistent user experience.
Enhanced user choice: Users could access and manage the account using a wide range of wallet implementations, including hardware wallets, mobile wallets, browser extensions, and more, without needing to modify or switch their account setup.
Developer-friendly integration: Wallet developers would have the flexibility to integrate their platforms with accounts utilizing EIP-4337 more easily, expanding the adoption and support for account abstraction in the Ethereum ecosystem

Author: bui-duc-huy
Date: 2023-05-11T04:58:05.092Z

I think (EIP-725X)[EIPs/eip-725.md at master · ethereum/EIPs · GitHub] can help

Author: xinbenlv
Date: 2023-05-29T13:53:42.949Z

Hi authors, I have a question about the “forbidden” opcodes.
On the EIP body it says

They should only be forbidden during verification, not execution.

But that’s not very obvious to me. Can you help me understand better by providing some examples about the intended enforcement approach?

Author: dror
Date: 2023-06-06T15:16:28.250Z

I don’t understand what you achieve with multiple EntryPoint contracts.
An account trusts the EntryPoint that its execute method is only called if validateUserOp is called first (and doesn’t fail).
While it is possible for an account to support multiple EntryPoint (e.g. using require(validEntryPoints[msg.sender])), I don’t see the merit of it: There should be a single EntryPoint on the network, and the only reason to replace is the unlikely case we find a security breach , in which case wallets would like to replace it.

Author: dror
Date: 2023-06-06T15:22:05.753Z

When an application submits a UserOperation (by calling the eth_sendUserOperation rpc call), the bundler first validate this UserOp is valid.
It does so by calling the simulateValidation() helper function, to make sure that creation, account validation and paymaster validation all succeed.
In order to protect itself (the bundler, not account), from denial of service attacks, it has to make sure this UserOp can’t interfere (invalidate) any other UserOp already in the mempool.
To do so, it performs a set of checks by tracing the above validation simulation - e.g. to make sure that opcodes that can be used for such denial of service (block number, timestamp,etc) are not used, and also that it only uses its own storage.
It will only accept UserOps that pass these validations.
If a UserOp is validated, the bundler knows it will pay, so there is no longer a possible of denial of service attack.
The executed code of the UserOp can do whatever it pleases - the UserOp is already guaranteed to pay. Just like normal transaction, the user pays even if the UserOp (or transaction) reverts.

Author: dror
Date: 2023-06-06T15:24:27.346Z

I don’t understand what you’re trying to do: during execution, you can do whatever you like. Moving storage to another randomly-allocated location is possible - but you still need to keep (in storage) this randomly allocated storage address.

Author: web3panther
Date: 2023-06-06T17:32:19.767Z

The problem I am trying to tackle is what if user adds a plugin to their AA wallet, that has a malicious code that can change the diamond storage layout causing users to lose access to wallet.

Author: bui-duc-huy
Date: 2023-06-08T03:52:08.115Z

ERC20 Gas Payment Implementation in Bundler:
Should we include logic to validate ERC20 gas payments in the bundler, such as checking prices to optimize gas usage?
The paymaster contract will solely validate gasPrice and return the ERC20 token to tx.origin. Users have the option to set maxPriorityFeePerGas and maxFeePerGas in the userOperation to zero.
When implementing ERC20 gas payments in the bundler, it is worth considering the inclusion of additional logic to validate these payments and optimize gas usage. One approach could involve performing price checks to ensure efficient gas consumption.
Furthermore, users are provided with the flexibility to set maxPriorityFeePerGas and maxFeePerGas to zero within the userOperation section.

Author: dror
Date: 2023-06-18T11:09:36.540Z

The idea is leave the core entities (EntryPoint and bundlers) as un-opinionated as possible. Tokens involve exposure to price volatility, which the core network shouldn’t deal with.
Payment with token is done using a TokenPaymaster, which pays the gas price in native token (eth), and receive tokens from the user’s account.

Author: xinbenlv
Date: 2023-06-22T15:48:31.874Z

Hi ERC-4337 contributors:
Just FYI, there is a pending Pull Request to move ERCs out from the current EIP repo, which may mean a new place for future ERC-4337 updates.
We will be grateful to hear your opinion on this
https://github.com/ethereum/EIPs/pull/7206

Author: Darren-Yau
Date: 2023-07-28T20:04:58.896Z

I’m interested in learning whether Account Abstraction will be implemented in the consensus layer in the future. I observed that EIP-4337 was favored over EIP-2938 because it avoids AA on the consensus layer. The reason for my inquiry is that I am an early solo staker who lost my mnemonic and now can’t create a withdrawal address. I’m curious if there are any upcoming EIPs that might introduce social recovery options for ETH2 addresses.

Author: 18dew
Date: 2023-08-02T07:03:54.369Z

Does this mean session key will have access to all functions of AA wallet by default. Or there would be some control needs to be in place which cross checks data from userOperation while validating transaction coming to smart contract via session key

Author: dror
Date: 2023-08-05T20:29:50.847Z

18dew:

Does this mean session key will have access to all functions of AA wallet by default


erc-4337 doesn’t define session key - a specific account implementation can define it, and it also has to define what it can do.
erc4337 only let the validation methods (of account and paymaster) declare the time-range they are valid, which is required in order to have session keys.
Note that this mechanism can be used for other purposes too. e.g. someone can create a paymaster that accepts a “coupon”, which is only valid on a specific time-range.

Author: PixelCircuits
Date: 2023-10-05T02:49:10.194Z

Why was nonce management moved to the EntryPoint contract itself? I would think that’s something accounts would want complete control over. For example, creating a userOp that an account wants to give nonce incrementing control to another account (in a gas efficient way). Or using an entire storage slot as a 256 bit wide bit field to invalidate one-off userOps (more gas efficient than using whole storage slots just to invalidate one userOp in current key-value implementation).

Author: zlace
Date: 2023-10-07T13:50:03.356Z

For this purpose, a UserOperation is not allowed to access any information that might change between simulation and execution, such as current block time, number, hash etc. In addition, a UserOperation is only allowed to access data related to this sender address: Multiple UserOperations should not access the same storage, so that it is impossible to invalidate a large number of UserOperations with a single state change.

From this statement it isn’t clear that this applies only to validation and that execution is unrestricted.

Author: dror
Date: 2023-10-16T07:04:29.670Z

zlace:

From this statement it isn’t clear that this applies only to validation


Thanks, your right. Will be fixed

Author: dror
Date: 2023-10-16T07:15:09.200Z

PixelCircuits:

Why was nonce management moved to the EntryPoint contract itself?


The make reason was too force uniqueness of UserOps. While accounts can work security on-chain, it makes offchain tools, such as block explorers and some paymasters more complex.
UserOps should behave as much as possible as transactions, and unique id is a major feature.
The adopted solution still allow unique out-of-order UserOps, with 192 bit unique id.
This seems to be sufficient (after all, addresses are considered unique and are only 160 bit)
Can you give an example where you think this is not enough?

Author: PixelCircuits
Date: 2023-10-16T15:02:14.447Z

The 192 bit ID plus 64 bit nonce is great, but I would tweak it to make one-off userOps more efficient. I’d suggest we make values starting at 2^64 - 256 and up be recognized as accessing a bit field all on the same storage slot. So a value of (2^64 - 256) + n would be explicitly pointing to bit n on the slot at [192bit ID]. This would eliminate having to set non zero storage on every userOp that is just an out-of-order one-off and save 17,100 gas ($0.43 on mainnet at time of writing).

Author: dror
Date: 2023-10-23T22:57:14.828Z

I don’t understand how you suggest to use a single storage slot for arbitrary number of one-off userops.

Author: PixelCircuits
Date: 2023-10-23T23:45:17.201Z

I guess I should have more accurately said one slot for every 256 on-off user ops.

Author: SamWilsn
Date: 2023-10-28T01:16:48.764Z

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

Author: dror
Date: 2023-10-31T18:18:27.802Z

The schema of the rpc calls are here

github.com



//github.com/eth-infinitism/bundler-spec/tree/main/src

Author: SamWilsn
Date: 2023-11-02T02:14:35.907Z

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

Author: z0r0z
Date: 2023-11-07T12:13:18.073Z

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)?

Author: dror
Date: 2023-11-22T19:04:50.764Z

z0r0z:

change validateUserOp to public rather than external


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

Author: z0r0z
Date: 2023-11-24T04:47:52.674Z

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.

Author: Philogy
Date: 2023-12-05T01:15:53.466Z

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:

Different wallets may want to validate nonces differently, enshrining the logic limits this.
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.
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?

Author: dror
Date: 2024-02-11T12:34:22.691Z

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)

Author: Philogy
Date: 2024-02-21T03:57:40.630Z

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?

Author: novaknole
Date: 2024-02-28T20:39:44.435Z

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:

deploy contract is run with “verificationGasLimit” - i.e

senderCreator.createSender{gas : opInfo.mUserOp.verificationGasLimit}(initCode);


Then:

try IAccount(sender).validateUserOp{gas : mUserOp.verificationGasLimit}(op, opInfo.userOpHash, missingAccountFunds)


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.

Author: karandeep
Date: 2024-04-28T17:57:20.031Z

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


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.

Author: dror
Date: 2024-05-01T01:00:59.882Z

novaknole:

In ERC4337, verificationGasLimit



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
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.

Author: dror
Date: 2024-05-01T01:05:55.308Z

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.

Author: ryley-o
Date: 2024-06-11T02:36:45.649Z

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

Author: matthiasgeihs
Date: 2024-06-21T10:49:28.988Z

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.

Author: fryorcraken
Date: 2024-08-15T03:14:12.707Z

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

Author: lucaslim
Date: 2024-08-19T06:00:34.715Z

@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

Author: peersky
Date: 2024-09-10T16:30:19.095Z

github.com/ethereum/ERCs








Update ERC-4337: Use ERC-7746 for userOp and PaymasterOp validation


master ← peersky:add-7746-as-dep-to-4337



          opened 04:27PM - 10 Sep 24 UTC




            peersky
          



+29
-48






This PR proposes replacing `validateUserOp` and `validatePaymasterOp` with the g…eneric middleware hook standard outlined in `ERC-7746`. This change introduces `beforeCall` and `afterCall` hooks, providing a more generalized approach to user operation and paymaster validations.

This approach is beneficial due to few reasons: 

- **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.






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.