๐ How to Deploy Your Own ERC-4337 Environment on Jovay โ
๐ Introduction โ
ERC-4337 (Account Abstraction) is a key standard in the Ethereum ecosystem. By introducing the concept of UserOperation, it decouples user transaction intent from actual on-chain execution, enabling developers to build more flexible and user-friendly DApp experiences. With Account Abstraction, DApps can offer capabilities that traditional EOA wallets simply cannot provide:
- ๐ Transaction Bundling: Multiple user operations can be bundled by a Bundler into a single on-chain transaction, reducing overall gas costs;
- ๐ฆ Smart Contract Wallets (Smart Accounts): A user's "account" is itself a smart contract, supporting advanced features such as multi-signature, social recovery, and permission management;
- โฝ Gas Sponsorship (Paymaster): Users don't need to hold native tokens (ETH). A third-party Paymaster can pay gas fees on behalf of users, and even allow users to pay transaction fees using ERC-20 tokens (e.g., USDC).
Both Jovay Testnet and Mainnet have deployed the EntryPoint v0.7 contract, providing developers with out-of-the-box ERC-4337 infrastructure. This tutorial will walk you through setting up a complete ERC-4337 service stack on Jovay step by step ๐ ๏ธ
๐ฏ What You'll Accomplish โ
By following this tutorial, you will:
- โ Launch Rundler (Alchemy's open-source ERC-4337 Bundler) on Jovay to provide UserOperation bundling and submission services;
- โ Deploy the official Demo Paymaster contract from Account Abstraction, enabling gas payment via ERC-20 tokens;
- โ Create your own ERC-4337 Smart Account by sending a UserOp, with the Paymaster sponsoring ETH as gas;
๐ We will use Jovay Testnet to demonstrate how to achieve the above goals.
๐ Environment Information โ
| Item | Details |
|---|---|
| ๐ Network | Jovay Testnet, Network Information |
| ๐ EntryPoint v0.7 | 0x0000000071727De22E5E9d8BAf0edAc6f37da032 |
| ๐ Other Common Contracts | Contract List |
| ๐ RPC Service | Register at ZAN and obtain the Jovay Testnet RPC URL for running Rundler |
โ ๏ธ Note: It is recommended to purchase a ZAN Professional plan. The free tier has rate limits that are insufficient for running Rundler in a production environment.
๐งฐ Prerequisites โ
Before getting started, make sure your development environment meets the following requirements:
- ๐ณ Docker and Docker Compose installed
- ๐ฆ Node.js installed (version >= 16)
- ๐ An Ethereum private key ready, with a small amount of Jovay ETH โ you can claim free ETH from the Jovay Testnet Faucet
๐ง Step-by-Step Guide โ
1๏ธโฃ Start the Bundler (Rundler) โ
Rundler is a high-performance ERC-4337 Bundler implementation open-sourced by Alchemy, written in Rust. It is responsible for collecting UserOperations submitted by users from the mempool, performing validation and simulation, and then bundling multiple UserOps into a single on-chain transaction to be submitted to the EntryPoint contract for execution.
We will use Docker to quickly launch Rundler ๐ณ
๐ฅ Pull the Docker Image โ
docker pull alchemyplatform/rundler:v0.10.1๐ Prepare the Chain Configuration File โ
Create a configuration file jovay-testnet.toml for Jovay Testnet:
name="JovayTestnet"
id=2019775
block_gas_limit=80000000
transaction_gas_limit=16777216
chain_history_size=1๐ก
chain_history_sizecontrols the block range that Rundler looks back for on-chain events. To reduce RPC request frequency, it is set to1here. For production environments, adjust or remove this configuration as needed.
๐ Prepare the Docker Compose File โ
Create a compose.yml file, noting the following key points:
- ๐ Replace
/path/to/jovay-testnet.tomlwith the actual path - ๐ Replace
${ZAN_API_KEY}with your API Key obtained from ZAN - ๐ Set the environment variable
BUILDER_PRIVATE_KEYto a private key that holds Jovay ETH
services:
rundler:
image: alchemyplatform/rundler:v0.10.1
command: node
ports:
# RPC port
- "3000:3000"
# Metrics port
- "8080:8080"
volumes:
- /path/to/jovay-testnet.toml:/chain.toml
environment:
- RUST_LOG=INFO
- CHAIN_SPEC=/chain.toml
- NODE_HTTP=https://api.zan.top/node/v1/jovay/testnet/${ZAN_API_KEY}
- BUILDER_PRIVATE_KEY=${BUILDER_PRIVATE_KEY}
- DISABLE_ENTRY_POINT_V0_6=true
- SIGNER_PRIVATE_KEYS=${BUILDER_PRIVATE_KEY}
- ENABLE_UNSAFE_FALLBACK=true
- USER_OPERATION_EVENT_BLOCK_DISTANCE=100
- USER_OPERATION_EVENT_BLOCK_DISTANCE_FALLBACK=100
- MIN_STAKE_VALUE=0
- MIN_UNSTAKE_DELAY=0
- POOL_CHAIN_POLL_INTERVAL_MILLIS=1000โ ๏ธ Production Note: If you plan to use this configuration in production, you should remove the following configuration items for security:
MIN_STAKE_VALUEMIN_UNSTAKE_DELAYPOOL_CHAIN_POLL_INTERVAL_MILLISchain_history_sizeinjovay-testnet.toml
๐ Start Rundler โ
docker compose up -dOnce started, Rundler will provide ERC-4337 JSON-RPC services at http://localhost:3000. You can check the logs with docker compose logs -f to confirm the service is running properly โ
2๏ธโฃ Deploy the Paymaster โ
This tutorial will guide you through deploying the LegacyTokenPaymaster contract to Jovay Testnet.
๐ข
LegacyTokenPaymasteris intended for tutorial demonstration only. For mainnet deployment, please implement a custom Paymaster contract tailored to your business needs.
๐ก What is LegacyTokenPaymaster? โ
LegacyTokenPaymaster is a demo Paymaster contract implementation within the ERC-4337 Account Abstraction framework. It is also an ERC-20 Token contract itself. Its core mechanism works as follows:
| Phase | Behavior |
|---|---|
๐ validatePaymasterUserOp | Validation phase: Checks whether the user holds enough Paymaster Tokens to confirm sponsorship eligibility |
๐ฐ postOp | Settlement phase: Deducts the corresponding amount of tokens from the user's Smart Account as gas fee compensation |
Key Features:
- ๐ช The Paymaster itself issues an ERC-20 Token, which users use to pay gas fees
- ๐ฑ The Token-to-ETH exchange rate is fixed at 1:100 (i.e., 1 Token = 100 ETH)
- ๐ฆ The Paymaster must pre-deposit ETH in the EntryPoint contract as the actual gas payment source
- ๐ค Users only need to hold the Paymaster-issued tokens to initiate transactions โ no ETH required
Step 1: ๐ฅ Clone the Repository โ
git clone --branch v0.7.0 https://github.com/eth-infinitism/account-abstraction.git
cd account-abstractionStep 2: ๐ฆ Install Dependencies โ
yarn installStep 3: โ๏ธ Configure the Network โ
Edit hardhat.config.ts and add the Jovay Testnet configuration under networks:
jovaytestnet: {
url: 'https://api.zan.top/public/jovay-testnet',
accounts: [
'<YOUR_PRIVATE_KEY>'
],
chainId: 2019775
}โ ๏ธ Replace
<YOUR_PRIVATE_KEY>with your own private key. Make sure the corresponding account has enough Jovay ETH for contract deployment.
Step 4: ๐ Download the Paymaster Deployment Script โ
Download the Paymaster deployment script into the deploy directory:
curl -o deploy/3_deploy_LegacyTokenPaymaster.ts \
https://gist.githubusercontent.com/zouxyan/985197b398362777d09e8d391656586f/raw/72d1d993b3d1d6c2710e94f6ddbf9796d6b75ce2/3_deploy_LegacyTokenPaymaster.tsThis script will automatically perform the following operations:
- ๐ญ Deploy
SimpleAccountFactory(reuses the existing contract if already deployed) - ๐ณ Deploy the
LegacyTokenPaymastercontract - ๐ฐ Deposit 0.01 ETH into the Paymaster via
EntryPoint.depositTo(as the gas sponsorship fund pool) - ๐ช Mint
1e18Paymaster Tokens to the deployer
Step 5: ๐ Create EntryPoint Deployment Record โ
Since the EntryPoint contract is already pre-deployed on Jovay Testnet, but the hardhat-deploy plugin requires a local deployment record to reference it. We need to manually create this record file:
mkdir -p deployments/jovaytestnet
echo '{"address":"0x0000000071727De22E5E9d8BAf0edAc6f37da032","abi":[]}' > deployments/jovaytestnet/EntryPoint.json
echo '2019775' > deployments/jovaytestnet/.chainId๐ก This step tells the
hardhat-deployplugin that the EntryPoint contract already exists at the specified address, so the deployment script can reference it directly without redeploying.
Step 6: ๐ Deploy the Contract โ
EntryPoint 0x0000000071727De22E5E9d8BAf0edAc6f37da032 is already deployed on Jovay Testnet. You only need to run the Paymaster deployment script:
npx hardhat deploy --network jovaytestnet --tags LegacyTokenPaymasterStep 7: โ Verify the Deployment โ
After successful deployment, the console will output a complete deployment summary with all contract addresses:
============================================================
Deployment Summary
============================================================
EntryPoint: 0x0000000071727De22E5E9d8BAf0edAc6f37da032
SimpleAccountFactory: 0x91E60e0613810449d098b0b5Ec8b51A0FE8c8985
LegacyTokenPaymaster: 0x8FcF8B3f04D4cA04238e3AC9A3312180149f34f5
Token Name: MyToken
Paymaster ETH Deposit: 0.01 ETH
Signer Token Balance: 1.0
============================================================๐ Please record these contract addresses carefully โ you will need them for subsequent Paymaster interactions.
3๏ธโฃ Send a UserOperation โ
Now comes the most exciting part ๐ Below we demonstrate how to send a UserOperation under the ERC-4337 v0.7 standard via Rundler, creating a Smart Account with gas sponsored by the Paymaster.
The core flow of the entire process is as follows:
๐ค User โโ(UserOp)โโโถ ๐ฆ Rundler โโ(Bundle Tx)โโโถ ๐ EntryPoint โโ(Call)โโโถ ๐ณ Paymaster
โ
Deduct Token โโโโ- ๐ซ The user does not need to hold any ETH
- โฝ Gas fees are paid by the Paymaster from its deposit in the EntryPoint
- ๐ช The Paymaster simultaneously deducts an equivalent amount of ERC-20 Tokens from the user's Smart Account as compensation
Continue working in the account-abstraction repository for the following steps:
Step 1: ๐ฅ Download the Test Script โ
Navigate to the test directory and download the UserOp sending script:
cd test
curl -o paymaster-uo-create-account.test.ts \
https://gist.githubusercontent.com/zouxyan/ce2878366f1439d0df78717751350d47/raw/736de648313e14cf6a0e73fdc05ca6f910163dd4/paymaster-uo-create-account.test.tsStep 2: โ๏ธ Confirm Hardhat Network Configuration โ
Make sure hardhat.config.ts has the target network configured:
networks: {
jovaytestnet: {
url: 'https://api.zan.top/public/jovay-testnet',
accounts: ['<deployer-private-key>'], // Deployer private key with ETH
chainId: 2019775
}
}โ ๏ธ The address corresponding to the private key in
accountsmust be the owner of the Paymaster contract (because the script needs to callmintTokensto mint tokens for the new account).
Step 3: โถ๏ธ Run the Test โ
Pass in the three required parameters via environment variables and execute:
BUNDLER_URL=http://<bundler-host>:<port> \
PAYMASTER_ADDRESS=0x<paymaster-address> \
FACTORY_ADDRESS=0x<factory-address> \
npx hardhat test test/paymaster-uo-create-account.test.ts --network jovaytestnet๐ Parameter Description:
| Environment Variable | Description | Example |
|---|---|---|
BUNDLER_URL | Bundler's JSON-RPC address | http://localhost:3000 |
PAYMASTER_ADDRESS | LegacyTokenPaymaster contract address (from deployment output) | 0x823477...5c926 |
FACTORY_ADDRESS | SimpleAccountFactory contract address (from deployment output) | 0x91E60e...8985 |
Step 4: ๐ View Results โ
The script outputs results in 4 phases. Let's walk through each one:
๐ข Phase 1 โ Calculate Account Address & Mint Tokens
Calculates the counterfactual address of the user's Smart Account (i.e., a deterministic address that can be computed before the contract is actually deployed), and mints 1 Paymaster Token to that address:
============================================================
Step 1: Calculate Account Address & Mint Tokens
============================================================
Counterfactual Account: 0x5764934Fa2a000CEcF3331696E2E38D1992461a1
Paymaster Deposit Before: 0.01 ETH
Minting 1.0 tokens to account...
Account Token Balance: 1.0
โ
Tokens minted successfully๐ก What is a Counterfactual Address? In ERC-4337, the address of a Smart Account can be deterministically computed using the
CREATE2opcode before the contract is deployed. This means you can transfer tokens to a contract address that "doesn't exist yet." When the first UserOp triggers the contract deployment, the tokens are already there waiting to be used.
๐ค Phase 2 โ Build & Send UserOperation
Constructs a UserOp and sends it to the Bundler. After the Bundler accepts the UserOp, it returns a UserOp Hash. You can query UserOp details via Rundler's query RPC (refer to the Alchemy documentation):
============================================================
Step 2: Build & Send UserOperation
============================================================
UserOp Hash: 0x325eed6f...
Sender: 0x5764934F...
Nonce: 0x00
Sending UserOp to bundler...
Bundler Response Hash: 0x325eed6f...
โ
UserOp submitted to bundler๐งพ Phase 3 โ UserOp Receipt & Cost Analysis
Waits for the UserOp to be included on-chain and retrieves the transaction receipt. You can view the transaction details on the Jovay Testnet Explorer:
============================================================
Step 3: UserOp Receipt
============================================================
UserOp Hash: 0x325eed6f...
Success: โ
true
Tx Hash: 0xabc123...
Block Number: 12345
Gas Used (tx): 350000
Actual Gas Cost: 0.00035 ETH
Paymaster: 0x823477...๐ฐ Phase 4 โ Cost Analysis
Finally, the cost analysis โ this is the part that best demonstrates the value of the Paymaster:
============================================================
Step 4: Cost Analysis
============================================================
Paymaster Deposit Before: 0.01 ETH
Paymaster Deposit After: 0.00969775806 ETH
Paymaster ETH Consumed: 0.00030224194 ETH
Account Token Before: 1.0
Account Token After: 0.999997263266
Account Token Consumed: 0.000002736734As you can clearly see:
- ๐ฆ The Paymaster consumed
0.00030224194 ETHto cover the actual gas fees - ๐ช The user was only charged
0.000002736734Paymaster Tokens as compensation - ๐ The user did not spend any ETH at all and successfully created a Smart Account contract at
0x5764934Fa2a000CEcF3331696E2E38D1992461a1
๐ What's More: Customize Your Own Paymaster โ
The tutorial above used a demo-level LegacyTokenPaymaster. In a real production environment, you can build a much more powerful custom Paymaster ๐ช
๐ฑ Use USDC as the Gas Token โ
Jovay provides ERC-20 cross-chain capabilities, supporting the bridging of ERC-20 tokens from Ethereum to Jovay. For example, Jovay officially supports USDC (on both Mainnet and Sepolia) for cross-chain usage on Jovay. For implementation details, refer to the cross-chain service tutorial.
Therefore, you can use USDC as the Paymaster's gas sponsorship token โ so your DApp users won't need to hold ETH and can initiate "transactions" on Jovay with just USDC ๐
๐ฎ Integrate Chainlink Oracle for Real-Time Exchange Rates โ
Jovay has a close partnership with Chainlink, which provides Oracle services for Jovay. By integrating Chainlink Price Feed, your Paymaster contract can:
- ๐ Retrieve real-time ETH/USDC exchange rates
- ๐ฑ Perform precise gas fee conversion and collection based on market prices
- ๐ก๏ธ Avoid arbitrage risks associated with using fixed exchange rates
๐๏ธ Build Off-Chain Verification Services โ
Furthermore, your Paymaster can be paired with an off-chain verification service to implement the following features in the Paymaster contract:
- โ๏ธ Signature Verification: Only UserOps authorized by the off-chain service's signature can use the Paymaster for gas sponsorship
- ๐ Whitelist Management: Restrict Paymaster usage to specific users or contracts only
- ๐ซ Quota Control: Limit the number of sponsored transactions or the maximum amount per user
- ๐ Fee Strategies: Set differentiated fee rates based on user tiers or business scenarios
๐ผ๏ธ Overall Architecture โ
Users send UserOp requests to Rundler with the Paymaster specified in the request. This allows users to complete on-chain business operations even without holding ETH, as long as they have USDC. The Paymaster deducts the user's USDC while using its own ETH to sponsor the gas fees on the user's behalf.
