1/5
## Mid-Session Recap: Unpacking Account Abstraction on Ethereum and zkSync This lesson serves as a crucial mid-session recap, consolidating our understanding of Ethereum's Account Abstraction (AA) as defined by EIP-4337. We'll reinforce the power and flexibility this EIP offers before transitioning to explore how zkSync implements Account Abstraction in a more native, and potentially simpler, manner. This recap also sets the stage for practical implementation on zkSync in the subsequent parts of this course. ## Ethereum Account Abstraction: EIP-4337 Explained The Ethereum Improvement Proposal EIP-4337 introduces a novel way to achieve Account Abstraction on Ethereum without requiring consensus-layer changes. Let's break down its core components and flow. **Core Concept: Programmable Transaction Validity** The fundamental shift with EIP-4337 is the decoupling of transaction validation from the traditional reliance on an Externally Owned Account's (EOA) private key signature. Instead, Account Abstraction empowers a smart contract, known as an "Account Contract" or "Smart Account," to define its own arbitrary validation logic. This means virtually *any* programmed condition can be used to authorize a transaction for that account. Examples of custom validation logic include: * Multi-signature approvals by a group of trusted friends. * Validation using a Google session key for enhanced usability. * Pre-defined spending limits for transactions. * Parental controls on a child's digital wallet. * Any other custom rule expressible in smart contract code. **The EIP-4337 Transaction Flow** Interacting with a Smart Account under EIP-4337 involves a multi-step process, orchestrated off-chain and on-chain: 1. **Step 1 (Off-Chain): User Creates a "UserOperation" (UserOp)** Instead of a standard Ethereum transaction, the user (or their wallet software) constructs a `UserOperation`. This data structure encapsulates the intended action (e.g., calling a dApp function, sending tokens), specifies who will pay for gas, includes a signature, and other necessary parameters. The data for this `UserOp` is signed according to the Smart Account's custom validation logic (e.g., by a Google key, multiple friends' signatures). 2. **Step 2 (Off-Chain): UserOp Enters an "Alt-Mempool"** The signed `UserOp` is then sent to a separate, alternative mempool specifically designed for `UserOperations`. This alt-mempool is distinct from Ethereum's standard transaction mempool. Specialized nodes, often referred to as "Bundlers," monitor this alt-mempool for incoming `UserOps`. 3. **Step 3 (On-Chain): Bundlers Process UserOps** Bundlers select `UserOps` from the alt-mempool, often bundling multiple `UserOps` together. They then submit these bundled `UserOps` as a single, standard Ethereum transaction to a global, singleton smart contract known as the **EntryPoint Contract**. The Bundler typically pays the L1 gas fees for this encompassing transaction and is subsequently reimbursed, usually from the Smart Account or a Paymaster. 4. **Step 4 (On-Chain): EntryPoint Contract Orchestrates Validation and Execution** The EntryPoint contract is central to the EIP-4337 flow. Upon receiving `UserOps` from a Bundler: * It first calls the `validateUserOp` function on the target Smart Account for each `UserOp`. This function contains the custom logic to verify the `UserOp`'s signature and other conditions. * If `validateUserOp` succeeds, indicating the `UserOp` is valid according to the Smart Account's rules, the EntryPoint contract then proceeds to call an `execute` (or similarly named) function on the Smart Account. * The `execute` function within the Smart Account then performs the actual intended operation, such as interacting with another dApp or transferring tokens. **Optional Components in EIP-4337** * **Paymasters:** These are smart contracts designed to sponsor gas fees for `UserOps`. If a Paymaster is involved and agrees to cover the costs, users can experience gasless transactions from their perspective. The EntryPoint contract interacts with Paymasters during the `UserOp` processing. * **Signature Aggregators:** These contracts allow for the bundling of multiple cryptographic signatures into a single, more compact signature. This can lead to gas savings, particularly when many `UserOps` with similar signature schemes are batched together, though they are less common in the basic flow. **Benefits and Use Cases of EIP-4337** The EIP-4337 standard unlocks numerous advantages: * **Gasless Transactions:** Users do not necessarily need ETH in their Smart Account if a Paymaster is configured to cover transaction fees. * **Custom Security Models:** Moving beyond simple private key security, AA enables social recovery mechanisms, multi-factor authentication, and other sophisticated security setups. * **Enhanced User Experience (UX):** Onboarding can be simplified. Users might not need to manage complex seed phrases if alternative validation methods (like biometric or social logins) are implemented. * **Programmable Wallets:** Features like daily spending limits, whitelisting approved interaction addresses, and parental controls become natively programmable at the account level. **Key Code Example: `MinimalAccount.sol`** To illustrate a basic Smart Account, we examined the `MinimalAccount.sol` contract, which implements the `IAccount` interface required by EIP-4337. * **`validateUserOp` Function:** This is the cornerstone of AA logic. ```solidity // A signature is valid, if it's the MinimalAccount owner function validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds) external requireFromEntryPoint // Modifier ensuring only EntryPoint can call returns (uint256 validationData) { validationData = _validateSignature(userOp, userOpHash); // _validateNonce(); // Nonce validation for replay protection _payPrefund(missingAccountFunds); // Logic for pre-funding gas } ``` This function is invoked by the EntryPoint contract. Its primary role is to check if the provided signature (`userOp.signature`) is valid according to the account's rules (in this minimal example, it simply checks if the signature corresponds to the `owner`). It also typically handles nonce validation (to prevent replay attacks, though simplified in this example) and ensures the account can pre-fund the gas required for its operation. The `requireFromEntryPoint` modifier ensures only the trusted EntryPoint contract can call this sensitive function. * **`execute` Function:** Called by the EntryPoint contract *after* `validateUserOp` returns successfully. ```solidity function execute(address dest, uint256 value, bytes calldata functionData) external requireFromEntryPointOrOwner { (bool success, bytes memory result) = dest.call{value: value}(functionData); if (!success) { revert MinialAccount_CallFailed(result); } } ``` This function executes the core logic of the `UserOp`, making the actual call to the destination contract (`dest`) with the specified `value` (ETH) and `functionData` (encoded function call). The `requireFromEntryPointOrOwner` modifier ensures this function can only be called by the EntryPoint (during normal AA flow) or directly by the account owner for administrative purposes. * **`_validateSignature` Function (Internal Detail):** This internal helper function contains the specific logic to verify the `userOp.signature` against the `userOpHash`. In our `MinimalAccount` example, this would typically involve using `ECDSA.recover` to derive the signer's address from the signature and hash, then comparing it to the stored `owner` address. It returns a status code indicating whether the signature validation succeeded or failed. **Key Code Example: `SendPackedUserOp.s.sol` (Foundry Script)** To facilitate the creation and submission of `UserOperations` during development and testing, a Foundry script named `SendPackedUserOp.s.sol` was utilized. * **`generateSignedUserOperation` Function:** This utility function is responsible for: 1. Constructing the unsigned `UserOperation` data by calling an internal helper like `_generateUnsignedUserOperation`. 2. Obtaining the `userOpHash` by calling `entryPoint.getUserOpHash(userOp)`. This hash is what needs to be signed. 3. Signing this `userOpHash` using a private key (e.g., via `vm.sign` in a Foundry testing environment). 4. Populating the `userOp.signature` field with the resulting signature. * **`_generateUnsignedUserOperation` Function:** This internal helper constructs the `PackedUserOperation` struct with all necessary fields *except* the signature. ```solidity function _generateUnsignedUserOperation(bytes memory callData, address sender, uint256 nonce) internal pure returns (PackedUserOperation memory) { return PackedUserOperation({ sender: sender, // The Smart Account address nonce: nonce, // The account's current nonce initCode: hex"", // Bytecode to deploy the account if it doesn't exist; empty if it does callData: callData, // The encoded function call to be executed by the Smart Account accountGasLimits: ..., // Gas limits for verification and execution phases preVerificationGas: ..., // Gas allocated before validation gasFees: ..., // maxFeePerGas, maxPriorityFeePerGas paymasterAndData: hex"", // Empty if no paymaster is used signature: hex"" // Initially empty, populated after signing }); } ``` * **Sending the UserOp (within the script's `run` function):** After the `UserOperation` is fully constructed and signed, the script (acting as a Bundler in a local or testnet environment) calls the `handleOps` function on the EntryPoint contract. ```solidity // Simplified representation of the call entryPoint.handleOps(ops, payable(helperConfig.getAccount())); ``` Here, `ops` is an array containing one or more `PackedUserOperation` structs, and the second argument is the address that will be compensated for the gas fees incurred by the Bundler. ## Transitioning to zkSync Account Abstraction While EIP-4337 provides a robust framework for Account Abstraction on Ethereum, its reliance on an alt-mempool, external Bundlers, and the EntryPoint contract introduces a degree of complexity to the overall architecture. **zkSync's Native Approach** zkSync, as a Layer 2 scaling solution, has taken a different path by building Account Abstraction **natively into its protocol level**. This fundamentally changes and simplifies how AA is handled. * **Key Distinction:** On zkSync, there is no requirement for a separate alt-mempool or external Bundler entities in the same way EIP-4337 mandates them for Ethereum. The zkSync sequencer and its underlying protocol are inherently designed to manage AA transactions. * **Transaction Type 113:** To interact with a Smart Account on zkSync, users (or their wallets) send a special transaction of `Type 113`. This type signals to the zkSync network that the transaction originates from or targets a Smart Account and requires AA logic to be processed. * **Combined Mempool:** zkSync effectively features a "combined mempool." The distinction between a standard mempool and an AA-specific alt-mempool dissolves. The native protocol understands how to route and process Type 113 transactions alongside regular transactions. **The zkSync AA Flow** 1. A user (e.g., via a wallet like MetaMask configured for zkSync) initiates and sends a Type 113 transaction directly to the zkSync network. 2. This transaction specifies the `from` address as the Smart Account address. 3. The zkSync protocol itself, upon receiving this Type 113 transaction, directly handles calling the appropriate validation logic defined within the target Smart Account. 4. If the Smart Account's validation logic confirms the transaction's validity, the transaction is then executed. 5. Paymaster functionality is also natively supported within zkSync's AA model, allowing for sponsored transactions. This native integration aims to provide a more streamlined and potentially more efficient AA experience compared to the layered approach of EIP-4337 on Ethereum L1. ## Key Learnings and Next Steps This exploration of Account Abstraction reveals its transformative potential for Web3 user experience and security. * **Power and Flexibility:** Account Abstraction is incredibly powerful, allowing developers to define custom validation and execution logic for wallets, moving beyond the limitations of traditional EOAs. * **EIP-4337 on Ethereum:** This standard brings AA to Ethereum Mainnet and EVM-compatible L1s/L2s through a system of UserOperations, Bundlers, and an EntryPoint contract, enabling AA without core protocol changes. * **Native AA on zkSync (and other L2s):** Solutions like zkSync are implementing AA more natively at the protocol level. This can simplify the architecture by eliminating the need for separate mempools and external bundler networks seen in EIP-4337. * **Course Game Plan:** 1. **Create a basic AA on Ethereum (DONE):** We have successfully built `MinimalAccount.sol` and the `SendPackedUserOp.s.sol` script to interact with it. The immediate next step for this Ethereum segment is to deploy this setup and send a `UserOperation` through it, likely on a testnet like Arbitrum. 2. **Create a basic AA on zkSync:** This will be the focus of our next major section, where we will explore implementing similar AA functionality leveraging zkSync's native capabilities. 3. **Deploy and send transactions:** We will *not* send another AA transaction to Ethereum L1 in this course, as the EIP-4337 flow has been covered. However, we *will* deploy our zkSync AA solution and send an AA transaction through it to demonstrate its native workings. **Important Resources Mentioned:** * **EIP-4337:** The official Ethereum Improvement Proposal for Account Abstraction using an alternative mempool. * **zkSync Documentation:** Particularly the sections on the "Bootloader," which is responsible for processing transactions (including Type 113 AA transactions) in batches. (Refer to `docs.zksync.io/zk-stack/components/zksync-evm/bootloader`). * **GitHub Repository:** The `Cyfrin/minimal-account-abstraction` repository contains the source code for `MinimalAccount.sol`, the diagrams discussed (`account-abstraction-again.png` for Ethereum EIP-4337, `account-abstraction.png` for zkSync), and the supporting scripts. The concepts covered are dense, so take a moment to digest this information. Understanding these foundational differences between EIP-4337 and native AA implementations is key as we move towards practical coding on zkSync.
A vital recap to Unpacking Account Abstraction on Ethereum and zkSync - Reinforce your understanding of Ethereum's EIP-4337, including UserOperations, Bundlers, and the EntryPoint contract. Then, explore zkSync's native Account Abstraction, contrasting its streamlined Type 113 transaction flow and simplified architecture.
Previous lesson
Previous
Next lesson
Next
Give us feedback
Course Overview
About the course
Advanced smart contract development
How to develop a stablecoin
How to develop a DeFi protocol
How to develop a DAO
Advanced smart contracts testing
Fuzz testing
Manual verification
Web3 Developer Relations
$85,000 - $125,000 (avg. salary)
Web3 developer
$60,000 - $150,000 (avg. salary)
Smart Contract Engineer
$100,000 - $150,000 (avg. salary)
Smart Contract Auditor
$100,000 - $200,000 (avg. salary)
Security researcher
$49,999 - $120,000 (avg. salary)
Guest lecturers:
Juliette Chevalier
Lead Developer relations at Aragon
Nader Dabit
Director of developer relations at EigenLayer
Ally Haire
Developer relations at Protocol Labs
Harrison
Founder at GasliteGG
Last updated on May 12, 2025
Solidity Developer
Advanced FoundryDuration: 36min
Duration: 3h 06min
Duration: 5h 02min
Duration: 6h 02min
Duration: 2h 47min
Duration: 1h 23min
Duration: 4h 28min
Duration: 1h 19min
Duration: 1h 10min
Course Overview
About the course
Advanced smart contract development
How to develop a stablecoin
How to develop a DeFi protocol
How to develop a DAO
Advanced smart contracts testing
Fuzz testing
Manual verification
Web3 Developer Relations
$85,000 - $125,000 (avg. salary)
Web3 developer
$60,000 - $150,000 (avg. salary)
Smart Contract Engineer
$100,000 - $150,000 (avg. salary)
Smart Contract Auditor
$100,000 - $200,000 (avg. salary)
Security researcher
$49,999 - $120,000 (avg. salary)
Guest lecturers:
Juliette Chevalier
Lead Developer relations at Aragon
Nader Dabit
Director of developer relations at EigenLayer
Ally Haire
Developer relations at Protocol Labs
Harrison
Founder at GasliteGG
Last updated on May 12, 2025