diff --git a/EIPS/eip-4337.md b/EIPS/eip-4337.md index 9311c228e89346..a24e55b3ce45e2 100644 --- a/EIPS/eip-4337.md +++ b/EIPS/eip-4337.md @@ -1,12 +1,12 @@ --- eip: 4337 -title: Account Abstraction using alt mempool +title: Account Abstraction Using Alt Mempool description: An account abstraction proposal which completely avoids consensus-layer protocol changes, instead relying on higher-layer infrastructure. author: Vitalik Buterin (@vbuterin), Yoav Weiss (@yoavw), Kristof Gazso (@kristofgazso), Namra Patel (@namrapatel), Dror Tirosh (@drortirosh), Shahaf Nacson (@shahafn), Tjaden Hess (@tjade273) discussions-to: https://ethereum-magicians.org/t/erc-4337-account-abstraction-via-entry-point-contract-specification/7160 +status: Draft type: Standards Track category: ERC -status: Draft created: 2021-09-29 --- @@ -16,11 +16,11 @@ An account abstraction proposal which completely avoids the need for consensus-l ## Motivation -See also ["Implementing Account Abstraction as Part of Eth 1.x"](https://ethereum-magicians.org/t/implementing-account-abstraction-as-part-of-eth1-x/4020) and the links therein for historical work and motivation, and [EIP-2938](./eip-2938.md) for a consensus layer proposal for implementing the same goal. +See also `https://ethereum-magicians.org/t/implementing-account-abstraction-as-part-of-eth1-x/4020` and the links therein for historical work and motivation, and [EIP-2938](./eip-2938.md) for a consensus layer proposal for implementing the same goal. This proposal takes a different approach, avoiding any adjustments to the consensus layer. It seeks to achieve the following goals: -* **Achieve the key goal of account abstraction**: allow users to use smart contract wallets containing arbitrary verification logic instead of EOAs as their primary account. Completely remove any need at all for users to also have EOAs (as status quo SC wallets and EIP-3074 both require) +* **Achieve the key goal of account abstraction**: allow users to use smart contract wallets containing arbitrary verification logic instead of EOAs as their primary account. Completely remove any need at all for users to also have EOAs (as status quo SC wallets and [EIP-3074](./eip-3074.md) both require) * **Decentralization** * 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 @@ -28,22 +28,23 @@ This proposal takes a different approach, avoiding any adjustments to the consen * **Do not require any Ethereum consensus changes**: Ethereum consensus layer development is focusing on the merge and later on scalability-oriented features, and there may not be any opportunity for further protocol changes for a long time. Hence, to increase the chance of faster adoption, this proposal avoids Ethereum consensus changes. * **Try to support other use cases** * Privacy-preserving applications - * Atomic multi-operations (similar goal to EIP-3074) - * Pay tx fees with ERC-20 tokens, allow developers to pay fees for their users, and [EIP-3074](./eip-3074.md)-like **sponsored transaction** use cases more generally + * Atomic multi-operations (similar goal to [EIP-3074](./eip-3074.md)) + * Pay tx fees with [EIP-20](./eip-20.md) tokens, allow developers to pay fees for their users, and [EIP-3074](./eip-3074.md)-like **sponsored transaction** use cases more generally * Support aggregated signature (e.g. BLS) -## Definitions +## Specification + +### Definitions * **UserOperation** - a structure that describes a transaction to be sent on behalf of a user. To avoid confusion, it is named "transaction". * Like a transaction, it contains "sender", "to", "calldata", "maxFeePerGas", "maxPriorityFee", "signature", "nonce" - * unlike transaction, it contains several other fields, desribed below + * unlike transaction, it contains several other fields, described below * also, the "nonce" and "signature" fields usage is not defined by the protocol, but by each account implementation * **Sender** - the account contract sending a user operation. * **EntryPoint** - a singleton contract to execute bundles of UserOperations. Bundlers/Clients whitelist the supported entrypoint. * **Bundler** - a node (block builder) that bundles multiple UserOperations and create an EntryPoint.handleOps() transaction. Note that not all block-builders on the network are required to be bundlers * **Aggregator** - a helper contract trusted by accounts to validate an aggregated signature. Bundlers/Clients whitelist the supported aggregators. -## Specification To avoid Ethereum consensus changes, we do not attempt to create new transaction types for account-abstracted transactions. Instead, users package up the action they want their account to take in an ABI-encoded struct called a `UserOperation`: @@ -56,8 +57,8 @@ To avoid Ethereum consensus changes, we do not attempt to create new transaction | `callGasLimit` | `uint256` | The amount of gas to allocate the main execution call | | `verificationGasLimit` | `uint256` | The amount of gas to allocate for the verification step | | `preVerificationGas` | `uint256` | The amount of gas to pay for to compensate the bundler for pre-verification execution and calldata | -| `maxFeePerGas` | `uint256` | Maximum fee per gas (similar to EIP 1559 `max_fee_per_gas`) | -| `maxPriorityFeePerGas` | `uint256` | Maximum priority fee per gas (similar to EIP 1559 `max_priority_fee_per_gas`) | +| `maxFeePerGas` | `uint256` | Maximum fee per gas (similar to [EIP-1559](./eip-1559.md) `max_fee_per_gas`) | +| `maxPriorityFeePerGas` | `uint256` | Maximum priority fee per gas (similar to EIP-1559 `max_priority_fee_per_gas`) | | `paymasterAndData` | `bytes` | Address of paymaster sponsoring the transaction, followed by extra data to send to the paymaster (empty for self-sponsored transaction) | | `signature` | `bytes` | Data passed into the account along with the nonce during the verification step | @@ -75,12 +76,12 @@ function handleAggregatedOps( address payable beneficiary ); + struct UserOpsPerAggregator { UserOperation[] userOps; IAggregator aggregator; bytes signature; } - function simulateValidation(UserOperation calldata userOp); error ValidationResult(uint256 preOpGas, uint256 prefund, uint256 deadline, @@ -110,6 +111,7 @@ interface IAccount { } ``` The account + * MUST validate the caller is a trusted EntryPoint * The userOpHash is a hash over the userOp (except signature), entryPoint and chainId * If the account does not support signature aggregation, it MUST validate the signature is a valid signature of the `userOpHash`, and @@ -121,20 +123,23 @@ The account (or SIG_VALIDATION_FAILED on signature mismatch) An account that works with aggregated signature should have the interface: + ```solidity interface IAggregatedAccount is IAccount { function getAggregator() view returns (address); } ``` + * **getAggregator()** returns the aggregator this account supports. * **validateUserOp()** (inherited from IAccount interface) MUST verify the `aggregator` parameter is valid and the same as `getAggregator` * The account should also support aggregator-specific getter (e.g. `getAggregationInfo()`). This method should export the account's public-key to the aggregator, and possibly more info - (note that it is not called directly by the entryPoint) + (note that it is not called directly by the entryPoint) * validateUserOp MAY ignore the signature field The core interface required by an aggregator is: + ```solidity interface IAggregator { @@ -168,6 +173,7 @@ resources (or revert) when the above methods are called in view mode, or if the ### Required entry point contract functionality There are 2 separate entry point methods: `handleOps` and `handleAggregatedOps` + * `handleOps` handle userOps of accounts that don't require any signature aggregator. * `handleAggregatedOps` can handle a batch that contains userOps of multiple aggregators (and also requests without any aggregator) * `handleAggregatedOps` performs the same logic below as `handleOps`, but it must transfer the correct aggregator to each userOp, and also must call `validateSignatures` on each aggregator after doing all the per-account validation. @@ -188,7 +194,7 @@ A node/bundler SHOULD drop (and not add to the mempool) `UserOperation` that fai ### 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 paymaster is not equal to the zero address, the entry point implements a different flow: +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 EIP-20 tokens and many other use cases. When the paymaster is not equal to the zero address, the entry point implements a different flow: ![](../assets/eip-4337/image2.png) @@ -242,20 +248,19 @@ function depositTo(address account) public payable // withdraw from the deposit function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external - ``` ### Client behavior upon receiving a UserOperation When a client receives a `UserOperation`, it must first run some basic sanity checks, namely that: -- Either the `sender` is an existing contract, or the `initCode` is not empty (but not both) -- If `initCode` is not empty, parse its first 20 bytes as a factory address. Record whether the factory is staked, in case the later simulation indicates that it needs to be. If the factory accesses global state, it must be staked - see [reputation, throttling and banning section](#reputation-scoring-and-throttlingbanning-for-global-entities) for details. -- The `verificationGasLimit` is sufficiently low (`<= MAX_VERIFICATION_GAS`) and the `preVerificationGas` is sufficiently high (enough to pay for the calldata gas cost of serializing the `UserOperation` plus `PRE_VERIFICATION_OVERHEAD_GAS`) -- The `paymasterAndData` is either empty, or start with the **paymaster** address, which is a contract that (i) currently has nonempty code on chain, (ii) has a sufficient deposit to pay for the UserOperation, and (iii) is not currently banned. During simulation, the paymaster's stake is also checked, depending on its storage usage - see [reputation, throttling and banning section](#reputation-scoring-and-throttlingbanning-for-global-entities) for details. -- The callgas is at least the cost of a `CALL` with non-zero value. -- The `maxFeePerGas` and `maxPriorityFeePerGas` are above a configurable minimum value that the client is willing to accept. At the minimum, they are sufficiently high to be included with the current `block.basefee`. -- The sender doesn't have another `UserOperation` already present in the pool (or it replaces an existing entry with the same sender and nonce, with a higher `maxPriorityFeePerGas` and an equally increased `maxFeePerGas`). Only one `UserOperation` per sender may be included in a single batch. A sender is exempt from this rule and may have multiple `UserOperations` in the pool and in a batch if it is staked (see [reputation, throttling and banning section](#reputation-scoring-and-throttlingbanning-for-global-entities) below), but this exception is of limited use to normal accounts. +* Either the `sender` is an existing contract, or the `initCode` is not empty (but not both) +* If `initCode` is not empty, parse its first 20 bytes as a factory address. Record whether the factory is staked, in case the later simulation indicates that it needs to be. If the factory accesses global state, it must be staked - see [reputation, throttling and banning section](#reputation-scoring-and-throttlingbanning-for-global-entities) for details. +* The `verificationGasLimit` is sufficiently low (`<= MAX_VERIFICATION_GAS`) and the `preVerificationGas` is sufficiently high (enough to pay for the calldata gas cost of serializing the `UserOperation` plus `PRE_VERIFICATION_OVERHEAD_GAS`) +* The `paymasterAndData` is either empty, or start with the **paymaster** address, which is a contract that (i) currently has nonempty code on chain, (ii) has a sufficient deposit to pay for the UserOperation, and (iii) is not currently banned. During simulation, the paymaster's stake is also checked, depending on its storage usage - see [reputation, throttling and banning section](#reputation-scoring-and-throttlingbanning-for-global-entities) for details. +* The callgas is at least the cost of a `CALL` with non-zero value. +* The `maxFeePerGas` and `maxPriorityFeePerGas` are above a configurable minimum value that the client is willing to accept. At the minimum, they are sufficiently high to be included with the current `block.basefee`. +* The sender doesn't have another `UserOperation` already present in the pool (or it replaces an existing entry with the same sender and nonce, with a higher `maxPriorityFeePerGas` and an equally increased `maxFeePerGas`). Only one `UserOperation` per sender may be included in a single batch. A sender is exempt from this rule and may have multiple `UserOperations` in the pool and in a batch if it is staked (see [reputation, throttling and banning section](#reputation-scoring-and-throttlingbanning-for-global-entities) below), but this exception is of limited use to normal accounts. If the `UserOperation` object passes these sanity checks, the client must next run the first op simulation, and if the simulation succeeds, the client must add the op to the pool. A second simulation must also happen during bundling to make sure the UserOperation is still valid. @@ -270,14 +275,15 @@ In addition, a UserOperation is only allowed to access data related to this send There are 3 special contracts that interact with the account: the factory (initCode) that deploys the contract, the paymaster that can pay for the gas, and signature aggregator (described later) Each of these contracts is also restricted in its storage access, to make sure UserOperation validations are isolated. -#### Specification +#### Specification: + To simulate a `UserOperation` validation, the client makes a view call to `simulateValidation(userop)` This method always revert with `ValidationResult` as successful response. If the call reverts with other error, the client rejects this `userOp`. -The simulated call performs the full validation, by -calling: +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`. @@ -311,9 +317,10 @@ We define storage slots as "associated with an address" as all the slots that un In solidity, this includes all storage of the contract itself, and any storage of other contracts that use this contract address as a mapping key. An address `A` is associated with: + 1. Slots of contract `A` address itself. 2. Slot `A` on any other address. -3. Slots of type `keccak256(A || X) + n` on any other address. (to cover `mapping(address => value)`, which is usually used for balance in ERC20 tokens). +3. Slots of type `keccak256(A || X) + n` on any other address. (to cover `mapping(address => value)`, which is usually used for balance in EIP-20 tokens). `n` is an offset value up to 128, to allow accessing fields in the format `mapping(address => struct)` @@ -332,14 +339,14 @@ These UserOperations can be bundled together with UserOperations from the main m ### Bundling During bundling, the client should: -- Exclude UserOps that access any sender address created by another UserOp on the same batch (via a factory). -- For each paymaster used in the batch, keep track of the balance while adding UserOps. Ensure that it has sufficient deposit to pay for all the UserOps that use it. -- Sort UserOps by aggregator, to create the lists of UserOps-per-aggregator. -- For each aggregator, run the aggregator-specific code to create aggregated signature, and update the UserOps +* Exclude UserOps that access any sender address created by another UserOp on the same batch (via a factory). +* For each paymaster used in the batch, keep track of the balance while adding UserOps. Ensure that it has sufficient deposit to pay for all the UserOps that use it. +* Sort UserOps by aggregator, to create the lists of UserOps-per-aggregator. +* For each aggregator, run the aggregator-specific code to create aggregated signature, and update the UserOps After creating the batch, before including the transaction in a block, the client should: -- Run `eth_estimateGas` with maximum possible gas, to verify the entire `handleOps` batch transaction, and use the estimated gas for the actual transaction execution. -- If the call reverted, check the `FailedOp` event. A `FailedOp` during `handleOps` simulation is an unexpected event since it was supposed to be caught by the single-UserOperation simulation. Remove the failed op that caused the revert from the batch and drop from the mempool. Other ops from the same paymaster should be removed from the current batch, but kept in the mempool. Repeat until `eth_estimateGas` succeeds. +* Run `eth_estimateGas` with maximum possible gas, to verify the entire `handleOps` batch transaction, and use the estimated gas for the actual transaction execution. +* If the call reverted, check the `FailedOp` event. A `FailedOp` during `handleOps` simulation is an unexpected event since it was supposed to be caught by the single-UserOperation simulation. Remove the failed op that caused the revert from the batch and drop from the mempool. Other ops from the same paymaster should be removed from the current batch, but kept in the mempool. Repeat until `eth_estimateGas` succeeds. In practice, restrictions (2) and (3) basically mean that the only external accesses that the account and the paymaster can make are reading code of other contracts if their code is guaranteed to be immutable (eg. this is useful for calling or delegatecalling to libraries). @@ -352,12 +359,14 @@ When a bundler includes a bundle in a block it must ensure that earlier transact The forbidden opcodes are to be forbidden when `depth > 2` (i.e. when it is the factory, account, paymaster, or other contracts called by them that are being executed). They are: `GASPRICE`, `GASLIMIT`, `DIFFICULTY`, `TIMESTAMP`, `BASEFEE`, `BLOCKHASH`, `NUMBER`, `SELFBALANCE`, `BALANCE`, `ORIGIN`, `GAS`, `CREATE`, `COINBASE`, `SELFDESTRUCT`. They should only be forbidden during verification, not execution. These opcodes are forbidden because their outputs may differ between simulation and execution, so simulation of calls using these opcodes does not reliably tell what would happen if these calls are later done on-chain. Exceptions to the forbidden opcodes: + 1. A single `CREATE2` is allowed if `op.initcode.length != 0` and must result in the deployment of a previously-undeployed `UserOperation.sender`. 2. `GAS` is allowed if followed immediately by one of { `CALL`, `DELEGATECALL`, `CALLCODE`, `STATICCALL` }. (that is, making calls is allowed, using `gasleft()` or `gas` opcode directly is forbidden) ### Reputation scoring and throttling/banning for global entities -#### Rationale + +#### Rationale. UserOperation's storage access rules prevent them from interfere with each other. But "global" entities - paymasters, factories and aggregators are accessed by multiple UserOperations, and thus might invalidate multiple previously-valid UserOperations. @@ -374,7 +383,7 @@ The stake is expected to be above MIN_STAKE_VALUE, and unstake delay above MIN_U The value of MIN_UNSTAKE_DELAY is 84600 (one day) The value of MIN_STAKE_VALUE is determined per chain, and specified in the "bundler specification test suite" -#### Specification +#### Specification. In the following specification, "entity" is either address that is explicitly referenced by the UserOperation: sender, factory, paymaster and aggregator. Clients maintain two mappings with a value for staked entities: @@ -421,7 +430,7 @@ Stated in simpler terms, we expect at least `1 / MIN_INCLUSION_RATE_DENOMINATOR` To help make sense of these params, note that a malicious paymaster can at most cause the network (only the p2p network, not the blockchain) to process `BAN_SLACK * MIN_INCLUSION_RATE_DENOMINATOR / 24` non-paying ops per hour. -## Rationale +## Rationale: The main challenge with a purely smart contract wallet based account abstraction system is DoS safety: how can a block builder including an operation make sure that it will actually pay fees, without having to first execute the entire operation? Requiring the block builder to execute the entire operation opens a DoS attack vector, as an attacker could easily send many operations that pretend to pay a fee but then revert at the last moment after a long execution. Similarly, to prevent attackers from cheaply clogging the mempool, nodes in the P2P network need to check if an operation will pay a fee before they are willing to forward it. @@ -433,10 +442,10 @@ The entry point-based approach allows for a clean separation between verificatio Paymasters facilitate transaction sponsorship, allowing third-party-designed mechanisms to pay for transactions. Many of these mechanisms _could_ be done by having the paymaster wrap a `UserOperation` with their own, but there are some important fundamental limitations to that approach: -* No possibility for "passive" paymasters (eg. that accept fees in some ERC-20 token at an exchange rate pulled from an on-chain DEX) +* No possibility for "passive" paymasters (eg. that accept fees in some EIP-20 token at an exchange rate pulled from an on-chain DEX) * Paymasters run the risk of getting griefed, as users could send ops that appear to pay the paymaster but then change their behavior after a block -The paymaster scheme allows a contract to passively pay on users' behalf under arbitrary conditions. It even allows ERC-20 token paymasters to secure a guarantee that they would only need to pay if the user pays them: the paymaster contract can check that there is sufficient approved ERC-20 balance in the `validatePaymasterUserOp` method, and then extract it with `transferFrom` in the `postOp` call; if the op itself transfers out or de-approves too much of the ERC-20s, the inner `postOp` will fail and revert the execution and the outer `postOp` can extract payment (note that because of storage access restrictions the ERC-20 would need to be a wrapper defined within the paymaster itself). +The paymaster scheme allows a contract to passively pay on users' behalf under arbitrary conditions. It even allows EIP-20 token paymasters to secure a guarantee that they would only need to pay if the user pays them: the paymaster contract can check that there is sufficient approved EIP-20 balance in the `validatePaymasterUserOp` method, and then extract it with `transferFrom` in the `postOp` call; if the op itself transfers out or de-approves too much of the EIP-20s, the inner `postOp` will fail and revert the execution and the outer `postOp` can extract payment (note that because of storage access restrictions the EIP-20 would need to be a wrapper defined within the paymaster itself). ### First-time account creation @@ -465,6 +474,7 @@ Accounts are encouraged to be DELEGATECALL forwarding contracts for gas efficien ## RPC methods ### eth Namespace + #### * eth_sendUserOperation eth_sendUserOperation submits a User Operation object to the User Operation pool of the client. The client MUST validate the UserOperation, and return a result accordingly. @@ -472,10 +482,12 @@ eth_sendUserOperation submits a User Operation object to the User Operation pool The result `SHOULD` be set to the **userOpHash** if and only if the request passed simulation and was accepted in the client's User Operation pool. If the validation, simulation, or User Operation pool inclusion fails, `result` `SHOULD NOT` be returned. Rather, the client `SHOULD` return the failure reason. ##### Parameters: + 1. **UserOperation** a full user-operation struct. All fields MUST be set as hex values. empty `bytes` block (e.g. empty `initCode`) MUST be set to `"0x"` 2. **EntryPoint** the entrypoint address the request should be sent through. this MUST be one of the entry points returned by the `supportedEntryPoints` rpc call. ##### Return value: + * If the UserOperation is valid, the client MUST return the calculated **userOpHash** for it * in case of failure, MUST return an `error` result object, with `code` and `message`. The error code and message SHOULD be set as follows: * **code: -32602** - invalid UserOperation struct/fields @@ -497,7 +509,9 @@ The result `SHOULD` be set to the **userOpHash** if and only if the request pass * The `data` field SHOULD contain an `aggregator` value ##### Example: + Request: + ```json= { "jsonrpc": "2.0", @@ -522,7 +536,9 @@ Request: } ``` + Response: + ``` { "jsonrpc": "2.0", @@ -532,6 +548,7 @@ Response: ``` ##### Example failure responses: + ```json { "jsonrpc": "2.0", @@ -571,12 +588,14 @@ Still, it might require putting a "semi-valid" signature (e.g. a signature in th gas limits (and prices) parameters are optional, but are used if specified. `maxFeePerGas` and `maxPriorityFeePerGas` default to zero, so no payment is required by neither account nor paymaster. -##### Return Values: +**Return Values:** + * **preVerificationGas** gas overhead of this UserOperation * **verificationGasLimit** actual gas used by the validation of this UserOperation * **callGasLimit** value used by inner account execution ##### Error Codes: + Same as `eth_sendUserOperation` This operation may also return an error if the inner call to the account contract reverts. @@ -585,6 +604,7 @@ This operation may also return an error if the inner call to the account contrac Return a UserOperation based on a hash (userOpHash) returned by `eth_sendUserOperation` **Parameters** + * **hash** a userOpHash value returned by `eth_sendUserOperation` **Return value**: @@ -596,6 +616,7 @@ Return a UserOperation based on a hash (userOpHash) returned by `eth_sendUserOpe Return a UserOperation receipt based on a hash (userOpHash) returned by `eth_sendUserOperation` **Parameters** + * **hash** a userOpHash value returned by `eth_sendUserOperation` **Return value**: @@ -638,9 +659,10 @@ Returns an array of the entryPoint addresses supported by the client. The first ] } ``` + #### * eth_chainId -Returns EIP155 Chain ID. +Returns EIP 155 Chain ID. ```json= # Request @@ -688,11 +710,11 @@ Clears the bundler mempool and reputation data of paymasters/accounts/factories/ Dumps the current UserOperations mempool -##### Parameters: +**Parameters:** -- **EntryPoint** the entrypoint used by eth_sendUserOperation +* **EntryPoint** the entrypoint used by eth_sendUserOperation -##### Returns: +**Returns:** `array` - Array of UserOperations currently in the mempool. @@ -781,16 +803,16 @@ After setting mode to "manual", an explicit call to debug_bundler_sendBundleNow Sets reputation of given addresses. parameters: -##### Parameters: +**Parameters:** -- An array of reputation entries to add/replace, with the fields: +* An array of reputation entries to add/replace, with the fields: - - `address` - The address to set the reputation for. - - `opsSeen` - number of times a user operations with that entity was seen and added to the mempool - - `opsIncluded` - number of times a user operations that uses this entity was included on-chain - - `status` - (string) The status of the address in the bundler 'ok' | 'throttled' | 'banned'. + * `address` - The address to set the reputation for. + * `opsSeen` - number of times a user operations with that entity was seen and added to the mempool + * `opsIncluded` - number of times a user operations that uses this entity was included on-chain + * `status` - (string) The status of the address in the bundler 'ok' | 'throttled' | 'banned'. -- **EntryPoint** the entrypoint used by eth_sendUserOperation +* **EntryPoint** the entrypoint used by eth_sendUserOperation ```json= # Request @@ -825,18 +847,18 @@ Returns the reputation data of all observed addresses. Returns an array of reputation objects, each with the fields described above in `debug_bundler_setReputation` with the -##### Parameters: +**Parameters:** -- **EntryPoint** the entrypoint used by eth_sendUserOperation +* **EntryPoint** the entrypoint used by eth_sendUserOperation -##### Return value: +**Return value:** An array of reputation entries with the fields: -- `address` - The address to set the reputation for. -- `opsSeen` - number of times a user operations with that entity was seen and added to the mempool -- `opsIncluded` - number of times a user operations that uses this entity was included on-chain -- `status` - (string) The status of the address in the bundler 'ok' | 'throttled' | 'banned'. +* `address` - The address to set the reputation for. +* `opsSeen` - number of times a user operations with that entity was seen and added to the mempool +* `opsIncluded` - number of times a user operations that uses this entity was included on-chain +* `status` - (string) The status of the address in the bundler 'ok' | 'throttled' | 'banned'. ```json= # Request @@ -863,15 +885,15 @@ An array of reputation entries with the fields: ## Backwards Compatibility -This ERC does not change the consensus layer, so there are no backwards compatibility issues for Ethereum as a whole. Unfortunately it is not easily compatible with pre-ERC-4337 accounts, because those accounts do not have a `validateUserOp` function. If the account has a function for authorizing a trusted op submitter, then this could be fixed by creating an ERC-4337-compatible account that re-implements the verification logic as a wrapper and setting it to be the original account's trusted op submitter. +This EIP does not change the consensus layer, so there are no backwards compatibility issues for Ethereum as a whole. Unfortunately it is not easily compatible with pre-EIP-4337 accounts, because those accounts do not have a `validateUserOp` function. If the account has a function for authorizing a trusted op submitter, then this could be fixed by creating an EIP-4337-compatible account that re-implements the verification logic as a wrapper and setting it to be the original account's trusted op submitter. ## Reference Implementation -See [https://github.com/eth-infinitism/account-abstraction/tree/main/contracts](https://github.com/eth-infinitism/account-abstraction/tree/main/contracts) +See `https://github.com/eth-infinitism/account-abstraction/tree/main/contracts` -## Security considerations +## Security Considerations -The entry point contract will need to be very heavily audited and formally verified, because it will serve as a central trust point for _all_ ERC 4337 accounts. In total, this architecture reduces auditing and formal verification load for the ecosystem, because the amount of work that individual _accounts_ have to do becomes much smaller (they need only verify the `validateUserOp` function and its "check signature, increment nonce and pay fees" logic) and check that other functions are `msg.sender == ENTRY_POINT` gated (perhaps also allowing `msg.sender == self`), but it is nevertheless the case that this is done precisely by concentrating security risk in the entry point contract that needs to be verified to be very robust. +The entry point contract will need to be very heavily audited and formally verified, because it will serve as a central trust point for _all_ [EIP-4337](./eip-4337.md). In total, this architecture reduces auditing and formal verification load for the ecosystem, because the amount of work that individual _accounts_ have to do becomes much smaller (they need only verify the `validateUserOp` function and its "check signature, increment nonce and pay fees" logic) and check that other functions are `msg.sender == ENTRY_POINT` gated (perhaps also allowing `msg.sender == self`), but it is nevertheless the case that this is done precisely by concentrating security risk in the entry point contract that needs to be verified to be very robust. Verification would need to cover two primary claims (not including claims needed to protect paymasters, and claims needed to establish p2p-level DoS resistance): @@ -879,4 +901,5 @@ Verification would need to cover two primary claims (not including claims needed * **Safety against fee draining**: If the entry point calls `validateUserOp` and passes, it also must make the generic call with calldata equal to `op.calldata` ## Copyright -Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). + +Copyright and related rights waived via [CC0](../LICENSE.md).