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: validate using handleOps() #929

Merged
merged 5 commits into from
Feb 27, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 10 additions & 43 deletions ERCS/erc-4337.md
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ In the execution loop, the `handleOps` call must perform the following steps for

![](../assets/eip-4337/bundle-seq.svg)

Before accepting a `UserOperation`, bundlers should use an RPC method to locally call the `simulateValidation` function on the `EntryPoint`, to verify that the signature is correct and the `UserOperation` actually pays fees; see the [Simulation section below](#useroperation-simulation) for details.
Before accepting a `UserOperation`, bundlers should use an RPC method to locally call the `handleOps` function on the `EntryPoint`, to verify that the signature is correct and the `UserOperation` actually pays fees; see the [Simulation section below](#useroperation-simulation) for details.
A node/bundler SHOULD drop (not add to the mempool) a `UserOperation` that fails the validation


Expand Down Expand Up @@ -382,57 +382,24 @@ Intuitively, the aim of the simulation is to ensure the onchain validation code

#### Simulation Specification:

To simulate a `UserOperation` validation, the bundler makes a view call to `simulateValidation(userOp)`.
To simulate a `UserOperation` validation, the bundler makes a view call to the `handleOps()` method with the UserOperation to check.

The `EntryPoint` itself does not implement the simulation methods. Instead, when making the simulation view call,
The bundler MAY provide the alternate `EntryPointSimulations` code, which extends the `EntryPoint` with the simulation methods.
Simulation should run only on the validation section of the account and paymaster, and is not required for the UserOperations's execution.
A bundler MAY add second "always failed" `UserOperation` to the bundle, so that the simulation will
end as soon as the first UserOperation's validation complete.

The simulation core methods:

```solidity

struct ValidationResult {
ReturnInfo returnInfo;
StakeInfo senderInfo;
StakeInfo factoryInfo;
StakeInfo paymasterInfo;
AggregatorStakeInfo aggregatorInfo;
}

function simulateValidation(PackedUserOperation calldata userOp)
external returns (ValidationResult memory);

struct ReturnInfo {
uint256 preOpGas;
uint256 prefund;
uint256 accountValidationData;
uint256 paymasterValidationData;
bytes paymasterContext;
}

struct StakeInfo {
uint256 stake;
uint256 unstakeDelaySec;
}

```

The `AggregatorStakeInfo` structure is further defined in [ERC-7766](./eip-7766.md).

This method returns `ValidationResult` or revert on validation failure.
The node MUST drop the `UserOperation` if the simulation fails (either by revert or by "signature failure")
The bundler MUST drop the `UserOperation` if the simulation reverts

The simulated call performs the full validation, by calling:

1. If `initCode` is present, create the account.
2. `account.validateUserOp`.
3. if specified a paymaster: `paymaster.validatePaymasterUserOp`.

The simulateValidation should validate the return value (validationData) returned by the account's `validateUserOp` and paymaster's `validatePaymasterUserOp`.
The paymaster MUST return either `SIG_VALIDATION_SUCCESS` (`0`) for success or `SIG_VALIDATION_FAILED` (`1`) for signature verification failure.
Either return value may contain a "validAfter" and "validUntil" timestamps, which is the time-range that this `UserOperation` is valid on-chain.
A node MAY drop a `UserOperation` if it expires too soon (e.g. wouldn't make it to the next block) by either the account or paymaster.
If the `ValidationResult` includes `sigFail`, the bundler MUST drop the `UserOperation`.
Either account or paymaster may return a time-range (validAfter/validUntil).
The `UserOperation` MUST be valid at the current time to be considered valid (that is, validAfter<=block.timestamp)
A bundler MAY drop a `UserOperation` if it expires too soon (e.g. wouldn't make it to the next block) by either the account or paymaster.
To decode the returned time-ranges, the bundler should run the validation using tracing, to decode the return value from the `validateUserOp` and `validatePaymasterUserOp` methods.

To prevent DoS attacks on bundlers, they must make sure the validation methods above pass the validation rules, which constrain their usage of opcodes and storage.
For the complete procedure see [ERC-7562](./eip-7562.md)
Expand Down
Loading