From c63daef55fb2630632783da02a95a26c2cda08ff Mon Sep 17 00:00:00 2001 From: Alex Forshtat Date: Fri, 23 Aug 2024 01:32:23 +0200 Subject: [PATCH 1/4] Initial commit for new JSON-RPC API ERC --- ERCS/erc-4337-rpc.md | 491 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 491 insertions(+) create mode 100644 ERCS/erc-4337-rpc.md diff --git a/ERCS/erc-4337-rpc.md b/ERCS/erc-4337-rpc.md new file mode 100644 index 0000000000..01c9435740 --- /dev/null +++ b/ERCS/erc-4337-rpc.md @@ -0,0 +1,491 @@ +--- +eip: +title: JSON-RPC API for Account Abstraction Using the UserOperation Mempool +description: A set of JSON-RPC API methods that defines a communication between smart contract account wallets and bundlers +author: Vitalik Buterin (@vbuterin), Yoav Weiss (@yoavw), Dror Tirosh (@drortirosh), Shahaf Nacson (@shahafn), Alex Forshtat (@forshtat), Kristof Gazso (@kristofgazso), Tjaden Hess (@tjade273) +discussions-to: +status: Draft +type: Standards Track +category: ERC +created: +requires: 4337, 7562 +--- + +## Abstract + +## Motivation + +## Specification + +### 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. + +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. **factory** and **factoryData** - either both exist, or none +3. paymaster fields (**paymaster**, **paymasterData**, **paymasterValidationGasLimit**, **paymasterPostOpGasLimit**) either all exist, or none. +4. **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 + * **code: -32500** - transaction rejected by entryPoint's simulateValidation, during wallet creation or validation + * The `message` field MUST be set to the FailedOp's "`AAxx`" error message from the EntryPoint + * **code: -32501** - transaction rejected by paymaster's validatePaymasterUserOp + * The `message` field SHOULD be set to the revert message from the paymaster + * The `data` field MUST contain a `paymaster` value + * **code: -32502** - transaction rejected because of opcode validation + * **code: -32503** - UserOperation out of time-range: either wallet or paymaster returned a time-range, and it has already expired (or will expire soon) + * The `data` field SHOULD contain the `validUntil` and `validAfter` values + * The `data` field SHOULD contain a `paymaster` value, if this error was triggered by the paymaster + * **code: -32504** - transaction rejected because paymaster is throttled/banned + * The `data` field SHOULD contain a `paymaster` value, depending on the failed entity + * **code: -32505** - transaction rejected because paymaster stake or unstake-delay is too low + * The `data` field SHOULD contain a `paymaster` value, depending on the failed entity + * The `data` field SHOULD contain a `minimumStake` and `minimumUnstakeDelay` + * **code: -32507** - transaction rejected because of wallet signature check failed (or paymaster signature, if the paymaster uses its data as signature) + * **code: -32508** - transaction rejected because paymaster balance can't cover all pending UserOperations. + +##### Example: + +Request: + +```json= +{ + "jsonrpc": "2.0", + "id": 1, + "method": "eth_sendUserOperation", + "params": [ + { + sender, // address + nonce, // uint256 + factory, // address + factoryData, // bytes + callData, // bytes + callGasLimit, // uint256 + verificationGasLimit, // uint256 + preVerificationGas, // uint256 + maxFeePerGas, // uint256 + maxPriorityFeePerGas, // uint256 + paymaster, // address + paymasterVerificationGasLimit, // uint256 + paymasterPostOpGasLimit, // uint256 + paymasterData, // bytes + signature // bytes + }, + entryPoint // address + ] +} + +``` + +Response: + +``` +{ + "jsonrpc": "2.0", + "id": 1, + "result": "0x1234...5678" +} +``` + +##### Example failure responses: + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "error": { + "message": "AA21 didn't pay prefund", + "code": -32500 + } +} +``` + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "error": { + "message": "paymaster stake too low", + "data": { + "paymaster": "0x123456789012345678901234567890123456790", + "minimumStake": "0xde0b6b3a7640000", + "minimumUnstakeDelay": "0x15180" + }, + "code": -32504 + } +} +``` + + +#### * eth_estimateUserOperationGas + +Estimate the gas values for a UserOperation. +Given UserOperation optionally without gas limits and gas prices, return the needed gas limits. +The signature field is ignored by the wallet, so that the operation will not require the user's approval. +Still, it might require putting a "semi-valid" signature (e.g. a signature in the right length) + +**Parameters**: +* Same as `eth_sendUserOperation`\ + 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. +* Optionally accepts the `State Override Set` to allow users to modify the state during the gas estimation.\ + This field as well as its behavior is equivalent to the ones defined for `eth_call` RPC method. + + +**Return Values:** + +* **preVerificationGas** gas overhead of this UserOperation +* **verificationGasLimit** estimation of gas limit required by the validation of this UserOperation +* **paymasterVerificationGasLimit** estimation of gas limit required by the paymaster verification, if the + UserOperation defines a Paymaster address +* **callGasLimit** estimation of gas limit required by the inner account execution + +**Note:** actual `postOpGasLimit` cannot be reliably estimated. Paymasters should provide this value to account, +and require that specific value on-chain. + +##### Error Codes: + +Same as `eth_sendUserOperation` +This operation may also return an error if either the inner call to the account contract reverts, +or paymaster's `postOp` call reverts. + +#### * eth_getUserOperationByHash + +Return a UserOperation based on a hash (userOpHash) returned by `eth_sendUserOperation` + +**Parameters** + +* **hash** a userOpHash value returned by `eth_sendUserOperation` + +**Return value**: + +* If the UserOperation is included in a block: + * Return a full UserOperation, with the addition of `entryPoint`, `blockNumber`, `blockHash` and `transactionHash`. + +* Else if the UserOperation is pending in the bundler's mempool: + * MAY return `null`, or: a full UserOperation, with the addition of the `entryPoint` field and a `null` value for `blockNumber`, `blockHash` and `transactionHash`. + +* Else: + * Return `null` + +#### * eth_getUserOperationReceipt + +Return a UserOperation receipt based on a hash (userOpHash) returned by `eth_sendUserOperation` + +**Parameters** + +* **hash** a userOpHash value returned by `eth_sendUserOperation` + +**Return value**: + +`null` in case the UserOperation is not yet included in a block, or: + +* **userOpHash** the request hash +* **entryPoint** +* **sender** +* **nonce** +* **paymaster** the paymaster used for this userOp (or empty) +* **actualGasCost** - the actual amount paid (by account or paymaster) for this UserOperation +* **actualGasUsed** - total gas used by this UserOperation (including preVerification, creation, validation and execution) +* **success** boolean - did this execution completed without a revert +* **reason** in case of revert, this is the revert reason +* **logs** the logs generated by this UserOperation (not including logs of other UserOperations in the same bundle) +* **receipt** the TransactionReceipt object. + Note that the returned TransactionReceipt is for the entire bundle, not only for this UserOperation. + +#### * eth_supportedEntryPoints + +Returns an array of the entryPoint addresses supported by the client. The first element of the array `SHOULD` be the entryPoint addressed preferred by the client. + +```json= +# Request +{ + "jsonrpc": "2.0", + "id": 1, + "method": "eth_supportedEntryPoints", + "params": [] +} + +# Response +{ + "jsonrpc": "2.0", + "id": 1, + "result": [ + "0xcd01C8aa8995A59eB7B2627E69b40e0524B5ecf8", + "0x7A0A0d159218E6a2f407B99173A2b12A6DDfC2a6" + ] +} +``` + +#### * eth_chainId + +Returns [EIP-155](./eip-155.md) Chain ID. + +```json= +# Request +{ + "jsonrpc": "2.0", + "id": 1, + "method": "eth_chainId", + "params": [] +} + +# Response +{ + "jsonrpc": "2.0", + "id": 1, + "result": "0x1" +} +``` + +### RPC methods (debug Namespace) + +This api must only be available in testing mode and is required by the compatibility test suite. In production, any `debug_*` rpc calls should be blocked. + +#### * debug_bundler_clearState + +Clears the bundler mempool and reputation data of paymasters/accounts/factories. + +```json= +# Request +{ + "jsonrpc": "2.0", + "id": 1, + "method": "debug_bundler_clearState", + "params": [] +} + +# Response +{ + "jsonrpc": "2.0", + "id": 1, + "result": "ok" +} +``` + +#### * debug_bundler_dumpMempool + +Dumps the current UserOperations mempool + +**Parameters:** + +* **EntryPoint** the entrypoint used by eth_sendUserOperation + +**Returns:** + +`array` - Array of UserOperations currently in the mempool. + +```json= +# Request +{ + "jsonrpc": "2.0", + "id": 1, + "method": "debug_bundler_dumpMempool", + "params": ["0x1306b01bC3e4AD202612D3843387e94737673F53"] +} + +# Response +{ + "jsonrpc": "2.0", + "id": 1, + "result": [ + { + sender, // address + nonce, // uint256 + factory, // address + factoryData, // bytes + callData, // bytes + callGasLimit, // uint256 + verificationGasLimit, // uint256 + preVerificationGas, // uint256 + maxFeePerGas, // uint256 + maxPriorityFeePerGas, // uint256 + signature // bytes + } + ] +} +``` + +#### * debug_bundler_sendBundleNow + +Forces the bundler to build and execute a bundle from the mempool as `handleOps()` transaction. + +Returns: `transactionHash` + +```json= +# Request +{ + "jsonrpc": "2.0", + "id": 1, + "method": "debug_bundler_sendBundleNow", + "params": [] +} + +# Response +{ + "jsonrpc": "2.0", + "id": 1, + "result": "0xdead9e43632ac70c46b4003434058b18db0ad809617bd29f3448d46ca9085576" +} +``` + +#### * debug_bundler_setBundlingMode + +Sets bundling mode. + +After setting mode to "manual", an explicit call to debug_bundler_sendBundleNow is required to send a bundle. + +##### parameters: + +`mode` - 'manual' | 'auto' + +```json= +# Request +{ + "jsonrpc": "2.0", + "id": 1, + "method": "debug_bundler_setBundlingMode", + "params": ["manual"] +} + +# Response +{ + "jsonrpc": "2.0", + "id": 1, + "result": "ok" +} +``` + +#### * debug_bundler_setReputation + +Sets the reputation of given addresses. parameters: + +**Parameters:** + +* 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 user operations that use this entity was included on-chain + +* **EntryPoint** the entrypoint used by eth_sendUserOperation + +```json= +# Request +{ + "jsonrpc": "2.0", + "id": 1, + "method": "debug_bundler_setReputation", + "params": [ + [ + { + "address": "0x7A0A0d159218E6a2f407B99173A2b12A6DDfC2a6", + "opsSeen": "0x14", + "opsIncluded": "0x0D" + } + ], + "0x1306b01bC3e4AD202612D3843387e94737673F53" + ] +} + +# Response +{ + "jsonrpc": "2.0", + "id": 1, + "result": "ok" +} +``` + + +#### * debug_bundler_dumpReputation + +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:** + +* **EntryPoint** the entrypoint used by eth_sendUserOperation + +**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 user operation that use this entity was included on-chain +* `status` - (string) The status of the address in the bundler 'ok' | 'throttled' | 'banned'. + +```json= +# Request +{ + "jsonrpc": "2.0", + "id": 1, + "method": "debug_bundler_dumpReputation", + "params": ["0x1306b01bC3e4AD202612D3843387e94737673F53"] +} + +# Response +{ + "jsonrpc": "2.0", + "id": 1, + "result": [ + { "address": "0x7A0A0d159218E6a2f407B99173A2b12A6DDfC2a6", + "opsSeen": "0x14", + "opsIncluded": "0x13", + "status": "ok" + } + ] +} +``` + +#### * debug_bundler_addUserOps + +Accept UserOperations into the mempool. +Assume the given UserOperations all pass validation (without actually validating them), and accept them directly into the mempool + +**Parameters:** + +* An array of UserOperations + +```json= +# Request +{ + "jsonrpc": "2.0", + "id": 1, + "method": "debug_bundler_addUserOps", + "params": [ + [ + { sender: "0xa...", ... }, + { sender: "0xb...", ... } + ] + ] +} + +# Response +{ + "jsonrpc": "2.0", + "id": 1, + "result": "ok" +} +``` + +## Backwards Compatibility + +## Reference Implementation + +## Security Considerations + +## Copyright + +Copyright and related rights waived via [CC0](../LICENSE.md). From b80687b2f3b7822a422432e2f3e6ed5a20d6c904 Mon Sep 17 00:00:00 2001 From: Alex Forshtat Date: Fri, 23 Aug 2024 13:34:39 +0200 Subject: [PATCH 2/4] Fill in the ERC --- ERCS/erc-4337-rpc.md | 177 +++++++++++++++++++++++++++---------------- 1 file changed, 111 insertions(+), 66 deletions(-) diff --git a/ERCS/erc-4337-rpc.md b/ERCS/erc-4337-rpc.md index 01c9435740..a120fd1485 100644 --- a/ERCS/erc-4337-rpc.md +++ b/ERCS/erc-4337-rpc.md @@ -13,46 +13,72 @@ requires: 4337, 7562 ## Abstract +Defines new JSON-RPC API methods which enable [ERC-4337](./eip-4337) wallets to communicate with `UserOpeation` mempool +nodes and bundlers, matching the functionality that exists for Ethereum transactions. + +Additionally, a set of `debug` JSON-RPC API methods is defined in order to facilitate development, testing and +debugging issues with ERC-4337 implementations. + ## Motivation +In ERC-4337, user transactions as defined in Ethereum are replaced with `UserOperation` objects, which contain all the +information needed to perform the operations requested by the users. + +However, existing Ethereum JSON-RPC API methods are not suited to working with `UserOperation` objects. +In order to facilitate the operation of the alternative `UserOperation` mempool it is important that all +implementations of the ERC-4337 protocol have a standardized set of APIs that can be used interchangeably. + ## Specification ### RPC methods (eth namespace) -#### * eth_sendUserOperation +#### 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. +The `eth_sendUserOperation` method submits a `UserOperation` object to the UserOperation mempool of the client. +The client MUST validate the `UserOperation`, and return a result accordingly. -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. +The result SHOULD be set to the `userOpHash` if and only if the request passed simulation and was accepted +in the client's UserOperation pool. + +If the validation, simulation, or UserOperation pool inclusion fails, +`userOpHash` 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. **factory** and **factoryData** - either both exist, or none -3. paymaster fields (**paymaster**, **paymasterData**, **paymasterValidationGasLimit**, **paymasterPostOpGasLimit**) either all exist, or none. -4. **EntryPoint** the entrypoint address the request should be sent through. this MUST be one of the entry points returned by the `supportedEntryPoints` rpc call. +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. **factory** and **factoryData**\ + Must provide either both of these parameters, or none. +3. **paymaster**, **paymasterData**, **paymasterValidationGasLimit**, **paymasterPostOpGasLimit**\ + Must provide either all of these parameters, or none. +4. **entryPoint** the `EntryPoint` contract 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 - * **code: -32500** - transaction rejected by entryPoint's simulateValidation, during wallet creation or validation - * The `message` field MUST be set to the FailedOp's "`AAxx`" error message from the EntryPoint - * **code: -32501** - transaction rejected by paymaster's validatePaymasterUserOp - * The `message` field SHOULD be set to the revert message from the paymaster +* 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 + * **code: -32500** - transaction rejected by `EntryPoint` contract's `simulateValidation` function + during wallet creation or validation + * The `message` field MUST be set to the emitted `FailedOp` event's "`AAxx`" error message from the `EntryPoint` + * **code: -32501** - transaction rejected by `paymaster` contract's `validatePaymasterUserOp` function + * The `message` field SHOULD be set to the revert message from the `paymaster` contract * The `data` field MUST contain a `paymaster` value - * **code: -32502** - transaction rejected because of opcode validation - * **code: -32503** - UserOperation out of time-range: either wallet or paymaster returned a time-range, and it has already expired (or will expire soon) + * **code: -32502** - transaction rejected because of [ERC-7562](./eip-7562) opcode validation rule violation + * **code: -32503** - UserOperation out of time-range:\ + either wallet or paymaster returned a time-range, and it has already expired or will expire soon. * The `data` field SHOULD contain the `validUntil` and `validAfter` values - * The `data` field SHOULD contain a `paymaster` value, if this error was triggered by the paymaster - * **code: -32504** - transaction rejected because paymaster is throttled/banned - * The `data` field SHOULD contain a `paymaster` value, depending on the failed entity - * **code: -32505** - transaction rejected because paymaster stake or unstake-delay is too low - * The `data` field SHOULD contain a `paymaster` value, depending on the failed entity + * The `data` field SHOULD contain a `paymaster` address if this error was triggered by the `paymaster` contract + * **code: -32504** - transaction rejected because `paymaster` is throttled or banned due to ERC-7562 reputation rules + * The `data` field SHOULD contain a `paymaster` address + * **code: -32505** - transaction rejected because `paymaster` contract's ERC-7562 stake or unstake-delay is too low + * The `data` field SHOULD contain a `paymaster` address * The `data` field SHOULD contain a `minimumStake` and `minimumUnstakeDelay` - * **code: -32507** - transaction rejected because of wallet signature check failed (or paymaster signature, if the paymaster uses its data as signature) - * **code: -32508** - transaction rejected because paymaster balance can't cover all pending UserOperations. + * **code: -32507** - transaction rejected because of wallet signature check failed + * **code: -32508** - transaction rejected because paymaster balance can't cover all pending `UserOperations`. ##### Example: @@ -126,17 +152,16 @@ Response: } ``` - #### * eth_estimateUserOperationGas -Estimate the gas values for a UserOperation. -Given UserOperation optionally without gas limits and gas prices, return the needed gas limits. +Estimate the gas values for a `UserOperation`. +Given `UserOperation` optionally without gas limits and gas prices, return the needed gas limits. The signature field is ignored by the wallet, so that the operation will not require the user's approval. -Still, it might require putting a "semi-valid" signature (e.g. a signature in the right length) +Still, it might require putting a "stub" `signature` value, e.g. a `signature` byte array of the right length. **Parameters**: * Same as `eth_sendUserOperation`\ - gas limits (and prices) parameters are optional, but are used if specified. + All gas limits and fees parameters are optional, but are used if specified.\ `maxFeePerGas` and `maxPriorityFeePerGas` default to zero, so no payment is required by neither account nor paymaster. * Optionally accepts the `State Override Set` to allow users to modify the state during the gas estimation.\ This field as well as its behavior is equivalent to the ones defined for `eth_call` RPC method. @@ -144,14 +169,14 @@ Still, it might require putting a "semi-valid" signature (e.g. a signature in th **Return Values:** -* **preVerificationGas** gas overhead of this UserOperation -* **verificationGasLimit** estimation of gas limit required by the validation of this UserOperation -* **paymasterVerificationGasLimit** estimation of gas limit required by the paymaster verification, if the - UserOperation defines a Paymaster address +* **preVerificationGas** gas overhead of this `UserOperation` +* **verificationGasLimit** estimation of gas limit required by the validation of this `UserOperation` +* **paymasterVerificationGasLimit** estimation of gas limit required by the paymaster verification\ + Returned only if the `UserOperation` specifies a `Paymaster` address * **callGasLimit** estimation of gas limit required by the inner account execution -**Note:** actual `postOpGasLimit` cannot be reliably estimated. Paymasters should provide this value to account, -and require that specific value on-chain. +**Note:** actual `postOpGasLimit` cannot be reliably estimated.\ +Paymasters should provide this value to account, and require that specific value on-chain during validation. ##### Error Codes: @@ -161,51 +186,52 @@ or paymaster's `postOp` call reverts. #### * eth_getUserOperationByHash -Return a UserOperation based on a hash (userOpHash) returned by `eth_sendUserOperation` +Return a `UserOperation`object based on a `userOpHash` value returned by `eth_sendUserOperation`. **Parameters** -* **hash** a userOpHash value returned by `eth_sendUserOperation` +* **hash** a `userOpHash` value returned by `eth_sendUserOperation` **Return value**: -* If the UserOperation is included in a block: +* If the `UserOperation` is included in a block: * Return a full UserOperation, with the addition of `entryPoint`, `blockNumber`, `blockHash` and `transactionHash`. -* Else if the UserOperation is pending in the bundler's mempool: - * MAY return `null`, or: a full UserOperation, with the addition of the `entryPoint` field and a `null` value for `blockNumber`, `blockHash` and `transactionHash`. +* Else if the `UserOperation` is pending in the bundler's mempool: + * MAY return `null`, or a full `UserOperation`, with the addition of the `entryPoint` field and a `null` value for `blockNumber`, `blockHash` and `transactionHash`. * Else: * Return `null` #### * eth_getUserOperationReceipt -Return a UserOperation receipt based on a hash (userOpHash) returned by `eth_sendUserOperation` +Return a `UserOperation` receipt object based on a `userOpHash` value returned by `eth_sendUserOperation`. **Parameters** -* **hash** a userOpHash value returned by `eth_sendUserOperation` +* **hash** a `userOpHash` value returned by `eth_sendUserOperation` **Return value**: -`null` in case the UserOperation is not yet included in a block, or: +`null` in case the `UserOperation` is not yet included in a block, or: * **userOpHash** the request hash * **entryPoint** * **sender** * **nonce** * **paymaster** the paymaster used for this userOp (or empty) -* **actualGasCost** - the actual amount paid (by account or paymaster) for this UserOperation -* **actualGasUsed** - total gas used by this UserOperation (including preVerification, creation, validation and execution) -* **success** boolean - did this execution completed without a revert -* **reason** in case of revert, this is the revert reason -* **logs** the logs generated by this UserOperation (not including logs of other UserOperations in the same bundle) -* **receipt** the TransactionReceipt object. - Note that the returned TransactionReceipt is for the entire bundle, not only for this UserOperation. +* **actualGasCost** - the actual amount paid (by account or paymaster) for this `UserOperation` +* **actualGasUsed** - total gas used by this `UserOperation`, including pre-verification, creation, validation and execution +* **success** boolean - whether this execution completed without a revert +* **reason** - in case of reverted `UserOperation`, the returned revert reason byte array +* **logs** - the logs generated by this particular `UserOperation`, not including logs of other `UserOperations` in the same bundle +* **receipt** the `TransactionReceipt` object. + Note that the returned `TransactionReceipt` is for the entire bundle, not only for this `UserOperation`. #### * eth_supportedEntryPoints -Returns an array of the entryPoint addresses supported by the client. The first element of the array `SHOULD` be the entryPoint addressed preferred by the client. +Returns an array of the `EntryPoint` contracts' addresses supported by the client. +The first element of the array `SHOULD` be the `EntryPoint` contract addressed preferred by the client. ```json= # Request @@ -250,7 +276,8 @@ Returns [EIP-155](./eip-155.md) Chain ID. ### RPC methods (debug Namespace) -This api must only be available in testing mode and is required by the compatibility test suite. In production, any `debug_*` rpc calls should be blocked. +This api must only be available in testing mode and is required by the compatibility test suite. +In production, any `debug_*` rpc calls should be blocked. #### * debug_bundler_clearState @@ -275,15 +302,15 @@ Clears the bundler mempool and reputation data of paymasters/accounts/factories. #### * debug_bundler_dumpMempool -Dumps the current UserOperations mempool +Dumps the current `UserOperation` mempool **Parameters:** -* **EntryPoint** the entrypoint used by eth_sendUserOperation +* **EntryPoint** the entrypoint used by `eth_sendUserOperation` **Returns:** -`array` - Array of UserOperations currently in the mempool. +`array` - Array of `UserOperation` objects currently in the mempool. ```json= # Request @@ -343,7 +370,7 @@ Returns: `transactionHash` Sets bundling mode. -After setting mode to "manual", an explicit call to debug_bundler_sendBundleNow is required to send a bundle. +After setting mode to "manual", an explicit call to `debug_bundler_sendBundleNow` is required to send a bundle. ##### parameters: @@ -368,17 +395,17 @@ After setting mode to "manual", an explicit call to debug_bundler_sendBundleNow #### * debug_bundler_setReputation -Sets the reputation of given addresses. parameters: +Sets the reputation of given addresses. **Parameters:** * An array of reputation entries to add/replace, with the fields: - * `address` - The address to set the reputation for. + * `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 user operations that use this entity was included on-chain -* **EntryPoint** the entrypoint used by eth_sendUserOperation +* **EntryPoint** the entrypoint used by `eth_sendUserOperation` ```json= # Request @@ -410,21 +437,20 @@ Sets the reputation of given addresses. parameters: #### * debug_bundler_dumpReputation 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 - +Returns an array of reputation objects, each with the fields described above in `debug_bundler_setReputation`. **Parameters:** -* **EntryPoint** the entrypoint used by eth_sendUserOperation +* **EntryPoint** the entrypoint used by `eth_sendUserOperation` **Return value:** An array of reputation entries with the fields: -* `address` - The address to set the reputation for. +* `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 user operation that use this entity was included on-chain -* `status` - (string) The status of the address in the bundler 'ok' | 'throttled' | 'banned'. +* `status` - (string) The status of the address in the bundler (`'ok'` | `'throttled'` | `'banned'`) ```json= # Request @@ -451,12 +477,13 @@ An array of reputation entries with the fields: #### * debug_bundler_addUserOps -Accept UserOperations into the mempool. -Assume the given UserOperations all pass validation (without actually validating them), and accept them directly into the mempool +Inject `UserOperation` objects array into the mempool. +Assume the given `UserOperation` objects all pass validation without actually validating them, +and accept them directly into the mempool. **Parameters:** -* An array of UserOperations +* An array of `UserOperation` objects ```json= # Request @@ -482,10 +509,28 @@ Assume the given UserOperations all pass validation (without actually validating ## Backwards Compatibility +This proposal defines a new JSON-RPC API standard that does not pose any backwards compatibility challenges. + ## Reference Implementation +See `https://github.com/eth-infinitism/bundler` + ## Security Considerations +### Preventing DoS attacks on UserOperation mempool + +Operating a public production ERC-4337 node is a computationally intensive task and may be a target of a DoS attack. +This is addressed by the ERC-7562 validation rules, which defines a way for the ERC-4337 node to track participants' +reputation as well as preventing nodes from accepting maliciously crafted `UserOperations`. + +It is strictly recommended that all ERC-4337 nodes also implement ERC-7562 validation rules to minimize DoS risks. + +### Disabling `debug` API in production servers + +The API defined in the `debug` namespace is not intended to ever be publicly available. +Production implementations of ERC-4337 must never make it available by default, +and in fact enabling it should result in a clear warning of the potential dangers of exposing this API. + ## Copyright Copyright and related rights waived via [CC0](../LICENSE.md). From 2cea7af7a40921517ac6a345df31fc3d543bdd31 Mon Sep 17 00:00:00 2001 From: Alex Forshtat Date: Sun, 8 Sep 2024 11:06:33 +0200 Subject: [PATCH 3/4] Address PR comments --- ERCS/erc-4337-rpc.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ERCS/erc-4337-rpc.md b/ERCS/erc-4337-rpc.md index a120fd1485..13bd5fdd56 100644 --- a/ERCS/erc-4337-rpc.md +++ b/ERCS/erc-4337-rpc.md @@ -30,11 +30,17 @@ implementations of the ERC-4337 protocol have a standardized set of APIs that ca ## Specification +### Definitions + +* **bundler**: a node exposing the APIs, in order to submit them to the network. + A bundler collects one or more UserOperations into a bundle and submits them together to + the `EntryPoint` in a single `handleUserOp` call. + ### RPC methods (eth namespace) #### eth_sendUserOperation -The `eth_sendUserOperation` method submits a `UserOperation` object to the UserOperation mempool of the client. +The `eth_sendUserOperation` method submits a `UserOperation` object to the UserOperation mempool. The client MUST validate the `UserOperation`, and return a result accordingly. The result SHOULD be set to the `userOpHash` if and only if the request passed simulation and was accepted From f310120140c7771bb2494e1fcc0c567483ecabad Mon Sep 17 00:00:00 2001 From: shahafn Date: Tue, 10 Sep 2024 17:57:13 +0300 Subject: [PATCH 4/4] Apply suggestions from code review --- ERCS/erc-4337-rpc.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ERCS/erc-4337-rpc.md b/ERCS/erc-4337-rpc.md index 13bd5fdd56..3c9458d300 100644 --- a/ERCS/erc-4337-rpc.md +++ b/ERCS/erc-4337-rpc.md @@ -2,7 +2,7 @@ eip: title: JSON-RPC API for Account Abstraction Using the UserOperation Mempool description: A set of JSON-RPC API methods that defines a communication between smart contract account wallets and bundlers -author: Vitalik Buterin (@vbuterin), Yoav Weiss (@yoavw), Dror Tirosh (@drortirosh), Shahaf Nacson (@shahafn), Alex Forshtat (@forshtat), Kristof Gazso (@kristofgazso), Tjaden Hess (@tjade273) +author: Vitalik Buterin (@vbuterin), Yoav Weiss (@yoavw), Dror Tirosh (@drortirosh), Shahaf Nacson (@shahafn), Alex Forshtat (@forshtat) discussions-to: status: Draft type: Standards Track @@ -34,7 +34,7 @@ implementations of the ERC-4337 protocol have a standardized set of APIs that ca * **bundler**: a node exposing the APIs, in order to submit them to the network. A bundler collects one or more UserOperations into a bundle and submits them together to - the `EntryPoint` in a single `handleUserOp` call. + the `EntryPoint` in a single `handleOps` call. ### RPC methods (eth namespace)