1/5
## Deploying and Interacting with Account Abstraction on zkSync This guide walks you through a practical demonstration of deploying a basic Account Abstraction (AA) smart contract on the zkSync network and subsequently sending a transaction initiated by this AA contract. We'll cover crucial code adjustments, deployment steps, and interaction patterns, highlighting the power of native AA on zkSync. ## Setting the Stage: Tools and Scripts for zkSync AA Our primary objective is to deploy an Account Abstraction contract and then use it to send an AA-powered transaction. While Foundry is a popular choice for smart contract development, its scripting capabilities for zkSync are still maturing. Therefore, for robust deployment and interaction scripting on zkSync, we will be utilizing **Hardhat** with JavaScript/TypeScript. This lesson will focus on two main actions: 1. Deploying the AA smart contract to the zkSync network. 2. Sending a transaction from this deployed AA contract, demonstrating its ability to act as an account. The necessary scripts for this demonstration are available in the `javascript-scripts` folder of the `Cyfrin/minimal-account-abstraction` GitHub repository. The key scripts we'll use are: * `DeployZkMinimal.ts`: This script handles the deployment of our AA smart contract. * `SendAATx.ts`: This script is used to send a transaction initiated by our deployed AA contract. While we won't delve into the intricacies of setting up your JavaScript environment (Node.js, Hardhat, TypeScript), we will guide you through the execution of these scripts. ## Essential Smart Contract Adjustments for zkSync AA Before deploying our `ZkMinimalAccount.sol` smart contract, two critical modifications are necessary to ensure correct functionality and security, particularly concerning signature validation and transaction execution logic on zkSync. ### 1. Correcting Signature Validation: Removing Redundant `toEthSignedMessageHash` A common pitfall when working with EIP-712 signatures, especially in the context of zkSync's AA, is the incorrect application of message hashing. **The Issue:** The original `ZkMinimalAccount.sol` and its corresponding test file (`ZkMinimalAccountTest.sol`) mistakenly applied `MessageHashUtils.toEthSignedMessageHash` (or its equivalent member function `.toEthSignedMessageHash()`) to a hash that was already correctly formatted for EIP-712 recovery. In `ZkMinimalAccount.sol` (around line 142 within `validateTransaction`): ```solidity // bytes32 txHash = _transaction.encodeHash(); // This is the correct hash // // Erroneous line that was removed/commented: // // bytes32 convertedHash = MessageHashUtils.toEthSignedMessageHash(txHash); // address signer = ECDSA.recover(txHash, _transaction.signature); // Use txHash directly ``` And in the helper function `_signTransaction` within `ZkMinimalAccountTest.sol` (around line 77): ```solidity // bytes32 unsignedTransactionHash = MemoryTransactionHelper.encodeHash(transaction); // // Erroneous line that was removed/commented: // // bytes32 digest = unsignedTransactionHash.toEthSignedMessageHash(); // (uint8 v, bytes32 r, bytes32 s) = vm.sign(ANVIL_DEFAULT_KEY, unsignedTransactionHash); // Sign unsignedTransactionHash directly ``` **The Reason:** The `encodeHash` function, typically provided by zkSync's system libraries (like `MemoryTransactionHelper.sol`), already prepares the transaction hash in the EIP-712 compatible format. This often includes prepending the `\x19\x01` domain separator and hashing structured data appropriately. Applying `toEthSignedMessageHash` again corrupts this correctly formatted hash, leading to signature mismatches during the `ECDSA.recover` process. **The Fix:** Remove the redundant calls to `MessageHashUtils.toEthSignedMessageHash` or `.toEthSignedMessageHash()`. The raw hash obtained from `_transaction.encodeHash()` (in the main contract) or `MemoryTransactionHelper.encodeHash()` (in tests) should be used directly for signature recovery or signing operations. ### 2. Ensuring Valid Execution: Checking the Magic Value in `executeTransactionFromOutside` A crucial security measure in AA contracts is to verify the outcome of the validation logic before proceeding with transaction execution. **The Issue:** The `executeTransactionFromOutside` function in `ZkMinimalAccount.sol` was calling `_validateTransaction` but was not checking its return value. The `_validateTransaction` function is designed to return a specific `bytes4` magic value (e.g., `ACCOUNT_VALIDATION_SUCCESS_MAGIC`) upon successful validation. Ignoring this return value means the contract might execute a transaction even if the signature validation failed silently. **The Code (Original vs. Corrected):** In `ZkMinimalAccount.sol` (around line 100): ```solidity function executeTransactionFromOutside(Transaction memory _transaction) external payable { // Original, problematic approach: // _validateTransaction(_transaction); // Corrected approach: bytes4 magic = _validateTransaction(_transaction); if (magic != ACCOUNT_VALIDATION_SUCCESS_MAGIC) { revert ZkMinimalAccount_InvalidSignature(); // Or a more specific error like "ValidationFailed" } _executeTransaction(_transaction); } ``` **The Fix:** The return value from `_validateTransaction` must be captured. This value should then be compared against the expected success magic value (e.g., `0x12345678`, often defined as a constant like `ACCOUNT_VALIDATION_SUCCESS_MAGIC`). If the returned magic value does not match the expected success value, the transaction must be reverted to prevent unauthorized execution. ## Deploying Your First AA Contract to zkSync Testnet With the necessary code refinements in place, we can now deploy our Account Abstraction smart contract to the zkSync Sepolia testnet. 1. Navigate to your project's terminal, ensuring you are in the root directory of the `Cyfrin/minimal-account-abstraction` repository. 2. Execute the deployment script using Yarn: ```bash yarn deploy ``` This command, as configured in the `package.json` file, triggers `ts-node javascript-scripts/DeployZkMinimal.ts`. 3. Upon successful execution, the script will output the address of the deployed `ZkMinimalAccount` contract. For this demonstration, the contract was deployed to: `0x19a519025994A1F32188dE1F0E11014A791fB358`. 4. You can verify the deployment on the zkSync Era Block Explorer for Sepolia (`sepolia.explorer.zksync.io`) by searching for this address. **Note on Contract Verification:** At the time of this writing, smart contracts that heavily interact with zkSync's system contracts (as AA contracts do) might present challenges for automated source code verification on block explorers. While the deployed bytecode is visible, full source code verification might not always be straightforward. ## Powering Your AA Contract: Funding for Gas Fees For an Account Abstraction smart contract to initiate and pay for its own transactions, it requires a balance of the native network token (ETH on zkSync). To enable our newly deployed AA contract to send transactions: 1. Open your MetaMask wallet (or any compatible wallet). 2. Ensure your wallet is connected to the zkSync Sepolia testnet. 3. Send a small amount of testnet ETH (e.g., `0.001 ETH`) to the deployed AA contract address (`0x19a519025994A1F32188dE1F0E11014A791fB358`). This provides the contract with the necessary funds to cover gas costs for its outgoing transactions. ## Initiating Transactions from Your AA Smart Contract Now that our AA contract is deployed and funded, we can demonstrate its core capability: sending a transaction where the contract itself is the initiator. 1. Open the `javascript-scripts/SendAATx.ts` script in your editor. 2. Locate the `ZK_MINIMAL_ADDRESS` constant (around line 14) and update it with the address of your deployed AA contract: ```typescript const ZK_MINIMAL_ADDRESS = "0x19a519025994A1F32188dE1F0E11014A791fB358"; ``` 3. Return to your terminal and execute the transaction sending script: ```bash yarn sendTx ``` This command runs `ts-node javascript-scripts/SendAATx.ts`. 4. **Behind the Scenes:** This script typically performs the following: * It constructs a "user operation," which includes the target contract address (`to`), transaction data (`data`), value (`value`), and other parameters for a transaction the AA contract should execute (e.g., an `approve` call on a mock USDC contract). * The owner EOA associated with the AA contract signs the hash of this user operation. * The script then submits this signed user operation to the zkSync network, targeting your AA contract's `executeTransactionFromOutside` (or a similar entry point) function. * Inside your AA contract, the `_validateTransaction` function verifies the signature against the owner. * If validation passes, `_executeTransaction` executes the intended operation (e.g., the `approve` call). 5. The script will output a transaction hash for the AA transaction sent to the network. 6. Refresh the page for your AA contract address on the zkSync Sepolia explorer. You should observe a new transaction. * **Crucially, the "FROM" field for this new transaction will be the address of your AA smart contract (`0x19a5...B358`).** This is the hallmark of Account Abstraction: the smart contract itself initiated and paid for this transaction. * Inspecting the transaction details will reveal the underlying action, such as an `approve` function call to a target contract (e.g., a mock USDC contract at `0x5249fD99f1C1aE9B04C65427257Fc3B8cD976620`), approving a specified spender. ## Core Account Abstraction Principles Demonstrated This exercise effectively showcases several foundational concepts of Account Abstraction: * **Smart Contracts as First-Class Accounts:** AA allows smart contracts to possess capabilities traditionally reserved for Externally Owned Accounts (EOAs), such as initiating transactions and paying for gas. * **Native AA on zkSync:** zkSync's architecture natively supports smart contracts acting as the effective `tx.origin` or `msg.sender` at the entry point of a transaction, which is fundamental to its AA implementation. * **EIP-712 Signatures for User Operations:** Securely authorizing transactions to be executed by an AA contract relies on cryptographic signatures, often following the EIP-712 standard for structured data signing. The `encodeHash` function within zkSync's tooling is vital for generating the correct message digest. * **Interaction with zkSync System Contracts:** AA contracts often interact with zkSync's system contracts for functionalities like nonce management (via `NONCE_HOLDER_SYSTEM_CONTRACT`) and deployment (via `DEPLOYER_SYSTEM_CONTRACT`). * **AA Transaction Lifecycle:** 1. An EOA (the "owner" of the AA) signs the details of the desired operation (the user operation). 2. This signed user operation is submitted to the network, targeting the AA smart contract. 3. The AA contract's validation logic (e.g., `validateTransaction`) verifies the signature and other preconditions. 4. Upon successful validation, the AA contract's execution logic (e.g., `executeTransaction`) performs the intended operation. ## Key Considerations for zkSync AA Development As you explore Account Abstraction on zkSync, keep these important points in mind: * **Foundry vs. Hardhat for zkSync Scripting:** For deployment and complex interaction scripts on zkSync, Hardhat (with TypeScript/JavaScript) currently offers more mature and robust tooling compared to Foundry's native scripting features. * **Contract Verification Challenges:** Smart contracts that interface deeply with zkSync's system contracts may encounter difficulties with automated source code verification on block explorers. * **Funding AA Wallets:** Remember that AA smart contract wallets must be funded with the native network token (ETH on zkSync) to cover the gas costs of the transactions they initiate. * **Security is Paramount - Magic Value Check:** Always rigorously check the return values of validation functions (like `_validateTransaction`'s magic value) before proceeding with state-changing operations. This prevents execution based on failed or bypassed validation. * **EIP-712 Hashing Integrity:** Pay close attention to the hashing mechanism. Ensure the hash being signed by the user and the hash being recovered within the contract are identical and correctly follow the EIP-712 standard. zkSync's `encodeHash` utility is designed to assist with this. This demonstration has successfully illustrated the deployment and operation of a basic Account Abstraction smart contract on zkSync, culminating in the contract itself initiating a transaction. This capability unlocks a new paradigm for user experience and smart contract design in the Web3 ecosystem.
An essential guide to Deploying and Interacting with Account Abstraction on zkSync - Deploy your first Account Abstraction contract on zkSync using Hardhat and initiate transactions as the contract itself. Learn vital smart contract adjustments for correct EIP-712 signature validation and secure transaction execution via magic value checks.
Previous lesson
Previous
Next lesson
Next
Give us feedback
Obtaining testnet funds -> Tenderly virtual testnets
Last updated on May 15, 2025
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