Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update ERC-4337: Update ERC-4337 and ERC-7769 with EIP-712 and EIP-7702 support #882

Merged
merged 11 commits into from
Feb 19, 2025
38 changes: 36 additions & 2 deletions ERCS/erc-4337.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ status: Draft
type: Standards Track
category: ERC
created: 2021-09-29
requires: 7562
requires: 712, 7562, 7702, 7769
---

## Abstract
Expand Down Expand Up @@ -210,7 +210,9 @@ The entry point method is `handleOps`, which handles an array of userOps

The entry point's `handleOps` function must perform the following steps (we first describe the simpler non-paymaster case). It must make two loops, the **verification loop** and the **execution loop**. In the verification loop, the `handleOps` call must perform the following steps for each `UserOperation`:

* **Create the account if it does not yet exist**, using the initcode provided in the `UserOperation`. If the account does not exist, _and_ the initcode is empty, or does not deploy a contract at the "sender" address, the call must fail.
* **Create the account if it does not yet exist**, using the initcode provided in the `UserOperation`.
* If the account is an EOA with an [EIP-7702](./eip-7702.md) authorization designation, the EntryPoint validates the authorized address matches the one specified in the UserOperation signature (see [Support for [EIP-7702] authorizations](#support-for-eip-7702-authorizations)).
* If the account does not exist, _and_ the initcode is empty, or does not deploy a contract at the "sender" address, the call must fail.
* calculate the maximum possible fee the account needs to pay (based on validation and call gas limits, and current gas values)
* calculate the fee the account must add to its "deposit" in the EntryPoint
* **Call `validateUserOp` on the account**, passing in the `UserOperation`, its hash and the required fee. The account should verify the operation's signature, and pay the fee if the account considers the operation valid. If any `validateUserOp` call fails, `handleOps` must skip execution of at least that operation, and may revert entirely.
Expand All @@ -222,6 +224,7 @@ In the execution loop, the `handleOps` call must perform the following steps for
* If the calldata starts with the methodsig `IAccountExecute.executeUserOp`, then the EntryPoint must build a calldata by encoding `executeUserOp(userOp,userOpHash)` and call the account using that calldata.
* After the call, refund the account's deposit with the excess gas cost that was pre-charged.\
A penalty of `10%` (`UNUSED_GAS_PENALTY_PERCENT`) is applied on the amounts of `callGasLimit` and `paymasterPostOpGasLimit` gas that remains **unused**.\
This penalty is only applied if the amount of the remaining unused gas is greater than or equal `40000` (`PENALTY_GAS_THRESHOLD`).\
This penalty is necessary to prevent the UserOps from reserving large parts of the gas space in the bundle but leaving it unused and preventing the bundler from including other UserOperations.
* After the execution of all calls, pay the collected fees from all UserOperations to the `beneficiary` address provided by the bundler.

Expand All @@ -230,6 +233,37 @@ In the execution loop, the `handleOps` call must perform the following steps for
Before accepting a `UserOperation`, bundlers should use an RPC method to locally call the `simulateValidation` function on the entry point, to verify that the signature is correct and the operation actually pays fees; see the [Simulation section below](#simulation) for details.
A node/bundler SHOULD drop (not add to the mempool) a `UserOperation` that fails the validation


### Support for [EIP-712](./eip-712.md) signatures

The `userOpHash` is calculated as an [EIP-712] typed message hash with the following parameters:

```solidity
bytes32 constant TYPE_HASH =
keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
);

bytes32 constant PACKED_USEROP_TYPEHASH =
keccak256(
"PackedUserOperation(address sender,uint256 nonce,bytes initCode,bytes callData,bytes32 accountGasLimits,uint256 preVerificationGas,bytes32 gasFees,bytes paymasterAndData)"
);
```

### Support for [EIP-7702] authorizations

On networks with the EIP-7702 enabled, the `eth_sendUserOperation` method accepts an extra `eip7702auth` parameter.
If this parameter is set, the bundler should add it to the authorizationList for for this transaction.
Seperately, the hash calculation is updated to include the current [EIP-7702] delegate

If the `initCode` field starts with `0x7702` padded with zeros, and this account was deployed using an EIP-7702 transaction, then the hash is calculated as follows:

* For the purpose of hash calculation, the first 20 bytes of the `initCode` field of the `UserOperation` are set to account's EIP-7702 delegate address (fetched with EXTCODECOPY)
* The `initCode` is not used to call a factory contract.
* If the `initCode` is longer than 20 bytes, then the rest of the initCode is used to call an initialization function in the account itself.

Note that a UserOperation may still be executed without such initCode. In this case the EntryPoint doesn't hash the current [EIP-7702 delegate], and can be potentially executed against a modified account.

### Extension: paymasters

We extend the entry point logic to support **paymasters** that can sponsor transactions for other users. This feature can be used to allow application developers to subsidize fees for their users, allow users to pay fees with [ERC-20] tokens and many other use cases. When the paymasterAndData field in the UserOp is not empty, the entry point implements a different flow for that UserOperation:
Expand Down
Loading