A production-grade, educational implementation of ERC-4337 Account Abstraction with modular smart accounts, paymasters, and security modules.
Account Abstraction (AA) transforms how users interact with blockchains by enabling smart contract wallets with programmable validation logic. Instead of being limited to ECDSA signatures from EOAs, AA enables:
- Multi-factor authentication (biometrics, hardware keys, social recovery)
- Gasless transactions (paymasters sponsor gas)
- Session keys (delegated signing for games/apps)
- Batch transactions (multiple operations in one tx)
- Progressive security (upgrade wallet security over time)
- Pay gas in tokens (USDC, DAI, etc.)
- Multisig control (M-of-N signatures required)
- Spending limits (daily/weekly caps)
+-----------------------------------------------------------------------------+
| ERC-4337 ARCHITECTURE |
+-----------------------------------------------------------------------------+
| |
| User/dApp |
| | |
| | Creates UserOperation |
| v |
| +-------------+ |
| | Bundler | Aggregates UserOps from mempool |
| +------+------+ |
| | |
| | handleOps([userOps]) |
| v |
| +-------------+ |
| | EntryPoint | Singleton contract (one per chain) |
| | (v0.7) | |
| +------+------+ |
| | |
| +-----+-----+ |
| | | |
| v v |
| +---------+ +-------------------------------------+ |
| | Smart | | PAYMASTERS | |
| | Account | | +------------+ +--------------+ | |
| +----+----+ | | Verifying | | Token | | |
| | | | (gasless) | | (pay in ERC20) | |
| | | +------------+ +--------------+ | |
| | +-------------------------------------+ |
| | |
| | Modular validation & execution |
| v |
| +-------------------------------------------------------------------------+ |
| | MODULES | |
| | +-----------+ +-----------+ +----------+ +----------+ +------------+ | |
| | | Session | | Social | | Multisig | | Spending | | ECDSA | | |
| | | Keys | | Recovery | | Validator| | Limits | | (default) | | |
| | | (gaming) | |(guardians)| | (M-of-N) | | (hook) | | | | |
| | +-----------+ +-----------+ +----------+ +----------+ +------------+ | |
| +-------------------------------------------------------------------------+ |
| |
+-----------------------------------------------------------------------------+
| Contract | Description |
|---|---|
EntryPoint |
Singleton that validates and executes UserOperations |
SmartAccount |
Modular ERC-4337 wallet with plugin architecture |
SmartAccountFactory |
CREATE2 factory for deterministic addresses |
VerifyingPaymaster |
Gas sponsor with off-chain signature verification |
TokenPaymaster |
Pay gas in ERC-20 tokens (USDC, DAI, etc.) |
| Module | Description |
|---|---|
SessionKeyModule |
Delegated signing with spending limits, time bounds, target whitelists |
MultisigValidatorModule |
M-of-N threshold signatures for shared control |
| Module | Description |
|---|---|
SocialRecoveryModule |
Guardian-based account recovery with timelock |
| Module | Description |
|---|---|
SpendingLimitHook |
Enforce per-tx, daily, and weekly spending limits |
erc4337-account-abstraction-toolkit/
├── src/
│ ├── core/
│ │ ├── EntryPoint.sol # ERC-4337 singleton
│ │ ├── SmartAccount.sol # Modular smart wallet
│ │ ├── SmartAccountFactory.sol # CREATE2 deployment
│ │ ├── BasePaymaster.sol # Paymaster base
│ │ ├── VerifyingPaymaster.sol # Signature-based sponsor
│ │ └── TokenPaymaster.sol # ERC-20 gas payment
│ ├── interfaces/
│ │ ├── IEntryPoint.sol # v0.7 interface
│ │ ├── IAccount.sol # Account interface
│ │ ├── IPaymaster.sol # Paymaster interface
│ │ ├── IModule.sol # Module interfaces
│ │ └── ISmartAccount.sol # Smart account interface
│ └── modules/
│ ├── SessionKeyModule.sol # Session key validator
│ ├── MultisigValidatorModule.sol # M-of-N multisig
│ ├── SocialRecoveryModule.sol # Guardian recovery
│ └── SpendingLimitHook.sol # Spending limits
├── test/
│ ├── Base.t.sol # Test utilities
│ ├── unit/ # Unit tests
│ ├── fuzz/ # Fuzz tests (1000 runs)
│ ├── invariant/ # Invariant tests (32k calls)
│ └── integration/ # E2E scenario tests
├── script/
│ ├── Deploy.s.sol # Full deployment script
│ └── CreateAccount.s.sol # Account creation helper
├── foundry.toml # Foundry config
└── README.md
# Clone the repository
git clone https://github.com/Kazopl/erc4337-account-abstraction-toolkit
cd erc4337-account-abstraction-toolkit
# Install dependencies
forge install
# Build
forge build# Run all tests
forge test
# Run with verbosity
forge test -vvv
# Run specific test file
forge test --match-path test/unit/SmartAccount.t.sol
# Run fuzz tests (1000 runs each)
forge test --match-path test/fuzz/
# Run invariant tests (32k calls)
forge test --match-path test/invariant/
# Run E2E integration tests
forge test --match-path test/integration/
# Gas report
forge test --gas-report# Start local node
anvil
# Deploy all contracts
forge script script/Deploy.s.sol --rpc-url http://localhost:8545 --broadcast# Set environment variables
export PRIVATE_KEY=your_private_key
export BASE_SEPOLIA_RPC_URL=https://base-sepolia.g.alchemy.com/v2/your-key
# Deploy to Base Sepolia
forge script script/Deploy.s.sol:DeployBaseSepolia \
--rpc-url $BASE_SEPOLIA_RPC_URL \
--broadcast \
--verify
# Deploy to Sepolia
forge script script/Deploy.s.sol:DeploySepolia \
--rpc-url $SEPOLIA_RPC_URL \
--broadcast \
--verifyCreate account and make first transaction without owning any ETH:
// 1. Get counterfactual address
address accountAddr = factory.getAddress(owner, salt);
// 2. Create UserOp with initCode (deploys account)
bytes memory initCode = abi.encodePacked(
address(factory),
abi.encodeCall(SmartAccountFactory.createAccount, (owner, salt))
);
// 3. Add paymaster data (backend signs approval)
userOp.paymasterAndData = abi.encodePacked(
address(paymaster),
verificationGasLimit,
postOpGasLimit,
validUntil,
validAfter,
paymasterSignature
);
// 4. Execute - account deployed + action executed, all gasless!
entryPoint.handleOps([userOp], beneficiary);Enable hot wallet signing for games without exposing main key:
// Install session key module
account.installModule(IModule.ModuleType.Validator, address(sessionKeyModule), "");
// Create session key with restrictions
sessionKeyModule.addSessionKey(
sessionKeyAddress,
block.timestamp, // Start: now
block.timestamp + 4 hours, // End: 4 hours
0.1 ether, // Max 0.1 ETH per tx
1 ether // Max 1 ETH total
);
// Only allow game contract
sessionKeyModule.setTargetPermission(sessionKey, gameContract, true, allowedSelectors);Shared control with M-of-N signatures:
// Install multisig module
address[] memory signers = [alice, bob, charlie];
bytes memory initData = abi.encode(signers, 2); // 2-of-3
account.installModule(IModule.ModuleType.Validator, address(multisigModule), initData);
// Sign UserOp with multiple keys (sorted order)
userOp.signature = abi.encodePacked(
address(multisigModule),
aliceSignature, // Lowest address first
bobSignature
);Users pay transaction fees in stablecoins:
// Configure token (owner)
tokenPaymaster.configureToken(
address(usdc),
6, // USDC decimals
2000 * 1e6, // 2000 USDC per ETH
true // Active
);
// User approves tokens
usdc.approve(address(tokenPaymaster), type(uint256).max);
// Include token paymaster in UserOp
userOp.paymasterAndData = abi.encodePacked(
address(tokenPaymaster),
verificationGas,
postOpGas,
address(usdc) // Token to pay with
);Enforce daily budgets for security:
// Install spending limit hook
bytes memory initData = abi.encode(
0.1 ether, // Max 0.1 ETH per transaction
1 ether, // Max 1 ETH per day
5 ether // Max 5 ETH per week
);
account.installModule(IModule.ModuleType.Hook, address(spendingLimitHook), initData);
// Now all transactions are checked against limits
// Exceeding limits will revertRecover account via trusted guardians:
// Configure guardians
socialRecoveryModule.setupRecovery(
[guardian1, guardian2, guardian3],
2, // 2-of-3 required
2 days // 48h delay
);
// If key lost, guardians initiate recovery
socialRecoveryModule.initiateRecovery(account, newOwner); // Guardian 1
socialRecoveryModule.approveRecovery(account); // Guardian 2
// After 48 hours
socialRecoveryModule.executeRecovery(account);- ECDSA signature validation (default)
- Modular validation via plugins
- Nonce management prevents replay
- Module installation restricted
- Time-bound sponsorship
- Off-chain signature verification
- Pre-charge with refund pattern
- Session keys with spending limits
- Multisig with sorted signatures
- Social recovery with timelock
- Spending limits reset daily/weekly
- Packed UserOperation structs
- Efficient storage patterns
- Sorted signatures in multisig
- Minimal external calls during validation
- ERC-4337 - Account Abstraction
- ERC-6900 - Modular Smart Accounts
- ERC-7579 - Minimal Modular Smart Accounts
- EIP-1271 - Smart Contract Signature Validation
- EIP-712 - Typed Structured Data Hashing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Submit a pull request
MIT License - see LICENSE for details.
Disclaimer: This is an educational implementation. For production use, consider:
- Using the canonical EntryPoint from eth-infinitism
- Professional security audit
- Battle-tested implementations like Safe or Kernel