diff --git a/pages/docs/understanding-ERC-4337/account-contract.md b/pages/docs/understanding-ERC-4337/account-contract.md index 22db01b..917d89d 100644 --- a/pages/docs/understanding-ERC-4337/account-contract.md +++ b/pages/docs/understanding-ERC-4337/account-contract.md @@ -1,35 +1,51 @@ # Account Contract -With EOAs, the address is consistent across all EVM networks. As long as the user has access to the private key they can access the same address on any network. Ideally, we would like to create the same user experience with contract accounts. +In ERC-4337, an account is a contract that is able to hold user assets and interact with contracts on the user's behalf. + +ERC-4337 does not require a specific account contract implementation. However, it does require that account contracts implement a specific interface. +This interface is defined in the [ERC-4337 Specification](https://eips.ethereum.org/EIPS/eip-4337), and contains only a single function, `validateUserOp`, which is used to verify the signature of a `UserOperation`. + +The interface is defined as follows: + +```solidity +import "./PackedUserOperation.sol"; +interface IAccount { + function validateUserOp( + PackedUserOperation calldata userOp, + bytes32 userOpHash, + uint256 missingAccountFunds + ) external returns (uint256 validationData); +} +``` -Users should be able to deterministically know their account address and keep it consistent on every EVM network irrespective of whether the account has been deployed or not. This means that they can generate an account and start sending funds to it with the knowledge that they'll be able to control those funds at any time, provided they have the correct verification method. +The `validateUserOp` function is called by the `EntryPoint` contract to verify the signature of a `UserOperation`. The `UserOperation` is passed as a `PackedUserOperation` object, which is a tightly packed representation of the `UserOperation` object. The `userOpHash` is the hash of the `UserOperation` object, and is used to verify the signature. -ERC-4337 does this by using the `CREATE2` opcode through a [Singleton Factory](https://eips.ethereum.org/EIPS/eip-2470) - the [Account Factory contract](./account-factory-contract.md). -For example, here is how you can calculate a `CREATE2` address with ethers.js: +The `missingAccountFunds` parameter is the amount of funds that are required to be deposited into the `EntryPoint` in order to cover the maximum costs to execute the transaction. This value will be `0` when a paymaster is used. -``` -const accountAddress = ethers.utils.getCreate2Address( - fromAddress, - salt, - initCodeHash -); -``` +## Transaction execution + +ERC-4337 does not require a specific interface for executing transactions. This is because the transaction execution calldata is defined in the `UserOperation` object, and is not dependent on the account contract. -The contract address would be determined by `fromAddress`, `salt`, and `initCodeHash`. +## Authentication and authorization -`fromAddress` -The fromAddress is the address of the Singleton Factory. This factory receives the `salt` and `initCode` as input and uses CREATE2 to deploy the contract on-chain. +The precise mechanism for authentication and authorization is left to the account contract implementation. However, the account contract must be able to verify the signature of a `UserOperation` using the `validateUserOp` function. -Because the Account Factory contract address is the same on every chain, we can rely on it to also deploy our smart contract code on all networks under the same address too. +## Nonces and replay protection -`salt` -For an ERC-4337 account, the salt parameter is the first nonce value. This is most likely 0. +Nonce and replay protection is provided by the EntryPoint and there is no requirement for the Account to implement their own nonce or replay protection. -`initCodeHash` -The initCode is passed along as a field on the UserOperation is the smart contract code and arguments used for initializing it. It is hashed using keccak256 to derive the initCodeHash. +## Sample implementation +The ERC-4337 core team has implemented [`SimpleAccount.sol`](https://github.com/eth-infinitism/account-abstraction/blob/develop/contracts/samples/SimpleAccount.sol), a sample minimal account that extends [`BaseAccount.sol`](https://github.com/eth-infinitism/account-abstraction/blob/develop/contracts/core/BaseAccount.sol), which implements the [`IAccount`](https://github.com/eth-infinitism/account-abstraction/blob/develop/contracts/interfaces/IAccount.sol) interface. +The `SimpleAccount` contract is a minimal account contract that is able to hold user assets and interact with contracts on the user's behalf. It is expected to be deployed as a proxy via the `SimpleAccountFactory` contract. -## Authentication and authorization +This account contract has a single EOA based owner that can execute any transaction. The owner must sign the `UserOperation` using an `ECDSA` signature of the `UserOperation` hash. More information about these signature can be found in [OpenZeppelin's ECDSA library](https://docs.openzeppelin.com/contracts/2.x/api/cryptography#ECDSA). -## Nonces and replay protection \ No newline at end of file +Execution of the `UserOperation` is done by calling the `execute` function, which is able to execute any transaction on behalf of the user. The `execute` function is able to call any contract and pass any calldata to the contract. This `execute` function can only be called by the `EntryPoint` contract, as so will only be executed once the `UserOperation` has been validated. See the interface for the execute function below. + +```solidity +interface ISimpleAccount { + function execute(address dest, uint256 value, bytes calldata func) external; +} +``` diff --git a/pages/docs/understanding-ERC-4337/account-factory-contract.md b/pages/docs/understanding-ERC-4337/account-factory-contract.md index e69de29..a35ef9c 100644 --- a/pages/docs/understanding-ERC-4337/account-factory-contract.md +++ b/pages/docs/understanding-ERC-4337/account-factory-contract.md @@ -0,0 +1,15 @@ +# Account Factory + +In ERC-4337, an account factory is a contract that is able to deploy account contracts on behalf of users. + +The ERC-4337 specification does not require a specific account factory implementation or interface. Instead `UserOperation` objects will contain the address of the account factory contract and execution calldata. + +There are some restrictions on which OpCodes can be used during account creation. These restrictions are defined in the [ERC-4337 Specification](https://eips.ethereum.org/EIPS/eip-4337). + +## Sample implementation + +The ERC-4337 core team has implemented [`SimpleAccountFactory.sol`](https://github.com/eth-infinitism/account-abstraction/blob/develop/contracts/samples/SimpleAccountFactory.sol) as a sample minimal account factory that deploys `SimpleAccount` contracts. + +If this factory is deployed via a Singleton Factory Pattern such as [ERC-2470](https://eips.ethereum.org/EIPS/eip-2470), the deployed account contracts will have a predictable address, which is useful for users interacting across different networks. + +This is due to the use of `CREATE2` to deploy the account contracts, which allows the user to predict the address of the deployed account contract before it is deployed. The address can be determined prior to deployment by hashing the factory address, the salt, and the init code of the account contract. The Simple Account Factory offers a function to calculate the address of the deployed account contract.