Try   HackMD

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 fromaawallet 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 fromaawallet 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)