|
| 1 | += Account Abstraction |
| 2 | + |
| 3 | +Unlike Externally Owned Accounts (EOAs), smart contracts may contain arbitrary verification logic based on authentication mechanisms different to Ethereum's native xref:api:utils.adoc#ECDSA[ECDSA] and have execution advantages such as batching or gas sponsorship. To leverage these properties of smart contracts, the community has widely adopted https://eips.ethereum.org/EIPS/eip-4337[ERC-4337], a standard to process user operations through an alternative mempool. |
| 4 | + |
| 5 | +The library provides multiple contracts for Account Abstraction following this standard as it enables more flexible and user-friendly interactions with applications. Account Abstraction use cases include wallets in novel contexts (e.g. embedded wallets), more granular configuration of accounts, and recovery mechanisms. |
| 6 | + |
| 7 | +== ERC-4337 Overview |
| 8 | + |
| 9 | +The ERC-4337 is a detailed specification of how to implement the necessary logic to handle operations without making changes to the protocol level (i.e. the rules of the blockchain itself). This specification defines the following components: |
| 10 | + |
| 11 | +=== UserOperation |
| 12 | + |
| 13 | +A `UserOperation` is a higher-layer pseudo-transaction object that represents the intent of the account. This shares some similarities with regular EVM transactions like the concept of `gasFees` or `callData` but includes fields that enable new capabilities. |
| 14 | + |
| 15 | +```solidity |
| 16 | +struct PackedUserOperation { |
| 17 | + address sender; |
| 18 | + uint256 nonce; |
| 19 | + bytes initCode; // concatenation of factory address and factoryData (or empty) |
| 20 | + bytes callData; |
| 21 | + bytes32 accountGasLimits; // concatenation of verificationGas (16 bytes) and callGas (16 bytes) |
| 22 | + uint256 preVerificationGas; |
| 23 | + bytes32 gasFees; // concatenation of maxPriorityFee (16 bytes) and maxFeePerGas (16 bytes) |
| 24 | + bytes paymasterAndData; // concatenation of paymaster fields (or empty) |
| 25 | + bytes signature; |
| 26 | +} |
| 27 | +``` |
| 28 | + |
| 29 | +This process of bundling user operations involves several costs that the bundler must cover, including base transaction fees, calldata serialization, entrypoint execution, and paymaster context costs. To compensate for these expenses, bundlers use the `preVerificationGas` and `gasFees` fields to charge users appropriately. |
| 30 | + |
| 31 | +NOTE: Estimating `preVerificationGas` is not standardized as it varies based on network conditions such as gas prices and the size of the operation bundle. |
| 32 | + |
| 33 | +TIP: Use xref:api:account.adoc#ERC4337Utils[`ERC4337Utils`] to manipulate the `UserOperation` struct and other ERC-4337 related values. |
| 34 | + |
| 35 | +=== Entrypoint |
| 36 | + |
| 37 | +Each `UserOperation` is executed through a contract known as the https://etherscan.io/address/0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108#code[`EntryPoint`]. This contract is a singleton deployed across multiple networks at the same address although other custom implementations may be used. |
| 38 | + |
| 39 | +The Entrypoint contracts is considered a trusted entity by the account. |
| 40 | + |
| 41 | +=== Bundlers |
| 42 | + |
| 43 | +The bundler is a piece of _offchain_ infrastructure that is in charge of processing an alternative mempool of user operations. Bundlers themselves call the Entrypoint contract's `handleOps` function with an array of UserOperations that are executed and included in a block. |
| 44 | + |
| 45 | +During the process, the bundler pays for the gas of executing the transaction and gets refunded during the execution phase of the Entrypoint contract. |
| 46 | + |
| 47 | +```solidity |
| 48 | +/// @dev Process `userOps` and `beneficiary` receives all |
| 49 | +/// the gas fees collected during the bundle execution. |
| 50 | +function handleOps( |
| 51 | + PackedUserOperation[] calldata ops, |
| 52 | + address payable beneficiary |
| 53 | +) external { ... } |
| 54 | +``` |
| 55 | + |
| 56 | +=== Account Contract |
| 57 | + |
| 58 | +The Account Contract is a smart contract that implements the logic required to validate a `UserOperation` in the context of ERC-4337. Any smart contract account should conform with the `IAccount` interface to validate operations. |
| 59 | + |
| 60 | +```solidity |
| 61 | +interface IAccount { |
| 62 | + function validateUserOp(PackedUserOperation calldata, bytes32, uint256) external returns (uint256 validationData); |
| 63 | +} |
| 64 | +``` |
| 65 | + |
| 66 | +Similarly, an Account should have a way to execute these operations by either handling arbitrary calldata on its `fallback` or implementing the `IAccountExecute` interface: |
| 67 | + |
| 68 | +```solidity |
| 69 | +interface IAccountExecute { |
| 70 | + function executeUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) external; |
| 71 | +} |
| 72 | +``` |
| 73 | + |
| 74 | +NOTE: The `IAccountExecute` interface is optional. Developers might want to use xref:api:account.adoc#ERC7821[`ERC-7821`] for a minimal batched execution interface or rely on ERC-7579 or any other execution logic. |
| 75 | + |
| 76 | +To build your own account, see xref:accounts.adoc[accounts]. |
| 77 | + |
| 78 | +=== Factory Contract |
| 79 | + |
| 80 | +The smart contract accounts are created by a Factory contract defined by the Account developer. This factory receives arbitrary bytes as `initData` and returns an `address` where the logic of the account is deployed. |
| 81 | + |
| 82 | +To build your own factory, see xref:accounts.adoc#accounts_factory[account factories]. |
| 83 | + |
| 84 | +=== Paymaster Contract |
| 85 | + |
| 86 | +A Paymaster is an optional entity that can sponsor gas fees for Accounts, or allow them to pay for those fees in ERC-20 instead of native currency. This abstracts gas away of the user experience in the same way that computational costs of cloud servers are abstracted away from end-users. |
| 87 | + |
| 88 | +To build your own paymaster, see https://docs.openzeppelin.com/community-contracts/0.0.1/paymasters[paymasters]. |
| 89 | + |
| 90 | +== Further notes |
| 91 | + |
| 92 | +=== ERC-7562 Validation Rules |
| 93 | + |
| 94 | +To process a bundle of `UserOperations`, bundlers call xref:api:account.adoc#Account-validateUserOp-struct-PackedUserOperation-bytes32-uint256-[`validateUserOp`] on each operation sender to check whether the operation can be executed. However, the bundler has no guarantee that the state of the blockchain will remain the same after the validation phase. To overcome this problem, https://eips.ethereum.org/EIPS/eip-7562[ERC-7562] proposes a set of limitations to EVM code so that bundlers (or node operators) are protected from unexpected state changes. |
| 95 | + |
| 96 | +These rules outline the requirements for operations to be processed by the canonical mempool. |
| 97 | + |
| 98 | +Accounts can access its own storage during the validation phase, they might easily violate ERC-7562 storage access rules in undirect ways. For example, most accounts access their public keys from storage when validating a signature, limiting the ability of having accounts that validate operations for other accounts (e.g. via ERC-1271) |
| 99 | + |
| 100 | +TIP: Although any Account that breaks such rules may still be processed by a private bundler, developers should keep in mind the centralization tradeoffs of relying on private infrastructure instead of _permissionless_ execution. |
0 commit comments