ERC-4337

Account Abstraction

via Alternative Mempool

One Year Later...

 
 
Yoav Weiss, Dror Tirosh, Shahaf Nacson
https://github.com/eth-infinitism/account-abstraction


What’s new?

  • Account changes
  • Extend Paymaster
  • Support Signature Aggregation
  • Relaxed Storage Rules
  • Staking, Reputations for all Entities
  • RPC API
  • Extras: spec-test, ref. impl, sdk

Note:
account: time-range (session keys)
pm: support token paymaster
agg: for rollups
RPC: simulation, estimation
Extras: For standarized bundler compatibility


Key challenges - Why is it so Complicated

  • EOA is secured by signature, nonce, gas fees.
  • An existing Tx in mempool can't be invalidated
  • AA UserOperation is validated by EVM code, and can be invalidated before paying.
  • Our goal: make invalidations expensive.DoS attack on the mempool should cost. A lot.
  • Putting n UserOps into the mempool should cost O(n)

UserOperation

    struct UserOperation {
        address sender;
        uint256 nonce;
        bytes initCode;
        bytes callData;
        uint256 callGasLimit;
        uint256 verificationGasLimit;
        uint256 preVerificationGas;
        uint256 maxFeePerGas;
        uint256 maxPriorityFeePerGas;
        bytes paymasterAndData;
        bytes signature;
    }

Submit UserOperation to bundler

        
      

Note:
explain all entities


Submit UserOperation to bundler with factory

        
      

Submit UserOperation to bundler with paymaster

        
      

Submit UserOperation to bundler

        
      

Creating HandleOps Transaction

        
      

Account API

function validateUserOp(UserOperation userOp,
   bytes32 userOpHash, uint256 missingAccountFunds)
external returns (uint256 validationData);
  • ValidationData:
    • Time-range: validAfter, validUntil
    • returned signature check:
      • signature aggregator (optional)
      • “0” - signature OK
      • “1” - sig check failed (ok during estimation)
  • BaseAccount
  • SimpleAccount: Proxy-based, EOA-like account

Notes:
missingfunds - maxPossiblecost


Minimal Account

function validateUserOp(UserOperation userOp,
  bytes32 userOpHash, uint256 missingFunds)
external returns (uint256 validationData) {
  require(msg.sender == address(entryPoint);
  bytes32 hash = userOpHash.toEthSignedMessageHash();
  bool sigFailed = owner != hash.recover(userOp.signature);
  validationData = sigFailed ? 1 : 0;
  require(nonce++ == userOp.nonce);
  if (missingFunds != 0)
    entryPoint.depositTo{value : missingFunds}(msg.sender);
}

Paymaster

function validatePaymasterUserOp(UserOperation userOp,
   bytes32 userOpHash, uint256 maxCost)
returns (bytes context, uint256 validationData)

function postOp(PostOpMode mode, bytes context,
                uint256 actualGasCost)
  • May access account token balance
  • returned validationData like in Account.
  • May work without stake
    • But with no self-storage, and no context

Custom Factory

  • Provided by each Account contract wallet.
  • UserOp.initCode : address + calldata
  • Can wrap existing factory (e.g. GnosisProxyFactory)
  • Can call “initializer” functions during construction
  • Must return same address for existing account

Custom Factory

contract SimpleAccountFactory {
   function createAccount(address owner,bytes32 salt)
    public returns (address) {
       address addr = Create2.computeAddress(...);
       uint codeSize = addr.code.length;
       if (codeSize > 0) return addr;

       ret = new Proxy{salt : salt} (
              accountImplementation,
              abi.encodeCall(
                  SimpleAccount.initialize, (owner))
           );
   }
}

Key challenges - Why is it so Complicated

  • EOA is secured by signature, nonce, gas fees.
  • An existing Tx in mempool can't be invalidated
  • AA UserOperation is validated by EVM code, and can be invalidated before paying.
  • Our goal: make invalidations expensive. DoS attack on the mempool should cost. A lot.
  • Putting n UserOps into the mempool should cost O(n)

Note:
The EP protects the account: only execute after its validation
The separation of validation help the bundlers to validate userops fast.
The rules below protect the bundlers: prevent DoS attacks


Protection Rule Principles

  1. Sandboxing - validation is the same on-chain and off-chain
  2. Isolation - UserOperations should not share state
  3. Staking - Bypassing rule (2) causes throttling. Staking make it expensive to re-deploy
  4. Low validation cost

Code Validation Rules

  • Prevent simulation and exectuion validation to behave differently.
  • Banned opcodes: NUMBER, TIMESTAMP, SELFDESTRUCT etc
  • Codehash must not change between 1st & 2nd simulations
  • Must not access EOA
  • GAS opcode: allowed just before *CALL
  • Must not revert on OOG

Storage validation rules

  • Storage Rules
    • Allowed access to account storage
      (e.g. account.getNonce())
    • Allowed access to referenced storage
      (e.g. token.balanceOf(account))
  • Staked entities
    • All entities can be staked
    • Allowed to access its own storage
    • Can be Throttled/Banned
    • Reputations

Bundler deep dive

  • Upon receiving eth_sendUserOperation(userOp):
    • Save codehashes of accessed addresses
    • Run off-chain checks (paymaster balance etc.), then call debug_traceCall simulateValidation(userOp) (first simulation). If simulation succeeds, add userOp to mempool.

Bundler deep dive

  • On bundle creation, for each candidate user operation from mempool perform the following:
    • validate no codehash changes
    • validate paymasters deposits
    • validate paymasters, aggregators, factories stakes/reputations if needed
    • validate bundle inclusion rules for accounts (e.g. 1 userOp per sender)
    • call debug_traceCall simulateValidation(userOp) (second simulation)

RPC APIs

  • eth_sendUserOperation
  • eth_estimateUserOperationGas
  • eth_getUserOperationReceipt
  • eth_getUserOperationByHash
  • eth_supportedEntryPoints
  • `eth_chainId
  • As well as debug apis
    `

Signature Aggregation

        
      

Bundler-Spec-Test

  • pytest tests validate enforcement of bundling rules, rpc compatibility etc.
Select a repo