# EIP-4337 What the fuck is account abstraction? Besides being a nice buzzword to raise your next 3 at 30 round, account abstraction removes all current limitations on what we currently consider wallets. Want to send transactions and have someone else pay for gas? -> Paymasters Want to have social recovery? -> Add multiple keys Want to build tornado cash into the wallet layer? Want to send ETH to someone's twitter handle since you don't know their wallet address? -> CREATE2 with some twitter hash and send it before they deploy their wallet There's already a shit ton of resources out there on account abstraction, so here are some notes. I'm assuming you understand the following - account abstraction via EIP-4337 is implemented solely with smart contracts, no changes to Ethereum are necessary - account abstraction wallet = smart contract, similar to gnosis safe - account abstraction is a simple concept, but due to limitations around blockchains, have a bunch of parts like `Operations`, `Paymasters`, `Bundler`, `EntryPoint`, and `Aggregator` :( ## Reading List Read this before you continue https://www.alchemy.com//blog/account-abstraction https://www.alchemy.com/blog/account-abstraction-paymasters https://www.alchemy.com/blog/account-abstraction-wallet-creation ## Quick Definitions skip this section if you aren't a noob `aawallet`: A smart contract account abstraction wallet. `EOA`: Externally Owned Account ## User operations Motivation: Users want to run a transaction from a smart contract instead of from their own private key EOA. This is a fancy name for a transaction that a user wants to execute. It looks something like this: ``` struct UserOp { // Normal eth_sendTransaction Parameters address to; bytes data; uint256 value; // Amount of ETH sent uint256 gas; bytes signature; // Can be signed in many ways, just needs correct validation uint256 nonce; // To prevent replay attacks // Tells Entrypoint which wallet to check for validation and charge for gas address sender; } ``` This is the object you pass into `UserOp`, it specifies everything you need to run a transaction. ## Entry Point Motivation: Without an entrypoint, an EOA would need to call `aawallet.executeOp()` and trust the `aawallet` will pay the gas costs for the transaction. Why is it called an entrypoint? This is the only place where EOAs call functions. How it works: - The goal is for the EOA to call `executeOp()` and know exactly what will happen(they get their gas refunded and the transaction executes successfully) - The problem is that `executeOp()` is hard to simulate, as differences in on-chain storage and `block.timestamp`, `block.number`, etc. could differ between the simulation and execution - Thus, we want a new function in EntryPoint(`handleOp()`) to do the following - If the wallet doesn't have enough funds to pay the maximum amount of gas the `UserOp` might use, reject - Call `aawallet.executeOp()` and track how much gas was used - Send a corresponding amount of gas from`aawallet` to my wallet - This is what account abstraction wallet's term as handling operations ## ValidateOp Motivation: Right now, we only have a single method that takes a `UserOp` and executes it. However, we want to break this into two parts - validating that someone with the correct permissions sent the `UserOp` and executing the `UserOp`. Otherwise, some malicious actor could just come in, submit a bunch of invalid transactions, and burn all the gas in the `aawallet` Now, EntryPoint's `handleOp()` should do the following - If the wallet doesn't have enough funds to pay the maximum amount of gas the `UserOp` might use, reject - Call `aawallet.executeOp()` and track how much gas it uses - Send a corresponding amount of gas from`aawallet` to my wallet ## Bundler Motivation: Save gas by aggregating executions of `UserOp` as each transaction in EVMs require a fixed 21,000 gas fee. Why is it called a Bundler? It bundles multiple transactions and executes them together. How it works: - For each `UserOp`, call `validateOp()` on the sender's wallet - For each `UserOp`, call `executeOp()` on the sender's wallet, then transfer ETH to the executor to pay for gas - Unfortunately, each bundler can only include one transaction from each sender so `validateOp()` rules aren't broken Side Note: If bundlers smell like flashbots, that's because there's a massive MEV opportunity here where you can order UserOps as a bundler to let MEV searchers to bid on them ## Paymasters Motivation: We can allow dApps to pay for user's gas, OlympusDAO to charge users OHM instead of ETH for gas, etc. Why is it called paymaster? It handles paying for gas for `UserOp` How it works: - You stake the native gas token to specific accounts in the paymaster ## Questions 1. Where is preVerifcationGasLimit used? `verifcationGasLimit` is used in `validateUserOp` 2. Has the entrypoint contract been formally verified? I wasn't able to find one online, is it there or has it not been verified 3. `When a client receives a UserOperation, it must first run some basic sanity checks, namely that:` What is a client in this context? 4. `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:` What is the fun equivalent for each of these(sender-?, factory-FunWalletFactory, paymaster-Token/Gasless, aggregator-?) 5. `No possibility for “passive” paymasters (eg. that accept fees in some ERC-20 token at an exchange rate pulled from an on-chain DEX)` Why is this the case? We have this with tokenpaymaster right? 6. `Do we need the funwalletfactory to be staked with the entrypoint?` If so, we don't have any functions in FunWalletFactory with the ability to stake from there(at minimum we should stake in the constructor)