0/5
## Understanding zkSync Native Account Abstraction: Setup and Core Concepts This lesson introduces the fundamentals of zkSync's native Account Abstraction (AA) and guides you through setting up your development environment to build a minimal account abstraction contract. Unlike Ethereum's ERC-4337, zkSync integrates AA directly into its protocol, offering a streamlined and efficient approach. ## zkSync Native Account Abstraction vs. Ethereum ERC-4337: Key Differences and Advantages zkSync's native implementation of Account Abstraction presents several key distinctions and benefits when compared to Ethereum's ERC-4337 standard: 1. **No Alternative Mempool:** Transactions intended for account abstraction contracts are sent directly to the standard zkSync mempool. This eliminates the need for a separate mempool (alt-mempool) that ERC-4337 relies on. 2. **No Central `EntryPoint.sol` Contract:** In zkSync, transactions are routed directly to your specific account contract. This removes the `EntryPoint.sol` contract, which acts as a central coordinator in the ERC-4337 architecture, thereby simplifying the transaction flow. 3. **Simplified Transaction Flow:** * A user, interacting via a wallet like Metamask, signs a transaction (specifically, a `TxType: 113` transaction). * This signed message is broadcast to the zkSync network. * The network processes this message, which ultimately results in calling functions on "Your Account" – your custom smart contract. * "Your Account" can then initiate interactions with other decentralized applications (DApps, e.g., `Dapp.sol`). * Optional components, such as Signature Aggregators and Paymasters, can still be integrated into this flow. 4. **Gasless Transactions from the User's Initial Perspective:** * When a user initiates an action, such as deploying a contract using Remix on zkSync, they are presented with a "Signature request" for a `TxType: 113` transaction, rather than a standard transaction confirmation prompt that requests immediate gas payment. * The user *signs* this data, but they do not pay gas at this specific moment. * The signed data is transmitted to a zkSync Era node. * A node, or a relayer/bundler, then executes the transaction (e.g., deploys the contract). * Gas fees are paid during this execution step. However, these fees can be covered by a paymaster or deducted from the user's account by the system after the transaction is processed. This abstracts the immediate gas payment away from the user for certain operations, enhancing the user experience. ## Recalling the Remix Deployment Experience A practical example of this `TxType: 113` interaction was previously observed when deploying a contract on zkSync via Remix. The Metamask pop-up displayed: * `TxType: 113` * A "Sign" button, instead of the usual "Send Transaction" or "Confirm" button. This indicated that the user was signing data for an account abstraction operation, not initiating a traditional Ethereum transaction. The wallet balance (e.g., `99.9766 ETH`) was only debited *after* the zkSync network processed the operation and the contract was deployed. ## Essential Resource: `Cyfrin/foundry-era-contracts` For developing and testing with zkSync's native account abstraction, the `Cyfrin/foundry-era-contracts` repository is a crucial resource. * **Repository Link:** `https://github.com/Cyfrin/foundry-era-contracts` * This repository is a fork, or mirror, of zkSync's official `era-contracts` (which contain system-level contracts). Cyfrin has adapted this fork to be more compatible with the Foundry development toolchain and easier to integrate into educational curricula. * It houses the "System Contracts" that empower many of zkSync Era's advanced functionalities, including native account abstraction. * **Installation:** For this lesson, we will use version `0.0.3`. Install it using Foundry: ```bash forge install Cyfrin/foundry-era-contracts@0.0.3 --no-commit ``` * **Important Note:** This codebase is provided for testing and educational purposes. It is not audited and should be used at your own risk. In the future, the recommendation may shift to an official, more user-friendly library if one becomes available. ## The Paradigm Shift: All Accounts are Smart Contracts on zkSync A fundamental design principle of zkSync Era is that all accounts are, at their core, smart contracts. This contrasts significantly with Ethereum's model. 1. **Ethereum's Account Model:** Ethereum distinguishes between two primary account types: * **Externally Owned Account (EOA):** Controlled by a private key (e.g., accounts managed by Metamask or Rabby). * **Smart Contract Wallet/Account:** Programmable accounts represented by code deployed on the blockchain (e.g., Gnosis Safe, Argent). This dichotomy can introduce complexities in development, such as needing to check `msg.sender == tx.origin` or determine if a caller is a contract. 2. **zkSync Era's Unified Account Model:** On zkSync Era, every account, including those that appear and behave like traditional EOAs (such as your Metamask account when used on the zkSync network), is an instance of a smart contract. * When an EOA interacts with zkSync, it is typically represented by a `DefaultAccount.sol` smart contract deployed on its behalf. * This unification simplifies interactions and development patterns, effectively allowing EOA-like addresses to possess smart contract capabilities. * The zkSync Block Explorer (e.g., `sepolia.explorer.zksync.io`) is designed to recognize these `DefaultAccount` instances. For a cleaner user experience, it often displays them as if they were simple EOAs (e.g., without a "Contract" tab), even though they are smart contracts under the hood. ## Key System Contract Interfaces and Implementations for Account Abstraction Understanding the core interfaces and their default implementations is vital for building custom accounts on zkSync. 1. **`IAccount.sol` Interface:** * **Location in `foundry-era-contracts`:** `lib/foundry-era-contracts/src/system-contracts/contracts/interfaces/IAccount.sol` * This interface is paramount. All account contracts on zkSync, including the `DefaultAccount` for EOAs and any custom account abstraction contracts you build, *must* implement `IAccount.sol`. * Key functions defined in this interface include: * `validateTransaction(bytes32 _txHash, bytes32 _suggestedSignedHash, Transaction calldata _transaction) external payable returns (bytes4 magic);` * `executeTransaction(bytes32 _txHash, bytes32 _suggestedSignedHash, Transaction calldata _transaction) external payable;` * `executeTransactionFromOutside(Transaction calldata _transaction) external payable;` (This function caters to specific use cases or legacy zkSync functionalities beyond the primary AA flow focused on `validate` and `execute`.) * `payForTransaction(bytes32 _txHash, bytes32 _suggestedSignedHash, Transaction calldata _transaction) external payable;` * `prepareForPaymaster(bytes32 _txHash, bytes32 _suggestedSignedHash, Transaction calldata _transaction) external payable;` 2. **`DefaultAccount.sol` Implementation:** * **Location in `foundry-era-contracts`:** `lib/foundry-era-contracts/src/system-contracts/contracts/DefaultAccount.sol` * This contract provides the default smart contract implementation for accounts that function like EOAs on zkSync. When you use your Metamask wallet on zkSync, its address on the zkSync network corresponds to an instance of this `DefaultAccount` contract. 3. **`Transaction` Struct:** * The `Transaction` struct is a critical data structure passed as a parameter to many functions within the `IAccount` interface. * **Imported from:** It is defined and can be imported, for example, from `lib/foundry-era-contracts/src/system-contracts/contracts/interfaces/Transaction.sol` or accessible via utility libraries like `MemoryTransactionHelper.sol` within the `foundry-era-contracts` repository. For our purposes, we will import it from the path used in the `IAccount.sol` interface context. ## Setting Up Your `ZkMinimalAccount.sol` Contract Our objective is to create a foundational smart contract account on zkSync. This involves setting up the basic structure and importing necessary components. 1. **Create a New File:** In your Foundry project, create a new Solidity file named `ZkMinimalAccount.sol` within the `src/zksync/` directory (or your preferred path). 2. **Initial Code Structure:** Populate `ZkMinimalAccount.sol` with the following boilerplate code: ```solidity // SPDX-License-Identifier: MIT pragma solidity 0.8.24; import {IAccount} from "lib/foundry-era-contracts/src/system-contracts/contracts/interfaces/IAccount.sol"; // The Transaction struct is defined within or alongside system contract interfaces. // For direct use as per IAccount, ensure the path correctly resolves to its definition. // The video lesson points to the struct being available via an import like this: import {Transaction} from "lib/foundry-era-contracts/src/system-contracts/contracts/interfaces/Transaction.sol"; contract ZkMinimalAccount is IAccount { // Magic value to be returned by validateTransaction on success // bytes4(keccak256("isValidSignature(bytes32,bytes)") // bytes4 constant PT_MAGIC_VALUE = 0x1626ba7e; // Example, actual value might differ based on system specifics // TODO: Implement owner state variable and constructor function validateTransaction( bytes32 _txHash, bytes32 _suggestedSignedHash, Transaction calldata _transaction ) external payable override returns (bytes4 magic) { // TODO: Actual validation logic // For now, returning a placeholder or the expected magic value if known // This function must return IAccount.validateTransaction.selector or similar magic bytes on success // For zkSync Era, the magic value returned by validateTransaction on success is `IAccount.validateTransaction.selector`. // However, in ERC-4337 context, it's often related to EIP-1271. // For native AA, the system expects a specific magic value. // For simplicity, let's assume a successful validation will be implemented later. // The IAccount interface defines the magic as: // bytes4 constant ACCOUNT_VALIDATION_SUCCESS_MAGIC = 0x56495AA4; // bytes4(keccak256("AA_VALIDATION_SUCCESS_MAGIC")) // However, the actual success return for `validateTransaction` is `IAccount(this).validateTransaction.selector` // As per system contracts, it's often: // `return _SUCCESS_MAGIC;` where `bytes4 constant _SUCCESS_MAGIC = 0x56495AA4;` (System Contract V1.3.0 and later) // Or, more accurately from IAccount interface: // return 0x56495AA4; // Placeholder for actual success magic from IAccount revert("Not implemented"); // Placeholder } function executeTransaction( bytes32 _txHash, bytes32 _suggestedSignedHash, Transaction calldata _transaction ) external payable override { // TODO: Actual execution logic revert("Not implemented"); // Placeholder } function executeTransactionFromOutside(Transaction calldata _transaction) external payable override { // TODO: Actual execution logic for transactions initiated from outside revert("Not implemented"); // Placeholder } function payForTransaction( bytes32 _txHash, bytes32 _suggestedSignedHash, Transaction calldata _transaction ) external payable override { // TODO: Logic for paying for the transaction, if not using a paymaster revert("Not implemented"); // Placeholder } function prepareForPaymaster( bytes32 _txHash, bytes32 _suggestedSignedHash, Transaction calldata _transaction ) external payable override { // TODO: Logic for preparing the transaction for a paymaster revert("Not implemented"); // Placeholder } // TODO: Implement fallback/receive functions if needed for ETH transfers } ``` * The contract `ZkMinimalAccount` inherits from the `IAccount` interface. * It imports the `IAccount` interface and the `Transaction` struct from the `foundry-era-contracts` library. * The necessary function signatures from `IAccount.sol` (`validateTransaction`, `executeTransaction`, `executeTransactionFromOutside`, `payForTransaction`, and `prepareForPaymaster`) are included as stubs. The `override` keyword is used, signifying that these functions are implementations of the interface requirements. (Initial stubs revert; actual implementation will follow). This initial setup provides the foundational understanding and the necessary code structure to begin implementing the logic for your custom account abstraction contract on zkSync Era. The native integration of AA, where every account can be a smart contract, alongside the simplified transaction flow, are the key advantages that zkSync offers in this domain.
A foundational guide to Understanding zkSync Native Account Abstraction: Setup and Core Concepts - Dive into zkSync's native Account Abstraction, contrasting its advantages like no alt-mempool with ERC-4337, and learn how all accounts are smart contracts. You'll install `foundry-era-contracts` and begin building a `ZkMinimalAccount.sol` by implementing the `IAccount` interface.
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